1 #include "config.h"
2 #ifndef HAVE_LIBXV
3 #include "stdio.h"
4 #include "stdlib.h"
5 int main(void)
6 {puts("Compiled without Xvideo extention support, sorry.");exit(0);}
7 #else
8 /*
9 * put a TV image to the root window - requires Xvideo
10 */
11
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <unistd.h>
15 #include <signal.h>
16 #include <string.h>
17 #include <sys/types.h>
18 #include <sys/wait.h>
19
20 #include <X11/Xlib.h>
21 #include <X11/Xutil.h>
22 #include <X11/StringDefs.h>
23 #include <X11/Xatom.h>
24 #include <X11/extensions/Xv.h>
25 #include <X11/extensions/Xvlib.h>
26
27 #include "vroot.h"
28 #include "atoms.h"
29 #include "parseconfig.h"
30
31 #define SDIMOF(array) ((signed int)(sizeof(array)/sizeof(array[0])))
32
33 int port=-1,bye=0,termsig=0,verbose=0;
34 GC gc;
35
36 XvAdaptorInfo *ai;
37 XvEncodingInfo *ei;
38 XvAttribute *at;
39 XvImageFormatValues *fo;
40
41 static char *reasons[] = {
42 "XvStarted",
43 "XvStopped",
44 "XvBusy",
45 "XvPreempted",
46 "XvHardError",
47 };
48
49 static char *events[] = {
50 "", "1",
51 "KeyPress",
52 "KeyRelease",
53 "ButtonPress",
54 "ButtonRelease",
55 "MotionNotify",
56 "EnterNotify",
57 "LeaveNotify",
58 "FocusIn",
59 "FocusOut",
60 "KeymapNotify",
61 "Expose",
62 "GraphicsExpose",
63 "NoExpose",
64 "VisibilityNotify",
65 "CreateNotify",
66 "DestroyNotify",
67 "UnmapNotify",
68 "MapNotify",
69 "MapRequest",
70 "ReparentNotify",
71 "ConfigureNotify",
72 "ConfigureRequest",
73 "GravityNotify",
74 "ResizeRequest",
75 "CirculateNotify",
76 "CirculateRequest",
77 "PropertyNotify",
78 "SelectionClear",
79 "SelectionRequest",
80 "SelectionNotify",
81 "ColormapNotify",
82 "ClientMessage",
83 "MappingNotify"
84 };
85
86 static void station_list(FILE *fp)
87 {
88 char filename[100];
89 char **list;
90
91 sprintf(filename,"%.*s/%s",(int)sizeof(filename)-8,
92 getenv("HOME"),".xawtv");
93 cfg_parse_file(CONFIGFILE);
94 cfg_parse_file(filename);
95
96 for (list = cfg_list_sections(); *list != NULL; list++) {
97 if (0 == strcmp(*list,"defaults")) continue;
98 if (0 == strcmp(*list,"global")) continue;
99 if (0 == strcmp(*list,"launch")) continue;
100 if (0 == strcmp(*list,"eventmap")) continue;
101 fprintf(fp,"\t\"%s\" EXEC v4lctl setstation \"%s\"\n",
102 *list,*list);
103 }
104 }
105
106 static void wm_menu(FILE *fp)
107 {
108 fprintf(fp,"\"TV stations\" MENU\n");
109 station_list(fp);
110 fprintf(fp,"\"TV stations\" END\n");
111 }
112
113 static void video_blit(Display *dpy, Window win)
114 {
115 XWindowAttributes wts;
116
117 XGetWindowAttributes(dpy, win, &wts);
118 #if 0
119 XClearArea(dpy,win,0,0,0,0,False);
120 XvStopVideo(dpy,port,win);
121 #endif
122 XvPutVideo(dpy,port,win,gc,
123 0,0,wts.width,wts.height,
124 0,0,wts.width,wts.height);
125 if (verbose)
126 fprintf(stderr,"XvPutVideo(win=0x%lx,w=%d,h=%d)\n",
127 win,wts.width,wts.height);
128 }
129
130 static void
131 catch_sig(int signal)
132 {
133 termsig = signal;
134 if (verbose)
135 fprintf(stderr,"received signal %d [%s]\n",
136 termsig,sys_siglist[termsig]);
137 }
138
139 static void usage(FILE *fp)
140 {
141 fprintf(fp,
142 "rootv is a simple TV application. Uses and requires Xvideo.\n"
143 "Most settings must be tweaked done using some other tool,\n"
144 "v4lctl for example.\n"
145 "\n"
146 "options:\n"
147 " -help print this text\n"
148 " -verbose be verbose\n"
149 " -root put video onto the root window instead of\n"
150 " creating a new window.\n"
151 " -id <win> put video into the window <win> instead of\n"
152 " creating a new window.\n"
153 " -station <st> tune station <st> (just calls v4lctl)\n"
154 " -no-mute don't toggle mute on start/exit.\n"
155 " -port <n> use Xvideo port <n>.\n"
156 " -bg fork into background.\n"
157 " -wm print WindowMaker menu, to set all stations\n"
158 " listed in ~/.xawtv using v4lctl.\n"
159 "\n");
160 }
161
162 int
163 main(int argc, char *argv[])
164 {
165 struct sigaction act,old;
166 Display *dpy;
167 Screen *scr;
168 Window win = -1;
169 XWindowAttributes wts;
170 KeySym keysym;
171 char c;
172
173 int ver, rel, req, ev, err, dummy;
174 int adaptors,attributes;
175 int i,stop,bg,newwin,do_mute,have_mute,grab;
176
177 dpy = XOpenDisplay(NULL);
178 scr = DefaultScreenOfDisplay(dpy);
179 init_atoms(dpy);
180
181 stop = 0;
182 bg = 0;
183 do_mute = 1;
184 have_mute = 0;
185 newwin = 1;
186
187 while (argc > 1) {
188 if (0 == strcmp(argv[1],"-wm")) {
189 /* windowmaker menu */
190 wm_menu(stdout);
191 exit(0);
192 }
193 if (0 == strcmp(argv[1],"-h") ||
194 0 == strcmp(argv[1],"-help") ||
195 0 == strcmp(argv[1],"--help")) {
196 usage(stdout);
197 exit(0);
198 }
199 if (argc > 2 && (0 == strcmp(argv[1],"-id") ||
200 0 == strcmp(argv[1],"-window-id"))) {
201 sscanf(argv[2],"%li",&win);
202 newwin = 0;
203 if (verbose)
204 fprintf(stderr,"using window id 0x%lx\n",win);
205 argc-=2;
206 argv+=2;
207 } else if (argc > 2 && 0 == strcmp(argv[1],"-port")) {
208 sscanf(argv[2],"%i",&port);
209 argc-=2;
210 argv+=2;
211 } else if (argc > 2 && 0 == strcmp(argv[1],"-station")) {
212 if (0 == fork()) {
213 execlp("v4lctl","v4lctl","setstation",argv[2],NULL);
214 exit(1);
215 } else {
216 wait(&dummy);
217 }
218 argc-=2;
219 argv+=2;
220 } else if (0 == strcmp(argv[1],"-root")) {
221 win = RootWindowOfScreen(scr);
222 newwin = 0;
223 if (verbose)
224 fprintf(stderr,"using root window [0x%lx]\n",win);
225 argc--;
226 argv++;
227 } else if (0 == strcmp(argv[1],"-bg")) {
228 bg = 1;
229 argc--;
230 argv++;
231 } else if (0 == strcmp(argv[1],"-verbose")) {
232 verbose = 1;
233 argc--;
234 argv++;
235 } else if (0 == strcmp(argv[1],"-no-mute")) {
236 do_mute = 0;
237 argc--;
238 argv++;
239 } else {
240 fprintf(stderr,"unknown arg: \"%s\"\n",argv[1]);
241 exit(1);
242 }
243 }
244
245 /* init X11 */
246 if (newwin) {
247 win = XCreateSimpleWindow(dpy,RootWindowOfScreen(scr),
248 0,0,640,480,1,
249 BlackPixelOfScreen(scr),
250 BlackPixelOfScreen(scr));
251 XChangeProperty(dpy, win, WM_PROTOCOLS, XA_ATOM, 32,
252 PropModeReplace,
253 (unsigned char *) &WM_DELETE_WINDOW, 1);
254 }
255 XGetWindowAttributes (dpy, win, &wts);
256 XSelectInput(dpy, win, wts.your_event_mask |
257 KeyPressMask | StructureNotifyMask | ExposureMask);
258
259 /* query+print Xvideo properties */
260 if (Success != XvQueryExtension(dpy,&ver,&rel,&req,&ev,&err)) {
261 puts("Server does'nt support Xvideo");
262 exit(1);
263 }
264 if (Success != XvQueryAdaptors(dpy,DefaultRootWindow(dpy),&adaptors,&ai)) {
265 puts("Oops: XvQueryAdaptors failed");
266 exit(1);
267 }
268 if (verbose)
269 fprintf(stderr,"%d adaptors available.\n",adaptors);
270 for (i = 0; i < adaptors; i++) {
271 if (verbose)
272 fprintf(stderr," port=%ld name=\"%s\"\n",ai[i].base_id,ai[i].name);
273
274 /* video adaptor ? */
275 if ((ai[i].type & XvInputMask) &&
276 (ai[i].type & XvVideoMask) &&
277 (port == -1)) {
278 port = ai[i].base_id;
279 }
280 }
281 if (adaptors > 0)
282 XvFreeAdaptorInfo(ai);
283 if (-1 == port) {
284 fprintf(stderr,"no Xvideo port found\n");
285 exit(1);
286 }
287
288 /* grab Xvideo port */
289 grab = 0;
290 for (i = 0; !grab && i < 3; i++) {
291 switch (XvGrabPort(dpy,port,CurrentTime)) {
292 case Success:
293 if (verbose)
294 fprintf(stderr,"grabbed Xv port\n");
295 grab=1;
296 break;
297 case XvAlreadyGrabbed:
298 if (verbose)
299 fprintf(stderr,"Xv port already grabbed\n");
300 sleep(1);
301 break;
302 default:
303 fprintf(stderr,"Xv port grab: Huh?\n");
304 exit(1);
305 }
306 }
307 if (!grab) {
308 fprintf(stderr,"can't grab Xv port\n");
309 exit(1);
310 }
311
312 at = XvQueryPortAttributes(dpy,port,&attributes);
313 for (i = 0; i < attributes; i++) {
314 if (0 == strcmp("XV_MUTE",at[i].name))
315 have_mute = 1;
316 }
317 gc = XCreateGC(dpy,win,0,NULL);
318
319 /* fork into background, but keep tty */
320 if (bg)
321 if (fork())
322 exit(0);
323
324 /* catch signals */
325 memset(&act,0,sizeof(act));
326 sigemptyset(&act.sa_mask);
327 act.sa_handler = catch_sig;
328 sigaction(SIGINT,&act,&old);
329 sigaction(SIGHUP,&act,&old);
330 sigaction(SIGTERM,&act,&old);
331
332 /* put video to the window */
333 if (newwin)
334 XMapWindow(dpy,win);
335 if (verbose)
336 fprintf(stderr,"starting video\n");
337 video_blit(dpy,win);
338 if (do_mute && have_mute)
339 XvSetPortAttribute(dpy,port,XV_MUTE,0);
340
341 /* receive events */
342 XvSelectPortNotify(dpy, port, 1);
343 XvSelectVideoNotify(dpy, win, 1);
344
345 /* main loop */
346 for (;!bye && !termsig;) {
347 int rc;
348 fd_set set;
349 XEvent event;
350
351 if (False == XCheckMaskEvent(dpy, ~0, &event)) {
352 /* wait for x11 events, make sure that signals are catched */
353 XFlush(dpy);
354 FD_ZERO(&set);
355 FD_SET(ConnectionNumber(dpy),&set);
356 rc = select(ConnectionNumber(dpy)+1,&set,NULL,NULL,NULL);
357 if (-1 == rc)
358 if (verbose)
359 perror("... select");
360 continue;
361 }
362
363 if (event.type > ev) {
364 /* Xvideo extention event */
365 switch (event.type-ev) {
366 case XvVideoNotify:
367 {
368 XvVideoNotifyEvent *xve = (XvVideoNotifyEvent*)&event;
369 if (verbose)
370 fprintf(stderr,"XvVideoNotify, reason=%s, exiting\n",
371 reasons[xve->reason]);
372 #if 0
373 bye=1;
374 #endif
375 break;
376 }
377 case XvPortNotify:
378 {
379 XvPortNotifyEvent *xpe = (XvPortNotifyEvent*)&event;
380 if (verbose)
381 fprintf(stderr,"XvPortNotify: %s=%ld\n",
382 XGetAtomName(dpy,xpe->attribute),xpe->value);
383 break;
384 }
385 }
386 } else {
387 /* other event */
388 switch (event.type) {
389 case KeyPress:
390 c = 0;
391 XLookupString (&event.xkey, &c, 1, &keysym, 0);
392 if (verbose)
393 fprintf(stderr,"key: %c\n",c);
394 switch (c) {
395 case 'q':
396 case 'Q':
397 case 3: /* ^C */
398 case 27: /* ESC */
399 bye = 1;
400 }
401 break;
402 case ClientMessage:
403 if (event.xclient.message_type == WM_PROTOCOLS &&
404 (Atom)event.xclient.data.l[0] == WM_DELETE_WINDOW)
405 bye = 1;
406 break;
407 case Expose:
408 if (event.xexpose.count)
409 break;
410 /* fall througth */
411 case ConfigureNotify:
412 video_blit(dpy,win);
413 break;
414 default:
415 if (verbose) {
416 if (event.type < SDIMOF(events))
417 fprintf(stderr,"ev: %s\n",events[event.type]);
418 else
419 fprintf(stderr,"ev: #%d\n",event.type);
420 }
421 }
422 }
423 }
424 if (verbose && termsig)
425 fprintf(stderr,"exiting on signal %d [%s]\n",
426 termsig,sys_siglist[termsig]);
427 if (do_mute && have_mute)
428 XvSetPortAttribute(dpy,port,XV_MUTE,1);
429 XvStopVideo(dpy,port,win);
430 XvUngrabPort(dpy,port,CurrentTime);
431 XClearArea(dpy,win,0,0,0,0,True);
432 XCloseDisplay(dpy);
433 if (verbose)
434 fprintf(stderr,"bye\n");
435
436 /* keep compiler happy */
437 exit(0);
438 }
439
440 #endif
441
|
This page was automatically generated by the
LXR engine.
|