Mercurial > ~darius > hgwebdir.cgi > simpletv
comparison simpletv.c @ 8:fc60aa65d85f
Reindent with c-basic-offset = 4
author | darius |
---|---|
date | Sun, 21 Aug 2005 12:35:31 +0000 |
parents | 210d197c77f9 |
children | ef818ccd826f |
comparison
equal
deleted
inserted
replaced
7:210d197c77f9 | 8:fc60aa65d85f |
---|---|
116 str, (long)arg, strerror(errno) ) | 116 str, (long)arg, strerror(errno) ) |
117 /*--------------------------------------------------------------------------*/ | 117 /*--------------------------------------------------------------------------*/ |
118 | 118 |
119 void | 119 void |
120 Close() { | 120 Close() { |
121 close(tuner_fd); | 121 close(tuner_fd); |
122 close(bktr_fd); | 122 close(bktr_fd); |
123 } | 123 } |
124 | 124 |
125 void | 125 void |
126 Open() { | 126 Open() { |
127 struct meteor_geomet geo; | 127 struct meteor_geomet geo; |
128 int buffer_size, format, source, c; | 128 int buffer_size, format, source, c; |
129 char *device_name; | 129 char *device_name; |
130 | 130 |
131 format = PAL; /* default value */ | 131 format = PAL; /* default value */ |
132 source = 1; /* default value */ | 132 source = 1; /* default value */ |
133 device_name = "/dev/bktr0"; /* default value */ | 133 device_name = "/dev/bktr0"; /* default value */ |
134 | 134 |
135 /* Open the Meteor or Bt848/Bt878 grabber */ | 135 /* Open the Meteor or Bt848/Bt878 grabber */ |
136 if ((bktr_fd = open(device_name, O_RDONLY)) < 0) { | 136 if ((bktr_fd = open(device_name, O_RDONLY)) < 0) { |
137 printf("open failed: %d\n", errno); | 137 printf("open failed: %d\n", errno); |
138 exit(1); | 138 exit(1); |
139 } | 139 } |
140 if ((tuner_fd = open("/dev/tuner0", O_RDONLY)) < 0) { | 140 if ((tuner_fd = open("/dev/tuner0", O_RDONLY)) < 0) { |
141 printf("open failed: %d\n", errno); | 141 printf("open failed: %d\n", errno); |
142 exit(1); | 142 exit(1); |
143 } | 143 } |
144 /* set up the capture type and size */ | 144 /* set up the capture type and size */ |
145 geo.rows = height; | 145 geo.rows = height; |
146 geo.columns = width; | 146 geo.columns = width; |
147 geo.frames = 1; | 147 geo.frames = 1; |
148 #ifdef USE_XVIMAGES | 148 #ifdef USE_XVIMAGES |
149 /* Should be YUV_12, but 422 actually gives a synced picture. Though */ | 149 /* Should be YUV_12, but 422 actually gives a synced picture. Though */ |
150 geo.oformat = METEOR_GEO_YUV_422 | METEOR_GEO_YUV_12; | 150 geo.oformat = METEOR_GEO_YUV_422 | METEOR_GEO_YUV_12; |
151 | 151 |
152 #else | 152 #else |
153 geo.oformat = METEOR_GEO_RGB24; | 153 geo.oformat = METEOR_GEO_RGB24; |
154 #endif | 154 #endif |
155 | 155 |
156 /* switch from interlaced capture to single field capture if */ | 156 /* switch from interlaced capture to single field capture if */ |
157 /* the grab height is less than half the normal TV height */ | 157 /* the grab height is less than half the normal TV height */ |
158 /* this gives better quality captures when the object in the TV */ | 158 /* this gives better quality captures when the object in the TV */ |
159 /* picture is moving */ | 159 /* picture is moving */ |
160 if ((format == PAL) && (height <= (PAL_HEIGHT / 2))) | 160 if ((format == PAL) && (height <= (PAL_HEIGHT / 2))) |
161 geo.oformat |= METEOR_GEO_ODD_ONLY; | 161 geo.oformat |= METEOR_GEO_ODD_ONLY; |
162 if ((format == NTSC) && (height <= (NTSC_HEIGHT / 2))) | 162 if ((format == NTSC) && (height <= (NTSC_HEIGHT / 2))) |
163 geo.oformat |= METEOR_GEO_ODD_ONLY; | 163 geo.oformat |= METEOR_GEO_ODD_ONLY; |
164 | 164 |
165 if (ioctl(bktr_fd, METEORSETGEO, &geo) < 0) { | 165 if (ioctl(bktr_fd, METEORSETGEO, &geo) < 0) { |
166 printf("METEORSETGEO ioctl failed: %d\n", errno); | 166 printf("METEORSETGEO ioctl failed: %d\n", errno); |
167 exit(1); | 167 exit(1); |
168 } | 168 } |
169 /* Select PAL or NTSC */ | 169 /* Select PAL or NTSC */ |
170 switch (format) { | 170 switch (format) { |
171 case PAL: | 171 case PAL: |
172 c = METEOR_FMT_PAL; | 172 c = METEOR_FMT_PAL; |
173 break; | 173 break; |
174 case NTSC: | 174 case NTSC: |
175 c = METEOR_FMT_NTSC; | 175 c = METEOR_FMT_NTSC; |
176 break; | 176 break; |
177 default: | 177 default: |
178 c = METEOR_FMT_NTSC; | 178 c = METEOR_FMT_NTSC; |
179 break; | 179 break; |
180 } | 180 } |
181 | 181 |
182 c = BT848_IFORM_F_PALBDGHI; | 182 c = BT848_IFORM_F_PALBDGHI; |
183 if (ioctl(bktr_fd, BT848SFMT, &c) < 0) { | 183 if (ioctl(bktr_fd, BT848SFMT, &c) < 0) { |
184 DO_IOCTL_SERR("BT848SFMT", c); | 184 DO_IOCTL_SERR("BT848SFMT", c); |
185 return; | 185 return; |
186 } | 186 } |
187 c = AUDIO_TUNER; | 187 c = AUDIO_TUNER; |
188 if (ioctl(tuner_fd, BT848_SAUDIO, &c) < 0) { | 188 if (ioctl(tuner_fd, BT848_SAUDIO, &c) < 0) { |
189 DO_IOCTL_SERR("BT848SFMT", c); | 189 DO_IOCTL_SERR("BT848SFMT", c); |
190 return; | 190 return; |
191 } | 191 } |
192 c = CHNLSET_AUSTRALIA; | 192 c = CHNLSET_AUSTRALIA; |
193 if (ioctl(tuner_fd, TVTUNER_SETTYPE, &c) < 0) { | 193 if (ioctl(tuner_fd, TVTUNER_SETTYPE, &c) < 0) { |
194 DO_IOCTL_SERR("TVTUNER_SETTYPE", c); | 194 DO_IOCTL_SERR("TVTUNER_SETTYPE", c); |
195 return; | 195 return; |
196 } | 196 } |
197 if (ioctl(tuner_fd, TVTUNER_SETCHNL, &channel) < 0) { | 197 if (ioctl(tuner_fd, TVTUNER_SETCHNL, &channel) < 0) { |
198 DO_IOCTL_SERR("TVTUNER_SETCHNL", channel); | 198 DO_IOCTL_SERR("TVTUNER_SETCHNL", channel); |
199 return; | 199 return; |
200 } | 200 } |
201 /* Select the Video Source */ | 201 /* Select the Video Source */ |
202 /* Video In, Tuner, S-Video */ | 202 /* Video In, Tuner, S-Video */ |
203 switch (source) { | 203 switch (source) { |
204 case 0: | 204 case 0: |
205 c = METEOR_INPUT_DEV0; | 205 c = METEOR_INPUT_DEV0; |
206 break; | 206 break; |
207 case 1: | 207 case 1: |
208 c = METEOR_INPUT_DEV1; | 208 c = METEOR_INPUT_DEV1; |
209 break; | 209 break; |
210 case 2: | 210 case 2: |
211 c = METEOR_INPUT_DEV2; | 211 c = METEOR_INPUT_DEV2; |
212 break; | 212 break; |
213 case 3: | 213 case 3: |
214 c = METEOR_INPUT_DEV3; | 214 c = METEOR_INPUT_DEV3; |
215 break; | 215 break; |
216 default: | 216 default: |
217 c = METEOR_INPUT_DEV0; | 217 c = METEOR_INPUT_DEV0; |
218 break; | 218 break; |
219 } | 219 } |
220 | 220 |
221 printf("Input - %x\n", c); | 221 printf("Input - %x\n", c); |
222 if (ioctl(bktr_fd, METEORSINPUT, &c) < 0) { | 222 if (ioctl(bktr_fd, METEORSINPUT, &c) < 0) { |
223 printf("ioctl failed: %d\n", errno); | 223 printf("ioctl failed: %d\n", errno); |
224 exit(1); | 224 exit(1); |
225 } | 225 } |
226 /* Use mmap to Map the drivers grab buffer */ | 226 /* Use mmap to Map the drivers grab buffer */ |
227 buffer_size = width * height * 4; /* R,G,B,spare */ | 227 buffer_size = width * height * 4; /* R,G,B,spare */ |
228 bktr_buffer = (unsigned char *)mmap((caddr_t) 0, buffer_size, PROT_READ, | 228 bktr_buffer = (unsigned char *)mmap((caddr_t) 0, buffer_size, PROT_READ, |
229 MAP_SHARED, bktr_fd, (off_t) 0); | 229 MAP_SHARED, bktr_fd, (off_t) 0); |
230 | 230 |
231 if (bktr_buffer == (unsigned char *)MAP_FAILED) | 231 if (bktr_buffer == (unsigned char *)MAP_FAILED) |
232 exit(1); | 232 exit(1); |
233 | 233 |
234 | 234 |
235 /* We may need to wait for a short time to allow the grabber */ | 235 /* We may need to wait for a short time to allow the grabber */ |
236 /* brightness to settle down */ | 236 /* brightness to settle down */ |
237 sleep(GRABBER_SETTLE_TIME); | 237 sleep(GRABBER_SETTLE_TIME); |
238 } | 238 } |
239 | 239 |
240 /*--------------------------------------------------------------------------*/ | 240 /*--------------------------------------------------------------------------*/ |
241 | 241 |
242 void | 242 void |
243 Capture() { | 243 Capture() { |
244 int c; | 244 int c; |
245 | 245 |
246 /* Perform a single frame capture */ | 246 /* Perform a single frame capture */ |
247 c = METEOR_CAP_SINGLE; | 247 c = METEOR_CAP_SINGLE; |
248 ioctl(bktr_fd, METEORCAPTUR, &c); | 248 ioctl(bktr_fd, METEORCAPTUR, &c); |
249 } | 249 } |
250 | 250 |
251 /*--------------------------------------------------------------------------*/ | 251 /*--------------------------------------------------------------------------*/ |
252 | 252 |
253 void | 253 void |
254 SaveImage() { | 254 SaveImage() { |
255 unsigned char *line_buffer; | 255 unsigned char *line_buffer; |
256 int o , w, h; | 256 int o , w, h; |
257 unsigned char *p; | 257 unsigned char *p; |
258 unsigned char header[30]; | 258 unsigned char header[30]; |
259 char *filename = "t.ppm" /* argv[3] */ ; | 259 char *filename = "t.ppm" /* argv[3] */ ; |
260 | 260 |
261 /* Create the output file */ | 261 /* Create the output file */ |
262 if ((o = open(filename, O_WRONLY | O_CREAT, 0644)) < 0) { | 262 if ((o = open(filename, O_WRONLY | O_CREAT, 0644)) < 0) { |
263 printf("ppm open failed: %d\n", errno); | 263 printf("ppm open failed: %d\n", errno); |
264 exit(1); | 264 exit(1); |
265 } | 265 } |
266 /* make PPM header and save to file */ | 266 /* make PPM header and save to file */ |
267 sprintf(header, "P6\n%d\n%d\n255\n", width, height); | 267 sprintf(header, "P6\n%d\n%d\n255\n", width, height); |
268 write(o, header, strlen(header)); | 268 write(o, header, strlen(header)); |
269 | 269 |
270 /* save the RGB data to PPM file */ | 270 /* save the RGB data to PPM file */ |
271 /* save this one line at a time */ | 271 /* save this one line at a time */ |
272 line_buffer = (unsigned char *)malloc(width * 3 * sizeof(unsigned char)); | 272 line_buffer = (unsigned char *)malloc(width * 3 * sizeof(unsigned char)); |
273 p = bktr_buffer; | 273 p = bktr_buffer; |
274 for (h = 0; h < height; h++) { | 274 for (h = 0; h < height; h++) { |
275 for (w = 0; w < width; w++) { | 275 for (w = 0; w < width; w++) { |
276 line_buffer[(w * 3) + 2] = *p++; /* blue */ | 276 line_buffer[(w * 3) + 2] = *p++; /* blue */ |
277 line_buffer[(w * 3) + 1] = *p++; /* green */ | 277 line_buffer[(w * 3) + 1] = *p++; /* green */ |
278 line_buffer[(w * 3) + 0] = *p++; /* red */ | 278 line_buffer[(w * 3) + 0] = *p++; /* red */ |
279 p++; /* NULL byte */ | 279 p++; /* NULL byte */ |
280 } | 280 } |
281 write(o, line_buffer, width * 3); | 281 write(o, line_buffer, width * 3); |
282 } | 282 } |
283 close(o); | 283 close(o); |
284 free(line_buffer); | 284 free(line_buffer); |
285 } | 285 } |
286 | 286 |
287 void | 287 void |
288 X_ShowCursor(void) { | 288 X_ShowCursor(void) { |
289 XDefineCursor(disp, win, 0); | 289 XDefineCursor(disp, win, 0); |
290 } | 290 } |
291 | 291 |
292 void | 292 void |
293 X_HideCursor(void) { | 293 X_HideCursor(void) { |
294 Cursor no_ptr; | 294 Cursor no_ptr; |
295 Pixmap bm_no; | 295 Pixmap bm_no; |
296 XColor black , dummy; | 296 XColor black , dummy; |
297 Colormap colormap; | 297 Colormap colormap; |
298 static unsigned char bm_no_data[] = {0, 0, 0, 0, 0, 0, 0, 0}; | 298 static unsigned char bm_no_data[] = {0, 0, 0, 0, 0, 0, 0, 0}; |
299 | 299 |
300 colormap = DefaultColormap(disp, DefaultScreen(disp)); | 300 colormap = DefaultColormap(disp, DefaultScreen(disp)); |
301 XAllocNamedColor(disp, colormap, "black", &black, &dummy); | 301 XAllocNamedColor(disp, colormap, "black", &black, &dummy); |
302 bm_no = XCreateBitmapFromData(disp, win, bm_no_data, 8, 8); | 302 bm_no = XCreateBitmapFromData(disp, win, bm_no_data, 8, 8); |
303 no_ptr = XCreatePixmapCursor(disp, bm_no, bm_no, &black, &black, 0, 0); | 303 no_ptr = XCreatePixmapCursor(disp, bm_no, bm_no, &black, &black, 0, 0); |
304 | 304 |
305 XDefineCursor(disp, win, no_ptr); | 305 XDefineCursor(disp, win, no_ptr); |
306 XFreeCursor(disp, no_ptr); | 306 XFreeCursor(disp, no_ptr); |
307 if (bm_no != None) | 307 if (bm_no != None) |
308 XFreePixmap(disp, bm_no); | 308 XFreePixmap(disp, bm_no); |
309 | 309 |
310 } | 310 } |
311 | 311 |
312 /* | 312 /* |
313 * Sends the EWMH fullscreen state event. | 313 * Sends the EWMH fullscreen state event. |
319 #define _NET_WM_STATE_REMOVE 0 /* remove/unset property */ | 319 #define _NET_WM_STATE_REMOVE 0 /* remove/unset property */ |
320 #define _NET_WM_STATE_ADD 1 /* add/set property */ | 320 #define _NET_WM_STATE_ADD 1 /* add/set property */ |
321 #define _NET_WM_STATE_TOGGLE 2 /* toggle property */ | 321 #define _NET_WM_STATE_TOGGLE 2 /* toggle property */ |
322 void | 322 void |
323 vo_x11_ewmh_fullscreen(int action) { | 323 vo_x11_ewmh_fullscreen(int action) { |
324 XEvent xev; | 324 XEvent xev; |
325 | 325 |
326 assert(action == _NET_WM_STATE_REMOVE || | 326 assert(action == _NET_WM_STATE_REMOVE || |
327 action == _NET_WM_STATE_ADD || action == _NET_WM_STATE_TOGGLE); | 327 action == _NET_WM_STATE_ADD || action == _NET_WM_STATE_TOGGLE); |
328 | 328 |
329 | 329 |
330 /* init X event structure for _NET_WM_FULLSCREEN client msg */ | 330 /* init X event structure for _NET_WM_FULLSCREEN client msg */ |
331 xev.xclient.type = ClientMessage; | 331 xev.xclient.type = ClientMessage; |
332 xev.xclient.serial = 0; | 332 xev.xclient.serial = 0; |
333 xev.xclient.send_event = True; | 333 xev.xclient.send_event = True; |
334 xev.xclient.message_type = XInternAtom(disp, "_NET_WM_STATE", False); | 334 xev.xclient.message_type = XInternAtom(disp, "_NET_WM_STATE", False); |
335 xev.xclient.window = win; | 335 xev.xclient.window = win; |
336 xev.xclient.format = 32; | 336 xev.xclient.format = 32; |
337 xev.xclient.data.l[0] = action; | 337 xev.xclient.data.l[0] = action; |
338 xev.xclient.data.l[1] = XInternAtom(disp, "_NET_WM_STATE_FULLSCREEN", False); | 338 xev.xclient.data.l[1] = XInternAtom(disp, "_NET_WM_STATE_FULLSCREEN", False); |
339 xev.xclient.data.l[2] = 0; | 339 xev.xclient.data.l[2] = 0; |
340 xev.xclient.data.l[3] = 0; | 340 xev.xclient.data.l[3] = 0; |
341 xev.xclient.data.l[4] = 0; | 341 xev.xclient.data.l[4] = 0; |
342 | 342 |
343 /* finally send that damn thing */ | 343 /* finally send that damn thing */ |
344 if (!XSendEvent(disp, DefaultRootWindow(disp), False, | 344 if (!XSendEvent(disp, DefaultRootWindow(disp), False, |
345 SubstructureRedirectMask | SubstructureNotifyMask, | 345 SubstructureRedirectMask | SubstructureNotifyMask, |
346 &xev)) { | 346 &xev)) { |
347 fprintf(stderr, "Failed to send fullscreen command\n"); | 347 fprintf(stderr, "Failed to send fullscreen command\n"); |
348 } | 348 } |
349 } | 349 } |
350 | 350 |
351 | 351 |
352 void | 352 void |
353 X_Setup(int w, int h) { | 353 X_Setup(int w, int h) { |
354 XGCValues gcvals; | 354 XGCValues gcvals; |
355 Window root; | 355 Window root; |
356 XVisualInfo vinfo_pref; | 356 XVisualInfo vinfo_pref; |
357 int num_vis; | 357 int num_vis; |
358 XPixmapFormatValues *pf; | 358 XPixmapFormatValues *pf; |
359 int num_pf , pfi, i, j; | 359 int num_pf , pfi, i, j; |
360 XSizeHints sz_hint; | 360 XSizeHints sz_hint; |
361 | 361 |
362 disp = XOpenDisplay(NULL); | 362 disp = XOpenDisplay(NULL); |
363 if (!disp) { | 363 if (!disp) { |
364 fprintf(stderr, "X-Error: unable to connect to display\n"); | 364 fprintf(stderr, "X-Error: unable to connect to display\n"); |
365 exit(1); | 365 exit(1); |
366 } | 366 } |
367 XSynchronize(disp, True); | 367 XSynchronize(disp, True); |
368 | 368 |
369 scr = DefaultScreen(disp); | 369 scr = DefaultScreen(disp); |
370 vis = DefaultVisual(disp, scr); | 370 vis = DefaultVisual(disp, scr); |
371 root = DefaultRootWindow(disp); | 371 root = DefaultRootWindow(disp); |
372 depth = DefaultDepth(disp, scr); | 372 depth = DefaultDepth(disp, scr); |
373 | 373 |
374 vinfo_pref.screen = scr; | 374 vinfo_pref.screen = scr; |
375 vinfo_pref.visualid = XVisualIDFromVisual(vis); | 375 vinfo_pref.visualid = XVisualIDFromVisual(vis); |
376 vi = XGetVisualInfo(disp, VisualScreenMask | VisualIDMask, | 376 vi = XGetVisualInfo(disp, VisualScreenMask | VisualIDMask, |
377 &vinfo_pref, &num_vis); | 377 &vinfo_pref, &num_vis); |
378 assert(num_vis == 1); | 378 assert(num_vis == 1); |
379 | 379 |
380 win = XCreateSimpleWindow(disp, root, 0, 0, w, h, 0, 0, 0); | 380 win = XCreateSimpleWindow(disp, root, 0, 0, w, h, 0, 0, 0); |
381 gc = XCreateGC(disp, win, (unsigned long)0, &gcvals); | 381 gc = XCreateGC(disp, win, (unsigned long)0, &gcvals); |
382 XSetForeground(disp, gc, 0); | 382 XSetForeground(disp, gc, 0); |
383 XSetBackground(disp, gc, 1); | 383 XSetBackground(disp, gc, 1); |
384 | 384 |
385 XMapWindow(disp, win); | 385 XMapWindow(disp, win); |
386 cmap = DefaultColormap(disp, scr); | 386 cmap = DefaultColormap(disp, scr); |
387 | 387 |
388 sz_hint.flags = PAspect; | 388 sz_hint.flags = PAspect; |
389 sz_hint.min_aspect.x = width; | 389 sz_hint.min_aspect.x = width; |
390 sz_hint.min_aspect.y = height; | 390 sz_hint.min_aspect.y = height; |
391 sz_hint.max_aspect.x = width; | 391 sz_hint.max_aspect.x = width; |
392 sz_hint.max_aspect.y = height; | 392 sz_hint.max_aspect.y = height; |
393 | 393 |
394 /* set min height/width to 4 to avoid off by one errors */ | 394 /* set min height/width to 4 to avoid off by one errors */ |
395 sz_hint.min_width = sz_hint.min_height = 4; | 395 sz_hint.min_width = sz_hint.min_height = 4; |
396 sz_hint.flags |= PMinSize; | 396 sz_hint.flags |= PMinSize; |
397 XSetWMNormalHints(disp, win, &sz_hint); | 397 XSetWMNormalHints(disp, win, &sz_hint); |
398 | 398 |
399 XSync(disp, False); | 399 XSync(disp, False); |
400 | 400 |
401 /* Setup with Xv extension */ | 401 /* Setup with Xv extension */ |
402 xv_adaptor = -1; | 402 xv_adaptor = -1; |
403 xv_format_id = -1; | 403 xv_format_id = -1; |
404 XvQueryAdaptors(disp, root, &xv_num_adaptors, &xv_adaptors); | 404 XvQueryAdaptors(disp, root, &xv_num_adaptors, &xv_adaptors); |
405 for (i = 0; i < xv_num_adaptors; i++) { | 405 for (i = 0; i < xv_num_adaptors; i++) { |
406 XvAdaptorInfo *adaptor = &xv_adaptors[i]; | 406 XvAdaptorInfo *adaptor = &xv_adaptors[i]; |
407 int takes_images; | 407 int takes_images; |
408 | 408 |
409 takes_images = adaptor->type & (XvInputMask | XvImageMask); | 409 takes_images = adaptor->type & (XvInputMask | XvImageMask); |
410 if (takes_images) { | 410 if (takes_images) { |
411 XvImageFormatValues *formats; | 411 XvImageFormatValues *formats; |
412 int num_formats; | 412 int num_formats; |
413 | 413 |
414 formats = XvListImageFormats(disp, adaptor->base_id, &num_formats); | 414 formats = XvListImageFormats(disp, adaptor->base_id, &num_formats); |
415 for (j = 0; j < num_formats; j++) | 415 for (j = 0; j < num_formats; j++) |
416 if (formats[j].type == XvYUV && formats[j].format == XvPlanar && | 416 if (formats[j].type == XvYUV && formats[j].format == XvPlanar && |
417 strcmp(formats[j].guid, "YV12") == 0) | 417 strcmp(formats[j].guid, "YV12") == 0) |
418 break; | 418 break; |
419 if (j < num_formats) { | 419 if (j < num_formats) { |
420 xv_adaptor = i; | 420 xv_adaptor = i; |
421 xv_format_id = formats[j].id; | 421 xv_format_id = formats[j].id; |
422 break; | 422 break; |
423 } | 423 } |
424 } | 424 } |
425 } | 425 } |
426 assert(xv_adaptor >= 0); | 426 assert(xv_adaptor >= 0); |
427 | 427 |
428 /* Create an image to captured frames */ | 428 /* Create an image to captured frames */ |
429 #ifdef USE_XVIMAGES | 429 #ifdef USE_XVIMAGES |
430 yuv_image = XvShmCreateImage(disp, xv_adaptors[xv_adaptor].base_id, | 430 yuv_image = XvShmCreateImage(disp, xv_adaptors[xv_adaptor].base_id, |
431 xv_format_id, 0, w, h, &shminfo); | 431 xv_format_id, 0, w, h, &shminfo); |
432 if (!yuv_image) | 432 if (!yuv_image) |
433 fprintf(stderr, "X-Error: unable to create XvShm XImage\n"); | 433 fprintf(stderr, "X-Error: unable to create XvShm XImage\n"); |
434 | 434 |
435 shminfo.shmid = shmget(IPC_PRIVATE, yuv_image->data_size, IPC_CREAT | 0777); | 435 shminfo.shmid = shmget(IPC_PRIVATE, yuv_image->data_size, IPC_CREAT | 0777); |
436 if (shminfo.shmid == -1) | 436 if (shminfo.shmid == -1) |
437 fprintf(stderr, "SharedMemory Error: unable to get identifier\n"); | 437 fprintf(stderr, "SharedMemory Error: unable to get identifier\n"); |
438 | 438 |
439 shminfo.shmaddr = yuv_image->data = shmat(shminfo.shmid, 0, 0); | 439 shminfo.shmaddr = yuv_image->data = shmat(shminfo.shmid, 0, 0); |
440 yuv_image->data = shminfo.shmaddr; | 440 yuv_image->data = shminfo.shmaddr; |
441 #else | 441 #else |
442 rgb_image = XShmCreateImage(disp, vis, depth, ZPixmap, NULL, &shminfo, w, h); | 442 rgb_image = XShmCreateImage(disp, vis, depth, ZPixmap, NULL, &shminfo, w, h); |
443 if (!rgb_image) | 443 if (!rgb_image) |
444 fprintf(stderr, "X-Error: unable to create XShm XImage\n"); | 444 fprintf(stderr, "X-Error: unable to create XShm XImage\n"); |
445 | 445 |
446 shminfo.shmid = shmget(IPC_PRIVATE, | 446 shminfo.shmid = shmget(IPC_PRIVATE, |
447 rgb_image->bytes_per_line * rgb_image->height, | 447 rgb_image->bytes_per_line * rgb_image->height, |
448 IPC_CREAT | 0777); | 448 IPC_CREAT | 0777); |
449 if (shminfo.shmid == -1) | 449 if (shminfo.shmid == -1) |
450 fprintf(stderr, "SharedMemory Error: unable to get identifier\n"); | 450 fprintf(stderr, "SharedMemory Error: unable to get identifier\n"); |
451 | 451 |
452 shminfo.shmaddr = rgb_image->data = shmat(shminfo.shmid, 0, 0); | 452 shminfo.shmaddr = rgb_image->data = shmat(shminfo.shmid, 0, 0); |
453 #endif | 453 #endif |
454 | 454 |
455 if (!XShmAttach(disp, &shminfo)) | 455 if (!XShmAttach(disp, &shminfo)) |
456 fprintf(stderr, "X-Error: unable to attach XShm Shared Memory Segment\n"); | 456 fprintf(stderr, "X-Error: unable to attach XShm Shared Memory Segment\n"); |
457 | 457 |
458 /* Create a pixmap for the window background */ | 458 /* Create a pixmap for the window background */ |
459 #ifdef OLD | 459 #ifdef OLD |
460 pmap = XShmCreatePixmap(disp, win, shminfo.shmaddr, &shminfo, w, h, depth); | 460 pmap = XShmCreatePixmap(disp, win, shminfo.shmaddr, &shminfo, w, h, depth); |
461 if (!pmap) | 461 if (!pmap) |
462 fprintf(stderr, "Unable to create pixmap\n"); | 462 fprintf(stderr, "Unable to create pixmap\n"); |
463 #endif | 463 #endif |
464 | 464 |
465 /* Determine bits-per-pixel for pixmaps */ | 465 /* Determine bits-per-pixel for pixmaps */ |
466 pf = XListPixmapFormats(disp, &num_pf); | 466 pf = XListPixmapFormats(disp, &num_pf); |
467 assert(pf); | 467 assert(pf); |
468 for (pfi = 0; pfi < num_pf; pfi++) | 468 for (pfi = 0; pfi < num_pf; pfi++) |
469 if (pf[pfi].depth == vi->depth) | 469 if (pf[pfi].depth == vi->depth) |
470 break; | 470 break; |
471 assert(pfi < num_pf); | 471 assert(pfi < num_pf); |
472 bits_per_pixel = pf[pfi].bits_per_pixel; | 472 bits_per_pixel = pf[pfi].bits_per_pixel; |
473 XFree(pf); | 473 XFree(pf); |
474 | 474 |
475 #ifdef OLD | 475 #ifdef OLD |
476 XSetWindowBackgroundPixmap(disp, win, pmap); | 476 XSetWindowBackgroundPixmap(disp, win, pmap); |
477 #endif | 477 #endif |
478 } | 478 } |
479 | 479 |
480 /*--------------------------------------------------------------------------*/ | 480 /*--------------------------------------------------------------------------*/ |
481 | 481 |
482 void | 482 void |
483 X_Shutdown() { | 483 X_Shutdown() { |
484 XShmDetach(disp, &shminfo); | 484 XShmDetach(disp, &shminfo); |
485 #ifdef USE_XVIMAGES | 485 #ifdef USE_XVIMAGES |
486 shmctl(shminfo.shmid, IPC_RMID, 0); | 486 shmctl(shminfo.shmid, IPC_RMID, 0); |
487 shmdt(shminfo.shmaddr); | 487 shmdt(shminfo.shmaddr); |
488 XFree(yuv_image); | 488 XFree(yuv_image); |
489 #else | 489 #else |
490 XDestroyImage(rgb_image); | 490 XDestroyImage(rgb_image); |
491 #endif | 491 #endif |
492 shmdt(shminfo.shmaddr); | 492 shmdt(shminfo.shmaddr); |
493 shmctl(shminfo.shmid, IPC_RMID, 0); | 493 shmctl(shminfo.shmid, IPC_RMID, 0); |
494 } | 494 } |
495 | 495 |
496 | 496 |
497 /*--------------------------------------------------------------------------*/ | 497 /*--------------------------------------------------------------------------*/ |
498 | 498 |
499 void | 499 void |
500 X_Display(void) { | 500 X_Display(void) { |
501 int _w , _h, _d; | 501 int _w , _h, _d; |
502 Window _dw; | 502 Window _dw; |
503 | 503 |
504 #ifdef USE_XVIMAGES | 504 #ifdef USE_XVIMAGES |
505 XGetGeometry(disp, win, &_dw, &_d, &_d, &_w, &_h, &_d, &_d); | 505 XGetGeometry(disp, win, &_dw, &_d, &_d, &_w, &_h, &_d, &_d); |
506 XvShmPutImage(disp, xv_adaptors[xv_adaptor].base_id, win, | 506 XvShmPutImage(disp, xv_adaptors[xv_adaptor].base_id, win, |
507 gc, yuv_image, 0, 0, yuv_image->width, yuv_image->height, | 507 gc, yuv_image, 0, 0, yuv_image->width, yuv_image->height, |
508 0, 0, _w, _h, True); | 508 0, 0, _w, _h, True); |
509 #else | 509 #else |
510 XShmPutImage(disp, win, gc, rgb_image, 0, 0, 0, 0, | 510 XShmPutImage(disp, win, gc, rgb_image, 0, 0, 0, 0, |
511 rgb_image->width, rgb_image->height, False); | 511 rgb_image->width, rgb_image->height, False); |
512 #endif | 512 #endif |
513 XSync(disp, False); | 513 XSync(disp, False); |
514 } | 514 } |
515 | 515 |
516 #define CMD_NONE 0 | 516 #define CMD_NONE 0 |
517 #define CMD_CHNUP 1 | 517 #define CMD_CHNUP 1 |
518 #define CMD_CHNDN 2 | 518 #define CMD_CHNDN 2 |
527 /*--------------------------------------------------------------------------*/ | 527 /*--------------------------------------------------------------------------*/ |
528 | 528 |
529 int | 529 int |
530 main(int argc, char *argv[]) { | 530 main(int argc, char *argv[]) { |
531 #ifndef USE_XVIMAGES | 531 #ifndef USE_XVIMAGES |
532 HermesHandle conv; | 532 HermesHandle conv; |
533 HermesFormat fmt_source, fmt_dest; | 533 HermesFormat fmt_source, fmt_dest; |
534 #endif | 534 #endif |
535 XEvent e; | 535 XEvent e; |
536 char *scratch_buf, *code, *c, *mixerdev; | 536 char *scratch_buf, *code, *c, *mixerdev; |
537 int frames, channelidx, oldchan, mute, cursor, fd, ret, cmd; | 537 int frames, channelidx, oldchan, mute, cursor, fd, ret, cmd; |
538 int exitnow, mfd, uselirc, curvol; | 538 int exitnow, mfd, uselirc, curvol; |
539 struct timeval then, now, diff, lastmove; | 539 struct timeval then, now, diff, lastmove; |
540 float rate; | 540 float rate; |
541 KeySym key; | 541 KeySym key; |
542 char text [255]; | 542 char text [255]; |
543 int channellist[] = {2, 7, 9, 10, 28}; | 543 int channellist[] = {2, 7, 9, 10, 28}; |
544 struct lirc_config *config; | 544 struct lirc_config *config; |
545 struct pollfd fds[1]; | 545 struct pollfd fds[1]; |
546 | 546 |
547 #define NUMCHANS (sizeof(channellist) / sizeof(channellist[0])) | 547 #define NUMCHANS (sizeof(channellist) / sizeof(channellist[0])) |
548 | 548 |
549 channelidx = mute = cursor = 0; | 549 channelidx = mute = cursor = 0; |
550 | 550 |
551 oldchan = channel = channellist[channelidx]; | 551 oldchan = channel = channellist[channelidx]; |
552 | 552 |
553 #ifndef USE_XVIMAGES | 553 #ifndef USE_XVIMAGES |
554 if (!Hermes_Init()) { | 554 if (!Hermes_Init()) { |
555 printf("Couldn't initialise Hermes!\n"); | 555 printf("Couldn't initialise Hermes!\n"); |
556 exit(1); | |
557 } | |
558 conv = Hermes_ConverterInstance(HERMES_CONVERT_NORMAL); | |
559 if (!conv) { | |
560 printf("Could not obtain converter instance from Hermes!\n"); | |
561 exit(1); | |
562 } | |
563 #endif | |
564 | |
565 X_Setup(width, height); | |
566 XSelectInput(disp, win, KeyReleaseMask | PointerMotionMask | ButtonPressMask | ButtonReleaseMask); | |
567 | |
568 X_HideCursor(); | |
569 | |
570 /* Open Capture device */ | |
571 Open(); | |
572 | |
573 /* Open audio mixer */ | |
574 mixerdev = "/dev/mixer"; | |
575 if ((mfd = open(mixerdev, O_RDWR)) == -1) | |
576 fprintf(stderr, "Unable to open %s - %s\n", mixerdev, strerror(errno)); | |
577 | |
578 /* Talk to LIRC */ | |
579 if ((fd = lirc_init(basename(argv[0]), 1)) == -1) { | |
580 fprintf(stderr, "Unable to init lirc client library\n"); | |
581 uselirc = 0; | |
582 } else { | |
583 if (lirc_readconfig(NULL, &config, NULL) != 0) { | |
584 fprintf(stderr, "Unable to parse config file\n"); | |
585 uselirc = 0; | |
586 } else | |
587 uselirc = 1; | |
588 fds[0].fd = fd; | |
589 fds[0].events = POLLRDNORM; | |
590 } | |
591 | |
592 #ifndef USE_XVIMAGES | |
593 /* Conversion from and to formats */ | |
594 fmt_source.indexed = 0; | |
595 fmt_source.bits = 32; | |
596 fmt_source.r = 0xff0000; | |
597 fmt_source.g = 0x00ff00; | |
598 fmt_source.b = 0x0000ff; | |
599 fmt_source.a = 0; | |
600 | |
601 fmt_dest.indexed = 0; | |
602 fmt_dest.bits = bits_per_pixel; | |
603 fmt_dest.r = vi->red_mask; | |
604 fmt_dest.g = vi->green_mask; | |
605 fmt_dest.b = vi->blue_mask; | |
606 fmt_dest.a = 0; | |
607 #else | |
608 scratch_buf = malloc(width * height); | |
609 #endif | |
610 | |
611 frames = 0; | |
612 gettimeofday(&then, NULL); | |
613 gettimeofday(&lastmove, NULL); | |
614 | |
615 exitnow = 0; | |
616 | |
617 /* Capture loop */ | |
618 while (1) { | |
619 if (frames == 50) { | |
620 gettimeofday(&now, NULL); | |
621 timersub(&now, &then, &diff); | |
622 | |
623 rate = (float)frames / (float)(diff.tv_usec / 1000000.0 + diff.tv_sec); | |
624 | |
625 printf("%d frames in %.2f seconds, rate %.2f\n", frames, (float)(diff.tv_usec / 1000000.0) + diff.tv_sec, rate); | |
626 gettimeofday(&then, NULL); | |
627 frames = 0; | |
628 XResetScreenSaver(disp); | |
629 } | |
630 frames++; | |
631 | |
632 timersub(&now, &lastmove, &diff); | |
633 if (((float)diff.tv_usec / 1000000.0 + (float)diff.tv_sec) > 2.0) { | |
634 if (cursor) { | |
635 X_HideCursor(); | |
636 cursor = 0; | |
637 } | |
638 } else { | |
639 if (!cursor) { | |
640 X_ShowCursor(); | |
641 cursor = 1; | |
642 } | |
643 } | |
644 | |
645 if (XCheckMaskEvent(disp, PointerMotionMask, &e) && e.type == MotionNotify) { | |
646 gettimeofday(&lastmove, NULL); | |
647 } | |
648 cmd = CMD_NONE; | |
649 | |
650 if (XCheckMaskEvent(disp, ButtonReleaseMask, &e)) { | |
651 printf("e.type = %d\n", e.type); | |
652 cmd = CMD_MUTE; | |
653 } | |
654 if (XCheckMaskEvent(disp, KeyReleaseMask, &e) && e.type == KeyRelease) { | |
655 gettimeofday(&lastmove, NULL); | |
656 | |
657 XLookupString(&e.xkey, text, 255, &key, 0); | |
658 printf("Press - %c\n", text[0]); | |
659 | |
660 switch (text[0]) { | |
661 case 'q': | |
662 cmd = CMD_QUIT; | |
663 break; | |
664 | |
665 case '=': | |
666 case '+': | |
667 cmd = CMD_CHNUP; | |
668 break; | |
669 | |
670 case '-': | |
671 cmd = CMD_CHNDN; | |
672 break; | |
673 | |
674 case 'h': | |
675 cmd = CMD_CURSOR; | |
676 break; | |
677 | |
678 case 'm': | |
679 cmd = CMD_MUTE; | |
680 break; | |
681 | |
682 case 'r': | |
683 cmd = CMD_RELOAD; | |
684 break; | |
685 | |
686 case ',': | |
687 cmd = CMD_VOLDN; | |
688 break; | |
689 | |
690 case '.': | |
691 cmd = CMD_VOLUP; | |
692 break; | |
693 | |
694 case 'f': | |
695 cmd = CMD_FSTOGGLE; | |
696 break; | |
697 } | |
698 } | |
699 | |
700 /* Poll for IR events */ | |
701 if (uselirc) { | |
702 fds[0].revents = 0; | |
703 | |
704 while (1) { | |
705 | |
706 if (poll(fds, 1, 0) == -1) { | |
707 fprintf(stderr, "Poll failed - %s\n", strerror(errno)); | |
708 exit(EXIT_FAILURE); | |
709 } | |
710 if ((fds[0].revents & POLLRDNORM) != 0) { | |
711 fprintf(stderr, "Processing IR.. \n", lircfails); | |
712 | |
713 /* Try and get an event */ | |
714 if (lirc_nextcode(&code) == 0) { | |
715 if (code == NULL) { | |
716 continue; | |
717 } | |
718 | |
719 /* Translate it (via the config file) */ | |
720 while ((ret = lirc_code2char(config, code, &c)) == 0 && | |
721 c != NULL) { | |
722 fprintf(stderr, "Got command \"%s\"\n", c); | |
723 | |
724 if (!strcmp(c, "Mute")) | |
725 cmd = CMD_MUTE; | |
726 else if (!strcmp(c, "CH_UP")) | |
727 cmd = CMD_CHNUP; | |
728 else if (!strcmp(c, "CH_DOWN")) | |
729 cmd = CMD_CHNDN; | |
730 else if (!strcmp(c, "Power")) | |
731 cmd = CMD_QUIT; | |
732 else if (!strcmp(c, "VOL_UP")) | |
733 cmd = CMD_VOLUP; | |
734 else if (!strcmp(c, "VOL_DOWN")) | |
735 cmd = CMD_VOLDN; | |
736 else if (!strcmp(c, "AV/TV")) | |
737 cmd = CMD_FSTOGGLE; | |
738 | |
739 free(code); | |
740 } | |
741 } else { | |
742 /* lircd probably died */ | |
743 uselirc = 0; | |
744 fprintf(stderr, "Failed to communicate with LIRC - daemon exited?"); | |
745 } | |
746 } else | |
747 break; | |
748 } | |
749 } | |
750 switch (cmd) { | |
751 case CMD_QUIT: | |
752 exitnow = 1; | |
753 break; | |
754 | |
755 case CMD_CHNUP: | |
756 case CMD_CHNDN: | |
757 if (cmd == CMD_CHNUP) | |
758 channelidx++; | |
759 else | |
760 channelidx--; | |
761 | |
762 if (channelidx < 0) | |
763 channelidx = NUMCHANS - 1; | |
764 if (channelidx > NUMCHANS - 1) | |
765 channelidx = 0; | |
766 | |
767 channel = channellist[channelidx]; | |
768 | |
769 printf("Channel - %d\n", channel); | |
770 if (oldchan != channel) { | |
771 oldchan = channel; | |
772 | |
773 if (ioctl(tuner_fd, TVTUNER_SETCHNL, &channel) < 0) { | |
774 DO_IOCTL_SERR("TVTUNER_SETCHNL", channel); | |
775 exit(1); | |
776 } | |
777 } | |
778 break; | |
779 | |
780 case CMD_MUTE: | |
781 if (mute) | |
782 mute = 0; | |
783 else | |
784 mute = 1; | |
785 | |
786 printf("Mute - %d\n", mute); | |
787 if (ioctl(tuner_fd, BT848_SAUDIO, &mute) < 0) { | |
788 DO_IOCTL_SERR("BT848_SAUDIO", mute); | |
556 exit(1); | 789 exit(1); |
557 } | 790 } |
558 conv = Hermes_ConverterInstance(HERMES_CONVERT_NORMAL); | 791 break; |
559 if (!conv) { | 792 |
560 printf("Could not obtain converter instance from Hermes!\n"); | 793 case CMD_CURSOR: |
561 exit(1); | 794 if (cursor) { |
562 } | 795 printf("Cursor hidden\n"); |
563 #endif | 796 X_HideCursor(); |
564 | 797 cursor = 0; |
565 X_Setup(width, height); | 798 } else { |
566 XSelectInput(disp, win, KeyReleaseMask | PointerMotionMask | ButtonPressMask | ButtonReleaseMask); | 799 printf("Cursor revealed\n"); |
567 | 800 X_ShowCursor(); |
568 X_HideCursor(); | 801 cursor = 1; |
569 | 802 } |
570 /* Open Capture device */ | 803 break; |
571 Open(); | 804 |
572 | 805 case CMD_RELOAD: |
573 /* Open audio mixer */ | 806 printf("Reloading\n"); |
574 mixerdev = "/dev/mixer"; | 807 Close(); |
575 if ((mfd = open(mixerdev, O_RDWR)) == -1) | 808 Open(); |
576 fprintf(stderr, "Unable to open %s - %s\n", mixerdev, strerror(errno)); | 809 break; |
577 | 810 |
578 /* Talk to LIRC */ | 811 case CMD_VOLUP: |
579 if ((fd = lirc_init(basename(argv[0]), 1)) == -1) { | 812 case CMD_VOLDN: |
580 fprintf(stderr, "Unable to init lirc client library\n"); | 813 if (ioctl(mfd, MIXER_READ(SOUND_MIXER_VOLUME), &curvol) == -1) { |
581 uselirc = 0; | 814 fprintf(stderr, "Unable to read current volume - %s\n", strerror(errno)); |
582 } else { | 815 break; |
583 if (lirc_readconfig(NULL, &config, NULL) != 0) { | 816 } |
584 fprintf(stderr, "Unable to parse config file\n"); | 817 curvol = curvol & 0x7f; |
585 uselirc = 0; | 818 |
586 } else | 819 if (cmd == CMD_VOLUP) |
587 uselirc = 1; | 820 curvol += 5; |
588 fds[0].fd = fd; | 821 else |
589 fds[0].events = POLLRDNORM; | 822 curvol -= 5; |
590 } | 823 |
824 if (curvol < 0) | |
825 curvol = 0; | |
826 if (curvol > 100) | |
827 curvol = 100; | |
828 | |
829 printf("Setting volume to %d\n", curvol); | |
830 curvol |= curvol << 8; | |
831 | |
832 if (ioctl(mfd, MIXER_WRITE(SOUND_MIXER_VOLUME), &curvol) == -1) { | |
833 fprintf(stderr, "Unable to write volume - %s\n", strerror(errno)); | |
834 break; | |
835 } | |
836 break; | |
837 | |
838 case CMD_FSTOGGLE: | |
839 vo_x11_ewmh_fullscreen(_NET_WM_STATE_TOGGLE); | |
840 break; | |
841 | |
842 } | |
843 | |
844 Capture(); | |
845 | |
846 #ifdef USE_XVIMAGES | |
847 /* bktr's YUV_12 is planar W*H bytes Y, W/2*H/2 bytes U, */ | |
848 /* W/2*H/2 bytes V. Xv's YV12 is the same with U and V */ | |
849 /* planes reversed. */ | |
850 { | |
851 int y_off , u_off, v_off; | |
852 y_off = 0; | |
853 u_off = width * height; | |
854 v_off = u_off + width * height / 4; | |
855 | |
856 assert(yuv_image->data_size == width * height * 3 / 2); | |
857 memcpy(yuv_image->data, bktr_buffer, u_off - y_off); | |
858 memcpy(yuv_image->data + u_off, bktr_buffer + v_off, v_off - u_off); | |
859 memcpy(yuv_image->data + v_off, bktr_buffer + u_off, v_off - u_off); | |
860 } | |
861 #else | |
862 /* SaveImage(); */ | |
863 | |
864 Hermes_ConverterRequest(conv, &fmt_source, &fmt_dest); | |
865 Hermes_ConverterCopy(conv, bktr_buffer, 0, 0, width, height, width * 4, | |
866 rgb_image->data, 0, 0, width, height, | |
867 rgb_image->bytes_per_line); | |
868 #endif | |
869 | |
870 X_Display(); | |
871 if (exitnow) { | |
872 printf("quitting\n"); | |
873 break; | |
874 } | |
875 } | |
591 | 876 |
592 #ifndef USE_XVIMAGES | 877 #ifndef USE_XVIMAGES |
593 /* Conversion from and to formats */ | 878 Hermes_ConverterReturn(conv); |
594 fmt_source.indexed = 0; | 879 Hermes_Done(); |
595 fmt_source.bits = 32; | 880 #endif |
596 fmt_source.r = 0xff0000; | 881 |
597 fmt_source.g = 0x00ff00; | 882 X_Shutdown(); |
598 fmt_source.b = 0x0000ff; | 883 lirc_freeconfig(config); |
599 fmt_source.a = 0; | 884 lirc_deinit(); |
600 | 885 |
601 fmt_dest.indexed = 0; | 886 return 0; |
602 fmt_dest.bits = bits_per_pixel; | 887 } |
603 fmt_dest.r = vi->red_mask; | |
604 fmt_dest.g = vi->green_mask; | |
605 fmt_dest.b = vi->blue_mask; | |
606 fmt_dest.a = 0; | |
607 #else | |
608 scratch_buf = malloc(width * height); | |
609 #endif | |
610 | |
611 frames = 0; | |
612 gettimeofday(&then, NULL); | |
613 gettimeofday(&lastmove, NULL); | |
614 | |
615 exitnow = 0; | |
616 | |
617 /* Capture loop */ | |
618 while (1) { | |
619 if (frames == 50) { | |
620 gettimeofday(&now, NULL); | |
621 timersub(&now, &then, &diff); | |
622 | |
623 rate = (float)frames / (float)(diff.tv_usec / 1000000.0 + diff.tv_sec); | |
624 | |
625 printf("%d frames in %.2f seconds, rate %.2f\n", frames, (float)(diff.tv_usec / 1000000.0) + diff.tv_sec, rate); | |
626 gettimeofday(&then, NULL); | |
627 frames = 0; | |
628 XResetScreenSaver(disp); | |
629 } | |
630 frames++; | |
631 | |
632 timersub(&now, &lastmove, &diff); | |
633 if (((float)diff.tv_usec / 1000000.0 + (float)diff.tv_sec) > 2.0) { | |
634 if (cursor) { | |
635 X_HideCursor(); | |
636 cursor = 0; | |
637 } | |
638 } else { | |
639 if (!cursor) { | |
640 X_ShowCursor(); | |
641 cursor = 1; | |
642 } | |
643 } | |
644 | |
645 if (XCheckMaskEvent(disp, PointerMotionMask, &e) && e.type == MotionNotify) { | |
646 gettimeofday(&lastmove, NULL); | |
647 } | |
648 cmd = CMD_NONE; | |
649 | |
650 if (XCheckMaskEvent(disp, ButtonReleaseMask, &e)) { | |
651 printf("e.type = %d\n", e.type); | |
652 cmd = CMD_MUTE; | |
653 } | |
654 if (XCheckMaskEvent(disp, KeyReleaseMask, &e) && e.type == KeyRelease) { | |
655 gettimeofday(&lastmove, NULL); | |
656 | |
657 XLookupString(&e.xkey, text, 255, &key, 0); | |
658 printf("Press - %c\n", text[0]); | |
659 | |
660 switch (text[0]) { | |
661 case 'q': | |
662 cmd = CMD_QUIT; | |
663 break; | |
664 | |
665 case '=': | |
666 case '+': | |
667 cmd = CMD_CHNUP; | |
668 break; | |
669 | |
670 case '-': | |
671 cmd = CMD_CHNDN; | |
672 break; | |
673 | |
674 case 'h': | |
675 cmd = CMD_CURSOR; | |
676 break; | |
677 | |
678 case 'm': | |
679 cmd = CMD_MUTE; | |
680 break; | |
681 | |
682 case 'r': | |
683 cmd = CMD_RELOAD; | |
684 break; | |
685 | |
686 case ',': | |
687 cmd = CMD_VOLDN; | |
688 break; | |
689 | |
690 case '.': | |
691 cmd = CMD_VOLUP; | |
692 break; | |
693 | |
694 case 'f': | |
695 cmd = CMD_FSTOGGLE; | |
696 break; | |
697 } | |
698 } | |
699 | |
700 /* Poll for IR events */ | |
701 if (uselirc) { | |
702 fds[0].revents = 0; | |
703 | |
704 while (1) { | |
705 | |
706 if (poll(fds, 1, 0) == -1) { | |
707 fprintf(stderr, "Poll failed - %s\n", strerror(errno)); | |
708 exit(EXIT_FAILURE); | |
709 } | |
710 if ((fds[0].revents & POLLRDNORM) != 0) { | |
711 fprintf(stderr, "Processing IR.. \n", lircfails); | |
712 | |
713 /* Try and get an event */ | |
714 if (lirc_nextcode(&code) == 0) { | |
715 if (code == NULL) { | |
716 continue; | |
717 } | |
718 | |
719 /* Translate it (via the config file) */ | |
720 while ((ret = lirc_code2char(config, code, &c)) == 0 && | |
721 c != NULL) { | |
722 fprintf(stderr, "Got command \"%s\"\n", c); | |
723 | |
724 if (!strcmp(c, "Mute")) | |
725 cmd = CMD_MUTE; | |
726 else if (!strcmp(c, "CH_UP")) | |
727 cmd = CMD_CHNUP; | |
728 else if (!strcmp(c, "CH_DOWN")) | |
729 cmd = CMD_CHNDN; | |
730 else if (!strcmp(c, "Power")) | |
731 cmd = CMD_QUIT; | |
732 else if (!strcmp(c, "VOL_UP")) | |
733 cmd = CMD_VOLUP; | |
734 else if (!strcmp(c, "VOL_DOWN")) | |
735 cmd = CMD_VOLDN; | |
736 else if (!strcmp(c, "AV/TV")) | |
737 cmd = CMD_FSTOGGLE; | |
738 | |
739 free(code); | |
740 } | |
741 } else { | |
742 /* lircd probably died */ | |
743 uselirc = 0; | |
744 fprintf(stderr, "Failed to communicate with LIRC - daemon exited?"); | |
745 } | |
746 } else | |
747 break; | |
748 } | |
749 } | |
750 switch (cmd) { | |
751 case CMD_QUIT: | |
752 exitnow = 1; | |
753 break; | |
754 | |
755 case CMD_CHNUP: | |
756 case CMD_CHNDN: | |
757 if (cmd == CMD_CHNUP) | |
758 channelidx++; | |
759 else | |
760 channelidx--; | |
761 | |
762 if (channelidx < 0) | |
763 channelidx = NUMCHANS - 1; | |
764 if (channelidx > NUMCHANS - 1) | |
765 channelidx = 0; | |
766 | |
767 channel = channellist[channelidx]; | |
768 | |
769 printf("Channel - %d\n", channel); | |
770 if (oldchan != channel) { | |
771 oldchan = channel; | |
772 | |
773 if (ioctl(tuner_fd, TVTUNER_SETCHNL, &channel) < 0) { | |
774 DO_IOCTL_SERR("TVTUNER_SETCHNL", channel); | |
775 exit(1); | |
776 } | |
777 } | |
778 break; | |
779 | |
780 case CMD_MUTE: | |
781 if (mute) | |
782 mute = 0; | |
783 else | |
784 mute = 1; | |
785 | |
786 printf("Mute - %d\n", mute); | |
787 if (ioctl(tuner_fd, BT848_SAUDIO, &mute) < 0) { | |
788 DO_IOCTL_SERR("BT848_SAUDIO", mute); | |
789 exit(1); | |
790 } | |
791 break; | |
792 | |
793 case CMD_CURSOR: | |
794 if (cursor) { | |
795 printf("Cursor hidden\n"); | |
796 X_HideCursor(); | |
797 cursor = 0; | |
798 } else { | |
799 printf("Cursor revealed\n"); | |
800 X_ShowCursor(); | |
801 cursor = 1; | |
802 } | |
803 break; | |
804 | |
805 case CMD_RELOAD: | |
806 printf("Reloading\n"); | |
807 Close(); | |
808 Open(); | |
809 break; | |
810 | |
811 case CMD_VOLUP: | |
812 case CMD_VOLDN: | |
813 if (ioctl(mfd, MIXER_READ(SOUND_MIXER_VOLUME), &curvol) == -1) { | |
814 fprintf(stderr, "Unable to read current volume - %s\n", strerror(errno)); | |
815 break; | |
816 } | |
817 curvol = curvol & 0x7f; | |
818 | |
819 if (cmd == CMD_VOLUP) | |
820 curvol += 5; | |
821 else | |
822 curvol -= 5; | |
823 | |
824 if (curvol < 0) | |
825 curvol = 0; | |
826 if (curvol > 100) | |
827 curvol = 100; | |
828 | |
829 printf("Setting volume to %d\n", curvol); | |
830 curvol |= curvol << 8; | |
831 | |
832 if (ioctl(mfd, MIXER_WRITE(SOUND_MIXER_VOLUME), &curvol) == -1) { | |
833 fprintf(stderr, "Unable to write volume - %s\n", strerror(errno)); | |
834 break; | |
835 } | |
836 break; | |
837 | |
838 case CMD_FSTOGGLE: | |
839 vo_x11_ewmh_fullscreen(_NET_WM_STATE_TOGGLE); | |
840 break; | |
841 | |
842 } | |
843 | |
844 Capture(); | |
845 | |
846 #ifdef USE_XVIMAGES | |
847 /* bktr's YUV_12 is planar W*H bytes Y, W/2*H/2 bytes U, */ | |
848 /* W/2*H/2 bytes V. Xv's YV12 is the same with U and V */ | |
849 /* planes reversed. */ | |
850 { | |
851 int y_off , u_off, v_off; | |
852 y_off = 0; | |
853 u_off = width * height; | |
854 v_off = u_off + width * height / 4; | |
855 | |
856 assert(yuv_image->data_size == width * height * 3 / 2); | |
857 memcpy(yuv_image->data, bktr_buffer, u_off - y_off); | |
858 memcpy(yuv_image->data + u_off, bktr_buffer + v_off, v_off - u_off); | |
859 memcpy(yuv_image->data + v_off, bktr_buffer + u_off, v_off - u_off); | |
860 } | |
861 #else | |
862 /* SaveImage(); */ | |
863 | |
864 Hermes_ConverterRequest(conv, &fmt_source, &fmt_dest); | |
865 Hermes_ConverterCopy(conv, bktr_buffer, 0, 0, width, height, width * 4, | |
866 rgb_image->data, 0, 0, width, height, | |
867 rgb_image->bytes_per_line); | |
868 #endif | |
869 | |
870 X_Display(); | |
871 if (exitnow) { | |
872 printf("quitting\n"); | |
873 break; | |
874 } | |
875 } | |
876 | |
877 #ifndef USE_XVIMAGES | |
878 Hermes_ConverterReturn(conv); | |
879 Hermes_Done(); | |
880 #endif | |
881 | |
882 X_Shutdown(); | |
883 lirc_freeconfig(config); | |
884 lirc_deinit(); | |
885 | |
886 return 0; | |
887 } |