~ubuntu-branches/ubuntu/trusty/multimon/trusty-proposed

« back to all changes in this revision

Viewing changes to xdisplay.c

  • Committer: Bazaar Package Importer
  • Author(s): A. Maitland Bottoms
  • Date: 2000-06-27 22:28:14 UTC
  • Revision ID: james.westby@ubuntu.com-20000627222814-r12knsgtb3acg3r0
Tags: 1.0-2
* test for Intel architecture before using (e.g. -m486) flags, 
  (closes:Bug#66281)
* Initial Emergency Alert System (EAS) decoder hacking

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *      xdisplay.c -- actually displaying things
 
3
 *
 
4
 *      Copyright (C) 1996  
 
5
 *          Thomas Sailer (sailer@ife.ee.ethz.ch, hb9jnx@hb9w.che.eu)
 
6
 *
 
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.
 
11
 *
 
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.
 
16
 *
 
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.
 
20
 */
 
21
 
 
22
/* ---------------------------------------------------------------------- */
 
23
 
 
24
#include "multimon.h"
 
25
#include <sys/types.h>
 
26
#include <sys/wait.h>
 
27
#include <sys/time.h>
 
28
#include <sys/resource.h>
 
29
#include <signal.h>
 
30
#include <math.h>
 
31
#include <string.h>
 
32
#include <stdio.h>
 
33
#include <unistd.h>
 
34
#include <fcntl.h>
 
35
#include <errno.h>
 
36
#include <X11/X.h>
 
37
#include <X11/Xlib.h>
 
38
#include <X11/Xutil.h>
 
39
 
 
40
/* ---------------------------------------------------------------------- */
 
41
 
 
42
#define WIDTH 512
 
43
#define HEIGHT 256
 
44
 
 
45
union comdata {
 
46
        short s[WIDTH];
 
47
        unsigned char b[0];
 
48
};
 
49
 
 
50
#define SAMPLING_RATE 22050
 
51
 
 
52
/* ---------------------------------------------------------------------- */
 
53
 
 
54
/*
 
55
 * child data structures
 
56
 */
 
57
 
 
58
static Display *display = NULL;
 
59
static Window window;
 
60
static GC gc;
 
61
static Pixmap pixmap;
 
62
static unsigned long col_zeroline;
 
63
static unsigned long col_background;
 
64
static unsigned long col_trace;
 
65
 
 
66
static int cmdpipe[2];
 
67
static int datapipe[2];
 
68
 
 
69
/*
 
70
 * parent data
 
71
 */
 
72
 
 
73
struct xdisp {
 
74
        int used;
 
75
        pid_t pid;
 
76
        int cmdfd;
 
77
        int datafd;
 
78
};
 
79
 
 
80
#define NUMCLI 16
 
81
 
 
82
static struct xdisp cli[NUMCLI] = { { 0, }, };
 
83
 
 
84
/* ---------------------------------------------------------------------- */
 
85
 
 
86
static int x_error_handler(Display *disp, XErrorEvent *evt)
 
87
{
 
88
    char err_buf[256], mesg[256], number[256];
 
89
    char *mtype = "XlibMessage";
 
90
 
 
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,
 
98
                          sizeof(err_buf));
 
99
    (void)fprintf(stderr, " (%s)\n", err_buf);
 
100
 
 
101
    abort();
 
102
}
 
103
 
 
104
/* ---------------------------------------------------------------------- */
 
105
 
 
106
static Bool predicate(Display *display, XEvent *event, char *arg)
 
107
{
 
108
        return True;
 
109
}
 
110
 
 
111
/* ---------------------------------------------------------------------- */
 
112
 
 
113
static char *x_getkey(void)
 
114
{
 
115
        XWindowAttributes winattrs;
 
116
        XEvent evt;
 
117
        static char kbuf[32];
 
118
        int i;
 
119
 
 
120
        if (!display)
 
121
                return NULL;
 
122
        while (XCheckIfEvent(display, &evt, predicate, NULL)) { 
 
123
                switch (evt.type) {
 
124
                case KeyPress:
 
125
                        i = XLookupString((XKeyEvent *)&evt, kbuf, 
 
126
                                          sizeof(kbuf)-1, NULL, NULL);
 
127
                        if (i) {
 
128
                                kbuf[i] = 0;
 
129
                                return kbuf;
 
130
                        }
 
131
                        continue;
 
132
                case DestroyNotify:
 
133
                        XCloseDisplay(display);
 
134
                        exit(0);
 
135
                case Expose:
 
136
                        XGetWindowAttributes(display, window, &winattrs);
 
137
                        XCopyArea(display, window, pixmap, gc, 0, 0, 
 
138
                                  winattrs.width, winattrs.height, 0, 0);
 
139
                        continue;
 
140
                default:
 
141
                        continue;
 
142
                }
 
143
        }
 
144
        return NULL;
 
145
}
 
146
 
 
147
/* ---------------------------------------------------------------------- */
 
148
 
 
149
static void process_keystrokes(void)
 
150
{
 
151
        char *cp;
 
152
 
 
153
        while ((cp = x_getkey())) {
 
154
                printf("X: Keys pressed: %s\n", cp);
 
155
        }
 
156
}
 
157
 
 
158
/* ---------------------------------------------------------------------- */
 
159
 
 
160
static int do_x_select(int fd, int wr)
 
161
{
 
162
        int *xconn, xconnnum;
 
163
        int max = fd, i;
 
164
        fd_set rmask, wmask;
 
165
        
 
166
        if (!XInternalConnectionNumbers(display, &xconn, &xconnnum)) {
 
167
                perror("XInternalConnectionNumbers");
 
168
                exit(1);
 
169
        }
 
170
        FD_ZERO(&rmask);
 
171
        FD_ZERO(&wmask);
 
172
        if (wr)
 
173
                FD_SET(fd, &wmask);
 
174
        else
 
175
                FD_SET(fd, &rmask);
 
176
        for (i = 0; i < xconnnum; i++) {
 
177
                FD_SET(xconn[i], &rmask);
 
178
                if (xconn[i] > max)
 
179
                        max = xconn[i];
 
180
        }
 
181
        i = select(max+1, &rmask, &wmask, NULL, NULL);
 
182
        if (i < 0) {
 
183
                perror("select");
 
184
                exit(1);
 
185
        }
 
186
        for (i = 0; i < xconnnum; i++) 
 
187
                if (FD_ISSET(xconn[i], &rmask))
 
188
                        XProcessInternalConnection(display, xconn[i]);
 
189
        XFree(xconn);
 
190
        process_keystrokes();
 
191
        if (wr)
 
192
                return FD_ISSET(fd, &wmask);
 
193
        else
 
194
                return FD_ISSET(fd, &rmask);
 
195
}
 
196
 
 
197
/* ---------------------------------------------------------------------- */
 
198
 
 
199
static void child_win_init(void)
 
200
{
 
201
        XSetWindowAttributes attr;
 
202
        XGCValues gcv;
 
203
        XColor color, dummy;
 
204
        XSizeHints sizehints;
 
205
        
 
206
        /*
 
207
         * start graphical output
 
208
         */
 
209
        if (!(display = XOpenDisplay(NULL))) {
 
210
                fprintf(stderr, "X: Unable to open X display\n");
 
211
                exit(1);
 
212
        }
 
213
        XSetErrorHandler(x_error_handler);
 
214
        XAllocNamedColor(display, DefaultColormap(display, 0), "red",
 
215
                         &color, &dummy);
 
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),
 
224
                               CWBackPixel, &attr);
 
225
        if (!(pixmap = XCreatePixmap(display, window, WIDTH, HEIGHT,
 
226
                                     DefaultDepth(display, 0)))) {
 
227
                fprintf(stderr, "X: unable to open offscreen pixmap\n");
 
228
                exit(1);
 
229
        }
 
230
        XSelectInput(display, window, KeyPressMask | StructureNotifyMask
 
231
                     | ExposureMask) ;
 
232
        gcv.line_width = 1;
 
233
        gcv.line_style = LineSolid;
 
234
        gc = XCreateGC(display, pixmap, GCForeground | GCLineWidth, &gcv);
 
235
        /*
 
236
         * Do not allow the window to be resized
 
237
         */
 
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);
 
245
}       
 
246
 
 
247
/* ---------------------------------------------------------------------- */
 
248
 
 
249
#define YCOORD(x) (((x)>>8)+(HEIGHT/2))
 
250
 
 
251
static void child_process(void)
 
252
{
 
253
        union comdata d;
 
254
        unsigned char *bp;
 
255
        int i, j;
 
256
 
 
257
        /*
 
258
         * main loop
 
259
         */
 
260
        for (;;) {
 
261
                /*
 
262
                 * send synchronisation mark
 
263
                 */
 
264
                while (!do_x_select(cmdpipe[1], 1));
 
265
                i = write(cmdpipe[1], "r", 1);
 
266
                if (i < 1) {
 
267
                        perror("write");
 
268
                        exit(1);
 
269
                }
 
270
                /*
 
271
                 * read data
 
272
                 */
 
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);
 
276
                        if (i < 1) {
 
277
                                perror("read");
 
278
                                exit(1);
 
279
                        }
 
280
                        j -= i;
 
281
                        bp += i;
 
282
                }
 
283
                /*
 
284
                 * clear pixmap
 
285
                 */
 
286
                XSetState(display, gc, col_background, col_background,
 
287
                          GXcopy, AllPlanes);
 
288
                XFillRectangle(display, pixmap, gc, 0, 0, 
 
289
                               WIDTH, HEIGHT);
 
290
                /*
 
291
                 * draw zero line
 
292
                 */
 
293
                XSetForeground(display, gc, col_zeroline);
 
294
                XDrawLine(display, pixmap, gc, 0, YCOORD(0), WIDTH,
 
295
                          YCOORD(0));
 
296
                /*
 
297
                 * draw input
 
298
                 */
 
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]),
 
302
                          i, YCOORD(d.s[i]));
 
303
                XCopyArea(display, pixmap, window, gc, 0, 0, 
 
304
                          WIDTH, HEIGHT, 0, 0);
 
305
                /* XSync(display, 0); */
 
306
        }
 
307
        XDestroyWindow(display, window);
 
308
        XCloseDisplay(display);
 
309
}
 
310
 
 
311
/* ---------------------------------------------------------------------- */
 
312
 
 
313
static void sigchld_handler(int sig)
 
314
{
 
315
        pid_t pid;
 
316
        int st;
 
317
        unsigned int cnum;
 
318
 
 
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) {
 
322
                                cli[cnum].used = 0;
 
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);
 
328
                        }
 
329
        }
 
330
}
 
331
 
 
332
/* ---------------------------------------------------------------------- */
 
333
 
 
334
void xdisp_terminate(int cnum)
 
335
{
 
336
        if (cnum  < 0 || cnum >= NUMCLI)
 
337
                return;
 
338
        kill(cli[cnum].pid, SIGTERM);
 
339
}
 
340
 
 
341
/* ---------------------------------------------------------------------- */
 
342
 
 
343
int xdisp_start(void)
 
344
{
 
345
        unsigned int cnum;
 
346
 
 
347
        /*
 
348
         * find free client struct
 
349
         */
 
350
        for (cnum = 0; (cnum < NUMCLI) && cli[cnum].used; cnum++);
 
351
        if (cnum >= NUMCLI)
 
352
                return -1;
 
353
        signal(SIGCHLD, sigchld_handler);
 
354
        /*
 
355
         * start "IPC" mechanism (using the pipes)
 
356
         */
 
357
        if (pipe(cmdpipe))
 
358
                return -1;
 
359
        if (pipe(datapipe)) {
 
360
                close(cmdpipe[0]);
 
361
                close(cmdpipe[1]);
 
362
        }
 
363
        if ((cli[cnum].pid = fork())) {
 
364
                if (cli[cnum].pid == (pid_t)-1) {
 
365
                        /* error */
 
366
                        close(cmdpipe[0]);
 
367
                        close(cmdpipe[1]);
 
368
                        close(datapipe[0]);
 
369
                        close(datapipe[1]);
 
370
                        return -1;
 
371
                }
 
372
                /* parent */
 
373
                cli[cnum].cmdfd = cmdpipe[0];
 
374
                close(cmdpipe[1]);
 
375
                close(datapipe[0]);
 
376
                cli[cnum].datafd = datapipe[1];
 
377
                cli[cnum].used = 1;
 
378
                fcntl(cmdpipe[0], F_SETFL, 
 
379
                      (fcntl(cmdpipe[0], F_GETFL, 0) | O_NDELAY));
 
380
                return cnum;
 
381
        }
 
382
        /*
 
383
         * child; the X process
 
384
         */
 
385
        close(cmdpipe[0]);
 
386
        close(datapipe[1]);
 
387
        close(0);  /* close stdin */
 
388
        child_win_init();
 
389
        child_process();
 
390
        exit(0);
 
391
}
 
392
 
 
393
/* ---------------------------------------------------------------------- */
 
394
 
 
395
int xdisp_update(int cnum, float *f)
 
396
{
 
397
        unsigned char *bp;
 
398
        short *sp;
 
399
        int i, j;
 
400
        char c;
 
401
        union comdata d;
 
402
 
 
403
        if (cnum < 0 || cnum >= NUMCLI)
 
404
                return 0;
 
405
        i = read(cli[cnum].cmdfd, &c, 1);
 
406
        if (i < 0 && errno != EAGAIN) {
 
407
                perror("read");
 
408
                xdisp_terminate(cnum);
 
409
                return 0;
 
410
        }
 
411
        if (i < 1)
 
412
                return 0;
 
413
        if (c != 'r')
 
414
                return 0;
 
415
        for (sp = d.s, i = 0; i < WIDTH; i++, sp++, f++) {
 
416
                if (*f >= 1)
 
417
                        *sp = 32767;
 
418
                else if (*f <= -1)
 
419
                        *sp = -32767;
 
420
                else 
 
421
                        *sp = 32767.0 * (*f);
 
422
        }
 
423
        bp = d.b;
 
424
        j = sizeof(d);
 
425
        while (j > 0) {
 
426
                i = write(cli[cnum].datafd, bp, j);
 
427
                if (i < 0 && errno != EAGAIN) {
 
428
                        perror("write");
 
429
                        xdisp_terminate(cnum);
 
430
                        return 0;
 
431
                }
 
432
                if (i > 0) {
 
433
                        bp += i;
 
434
                        j -= i;
 
435
                }
 
436
        }
 
437
        return 1;
 
438
}
 
439
 
 
440
/* ---------------------------------------------------------------------- */