Add wayvncctl get-outputs command

Signed-off-by: Jim Ramsay <i.am@jimramsay.com>
pull/195/head
Jim Ramsay 2022-11-22 22:20:56 -05:00 committed by Andri Yngvason
parent ac5e207321
commit 80fd6b074e
5 changed files with 103 additions and 3 deletions

View File

@ -27,6 +27,14 @@ struct ctl_server_vnc_client {
char username[256]; char username[256];
}; };
struct ctl_server_output {
char name[65];
char description[128];
unsigned height;
unsigned width;
bool captured;
};
struct ctl_server_actions { struct ctl_server_actions {
void* userdata; void* userdata;
struct cmd_response* (*on_output_cycle)(struct ctl*, struct cmd_response* (*on_output_cycle)(struct ctl*,
@ -39,6 +47,12 @@ struct ctl_server_actions {
// Receiver will free(clients) when done. // Receiver will free(clients) when done.
int (*get_client_list)(struct ctl*, int (*get_client_list)(struct ctl*,
struct ctl_server_vnc_client** clients); struct ctl_server_vnc_client** clients);
// Return number of elements created
// Allocate 'outputs' array or set to NULL if none
// Receiver will free(outputs) when done.
int (*get_output_list)(struct ctl*,
struct ctl_server_output** outputs);
}; };
struct ctl* ctl_server_new(const char* socket_path, struct ctl* ctl_server_new(const char* socket_path,

View File

@ -412,6 +412,29 @@ static void pretty_client_list(json_t* data)
} }
} }
static void pretty_output_list(json_t* data)
{
int n = json_array_size(data);
printf("There %s %d output%s%s\n", (n == 1) ? "is" : "are",
n, (n == 1) ? "" : "s", (n > 0) ? ":" : ".");
int i;
json_t* value;
json_array_foreach(data, i, value) {
char* name = NULL;
char* description = NULL;
int height = -1;
int width = -1;
int captured = false;
json_unpack(value, "{s:s, s:s, s:i, s:i, s:b}", "name", &name,
"description", &description,
"height", &height,
"width", &width,
"captured", &captured);
printf("%s output[%s]: %s (%dx%d)\n",
captured ? "*" : " ", name, description, width,
height);
}
}
static void pretty_print(json_t* data, static void pretty_print(json_t* data,
struct jsonipc_request* request) struct jsonipc_request* request)
{ {
@ -422,6 +445,8 @@ static void pretty_print(json_t* data,
pretty_version(data); pretty_version(data);
else if (strcmp(method, "get-clients") == 0) else if (strcmp(method, "get-clients") == 0)
pretty_client_list(data); pretty_client_list(data);
else if (strcmp(method, "get-outputs") == 0)
pretty_output_list(data);
else else
json_dumpf(data, stdout, JSON_INDENT(2)); json_dumpf(data, stdout, JSON_INDENT(2));
} }

View File

@ -47,6 +47,7 @@ enum cmd_type {
CMD_EVENT_RECEIVE, CMD_EVENT_RECEIVE,
CMD_SET_OUTPUT, CMD_SET_OUTPUT,
CMD_GET_CLIENTS, CMD_GET_CLIENTS,
CMD_GET_OUTPUTS,
CMD_UNKNOWN, CMD_UNKNOWN,
}; };
#define CMD_LIST_LEN CMD_UNKNOWN #define CMD_LIST_LEN CMD_UNKNOWN
@ -99,7 +100,10 @@ static struct cmd_info cmd_list[] = {
"Return a list of all currently connected VNC sessions", "Return a list of all currently connected VNC sessions",
{{NULL, NULL}} {{NULL, NULL}}
}, },
[CMD_GET_OUTPUTS] = { "get-outputs",
"Return a list of all currently detected Wayland outputs",
{{NULL, NULL}}
},
}; };
#define CLIENT_EVENT_PARAMS(including) \ #define CLIENT_EVENT_PARAMS(including) \
@ -290,6 +294,7 @@ static struct cmd* parse_command(struct jsonipc_request* ipc,
case CMD_VERSION: case CMD_VERSION:
case CMD_EVENT_RECEIVE: case CMD_EVENT_RECEIVE:
case CMD_GET_CLIENTS: case CMD_GET_CLIENTS:
case CMD_GET_OUTPUTS:
cmd = calloc(1, sizeof(*cmd)); cmd = calloc(1, sizeof(*cmd));
cmd->type = cmd_type; cmd->type = cmd_type;
break; break;
@ -448,6 +453,25 @@ static struct cmd_response* generate_vnc_client_list(struct ctl* self)
return response; return response;
} }
static struct cmd_response* generate_output_list(struct ctl* self)
{
struct ctl_server_output* outputs;
size_t num_outputs = self->actions.get_output_list(self, &outputs);
struct cmd_response* response = cmd_ok();
response->data = json_array();
for (int i = 0; i < num_outputs; ++i)
json_array_append_new(response->data, json_pack(
"{s:s, s:s, s:i, s:i, s:b}",
"name", outputs[i].name,
"description", outputs[i].description,
"height", outputs[i].height,
"width", outputs[i].width,
"captured", outputs[i].captured));
free(outputs);
return response;
}
static struct cmd_response* ctl_server_dispatch_cmd(struct ctl* self, static struct cmd_response* ctl_server_dispatch_cmd(struct ctl* self,
struct ctl_client* client, struct cmd* cmd) struct ctl_client* client, struct cmd* cmd)
{ {
@ -479,6 +503,9 @@ static struct cmd_response* ctl_server_dispatch_cmd(struct ctl* self,
case CMD_GET_CLIENTS: case CMD_GET_CLIENTS:
response = generate_vnc_client_list(self); response = generate_vnc_client_list(self);
break; break;
case CMD_GET_OUTPUTS:
response = generate_output_list(self);
break;
case CMD_UNKNOWN: case CMD_UNKNOWN:
break; break;
} }

View File

@ -493,6 +493,30 @@ static int get_client_list(struct ctl* ctl,
return self->nr_clients; return self->nr_clients;
} }
static int get_output_list(struct ctl* ctl,
struct ctl_server_output** outputs)
{
struct wayvnc* self = ctl_server_userdata(ctl);
int n = wl_list_length(&self->outputs);
if (n == 0) {
*outputs = NULL;
return 0;
}
*outputs = calloc(n, sizeof(**outputs));
struct output* output;
struct ctl_server_output* item = *outputs;
wl_list_for_each(output, &self->outputs, link) {
strlcpy(item->name, output->name, sizeof(item->name));
strlcpy(item->description, output->description,
sizeof(item->description));
item->height = output->height;
item->width = output->width;
item->captured = (output->id == self->selected_output->id);
item++;
}
return n;
}
int init_main_loop(struct wayvnc* self) int init_main_loop(struct wayvnc* self)
{ {
struct aml* loop = aml_get_default(); struct aml* loop = aml_get_default();
@ -1335,6 +1359,7 @@ int main(int argc, char* argv[])
.on_output_cycle = on_output_cycle, .on_output_cycle = on_output_cycle,
.on_output_switch = on_output_switch, .on_output_switch = on_output_switch,
.get_client_list = get_client_list, .get_client_list = get_client_list,
.get_output_list = get_output_list,
}; };
self.ctl = ctl_server_new(socket_path, &ctl_actions); self.ctl = ctl_server_new(socket_path, &ctl_actions);
if (!self.ctl) if (!self.ctl)

View File

@ -68,11 +68,15 @@ is also possible to run wayvnc without a physical display attached.
## MULTIPLE OUTPUTS ## MULTIPLE OUTPUTS
If the Wayland session consists of multiple outputs, only one will be captured. If the Wayland session consists of multiple outputs, only one will be captured.
By default this will be the first one, but can be specified by the _-o_ command By default this will be the first one, but can be specified by the _-o_ command
line argument. The argument accepts the short name such as _eDP-1_ or _DP-4_. line argument. The argument accepts the short name such as _eDP-1_ or _DP-4_.
Running wayvnc in verbose mode (_-v_) will display the names of all outputs on Running wayvnc in verbose mode (_-v_) will display the names of all outputs on
startup. startup, or you can query them at runtime via the *wayvncctl get-outputs*
command.
You can also change which output is being captured on the fly via the *wayvncctl
set-output* command.
# CONFIGURATION # CONFIGURATION
@ -204,6 +208,11 @@ _GET-CLIENTS_
The *get-clients* command retrieves a list of all VNC clients currently The *get-clients* command retrieves a list of all VNC clients currently
connected to wayvnc. connected to wayvnc.
_GET-OUTPUTS_
The *get-outputs* command retrieves a list of all outputs known to wayvnc and
whether or not each one is currently being captured.
## IPC EVENTS ## IPC EVENTS
_CLIENT-CONNECTED_ _CLIENT-CONNECTED_