From b7d8fc1a0be728e8830c04fa6d836c8d18c6bc3a Mon Sep 17 00:00:00 2001 From: notaz Date: Sun, 13 Jul 2014 21:39:59 +0300 Subject: [PATCH] commands over unix socket --- Makefile | 5 ++- custom.c | 48 +++++++++++++++++++++ main.c | 120 ++++++++++++++++++++++++++++++++++++++++++++++------- readme.txt | 33 +++++++++++++++ 4 files changed, 191 insertions(+), 15 deletions(-) create mode 100644 custom.c diff --git a/Makefile b/Makefile index fe05688..7bae7b7 100644 --- a/Makefile +++ b/Makefile @@ -7,11 +7,14 @@ LDLIBS += -lpthread -lrt OBJS = main.o fonts.o -all: liveinfo +all: liveinfo custom liveinfo: $(OBJS) $(CC) -o $@ $^ $(CFLAGS) $(LDFLAGS) $(LDLIBS) +custom: custom.c + $(CC) -o $@ $^ $(CFLAGS) $(LDFLAGS) + clean: $(RM) liveinfo $(OBJS) diff --git a/custom.c b/custom.c new file mode 100644 index 0000000..728e831 --- /dev/null +++ b/custom.c @@ -0,0 +1,48 @@ +/* + * This file is licensed under the Creative Commons Zero License, + * version 1.0, available at + * http://creativecommons.org/publicdomain/zero/1.0/legalcode + */ + +#include +#include +#include +#include +#include + +/* + * example usage: + * ./custom "fps: 60" + */ +int main(int argc, char *argv[]) +{ + static const char socket_name[] = "\0liveinfo"; + struct sockaddr_un sun; + int sock; + int ret; + + if (argv[1] == NULL) { + fprintf(stderr, "usage:\n%s \"label: value\"\n", argv[0]); + return 1; + } + + sock = socket(PF_UNIX, SOCK_DGRAM, 0); + if (sock == -1) { + perror("socket PF_UNIX"); + return 1; + } + + memset(&sun, 0, sizeof(sun)); + sun.sun_family = AF_UNIX; + memcpy(sun.sun_path, socket_name, sizeof(socket_name)); + + ret = sendto(sock, argv[1], strlen(argv[1]), 0, + (struct sockaddr *)&sun, sizeof(sun)); + if (ret < 0) { + perror("sendto"); + return 1; + } + + close(sock); + return 0; +} diff --git a/main.c b/main.c index 75799b4..010f63c 100644 --- a/main.c +++ b/main.c @@ -42,6 +42,7 @@ static int g_flip_id; static int g_exit, g_hide; static pthread_cond_t g_cond; +#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0])) #define IS_START(buf, str) \ !strncmp(buf, str, sizeof(str) - 1) @@ -218,6 +219,70 @@ static void handle_usr1(int num) pthread_cond_signal(&g_cond); } +static struct { + char text[16]; + int idle; +} user_msgs[16]; + +static int handle_socket(int sock) +{ + char buf[256], *p; + int i, ret; + + ret = recv(sock, buf, sizeof(buf) - 1, 0); + if (ret < 0) { + perror("recv"); + return ret; + } + if (ret == 0) + return 0; + + buf[ret] = 0; + p = strchr(buf, ':'); + if (p != NULL) { + for (i = 0; i < ARRAY_SIZE(user_msgs); i++) { + if (user_msgs[i].text[0] == 0) + break; + if (!strncmp(user_msgs[i].text, buf, p - buf + 1)) + break; + } + if (i == ARRAY_SIZE(user_msgs)) { + printf("out of user_msg slots\n"); + return 0; + } + memcpy(user_msgs[i].text, buf, sizeof(user_msgs[i].text) - 1); + user_msgs[i].text[sizeof(user_msgs[i].text) - 1] = 0; + user_msgs[i].idle = 0; + } + else if (!strcmp(buf, "poke")) { + // if hidden, show up + // if visible, exit + if (g_hide) { + g_hide = 0; + return 1; + } + g_exit = 1; + return 1; + } + else if (!strcmp(buf, "hide")) { + g_hide = 1; + return 1; + } + else if (!strcmp(buf, "show")) { + g_hide = 0; + return 1; + } + else if (!strcmp(buf, "quit")) { + g_exit = 1; + return 1; + } + else { + printf("unknown command: '%s'\n", buf); + } + + return 0; +} + #define s_printf(x, y, fmt, ...) \ basic_text_out16(g_screen, WIDTH, x, y, fmt, ##__VA_ARGS__); @@ -678,10 +743,10 @@ int main(int argc, char *argv[]) int y = 0, y_max = 0; int fd = -1; int sock; - int ret; + int i, ret; // look for other instance - sock = socket(PF_UNIX, SOCK_STREAM, 0); + sock = socket(PF_UNIX, SOCK_DGRAM, 0); if (sock == -1) { perror("socket PF_UNIX"); return 1; @@ -694,11 +759,11 @@ int main(int argc, char *argv[]) ret = connect(sock, (struct sockaddr *)&sun, sizeof(sun)); if (ret == 0) { printf("other instance detected, sending poke command\n"); - ret = send(sock, "poke", 5, 0); - if (ret != 5) + ret = send(sock, "poke", 4, 0); + if (ret != 4) perror("send"); close(sock); - return ret == 5 ? 0 : 1; + return ret == 4 ? 0 : 1; } fd = open(fbname, O_RDWR); @@ -729,12 +794,14 @@ int main(int argc, char *argv[]) return 1; } +#if 0 ret = listen(sock, 1); if (ret != 0) { perror("listen"); close(sock); return 1; } +#endif pfd.fd = sock; pfd.events = POLLIN | POLLPRI; @@ -768,6 +835,19 @@ int main(int argc, char *argv[]) while (!g_exit) { + // anything on unix socket? + ret = poll(&pfd, 1, 0); + if (ret < 0) { + perror("poll"); + break; + } + if (ret > 0) { + ret = handle_socket(sock); + if (ret < 0) + break; + continue; + } + // handle hiding if (g_hide) { if (!is_hidden) { @@ -783,6 +863,9 @@ int main(int argc, char *argv[]) is_hidden = 0; } + if (check_layer(fd) != 0) + break; + collect_stats(); y += Y_STEP; @@ -823,18 +906,27 @@ int main(int argc, char *argv[]) get_bwatts (0, y += Y_STEP); get_btemp (0, y += Y_STEP); - flip_fb(fd); - - if (check_layer(fd) != 0) - break; + // print user messages + y += Y_STEP; + for (i = 0; i < ARRAY_SIZE(user_msgs); i++) { + if (user_msgs[i].text[0] == 0) + break; + user_msgs[i].idle++; + if (user_msgs[i].idle > 6) { + // drop old entry, shift others up + memmove(&user_msgs[i], &user_msgs[i + 1], + (ARRAY_SIZE(user_msgs) - i - 1) * sizeof(user_msgs[0])); + user_msgs[ARRAY_SIZE(user_msgs) - 1].text[0] = 0; + // reprocess + i--; + continue; + } - // anything on unix socket? - ret = poll(&pfd, 1, 0); - if (ret != 0) { - printf("poll returned %d\n", ret); - break; + s_printf(0, y += Y_STEP, user_msgs[i].text); } + flip_fb(fd); + do_sleep: ts.tv_sec++; pthread_cond_timedwait(&g_cond, &mutex, &ts); diff --git a/readme.txt b/readme.txt index fbcacbd..acc9149 100644 --- a/readme.txt +++ b/readme.txt @@ -44,6 +44,39 @@ Fields T: 23.2C battery temperature +Controlling live info +--------------------- + +It's possible to hide Live info by sending it USR1 signal and show it +again by sending the same signal. This can be done by simply running +"killall -USR1 liveinfo" command. This command can also be bound to +xfce keyboard shortcuts or similar. +Sending the TERM signal ("killall liveinfo") causes it to cleanly exit +(sending it KILL / -9 signal will leave the layer enabled and visible, +so is not recommended). + + +Showing custom fields and alternative control +--------------------------------------------- + +There is a tool called 'custom' included inside of .pnd, it can be used +to also send commands and display custom fields. The code is included +inside the .pnd and can be integrated in other programs, it's simple +communication over local/unix sockets. + +Any command containing a semicolon ":" is interpreted as a field to +display on screen. For example, running +./custom "fps: 60" +will show that string on screen. There is no removal command, the +string will time out by itself. + +Other understood commands are: + quit - self explanatory + hide + show + poke - if hidden, show up; if visible, exit + + License ------- -- 2.39.2