demux:ogg: no need to change the es_format_t before a copy
[vlc.git] / modules / video_output / sdl.c
blob1fe55d64f314297ad399ce278389f56f3cfac2ee
1 /*****************************************************************************
2 * sdl.c: SDL video output display method
3 *****************************************************************************
4 * Copyright (C) 1998-2009 VLC authors and VideoLAN
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 it
13 * under the terms of the GNU Lesser General Public License as published by
14 * the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
22 * You should have received a copy of the GNU Lesser General Public License
23 * along with this program; if not, write to the Free Software Foundation,
24 * 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 #if !defined(_WIN32) && !defined(__OS2__)
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 #define OVERLAY_TEXT N_("YUV overlay")
62 #define OVERLAY_LONGTEXT N_(\
63 "Use the hardware YUV overlay of the graphic card (if available).")
65 vlc_module_begin()
66 set_shortname("SDL")
67 set_category(CAT_VIDEO)
68 set_subcategory(SUBCAT_VIDEO_VOUT)
69 set_description(N_("Simple DirectMedia Layer video output"))
70 set_capability("vout display", 70)
71 add_shortcut("sdl")
72 add_bool("sdl-overlay", true, OVERLAY_TEXT, OVERLAY_LONGTEXT, false)
73 add_string("sdl-chroma", NULL, CHROMA_TEXT, CHROMA_LONGTEXT, true)
74 add_obsolete_string("sdl-video-driver") /* obsolete since 1.1.0 */
75 set_callbacks(Open, Close)
76 #if defined(__i386__) || defined(__x86_64__)
77 /* On i386, SDL is linked against svgalib */
78 cannot_unload_broken_library()
79 #endif
80 vlc_module_end()
83 /*****************************************************************************
84 * Local prototypes
85 *****************************************************************************/
86 static picture_pool_t *Pool (vout_display_t *, unsigned);
87 static void PictureDisplay(vout_display_t *, picture_t *, subpicture_t *);
88 static int Control(vout_display_t *, int, va_list);
89 static void Manage(vout_display_t *);
91 /* */
92 static int ConvertKey(SDLKey);
94 /* */
95 static vlc_mutex_t sdl_lock = VLC_STATIC_MUTEX;
97 /* */
98 struct vout_display_sys_t {
99 vout_display_place_t place;
101 SDL_Surface *display;
102 int display_bpp;
103 uint32_t display_flags;
105 unsigned int desktop_width;
106 unsigned int desktop_height;
108 /* For YUV output */
109 SDL_Overlay *overlay;
110 bool is_uv_swapped;
112 /* */
113 picture_pool_t *pool;
117 * This function initializes SDL vout method.
119 static int Open(vlc_object_t *object)
121 vout_display_t *vd = (vout_display_t *)object;
122 vout_display_sys_t *sys;
124 if (vout_display_IsWindowed(vd))
125 return VLC_EGENERIC;
126 #if !defined(_WIN32) && !defined(__OS2__)
127 if (!vlc_xlib_init (object))
128 return VLC_EGENERIC;
129 #endif
131 /* XXX: check for conflicts with the SDL audio output */
132 vlc_mutex_lock(&sdl_lock);
134 /* Check if SDL video module has been initialized */
135 if (SDL_WasInit(SDL_INIT_VIDEO) != 0) {
136 vlc_mutex_unlock(&sdl_lock);
137 return VLC_EGENERIC;
140 vd->sys = sys = calloc(1, sizeof(*sys));
141 if (!sys) {
142 vlc_mutex_unlock(&sdl_lock);
143 return VLC_ENOMEM;
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 /* In debug mode you may want vlc to dump a core instead of staying stuck */
153 sdl_flags |= SDL_INIT_NOPARACHUTE;
155 /* Initialize library */
156 if (SDL_Init(sdl_flags) < 0) {
157 vlc_mutex_unlock(&sdl_lock);
159 msg_Err(vd, "cannot initialize SDL (%s)", SDL_GetError());
160 free(sys);
161 return VLC_EGENERIC;
163 vlc_mutex_unlock(&sdl_lock);
165 /* Translate keys into unicode */
166 SDL_EnableUNICODE(1);
168 /* Get the desktop resolution */
169 /* FIXME: SDL has a problem with virtual desktop */
170 sys->desktop_width = SDL_GetVideoInfo()->current_w;
171 sys->desktop_height = SDL_GetVideoInfo()->current_h;
173 /* */
174 video_format_t fmt;
175 video_format_ApplyRotation(&fmt, &vd->fmt);
177 /* */
178 vout_display_info_t info = vd->info;
180 info.needs_event_thread = true;
182 /* Set main window's size */
183 int display_width;
184 int display_height;
185 if (vd->cfg->is_fullscreen) {
186 display_width = sys->desktop_width;
187 display_height = sys->desktop_height;
188 } else {
189 display_width = vd->cfg->display.width;
190 display_height = vd->cfg->display.height;
193 /* Initialize flags and cursor */
194 sys->display_flags = SDL_ANYFORMAT | SDL_HWPALETTE | SDL_HWSURFACE | SDL_DOUBLEBUF;
195 sys->display_flags |= vd->cfg->is_fullscreen ? SDL_FULLSCREEN : SDL_RESIZABLE;
197 sys->display_bpp = SDL_VideoModeOK(display_width, display_height,
198 16, sys->display_flags);
199 if (sys->display_bpp == 0) {
200 msg_Err(vd, "no video mode available");
201 goto error;
204 sys->display = SDL_SetVideoMode(display_width, display_height,
205 sys->display_bpp, sys->display_flags);
206 if (!sys->display) {
207 msg_Err(vd, "cannot set video mode");
208 goto error;
211 /* We keep the surface locked forever */
212 SDL_LockSurface(sys->display);
214 /* */
215 vlc_fourcc_t forced_chroma = 0;
216 char *psz_chroma = var_InheritString(vd, "sdl-chroma");
217 if (psz_chroma) {
218 forced_chroma = vlc_fourcc_GetCodecFromString(VIDEO_ES, psz_chroma);
219 if (forced_chroma)
220 msg_Dbg(vd, "Forcing chroma to 0x%.8x (%4.4s)",
221 forced_chroma, (const char*)&forced_chroma);
222 free(psz_chroma);
225 /* Try to open an overlay if requested */
226 sys->overlay = NULL;
227 const bool is_overlay = var_InheritBool(vd, "sdl-overlay");
228 if (is_overlay) {
229 static const struct
231 vlc_fourcc_t vlc;
232 uint32_t sdl;
233 } vlc_to_sdl[] = {
234 { VLC_CODEC_YV12, SDL_YV12_OVERLAY },
235 { VLC_CODEC_I420, SDL_IYUV_OVERLAY },
236 { VLC_CODEC_YUYV, SDL_YUY2_OVERLAY },
237 { VLC_CODEC_UYVY, SDL_UYVY_OVERLAY },
238 { VLC_CODEC_YVYU, SDL_YVYU_OVERLAY },
240 { 0, 0 }
242 const vlc_fourcc_t forced_chromas[] = {
243 forced_chroma, 0
245 const vlc_fourcc_t *fallback_chromas =
246 vlc_fourcc_GetYUVFallback(fmt.i_chroma);
247 const vlc_fourcc_t *chromas = forced_chroma ? forced_chromas : fallback_chromas;
249 for (int pass = forced_chroma ? 1 : 0; pass < 2 && !sys->overlay; pass++) {
250 for (int i = 0; chromas[i] != 0; i++) {
251 const vlc_fourcc_t vlc = chromas[i];
253 uint32_t sdl = 0;
254 for (int j = 0; vlc_to_sdl[j].vlc != 0 && !sdl; j++) {
255 if (vlc_to_sdl[j].vlc == vlc)
256 sdl = vlc_to_sdl[j].sdl;
258 if (!sdl)
259 continue;
261 sys->overlay = SDL_CreateYUVOverlay(fmt.i_width, fmt.i_height,
262 sdl, sys->display);
263 if (sys->overlay && !sys->overlay->hw_overlay && pass == 0) {
264 /* Ignore non hardware overlay surface in first pass */
265 SDL_FreeYUVOverlay(sys->overlay);
266 sys->overlay = NULL;
268 if (sys->overlay) {
269 /* We keep the surface locked forever */
270 SDL_LockYUVOverlay(sys->overlay);
272 fmt.i_chroma = vlc;
273 sys->is_uv_swapped = vlc_fourcc_AreUVPlanesSwapped(fmt.i_chroma,
274 vd->fmt.i_chroma);
275 if (sys->is_uv_swapped)
276 fmt.i_chroma = vd->fmt.i_chroma;
277 break;
281 } else {
282 msg_Warn(vd, "SDL overlay disabled by the user");
285 /* */
286 vout_display_cfg_t place_cfg = *vd->cfg;
287 place_cfg.display.width = display_width;
288 place_cfg.display.height = display_height;
289 vout_display_PlacePicture(&sys->place, &vd->source, &place_cfg, !sys->overlay);
291 /* If no overlay, fallback to software output */
292 if (!sys->overlay) {
293 /* */
294 switch (sys->display->format->BitsPerPixel) {
295 case 8:
296 fmt.i_chroma = VLC_CODEC_RGB8;
297 break;
298 case 15:
299 fmt.i_chroma = VLC_CODEC_RGB15;
300 break;
301 case 16:
302 fmt.i_chroma = VLC_CODEC_RGB16;
303 break;
304 case 24:
305 fmt.i_chroma = VLC_CODEC_RGB24;
306 break;
307 case 32:
308 fmt.i_chroma = VLC_CODEC_RGB32;
309 break;
310 default:
311 msg_Err(vd, "unknown screen depth %i",
312 sys->display->format->BitsPerPixel);
313 goto error;
316 /* All we have is an RGB image with square pixels */
317 fmt.i_width = display_width;
318 fmt.i_height = display_height;
319 fmt.i_rmask = sys->display->format->Rmask;
320 fmt.i_gmask = sys->display->format->Gmask;
321 fmt.i_bmask = sys->display->format->Bmask;
323 info.has_pictures_invalid = true;
326 if (vd->cfg->display.title)
327 SDL_WM_SetCaption(vd->cfg->display.title,
328 vd->cfg->display.title);
329 else if (!sys->overlay)
330 SDL_WM_SetCaption(VOUT_TITLE " (software RGB SDL output)",
331 VOUT_TITLE " (software RGB SDL output)");
332 else if (sys->overlay->hw_overlay)
333 SDL_WM_SetCaption(VOUT_TITLE " (hardware YUV SDL output)",
334 VOUT_TITLE " (hardware YUV SDL output)");
335 else
336 SDL_WM_SetCaption(VOUT_TITLE " (software YUV SDL output)",
337 VOUT_TITLE " (software YUV SDL output)");
339 /* Setup events */
340 SDL_EventState(SDL_KEYUP, SDL_IGNORE); /* ignore keys up */
342 /* Setup vout_display now that everything is fine */
343 vd->fmt = fmt;
344 vd->info = info;
346 vd->pool = Pool;
347 vd->prepare = NULL;
348 vd->display = PictureDisplay;
349 vd->control = Control;
350 vd->manage = Manage;
352 /* */
353 vout_display_SendEventDisplaySize(vd, display_width, display_height);
354 return VLC_SUCCESS;
356 error:
357 msg_Err(vd, "cannot set up SDL (%s)", SDL_GetError());
359 if (sys->display) {
360 SDL_UnlockSurface(sys->display);
361 SDL_FreeSurface(sys->display);
364 vlc_mutex_lock(&sdl_lock);
365 SDL_QuitSubSystem(SDL_INIT_VIDEO);
366 vlc_mutex_unlock(&sdl_lock);
368 free(sys);
369 return VLC_EGENERIC;
373 * Close a SDL video output
375 static void Close(vlc_object_t *object)
377 vout_display_t *vd = (vout_display_t *)object;
378 vout_display_sys_t *sys = vd->sys;
380 if (sys->pool)
381 picture_pool_Release(sys->pool);
383 if (sys->overlay) {
384 SDL_LockYUVOverlay(sys->overlay);
385 SDL_FreeYUVOverlay(sys->overlay);
387 SDL_UnlockSurface (sys->display);
388 SDL_FreeSurface(sys->display);
390 vlc_mutex_lock(&sdl_lock);
391 SDL_QuitSubSystem(SDL_INIT_VIDEO);
392 vlc_mutex_unlock(&sdl_lock);
394 free(sys);
398 * Return a pool of direct buffers
400 static picture_pool_t *Pool(vout_display_t *vd, unsigned count)
402 vout_display_sys_t *sys = vd->sys;
403 VLC_UNUSED(count);
405 if (!sys->pool) {
406 picture_resource_t rsc;
408 memset(&rsc, 0, sizeof(rsc));
410 if (sys->overlay) {
411 SDL_Overlay *ol = sys->overlay;
413 for (int i = 0; i < ol->planes; i++) {
414 rsc.p[i].p_pixels = ol->pixels[ i > 0 && sys->is_uv_swapped ? (3-i) : i];
415 rsc.p[i].i_pitch = ol->pitches[i > 0 && sys->is_uv_swapped ? (3-i) : i];
416 rsc.p[i].i_lines = ol->h;
417 if (ol->format == SDL_YV12_OVERLAY ||
418 ol->format == SDL_IYUV_OVERLAY)
419 rsc.p[i].i_lines /= 2;
422 } else {
423 const int x = sys->place.x;
424 const int y = sys->place.y;
426 SDL_Surface *sf = sys->display;
427 SDL_FillRect(sf, NULL, 0);
429 assert(x >= 0 && y >= 0);
430 rsc.p[0].p_pixels = (uint8_t*)sf->pixels + y * sf->pitch + x * ((sf->format->BitsPerPixel + 7) / 8);
431 rsc.p[0].i_pitch = sf->pitch;
432 rsc.p[0].i_lines = vd->fmt.i_height;
435 picture_t *picture = picture_NewFromResource(&vd->fmt, &rsc);;
436 if (!picture)
437 return NULL;
439 sys->pool = picture_pool_New(1, &picture);
442 return sys->pool;
446 * Display a picture
448 static void PictureDisplay(vout_display_t *vd, picture_t *p_pic, subpicture_t *p_subpicture)
450 vout_display_sys_t *sys = vd->sys;
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;
459 SDL_UnlockYUVOverlay(sys->overlay);
460 SDL_DisplayYUVOverlay(sys->overlay , &disp);
461 SDL_LockYUVOverlay(sys->overlay);
462 } else {
463 SDL_Flip(sys->display);
466 picture_Release(p_pic);
467 VLC_UNUSED(p_subpicture);
472 * Control for vout display
474 static int Control(vout_display_t *vd, int query, va_list args)
476 vout_display_sys_t *sys = vd->sys;
478 switch (query)
480 case VOUT_DISPLAY_HIDE_MOUSE:
481 SDL_ShowCursor(0);
482 return VLC_SUCCESS;
484 case VOUT_DISPLAY_CHANGE_DISPLAY_SIZE: {
485 const vout_display_cfg_t *cfg = va_arg(args, const vout_display_cfg_t *);
487 /* */
488 sys->display = SDL_SetVideoMode(cfg->display.width,
489 cfg->display.height,
490 sys->display_bpp, sys->display_flags);
491 if (!sys->display) {
492 sys->display = SDL_SetVideoMode(vd->cfg->display.width,
493 vd->cfg->display.height,
494 sys->display_bpp, sys->display_flags);
495 return VLC_EGENERIC;
497 if (sys->overlay)
498 vout_display_PlacePicture(&sys->place, &vd->source, cfg, !sys->overlay);
499 else
500 vout_display_SendEventPicturesInvalid(vd);
501 return VLC_SUCCESS;
503 case VOUT_DISPLAY_CHANGE_FULLSCREEN: {
504 bool fs = va_arg(args, int);
506 /* Fix flags */
507 sys->display_flags &= ~(SDL_FULLSCREEN | SDL_RESIZABLE);
508 sys->display_flags |= fs ? SDL_FULLSCREEN : SDL_RESIZABLE;
510 if (sys->overlay)
511 sys->display = SDL_SetVideoMode(sys->desktop_width, sys->desktop_height,
512 sys->display_bpp, sys->display_flags);
514 vout_display_SendEventDisplaySize(vd, sys->desktop_width, sys->desktop_height);
515 return VLC_SUCCESS;
517 case VOUT_DISPLAY_CHANGE_ZOOM:
518 case VOUT_DISPLAY_CHANGE_DISPLAY_FILLED:
519 case VOUT_DISPLAY_CHANGE_SOURCE_ASPECT: {
520 const vout_display_cfg_t *cfg;
521 const video_format_t *source;
523 if (query == VOUT_DISPLAY_CHANGE_SOURCE_ASPECT) {
524 source = va_arg(args, const video_format_t *);
525 cfg = vd->cfg;
526 } else {
527 source = &vd->source;
528 cfg = va_arg(args, const vout_display_cfg_t *);
530 if (sys->overlay) {
531 sys->display = SDL_SetVideoMode(cfg->display.width, cfg->display.height,
532 sys->display_bpp, sys->display_flags);
534 vout_display_PlacePicture(&sys->place, source, cfg, !sys->overlay);
535 } else {
536 vout_display_SendEventPicturesInvalid(vd);
538 return VLC_SUCCESS;
541 case VOUT_DISPLAY_RESET_PICTURES: {
542 /* */
543 assert(!sys->overlay);
545 /* */
546 if (sys->pool)
547 picture_pool_Release(sys->pool);
548 sys->pool = NULL;
550 vout_display_PlacePicture(&sys->place, &vd->source, vd->cfg, !sys->overlay);
552 /* */
553 vd->fmt.i_width = sys->place.width;
554 vd->fmt.i_height = sys->place.height;
555 return VLC_SUCCESS;
558 case VOUT_DISPLAY_CHANGE_SOURCE_CROP:
559 /* I don't think it is possible to support with SDL:
560 * - crop
562 return VLC_EGENERIC;
564 default:
565 msg_Err(vd, "Unsupported query in vout display SDL");
566 return VLC_EGENERIC;
571 * Proccess pending event
573 static void Manage(vout_display_t *vd)
575 vout_display_sys_t *sys = vd->sys;
576 SDL_Event event;
578 /* */
579 while (SDL_PollEvent(&event)) {
580 switch (event.type) {
581 case SDL_QUIT:
582 vout_display_SendEventClose(vd);
583 break;
585 case SDL_KEYDOWN: {
586 /* convert the key if possible */
587 int key = ConvertKey(event.key.keysym.sym);
589 if (!key) {
590 /* Find the right caracter */
591 if ((event.key.keysym.unicode & 0xff80) == 0) {
592 key = event.key.keysym.unicode & 0x7f;
593 /* FIXME: find a better solution than this
594 hack to find the right caracter */
595 if (key >= 1 && key <= 26)
596 key += 96;
597 else if (key >= 65 && key <= 90)
598 key += 32;
601 if (!key)
602 break;
604 if (event.key.keysym.mod & KMOD_SHIFT)
605 key |= KEY_MODIFIER_SHIFT;
606 if (event.key.keysym.mod & KMOD_CTRL)
607 key |= KEY_MODIFIER_CTRL;
608 if (event.key.keysym.mod & KMOD_ALT)
609 key |= KEY_MODIFIER_ALT;
610 vout_display_SendEventKey(vd, key);
611 break;
614 case SDL_MOUSEBUTTONDOWN:
615 case SDL_MOUSEBUTTONUP: {
616 static const struct { int sdl; int vlc; } buttons[] = {
617 { SDL_BUTTON_LEFT, MOUSE_BUTTON_LEFT },
618 { SDL_BUTTON_MIDDLE, MOUSE_BUTTON_CENTER },
619 { SDL_BUTTON_RIGHT, MOUSE_BUTTON_RIGHT },
620 { SDL_BUTTON_WHEELUP, MOUSE_BUTTON_WHEEL_UP },
621 { SDL_BUTTON_WHEELDOWN, MOUSE_BUTTON_WHEEL_DOWN },
622 { -1, -1 },
625 SDL_ShowCursor(1);
626 for (int i = 0; buttons[i].sdl != -1; i++) {
627 if (buttons[i].sdl == event.button.button) {
628 if (event.type == SDL_MOUSEBUTTONDOWN)
629 vout_display_SendEventMousePressed(vd, buttons[i].vlc);
630 else
631 vout_display_SendEventMouseReleased(vd, buttons[i].vlc);
634 break;
637 case SDL_MOUSEMOTION: {
638 if (sys->place.width <= 0 || sys->place.height <= 0)
639 break;
641 SDL_ShowCursor(1);
643 vout_display_SendMouseMovedDisplayCoordinates(vd, ORIENT_NORMAL,
644 event.motion.x, event.motion.y,
645 &sys->place);
646 break;
649 case SDL_VIDEORESIZE:
650 vout_display_SendEventDisplaySize(vd, event.resize.w, event.resize.h);
651 break;
653 default:
654 break;
660 static const struct {
661 SDLKey sdl_key;
662 int vlckey;
664 } sdlkeys_to_vlckeys[] = {
665 { SDLK_F1, KEY_F1 },
666 { SDLK_F2, KEY_F2 },
667 { SDLK_F3, KEY_F3 },
668 { SDLK_F4, KEY_F4 },
669 { SDLK_F5, KEY_F5 },
670 { SDLK_F6, KEY_F6 },
671 { SDLK_F7, KEY_F7 },
672 { SDLK_F8, KEY_F8 },
673 { SDLK_F9, KEY_F9 },
674 { SDLK_F10, KEY_F10 },
675 { SDLK_F11, KEY_F11 },
676 { SDLK_F12, KEY_F12 },
678 { SDLK_RETURN, KEY_ENTER },
679 { SDLK_KP_ENTER, KEY_ENTER },
680 { SDLK_SPACE, ' ' },
681 { SDLK_ESCAPE, KEY_ESC },
683 { SDLK_MENU, KEY_MENU },
684 { SDLK_LEFT, KEY_LEFT },
685 { SDLK_RIGHT, KEY_RIGHT },
686 { SDLK_UP, KEY_UP },
687 { SDLK_DOWN, KEY_DOWN },
689 { SDLK_HOME, KEY_HOME },
690 { SDLK_END, KEY_END },
691 { SDLK_PAGEUP, KEY_PAGEUP },
692 { SDLK_PAGEDOWN, KEY_PAGEDOWN },
694 { SDLK_INSERT, KEY_INSERT },
695 { SDLK_DELETE, KEY_DELETE },
696 /*TODO: find a equivalent for SDL
697 { , KEY_MEDIA_NEXT_TRACK }
698 { , KEY_MEDIA_PREV_TRACK }
699 { , KEY_VOLUME_MUTE }
700 { , KEY_VOLUME_DOWN }
701 { , KEY_VOLUME_UP }
702 { , KEY_MEDIA_PLAY_PAUSE }
703 { , KEY_MEDIA_PLAY_PAUSE }*/
705 { 0, 0 }
708 static int ConvertKey(SDLKey sdl_key)
710 for (int i = 0; sdlkeys_to_vlckeys[i].sdl_key != 0; i++) {
711 if (sdlkeys_to_vlckeys[i].sdl_key == sdl_key)
712 return sdlkeys_to_vlckeys[i].vlckey;
714 return 0;