Merge svn changes up to r27441
[mplayer.git] / libvo / vo_dfbmga.c
blobfac15a46dd46d5738367a0ea98f1607e90d7a20d
1 /*
2 MPlayer video driver for DirectFB / Matrox G200/G400/G450/G550
4 Copyright (C) 2002-2005 Ville Syrjala <syrjala@sci.fi>
6 Originally based on vo_directfb.c by
7 Jiri Svoboda <Jiri.Svoboda@seznam.cz>
9 This library 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 of the License, or (at your option) any later version.
14 This library 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
20 License along with this library; if not, write to the
21 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
22 Boston, MA 02110-1301 USA.
25 /* directfb includes */
26 #include <directfb.h>
28 #define DFB_VERSION(a,b,c) (((a)<<16)|((b)<<8)|(c))
30 /* other things */
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
35 #include "config.h"
36 #include "video_out.h"
37 #include "video_out_internal.h"
38 #include "fastmemcpy.h"
39 #include "sub.h"
40 #include "mp_msg.h"
41 #include "aspect.h"
42 #include "mp_fifo.h"
44 static const vo_info_t info = {
45 "DirectFB / Matrox G200/G400/G450/G550",
46 "dfbmga",
47 "Ville Syrjala <syrjala@sci.fi>",
51 const LIBVO_EXTERN(dfbmga)
53 /******************************
54 * directfb *
55 ******************************/
58 * (Globals)
60 static IDirectFB *dfb;
62 static IDirectFBDisplayLayer *primary;
63 static IDirectFBDisplayLayer *bes;
64 static IDirectFBDisplayLayer *crtc2;
65 static IDirectFBDisplayLayer *spic;
67 static int num_bufs;
68 static int current_buf;
69 static int current_ip_buf;
70 static IDirectFBSurface *bufs[3];
72 static IDirectFBSurface *frame;
73 static IDirectFBSurface *subframe;
75 static IDirectFBSurface *besframe;
76 static IDirectFBSurface *c2frame;
77 static IDirectFBSurface *spicframe;
79 static DFBSurfacePixelFormat frame_format;
80 static DFBSurfacePixelFormat subframe_format;
82 static DFBRectangle besrect;
83 static DFBRectangle c2rect;
84 static DFBRectangle *subrect;
86 static IDirectFBInputDevice *keyboard;
87 static IDirectFBInputDevice *remote;
88 static IDirectFBEventBuffer *buffer;
90 static int blit_done;
91 static int stretch;
93 static int use_bes;
94 static int use_crtc2;
95 static int use_spic;
96 static int use_input;
97 static int use_remote;
98 static int field_parity;
99 static int flipping;
100 static DFBDisplayLayerBufferMode buffermode;
101 static int tvnorm;
103 static int osd_changed;
104 static int osd_dirty;
105 static int osd_current;
106 static int osd_max;
108 static int is_g200;
110 /******************************
111 * vo_dfbmga *
112 ******************************/
114 #if DIRECTFBVERSION < DFB_VERSION(0,9,18)
115 #define DSPF_ALUT44 DSPF_LUT8
116 #define DLBM_TRIPLE ~0
117 #define DSFLIP_ONSYNC 0
118 #endif
120 #if DIRECTFBVERSION < DFB_VERSION(0,9,16)
121 #define DSPF_ARGB1555 DSPF_RGB15
122 #endif
124 static uint32_t in_width;
125 static uint32_t in_height;
126 static uint32_t buf_height;
127 static uint32_t screen_width;
128 static uint32_t screen_height;
129 static uint32_t sub_width;
130 static uint32_t sub_height;
132 static char *
133 pixelformat_name( DFBSurfacePixelFormat format )
135 switch(format) {
136 case DSPF_ARGB:
137 return "ARGB";
138 case DSPF_RGB32:
139 return "RGB32";
140 case DSPF_RGB24:
141 return "RGB24";
142 case DSPF_RGB16:
143 return "RGB16";
144 case DSPF_ARGB1555:
145 return "ARGB1555";
146 case DSPF_YUY2:
147 return "YUY2";
148 case DSPF_UYVY:
149 return "UYVY";
150 case DSPF_YV12:
151 return "YV12";
152 case DSPF_I420:
153 return "I420";
154 case DSPF_ALUT44:
155 return "ALUT44";
156 #if DIRECTFBVERSION > DFB_VERSION(0,9,21)
157 case DSPF_NV12:
158 return "NV12";
159 case DSPF_NV21:
160 return "NV21";
161 #endif
162 default:
163 return "Unknown pixel format";
167 static DFBSurfacePixelFormat
168 imgfmt_to_pixelformat( uint32_t format )
170 switch (format) {
171 case IMGFMT_BGR32:
172 return DSPF_RGB32;
173 case IMGFMT_BGR24:
174 return DSPF_RGB24;
175 case IMGFMT_BGR16:
176 return DSPF_RGB16;
177 case IMGFMT_BGR15:
178 return DSPF_ARGB1555;
179 case IMGFMT_YUY2:
180 return DSPF_YUY2;
181 case IMGFMT_UYVY:
182 return DSPF_UYVY;
183 case IMGFMT_YV12:
184 return DSPF_YV12;
185 case IMGFMT_I420:
186 case IMGFMT_IYUV:
187 return DSPF_I420;
188 #if DIRECTFBVERSION > DFB_VERSION(0,9,21)
189 case IMGFMT_NV12:
190 return DSPF_NV12;
191 case IMGFMT_NV21:
192 return DSPF_NV21;
193 #endif
194 default:
195 return DSPF_UNKNOWN;
199 struct layer_enum
201 const char *name;
202 IDirectFBDisplayLayer **layer;
203 DFBResult res;
206 static DFBEnumerationResult
207 get_layer_by_name( DFBDisplayLayerID id,
208 DFBDisplayLayerDescription desc,
209 void *data )
211 struct layer_enum *l = (struct layer_enum *) data;
213 #if DIRECTFBVERSION > DFB_VERSION(0,9,15)
214 /* We have desc.name so use it */
215 if (!strcmp( l->name, desc.name ))
216 if ((l->res = dfb->GetDisplayLayer( dfb, id, l->layer )) == DFB_OK)
217 return DFENUM_CANCEL;
218 #else
219 /* Fake it according to id */
220 if ((id == 0 && !strcmp( l->name, "FBDev Primary Layer" )) ||
221 (id == 1 && !strcmp( l->name, "Matrox Backend Scaler" )) ||
222 (id == 2 && !strcmp( l->name, "Matrox CRTC2" )) ||
223 (id == 3 && !strcmp( l->name, "Matrox CRTC2 Sub-Picture" )))
224 if ((l->res = dfb->GetDisplayLayer( dfb, id, l->layer )) == DFB_OK)
225 return DFENUM_CANCEL;
226 #endif
228 return DFENUM_OK;
231 static int
232 preinit( const char *arg )
234 DFBResult res;
235 int force_input = -1;
237 /* Some defaults */
238 use_bes = 0;
239 use_crtc2 = 1;
240 use_spic = 1;
241 field_parity = -1;
242 #if DIRECTFBVERSION > DFB_VERSION(0,9,17)
243 buffermode = DLBM_TRIPLE;
244 osd_max = 4;
245 #else
246 buffermode = DLBM_BACKVIDEO;
247 osd_max = 2;
248 #endif
249 flipping = 1;
250 tvnorm = -1;
252 use_input = !getenv( "DISPLAY" );
254 if (vo_subdevice) {
255 int show_help = 0;
256 int opt_no = 0;
257 while (*vo_subdevice != '\0') {
258 if (!strncmp(vo_subdevice, "bes", 3)) {
259 use_bes = !opt_no;
260 vo_subdevice += 3;
261 opt_no = 0;
262 } else if (!strncmp(vo_subdevice, "crtc2", 5)) {
263 use_crtc2 = !opt_no;
264 vo_subdevice += 5;
265 opt_no = 0;
266 } else if (!strncmp(vo_subdevice, "spic", 4)) {
267 use_spic = !opt_no;
268 vo_subdevice += 4;
269 opt_no = 0;
270 } else if (!strncmp(vo_subdevice, "input", 5)) {
271 force_input = !opt_no;
272 vo_subdevice += 5;
273 opt_no = 0;
274 } else if (!strncmp(vo_subdevice, "remote", 6)) {
275 use_remote = !opt_no;
276 vo_subdevice += 6;
277 opt_no = 0;
278 } else if (!strncmp(vo_subdevice, "buffermode=", 11)) {
279 if (opt_no) {
280 show_help = 1;
281 break;
283 vo_subdevice += 11;
284 if (!strncmp(vo_subdevice, "single", 6)) {
285 buffermode = DLBM_FRONTONLY;
286 osd_max = 1;
287 flipping = 0;
288 vo_subdevice += 6;
289 } else if (!strncmp(vo_subdevice, "double", 6)) {
290 buffermode = DLBM_BACKVIDEO;
291 osd_max = 2;
292 flipping = 1;
293 vo_subdevice += 6;
294 } else if (!strncmp(vo_subdevice, "triple", 6)) {
295 buffermode = DLBM_TRIPLE;
296 osd_max = 4;
297 flipping = 1;
298 vo_subdevice += 6;
299 } else {
300 show_help = 1;
301 break;
303 opt_no = 0;
304 } else if (!strncmp(vo_subdevice, "fieldparity=", 12)) {
305 if (opt_no) {
306 show_help = 1;
307 break;
309 vo_subdevice += 12;
310 if (!strncmp(vo_subdevice, "top", 3)) {
311 field_parity = 0;
312 vo_subdevice += 3;
313 } else if (!strncmp(vo_subdevice, "bottom", 6)) {
314 field_parity = 1;
315 vo_subdevice += 6;
316 } else {
317 show_help = 1;
318 break;
320 opt_no = 0;
321 } else if (!strncmp(vo_subdevice, "tvnorm=", 7)) {
322 if (opt_no) {
323 show_help = 1;
324 break;
326 vo_subdevice += 7;
327 if (!strncmp(vo_subdevice, "pal", 3)) {
328 tvnorm = 0;
329 vo_subdevice += 3;
330 } else if (!strncmp(vo_subdevice, "ntsc" , 4)) {
331 tvnorm = 1;
332 vo_subdevice += 4;
333 } else if (!strncmp(vo_subdevice, "auto" , 4)) {
334 tvnorm = 2;
335 vo_subdevice += 4;
336 } else {
337 show_help = 1;
338 break;
340 opt_no = 0;
341 } else if (!strncmp(vo_subdevice, "no", 2)) {
342 if (opt_no) {
343 show_help = 1;
344 break;
346 vo_subdevice += 2;
347 opt_no = 1;
348 } else if (*vo_subdevice == ':') {
349 if (opt_no) {
350 show_help = 1;
351 break;
353 vo_subdevice++;
354 opt_no = 0;
355 } else {
356 show_help = 1;
357 break;
360 if (show_help) {
361 mp_msg( MSGT_VO, MSGL_ERR,
362 "\nvo_dfbmga command line help:\n"
363 "Example: mplayer -vo dfbmga:nocrtc2:bes:buffermode=single\n"
364 "\nOptions (use 'no' prefix to disable):\n"
365 " bes Use Backend Scaler\n"
366 " crtc2 Use CRTC2\n"
367 " spic Use hardware sub-picture for OSD\n"
368 " input Use DirectFB for keyboard input\n"
369 " remote Use DirectFB for remote control input\n"
370 "\nOther options:\n"
371 " buffermode=(single|double|triple)\n"
372 " single Use single buffering\n"
373 " double Use double buffering\n"
374 " triple Use triple buffering\n"
375 " fieldparity=(top|bottom)\n"
376 " top Top field first\n"
377 " bottom Bottom field first\n"
378 " tvnorm=(pal|ntsc|auto)\n"
379 " pal Force PAL\n"
380 " ntsc Force NTSC\n"
381 " auto Select according to FPS\n"
382 "\n" );
383 return -1;
386 if (!use_bes && !use_crtc2) {
387 mp_msg( MSGT_VO, MSGL_ERR, "vo_dfbmga: No output selected\n" );
388 return -1;
391 if ((res = DirectFBInit( NULL, NULL )) != DFB_OK) {
392 mp_msg( MSGT_VO, MSGL_ERR,
393 "vo_dfbmga: DirectFBInit() failed - %s\n",
394 DirectFBErrorString( res ) );
395 return -1;
398 switch (tvnorm) {
399 case 0:
400 DirectFBSetOption( "matrox-tv-standard", "pal" );
401 mp_msg( MSGT_VO, MSGL_INFO, "vo_dfbmga: Forced TV standard to PAL\n" );
402 break;
403 case 1:
404 DirectFBSetOption( "matrox-tv-standard", "ntsc" );
405 mp_msg( MSGT_VO, MSGL_INFO, "vo_dfbmga: Forced TV standard to NTSC\n" );
406 break;
407 case 2:
408 if (vo_fps > 27) {
409 DirectFBSetOption( "matrox-tv-standard", "ntsc" );
410 mp_msg( MSGT_VO, MSGL_INFO,
411 "vo_dfbmga: Selected TV standard based upon FPS: NTSC\n" );
412 } else {
413 DirectFBSetOption( "matrox-tv-standard", "pal" );
414 mp_msg( MSGT_VO, MSGL_INFO,
415 "vo_dfbmga: Selected TV standard based upon FPS: PAL\n" );
417 break;
420 if ((res = DirectFBCreate( &dfb )) != DFB_OK) {
421 mp_msg( MSGT_VO, MSGL_ERR,
422 "vo_dfbmga: DirectFBCreate() failed - %s\n",
423 DirectFBErrorString( res ) );
424 return -1;
427 if (use_bes) {
428 struct layer_enum l = {
429 "FBDev Primary Layer",
430 &primary,
431 DFB_UNSUPPORTED
433 dfb->EnumDisplayLayers( dfb, get_layer_by_name, &l );
434 if (l.res != DFB_OK) {
435 mp_msg( MSGT_VO, MSGL_ERR, "vo_dfbmga: Can't get primary layer - %s\n",
436 DirectFBErrorString( l.res ) );
437 uninit();
438 return -1;
440 if ((res = primary->SetCooperativeLevel( primary, DLSCL_EXCLUSIVE )) != DFB_OK) {
441 mp_msg( MSGT_VO, MSGL_ERR, "Can't get exclusive access to primary layer - %s\n",
442 DirectFBErrorString( res ) );
443 uninit();
444 return -1;
446 use_input = 1;
449 if (force_input != -1)
450 use_input = force_input;
452 if (use_bes) {
453 DFBDisplayLayerConfig dlc;
454 DFBDisplayLayerConfigFlags failed;
455 struct layer_enum l = {
456 "Matrox Backend Scaler",
457 &bes,
458 DFB_UNSUPPORTED
461 dfb->EnumDisplayLayers( dfb, get_layer_by_name, &l );
462 if (l.res != DFB_OK) {
463 mp_msg( MSGT_VO, MSGL_ERR, "Can't get BES layer - %s\n",
464 DirectFBErrorString( l.res ) );
465 uninit();
466 return -1;
468 if ((res = bes->SetCooperativeLevel( bes, DLSCL_EXCLUSIVE )) != DFB_OK) {
469 mp_msg( MSGT_VO, MSGL_ERR, "Can't get exclusive access to BES - %s\n",
470 DirectFBErrorString( res ) );
471 uninit();
472 return -1;
474 dlc.flags = DLCONF_PIXELFORMAT;
475 dlc.pixelformat = DSPF_RGB16;
476 if (bes->TestConfiguration( bes, &dlc, &failed ) != DFB_OK) {
477 is_g200 = 1;
478 use_crtc2 = 0;
482 if (use_crtc2) {
483 struct layer_enum l = {
484 #if DIRECTFBVERSION > DFB_VERSION(0,9,20)
485 "Matrox CRTC2 Layer",
486 #else
487 "Matrox CRTC2",
488 #endif
489 &crtc2,
490 DFB_UNSUPPORTED
493 dfb->EnumDisplayLayers( dfb, get_layer_by_name, &l );
494 if (l.res != DFB_OK) {
495 mp_msg( MSGT_VO, MSGL_ERR, "Can't get CRTC2 layer - %s\n",
496 DirectFBErrorString( l.res ) );
497 uninit();
498 return -1;
500 if ((res = crtc2->SetCooperativeLevel( crtc2, DLSCL_EXCLUSIVE )) != DFB_OK) {
501 mp_msg( MSGT_VO, MSGL_ERR, "Can't get exclusive access to CRTC2 - %s\n",
502 DirectFBErrorString( res ) );
503 uninit();
504 return -1;
508 if (use_input || use_remote) {
509 if ((res = dfb->CreateEventBuffer( dfb, &buffer )) != DFB_OK) {
510 mp_msg( MSGT_VO, MSGL_ERR,
511 "vo_dfbmga: Can't create event buffer - %s\n",
512 DirectFBErrorString( res ) );
513 uninit();
514 return -1;
518 if (use_input) {
519 if ((res = dfb->GetInputDevice( dfb, DIDID_KEYBOARD, &keyboard )) != DFB_OK) {
520 mp_msg( MSGT_VO, MSGL_ERR,
521 "vo_dfbmga: Can't get keyboard - %s\n",
522 DirectFBErrorString( res ) );
523 uninit();
524 return -1;
526 if ((res = keyboard->AttachEventBuffer( keyboard, buffer )) != DFB_OK) {
527 mp_msg( MSGT_VO, MSGL_ERR,
528 "vo_dfbmga: Can't attach event buffer to keyboard - %s\n",
529 DirectFBErrorString( res ) );
530 uninit();
531 return -1;
534 if (use_remote) {
535 if ((res = dfb->GetInputDevice( dfb, DIDID_REMOTE, &remote )) != DFB_OK) {
536 mp_msg( MSGT_VO, MSGL_ERR,
537 "vo_dfbmga: Can't get remote control - %s\n",
538 DirectFBErrorString( res ) );
539 uninit();
540 return -1;
542 if ((res = remote->AttachEventBuffer( remote, buffer )) != DFB_OK) {
543 mp_msg( MSGT_VO, MSGL_ERR,
544 "vo_dfbmga: Can't attach event buffer to remote control - %s\n",
545 DirectFBErrorString( res ) );
546 uninit();
547 return -1;
551 return 0;
554 static void release_config( void )
556 if (spicframe)
557 spicframe->Release( spicframe );
558 if (spic)
559 spic->Release( spic );
560 if (c2frame)
561 c2frame->Release( c2frame );
562 if (besframe)
563 besframe->Release( besframe );
564 if (bufs[0])
565 bufs[0]->Release( bufs[0] );
566 if (bufs[1])
567 bufs[1]->Release( bufs[1] );
568 if (bufs[2])
569 bufs[2]->Release( bufs[2] );
571 spicframe = NULL;
572 spic = NULL;
573 c2frame = NULL;
574 besframe = NULL;
575 bufs[0] = NULL;
576 bufs[1] = NULL;
577 bufs[2] = NULL;
580 static int
581 config( uint32_t width, uint32_t height,
582 uint32_t d_width, uint32_t d_height,
583 uint32_t flags,
584 char *title,
585 uint32_t format )
587 DFBResult res;
589 DFBDisplayLayerConfig dlc;
590 DFBDisplayLayerConfigFlags failed;
592 uint32_t out_width;
593 uint32_t out_height;
595 release_config();
597 in_width = width;
598 in_height = height;
600 aspect_save_orig(width, height);
601 aspect_save_prescale(d_width, d_height);
603 dlc.pixelformat = imgfmt_to_pixelformat( format );
606 /* Draw to a temporary surface */
607 DFBSurfaceDescription dsc;
609 dsc.flags = DSDESC_WIDTH | DSDESC_HEIGHT |
610 DSDESC_PIXELFORMAT;
611 dsc.width = (in_width + 15) & ~15;
612 dsc.height = (in_height + 15) & ~15;
613 dsc.pixelformat = dlc.pixelformat;
615 /* Don't waste video memory since we don't need direct stretchblit */
616 if (use_bes) {
617 dsc.flags |= DSDESC_CAPS;
618 dsc.caps = DSCAPS_SYSTEMONLY;
621 for (num_bufs = 0; num_bufs < 3; num_bufs++) {
622 if ((res = dfb->CreateSurface( dfb, &dsc, &bufs[num_bufs] )) != DFB_OK) {
623 if (num_bufs == 0) {
624 mp_msg( MSGT_VO, MSGL_ERR,
625 "vo_dfbmga: Can't create surfaces - %s!\n",
626 DirectFBErrorString( res ) );
627 return -1;
629 break;
632 frame = bufs[0];
633 current_buf = 0;
634 current_ip_buf = 0;
635 buf_height = dsc.height;
637 frame->GetPixelFormat( frame, &frame_format );
638 mp_msg( MSGT_VO, MSGL_INFO, "vo_dfbmga: Video surface %dx%d %s\n",
639 in_width, in_height,
640 pixelformat_name( frame_format ) );
644 * BES
646 if (use_bes) {
647 aspect_save_screenres( 0x10000, 0x10000 );
648 aspect( &out_width, &out_height, A_ZOOM );
649 besrect.x = (0x10000 - out_width) * in_width / out_width / 2;
650 besrect.y = (0x10000 - out_height) * in_height / out_height / 2;
651 besrect.w = in_width;
652 besrect.h = in_height;
654 dlc.flags = DLCONF_WIDTH | DLCONF_HEIGHT | DLCONF_PIXELFORMAT | DLCONF_BUFFERMODE;
655 dlc.width = besrect.w + besrect.x * 2;
656 dlc.height = besrect.h + besrect.y * 2;
658 if (use_crtc2)
659 dlc.buffermode = DLBM_FRONTONLY;
660 else
661 dlc.buffermode = buffermode;
663 if ((res = bes->TestConfiguration( bes, &dlc, &failed )) != DFB_OK) {
664 mp_msg( MSGT_VO, MSGL_ERR,
665 "vo_dfbmga: Invalid BES configuration - %s!\n",
666 DirectFBErrorString( res ) );
667 return -1;
669 if ((res = bes->SetConfiguration( bes, &dlc )) != DFB_OK) {
670 mp_msg( MSGT_VO, MSGL_ERR,
671 "vo_dfbmga: BES configuration failed - %s!\n",
672 DirectFBErrorString( res ) );
673 return -1;
675 bes->GetSurface( bes, &besframe );
676 besframe->SetBlittingFlags( besframe, DSBLIT_NOFX );
678 bes->SetScreenLocation( bes, 0.0, 0.0, 1.0, 1.0 );
680 besframe->Clear( besframe, 0, 0, 0, 0xff );
681 besframe->Flip( besframe, NULL, 0 );
682 besframe->Clear( besframe, 0, 0, 0, 0xff );
683 besframe->Flip( besframe, NULL, 0 );
684 besframe->Clear( besframe, 0, 0, 0, 0xff );
686 mp_msg( MSGT_VO, MSGL_INFO, "vo_dfbmga: BES using %s buffering\n",
687 dlc.buffermode == DLBM_TRIPLE ? "triple" :
688 dlc.buffermode == DLBM_BACKVIDEO ? "double" : "single" );
689 mp_msg( MSGT_VO, MSGL_INFO, "vo_dfbmga: BES surface %dx%d %s\n", dlc.width, dlc.height, pixelformat_name( dlc.pixelformat ) );
693 * CRTC2
695 if (use_crtc2) {
696 dlc.flags = DLCONF_PIXELFORMAT | DLCONF_BUFFERMODE | DLCONF_OPTIONS;
697 dlc.buffermode = buffermode;
698 dlc.options = DLOP_NONE;
700 #if DIRECTFBVERSION > DFB_VERSION(0,9,16)
701 if (field_parity != -1) {
702 dlc.options |= DLOP_FIELD_PARITY;
704 #endif
705 mp_msg( MSGT_VO, MSGL_INFO, "vo_dfbmga: Field parity set to: ");
706 switch (field_parity) {
707 case -1:
708 mp_msg( MSGT_VO, MSGL_INFO, "Don't care\n");
709 break;
710 case 0:
711 mp_msg( MSGT_VO, MSGL_INFO, "Top field first\n");
712 break;
713 case 1:
714 mp_msg( MSGT_VO, MSGL_INFO, "Bottom field first\n");
715 break;
718 switch (dlc.pixelformat) {
719 case DSPF_I420:
720 case DSPF_YV12:
721 /* sub-picture supported */
722 break;
724 case DSPF_YUY2:
725 case DSPF_UYVY:
726 /* Blit to YUY2/UYVY not supported */
727 dlc.pixelformat = DSPF_ARGB;
729 /* fall through */
730 default:
731 /* sub-picture not supported */
732 use_spic = 0;
735 if ((res = crtc2->TestConfiguration( crtc2, &dlc, &failed )) != DFB_OK) {
736 mp_msg( MSGT_VO, MSGL_ERR,
737 "vo_dfbmga: Invalid CRTC2 configuration - %s!\n",
738 DirectFBErrorString( res ) );
739 return -1;
741 if ((res = crtc2->SetConfiguration( crtc2, &dlc )) != DFB_OK) {
742 mp_msg( MSGT_VO, MSGL_ERR,
743 "vo_dfbmga: CRTC2 configuration failed - %s!\n",
744 DirectFBErrorString( res ) );
745 return -1;
748 #if DIRECTFBVERSION > DFB_VERSION(0,9,16)
749 if (field_parity != -1)
750 crtc2->SetFieldParity( crtc2, field_parity );
751 #endif
753 crtc2->GetSurface( crtc2, &c2frame );
754 c2frame->SetBlittingFlags( c2frame, DSBLIT_NOFX );
755 c2frame->SetColor( c2frame, 0, 0, 0, 0xff );
757 c2frame->GetSize( c2frame, &screen_width, &screen_height );
759 /* Don't stretch only slightly smaller videos */
760 if ((in_width > (0.95 * screen_width)) &&
761 (in_width < screen_width))
762 out_width = in_width;
763 else
764 out_width = screen_width;
765 if ((in_height > (0.95 * screen_height)) &&
766 (in_height < screen_height))
767 out_height = in_height;
768 else
769 out_height = screen_height;
771 aspect_save_screenres( out_width, out_height );
772 aspect( &out_width, &out_height, (flags & VOFLAG_FULLSCREEN) ? A_ZOOM : A_NOZOOM );
774 if (in_width != out_width ||
775 in_height != out_height)
776 stretch = 1;
777 else
778 stretch = 0;
780 c2rect.x = (screen_width - out_width) / 2;
781 c2rect.y = (screen_height - out_height) / 2;
782 c2rect.w = out_width;
783 c2rect.h = out_height;
785 c2frame->Clear( c2frame, 0, 0, 0, 0xff );
786 c2frame->Flip( c2frame, NULL, 0 );
787 c2frame->Clear( c2frame, 0, 0, 0, 0xff );
788 c2frame->Flip( c2frame, NULL, 0 );
789 c2frame->Clear( c2frame, 0, 0, 0, 0xff );
791 mp_msg( MSGT_VO, MSGL_INFO, "vo_dfbmga: CRTC2 using %s buffering\n",
792 dlc.buffermode == DLBM_TRIPLE ? "triple" :
793 dlc.buffermode == DLBM_BACKVIDEO ? "double" : "single" );
794 mp_msg( MSGT_VO, MSGL_INFO, "vo_dfbmga: CRTC2 surface %dx%d %s\n", screen_width, screen_height, pixelformat_name( dlc.pixelformat ) );
795 } else {
796 use_spic = 0;
800 * Sub-picture
802 if (use_spic) {
803 /* Draw OSD to sub-picture surface */
804 IDirectFBPalette *palette;
805 DFBColor color;
806 int i;
807 struct layer_enum l = {
808 "Matrox CRTC2 Sub-Picture",
809 &spic,
810 DFB_UNSUPPORTED
812 dfb->EnumDisplayLayers( dfb, get_layer_by_name, &l );
813 if (l.res != DFB_OK) {
814 mp_msg( MSGT_VO, MSGL_ERR, "vo_dfbmga: Can't get sub-picture layer - %s\n",
815 DirectFBErrorString( l.res ) );
816 return -1;
818 if ((res = spic->SetCooperativeLevel( spic, DLSCL_EXCLUSIVE )) != DFB_OK) {
819 mp_msg( MSGT_VO, MSGL_ERR, "Can't get exclusive access to sub-picture - %s\n",
820 DirectFBErrorString( res ) );
821 return -1;
824 dlc.flags = DLCONF_PIXELFORMAT | DLCONF_BUFFERMODE;
825 dlc.pixelformat = DSPF_ALUT44;
826 dlc.buffermode = buffermode;
828 #if DIRECTFBVERSION > DFB_VERSION(0,9,16)
829 dlc.flags |= DLCONF_OPTIONS;
830 dlc.options = DLOP_ALPHACHANNEL;
831 #endif
832 if ((res = spic->TestConfiguration( spic, &dlc, &failed )) != DFB_OK) {
833 mp_msg( MSGT_VO, MSGL_ERR,
834 "vo_dfbmga: Invalid sub-picture configuration - %s!\n",
835 DirectFBErrorString( res ) );
836 return -1;
838 if ((res = spic->SetConfiguration( spic, &dlc )) != DFB_OK) {
839 mp_msg( MSGT_VO, MSGL_ERR,
840 "vo_dfbmga: Sub-picture configuration failed - %s!\n",
841 DirectFBErrorString( res ) );
842 return -1;
845 spic->GetSurface( spic, &spicframe );
847 spicframe->GetPalette( spicframe, &palette );
848 color.a = 0xff;
849 for (i = 0; i < 16; i++) {
850 color.r = i * 17;
851 color.g = i * 17;
852 color.b = i * 17;
853 palette->SetEntries( palette, &color, 1, i );
855 palette->Release( palette );
857 spicframe->Clear( spicframe, 0, 0, 0, 0 );
858 spicframe->Flip( spicframe, NULL, 0 );
859 spicframe->Clear( spicframe, 0, 0, 0, 0 );
860 spicframe->Flip( spicframe, NULL, 0 );
861 spicframe->Clear( spicframe, 0, 0, 0, 0 );
863 mp_msg( MSGT_VO, MSGL_INFO, "vo_dfbmga: Sub-picture layer using %s buffering\n",
864 dlc.buffermode == DLBM_TRIPLE ? "triple" :
865 dlc.buffermode == DLBM_BACKVIDEO ? "double" : "single" );
867 subframe = spicframe;
868 subrect = NULL;
869 } else if (use_crtc2) {
870 /* Draw OSD to CRTC2 surface */
871 subframe = c2frame;
872 subrect = &c2rect;
873 } else {
874 /* Draw OSD to BES surface */
875 subframe = besframe;
876 subrect = &besrect;
879 subframe->GetSize( subframe, &sub_width, &sub_height );
880 subframe->GetPixelFormat( subframe, &subframe_format );
881 mp_msg( MSGT_VO, MSGL_INFO, "vo_dfbmga: Sub-picture surface %dx%d %s (%s)\n",
882 sub_width, sub_height,
883 pixelformat_name( subframe_format ),
884 use_crtc2 ? (use_spic ? "Sub-picture layer" : "CRTC2") : "BES" );
886 osd_dirty = 0;
887 osd_current = 1;
888 blit_done = 0;
890 return 0;
893 static int
894 query_format( uint32_t format )
896 switch (format) {
897 case IMGFMT_BGR32:
898 case IMGFMT_BGR24:
899 case IMGFMT_BGR16:
900 case IMGFMT_BGR15:
901 case IMGFMT_UYVY:
902 case IMGFMT_YV12:
903 case IMGFMT_I420:
904 case IMGFMT_IYUV:
905 if (is_g200)
906 return 0;
907 case IMGFMT_YUY2:
908 break;
909 #if DIRECTFBVERSION > DFB_VERSION(0,9,21)
910 case IMGFMT_NV12:
911 case IMGFMT_NV21:
912 if (!use_bes || use_crtc2)
913 return 0;
914 break;
915 #endif
916 default:
917 return 0;
920 return VFCAP_HWSCALE_UP |
921 VFCAP_HWSCALE_DOWN |
922 VFCAP_CSP_SUPPORTED_BY_HW |
923 VFCAP_CSP_SUPPORTED |
924 VFCAP_OSD;
927 static void
928 vo_draw_alpha_alut44( int w, int h,
929 unsigned char* src,
930 unsigned char *srca,
931 int srcstride,
932 unsigned char* dst,
933 int dststride )
935 int x;
937 while (h--) {
938 for (x = 0; x < w; x++) {
939 if (srca[x])
940 dst[x] = ((255 - srca[x]) & 0xF0) | (src[x] >> 4);
942 src += srcstride;
943 srca += srcstride;
944 dst += dststride;
948 static void
949 clear_alpha( int x0, int y0,
950 int w, int h )
952 if (use_spic && !flipping && vo_osd_changed_flag)
953 subframe->FillRectangle( subframe, x0, y0, w, h );
956 static void
957 draw_alpha( int x0, int y0,
958 int w, int h,
959 unsigned char *src,
960 unsigned char *srca,
961 int stride )
963 void *dst;
964 int pitch;
966 if (use_spic) {
967 if (!osd_changed || (!flipping && !vo_osd_changed_flag))
968 return;
969 osd_dirty |= osd_current;
970 } else {
971 if (x0 < subrect->x ||
972 y0 < subrect->y ||
973 x0 + w > subrect->x + subrect->w ||
974 y0 + h > subrect->y + subrect->h)
975 osd_dirty |= osd_current;
978 if (subframe->Lock( subframe, DSLF_READ | DSLF_WRITE, &dst, &pitch ) != DFB_OK)
979 return;
981 switch (subframe_format) {
982 case DSPF_ALUT44:
983 vo_draw_alpha_alut44( w, h, src, srca, stride,
984 ((uint8_t *) dst) + pitch * y0 + x0,
985 pitch );
986 break;
987 case DSPF_RGB32:
988 case DSPF_ARGB:
989 vo_draw_alpha_rgb32( w, h, src, srca, stride,
990 (( uint8_t *) dst) + pitch * y0 + 4 * x0,
991 pitch );
992 break;
993 case DSPF_RGB24:
994 vo_draw_alpha_rgb24( w, h, src, srca, stride,
995 ((uint8_t *) dst) + pitch * y0 + 3 * x0,
996 pitch );
997 break;
998 case DSPF_RGB16:
999 vo_draw_alpha_rgb16( w, h, src, srca, stride,
1000 ((uint8_t *) dst) + pitch * y0 + 2 * x0,
1001 pitch );
1002 break;
1003 case DSPF_ARGB1555:
1004 vo_draw_alpha_rgb15( w, h, src, srca, stride,
1005 ((uint8_t *) dst) + pitch * y0 + 2 * x0,
1006 pitch );
1007 break;
1008 case DSPF_YUY2:
1009 vo_draw_alpha_yuy2( w, h, src, srca, stride,
1010 ((uint8_t *) dst) + pitch * y0 + 2 * x0,
1011 pitch );
1012 break;
1013 case DSPF_UYVY:
1014 vo_draw_alpha_yuy2( w, h, src, srca, stride,
1015 ((uint8_t *) dst) + pitch * y0 + 2 * x0 + 1,
1016 pitch );
1017 break;
1018 #if DIRECTFBVERSION > DFB_VERSION(0,9,21)
1019 case DSPF_NV12:
1020 case DSPF_NV21:
1021 #endif
1022 case DSPF_I420:
1023 case DSPF_YV12:
1024 vo_draw_alpha_yv12( w, h, src, srca, stride,
1025 ((uint8_t *) dst) + pitch * y0 + x0,
1026 pitch );
1027 break;
1030 subframe->Unlock( subframe );
1033 static int
1034 draw_frame( uint8_t * src[] )
1036 return -1;
1039 static int
1040 draw_slice( uint8_t * src[], int stride[], int w, int h, int x, int y )
1042 void *dst;
1043 int pitch;
1045 if (frame->Lock( frame, DSLF_WRITE, &dst, &pitch ) != DFB_OK)
1046 return VO_FALSE;
1048 memcpy_pic( dst + pitch * y + x, src[0],
1049 w, h, pitch, stride[0] );
1051 dst += pitch * buf_height;
1053 y /= 2;
1054 h /= 2;
1056 #if DIRECTFBVERSION > DFB_VERSION(0,9,21)
1057 if (frame_format == DSPF_NV12 || frame_format == DSPF_NV21) {
1058 memcpy_pic( dst + pitch * y + x, src[1],
1059 w, h, pitch, stride[1] );
1060 } else
1061 #endif
1063 x /= 2;
1064 w /= 2;
1065 pitch /= 2;
1067 if (frame_format == DSPF_I420 )
1068 memcpy_pic( dst + pitch * y + x, src[1],
1069 w, h, pitch, stride[1] );
1070 else
1071 memcpy_pic( dst + pitch * y + x, src[2],
1072 w, h, pitch, stride[2] );
1074 dst += pitch * buf_height / 2;
1076 if (frame_format == DSPF_I420 )
1077 memcpy_pic( dst + pitch * y + x, src[2],
1078 w, h, pitch, stride[2] );
1079 else
1080 memcpy_pic( dst + pitch * y + x, src[1],
1081 w, h, pitch, stride[1] );
1084 frame->Unlock( frame );
1086 return VO_TRUE;
1089 static void
1090 blit_to_screen( void )
1092 IDirectFBSurface *blitsrc = frame;
1093 DFBRectangle *srect = NULL;
1095 if (use_bes) {
1096 #if DIRECTFBVERSION > DFB_VERSION(0,9,15)
1097 if (vo_vsync && !flipping && !use_crtc2)
1098 bes->WaitForSync( bes );
1099 #endif
1101 besframe->Blit( besframe, blitsrc, NULL, besrect.x, besrect.y );
1102 blitsrc = besframe;
1103 srect = &besrect;
1106 if (use_crtc2) {
1107 #if DIRECTFBVERSION > DFB_VERSION(0,9,15)
1108 if (vo_vsync && !flipping)
1109 crtc2->WaitForSync( crtc2 );
1110 #endif
1112 if (stretch)
1113 c2frame->StretchBlit( c2frame, blitsrc, srect, &c2rect );
1114 else
1115 c2frame->Blit( c2frame, blitsrc, srect, c2rect.x, c2rect.y );
1119 static void
1120 draw_osd( void )
1122 frame = bufs[current_buf];
1123 frame->Unlock( frame );
1125 osd_changed = vo_osd_changed( 0 );
1126 if (osd_dirty & osd_current) {
1127 if (use_spic) {
1128 if (flipping)
1129 subframe->Clear( subframe, 0, 0, 0, 0 );
1130 } else {
1131 /* Clear black bars around the picture */
1132 subframe->FillRectangle( subframe,
1133 0, 0,
1134 sub_width, subrect->y );
1135 subframe->FillRectangle( subframe,
1136 0, subrect->y + subrect->h,
1137 sub_width, subrect->y );
1138 subframe->FillRectangle( subframe,
1139 0, subrect->y,
1140 subrect->x, subrect->h );
1141 subframe->FillRectangle( subframe,
1142 subrect->x + subrect->w, subrect->y,
1143 subrect->x, subrect->h );
1145 osd_dirty &= ~osd_current;
1148 blit_to_screen();
1149 blit_done = 1;
1151 vo_remove_text( sub_width, sub_height, clear_alpha );
1152 vo_draw_text( sub_width, sub_height, draw_alpha );
1154 if (use_spic && flipping && osd_changed) {
1155 subframe->Flip( subframe, NULL, 0 );
1156 osd_current <<= 1;
1157 if (osd_current > osd_max)
1158 osd_current = 1;
1162 static void
1163 flip_page( void )
1165 if (!blit_done)
1166 blit_to_screen();
1168 if (flipping) {
1169 if (use_crtc2)
1170 c2frame->Flip( c2frame, NULL, vo_vsync ? DSFLIP_WAITFORSYNC : DSFLIP_ONSYNC );
1171 else
1172 besframe->Flip( besframe, NULL, vo_vsync ? DSFLIP_WAITFORSYNC : DSFLIP_ONSYNC );
1174 if (!use_spic) {
1175 osd_current <<= 1;
1176 if (osd_current > osd_max)
1177 osd_current = 1;
1181 blit_done = 0;
1182 current_buf = 0;
1185 static void
1186 uninit( void )
1188 release_config();
1190 if (buffer)
1191 buffer->Release( buffer );
1192 if (remote)
1193 remote->Release( remote );
1194 if (keyboard)
1195 keyboard->Release( keyboard );
1196 if (crtc2)
1197 crtc2->Release( crtc2 );
1198 if (bes)
1199 bes->Release( bes );
1200 if (primary)
1201 primary->Release( primary );
1202 if (dfb)
1203 dfb->Release( dfb );
1205 buffer = NULL;
1206 remote = NULL;
1207 keyboard = NULL;
1208 crtc2 = NULL;
1209 bes = NULL;
1210 primary = NULL;
1211 dfb = NULL;
1214 static uint32_t
1215 get_image( mp_image_t *mpi )
1217 int buf = current_buf;
1218 void *dst;
1219 int pitch;
1221 if (mpi->flags & MP_IMGFLAG_READABLE &&
1222 (mpi->type == MP_IMGTYPE_IPB || mpi->type == MP_IMGTYPE_IP)) {
1223 if (num_bufs < 2)
1224 return VO_FALSE;
1226 current_ip_buf ^= 1;
1228 if (mpi->type == MP_IMGTYPE_IPB && num_bufs < 3 && current_ip_buf)
1229 return VO_FALSE;
1231 buf = current_ip_buf;
1233 if (mpi->type == MP_IMGTYPE_IPB)
1234 buf++;
1236 frame = bufs[buf];
1237 frame->Unlock( frame );
1239 /* Always use DSLF_READ to preserve system memory copy */
1240 if (frame->Lock( frame, DSLF_WRITE | DSLF_READ,
1241 &dst, &pitch ) != DFB_OK)
1242 return VO_FALSE;
1244 if ((mpi->width == pitch) ||
1245 (mpi->flags & (MP_IMGFLAG_ACCEPT_STRIDE | MP_IMGFLAG_ACCEPT_WIDTH))) {
1247 mpi->planes[0] = dst;
1248 mpi->width = in_width;
1249 mpi->stride[0] = pitch;
1251 if (mpi->flags & MP_IMGFLAG_PLANAR) {
1252 if (mpi->num_planes > 2) {
1253 mpi->stride[1] = mpi->stride[2] = pitch / 2;
1255 if (mpi->flags & MP_IMGFLAG_SWAPPED) {
1256 /* I420 */
1257 mpi->planes[1] = dst + buf_height * pitch;
1258 mpi->planes[2] = mpi->planes[1] + buf_height * pitch / 4;
1259 } else {
1260 /* YV12 */
1261 mpi->planes[2] = dst + buf_height * pitch;
1262 mpi->planes[1] = mpi->planes[2] + buf_height * pitch / 4;
1264 } else {
1265 /* NV12/NV21 */
1266 mpi->stride[1] = pitch;
1267 mpi->planes[1] = dst + buf_height * pitch;
1271 mpi->flags |= MP_IMGFLAG_DIRECT;
1272 mpi->priv = (void *) buf;
1273 current_buf = buf;
1275 return VO_TRUE;
1278 frame->Unlock( frame );
1280 return VO_FALSE;
1285 static uint32_t
1286 draw_image( mp_image_t *mpi )
1288 if (mpi->flags & MP_IMGFLAG_DIRECT) {
1289 current_buf = (int) mpi->priv;
1290 return VO_TRUE;
1292 if (mpi->flags & MP_IMGFLAG_DRAW_CALLBACK)
1293 return VO_TRUE;
1295 if (mpi->flags & MP_IMGFLAG_PLANAR)
1296 return draw_slice( mpi->planes, mpi->stride,
1297 mpi->w, mpi->h, 0, 0 );
1298 else {
1299 void *dst;
1300 int pitch;
1302 if (frame->Lock( frame, DSLF_WRITE, &dst, &pitch ) != DFB_OK)
1303 return VO_FALSE;
1304 memcpy_pic( dst, mpi->planes[0],
1305 mpi->w * (mpi->bpp / 8), mpi->h,
1306 pitch, mpi->stride[0] );
1307 frame->Unlock( frame );
1309 return VO_TRUE;
1313 static int
1314 set_equalizer( char *data, int value )
1316 DFBResult res;
1317 DFBColorAdjustment ca;
1318 float factor = (float) 0xffff / 200.0;
1320 ca.flags = DCAF_NONE;
1322 if (!strcasecmp( data, "brightness" )) {
1323 ca.flags |= DCAF_BRIGHTNESS;
1324 ca.brightness = value * factor + 0x8000;
1326 if (!strcasecmp( data, "contrast" )) {
1327 ca.flags |= DCAF_CONTRAST;
1328 ca.contrast = value * factor + 0x8000;
1330 if (!strcasecmp( data, "hue" )) {
1331 ca.flags |= DCAF_HUE;
1332 ca.hue = value * factor + 0x8000;
1334 if (!strcasecmp( data, "saturation" )) {
1335 ca.flags |= DCAF_SATURATION;
1336 ca.saturation = value * factor + 0x8000;
1339 /* Prefer CRTC2 over BES */
1340 if (use_crtc2)
1341 res = crtc2->SetColorAdjustment( crtc2, &ca );
1342 else
1343 res = bes->SetColorAdjustment( bes, &ca );
1345 if (res != DFB_OK)
1346 return VO_FALSE;
1348 return VO_TRUE;
1351 static int
1352 get_equalizer( char *data, int *value )
1354 DFBResult res;
1355 DFBColorAdjustment ca;
1356 float factor = 200.0 / (float) 0xffff;
1358 /* Prefer CRTC2 over BES */
1359 if (use_crtc2)
1360 res = crtc2->GetColorAdjustment( crtc2, &ca );
1361 else
1362 res = bes->GetColorAdjustment( bes, &ca );
1364 if (res != DFB_OK)
1365 return VO_FALSE;
1367 if (!strcasecmp( data, "brightness" ) &&
1368 (ca.flags & DCAF_BRIGHTNESS))
1369 *value = (ca.brightness - 0x8000) * factor;
1370 if (!strcasecmp( data, "contrast" ) &&
1371 (ca.flags & DCAF_CONTRAST))
1372 *value = (ca.contrast - 0x8000) * factor;
1373 if (!strcasecmp( data, "hue" ) &&
1374 (ca.flags & DCAF_HUE))
1375 *value = (ca.hue - 0x8000) * factor;
1376 if (!strcasecmp( data, "saturation" ) &&
1377 (ca.flags & DCAF_SATURATION))
1378 *value = (ca.saturation - 0x8000) * factor;
1380 return VO_TRUE;
1383 static int
1384 control( uint32_t request, void *data)
1386 switch (request) {
1387 case VOCTRL_GUISUPPORT:
1388 case VOCTRL_GUI_NOWINDOW:
1389 return VO_TRUE;
1391 case VOCTRL_QUERY_FORMAT:
1392 return query_format( *((uint32_t *) data) );
1394 case VOCTRL_GET_IMAGE:
1395 return get_image( data );
1397 case VOCTRL_DRAW_IMAGE:
1398 return draw_image( data );
1400 case VOCTRL_SET_EQUALIZER:
1402 struct voctrl_set_equalizer_args *args = data;
1403 return set_equalizer(args->name, args->value);
1405 case VOCTRL_GET_EQUALIZER:
1407 struct voctrl_get_equalizer_args *args = data;
1408 return get_equalizer(args->name, args->valueptr);
1412 return VO_NOTIMPL;
1415 #include "osdep/keycodes.h"
1417 static void
1418 check_events( void )
1420 DFBInputEvent event;
1422 if (!buffer)
1423 return;
1425 if (buffer->GetEvent( buffer, DFB_EVENT( &event )) == DFB_OK) {
1426 if (event.type == DIET_KEYPRESS) {
1427 switch (event.key_symbol) {
1428 case DIKS_ESCAPE:
1429 mplayer_put_key( KEY_ESC );
1430 break;
1431 case DIKS_PAGE_UP:
1432 mplayer_put_key( KEY_PAGE_UP );
1433 break;
1434 case DIKS_PAGE_DOWN:
1435 mplayer_put_key( KEY_PAGE_DOWN );
1436 break;
1437 case DIKS_CURSOR_UP:
1438 mplayer_put_key( KEY_UP );
1439 break;
1440 case DIKS_CURSOR_DOWN:
1441 mplayer_put_key( KEY_DOWN );
1442 break;
1443 case DIKS_CURSOR_LEFT:
1444 mplayer_put_key( KEY_LEFT );
1445 break;
1446 case DIKS_CURSOR_RIGHT:
1447 mplayer_put_key( KEY_RIGHT );
1448 break;
1449 case DIKS_INSERT:
1450 mplayer_put_key( KEY_INSERT );
1451 break;
1452 case DIKS_DELETE:
1453 mplayer_put_key( KEY_DELETE );
1454 break;
1455 case DIKS_HOME:
1456 mplayer_put_key( KEY_HOME );
1457 break;
1458 case DIKS_END:
1459 mplayer_put_key( KEY_END );
1460 break;
1462 case DIKS_POWER:
1463 mplayer_put_key( KEY_POWER );
1464 break;
1465 case DIKS_MENU:
1466 mplayer_put_key( KEY_MENU );
1467 break;
1468 case DIKS_PLAY:
1469 mplayer_put_key( KEY_PLAY );
1470 break;
1471 case DIKS_STOP:
1472 mplayer_put_key( KEY_STOP );
1473 break;
1474 case DIKS_PAUSE:
1475 mplayer_put_key( KEY_PAUSE );
1476 break;
1477 case DIKS_PLAYPAUSE:
1478 mplayer_put_key( KEY_PLAYPAUSE );
1479 break;
1480 case DIKS_FORWARD:
1481 mplayer_put_key( KEY_FORWARD );
1482 break;
1483 case DIKS_NEXT:
1484 mplayer_put_key( KEY_NEXT );
1485 break;
1486 case DIKS_REWIND:
1487 mplayer_put_key( KEY_REWIND );
1488 break;
1489 case DIKS_PREVIOUS:
1490 mplayer_put_key( KEY_PREV );
1491 break;
1492 case DIKS_VOLUME_UP:
1493 mplayer_put_key( KEY_VOLUME_UP );
1494 break;
1495 case DIKS_VOLUME_DOWN:
1496 mplayer_put_key( KEY_VOLUME_DOWN );
1497 break;
1498 case DIKS_MUTE:
1499 mplayer_put_key( KEY_MUTE );
1500 break;
1502 default:
1503 mplayer_put_key( event.key_symbol );
1509 * empty buffer, because of repeating
1510 * keyboard repeat is faster than key handling and this causes problems during seek
1511 * temporary workabout. should be solved in the future
1513 buffer->Reset( buffer );