Updated sdl to use new VOUT_DISPLAY_CHANGE_DISPLAY_SIZE parameter.
[vlc.git] / modules / video_output / sdl.c
1 /*****************************************************************************
2  * sdl.c: SDL video output display method
3  *****************************************************************************
4  * Copyright (C) 1998-2009 the VideoLAN team
5  * $Id$
6  *
7  * Authors: Samuel Hocevar <sam@zoy.org>
8  *          Pierre Baillet <oct@zoy.org>
9  *          Arnaud de Bossoreille de Ribou <bozo@via.ecp.fr>
10  *          Laurent Aimar <fenrir _AT_ videolan _DOT_ org>
11  *
12  * This program is free software; you can redistribute it and/or modify
13  * it under the terms of the GNU General Public License as published by
14  * the Free Software Foundation; either version 2 of the License, or
15  * (at your option) any later version.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, write to the Free Software
24  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
25  *****************************************************************************/
26
27 /*****************************************************************************
28  * Preamble
29  *****************************************************************************/
30 #ifdef HAVE_CONFIG_H
31 # include "config.h"
32 #endif
33
34 #include <vlc_common.h>
35 #include <vlc_plugin.h>
36 #include <vlc_vout_display.h>
37 #include <vlc_picture_pool.h>
38
39 #include <assert.h>
40
41 #include <SDL/SDL.h>
42
43 /*****************************************************************************
44  * Module descriptor
45  *****************************************************************************/
46 static int  Open (vlc_object_t *);
47 static void Close(vlc_object_t *);
48
49 #define CHROMA_TEXT N_("SDL chroma format")
50 #define CHROMA_LONGTEXT N_(\
51     "Force the SDL renderer to use a specific chroma format instead of " \
52     "trying to improve performances by using the most efficient one.")
53
54 #define DRIVER_TEXT N_("SDL video driver name")
55 #define DRIVER_LONGTEXT N_(\
56     "Force a specific SDL video output driver.")
57
58 vlc_module_begin()
59     set_shortname("SDL")
60     set_category(CAT_VIDEO)
61     set_subcategory(SUBCAT_VIDEO_VOUT)
62     set_description(N_("Simple DirectMedia Layer video output"))
63     set_capability("vout display", 60)
64     add_shortcut("sdl")
65     add_string("sdl-chroma", NULL, NULL, CHROMA_TEXT, CHROMA_LONGTEXT, true)
66 #ifdef HAVE_SETENV
67     add_string("sdl-video-driver", NULL, NULL, DRIVER_TEXT, DRIVER_LONGTEXT, true)
68 #endif
69     set_callbacks(Open, Close)
70 #if defined(__i386__) || defined(__x86_64__)
71     /* On i386, SDL is linked against svgalib */
72     linked_with_a_crap_library_which_uses_atexit()
73 #endif
74 vlc_module_end()
75
76
77 /*****************************************************************************
78  * Local prototypes
79  *****************************************************************************/
80 static picture_t *Get    (vout_display_t *);
81 static void       Display(vout_display_t *, picture_t *);
82 static int        Control(vout_display_t *, int, va_list);
83 static void       Manage(vout_display_t *);
84
85 /* */
86 static int ConvertKey(SDLKey);
87
88 /* */
89 static vlc_mutex_t sdl_lock = VLC_STATIC_MUTEX;
90
91 /* */
92 struct vout_display_sys_t {
93     vout_display_place_t place;
94
95     SDL_Surface          *display;
96     int                  display_bpp;
97     uint32_t             display_flags;
98
99     unsigned int         desktop_width;
100     unsigned int         desktop_height;
101
102     /* For YUV output */
103     SDL_Overlay          *overlay;
104     bool                 is_uv_swapped;
105
106     /* */
107     picture_pool_t       *pool;
108 };
109
110 /**
111  * This function initializes SDL vout method.
112  */
113 static int Open(vlc_object_t *object)
114 {
115     vout_display_t *vd = (vout_display_t *)object;
116     vout_display_sys_t *sys;
117
118     /* XXX: check for conflicts with the SDL audio output */
119     vlc_mutex_lock(&sdl_lock);
120
121     /* Check if SDL video module has been initialized */
122     if (SDL_WasInit(SDL_INIT_VIDEO) != 0) {
123         vlc_mutex_unlock(&sdl_lock);
124         return VLC_EGENERIC;
125     }
126
127     vd->sys = sys = calloc(1, sizeof(*sys));
128     if (!sys) {
129         vlc_mutex_unlock(&sdl_lock);
130         return VLC_ENOMEM;
131     }
132
133 #ifdef HAVE_SETENV
134     char *psz_driver = var_CreateGetNonEmptyString(vd, "sdl-video-driver");
135     if (psz_driver) {
136         setenv("SDL_VIDEODRIVER", psz_driver, 1);
137         free(psz_driver);
138     }
139 #endif
140
141     /* */
142     int sdl_flags = SDL_INIT_VIDEO;
143 #ifndef WIN32
144     /* Win32 SDL implementation doesn't support SDL_INIT_EVENTTHREAD yet*/
145     sdl_flags |= SDL_INIT_EVENTTHREAD;
146 #endif
147 #ifndef NDEBUG
148     /* In debug mode you may want vlc to dump a core instead of staying stuck */
149     sdl_flags |= SDL_INIT_NOPARACHUTE;
150 #endif
151
152     /* Initialize library */
153     if (SDL_Init(sdl_flags) < 0) {
154         vlc_mutex_unlock(&sdl_lock);
155
156         msg_Err(vd, "cannot initialize SDL (%s)", SDL_GetError());
157         free(sys);
158         return VLC_EGENERIC;
159     }
160     vlc_mutex_unlock(&sdl_lock);
161
162     /* Translate keys into unicode */
163     SDL_EnableUNICODE(1);
164
165     /* Get the desktop resolution */
166     /* FIXME: SDL has a problem with virtual desktop */
167     sys->desktop_width  = SDL_GetVideoInfo()->current_w;
168     sys->desktop_height = SDL_GetVideoInfo()->current_h;
169
170     /* */
171     video_format_t fmt = vd->fmt;
172
173     /* */
174     vout_display_info_t info = vd->info;
175
176     /* Set main window's size */
177     int display_width;
178     int display_height;
179     if (vd->cfg->is_fullscreen) {
180         display_width  = sys->desktop_width;
181         display_height = sys->desktop_height;
182     } else {
183         display_width  = vd->cfg->display.width;
184         display_height = vd->cfg->display.height;
185     }
186
187     /* Initialize flags and cursor */
188     sys->display_flags = SDL_ANYFORMAT | SDL_HWPALETTE | SDL_HWSURFACE | SDL_DOUBLEBUF;
189     sys->display_flags |= vd->cfg->is_fullscreen ? SDL_FULLSCREEN : SDL_RESIZABLE;
190
191     sys->display_bpp = SDL_VideoModeOK(display_width, display_height,
192                                        16, sys->display_flags);
193     if (sys->display_bpp == 0) {
194         msg_Err(vd, "no video mode available");
195         goto error;
196     }
197
198     sys->display = SDL_SetVideoMode(display_width, display_height,
199                                     sys->display_bpp, sys->display_flags);
200     if (!sys->display) {
201         msg_Err(vd, "cannot set video mode");
202         goto error;
203     }
204
205     /* We keep the surface locked forever */
206     SDL_LockSurface(sys->display);
207
208     /* */
209     vlc_fourcc_t forced_chroma = 0;
210     char *psz_chroma = var_CreateGetNonEmptyString(vd, "sdl-chroma");
211     if (psz_chroma) {
212         forced_chroma = vlc_fourcc_GetCodecFromString(VIDEO_ES, psz_chroma);
213         if (forced_chroma)
214             msg_Dbg(vd, "Forcing chroma to 0x%.8x (%4.4s)",
215                     forced_chroma, (const char*)&forced_chroma);
216         free(psz_chroma);
217     }
218
219     /* Try to open an overlay if requested */
220     sys->overlay = NULL;
221     const bool is_overlay = var_CreateGetBool(vd, "overlay");
222     if (is_overlay) {
223         static const struct
224         {
225             vlc_fourcc_t vlc;
226             uint32_t     sdl;
227         } vlc_to_sdl[] = {
228             { VLC_CODEC_YV12, SDL_YV12_OVERLAY },
229             { VLC_CODEC_I420, SDL_IYUV_OVERLAY },
230             { VLC_CODEC_YUYV, SDL_YUY2_OVERLAY },
231             { VLC_CODEC_UYVY, SDL_UYVY_OVERLAY },
232             { VLC_CODEC_YVYU, SDL_YVYU_OVERLAY },
233
234             { 0, 0 }
235         };
236         const vlc_fourcc_t forced_chromas[] = {
237             forced_chroma, 0
238         };
239         const vlc_fourcc_t *fallback_chromas =
240             vlc_fourcc_GetYUVFallback(fmt.i_chroma);
241         const vlc_fourcc_t *chromas = forced_chroma ? forced_chromas : fallback_chromas;
242
243         for (int pass = forced_chroma ? 1 : 0; pass < 2 && !sys->overlay; pass++) {
244             for (int i = 0; chromas[i] != 0; i++) {
245                 const vlc_fourcc_t vlc = chromas[i];
246
247                 uint32_t sdl = 0;
248                 for (int j = 0; vlc_to_sdl[j].vlc != 0 && !sdl; j++) {
249                     if (vlc_to_sdl[j].vlc == vlc)
250                         sdl = vlc_to_sdl[j].sdl;
251                 }
252                 if (!sdl)
253                     continue;
254
255                 sys->overlay = SDL_CreateYUVOverlay(fmt.i_width, fmt.i_height,
256                                                     sdl, sys->display);
257                 if (sys->overlay && !sys->overlay->hw_overlay && pass == 0) {
258                     /* Ignore non hardware overlay surface in first pass */
259                     SDL_FreeYUVOverlay(sys->overlay);
260                     sys->overlay = NULL;
261                 }
262                 if (sys->overlay) {
263                     /* We keep the surface locked forever */
264                     SDL_LockYUVOverlay(sys->overlay);
265
266                     fmt.i_chroma = vlc;
267                     sys->is_uv_swapped = vlc_fourcc_AreUVPlanesSwapped(fmt.i_chroma,
268                                                                        vd->fmt.i_chroma);
269                     if (sys->is_uv_swapped)
270                         fmt.i_chroma = vd->fmt.i_chroma;
271                     break;
272                 }
273             }
274         }
275     } else {
276         msg_Warn(vd, "SDL overlay disabled by the user");
277     }
278
279     /* */
280     vout_display_cfg_t place_cfg = *vd->cfg;
281     place_cfg.display.width  = display_width;
282     place_cfg.display.height = display_height;
283     vout_display_PlacePicture(&sys->place, &vd->source, &place_cfg, !sys->overlay);
284
285     /* If no overlay, fallback to software output */
286     if (!sys->overlay) {
287         /* */
288         switch (sys->display->format->BitsPerPixel) {
289         case 8:
290             fmt.i_chroma = VLC_CODEC_RGB8;
291             break;
292         case 15:
293             fmt.i_chroma = VLC_CODEC_RGB15;
294             break;
295         case 16:
296             fmt.i_chroma = VLC_CODEC_RGB16;
297             break;
298         case 24:
299             fmt.i_chroma = VLC_CODEC_RGB24;
300             break;
301         case 32:
302             fmt.i_chroma = VLC_CODEC_RGB32;
303             break;
304         default:
305             msg_Err(vd, "unknown screen depth %i",
306                     sys->display->format->BitsPerPixel);
307             goto error;
308         }
309
310         /* All we have is an RGB image with square pixels */
311         fmt.i_width  = display_width;
312         fmt.i_height = display_height;
313         fmt.i_rmask = sys->display->format->Rmask;
314         fmt.i_gmask = sys->display->format->Gmask;
315         fmt.i_bmask = sys->display->format->Bmask;
316
317         info.has_pictures_invalid = true;
318     }
319
320     if (vd->cfg->display.title)
321         SDL_WM_SetCaption(vd->cfg->display.title,
322                           vd->cfg->display.title);
323     else if (!sys->overlay)
324         SDL_WM_SetCaption(VOUT_TITLE " (software RGB SDL output)",
325                           VOUT_TITLE " (software RGB SDL output)");
326     else if (sys->overlay->hw_overlay)
327         SDL_WM_SetCaption(VOUT_TITLE " (hardware YUV SDL output)",
328                           VOUT_TITLE " (hardware YUV SDL output)");
329     else
330         SDL_WM_SetCaption(VOUT_TITLE " (software YUV SDL output)",
331                           VOUT_TITLE " (software YUV SDL output)");
332
333     /* Setup events */
334     SDL_EventState(SDL_KEYUP, SDL_IGNORE);               /* ignore keys up */
335
336     /* Setup vout_display now that everything is fine */
337     vd->fmt = fmt;
338     vd->info = info;
339
340     vd->get     = Get;
341     vd->prepare = NULL;
342     vd->display = Display;
343     vd->control = Control;
344     vd->manage  = Manage;
345
346     /* */
347     vout_display_SendEventDisplaySize(vd, display_width, display_height, vd->cfg->is_fullscreen);
348     return VLC_SUCCESS;
349
350 error:
351     msg_Err(vd, "cannot set up SDL (%s)", SDL_GetError());
352
353     if (sys->display) {
354         SDL_UnlockSurface(sys->display);
355         SDL_FreeSurface(sys->display);
356     }
357
358     vlc_mutex_lock(&sdl_lock);
359     SDL_QuitSubSystem(SDL_INIT_VIDEO);
360     vlc_mutex_unlock(&sdl_lock);
361
362     free(sys);
363     return VLC_EGENERIC;
364 }
365
366 /**
367  * Close a SDL video output
368  */
369 static void Close(vlc_object_t *object)
370 {
371     vout_display_t *vd = (vout_display_t *)object;
372     vout_display_sys_t *sys = vd->sys;
373
374     if (sys->pool)
375         picture_pool_Delete(sys->pool);
376
377     if (sys->overlay) {
378         SDL_LockYUVOverlay(sys->overlay);
379         SDL_FreeYUVOverlay(sys->overlay);
380     }
381     SDL_UnlockSurface (sys->display);
382     SDL_FreeSurface(sys->display);
383
384     vlc_mutex_lock(&sdl_lock);
385     SDL_QuitSubSystem(SDL_INIT_VIDEO);
386     vlc_mutex_unlock(&sdl_lock);
387
388     free(sys);
389 }
390
391 /**
392  * Return a direct buffer
393  */
394 static picture_t *Get(vout_display_t *vd)
395 {
396     vout_display_sys_t *sys = vd->sys;
397
398     if (!sys->pool) {
399         picture_resource_t rsc;
400
401         memset(&rsc, 0, sizeof(rsc));
402
403         if (sys->overlay) {
404             SDL_Overlay *ol = sys->overlay;
405
406             for (int i = 0; i < ol->planes; i++) {
407                 rsc.p[i].p_pixels = ol->pixels[ i > 0 && sys->is_uv_swapped ? (3-i) : i];
408                 rsc.p[i].i_pitch  = ol->pitches[i > 0 && sys->is_uv_swapped ? (3-i) : i];
409                 rsc.p[i].i_lines  = ol->h;
410                 if (ol->format == SDL_YV12_OVERLAY ||
411                     ol->format == SDL_IYUV_OVERLAY)
412                     rsc.p[i].i_lines /= 2;
413
414             }
415         } else {
416             const int x = sys->place.x;
417             const int y = sys->place.y;
418
419             SDL_Surface *sf = sys->display;
420             SDL_FillRect(sf, NULL, 0);
421
422             assert(x >= 0 && y >= 0);
423             rsc.p[0].p_pixels = (uint8_t*)sf->pixels + y * sf->pitch + x * ((sf->format->BitsPerPixel + 7) / 8);
424             rsc.p[0].i_pitch  = sf->pitch;
425             rsc.p[0].i_lines  = vd->fmt.i_height;
426         }
427
428         picture_t *picture = picture_NewFromResource(&vd->fmt, &rsc);;
429         if (!picture)
430             return NULL;
431
432         sys->pool = picture_pool_New(1, &picture);
433         if (!sys->pool)
434             return NULL;
435     }
436
437     return picture_pool_Get(sys->pool);
438 }
439
440 /**
441  * Display a picture
442  */
443 static void Display(vout_display_t *vd, picture_t *p_pic)
444 {
445     vout_display_sys_t *sys = vd->sys;
446
447     if (sys->overlay) {
448         SDL_Rect disp;
449         disp.x = sys->place.x;
450         disp.y = sys->place.y;
451         disp.w = sys->place.width;
452         disp.h = sys->place.height;
453
454         SDL_UnlockYUVOverlay(sys->overlay);
455         SDL_DisplayYUVOverlay(sys->overlay , &disp);
456         SDL_LockYUVOverlay(sys->overlay);
457     } else {
458         SDL_Flip(sys->display);
459     }
460
461     picture_Release(p_pic);
462 }
463
464
465 /**
466  * Control for vout display
467  */
468 static int Control(vout_display_t *vd, int query, va_list args)
469 {
470     vout_display_sys_t *sys = vd->sys;
471
472     switch (query)
473     {
474     case VOUT_DISPLAY_HIDE_MOUSE:
475         SDL_ShowCursor(0);
476         return VLC_SUCCESS;
477
478     case VOUT_DISPLAY_CHANGE_DISPLAY_SIZE: {
479         const vout_display_cfg_t *cfg = va_arg(args, const vout_display_cfg_t *);
480         const bool is_forced = (bool)va_arg(args, int);
481
482         /* */
483         if (is_forced)
484             sys->display = SDL_SetVideoMode(cfg->display.width,
485                                             cfg->display.height,
486                                             sys->display_bpp, sys->display_flags);
487         if (!sys->display) {
488             sys->display = SDL_SetVideoMode(vd->cfg->display.width,
489                                             vd->cfg->display.height,
490                                             sys->display_bpp, sys->display_flags);
491             return VLC_EGENERIC;
492         }
493         if (sys->overlay)
494             vout_display_PlacePicture(&sys->place, &vd->source, cfg, !sys->overlay);
495         else
496             vout_display_SendEventPicturesInvalid(vd);
497         return VLC_SUCCESS;
498     }
499     case VOUT_DISPLAY_CHANGE_FULLSCREEN: {
500         vout_display_cfg_t cfg = *va_arg(args, const vout_display_cfg_t *);
501
502         /* Fix flags */
503         sys->display_flags &= ~(SDL_FULLSCREEN | SDL_RESIZABLE);
504         sys->display_flags |= cfg.is_fullscreen ? SDL_FULLSCREEN : SDL_RESIZABLE;
505
506         if (cfg.is_fullscreen) {
507             cfg.display.width = sys->desktop_width;
508             cfg.display.height = sys->desktop_height;
509         }
510
511         if (sys->overlay) {
512             sys->display = SDL_SetVideoMode(cfg.display.width, cfg.display.height,
513                                             sys->display_bpp, sys->display_flags);
514
515             vout_display_PlacePicture(&sys->place, &vd->source, &cfg, !sys->overlay);
516         }
517         vout_display_SendEventDisplaySize(vd, cfg.display.width, cfg.display.height, cfg.is_fullscreen);
518         return VLC_SUCCESS;
519     }
520     case VOUT_DISPLAY_CHANGE_ZOOM:
521     case VOUT_DISPLAY_CHANGE_DISPLAY_FILLED:
522     case VOUT_DISPLAY_CHANGE_SOURCE_ASPECT: {
523         const vout_display_cfg_t *cfg;
524         const video_format_t *source;
525
526         if (query == VOUT_DISPLAY_CHANGE_SOURCE_ASPECT) {
527             source = va_arg(args, const video_format_t *);
528             cfg = vd->cfg;
529         } else {
530             source = &vd->source;
531             cfg = va_arg(args, const vout_display_cfg_t *);
532         }
533         if (sys->overlay) {
534             sys->display = SDL_SetVideoMode(cfg->display.width, cfg->display.height,
535                                             sys->display_bpp, sys->display_flags);
536
537             vout_display_PlacePicture(&sys->place, source, cfg, !sys->overlay);
538         } else {
539             vout_display_SendEventPicturesInvalid(vd);
540         }
541         return VLC_SUCCESS;
542     }
543
544     case VOUT_DISPLAY_RESET_PICTURES: {
545         /* */
546         assert(!sys->overlay);
547
548         /* */
549         if (sys->pool)
550             picture_pool_Delete(sys->pool);
551         sys->pool = NULL;
552
553         vout_display_PlacePicture(&sys->place, &vd->source, vd->cfg, !sys->overlay);
554
555         /* */
556         vd->fmt.i_width  = sys->place.width;
557         vd->fmt.i_height = sys->place.height;
558         return VLC_SUCCESS;
559     }
560
561     case VOUT_DISPLAY_CHANGE_SOURCE_CROP:
562     case VOUT_DISPLAY_CHANGE_ON_TOP:
563         /* I don't think it is possible to support with SDL:
564          * - crop
565          * - on top
566          */
567         return VLC_EGENERIC;
568
569     default:
570         msg_Err(vd, "Unsupported query in vout display SDL");
571         return VLC_EGENERIC;
572     }
573 }
574
575 /**
576  * Proccess pending event
577  */
578 static void Manage(vout_display_t *vd)
579 {
580     vout_display_sys_t *sys = vd->sys;
581     SDL_Event event;
582
583     /* */
584     while (SDL_PollEvent(&event)) {
585         switch (event.type) {
586         case SDL_QUIT:
587             vout_display_SendEventClose(vd);
588             break;
589
590         case SDL_KEYDOWN: {
591             /* convert the key if possible */
592             int key = ConvertKey(event.key.keysym.sym);
593
594             if (!key) {
595                 /* Find the right caracter */
596                 if ((event.key.keysym.unicode & 0xff80) == 0) {
597                     key = event.key.keysym.unicode & 0x7f;
598                     /* FIXME: find a better solution than this
599                               hack to find the right caracter */
600                     if (key >= 1 && key <= 26)
601                         key += 96;
602                     else if (key >= 65 && key <= 90)
603                         key += 32;
604                 }
605             }
606             if (!key)
607                 break;
608
609             if (event.key.keysym.mod & KMOD_SHIFT)
610                 key |= KEY_MODIFIER_SHIFT;
611             if (event.key.keysym.mod & KMOD_CTRL)
612                 key |= KEY_MODIFIER_CTRL;
613             if (event.key.keysym.mod & KMOD_ALT)
614                 key |= KEY_MODIFIER_ALT;
615             vout_display_SendEventKey(vd, key);
616             break;
617         }
618
619         case SDL_MOUSEBUTTONDOWN:
620         case SDL_MOUSEBUTTONUP: {
621             static const struct { int sdl; int vlc; } buttons[] = {
622                 { SDL_BUTTON_LEFT,      MOUSE_BUTTON_LEFT },
623                 { SDL_BUTTON_MIDDLE,    MOUSE_BUTTON_CENTER },
624                 { SDL_BUTTON_RIGHT,     MOUSE_BUTTON_RIGHT },
625                 { SDL_BUTTON_WHEELUP,   MOUSE_BUTTON_WHEEL_UP },
626                 { SDL_BUTTON_WHEELDOWN, MOUSE_BUTTON_WHEEL_DOWN },
627                 { -1, -1 },
628             };
629
630             SDL_ShowCursor(1);
631             for (int i = 0; buttons[i].sdl != -1; i++) {
632                 if (buttons[i].sdl == event.button.button) {
633                     if (event.type == SDL_MOUSEBUTTONDOWN)
634                         vout_display_SendEventMousePressed(vd, buttons[i].vlc);
635                     else
636                         vout_display_SendEventMouseReleased(vd, buttons[i].vlc);
637                 }
638             }
639             break;
640         }
641
642         case SDL_MOUSEMOTION: {
643             if (sys->place.width <= 0 || sys->place.height <= 0)
644                 break;
645
646             const int x = (int64_t)(event.motion.x - sys->place.x) * vd->source.i_width  / sys->place.width;
647             const int y = (int64_t)(event.motion.y - sys->place.y) * vd->source.i_height / sys->place.height;
648
649             SDL_ShowCursor(1);
650             if (x >= 0 && (unsigned)x < vd->source.i_width &&
651                 y >= 0 && (unsigned)y < vd->source.i_height)
652                 vout_display_SendEventMouseMoved(vd, x, y);
653             break;
654         }
655
656         case SDL_VIDEORESIZE:
657             vout_display_SendEventDisplaySize(vd, event.resize.w, event.resize.h, vd->cfg->is_fullscreen);
658             break;
659
660         default:
661             break;
662         }
663     }
664
665 }
666
667 static const struct {
668     SDLKey sdl_key;
669     int    vlckey;
670
671 } sdlkeys_to_vlckeys[] = {
672     { SDLK_F1,  KEY_F1 },
673     { SDLK_F2,  KEY_F2 },
674     { SDLK_F3,  KEY_F3 },
675     { SDLK_F4,  KEY_F4 },
676     { SDLK_F5,  KEY_F5 },
677     { SDLK_F6,  KEY_F6 },
678     { SDLK_F7,  KEY_F7 },
679     { SDLK_F8,  KEY_F8 },
680     { SDLK_F9,  KEY_F9 },
681     { SDLK_F10, KEY_F10 },
682     { SDLK_F11, KEY_F11 },
683     { SDLK_F12, KEY_F12 },
684
685     { SDLK_RETURN, KEY_ENTER },
686     { SDLK_KP_ENTER, KEY_ENTER },
687     { SDLK_SPACE, KEY_SPACE },
688     { SDLK_ESCAPE, KEY_ESC },
689
690     { SDLK_MENU, KEY_MENU },
691     { SDLK_LEFT, KEY_LEFT },
692     { SDLK_RIGHT, KEY_RIGHT },
693     { SDLK_UP, KEY_UP },
694     { SDLK_DOWN, KEY_DOWN },
695
696     { SDLK_HOME, KEY_HOME },
697     { SDLK_END, KEY_END },
698     { SDLK_PAGEUP, KEY_PAGEUP },
699     { SDLK_PAGEDOWN,  KEY_PAGEDOWN },
700
701     { SDLK_INSERT, KEY_INSERT },
702     { SDLK_DELETE, KEY_DELETE },
703     /*TODO: find a equivalent for SDL 
704     { , KEY_MEDIA_NEXT_TRACK }
705     { , KEY_MEDIA_PREV_TRACK }
706     { , KEY_VOLUME_MUTE }
707     { , KEY_VOLUME_DOWN }
708     { , KEY_VOLUME_UP }
709     { , KEY_MEDIA_PLAY_PAUSE }
710     { , KEY_MEDIA_PLAY_PAUSE }*/
711
712     { 0, 0 }
713 };
714
715 static int ConvertKey(SDLKey sdl_key)
716 {
717     for (int i = 0; sdlkeys_to_vlckeys[i].sdl_key != 0; i++) {
718         if (sdlkeys_to_vlckeys[i].sdl_key == sdl_key)
719             return sdlkeys_to_vlckeys[i].vlckey;
720     }
721     return 0;
722 }
723