Remove legacy parameter from add_string()
[vlc/asuraparaju-public.git] / modules / video_output / sdl.c
blobddd13c125335ca5b99d05be5c61aa485efb8e9a6
1 /*****************************************************************************
2 * sdl.c: SDL video output display method
3 *****************************************************************************
4 * Copyright (C) 1998-2009 the VideoLAN team
5 * $Id$
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>
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.
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.
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 *****************************************************************************/
27 /*****************************************************************************
28 * Preamble
29 *****************************************************************************/
30 #ifdef HAVE_CONFIG_H
31 # include "config.h"
32 #endif
34 #include <vlc_common.h>
35 #include <vlc_plugin.h>
36 #include <vlc_vout_display.h>
37 #include <vlc_picture_pool.h>
39 #include <assert.h>
41 #include <SDL.h>
43 #ifndef WIN32
44 # ifdef X_DISPLAY_MISSING
45 # error Xlib required due to XInitThreads
46 # endif
47 # include <vlc_xlib.h>
48 #endif
50 /*****************************************************************************
51 * Module descriptor
52 *****************************************************************************/
53 static int Open (vlc_object_t *);
54 static void Close(vlc_object_t *);
56 #define CHROMA_TEXT N_("SDL chroma format")
57 #define CHROMA_LONGTEXT N_(\
58 "Force the SDL renderer to use a specific chroma format instead of " \
59 "trying to improve performances by using the most efficient one.")
61 vlc_module_begin()
62 set_shortname("SDL")
63 set_category(CAT_VIDEO)
64 set_subcategory(SUBCAT_VIDEO_VOUT)
65 set_description(N_("Simple DirectMedia Layer video output"))
66 set_capability("vout display", 60)
67 add_shortcut("sdl")
68 add_string("sdl-chroma", NULL, CHROMA_TEXT, CHROMA_LONGTEXT, true)
69 add_obsolete_string("sdl-video-driver") /* obsolete since 1.1.0 */
70 set_callbacks(Open, Close)
71 #if defined(__i386__) || defined(__x86_64__)
72 /* On i386, SDL is linked against svgalib */
73 cannot_unload_broken_library()
74 #endif
75 vlc_module_end()
78 /*****************************************************************************
79 * Local prototypes
80 *****************************************************************************/
81 static picture_pool_t *Pool (vout_display_t *, unsigned);
82 static void PictureDisplay(vout_display_t *, picture_t *);
83 static int Control(vout_display_t *, int, va_list);
84 static void Manage(vout_display_t *);
86 /* */
87 static int ConvertKey(SDLKey);
89 /* */
90 static vlc_mutex_t sdl_lock = VLC_STATIC_MUTEX;
92 /* */
93 struct vout_display_sys_t {
94 vout_display_place_t place;
96 SDL_Surface *display;
97 int display_bpp;
98 uint32_t display_flags;
100 unsigned int desktop_width;
101 unsigned int desktop_height;
103 /* For YUV output */
104 SDL_Overlay *overlay;
105 bool is_uv_swapped;
107 /* */
108 picture_pool_t *pool;
112 * This function initializes SDL vout method.
114 static int Open(vlc_object_t *object)
116 vout_display_t *vd = (vout_display_t *)object;
117 vout_display_sys_t *sys;
119 #ifndef WIN32
120 if (!vlc_xlib_init (object))
121 return VLC_EGENERIC;
122 #endif
124 /* XXX: check for conflicts with the SDL audio output */
125 vlc_mutex_lock(&sdl_lock);
127 /* Check if SDL video module has been initialized */
128 if (SDL_WasInit(SDL_INIT_VIDEO) != 0) {
129 vlc_mutex_unlock(&sdl_lock);
130 return VLC_EGENERIC;
133 vd->sys = sys = calloc(1, sizeof(*sys));
134 if (!sys) {
135 vlc_mutex_unlock(&sdl_lock);
136 return VLC_ENOMEM;
139 /* */
140 int sdl_flags = SDL_INIT_VIDEO;
141 #ifndef WIN32
142 /* Win32 SDL implementation doesn't support SDL_INIT_EVENTTHREAD yet*/
143 sdl_flags |= SDL_INIT_EVENTTHREAD;
144 #endif
145 #ifndef NDEBUG
146 /* In debug mode you may want vlc to dump a core instead of staying stuck */
147 sdl_flags |= SDL_INIT_NOPARACHUTE;
148 #endif
150 /* Initialize library */
151 if (SDL_Init(sdl_flags) < 0) {
152 vlc_mutex_unlock(&sdl_lock);
154 msg_Err(vd, "cannot initialize SDL (%s)", SDL_GetError());
155 free(sys);
156 return VLC_EGENERIC;
158 vlc_mutex_unlock(&sdl_lock);
160 /* Translate keys into unicode */
161 SDL_EnableUNICODE(1);
163 /* Get the desktop resolution */
164 /* FIXME: SDL has a problem with virtual desktop */
165 sys->desktop_width = SDL_GetVideoInfo()->current_w;
166 sys->desktop_height = SDL_GetVideoInfo()->current_h;
168 /* */
169 video_format_t fmt = vd->fmt;
171 /* */
172 vout_display_info_t info = vd->info;
174 /* Set main window's size */
175 int display_width;
176 int display_height;
177 if (vd->cfg->is_fullscreen) {
178 display_width = sys->desktop_width;
179 display_height = sys->desktop_height;
180 } else {
181 display_width = vd->cfg->display.width;
182 display_height = vd->cfg->display.height;
185 /* Initialize flags and cursor */
186 sys->display_flags = SDL_ANYFORMAT | SDL_HWPALETTE | SDL_HWSURFACE | SDL_DOUBLEBUF;
187 sys->display_flags |= vd->cfg->is_fullscreen ? SDL_FULLSCREEN : SDL_RESIZABLE;
189 sys->display_bpp = SDL_VideoModeOK(display_width, display_height,
190 16, sys->display_flags);
191 if (sys->display_bpp == 0) {
192 msg_Err(vd, "no video mode available");
193 goto error;
195 vout_display_DeleteWindow(vd, NULL);
197 sys->display = SDL_SetVideoMode(display_width, display_height,
198 sys->display_bpp, sys->display_flags);
199 if (!sys->display) {
200 msg_Err(vd, "cannot set video mode");
201 goto error;
204 /* We keep the surface locked forever */
205 SDL_LockSurface(sys->display);
207 /* */
208 vlc_fourcc_t forced_chroma = 0;
209 char *psz_chroma = var_InheritString(vd, "sdl-chroma");
210 if (psz_chroma) {
211 forced_chroma = vlc_fourcc_GetCodecFromString(VIDEO_ES, psz_chroma);
212 if (forced_chroma)
213 msg_Dbg(vd, "Forcing chroma to 0x%.8x (%4.4s)",
214 forced_chroma, (const char*)&forced_chroma);
215 free(psz_chroma);
218 /* Try to open an overlay if requested */
219 sys->overlay = NULL;
220 const bool is_overlay = var_InheritBool(vd, "overlay");
221 if (is_overlay) {
222 static const struct
224 vlc_fourcc_t vlc;
225 uint32_t sdl;
226 } vlc_to_sdl[] = {
227 { VLC_CODEC_YV12, SDL_YV12_OVERLAY },
228 { VLC_CODEC_I420, SDL_IYUV_OVERLAY },
229 { VLC_CODEC_YUYV, SDL_YUY2_OVERLAY },
230 { VLC_CODEC_UYVY, SDL_UYVY_OVERLAY },
231 { VLC_CODEC_YVYU, SDL_YVYU_OVERLAY },
233 { 0, 0 }
235 const vlc_fourcc_t forced_chromas[] = {
236 forced_chroma, 0
238 const vlc_fourcc_t *fallback_chromas =
239 vlc_fourcc_GetYUVFallback(fmt.i_chroma);
240 const vlc_fourcc_t *chromas = forced_chroma ? forced_chromas : fallback_chromas;
242 for (int pass = forced_chroma ? 1 : 0; pass < 2 && !sys->overlay; pass++) {
243 for (int i = 0; chromas[i] != 0; i++) {
244 const vlc_fourcc_t vlc = chromas[i];
246 uint32_t sdl = 0;
247 for (int j = 0; vlc_to_sdl[j].vlc != 0 && !sdl; j++) {
248 if (vlc_to_sdl[j].vlc == vlc)
249 sdl = vlc_to_sdl[j].sdl;
251 if (!sdl)
252 continue;
254 sys->overlay = SDL_CreateYUVOverlay(fmt.i_width, fmt.i_height,
255 sdl, sys->display);
256 if (sys->overlay && !sys->overlay->hw_overlay && pass == 0) {
257 /* Ignore non hardware overlay surface in first pass */
258 SDL_FreeYUVOverlay(sys->overlay);
259 sys->overlay = NULL;
261 if (sys->overlay) {
262 /* We keep the surface locked forever */
263 SDL_LockYUVOverlay(sys->overlay);
265 fmt.i_chroma = vlc;
266 sys->is_uv_swapped = vlc_fourcc_AreUVPlanesSwapped(fmt.i_chroma,
267 vd->fmt.i_chroma);
268 if (sys->is_uv_swapped)
269 fmt.i_chroma = vd->fmt.i_chroma;
270 break;
274 } else {
275 msg_Warn(vd, "SDL overlay disabled by the user");
278 /* */
279 vout_display_cfg_t place_cfg = *vd->cfg;
280 place_cfg.display.width = display_width;
281 place_cfg.display.height = display_height;
282 vout_display_PlacePicture(&sys->place, &vd->source, &place_cfg, !sys->overlay);
284 /* If no overlay, fallback to software output */
285 if (!sys->overlay) {
286 /* */
287 switch (sys->display->format->BitsPerPixel) {
288 case 8:
289 fmt.i_chroma = VLC_CODEC_RGB8;
290 break;
291 case 15:
292 fmt.i_chroma = VLC_CODEC_RGB15;
293 break;
294 case 16:
295 fmt.i_chroma = VLC_CODEC_RGB16;
296 break;
297 case 24:
298 fmt.i_chroma = VLC_CODEC_RGB24;
299 break;
300 case 32:
301 fmt.i_chroma = VLC_CODEC_RGB32;
302 break;
303 default:
304 msg_Err(vd, "unknown screen depth %i",
305 sys->display->format->BitsPerPixel);
306 goto error;
309 /* All we have is an RGB image with square pixels */
310 fmt.i_width = display_width;
311 fmt.i_height = display_height;
312 fmt.i_rmask = sys->display->format->Rmask;
313 fmt.i_gmask = sys->display->format->Gmask;
314 fmt.i_bmask = sys->display->format->Bmask;
316 info.has_pictures_invalid = true;
319 if (vd->cfg->display.title)
320 SDL_WM_SetCaption(vd->cfg->display.title,
321 vd->cfg->display.title);
322 else if (!sys->overlay)
323 SDL_WM_SetCaption(VOUT_TITLE " (software RGB SDL output)",
324 VOUT_TITLE " (software RGB SDL output)");
325 else if (sys->overlay->hw_overlay)
326 SDL_WM_SetCaption(VOUT_TITLE " (hardware YUV SDL output)",
327 VOUT_TITLE " (hardware YUV SDL output)");
328 else
329 SDL_WM_SetCaption(VOUT_TITLE " (software YUV SDL output)",
330 VOUT_TITLE " (software YUV SDL output)");
332 /* Setup events */
333 SDL_EventState(SDL_KEYUP, SDL_IGNORE); /* ignore keys up */
335 /* Setup vout_display now that everything is fine */
336 vd->fmt = fmt;
337 vd->info = info;
339 vd->pool = Pool;
340 vd->prepare = NULL;
341 vd->display = PictureDisplay;
342 vd->control = Control;
343 vd->manage = Manage;
345 /* */
346 vout_display_SendEventDisplaySize(vd, display_width, display_height, vd->cfg->is_fullscreen);
347 return VLC_SUCCESS;
349 error:
350 msg_Err(vd, "cannot set up SDL (%s)", SDL_GetError());
352 if (sys->display) {
353 SDL_UnlockSurface(sys->display);
354 SDL_FreeSurface(sys->display);
357 vlc_mutex_lock(&sdl_lock);
358 SDL_QuitSubSystem(SDL_INIT_VIDEO);
359 vlc_mutex_unlock(&sdl_lock);
361 free(sys);
362 return VLC_EGENERIC;
366 * Close a SDL video output
368 static void Close(vlc_object_t *object)
370 vout_display_t *vd = (vout_display_t *)object;
371 vout_display_sys_t *sys = vd->sys;
373 if (sys->pool)
374 picture_pool_Delete(sys->pool);
376 if (sys->overlay) {
377 SDL_LockYUVOverlay(sys->overlay);
378 SDL_FreeYUVOverlay(sys->overlay);
380 SDL_UnlockSurface (sys->display);
381 SDL_FreeSurface(sys->display);
383 vlc_mutex_lock(&sdl_lock);
384 SDL_QuitSubSystem(SDL_INIT_VIDEO);
385 vlc_mutex_unlock(&sdl_lock);
387 free(sys);
391 * Return a pool of direct buffers
393 static picture_pool_t *Pool(vout_display_t *vd, unsigned count)
395 vout_display_sys_t *sys = vd->sys;
396 VLC_UNUSED(count);
398 if (!sys->pool) {
399 picture_resource_t rsc;
401 memset(&rsc, 0, sizeof(rsc));
403 if (sys->overlay) {
404 SDL_Overlay *ol = sys->overlay;
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;
415 } else {
416 const int x = sys->place.x;
417 const int y = sys->place.y;
419 SDL_Surface *sf = sys->display;
420 SDL_FillRect(sf, NULL, 0);
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;
428 picture_t *picture = picture_NewFromResource(&vd->fmt, &rsc);;
429 if (!picture)
430 return NULL;
432 sys->pool = picture_pool_New(1, &picture);
435 return sys->pool;
439 * Display a picture
441 static void PictureDisplay(vout_display_t *vd, picture_t *p_pic)
443 vout_display_sys_t *sys = vd->sys;
445 if (sys->overlay) {
446 SDL_Rect disp;
447 disp.x = sys->place.x;
448 disp.y = sys->place.y;
449 disp.w = sys->place.width;
450 disp.h = sys->place.height;
452 SDL_UnlockYUVOverlay(sys->overlay);
453 SDL_DisplayYUVOverlay(sys->overlay , &disp);
454 SDL_LockYUVOverlay(sys->overlay);
455 } else {
456 SDL_Flip(sys->display);
459 picture_Release(p_pic);
464 * Control for vout display
466 static int Control(vout_display_t *vd, int query, va_list args)
468 vout_display_sys_t *sys = vd->sys;
470 switch (query)
472 case VOUT_DISPLAY_HIDE_MOUSE:
473 SDL_ShowCursor(0);
474 return VLC_SUCCESS;
476 case VOUT_DISPLAY_CHANGE_DISPLAY_SIZE: {
477 const vout_display_cfg_t *cfg = va_arg(args, const vout_display_cfg_t *);
479 /* */
480 sys->display = SDL_SetVideoMode(cfg->display.width,
481 cfg->display.height,
482 sys->display_bpp, sys->display_flags);
483 if (!sys->display) {
484 sys->display = SDL_SetVideoMode(vd->cfg->display.width,
485 vd->cfg->display.height,
486 sys->display_bpp, sys->display_flags);
487 return VLC_EGENERIC;
489 if (sys->overlay)
490 vout_display_PlacePicture(&sys->place, &vd->source, cfg, !sys->overlay);
491 else
492 vout_display_SendEventPicturesInvalid(vd);
493 return VLC_SUCCESS;
495 case VOUT_DISPLAY_CHANGE_FULLSCREEN: {
496 vout_display_cfg_t cfg = *va_arg(args, const vout_display_cfg_t *);
498 /* Fix flags */
499 sys->display_flags &= ~(SDL_FULLSCREEN | SDL_RESIZABLE);
500 sys->display_flags |= cfg.is_fullscreen ? SDL_FULLSCREEN : SDL_RESIZABLE;
502 if (cfg.is_fullscreen) {
503 cfg.display.width = sys->desktop_width;
504 cfg.display.height = sys->desktop_height;
507 if (sys->overlay) {
508 sys->display = SDL_SetVideoMode(cfg.display.width, cfg.display.height,
509 sys->display_bpp, sys->display_flags);
511 vout_display_PlacePicture(&sys->place, &vd->source, &cfg, !sys->overlay);
513 vout_display_SendEventDisplaySize(vd, cfg.display.width, cfg.display.height, cfg.is_fullscreen);
514 return VLC_SUCCESS;
516 case VOUT_DISPLAY_CHANGE_ZOOM:
517 case VOUT_DISPLAY_CHANGE_DISPLAY_FILLED:
518 case VOUT_DISPLAY_CHANGE_SOURCE_ASPECT: {
519 const vout_display_cfg_t *cfg;
520 const video_format_t *source;
522 if (query == VOUT_DISPLAY_CHANGE_SOURCE_ASPECT) {
523 source = va_arg(args, const video_format_t *);
524 cfg = vd->cfg;
525 } else {
526 source = &vd->source;
527 cfg = va_arg(args, const vout_display_cfg_t *);
529 if (sys->overlay) {
530 sys->display = SDL_SetVideoMode(cfg->display.width, cfg->display.height,
531 sys->display_bpp, sys->display_flags);
533 vout_display_PlacePicture(&sys->place, source, cfg, !sys->overlay);
534 } else {
535 vout_display_SendEventPicturesInvalid(vd);
537 return VLC_SUCCESS;
540 case VOUT_DISPLAY_RESET_PICTURES: {
541 /* */
542 assert(!sys->overlay);
544 /* */
545 if (sys->pool)
546 picture_pool_Delete(sys->pool);
547 sys->pool = NULL;
549 vout_display_PlacePicture(&sys->place, &vd->source, vd->cfg, !sys->overlay);
551 /* */
552 vd->fmt.i_width = sys->place.width;
553 vd->fmt.i_height = sys->place.height;
554 return VLC_SUCCESS;
557 case VOUT_DISPLAY_CHANGE_SOURCE_CROP:
558 case VOUT_DISPLAY_CHANGE_WINDOW_STATE:
559 /* I don't think it is possible to support with SDL:
560 * - crop
561 * - on top
563 return VLC_EGENERIC;
565 default:
566 msg_Err(vd, "Unsupported query in vout display SDL");
567 return VLC_EGENERIC;
572 * Proccess pending event
574 static void Manage(vout_display_t *vd)
576 vout_display_sys_t *sys = vd->sys;
577 SDL_Event event;
579 /* */
580 while (SDL_PollEvent(&event)) {
581 switch (event.type) {
582 case SDL_QUIT:
583 vout_display_SendEventClose(vd);
584 break;
586 case SDL_KEYDOWN: {
587 /* convert the key if possible */
588 int key = ConvertKey(event.key.keysym.sym);
590 if (!key) {
591 /* Find the right caracter */
592 if ((event.key.keysym.unicode & 0xff80) == 0) {
593 key = event.key.keysym.unicode & 0x7f;
594 /* FIXME: find a better solution than this
595 hack to find the right caracter */
596 if (key >= 1 && key <= 26)
597 key += 96;
598 else if (key >= 65 && key <= 90)
599 key += 32;
602 if (!key)
603 break;
605 if (event.key.keysym.mod & KMOD_SHIFT)
606 key |= KEY_MODIFIER_SHIFT;
607 if (event.key.keysym.mod & KMOD_CTRL)
608 key |= KEY_MODIFIER_CTRL;
609 if (event.key.keysym.mod & KMOD_ALT)
610 key |= KEY_MODIFIER_ALT;
611 vout_display_SendEventKey(vd, key);
612 break;
615 case SDL_MOUSEBUTTONDOWN:
616 case SDL_MOUSEBUTTONUP: {
617 static const struct { int sdl; int vlc; } buttons[] = {
618 { SDL_BUTTON_LEFT, MOUSE_BUTTON_LEFT },
619 { SDL_BUTTON_MIDDLE, MOUSE_BUTTON_CENTER },
620 { SDL_BUTTON_RIGHT, MOUSE_BUTTON_RIGHT },
621 { SDL_BUTTON_WHEELUP, MOUSE_BUTTON_WHEEL_UP },
622 { SDL_BUTTON_WHEELDOWN, MOUSE_BUTTON_WHEEL_DOWN },
623 { -1, -1 },
626 SDL_ShowCursor(1);
627 for (int i = 0; buttons[i].sdl != -1; i++) {
628 if (buttons[i].sdl == event.button.button) {
629 if (event.type == SDL_MOUSEBUTTONDOWN)
630 vout_display_SendEventMousePressed(vd, buttons[i].vlc);
631 else
632 vout_display_SendEventMouseReleased(vd, buttons[i].vlc);
635 break;
638 case SDL_MOUSEMOTION: {
639 if (sys->place.width <= 0 || sys->place.height <= 0)
640 break;
642 const int x = (int64_t)(event.motion.x - sys->place.x) * vd->source.i_width / sys->place.width;
643 const int y = (int64_t)(event.motion.y - sys->place.y) * vd->source.i_height / sys->place.height;
645 SDL_ShowCursor(1);
646 vout_display_SendEventMouseMoved(vd, x, y);
647 break;
650 case SDL_VIDEORESIZE:
651 vout_display_SendEventDisplaySize(vd, event.resize.w, event.resize.h, vd->cfg->is_fullscreen);
652 break;
654 default:
655 break;
661 static const struct {
662 SDLKey sdl_key;
663 int vlckey;
665 } sdlkeys_to_vlckeys[] = {
666 { SDLK_F1, KEY_F1 },
667 { SDLK_F2, KEY_F2 },
668 { SDLK_F3, KEY_F3 },
669 { SDLK_F4, KEY_F4 },
670 { SDLK_F5, KEY_F5 },
671 { SDLK_F6, KEY_F6 },
672 { SDLK_F7, KEY_F7 },
673 { SDLK_F8, KEY_F8 },
674 { SDLK_F9, KEY_F9 },
675 { SDLK_F10, KEY_F10 },
676 { SDLK_F11, KEY_F11 },
677 { SDLK_F12, KEY_F12 },
679 { SDLK_RETURN, KEY_ENTER },
680 { SDLK_KP_ENTER, KEY_ENTER },
681 { SDLK_SPACE, ' ' },
682 { SDLK_ESCAPE, KEY_ESC },
684 { SDLK_MENU, KEY_MENU },
685 { SDLK_LEFT, KEY_LEFT },
686 { SDLK_RIGHT, KEY_RIGHT },
687 { SDLK_UP, KEY_UP },
688 { SDLK_DOWN, KEY_DOWN },
690 { SDLK_HOME, KEY_HOME },
691 { SDLK_END, KEY_END },
692 { SDLK_PAGEUP, KEY_PAGEUP },
693 { SDLK_PAGEDOWN, KEY_PAGEDOWN },
695 { SDLK_INSERT, KEY_INSERT },
696 { SDLK_DELETE, KEY_DELETE },
697 /*TODO: find a equivalent for SDL
698 { , KEY_MEDIA_NEXT_TRACK }
699 { , KEY_MEDIA_PREV_TRACK }
700 { , KEY_VOLUME_MUTE }
701 { , KEY_VOLUME_DOWN }
702 { , KEY_VOLUME_UP }
703 { , KEY_MEDIA_PLAY_PAUSE }
704 { , KEY_MEDIA_PLAY_PAUSE }*/
706 { 0, 0 }
709 static int ConvertKey(SDLKey sdl_key)
711 for (int i = 0; sdlkeys_to_vlckeys[i].sdl_key != 0; i++) {
712 if (sdlkeys_to_vlckeys[i].sdl_key == sdl_key)
713 return sdlkeys_to_vlckeys[i].vlckey;
715 return 0;