2
* xdisplay.c -- actually displaying things
5
* Thomas Sailer (sailer@ife.ee.ethz.ch, hb9jnx@hb9w.che.eu)
7
* This program is free software; you can redistribute it and/or modify
8
* it under the terms of the GNU General Public License as published by
9
* the Free Software Foundation; either version 2 of the License, or
10
* (at your option) any later version.
12
* This program is distributed in the hope that it will be useful,
13
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
* GNU General Public License for more details.
17
* You should have received a copy of the GNU General Public License
18
* along with this program; if not, write to the Free Software
19
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22
/* ---------------------------------------------------------------------- */
25
#include <sys/types.h>
28
#include <sys/resource.h>
38
#include <X11/Xutil.h>
40
/* ---------------------------------------------------------------------- */
50
#define SAMPLING_RATE 22050
52
/* ---------------------------------------------------------------------- */
55
* child data structures
58
static Display *display = NULL;
62
static unsigned long col_zeroline;
63
static unsigned long col_background;
64
static unsigned long col_trace;
66
static int cmdpipe[2];
67
static int datapipe[2];
82
static struct xdisp cli[NUMCLI] = { { 0, }, };
84
/* ---------------------------------------------------------------------- */
86
static int x_error_handler(Display *disp, XErrorEvent *evt)
88
char err_buf[256], mesg[256], number[256];
89
char *mtype = "XlibMessage";
91
XGetErrorText(disp, evt->error_code, err_buf, sizeof(err_buf));
92
(void)fprintf(stderr, "X Error: %s\n", err_buf);
93
XGetErrorDatabaseText(disp, mtype, "MajorCode",
94
"Request Major code %d", mesg, sizeof(mesg));
95
(void)fprintf(stderr, mesg, evt->request_code);
96
(void)sprintf(number, "%d", evt->request_code);
97
XGetErrorDatabaseText(disp, "XRequest", number, "", err_buf,
99
(void)fprintf(stderr, " (%s)\n", err_buf);
104
/* ---------------------------------------------------------------------- */
106
static Bool predicate(Display *display, XEvent *event, char *arg)
111
/* ---------------------------------------------------------------------- */
113
static char *x_getkey(void)
115
XWindowAttributes winattrs;
117
static char kbuf[32];
122
while (XCheckIfEvent(display, &evt, predicate, NULL)) {
125
i = XLookupString((XKeyEvent *)&evt, kbuf,
126
sizeof(kbuf)-1, NULL, NULL);
133
XCloseDisplay(display);
136
XGetWindowAttributes(display, window, &winattrs);
137
XCopyArea(display, window, pixmap, gc, 0, 0,
138
winattrs.width, winattrs.height, 0, 0);
147
/* ---------------------------------------------------------------------- */
149
static void process_keystrokes(void)
153
while ((cp = x_getkey())) {
154
printf("X: Keys pressed: %s\n", cp);
158
/* ---------------------------------------------------------------------- */
160
static int do_x_select(int fd, int wr)
162
int *xconn, xconnnum;
166
if (!XInternalConnectionNumbers(display, &xconn, &xconnnum)) {
167
perror("XInternalConnectionNumbers");
176
for (i = 0; i < xconnnum; i++) {
177
FD_SET(xconn[i], &rmask);
181
i = select(max+1, &rmask, &wmask, NULL, NULL);
186
for (i = 0; i < xconnnum; i++)
187
if (FD_ISSET(xconn[i], &rmask))
188
XProcessInternalConnection(display, xconn[i]);
190
process_keystrokes();
192
return FD_ISSET(fd, &wmask);
194
return FD_ISSET(fd, &rmask);
197
/* ---------------------------------------------------------------------- */
199
static void child_win_init(void)
201
XSetWindowAttributes attr;
204
XSizeHints sizehints;
207
* start graphical output
209
if (!(display = XOpenDisplay(NULL))) {
210
fprintf(stderr, "X: Unable to open X display\n");
213
XSetErrorHandler(x_error_handler);
214
XAllocNamedColor(display, DefaultColormap(display, 0), "red",
216
col_zeroline = color.pixel;
217
col_background = WhitePixel(display, 0);
218
col_trace = BlackPixel(display, 0);
219
attr.background_pixel = col_background;
220
window = XCreateWindow(display, XRootWindow(display, 0),
221
200, 200, WIDTH, HEIGHT, 5,
222
DefaultDepth(display, 0),
223
InputOutput, DefaultVisual(display, 0),
225
if (!(pixmap = XCreatePixmap(display, window, WIDTH, HEIGHT,
226
DefaultDepth(display, 0)))) {
227
fprintf(stderr, "X: unable to open offscreen pixmap\n");
230
XSelectInput(display, window, KeyPressMask | StructureNotifyMask
233
gcv.line_style = LineSolid;
234
gc = XCreateGC(display, pixmap, GCForeground | GCLineWidth, &gcv);
236
* Do not allow the window to be resized
238
memset(&sizehints, 0, sizeof(sizehints));
239
sizehints.min_width = sizehints.max_width = WIDTH;
240
sizehints.min_height = sizehints.max_height = HEIGHT;
241
sizehints.flags = PMinSize | PMaxSize;
242
XSetWMNormalHints(display, window, &sizehints);
243
XMapWindow(display, window);
244
XSynchronize(display, 1);
247
/* ---------------------------------------------------------------------- */
249
#define YCOORD(x) (((x)>>8)+(HEIGHT/2))
251
static void child_process(void)
262
* send synchronisation mark
264
while (!do_x_select(cmdpipe[1], 1));
265
i = write(cmdpipe[1], "r", 1);
273
for (j = sizeof(d), bp = d.b; j > 0; ) {
274
while (!do_x_select(datapipe[0], 0));
275
i = read(datapipe[0], bp, j);
286
XSetState(display, gc, col_background, col_background,
288
XFillRectangle(display, pixmap, gc, 0, 0,
293
XSetForeground(display, gc, col_zeroline);
294
XDrawLine(display, pixmap, gc, 0, YCOORD(0), WIDTH,
299
XSetForeground(display, gc, col_trace);
300
for (i = 1; i < WIDTH; i++)
301
XDrawLine(display, pixmap, gc, i-1, YCOORD(d.s[i-1]),
303
XCopyArea(display, pixmap, window, gc, 0, 0,
304
WIDTH, HEIGHT, 0, 0);
305
/* XSync(display, 0); */
307
XDestroyWindow(display, window);
308
XCloseDisplay(display);
311
/* ---------------------------------------------------------------------- */
313
static void sigchld_handler(int sig)
319
while ((pid = wait4(0, &st, WNOHANG, NULL)) != (pid_t)-1) {
320
for (cnum = 0; cnum < NUMCLI; cnum++)
321
if (cli[cnum].used && cli[cnum].pid == pid) {
323
close(cli[cnum].cmdfd);
324
close(cli[cnum].datafd);
325
cli[cnum].pid = (pid_t)-1;
326
fprintf(stderr, "child process %i died, "
327
"status %i\n", (int)pid, st);
332
/* ---------------------------------------------------------------------- */
334
void xdisp_terminate(int cnum)
336
if (cnum < 0 || cnum >= NUMCLI)
338
kill(cli[cnum].pid, SIGTERM);
341
/* ---------------------------------------------------------------------- */
343
int xdisp_start(void)
348
* find free client struct
350
for (cnum = 0; (cnum < NUMCLI) && cli[cnum].used; cnum++);
353
signal(SIGCHLD, sigchld_handler);
355
* start "IPC" mechanism (using the pipes)
359
if (pipe(datapipe)) {
363
if ((cli[cnum].pid = fork())) {
364
if (cli[cnum].pid == (pid_t)-1) {
373
cli[cnum].cmdfd = cmdpipe[0];
376
cli[cnum].datafd = datapipe[1];
378
fcntl(cmdpipe[0], F_SETFL,
379
(fcntl(cmdpipe[0], F_GETFL, 0) | O_NDELAY));
383
* child; the X process
387
close(0); /* close stdin */
393
/* ---------------------------------------------------------------------- */
395
int xdisp_update(int cnum, float *f)
403
if (cnum < 0 || cnum >= NUMCLI)
405
i = read(cli[cnum].cmdfd, &c, 1);
406
if (i < 0 && errno != EAGAIN) {
408
xdisp_terminate(cnum);
415
for (sp = d.s, i = 0; i < WIDTH; i++, sp++, f++) {
421
*sp = 32767.0 * (*f);
426
i = write(cli[cnum].datafd, bp, j);
427
if (i < 0 && errno != EAGAIN) {
429
xdisp_terminate(cnum);
440
/* ---------------------------------------------------------------------- */