video: default to colorspace/range from libavcodec
[mplayer.git] / libvo / vo_dfbmga.c
blob57b798040e889a166996b60d7dc59303765f72f7
1 /*
2 * MPlayer video driver for DirectFB / Matrox G200/G400/G450/G550
4 * copyright (C) 2002-2008 Ville Syrjala <syrjala@sci.fi>
5 * Originally based on vo_directfb.c by Jiri Svoboda <Jiri.Svoboda@seznam.cz>.
7 * This file is part of MPlayer.
9 * MPlayer is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * MPlayer is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public License
20 * along with MPlayer; if not, write to the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24 #include <directfb.h>
25 #include <directfb_version.h>
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
30 #include "config.h"
31 #include "video_out.h"
32 #include "video_out_internal.h"
33 #include "fastmemcpy.h"
34 #include "sub/sub.h"
35 #include "mp_msg.h"
36 #include "aspect.h"
37 #include "mp_fifo.h"
38 #include "input/keycodes.h"
40 static const vo_info_t info = {
41 "DirectFB / Matrox G200/G400/G450/G550",
42 "dfbmga",
43 "Ville Syrjala <syrjala@sci.fi>",
47 const LIBVO_EXTERN(dfbmga)
49 static IDirectFB *dfb;
51 static IDirectFBDisplayLayer *crtc1;
52 static IDirectFBDisplayLayer *bes;
53 static IDirectFBDisplayLayer *crtc2;
54 static IDirectFBDisplayLayer *spic;
56 static int num_bufs;
57 static int current_buf;
58 static int current_ip_buf;
59 static IDirectFBSurface *bufs[3];
61 static IDirectFBSurface *frame;
62 static IDirectFBSurface *subframe;
64 static IDirectFBSurface *besframe;
65 static IDirectFBSurface *c1frame;
66 static IDirectFBSurface *c2frame;
67 static IDirectFBSurface *spicframe;
69 static DFBSurfacePixelFormat frame_format;
70 static DFBSurfacePixelFormat subframe_format;
72 static DFBRectangle besrect;
73 static DFBRectangle c1rect;
74 static DFBRectangle c2rect;
75 static DFBRectangle *subrect;
77 static IDirectFBInputDevice *keyboard;
78 static IDirectFBInputDevice *remote;
79 static IDirectFBEventBuffer *buffer;
81 static int blit_done;
82 static int c1stretch;
83 static int c2stretch;
85 static int use_bes;
86 static int use_crtc1;
87 static int use_crtc2;
88 static int use_spic;
89 static int use_input;
90 static int use_remote;
91 static int field_parity;
92 static int flipping;
93 static DFBDisplayLayerBufferMode buffermode;
94 static int tvnorm;
96 static int osd_changed;
97 static int osd_dirty;
98 static int osd_current;
99 static int osd_max;
101 static int is_g200;
103 static uint32_t in_width;
104 static uint32_t in_height;
105 static uint32_t buf_height;
106 static uint32_t screen_width;
107 static uint32_t screen_height;
108 static uint32_t sub_width;
109 static uint32_t sub_height;
111 static char *
112 pixelformat_name( DFBSurfacePixelFormat format )
114 switch(format) {
115 case DSPF_ARGB:
116 return "ARGB";
117 case DSPF_RGB32:
118 return "RGB32";
119 case DSPF_RGB16:
120 return "RGB16";
121 case DSPF_ARGB1555:
122 return "ARGB1555";
123 case DSPF_YUY2:
124 return "YUY2";
125 case DSPF_UYVY:
126 return "UYVY";
127 case DSPF_YV12:
128 return "YV12";
129 case DSPF_I420:
130 return "I420";
131 case DSPF_ALUT44:
132 return "ALUT44";
133 case DSPF_NV12:
134 return "NV12";
135 case DSPF_NV21:
136 return "NV21";
137 default:
138 return "Unknown pixel format";
142 static DFBSurfacePixelFormat
143 imgfmt_to_pixelformat( uint32_t format )
145 switch (format) {
146 case IMGFMT_BGR32:
147 return DSPF_RGB32;
148 case IMGFMT_BGR16:
149 return DSPF_RGB16;
150 case IMGFMT_BGR15:
151 return DSPF_ARGB1555;
152 case IMGFMT_YUY2:
153 return DSPF_YUY2;
154 case IMGFMT_UYVY:
155 return DSPF_UYVY;
156 case IMGFMT_YV12:
157 return DSPF_YV12;
158 case IMGFMT_I420:
159 case IMGFMT_IYUV:
160 return DSPF_I420;
161 case IMGFMT_NV12:
162 return DSPF_NV12;
163 case IMGFMT_NV21:
164 return DSPF_NV21;
165 default:
166 return DSPF_UNKNOWN;
170 struct layer_enum
172 const char *name;
173 IDirectFBDisplayLayer **layer;
174 DFBResult res;
177 static DFBEnumerationResult
178 get_layer_by_name( DFBDisplayLayerID id,
179 DFBDisplayLayerDescription desc,
180 void *data )
182 struct layer_enum *l = (struct layer_enum *) data;
184 if (!strcmp( l->name, desc.name ))
185 if ((l->res = dfb->GetDisplayLayer( dfb, id, l->layer )) == DFB_OK)
186 return DFENUM_CANCEL;
188 return DFENUM_OK;
191 static int
192 preinit( const char *arg )
194 DFBResult res;
195 int force_input = -1;
197 /* Some defaults */
198 use_bes = 0;
199 use_crtc1 = 0;
200 use_crtc2 = 1;
201 use_spic = 1;
202 field_parity = -1;
203 buffermode = DLBM_TRIPLE;
204 osd_max = 4;
205 flipping = 1;
206 tvnorm = -1;
208 use_input = !getenv( "DISPLAY" );
210 if (vo_subdevice) {
211 int show_help = 0;
212 int opt_no = 0;
213 while (*vo_subdevice != '\0') {
214 if (!strncmp(vo_subdevice, "bes", 3)) {
215 use_bes = !opt_no;
216 vo_subdevice += 3;
217 opt_no = 0;
218 } else if (!strncmp(vo_subdevice, "crtc1", 5)) {
219 use_crtc1 = !opt_no;
220 vo_subdevice += 5;
221 opt_no = 0;
222 } else if (!strncmp(vo_subdevice, "crtc2", 5)) {
223 use_crtc2 = !opt_no;
224 vo_subdevice += 5;
225 opt_no = 0;
226 } else if (!strncmp(vo_subdevice, "spic", 4)) {
227 use_spic = !opt_no;
228 vo_subdevice += 4;
229 opt_no = 0;
230 } else if (!strncmp(vo_subdevice, "input", 5)) {
231 force_input = !opt_no;
232 vo_subdevice += 5;
233 opt_no = 0;
234 } else if (!strncmp(vo_subdevice, "remote", 6)) {
235 use_remote = !opt_no;
236 vo_subdevice += 6;
237 opt_no = 0;
238 } else if (!strncmp(vo_subdevice, "buffermode=", 11)) {
239 if (opt_no) {
240 show_help = 1;
241 break;
243 vo_subdevice += 11;
244 if (!strncmp(vo_subdevice, "single", 6)) {
245 buffermode = DLBM_FRONTONLY;
246 osd_max = 1;
247 flipping = 0;
248 vo_subdevice += 6;
249 } else if (!strncmp(vo_subdevice, "double", 6)) {
250 buffermode = DLBM_BACKVIDEO;
251 osd_max = 2;
252 flipping = 1;
253 vo_subdevice += 6;
254 } else if (!strncmp(vo_subdevice, "triple", 6)) {
255 buffermode = DLBM_TRIPLE;
256 osd_max = 4;
257 flipping = 1;
258 vo_subdevice += 6;
259 } else {
260 show_help = 1;
261 break;
263 opt_no = 0;
264 } else if (!strncmp(vo_subdevice, "fieldparity=", 12)) {
265 if (opt_no) {
266 show_help = 1;
267 break;
269 vo_subdevice += 12;
270 if (!strncmp(vo_subdevice, "top", 3)) {
271 field_parity = 0;
272 vo_subdevice += 3;
273 } else if (!strncmp(vo_subdevice, "bottom", 6)) {
274 field_parity = 1;
275 vo_subdevice += 6;
276 } else {
277 show_help = 1;
278 break;
280 opt_no = 0;
281 } else if (!strncmp(vo_subdevice, "tvnorm=", 7)) {
282 if (opt_no) {
283 show_help = 1;
284 break;
286 vo_subdevice += 7;
287 if (!strncmp(vo_subdevice, "pal", 3)) {
288 tvnorm = 0;
289 vo_subdevice += 3;
290 } else if (!strncmp(vo_subdevice, "ntsc" , 4)) {
291 tvnorm = 1;
292 vo_subdevice += 4;
293 } else if (!strncmp(vo_subdevice, "auto" , 4)) {
294 tvnorm = 2;
295 vo_subdevice += 4;
296 } else {
297 show_help = 1;
298 break;
300 opt_no = 0;
301 } else if (!strncmp(vo_subdevice, "no", 2)) {
302 if (opt_no) {
303 show_help = 1;
304 break;
306 vo_subdevice += 2;
307 opt_no = 1;
308 } else if (*vo_subdevice == ':') {
309 if (opt_no) {
310 show_help = 1;
311 break;
313 vo_subdevice++;
314 opt_no = 0;
315 } else {
316 show_help = 1;
317 break;
320 if (show_help) {
321 mp_msg( MSGT_VO, MSGL_ERR,
322 "\nvo_dfbmga command line help:\n"
323 "Example: mplayer -vo dfbmga:nocrtc2:bes:buffermode=single\n"
324 "\nOptions (use 'no' prefix to disable):\n"
325 " bes Use Backend Scaler\n"
326 " crtc1 Use CRTC1\n"
327 " crtc2 Use CRTC2\n"
328 " spic Use hardware sub-picture for OSD\n"
329 " input Use DirectFB for keyboard input\n"
330 " remote Use DirectFB for remote control input\n"
331 "\nOther options:\n"
332 " buffermode=(single|double|triple)\n"
333 " single Use single buffering\n"
334 " double Use double buffering\n"
335 " triple Use triple buffering\n"
336 " fieldparity=(top|bottom)\n"
337 " top Top field first\n"
338 " bottom Bottom field first\n"
339 " tvnorm=(pal|ntsc|auto)\n"
340 " pal Force PAL\n"
341 " ntsc Force NTSC\n"
342 " auto Select according to FPS\n"
343 "\n" );
344 return -1;
347 if (!use_bes && !use_crtc1 && !use_crtc2) {
348 mp_msg( MSGT_VO, MSGL_ERR, "vo_dfbmga: No output selected\n" );
349 return -1;
351 if (use_bes && use_crtc1) {
352 mp_msg( MSGT_VO, MSGL_ERR, "vo_dfbmga: Both BES and CRTC1 outputs selected\n" );
353 return -1;
356 if ((res = DirectFBInit( NULL, NULL )) != DFB_OK) {
357 mp_msg( MSGT_VO, MSGL_ERR,
358 "vo_dfbmga: DirectFBInit() failed - %s\n",
359 DirectFBErrorString( res ) );
360 return -1;
363 switch (tvnorm) {
364 case 0:
365 DirectFBSetOption( "matrox-tv-standard", "pal" );
366 mp_msg( MSGT_VO, MSGL_INFO, "vo_dfbmga: Forced TV standard to PAL\n" );
367 break;
368 case 1:
369 DirectFBSetOption( "matrox-tv-standard", "ntsc" );
370 mp_msg( MSGT_VO, MSGL_INFO, "vo_dfbmga: Forced TV standard to NTSC\n" );
371 break;
372 case 2:
373 if (vo_fps > 27) {
374 DirectFBSetOption( "matrox-tv-standard", "ntsc" );
375 mp_msg( MSGT_VO, MSGL_INFO,
376 "vo_dfbmga: Selected TV standard based upon FPS: NTSC\n" );
377 } else {
378 DirectFBSetOption( "matrox-tv-standard", "pal" );
379 mp_msg( MSGT_VO, MSGL_INFO,
380 "vo_dfbmga: Selected TV standard based upon FPS: PAL\n" );
382 break;
385 if ((res = DirectFBCreate( &dfb )) != DFB_OK) {
386 mp_msg( MSGT_VO, MSGL_ERR,
387 "vo_dfbmga: DirectFBCreate() failed - %s\n",
388 DirectFBErrorString( res ) );
389 return -1;
392 if (use_crtc1 || use_bes) {
393 struct layer_enum l = {
394 "FBDev Primary Layer",
395 &crtc1,
396 DFB_UNSUPPORTED
398 dfb->EnumDisplayLayers( dfb, get_layer_by_name, &l );
399 if (l.res != DFB_OK) {
400 mp_msg( MSGT_VO, MSGL_ERR, "vo_dfbmga: Can't get CRTC1 layer - %s\n",
401 DirectFBErrorString( l.res ) );
402 uninit();
403 return -1;
405 if ((res = crtc1->SetCooperativeLevel( crtc1, DLSCL_EXCLUSIVE )) != DFB_OK) {
406 mp_msg( MSGT_VO, MSGL_ERR, "Can't get exclusive access to CRTC1 layer - %s\n",
407 DirectFBErrorString( res ) );
408 uninit();
409 return -1;
411 use_input = 1;
414 if (force_input != -1)
415 use_input = force_input;
417 if (use_bes) {
418 DFBDisplayLayerConfig dlc;
419 DFBDisplayLayerConfigFlags failed;
420 struct layer_enum l = {
421 "Matrox Backend Scaler",
422 &bes,
423 DFB_UNSUPPORTED
426 dfb->EnumDisplayLayers( dfb, get_layer_by_name, &l );
427 if (l.res != DFB_OK) {
428 mp_msg( MSGT_VO, MSGL_ERR, "Can't get BES layer - %s\n",
429 DirectFBErrorString( l.res ) );
430 uninit();
431 return -1;
433 if ((res = bes->SetCooperativeLevel( bes, DLSCL_EXCLUSIVE )) != DFB_OK) {
434 mp_msg( MSGT_VO, MSGL_ERR, "Can't get exclusive access to BES - %s\n",
435 DirectFBErrorString( res ) );
436 uninit();
437 return -1;
439 dlc.flags = DLCONF_PIXELFORMAT;
440 dlc.pixelformat = DSPF_RGB16;
441 if (bes->TestConfiguration( bes, &dlc, &failed ) != DFB_OK) {
442 is_g200 = 1;
443 use_crtc2 = 0;
447 if (use_crtc2) {
448 struct layer_enum l = {
449 "Matrox CRTC2 Layer",
450 &crtc2,
451 DFB_UNSUPPORTED
454 dfb->EnumDisplayLayers( dfb, get_layer_by_name, &l );
455 if (l.res != DFB_OK) {
456 mp_msg( MSGT_VO, MSGL_ERR, "Can't get CRTC2 layer - %s\n",
457 DirectFBErrorString( l.res ) );
458 uninit();
459 return -1;
461 if ((res = crtc2->SetCooperativeLevel( crtc2, DLSCL_EXCLUSIVE )) != DFB_OK) {
462 mp_msg( MSGT_VO, MSGL_ERR, "Can't get exclusive access to CRTC2 - %s\n",
463 DirectFBErrorString( res ) );
464 uninit();
465 return -1;
469 if (use_input || use_remote) {
470 if ((res = dfb->CreateEventBuffer( dfb, &buffer )) != DFB_OK) {
471 mp_msg( MSGT_VO, MSGL_ERR,
472 "vo_dfbmga: Can't create event buffer - %s\n",
473 DirectFBErrorString( res ) );
474 uninit();
475 return -1;
479 if (use_input) {
480 if ((res = dfb->GetInputDevice( dfb, DIDID_KEYBOARD, &keyboard )) != DFB_OK) {
481 mp_msg( MSGT_VO, MSGL_ERR,
482 "vo_dfbmga: Can't get keyboard - %s\n",
483 DirectFBErrorString( res ) );
484 uninit();
485 return -1;
487 if ((res = keyboard->AttachEventBuffer( keyboard, buffer )) != DFB_OK) {
488 mp_msg( MSGT_VO, MSGL_ERR,
489 "vo_dfbmga: Can't attach event buffer to keyboard - %s\n",
490 DirectFBErrorString( res ) );
491 uninit();
492 return -1;
495 if (use_remote) {
496 if ((res = dfb->GetInputDevice( dfb, DIDID_REMOTE, &remote )) != DFB_OK) {
497 mp_msg( MSGT_VO, MSGL_ERR,
498 "vo_dfbmga: Can't get remote control - %s\n",
499 DirectFBErrorString( res ) );
500 uninit();
501 return -1;
503 if ((res = remote->AttachEventBuffer( remote, buffer )) != DFB_OK) {
504 mp_msg( MSGT_VO, MSGL_ERR,
505 "vo_dfbmga: Can't attach event buffer to remote control - %s\n",
506 DirectFBErrorString( res ) );
507 uninit();
508 return -1;
512 return 0;
515 static void release_config( void )
517 if (spicframe)
518 spicframe->Release( spicframe );
519 if (spic)
520 spic->Release( spic );
521 if (c2frame)
522 c2frame->Release( c2frame );
523 if (c1frame)
524 c1frame->Release( c1frame );
525 if (besframe)
526 besframe->Release( besframe );
527 if (bufs[0])
528 bufs[0]->Release( bufs[0] );
529 if (bufs[1])
530 bufs[1]->Release( bufs[1] );
531 if (bufs[2])
532 bufs[2]->Release( bufs[2] );
534 spicframe = NULL;
535 spic = NULL;
536 c2frame = NULL;
537 c1frame = NULL;
538 besframe = NULL;
539 bufs[0] = NULL;
540 bufs[1] = NULL;
541 bufs[2] = NULL;
544 static int
545 config( uint32_t width, uint32_t height,
546 uint32_t d_width, uint32_t d_height,
547 uint32_t flags,
548 char *title,
549 uint32_t format )
551 DFBResult res;
553 DFBDisplayLayerConfig dlc;
554 DFBDisplayLayerConfigFlags failed;
556 uint32_t out_width;
557 uint32_t out_height;
559 release_config();
561 in_width = width;
562 in_height = height;
564 aspect_save_orig(width, height);
565 aspect_save_prescale(d_width, d_height);
567 dlc.pixelformat = imgfmt_to_pixelformat( format );
570 /* Draw to a temporary surface */
571 DFBSurfaceDescription dsc;
573 dsc.flags = DSDESC_WIDTH | DSDESC_HEIGHT |
574 DSDESC_PIXELFORMAT;
575 dsc.width = (in_width + 15) & ~15;
576 dsc.height = (in_height + 15) & ~15;
577 dsc.pixelformat = dlc.pixelformat;
579 /* Don't waste video memory since we don't need direct stretchblit */
580 if (use_bes) {
581 dsc.flags |= DSDESC_CAPS;
582 dsc.caps = DSCAPS_SYSTEMONLY;
585 for (num_bufs = 0; num_bufs < 3; num_bufs++) {
586 if ((res = dfb->CreateSurface( dfb, &dsc, &bufs[num_bufs] )) != DFB_OK) {
587 if (num_bufs == 0) {
588 mp_msg( MSGT_VO, MSGL_ERR,
589 "vo_dfbmga: Can't create surfaces - %s!\n",
590 DirectFBErrorString( res ) );
591 return -1;
593 break;
596 frame = bufs[0];
597 current_buf = 0;
598 current_ip_buf = 0;
599 buf_height = dsc.height;
601 frame->GetPixelFormat( frame, &frame_format );
602 mp_msg( MSGT_VO, MSGL_INFO, "vo_dfbmga: Video surface %dx%d %s\n",
603 in_width, in_height,
604 pixelformat_name( frame_format ) );
608 * BES
610 if (use_bes) {
611 aspect_save_screenres( 0x10000, 0x10000 );
612 aspect( &out_width, &out_height, A_ZOOM );
613 besrect.x = (0x10000 - out_width) * in_width / out_width / 2;
614 besrect.y = (0x10000 - out_height) * in_height / out_height / 2;
615 besrect.w = in_width;
616 besrect.h = in_height;
618 dlc.flags = DLCONF_WIDTH | DLCONF_HEIGHT | DLCONF_PIXELFORMAT | DLCONF_BUFFERMODE;
619 dlc.width = besrect.w + besrect.x * 2;
620 dlc.height = besrect.h + besrect.y * 2;
621 dlc.buffermode = buffermode;
623 if ((res = bes->TestConfiguration( bes, &dlc, &failed )) != DFB_OK) {
624 mp_msg( MSGT_VO, MSGL_ERR,
625 "vo_dfbmga: Invalid BES configuration - %s!\n",
626 DirectFBErrorString( res ) );
627 return -1;
629 if ((res = bes->SetConfiguration( bes, &dlc )) != DFB_OK) {
630 mp_msg( MSGT_VO, MSGL_ERR,
631 "vo_dfbmga: BES configuration failed - %s!\n",
632 DirectFBErrorString( res ) );
633 return -1;
635 bes->GetSurface( bes, &besframe );
636 besframe->SetBlittingFlags( besframe, DSBLIT_NOFX );
638 bes->SetScreenLocation( bes, 0.0, 0.0, 1.0, 1.0 );
640 besframe->Clear( besframe, 0, 0, 0, 0xff );
641 besframe->Flip( besframe, NULL, 0 );
642 besframe->Clear( besframe, 0, 0, 0, 0xff );
643 besframe->Flip( besframe, NULL, 0 );
644 besframe->Clear( besframe, 0, 0, 0, 0xff );
646 mp_msg( MSGT_VO, MSGL_INFO, "vo_dfbmga: BES using %s buffering\n",
647 dlc.buffermode == DLBM_TRIPLE ? "triple" :
648 dlc.buffermode == DLBM_BACKVIDEO ? "double" : "single" );
649 mp_msg( MSGT_VO, MSGL_INFO, "vo_dfbmga: BES surface %dx%d %s\n", dlc.width, dlc.height, pixelformat_name( dlc.pixelformat ) );
653 * CRTC1
655 if (use_crtc1) {
656 dlc.flags = DLCONF_BUFFERMODE;
657 dlc.buffermode = buffermode;
659 if ((res = crtc1->TestConfiguration( crtc1, &dlc, &failed )) != DFB_OK) {
660 mp_msg( MSGT_VO, MSGL_ERR,
661 "vo_dfbmga: Invalid CRTC1 configuration - %s!\n",
662 DirectFBErrorString( res ) );
663 return -1;
665 if ((res = crtc1->SetConfiguration( crtc1, &dlc )) != DFB_OK) {
666 mp_msg( MSGT_VO, MSGL_ERR,
667 "vo_dfbmga: CRTC1 configuration failed - %s!\n",
668 DirectFBErrorString( res ) );
669 return -1;
671 if ((res = crtc1->GetConfiguration( crtc1, &dlc )) != DFB_OK) {
672 mp_msg( MSGT_VO, MSGL_ERR,
673 "vo_dfbmga: Getting CRTC1 configuration failed - %s!\n",
674 DirectFBErrorString( res ) );
675 return -1;
678 crtc1->GetSurface( crtc1, &c1frame );
679 c1frame->SetBlittingFlags( c1frame, DSBLIT_NOFX );
680 c1frame->SetColor( c1frame, 0, 0, 0, 0xff );
682 c1frame->GetSize( c1frame, &screen_width, &screen_height );
684 aspect_save_screenres( screen_width, screen_height );
685 aspect( &out_width, &out_height, (flags & VOFLAG_FULLSCREEN) ? A_ZOOM : A_NOZOOM );
687 if (in_width != out_width || in_height != out_height)
688 c1stretch = 1;
689 else
690 c1stretch = 0;
692 c1rect.x = (screen_width - out_width) / 2;
693 c1rect.y = (screen_height - out_height) / 2;
694 c1rect.w = out_width;
695 c1rect.h = out_height;
697 c1frame->Clear( c1frame, 0, 0, 0, 0xff );
698 c1frame->Flip( c1frame, NULL, 0 );
699 c1frame->Clear( c1frame, 0, 0, 0, 0xff );
700 c1frame->Flip( c1frame, NULL, 0 );
701 c1frame->Clear( c1frame, 0, 0, 0, 0xff );
703 mp_msg( MSGT_VO, MSGL_INFO, "vo_dfbmga: CRTC1 using %s buffering\n",
704 dlc.buffermode == DLBM_TRIPLE ? "triple" :
705 dlc.buffermode == DLBM_BACKVIDEO ? "double" : "single" );
706 mp_msg( MSGT_VO, MSGL_INFO, "vo_dfbmga: CRTC1 surface %dx%d %s\n", screen_width, screen_height, pixelformat_name( dlc.pixelformat ) );
710 * CRTC2
712 if (use_crtc2) {
713 dlc.flags = DLCONF_PIXELFORMAT | DLCONF_BUFFERMODE | DLCONF_OPTIONS;
714 dlc.buffermode = buffermode;
715 dlc.options = DLOP_NONE;
717 if (field_parity != -1) {
718 dlc.options |= DLOP_FIELD_PARITY;
720 mp_msg( MSGT_VO, MSGL_INFO, "vo_dfbmga: Field parity set to: ");
721 switch (field_parity) {
722 case -1:
723 mp_msg( MSGT_VO, MSGL_INFO, "Don't care\n");
724 break;
725 case 0:
726 mp_msg( MSGT_VO, MSGL_INFO, "Top field first\n");
727 break;
728 case 1:
729 mp_msg( MSGT_VO, MSGL_INFO, "Bottom field first\n");
730 break;
733 switch (dlc.pixelformat) {
734 case DSPF_I420:
735 case DSPF_YV12:
736 /* sub-picture supported */
737 break;
739 case DSPF_YUY2:
740 case DSPF_UYVY:
741 /* Blit to YUY2/UYVY not supported */
742 dlc.pixelformat = DSPF_ARGB;
744 /* fall through */
745 default:
746 /* sub-picture not supported */
747 use_spic = 0;
750 if ((res = crtc2->TestConfiguration( crtc2, &dlc, &failed )) != DFB_OK) {
751 mp_msg( MSGT_VO, MSGL_ERR,
752 "vo_dfbmga: Invalid CRTC2 configuration - %s!\n",
753 DirectFBErrorString( res ) );
754 return -1;
756 if ((res = crtc2->SetConfiguration( crtc2, &dlc )) != DFB_OK) {
757 mp_msg( MSGT_VO, MSGL_ERR,
758 "vo_dfbmga: CRTC2 configuration failed - %s!\n",
759 DirectFBErrorString( res ) );
760 return -1;
763 if (field_parity != -1)
764 crtc2->SetFieldParity( crtc2, field_parity );
766 crtc2->GetSurface( crtc2, &c2frame );
767 c2frame->SetBlittingFlags( c2frame, DSBLIT_NOFX );
768 c2frame->SetColor( c2frame, 0, 0, 0, 0xff );
770 c2frame->GetSize( c2frame, &screen_width, &screen_height );
772 /* Don't stretch only slightly smaller videos */
773 if ((in_width > (0.95 * screen_width)) &&
774 (in_width < screen_width))
775 out_width = in_width;
776 else
777 out_width = screen_width;
778 if ((in_height > (0.95 * screen_height)) &&
779 (in_height < screen_height))
780 out_height = in_height;
781 else
782 out_height = screen_height;
784 aspect_save_screenres( out_width, out_height );
785 aspect( &out_width, &out_height, (flags & VOFLAG_FULLSCREEN) ? A_ZOOM : A_NOZOOM );
787 if (in_width != out_width ||
788 in_height != out_height)
789 c2stretch = 1;
790 else
791 c2stretch = 0;
793 c2rect.x = (screen_width - out_width) / 2;
794 c2rect.y = (screen_height - out_height) / 2;
795 c2rect.w = out_width;
796 c2rect.h = out_height;
798 c2frame->Clear( c2frame, 0, 0, 0, 0xff );
799 c2frame->Flip( c2frame, NULL, 0 );
800 c2frame->Clear( c2frame, 0, 0, 0, 0xff );
801 c2frame->Flip( c2frame, NULL, 0 );
802 c2frame->Clear( c2frame, 0, 0, 0, 0xff );
804 mp_msg( MSGT_VO, MSGL_INFO, "vo_dfbmga: CRTC2 using %s buffering\n",
805 dlc.buffermode == DLBM_TRIPLE ? "triple" :
806 dlc.buffermode == DLBM_BACKVIDEO ? "double" : "single" );
807 mp_msg( MSGT_VO, MSGL_INFO, "vo_dfbmga: CRTC2 surface %dx%d %s\n", screen_width, screen_height, pixelformat_name( dlc.pixelformat ) );
808 } else {
809 use_spic = 0;
813 * Sub-picture
815 if (use_spic) {
816 /* Draw OSD to sub-picture surface */
817 IDirectFBPalette *palette;
818 DFBColor color;
819 int i;
820 struct layer_enum l = {
821 "Matrox CRTC2 Sub-Picture",
822 &spic,
823 DFB_UNSUPPORTED
825 dfb->EnumDisplayLayers( dfb, get_layer_by_name, &l );
826 if (l.res != DFB_OK) {
827 mp_msg( MSGT_VO, MSGL_ERR, "vo_dfbmga: Can't get sub-picture layer - %s\n",
828 DirectFBErrorString( l.res ) );
829 return -1;
831 if ((res = spic->SetCooperativeLevel( spic, DLSCL_EXCLUSIVE )) != DFB_OK) {
832 mp_msg( MSGT_VO, MSGL_ERR, "Can't get exclusive access to sub-picture - %s\n",
833 DirectFBErrorString( res ) );
834 return -1;
837 dlc.flags = DLCONF_PIXELFORMAT | DLCONF_BUFFERMODE;
838 dlc.pixelformat = DSPF_ALUT44;
839 dlc.buffermode = buffermode;
840 dlc.flags |= DLCONF_OPTIONS;
841 dlc.options = DLOP_ALPHACHANNEL;
843 if ((res = spic->TestConfiguration( spic, &dlc, &failed )) != DFB_OK) {
844 mp_msg( MSGT_VO, MSGL_ERR,
845 "vo_dfbmga: Invalid sub-picture configuration - %s!\n",
846 DirectFBErrorString( res ) );
847 return -1;
849 if ((res = spic->SetConfiguration( spic, &dlc )) != DFB_OK) {
850 mp_msg( MSGT_VO, MSGL_ERR,
851 "vo_dfbmga: Sub-picture configuration failed - %s!\n",
852 DirectFBErrorString( res ) );
853 return -1;
856 spic->GetSurface( spic, &spicframe );
858 spicframe->GetPalette( spicframe, &palette );
859 color.a = 0xff;
860 for (i = 0; i < 16; i++) {
861 color.r = i * 17;
862 color.g = i * 17;
863 color.b = i * 17;
864 palette->SetEntries( palette, &color, 1, i );
866 palette->Release( palette );
868 spicframe->Clear( spicframe, 0, 0, 0, 0 );
869 spicframe->Flip( spicframe, NULL, 0 );
870 spicframe->Clear( spicframe, 0, 0, 0, 0 );
871 spicframe->Flip( spicframe, NULL, 0 );
872 spicframe->Clear( spicframe, 0, 0, 0, 0 );
874 mp_msg( MSGT_VO, MSGL_INFO, "vo_dfbmga: Sub-picture layer using %s buffering\n",
875 dlc.buffermode == DLBM_TRIPLE ? "triple" :
876 dlc.buffermode == DLBM_BACKVIDEO ? "double" : "single" );
878 subframe = spicframe;
879 subrect = NULL;
880 } else if (use_crtc2) {
881 /* Draw OSD to CRTC2 surface */
882 subframe = c2frame;
883 subrect = &c2rect;
884 } else if (use_crtc1) {
885 /* Draw OSD to CRTC1 surface */
886 subframe = c1frame;
887 subrect = &c1rect;
888 } else {
889 /* Draw OSD to BES surface */
890 subframe = besframe;
891 subrect = &besrect;
894 subframe->GetSize( subframe, &sub_width, &sub_height );
895 subframe->GetPixelFormat( subframe, &subframe_format );
896 mp_msg( MSGT_VO, MSGL_INFO, "vo_dfbmga: Sub-picture surface %dx%d %s (%s)\n",
897 sub_width, sub_height,
898 pixelformat_name( subframe_format ),
899 use_crtc2 ? (use_spic ? "Sub-picture layer" : "CRTC2") :
900 use_crtc1 ? "CRTC1" : "BES" );
902 osd_dirty = 0;
903 osd_current = 1;
904 blit_done = 0;
906 return 0;
909 static int
910 query_format( uint32_t format )
912 switch (format) {
913 case IMGFMT_YV12:
914 case IMGFMT_I420:
915 case IMGFMT_IYUV:
916 if (is_g200 || use_crtc1)
917 return 0;
918 break;
919 case IMGFMT_BGR32:
920 case IMGFMT_BGR16:
921 case IMGFMT_BGR15:
922 if (is_g200 && use_bes)
923 return 0;
924 break;
925 case IMGFMT_UYVY:
926 if (is_g200)
927 return 0;
928 break;
929 case IMGFMT_YUY2:
930 break;
931 case IMGFMT_NV12:
932 case IMGFMT_NV21:
933 if (use_crtc1 || use_crtc2)
934 return 0;
935 break;
936 default:
937 return 0;
940 return VFCAP_HWSCALE_UP |
941 VFCAP_HWSCALE_DOWN |
942 VFCAP_CSP_SUPPORTED_BY_HW |
943 VFCAP_CSP_SUPPORTED |
944 VFCAP_OSD;
947 static void
948 vo_draw_alpha_alut44( int w, int h,
949 unsigned char* src,
950 unsigned char *srca,
951 int srcstride,
952 unsigned char* dst,
953 int dststride )
955 int x;
957 while (h--) {
958 for (x = 0; x < w; x++) {
959 if (srca[x])
960 dst[x] = ((255 - srca[x]) & 0xF0) | (src[x] >> 4);
962 src += srcstride;
963 srca += srcstride;
964 dst += dststride;
968 static void
969 clear_alpha( int x0, int y0,
970 int w, int h )
972 if (use_spic && !flipping && vo_osd_changed_flag)
973 subframe->FillRectangle( subframe, x0, y0, w, h );
976 static void
977 draw_alpha( int x0, int y0,
978 int w, int h,
979 unsigned char *src,
980 unsigned char *srca,
981 int stride )
983 uint8_t *dst;
984 void *ptr;
985 int pitch;
987 if (use_spic) {
988 if (!osd_changed || (!flipping && !vo_osd_changed_flag))
989 return;
990 osd_dirty |= osd_current;
991 } else {
992 if (x0 < subrect->x ||
993 y0 < subrect->y ||
994 x0 + w > subrect->x + subrect->w ||
995 y0 + h > subrect->y + subrect->h)
996 osd_dirty |= osd_current;
999 if (subframe->Lock( subframe, DSLF_READ | DSLF_WRITE, &ptr, &pitch ) != DFB_OK)
1000 return;
1001 dst = ptr;
1003 switch (subframe_format) {
1004 case DSPF_ALUT44:
1005 vo_draw_alpha_alut44( w, h, src, srca, stride,
1006 dst + pitch * y0 + x0,
1007 pitch );
1008 break;
1009 case DSPF_RGB32:
1010 case DSPF_ARGB:
1011 vo_draw_alpha_rgb32( w, h, src, srca, stride,
1012 dst + pitch * y0 + 4 * x0,
1013 pitch );
1014 break;
1015 case DSPF_RGB16:
1016 vo_draw_alpha_rgb16( w, h, src, srca, stride,
1017 dst + pitch * y0 + 2 * x0,
1018 pitch );
1019 break;
1020 case DSPF_ARGB1555:
1021 vo_draw_alpha_rgb15( w, h, src, srca, stride,
1022 dst + pitch * y0 + 2 * x0,
1023 pitch );
1024 break;
1025 case DSPF_YUY2:
1026 vo_draw_alpha_yuy2( w, h, src, srca, stride,
1027 dst + pitch * y0 + 2 * x0,
1028 pitch );
1029 break;
1030 case DSPF_UYVY:
1031 vo_draw_alpha_yuy2( w, h, src, srca, stride,
1032 dst + pitch * y0 + 2 * x0 + 1,
1033 pitch );
1034 break;
1035 case DSPF_NV12:
1036 case DSPF_NV21:
1037 case DSPF_I420:
1038 case DSPF_YV12:
1039 vo_draw_alpha_yv12( w, h, src, srca, stride,
1040 dst + pitch * y0 + x0,
1041 pitch );
1042 break;
1045 subframe->Unlock( subframe );
1048 static int
1049 draw_frame( uint8_t * src[] )
1051 return -1;
1054 static int
1055 draw_slice( uint8_t * src[], int stride[], int w, int h, int x, int y )
1057 uint8_t *dst;
1058 void *ptr;
1059 int pitch;
1061 if (frame->Lock( frame, DSLF_WRITE, &ptr, &pitch ) != DFB_OK)
1062 return VO_FALSE;
1063 dst = ptr;
1065 memcpy_pic( dst + pitch * y + x, src[0],
1066 w, h, pitch, stride[0] );
1068 dst += pitch * buf_height;
1070 y /= 2;
1071 h /= 2;
1073 if (frame_format == DSPF_NV12 || frame_format == DSPF_NV21) {
1074 memcpy_pic( dst + pitch * y + x, src[1],
1075 w, h, pitch, stride[1] );
1076 } else {
1077 x /= 2;
1078 w /= 2;
1079 pitch /= 2;
1081 if (frame_format == DSPF_I420 )
1082 memcpy_pic( dst + pitch * y + x, src[1],
1083 w, h, pitch, stride[1] );
1084 else
1085 memcpy_pic( dst + pitch * y + x, src[2],
1086 w, h, pitch, stride[2] );
1088 dst += pitch * buf_height / 2;
1090 if (frame_format == DSPF_I420 )
1091 memcpy_pic( dst + pitch * y + x, src[2],
1092 w, h, pitch, stride[2] );
1093 else
1094 memcpy_pic( dst + pitch * y + x, src[1],
1095 w, h, pitch, stride[1] );
1098 frame->Unlock( frame );
1100 return VO_TRUE;
1103 static void
1104 blit_to_screen( void )
1106 IDirectFBSurface *blitsrc = frame;
1107 DFBRectangle *srect = NULL;
1109 if (use_bes) {
1110 if (vo_vsync && !flipping)
1111 bes->WaitForSync( bes );
1113 besframe->Blit( besframe, blitsrc, NULL, besrect.x, besrect.y );
1114 blitsrc = besframe;
1115 srect = &besrect;
1118 if (use_crtc1) {
1119 if (vo_vsync && !flipping)
1120 crtc1->WaitForSync( crtc1 );
1122 if (c1stretch)
1123 c1frame->StretchBlit( c1frame, blitsrc, srect, &c1rect );
1124 else
1125 c1frame->Blit( c1frame, blitsrc, srect, c1rect.x, c1rect.y );
1128 if (use_crtc2) {
1129 if (vo_vsync && !flipping)
1130 crtc2->WaitForSync( crtc2 );
1132 if (c2stretch)
1133 c2frame->StretchBlit( c2frame, blitsrc, srect, &c2rect );
1134 else
1135 c2frame->Blit( c2frame, blitsrc, srect, c2rect.x, c2rect.y );
1139 static void
1140 draw_osd( void )
1142 frame = bufs[current_buf];
1143 frame->Unlock( frame );
1145 osd_changed = vo_osd_changed( 0 );
1146 if (osd_dirty & osd_current) {
1147 if (use_spic) {
1148 if (flipping)
1149 subframe->Clear( subframe, 0, 0, 0, 0 );
1150 } else {
1151 /* Clear black bars around the picture */
1152 subframe->FillRectangle( subframe,
1153 0, 0,
1154 sub_width, subrect->y );
1155 subframe->FillRectangle( subframe,
1156 0, subrect->y + subrect->h,
1157 sub_width, subrect->y );
1158 subframe->FillRectangle( subframe,
1159 0, subrect->y,
1160 subrect->x, subrect->h );
1161 subframe->FillRectangle( subframe,
1162 subrect->x + subrect->w, subrect->y,
1163 subrect->x, subrect->h );
1165 osd_dirty &= ~osd_current;
1168 blit_to_screen();
1169 blit_done = 1;
1171 vo_remove_text( sub_width, sub_height, clear_alpha );
1172 vo_draw_text( sub_width, sub_height, draw_alpha );
1174 if (use_spic && flipping && osd_changed) {
1175 subframe->Flip( subframe, NULL, 0 );
1176 osd_current <<= 1;
1177 if (osd_current > osd_max)
1178 osd_current = 1;
1182 static void
1183 flip_page( void )
1185 if (!blit_done)
1186 blit_to_screen();
1188 if (flipping) {
1189 if (use_crtc2)
1190 c2frame->Flip( c2frame, NULL, vo_vsync ? DSFLIP_WAITFORSYNC : DSFLIP_ONSYNC );
1191 if (use_crtc1)
1192 c1frame->Flip( c1frame, NULL, vo_vsync ? DSFLIP_WAITFORSYNC : DSFLIP_ONSYNC );
1193 if (use_bes)
1194 besframe->Flip( besframe, NULL, vo_vsync ? DSFLIP_WAITFORSYNC : DSFLIP_ONSYNC );
1196 if (!use_spic) {
1197 osd_current <<= 1;
1198 if (osd_current > osd_max)
1199 osd_current = 1;
1203 blit_done = 0;
1204 current_buf = 0;
1207 static void
1208 uninit( void )
1210 release_config();
1212 if (buffer)
1213 buffer->Release( buffer );
1214 if (remote)
1215 remote->Release( remote );
1216 if (keyboard)
1217 keyboard->Release( keyboard );
1218 if (crtc2)
1219 crtc2->Release( crtc2 );
1220 if (bes)
1221 bes->Release( bes );
1222 if (crtc1)
1223 crtc1->Release( crtc1 );
1224 if (dfb)
1225 dfb->Release( dfb );
1227 buffer = NULL;
1228 remote = NULL;
1229 keyboard = NULL;
1230 crtc2 = NULL;
1231 bes = NULL;
1232 crtc1 = NULL;
1233 dfb = NULL;
1236 static uint32_t
1237 get_image( mp_image_t *mpi )
1239 int buf = current_buf;
1240 uint8_t *dst;
1241 void *ptr;
1242 int pitch;
1244 if (mpi->flags & MP_IMGFLAG_READABLE &&
1245 (mpi->type == MP_IMGTYPE_IPB || mpi->type == MP_IMGTYPE_IP)) {
1246 if (num_bufs < 2)
1247 return VO_FALSE;
1249 current_ip_buf ^= 1;
1251 if (mpi->type == MP_IMGTYPE_IPB && num_bufs < 3 && current_ip_buf)
1252 return VO_FALSE;
1254 buf = current_ip_buf;
1256 if (mpi->type == MP_IMGTYPE_IPB)
1257 buf++;
1259 frame = bufs[buf];
1260 frame->Unlock( frame );
1262 /* Always use DSLF_READ to preserve system memory copy */
1263 if (frame->Lock( frame, DSLF_WRITE | DSLF_READ,
1264 &ptr, &pitch ) != DFB_OK)
1265 return VO_FALSE;
1266 dst = ptr;
1268 if ((mpi->width == pitch) ||
1269 (mpi->flags & (MP_IMGFLAG_ACCEPT_STRIDE | MP_IMGFLAG_ACCEPT_WIDTH))) {
1271 mpi->planes[0] = dst;
1272 mpi->width = in_width;
1273 mpi->stride[0] = pitch;
1275 if (mpi->flags & MP_IMGFLAG_PLANAR) {
1276 if (mpi->num_planes > 2) {
1277 mpi->stride[1] = mpi->stride[2] = pitch / 2;
1279 if (mpi->flags & MP_IMGFLAG_SWAPPED) {
1280 /* I420 */
1281 mpi->planes[1] = dst + buf_height * pitch;
1282 mpi->planes[2] = mpi->planes[1] + buf_height * pitch / 4;
1283 } else {
1284 /* YV12 */
1285 mpi->planes[2] = dst + buf_height * pitch;
1286 mpi->planes[1] = mpi->planes[2] + buf_height * pitch / 4;
1288 } else {
1289 /* NV12/NV21 */
1290 mpi->stride[1] = pitch;
1291 mpi->planes[1] = dst + buf_height * pitch;
1295 mpi->flags |= MP_IMGFLAG_DIRECT;
1296 mpi->priv = (void *) buf;
1297 current_buf = buf;
1299 return VO_TRUE;
1302 frame->Unlock( frame );
1304 return VO_FALSE;
1309 static uint32_t
1310 draw_image( mp_image_t *mpi )
1312 if (mpi->flags & MP_IMGFLAG_DIRECT) {
1313 current_buf = (int) mpi->priv;
1314 return VO_TRUE;
1316 if (mpi->flags & MP_IMGFLAG_DRAW_CALLBACK)
1317 return VO_TRUE;
1319 if (mpi->flags & MP_IMGFLAG_PLANAR)
1320 return draw_slice( mpi->planes, mpi->stride,
1321 mpi->w, mpi->h, 0, 0 );
1322 else {
1323 void *dst;
1324 int pitch;
1326 if (frame->Lock( frame, DSLF_WRITE, &dst, &pitch ) != DFB_OK)
1327 return VO_FALSE;
1328 memcpy_pic( dst, mpi->planes[0],
1329 mpi->w * (mpi->bpp / 8), mpi->h,
1330 pitch, mpi->stride[0] );
1331 frame->Unlock( frame );
1333 return VO_TRUE;
1337 static int
1338 set_equalizer( const char *data, int value )
1340 DFBResult res;
1341 DFBColorAdjustment ca;
1342 float factor = (float) 0xffff / 200.0;
1344 ca.flags = DCAF_NONE;
1346 if (!strcasecmp( data, "brightness" )) {
1347 ca.flags |= DCAF_BRIGHTNESS;
1348 ca.brightness = value * factor + 0x8000;
1350 if (!strcasecmp( data, "contrast" )) {
1351 ca.flags |= DCAF_CONTRAST;
1352 ca.contrast = value * factor + 0x8000;
1354 if (!strcasecmp( data, "hue" )) {
1355 ca.flags |= DCAF_HUE;
1356 ca.hue = value * factor + 0x8000;
1358 if (!strcasecmp( data, "saturation" )) {
1359 ca.flags |= DCAF_SATURATION;
1360 ca.saturation = value * factor + 0x8000;
1363 /* Prefer CRTC2 over BES */
1364 if (use_crtc2)
1365 res = crtc2->SetColorAdjustment( crtc2, &ca );
1366 else if (use_crtc1)
1367 res = crtc1->SetColorAdjustment( crtc1, &ca );
1368 else
1369 res = bes->SetColorAdjustment( bes, &ca );
1371 if (res != DFB_OK)
1372 return VO_FALSE;
1374 return VO_TRUE;
1377 static int
1378 get_equalizer( const char *data, int *value )
1380 DFBResult res;
1381 DFBColorAdjustment ca;
1382 float factor = 200.0 / (float) 0xffff;
1384 /* Prefer CRTC2 over BES */
1385 if (use_crtc2)
1386 res = crtc2->GetColorAdjustment( crtc2, &ca );
1387 else if (use_crtc1)
1388 res = crtc1->GetColorAdjustment( crtc1, &ca );
1389 else
1390 res = bes->GetColorAdjustment( bes, &ca );
1392 if (res != DFB_OK)
1393 return VO_FALSE;
1395 if (!strcasecmp( data, "brightness" ) &&
1396 (ca.flags & DCAF_BRIGHTNESS))
1397 *value = (ca.brightness - 0x8000) * factor;
1398 if (!strcasecmp( data, "contrast" ) &&
1399 (ca.flags & DCAF_CONTRAST))
1400 *value = (ca.contrast - 0x8000) * factor;
1401 if (!strcasecmp( data, "hue" ) &&
1402 (ca.flags & DCAF_HUE))
1403 *value = (ca.hue - 0x8000) * factor;
1404 if (!strcasecmp( data, "saturation" ) &&
1405 (ca.flags & DCAF_SATURATION))
1406 *value = (ca.saturation - 0x8000) * factor;
1408 return VO_TRUE;
1411 static int
1412 control( uint32_t request, void *data)
1414 switch (request) {
1415 case VOCTRL_QUERY_FORMAT:
1416 return query_format( *((uint32_t *) data) );
1418 case VOCTRL_GET_IMAGE:
1419 return get_image( data );
1421 case VOCTRL_DRAW_IMAGE:
1422 return draw_image( data );
1424 case VOCTRL_SET_EQUALIZER:
1426 struct voctrl_set_equalizer_args *args = data;
1427 return set_equalizer(args->name, args->value);
1429 case VOCTRL_GET_EQUALIZER:
1431 struct voctrl_get_equalizer_args *args = data;
1432 return get_equalizer(args->name, args->valueptr);
1436 return VO_NOTIMPL;
1439 static void
1440 check_events( void )
1442 DFBInputEvent event;
1444 if (!buffer)
1445 return;
1447 if (buffer->GetEvent( buffer, DFB_EVENT( &event )) == DFB_OK) {
1448 if (event.type == DIET_KEYPRESS) {
1449 switch (event.key_symbol) {
1450 case DIKS_ESCAPE:
1451 mplayer_put_key( KEY_ESC );
1452 break;
1453 case DIKS_PAGE_UP:
1454 mplayer_put_key( KEY_PAGE_UP );
1455 break;
1456 case DIKS_PAGE_DOWN:
1457 mplayer_put_key( KEY_PAGE_DOWN );
1458 break;
1459 case DIKS_CURSOR_UP:
1460 mplayer_put_key( KEY_UP );
1461 break;
1462 case DIKS_CURSOR_DOWN:
1463 mplayer_put_key( KEY_DOWN );
1464 break;
1465 case DIKS_CURSOR_LEFT:
1466 mplayer_put_key( KEY_LEFT );
1467 break;
1468 case DIKS_CURSOR_RIGHT:
1469 mplayer_put_key( KEY_RIGHT );
1470 break;
1471 case DIKS_INSERT:
1472 mplayer_put_key( KEY_INSERT );
1473 break;
1474 case DIKS_DELETE:
1475 mplayer_put_key( KEY_DELETE );
1476 break;
1477 case DIKS_HOME:
1478 mplayer_put_key( KEY_HOME );
1479 break;
1480 case DIKS_END:
1481 mplayer_put_key( KEY_END );
1482 break;
1484 case DIKS_POWER:
1485 mplayer_put_key( KEY_POWER );
1486 break;
1487 case DIKS_MENU:
1488 mplayer_put_key( KEY_MENU );
1489 break;
1490 case DIKS_PLAY:
1491 mplayer_put_key( KEY_PLAY );
1492 break;
1493 case DIKS_STOP:
1494 mplayer_put_key( KEY_STOP );
1495 break;
1496 case DIKS_PAUSE:
1497 mplayer_put_key( KEY_PAUSE );
1498 break;
1499 case DIKS_PLAYPAUSE:
1500 mplayer_put_key( KEY_PLAYPAUSE );
1501 break;
1502 case DIKS_FORWARD:
1503 mplayer_put_key( KEY_FORWARD );
1504 break;
1505 case DIKS_NEXT:
1506 mplayer_put_key( KEY_NEXT );
1507 break;
1508 case DIKS_REWIND:
1509 mplayer_put_key( KEY_REWIND );
1510 break;
1511 case DIKS_PREVIOUS:
1512 mplayer_put_key( KEY_PREV );
1513 break;
1514 case DIKS_VOLUME_UP:
1515 mplayer_put_key( KEY_VOLUME_UP );
1516 break;
1517 case DIKS_VOLUME_DOWN:
1518 mplayer_put_key( KEY_VOLUME_DOWN );
1519 break;
1520 case DIKS_MUTE:
1521 mplayer_put_key( KEY_MUTE );
1522 break;
1524 default:
1525 mplayer_put_key( event.key_symbol );
1531 * empty buffer, because of repeating
1532 * keyboard repeat is faster than key handling and this causes problems during seek
1533 * temporary workabout. should be solved in the future
1535 buffer->Reset( buffer );