]> mj.ucw.cz Git - osdd.git/blobdiff - client.c
Cleaned up utility functions and implemented `osd-batt --check-every'
[osdd.git] / client.c
diff --git a/client.c b/client.c
new file mode 100644 (file)
index 0000000..8b439f3
--- /dev/null
+++ b/client.c
@@ -0,0 +1,110 @@
+/*
+ *     On-screen Display -- Support Functions for Clients
+ *
+ *     (c) 2010 Martin Mares <mj@ucw.cz>
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <poll.h>
+#include <X11/Xlib.h>
+#include <X11/Xatom.h>
+
+#undef DEBUG
+#include "osd.h"
+
+static Display *dpy;
+static Atom pty;
+
+#define MAX_MSG_SIZE 1024
+
+struct osd_msg {
+  int cnt;
+  char buf[MAX_MSG_SIZE];
+};
+
+void
+osd_init(void)
+{
+  if (dpy)
+    return;
+
+  dpy = XOpenDisplay(NULL);
+  if (!dpy)
+    die("Cannot open display");
+
+  pty = XInternAtom(dpy, "OSD_QUEUE", False);
+  if (!pty)
+    die("Cannot intern OSD_QUEUE atom");
+}
+
+struct osd_msg *
+osd_new_msg(void)
+{
+  struct osd_msg *msg = xmalloc(sizeof(*msg));
+  msg->cnt = 0;
+  return msg;
+}
+
+void
+osd_add_line(struct osd_msg *msg, char *key, char *val)
+{
+  if (!key)
+    key = "";
+  msg->cnt += snprintf(msg->buf + msg->cnt, MAX_MSG_SIZE - msg->cnt - 1, "%s:%s\n", key, val);
+  if (msg->cnt > MAX_MSG_SIZE - 1)
+    die("OSD message too long (at most %d bytes)", MAX_MSG_SIZE);
+}
+
+void
+osd_send(struct osd_msg *msg)
+{
+  osd_init();
+  msg->buf[msg->cnt++] = '\n';
+  if (!XChangeProperty(dpy, DefaultRootWindow(dpy), pty, XA_STRING, 8, PropModeAppend, (unsigned char *) msg->buf, msg->cnt))
+    die("XChangeProperty failed");
+  XFlush(dpy);
+  free(msg);
+}
+
+void
+osd_fork(void)
+{
+  osd_init();
+  pid_t pid = fork();
+  if (pid < 0)
+    die("Cannot fork: %m");
+  if (pid > 0)
+    exit(0);
+  setsid();
+}
+
+void
+osd_wait(int delay)
+{
+  DBG("Waiting for %d seconds\n", delay);
+  timestamp_t wait_until = get_current_time() + delay*1000;
+
+  struct pollfd pfd = {
+    .fd = ConnectionNumber(dpy),
+    .events = POLLIN,
+  };
+
+  for (;;)
+    {
+      timestamp_t now = get_current_time();
+      if (now >= wait_until)
+       return;
+
+      DBG("... waiting for %d ms\n", (int)(wait_until - now));
+      poll(&pfd, 1, wait_until - now);
+      if (pfd.revents & POLLIN)
+       {
+         XEvent ev;
+         while (XPending(dpy))
+           XNextEvent(dpy, &ev);
+       }
+    }
+}