Introduce an event loop mode in wayvncctl
Signed-off-by: Jim Ramsay <i.am@jimramsay.com>pull/183/head
parent
debd8a67cb
commit
d8239109e5
|
@ -52,6 +52,8 @@ struct jsonipc_request* jsonipc_request_parse_new(json_t* root,
|
||||||
struct jsonipc_error* err);
|
struct jsonipc_error* err);
|
||||||
struct jsonipc_request* jsonipc_request_new(const char* method, json_t* params);
|
struct jsonipc_request* jsonipc_request_new(const char* method, json_t* params);
|
||||||
struct jsonipc_request* jsonipc_event_new(const char* method, json_t* params);
|
struct jsonipc_request* jsonipc_event_new(const char* method, json_t* params);
|
||||||
|
struct jsonipc_request* jsonipc_event_parse_new(json_t* root,
|
||||||
|
struct jsonipc_error* err);
|
||||||
json_t* jsonipc_request_pack(struct jsonipc_request*, json_error_t* err);
|
json_t* jsonipc_request_pack(struct jsonipc_request*, json_error_t* err);
|
||||||
void jsonipc_request_destroy(struct jsonipc_request*);
|
void jsonipc_request_destroy(struct jsonipc_request*);
|
||||||
|
|
||||||
|
|
116
src/ctl-client.c
116
src/ctl-client.c
|
@ -200,6 +200,8 @@ static json_t* read_one_object(struct ctl_client* self, int timeout_ms)
|
||||||
while (root == NULL) {
|
while (root == NULL) {
|
||||||
int n = poll(&pfd, 1, timeout_ms);
|
int n = poll(&pfd, 1, timeout_ms);
|
||||||
if (n == -1) {
|
if (n == -1) {
|
||||||
|
if (errno == EINTR && self->wait_for_events)
|
||||||
|
continue;
|
||||||
WARN("Error waiting for a response: %m");
|
WARN("Error waiting for a response: %m");
|
||||||
break;
|
break;
|
||||||
} else if (n == 0) {
|
} else if (n == 0) {
|
||||||
|
@ -395,17 +397,121 @@ static void setup_signals(struct ctl_client* self)
|
||||||
sigaction(SIGTERM, &sa, NULL);
|
sigaction(SIGTERM, &sa, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ctl_client_event_loop(struct ctl_client* self)
|
static void print_indent(int level)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < level; ++i)
|
||||||
|
printf(" ");
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool json_has_content(json_t* root)
|
||||||
|
{
|
||||||
|
if (!root)
|
||||||
|
return false;
|
||||||
|
size_t i;
|
||||||
|
const char* key;
|
||||||
|
json_t* value;
|
||||||
|
switch (json_typeof(root)) {
|
||||||
|
case JSON_NULL:
|
||||||
|
return false;
|
||||||
|
case JSON_INTEGER:
|
||||||
|
case JSON_REAL:
|
||||||
|
case JSON_TRUE:
|
||||||
|
case JSON_FALSE:
|
||||||
|
return true;
|
||||||
|
case JSON_STRING:
|
||||||
|
return json_string_value(root)[0] != '\0';
|
||||||
|
case JSON_OBJECT:
|
||||||
|
json_object_foreach(root, key, value)
|
||||||
|
if (json_has_content(value))
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
case JSON_ARRAY:
|
||||||
|
json_array_foreach(root, i, value)
|
||||||
|
if (json_has_content(value))
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void print_as_yaml(json_t* data, int level, bool needs_leading_newline)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
const char* key;
|
||||||
|
json_t* value;
|
||||||
|
bool needs_indent = needs_leading_newline;
|
||||||
|
switch(json_typeof(data)) {
|
||||||
|
case JSON_NULL:
|
||||||
|
printf("<null>\n");
|
||||||
|
break;
|
||||||
|
case JSON_OBJECT:
|
||||||
|
if (json_object_size(data) > 0 && needs_leading_newline)
|
||||||
|
printf("\n");
|
||||||
|
json_object_foreach(data, key, value) {
|
||||||
|
if (!json_has_content(value))
|
||||||
|
continue;
|
||||||
|
if (needs_indent)
|
||||||
|
print_indent(level);
|
||||||
|
else
|
||||||
|
needs_indent = true;
|
||||||
|
printf("%s: ", key);
|
||||||
|
print_as_yaml(value, level + 1, true);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case JSON_ARRAY:
|
||||||
|
if (json_array_size(data) > 0 && needs_leading_newline)
|
||||||
|
printf("\n");
|
||||||
|
json_array_foreach(data, i, value) {
|
||||||
|
if (!json_has_content(value))
|
||||||
|
continue;
|
||||||
|
print_indent(level);
|
||||||
|
printf("- ");
|
||||||
|
print_as_yaml(value, level + 1, json_is_array(value));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case JSON_STRING:
|
||||||
|
printf("%s\n", json_string_value(data));
|
||||||
|
break;
|
||||||
|
case JSON_INTEGER:
|
||||||
|
printf("%" JSON_INTEGER_FORMAT "\n", json_integer_value(data));
|
||||||
|
break;
|
||||||
|
case JSON_REAL:
|
||||||
|
printf("%f\n", json_real_value(data));
|
||||||
|
break;
|
||||||
|
case JSON_TRUE:
|
||||||
|
printf("true\n");
|
||||||
|
break;
|
||||||
|
case JSON_FALSE:
|
||||||
|
printf("false\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void print_event(struct jsonipc_request* event, unsigned flags)
|
||||||
|
{
|
||||||
|
if (flags & PRINT_JSON) {
|
||||||
|
print_compact_json(event->json);
|
||||||
|
} else {
|
||||||
|
printf("\n%s:", event->method);
|
||||||
|
print_as_yaml(event->params, 1, true);
|
||||||
|
}
|
||||||
|
fflush(stdout);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ctl_client_event_loop(struct ctl_client* self, unsigned flags)
|
||||||
{
|
{
|
||||||
self->wait_for_events = true;
|
self->wait_for_events = true;
|
||||||
setup_signals(self);
|
setup_signals(self);
|
||||||
while (self->wait_for_events) {
|
while (self->wait_for_events) {
|
||||||
DEBUG("Waiting for an event");
|
DEBUG("Waiting for an event");
|
||||||
json_t* root = read_one_object(self, -1);
|
json_t* root = read_one_object(self, -1);
|
||||||
json_dumpf(root, stdout, 0);
|
if (!root)
|
||||||
printf("\n");
|
break;
|
||||||
fflush(stdout);
|
struct jsonipc_error err = JSONIPC_ERR_INIT;
|
||||||
|
struct jsonipc_request* event = jsonipc_event_parse_new(root, &err);
|
||||||
json_decref(root);
|
json_decref(root);
|
||||||
|
print_event(event, flags);
|
||||||
|
jsonipc_request_destroy(event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -427,7 +533,7 @@ int ctl_client_run_command(struct ctl_client* self,
|
||||||
result = ctl_client_print_response(self, request, response, flags);
|
result = ctl_client_print_response(self, request, response, flags);
|
||||||
|
|
||||||
if (result == 0 && strcmp(request->method, "event-receive") == 0)
|
if (result == 0 && strcmp(request->method, "event-receive") == 0)
|
||||||
ctl_client_event_loop(self);
|
ctl_client_event_loop(self, flags);
|
||||||
|
|
||||||
jsonipc_response_destroy(response);
|
jsonipc_response_destroy(response);
|
||||||
receive_failure:
|
receive_failure:
|
||||||
|
|
|
@ -111,6 +111,12 @@ struct jsonipc_request* jsonipc_event_new(const char* method, json_t* params)
|
||||||
return jsonipc_request__new(method, params, NULL);
|
return jsonipc_request__new(method, params, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct jsonipc_request* jsonipc_event_parse_new(json_t* root,
|
||||||
|
struct jsonipc_error* err)
|
||||||
|
{
|
||||||
|
return jsonipc_request_parse_new(root, err);
|
||||||
|
}
|
||||||
|
|
||||||
json_t* jsonipc_request_pack(struct jsonipc_request* self, json_error_t* err)
|
json_t* jsonipc_request_pack(struct jsonipc_request* self, json_error_t* err)
|
||||||
{
|
{
|
||||||
return json_pack_ex(err, 0, "{s:s, s:O*, s:O*}",
|
return json_pack_ex(err, 0, "{s:s, s:O*, s:O*}",
|
||||||
|
|
|
@ -46,9 +46,36 @@ command and its available parameters.
|
||||||
|
|
||||||
While *wayvncctl* normally terminates after sending one request and receiving
|
While *wayvncctl* normally terminates after sending one request and receiving
|
||||||
the corresponding reply, the *event-receive* command acts differently. Instead
|
the corresponding reply, the *event-receive* command acts differently. Instead
|
||||||
of exiting immediately, *wayvncctl* waits for any events fr the server, printing
|
of exiting immediately, *wayvncctl* waits for any events from the server,
|
||||||
each to stdout as they arrive. This mode of operation will block until either
|
printing each to stdout as they arrive. This mode of operation will block until
|
||||||
it receives a signal to terminate, or until the wayvnc server terminates.
|
either it receives a signal to terminate, or until the wayvnc server terminates.
|
||||||
|
|
||||||
|
In _--json_ mode, each event is printed on one line, with a newline character at
|
||||||
|
the end, for ease in scripting:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ wayvncctl --json event-receive
|
||||||
|
{"method":"client-connected","params":{"id":"0x10ef670","hostname":null,"username":null,"connection_count":1}}
|
||||||
|
{"method":"client-disconnected","params":{"id":"0x10ef670","hostname":null,"username":null,"connection_count":0}}
|
||||||
|
```
|
||||||
|
|
||||||
|
The default human-readible output is a multi-line yaml-like format, with two
|
||||||
|
newline characters between each event:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ wayvncctl event-receive
|
||||||
|
|
||||||
|
client-connected:
|
||||||
|
id: 0x10ef670
|
||||||
|
hostname: 192.168.1.18
|
||||||
|
connection_count: 1
|
||||||
|
|
||||||
|
client-disconnected:
|
||||||
|
id: 0x10ef670
|
||||||
|
hostname: 192.168.1.18
|
||||||
|
connection_count: 0
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
# EXAMPLES
|
# EXAMPLES
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue