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