--- /dev/null
+/*
+ * This file is licensed under the Creative Commons Zero License,
+ * version 1.0, available at
+ * http://creativecommons.org/publicdomain/zero/1.0/legalcode
+ */
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <unistd.h>
+
+/*
+ * 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;
+}
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)
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__);
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;
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);
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;
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) {
is_hidden = 0;
}
+ if (check_layer(fd) != 0)
+ break;
+
collect_stats();
y += Y_STEP;
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);
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
-------