Handle all wayvncctl help commands locally
This means that wayvncctl can now provide full descriptions of all commands and events without wayvnc running. Signed-off-by: Jim Ramsay <i.am@jimramsay.com>pull/201/head
parent
d75ca4bf51
commit
cb116cc980
|
@ -16,6 +16,7 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
struct ctl_client;
|
||||
|
@ -26,9 +27,12 @@ struct ctl_client* ctl_client_new(const char* socket_path, void* userdata);
|
|||
void ctl_client_destroy(struct ctl_client*);
|
||||
void* ctl_client_userdata(struct ctl_client*);
|
||||
|
||||
#define PRINT_JSON 0x00000001
|
||||
#define RECONNECT 0x00000002
|
||||
#define CTL_CLIENT_PRINT_JSON (1 << 0)
|
||||
#define CTL_CLIENT_SOCKET_WAIT (1 << 1)
|
||||
#define CTL_CLIENT_RECONNECT (1 << 2)
|
||||
|
||||
int ctl_client_connect(struct ctl_client* self, int timeout);
|
||||
int ctl_client_run_command(struct ctl_client* self,
|
||||
int argc, char* argv[], unsigned flags);
|
||||
|
||||
void ctl_client_print_command_list(FILE* stream);
|
||||
void ctl_client_print_event_list(FILE* stream);
|
||||
|
|
184
src/ctl-client.c
184
src/ctl-client.c
|
@ -144,7 +144,7 @@ static int try_connect(struct ctl_client* self, int timeout)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int ctl_client_connect(struct ctl_client* self, int timeout)
|
||||
static int ctl_client_connect(struct ctl_client* self, int timeout)
|
||||
{
|
||||
// TODO: Support arbitrary timeouts?
|
||||
assert(timeout == 0 || timeout == -1);
|
||||
|
@ -311,79 +311,6 @@ out:
|
|||
printf("\n");
|
||||
}
|
||||
|
||||
static void print_command_usage(const char* name, json_t* data)
|
||||
{
|
||||
char* desc = NULL;
|
||||
json_t* params = NULL;
|
||||
json_unpack(data, "{s:s, s?o}", "description", &desc,
|
||||
"params", ¶ms);
|
||||
printf("Usage: wayvncctl [options] %s%s\n\n%s\n", name,
|
||||
params ? " [params]" : "",
|
||||
desc);
|
||||
if (params) {
|
||||
printf("\nParameters:");
|
||||
const char* param_name;
|
||||
json_t* param_value;
|
||||
json_object_foreach(params, param_name, param_value) {
|
||||
printf("\n --%s=...\n %s\n", param_name,
|
||||
json_string_value(param_value));
|
||||
}
|
||||
}
|
||||
printf("\nRun 'wayvncctl --help' for allowed Options\n");
|
||||
}
|
||||
|
||||
static void print_event_details(const char* name, json_t* data)
|
||||
{
|
||||
char* desc = NULL;
|
||||
json_t* params = NULL;
|
||||
json_unpack(data, "{s:s, s?o}", "description", &desc,
|
||||
"params", ¶ms);
|
||||
printf("Event: %s\n\n%s\n", name,
|
||||
desc);
|
||||
if (params) {
|
||||
printf("\nParameters:");
|
||||
const char* param_name;
|
||||
json_t* param_value;
|
||||
json_object_foreach(params, param_name, param_value) {
|
||||
printf("\n %s:...\n %s\n", param_name,
|
||||
json_string_value(param_value));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void print_help(json_t* data, json_t* request)
|
||||
{
|
||||
if (json_object_get(data, "commands")) {
|
||||
printf("Allowed commands:\n");
|
||||
json_t* cmd_list = json_object_get(data, "commands");
|
||||
|
||||
size_t index;
|
||||
json_t* value;
|
||||
json_array_foreach(cmd_list, index, value) {
|
||||
printf(" - %s\n", json_string_value(value));
|
||||
}
|
||||
printf("\nRun 'wayvncctl command-name --help' for command-specific details.\n");
|
||||
|
||||
printf("\nSupported events:\n");
|
||||
json_t* evt_list = json_object_get(data, "events");
|
||||
json_array_foreach(evt_list, index, value) {
|
||||
printf(" - %s\n", json_string_value(value));
|
||||
}
|
||||
printf("\nRun 'wayvncctl help --event=event-name' for event-specific details.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
bool is_command = json_object_get(request, "command");
|
||||
const char* key;
|
||||
json_t* value;
|
||||
json_object_foreach(data, key, value) {
|
||||
if (is_command)
|
||||
print_command_usage(key, value);
|
||||
else
|
||||
print_event_details(key, value);
|
||||
}
|
||||
}
|
||||
|
||||
static void pretty_version(json_t* data)
|
||||
{
|
||||
printf("wayvnc is running:\n");
|
||||
|
@ -441,9 +368,6 @@ static void pretty_print(json_t* data,
|
|||
{
|
||||
enum cmd_type cmd = ctl_command_parse_name(request->method);
|
||||
switch (cmd) {
|
||||
case CMD_HELP:
|
||||
print_help(data, request->params);
|
||||
break;
|
||||
case CMD_VERSION:
|
||||
pretty_version(data);
|
||||
break;
|
||||
|
@ -459,7 +383,8 @@ static void pretty_print(json_t* data,
|
|||
printf("Ok\n");
|
||||
break;
|
||||
case CMD_EVENT_RECEIVE:
|
||||
abort(); // Event loop code handles this one
|
||||
case CMD_HELP:
|
||||
abort(); // Handled directly by ctl_client_run_command
|
||||
case CMD_UNKNOWN:
|
||||
json_dumpf(data, stdout, JSON_INDENT(2));
|
||||
}
|
||||
|
@ -477,7 +402,7 @@ static int ctl_client_print_response(struct ctl_client* self,
|
|||
{
|
||||
DEBUG("Response code: %d", response->code);
|
||||
if (response->data) {
|
||||
if (self->flags & PRINT_JSON)
|
||||
if (self->flags & CTL_CLIENT_PRINT_JSON)
|
||||
print_compact_json(response->data);
|
||||
else if (response->code == 0)
|
||||
pretty_print(response->data, request);
|
||||
|
@ -594,7 +519,7 @@ static void print_as_yaml(json_t* data, int level, bool needs_leading_newline)
|
|||
|
||||
static void print_event(struct jsonipc_request* event, unsigned flags)
|
||||
{
|
||||
if (flags & PRINT_JSON) {
|
||||
if (flags & CTL_CLIENT_PRINT_JSON) {
|
||||
print_compact_json(event->json);
|
||||
} else {
|
||||
printf("\n%s:", event->method);
|
||||
|
@ -686,7 +611,7 @@ static int ctl_client_event_loop(struct ctl_client* self,
|
|||
if (!root) {
|
||||
if (errno == ECONNRESET) {
|
||||
send_shutdown_event(self);
|
||||
if (self->flags & RECONNECT &&
|
||||
if (self->flags & CTL_CLIENT_RECONNECT &&
|
||||
ctl_client_reconnect_event_loop(
|
||||
self, request, -1) == 0)
|
||||
continue;
|
||||
|
@ -714,6 +639,93 @@ static int ctl_client_print_single_command(struct ctl_client* self,
|
|||
return result;
|
||||
}
|
||||
|
||||
void ctl_client_print_command_list(FILE* stream)
|
||||
{
|
||||
fprintf(stream, "Commands:\n");
|
||||
for (size_t i = 0; i < CMD_LIST_LEN; ++i)
|
||||
fprintf(stream, " - %s\n", ctl_command_list[i].name);
|
||||
fprintf(stream, "\nRun 'wayvncctl command-name --help' for command-specific details.\n");
|
||||
}
|
||||
|
||||
void ctl_client_print_event_list(FILE* stream)
|
||||
{
|
||||
printf("Events:\n");
|
||||
for (size_t i = 0; i < EVT_LIST_LEN; ++i)
|
||||
printf(" - %s\n", ctl_event_list[i].name);
|
||||
printf("\nRun 'wayvncctl help --event=event-name' for event-specific details.\n");
|
||||
}
|
||||
|
||||
static void print_cmd_info_params(const struct cmd_info* info)
|
||||
{
|
||||
if (info->params[0].name != NULL) {
|
||||
printf("\nParameters:");
|
||||
for (int i = 0; info->params[i].name != NULL; ++i)
|
||||
printf("\n --%s=...\n %s\n", info->params[i].name,
|
||||
info->params[i].description);
|
||||
}
|
||||
}
|
||||
|
||||
static int print_command_usage(const char* cmd_name)
|
||||
{
|
||||
enum cmd_type type = ctl_command_parse_name(cmd_name);
|
||||
struct cmd_info* info = ctl_command_by_type(type);
|
||||
if (!info) {
|
||||
WARN("No such command \"%s\"\n", cmd_name);
|
||||
return 1;
|
||||
}
|
||||
bool params = info->params[0].name != NULL;
|
||||
printf("Usage: wayvncctl [options] %s%s\n\n%s\n", info->name,
|
||||
params ? " [params]" : "",
|
||||
info->description);
|
||||
print_cmd_info_params(info);
|
||||
printf("\nRun 'wayvncctl --help' for allowed options\n");
|
||||
if (type == CMD_EVENT_RECEIVE) {
|
||||
printf("\n");
|
||||
ctl_client_print_event_list(stdout);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int print_event_details(const char* evt_name)
|
||||
{
|
||||
struct cmd_info* info = ctl_event_by_name(evt_name);
|
||||
if (!info) {
|
||||
WARN("No such event \"%s\"\n", evt_name);
|
||||
return 1;
|
||||
}
|
||||
printf("Event: %s\n\n%s\n", info->name,
|
||||
info->description);
|
||||
print_cmd_info_params(info);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ctl_client_print_help(struct ctl_client* self,
|
||||
struct jsonipc_request* request)
|
||||
{
|
||||
if (self->flags & CTL_CLIENT_PRINT_JSON) {
|
||||
WARN("JSON output is not supported for the \"help\" command");
|
||||
return 1;
|
||||
}
|
||||
|
||||
json_t* params = request->params;
|
||||
const char* cmd_name = NULL;
|
||||
const char* evt_name = NULL;
|
||||
if (params)
|
||||
json_unpack(params, "{s?s, s?s}", "command", &cmd_name,
|
||||
"event", &evt_name);
|
||||
|
||||
if (cmd_name)
|
||||
return print_command_usage(cmd_name);
|
||||
if (evt_name)
|
||||
return print_event_details(evt_name);
|
||||
|
||||
ctl_client_print_command_list(stdout);
|
||||
printf("\n");
|
||||
ctl_client_print_event_list(stdout);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ctl_client_run_command(struct ctl_client* self,
|
||||
int argc, char* argv[], unsigned flags)
|
||||
{
|
||||
|
@ -725,7 +737,17 @@ int ctl_client_run_command(struct ctl_client* self,
|
|||
goto parse_failure;
|
||||
|
||||
enum cmd_type cmd = ctl_command_parse_name(request->method);
|
||||
if (cmd != CMD_HELP) {
|
||||
int timeout = (flags & CTL_CLIENT_SOCKET_WAIT) ? -1 : 0;
|
||||
result = ctl_client_connect(self, timeout);
|
||||
if (result != 0)
|
||||
return result;
|
||||
}
|
||||
|
||||
switch (cmd) {
|
||||
case CMD_HELP:
|
||||
result = ctl_client_print_help(self, request);
|
||||
break;
|
||||
case CMD_EVENT_RECEIVE:
|
||||
result = ctl_client_event_loop(self, request);
|
||||
break;
|
||||
|
|
|
@ -47,11 +47,11 @@ static int wayvncctl_usage(FILE* stream, struct option_parser* options, int rc)
|
|||
static const char* usage =
|
||||
"Usage: wayvncctl [options] [command [--param1=value1 ...]]\n"
|
||||
"\n"
|
||||
"Connects to and interacts with a running wayvnc instance."
|
||||
"\n"
|
||||
"Try 'wayvncctl help' for a list of available commands.";
|
||||
"Connects to and interacts with a running wayvnc instance.";
|
||||
fprintf(stream, "%s\n\n", usage);
|
||||
option_parser_print_options(options, stream);
|
||||
fprintf(stream, "\n");
|
||||
ctl_client_print_command_list(stream);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
@ -67,7 +67,6 @@ int main(int argc, char* argv[])
|
|||
|
||||
bool verbose = false;
|
||||
const char* socket_path = NULL;
|
||||
int wait_for_socket = 0;
|
||||
|
||||
unsigned flags = 0;
|
||||
|
||||
|
@ -103,13 +102,13 @@ int main(int argc, char* argv[])
|
|||
socket_path = optarg;
|
||||
break;
|
||||
case 'w':
|
||||
wait_for_socket = -1;
|
||||
flags |= CTL_CLIENT_SOCKET_WAIT;
|
||||
break;
|
||||
case 'r':
|
||||
flags |= RECONNECT;
|
||||
flags |= CTL_CLIENT_RECONNECT;
|
||||
break;
|
||||
case 'j':
|
||||
flags |= PRINT_JSON;
|
||||
flags |= CTL_CLIENT_PRINT_JSON;
|
||||
break;
|
||||
case 'v':
|
||||
verbose = true;
|
||||
|
@ -133,13 +132,8 @@ int main(int argc, char* argv[])
|
|||
if (!self.ctl)
|
||||
goto ctl_client_failure;
|
||||
|
||||
int result = ctl_client_connect(self.ctl, wait_for_socket);
|
||||
if (result != 0)
|
||||
goto socket_failure;
|
||||
int result = ctl_client_run_command(self.ctl, argc, argv, flags);
|
||||
|
||||
result = ctl_client_run_command(self.ctl, argc, argv, flags);
|
||||
|
||||
socket_failure:
|
||||
ctl_client_destroy(self.ctl);
|
||||
|
||||
return result;
|
||||
|
|
|
@ -44,12 +44,14 @@ For a full list of currently supported commands, see
|
|||
*wayvnc(1)* section _IPC COMMANDS_, or run the
|
||||
*wayvncctl help* command.
|
||||
|
||||
Running *wayvncctl help* contacts the server over the control socket and returns
|
||||
a list of the available commands.
|
||||
Running *wayvncctl help* returns a list of the available commands and events.
|
||||
|
||||
Running *wayvncctl command-name --help* returns a description of the server-side
|
||||
command and its available parameters.
|
||||
|
||||
Running *wayvncctl help --event=event-name* returns a description of the
|
||||
server-side event and expected parameters.
|
||||
|
||||
# ASYNCHRONOUS EVENTS
|
||||
|
||||
While *wayvncctl* normally terminates after sending one request and receiving
|
||||
|
@ -109,12 +111,24 @@ Query the server for all available IPC command names:
|
|||
|
||||
```
|
||||
$ wayvncctl help
|
||||
Allowed commands:
|
||||
Commands:
|
||||
- help
|
||||
- version
|
||||
- event-receive
|
||||
- set-output
|
||||
- get-clients
|
||||
- get-outputs
|
||||
- disconnect-client
|
||||
- wayvnc-exit
|
||||
|
||||
Run 'wayvncctl command-name --help' for command-specific details.
|
||||
|
||||
Events:
|
||||
- client-connected
|
||||
- client-disconnected
|
||||
- capture-changed
|
||||
|
||||
Run 'wayvncctl help --event=event-name' for event-specific details.
|
||||
```
|
||||
|
||||
Get help on the "set-output" IPC command:
|
||||
|
|
Loading…
Reference in New Issue