]> mj.ucw.cz Git - osdd.git/blob - client.c
New display code is able to show text messages
[osdd.git] / client.c
1 /*
2  *      On-screen Display -- Support Functions for Clients
3  *
4  *      (c) 2010 Martin Mares <mj@ucw.cz>
5  */
6
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <string.h>
10 #include <unistd.h>
11 #include <poll.h>
12 #include <X11/Xlib.h>
13 #include <X11/Xatom.h>
14
15 #undef DEBUG
16 #include "util.h"
17 #include "osd.h"
18
19 static Display *dpy;
20 static Atom pty;
21
22 #define MAX_MSG_SIZE 1024
23
24 struct osd_msg {
25   int cnt;
26   char buf[MAX_MSG_SIZE];
27 };
28
29 void
30 osd_init(void)
31 {
32   if (dpy)
33     return;
34
35   dpy = XOpenDisplay(NULL);
36   if (!dpy)
37     die("Cannot open display");
38
39   pty = XInternAtom(dpy, "OSD_QUEUE", False);
40   if (!pty)
41     die("Cannot intern OSD_QUEUE atom");
42 }
43
44 struct osd_msg *
45 osd_new_msg(void)
46 {
47   struct osd_msg *msg = xmalloc(sizeof(*msg));
48   msg->cnt = 0;
49   return msg;
50 }
51
52 void
53 osd_add_line(struct osd_msg *msg, char *key, char *val)
54 {
55   if (!key)
56     key = "";
57   msg->cnt += snprintf(msg->buf + msg->cnt, MAX_MSG_SIZE - msg->cnt - 1, "%s:%s\n", key, val);
58   if (msg->cnt > MAX_MSG_SIZE - 1)
59     die("OSD message too long (at most %d bytes)", MAX_MSG_SIZE);
60 }
61
62 void
63 osd_send(struct osd_msg *msg)
64 {
65   osd_init();
66   msg->buf[msg->cnt++] = '\n';
67   if (!XChangeProperty(dpy, DefaultRootWindow(dpy), pty, XA_STRING, 8, PropModeAppend, (unsigned char *) msg->buf, msg->cnt))
68     die("XChangeProperty failed");
69   XFlush(dpy);
70   free(msg);
71 }
72
73 void
74 osd_fork(void)
75 {
76   osd_init();
77   pid_t pid = fork();
78   if (pid < 0)
79     die("Cannot fork: %m");
80   if (pid > 0)
81     exit(0);
82   setsid();
83 }
84
85 void
86 osd_wait(int delay)
87 {
88   DBG("Waiting for %d seconds\n", delay);
89   timestamp_t wait_until = get_current_time() + delay*1000;
90
91   struct pollfd pfd = {
92     .fd = ConnectionNumber(dpy),
93     .events = POLLIN,
94   };
95
96   for (;;)
97     {
98       timestamp_t now = get_current_time();
99       if (now >= wait_until)
100         return;
101
102       DBG("... waiting for %d ms\n", (int)(wait_until - now));
103       poll(&pfd, 1, wait_until - now);
104       if (pfd.revents & POLLIN)
105         {
106           // We use the event loop only to detect that the X server has been shut down.
107           // In such cases, xlib raises an error and exits.
108           XEvent ev;
109           while (XPending(dpy))
110             XNextEvent(dpy, &ev);
111         }
112     }
113 }