sdl.c 21.6 KB
Newer Older
1
/*****************************************************************************
2
 * sdl.c: SDL video output display method
3
 *****************************************************************************
Jean-Baptiste Kempf's avatar
LGPL  
Jean-Baptiste Kempf committed
4
 * Copyright (C) 1998-2009 VLC authors and VideoLAN
5
 * $Id$
6 7 8 9
 *
 * Authors: Samuel Hocevar <sam@zoy.org>
 *          Pierre Baillet <oct@zoy.org>
 *          Arnaud de Bossoreille de Ribou <bozo@via.ecp.fr>
10
 *          Laurent Aimar <fenrir _AT_ videolan _DOT_ org>
11
 *
Jean-Baptiste Kempf's avatar
LGPL  
Jean-Baptiste Kempf committed
12 13 14
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2.1 of the License, or
15
 * (at your option) any later version.
16
 *
17 18
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Jean-Baptiste Kempf's avatar
LGPL  
Jean-Baptiste Kempf committed
19 20
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Lesser General Public License for more details.
21
 *
Jean-Baptiste Kempf's avatar
LGPL  
Jean-Baptiste Kempf committed
22 23 24
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
25 26 27 28 29
 *****************************************************************************/

/*****************************************************************************
 * Preamble
 *****************************************************************************/
30 31 32 33
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif

34
#include <vlc_common.h>
35
#include <vlc_plugin.h>
36 37
#include <vlc_vout_display.h>
#include <vlc_picture_pool.h>
38

39
#include <assert.h>
40

41
#include <SDL.h>
42

43
#if !defined(_WIN32) && !defined(__OS2__)
44 45 46 47 48 49
# ifdef X_DISPLAY_MISSING
#  error Xlib required due to XInitThreads
# endif
# include <vlc_xlib.h>
#endif

50
/*****************************************************************************
51
 * Module descriptor
52
 *****************************************************************************/
53 54
static int  Open (vlc_object_t *);
static void Close(vlc_object_t *);
55

56 57 58 59
#define CHROMA_TEXT N_("SDL chroma format")
#define CHROMA_LONGTEXT N_(\
    "Force the SDL renderer to use a specific chroma format instead of " \
    "trying to improve performances by using the most efficient one.")
60

61 62 63 64
#define OVERLAY_TEXT N_("YUV overlay")
#define OVERLAY_LONGTEXT N_(\
    "Use the hardware YUV overlay of the graphic card (if available).")

65 66 67 68 69
vlc_module_begin()
    set_shortname("SDL")
    set_category(CAT_VIDEO)
    set_subcategory(SUBCAT_VIDEO_VOUT)
    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 76 77
    set_callbacks(Open, Close)
#if defined(__i386__) || defined(__x86_64__)
    /* On i386, SDL is linked against svgalib */
78
    cannot_unload_broken_library()
79 80
#endif
vlc_module_end()
81

82 83 84 85

/*****************************************************************************
 * Local prototypes
 *****************************************************************************/
86
static picture_pool_t *Pool  (vout_display_t *, unsigned);
87
static void           PictureDisplay(vout_display_t *, picture_t *, subpicture_t *);
88 89
static int            Control(vout_display_t *, int, va_list);
static void           Manage(vout_display_t *);
90

91 92
/* */
static int ConvertKey(SDLKey);
93

94 95
/* */
static vlc_mutex_t sdl_lock = VLC_STATIC_MUTEX;
96

97 98 99
/* */
struct vout_display_sys_t {
    vout_display_place_t place;
100

101 102 103
    SDL_Surface          *display;
    int                  display_bpp;
    uint32_t             display_flags;
104

105 106
    unsigned int         desktop_width;
    unsigned int         desktop_height;
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
107

108 109 110
    /* For YUV output */
    SDL_Overlay          *overlay;
    bool                 is_uv_swapped;
111

112 113 114
    /* */
    picture_pool_t       *pool;
};
115

116 117 118 119 120 121 122
/**
 * This function initializes SDL vout method.
 */
static int Open(vlc_object_t *object)
{
    vout_display_t *vd = (vout_display_t *)object;
    vout_display_sys_t *sys;
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
123

124 125
    if (vout_display_IsWindowed(vd))
        return VLC_EGENERIC;
126
#if !defined(_WIN32) && !defined(__OS2__)
127 128 129 130
    if (!vlc_xlib_init (object))
        return VLC_EGENERIC;
#endif

131 132
    /* XXX: check for conflicts with the SDL audio output */
    vlc_mutex_lock(&sdl_lock);
133

134
    /* Check if SDL video module has been initialized */
135 136
    if (SDL_WasInit(SDL_INIT_VIDEO) != 0) {
        vlc_mutex_unlock(&sdl_lock);
137
        return VLC_EGENERIC;
138 139
    }

140 141 142 143 144
    vd->sys = sys = calloc(1, sizeof(*sys));
    if (!sys) {
        vlc_mutex_unlock(&sdl_lock);
        return VLC_ENOMEM;
    }
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 153 154 155 156 157 158 159 160
    /* In debug mode you may want vlc to dump a core instead of staying stuck */
    sdl_flags |= SDL_INIT_NOPARACHUTE;

    /* Initialize library */
    if (SDL_Init(sdl_flags) < 0) {
        vlc_mutex_unlock(&sdl_lock);

        msg_Err(vd, "cannot initialize SDL (%s)", SDL_GetError());
        free(sys);
161
        return VLC_EGENERIC;
162
    }
163
    vlc_mutex_unlock(&sdl_lock);
164

165 166 167
    /* Translate keys into unicode */
    SDL_EnableUNICODE(1);

168
    /* Get the desktop resolution */
169
    /* FIXME: SDL has a problem with virtual desktop */
170 171
    sys->desktop_width  = SDL_GetVideoInfo()->current_w;
    sys->desktop_height = SDL_GetVideoInfo()->current_h;
172

173
    /* */
174
    video_format_t fmt;
175
    video_format_ApplyRotation(&fmt, &vd->fmt);
176

177 178
    /* */
    vout_display_info_t info = vd->info;
179

180 181
    info.needs_event_thread = true;

182 183 184 185 186 187 188 189 190 191
    /* Set main window's size */
    int display_width;
    int display_height;
    if (vd->cfg->is_fullscreen) {
        display_width  = sys->desktop_width;
        display_height = sys->desktop_height;
    } else {
        display_width  = vd->cfg->display.width;
        display_height = vd->cfg->display.height;
    }
192

193 194 195 196 197 198 199 200 201
    /* Initialize flags and cursor */
    sys->display_flags = SDL_ANYFORMAT | SDL_HWPALETTE | SDL_HWSURFACE | SDL_DOUBLEBUF;
    sys->display_flags |= vd->cfg->is_fullscreen ? SDL_FULLSCREEN : SDL_RESIZABLE;

    sys->display_bpp = SDL_VideoModeOK(display_width, display_height,
                                       16, sys->display_flags);
    if (sys->display_bpp == 0) {
        msg_Err(vd, "no video mode available");
        goto error;
202
    }
203 204 205 206 207 208

    sys->display = SDL_SetVideoMode(display_width, display_height,
                                    sys->display_bpp, sys->display_flags);
    if (!sys->display) {
        msg_Err(vd, "cannot set video mode");
        goto error;
209 210
    }

211 212 213 214 215
    /* We keep the surface locked forever */
    SDL_LockSurface(sys->display);

    /* */
    vlc_fourcc_t forced_chroma = 0;
Rémi Duraffort's avatar
Rémi Duraffort committed
216
    char *psz_chroma = var_InheritString(vd, "sdl-chroma");
217 218 219 220 221 222 223
    if (psz_chroma) {
        forced_chroma = vlc_fourcc_GetCodecFromString(VIDEO_ES, psz_chroma);
        if (forced_chroma)
            msg_Dbg(vd, "Forcing chroma to 0x%.8x (%4.4s)",
                    forced_chroma, (const char*)&forced_chroma);
        free(psz_chroma);
    }
224

225 226
    /* Try to open an overlay if requested */
    sys->overlay = NULL;
227
    const bool is_overlay = var_InheritBool(vd, "sdl-overlay");
228 229
    if (is_overlay) {
        static const struct
230
        {
231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278
            vlc_fourcc_t vlc;
            uint32_t     sdl;
        } vlc_to_sdl[] = {
            { VLC_CODEC_YV12, SDL_YV12_OVERLAY },
            { VLC_CODEC_I420, SDL_IYUV_OVERLAY },
            { VLC_CODEC_YUYV, SDL_YUY2_OVERLAY },
            { VLC_CODEC_UYVY, SDL_UYVY_OVERLAY },
            { VLC_CODEC_YVYU, SDL_YVYU_OVERLAY },

            { 0, 0 }
        };
        const vlc_fourcc_t forced_chromas[] = {
            forced_chroma, 0
        };
        const vlc_fourcc_t *fallback_chromas =
            vlc_fourcc_GetYUVFallback(fmt.i_chroma);
        const vlc_fourcc_t *chromas = forced_chroma ? forced_chromas : fallback_chromas;

        for (int pass = forced_chroma ? 1 : 0; pass < 2 && !sys->overlay; pass++) {
            for (int i = 0; chromas[i] != 0; i++) {
                const vlc_fourcc_t vlc = chromas[i];

                uint32_t sdl = 0;
                for (int j = 0; vlc_to_sdl[j].vlc != 0 && !sdl; j++) {
                    if (vlc_to_sdl[j].vlc == vlc)
                        sdl = vlc_to_sdl[j].sdl;
                }
                if (!sdl)
                    continue;

                sys->overlay = SDL_CreateYUVOverlay(fmt.i_width, fmt.i_height,
                                                    sdl, sys->display);
                if (sys->overlay && !sys->overlay->hw_overlay && pass == 0) {
                    /* Ignore non hardware overlay surface in first pass */
                    SDL_FreeYUVOverlay(sys->overlay);
                    sys->overlay = NULL;
                }
                if (sys->overlay) {
                    /* We keep the surface locked forever */
                    SDL_LockYUVOverlay(sys->overlay);

                    fmt.i_chroma = vlc;
                    sys->is_uv_swapped = vlc_fourcc_AreUVPlanesSwapped(fmt.i_chroma,
                                                                       vd->fmt.i_chroma);
                    if (sys->is_uv_swapped)
                        fmt.i_chroma = vd->fmt.i_chroma;
                    break;
                }
279 280
            }
        }
281 282 283
    } else {
        msg_Warn(vd, "SDL overlay disabled by the user");
    }
284

285 286 287 288 289 290 291 292 293 294 295 296 297 298 299
    /* */
    vout_display_cfg_t place_cfg = *vd->cfg;
    place_cfg.display.width  = display_width;
    place_cfg.display.height = display_height;
    vout_display_PlacePicture(&sys->place, &vd->source, &place_cfg, !sys->overlay);

    /* If no overlay, fallback to software output */
    if (!sys->overlay) {
        /* */
        switch (sys->display->format->BitsPerPixel) {
        case 8:
            fmt.i_chroma = VLC_CODEC_RGB8;
            break;
        case 15:
            fmt.i_chroma = VLC_CODEC_RGB15;
300
            break;
301 302 303 304 305 306 307 308 309 310 311 312 313
        case 16:
            fmt.i_chroma = VLC_CODEC_RGB16;
            break;
        case 24:
            fmt.i_chroma = VLC_CODEC_RGB24;
            break;
        case 32:
            fmt.i_chroma = VLC_CODEC_RGB32;
            break;
        default:
            msg_Err(vd, "unknown screen depth %i",
                    sys->display->format->BitsPerPixel);
            goto error;
314 315
        }

316 317 318 319 320 321
        /* All we have is an RGB image with square pixels */
        fmt.i_width  = display_width;
        fmt.i_height = display_height;
        fmt.i_rmask = sys->display->format->Rmask;
        fmt.i_gmask = sys->display->format->Gmask;
        fmt.i_bmask = sys->display->format->Bmask;
322

323
        info.has_pictures_invalid = true;
324 325
    }

326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345
    if (vd->cfg->display.title)
        SDL_WM_SetCaption(vd->cfg->display.title,
                          vd->cfg->display.title);
    else if (!sys->overlay)
        SDL_WM_SetCaption(VOUT_TITLE " (software RGB SDL output)",
                          VOUT_TITLE " (software RGB SDL output)");
    else if (sys->overlay->hw_overlay)
        SDL_WM_SetCaption(VOUT_TITLE " (hardware YUV SDL output)",
                          VOUT_TITLE " (hardware YUV SDL output)");
    else
        SDL_WM_SetCaption(VOUT_TITLE " (software YUV SDL output)",
                          VOUT_TITLE " (software YUV SDL output)");

    /* Setup events */
    SDL_EventState(SDL_KEYUP, SDL_IGNORE);               /* ignore keys up */

    /* Setup vout_display now that everything is fine */
    vd->fmt = fmt;
    vd->info = info;

346
    vd->pool    = Pool;
347
    vd->prepare = NULL;
348
    vd->display = PictureDisplay;
349 350 351 352
    vd->control = Control;
    vd->manage  = Manage;

    /* */
353
    vout_display_SendEventDisplaySize(vd, display_width, display_height);
354
    return VLC_SUCCESS;
355

356 357
error:
    msg_Err(vd, "cannot set up SDL (%s)", SDL_GetError());
358

359 360 361
    if (sys->display) {
        SDL_UnlockSurface(sys->display);
        SDL_FreeSurface(sys->display);
362
    }
363 364 365 366 367 368 369

    vlc_mutex_lock(&sdl_lock);
    SDL_QuitSubSystem(SDL_INIT_VIDEO);
    vlc_mutex_unlock(&sdl_lock);

    free(sys);
    return VLC_EGENERIC;
370 371
}

372 373 374 375
/**
 * Close a SDL video output
 */
static void Close(vlc_object_t *object)
376
{
377 378 379 380
    vout_display_t *vd = (vout_display_t *)object;
    vout_display_sys_t *sys = vd->sys;

    if (sys->pool)
381
        picture_pool_Release(sys->pool);
382

383 384 385 386 387 388 389 390 391 392
    if (sys->overlay) {
        SDL_LockYUVOverlay(sys->overlay);
        SDL_FreeYUVOverlay(sys->overlay);
    }
    SDL_UnlockSurface (sys->display);
    SDL_FreeSurface(sys->display);

    vlc_mutex_lock(&sdl_lock);
    SDL_QuitSubSystem(SDL_INIT_VIDEO);
    vlc_mutex_unlock(&sdl_lock);
393

394
    free(sys);
395 396
}

397
/**
398
 * Return a pool of direct buffers
399
 */
400
static picture_pool_t *Pool(vout_display_t *vd, unsigned count)
401
{
402
    vout_display_sys_t *sys = vd->sys;
403
    VLC_UNUSED(count);
404

405 406
    if (!sys->pool) {
        picture_resource_t rsc;
407

408
        memset(&rsc, 0, sizeof(rsc));
409

410 411
        if (sys->overlay) {
            SDL_Overlay *ol = sys->overlay;
412

413 414 415 416 417 418 419
            for (int i = 0; i < ol->planes; i++) {
                rsc.p[i].p_pixels = ol->pixels[ i > 0 && sys->is_uv_swapped ? (3-i) : i];
                rsc.p[i].i_pitch  = ol->pitches[i > 0 && sys->is_uv_swapped ? (3-i) : i];
                rsc.p[i].i_lines  = ol->h;
                if (ol->format == SDL_YV12_OVERLAY ||
                    ol->format == SDL_IYUV_OVERLAY)
                    rsc.p[i].i_lines /= 2;
420

421 422 423 424
            }
        } else {
            const int x = sys->place.x;
            const int y = sys->place.y;
425

426 427
            SDL_Surface *sf = sys->display;
            SDL_FillRect(sf, NULL, 0);
428

429 430 431 432 433
            assert(x >= 0 && y >= 0);
            rsc.p[0].p_pixels = (uint8_t*)sf->pixels + y * sf->pitch + x * ((sf->format->BitsPerPixel + 7) / 8);
            rsc.p[0].i_pitch  = sf->pitch;
            rsc.p[0].i_lines  = vd->fmt.i_height;
        }
434

435 436 437
        picture_t *picture = picture_NewFromResource(&vd->fmt, &rsc);;
        if (!picture)
            return NULL;
438

439 440
        sys->pool = picture_pool_New(1, &picture);
    }
441

442
    return sys->pool;
443
}
444

445 446 447
/**
 * Display a picture
 */
448
static void PictureDisplay(vout_display_t *vd, picture_t *p_pic, subpicture_t *p_subpicture)
449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464
{
    vout_display_sys_t *sys = vd->sys;

    if (sys->overlay) {
        SDL_Rect disp;
        disp.x = sys->place.x;
        disp.y = sys->place.y;
        disp.w = sys->place.width;
        disp.h = sys->place.height;

        SDL_UnlockYUVOverlay(sys->overlay);
        SDL_DisplayYUVOverlay(sys->overlay , &disp);
        SDL_LockYUVOverlay(sys->overlay);
    } else {
        SDL_Flip(sys->display);
    }
465

466
    picture_Release(p_pic);
467
    VLC_UNUSED(p_subpicture);
468
}
469

470

471 472 473 474 475 476
/**
 * Control for vout display
 */
static int Control(vout_display_t *vd, int query, va_list args)
{
    vout_display_sys_t *sys = vd->sys;
477

478 479 480 481 482 483 484 485 486 487
    switch (query)
    {
    case VOUT_DISPLAY_HIDE_MOUSE:
        SDL_ShowCursor(0);
        return VLC_SUCCESS;

    case VOUT_DISPLAY_CHANGE_DISPLAY_SIZE: {
        const vout_display_cfg_t *cfg = va_arg(args, const vout_display_cfg_t *);

        /* */
488 489 490
        sys->display = SDL_SetVideoMode(cfg->display.width,
                                        cfg->display.height,
                                        sys->display_bpp, sys->display_flags);
491 492 493 494 495
        if (!sys->display) {
            sys->display = SDL_SetVideoMode(vd->cfg->display.width,
                                            vd->cfg->display.height,
                                            sys->display_bpp, sys->display_flags);
            return VLC_EGENERIC;
496
        }
497 498 499 500 501
        if (sys->overlay)
            vout_display_PlacePicture(&sys->place, &vd->source, cfg, !sys->overlay);
        else
            vout_display_SendEventPicturesInvalid(vd);
        return VLC_SUCCESS;
502
    }
503
    case VOUT_DISPLAY_CHANGE_FULLSCREEN: {
504
        bool fs = va_arg(args, int);
505

506 507
        /* Fix flags */
        sys->display_flags &= ~(SDL_FULLSCREEN | SDL_RESIZABLE);
508
        sys->display_flags |= fs ? SDL_FULLSCREEN : SDL_RESIZABLE;
509

510 511
        if (sys->overlay)
            sys->display = SDL_SetVideoMode(sys->desktop_width, sys->desktop_height,
512
                                            sys->display_bpp, sys->display_flags);
513

514
        vout_display_SendEventDisplaySize(vd, sys->desktop_width, sys->desktop_height);
515 516 517 518 519 520 521 522 523 524 525 526 527 528 529
        return VLC_SUCCESS;
    }
    case VOUT_DISPLAY_CHANGE_ZOOM:
    case VOUT_DISPLAY_CHANGE_DISPLAY_FILLED:
    case VOUT_DISPLAY_CHANGE_SOURCE_ASPECT: {
        const vout_display_cfg_t *cfg;

        if (query == VOUT_DISPLAY_CHANGE_SOURCE_ASPECT) {
            cfg = vd->cfg;
        } else {
            cfg = va_arg(args, const vout_display_cfg_t *);
        }
        if (sys->overlay) {
            sys->display = SDL_SetVideoMode(cfg->display.width, cfg->display.height,
                                            sys->display_bpp, sys->display_flags);
530

531
            vout_display_PlacePicture(&sys->place, &vd->source, cfg, !sys->overlay);
532 533 534 535
        } else {
            vout_display_SendEventPicturesInvalid(vd);
        }
        return VLC_SUCCESS;
536 537
    }

538 539 540
    case VOUT_DISPLAY_RESET_PICTURES: {
        /* */
        assert(!sys->overlay);
Joseph Tulou's avatar
Joseph Tulou committed
541

542 543
        /* */
        if (sys->pool)
544
            picture_pool_Release(sys->pool);
545
        sys->pool = NULL;
Joseph Tulou's avatar
Joseph Tulou committed
546

547
        vout_display_PlacePicture(&sys->place, &vd->source, vd->cfg, !sys->overlay);
Joseph Tulou's avatar
Joseph Tulou committed
548

549 550 551 552 553
        /* */
        vd->fmt.i_width  = sys->place.width;
        vd->fmt.i_height = sys->place.height;
        return VLC_SUCCESS;
    }
Joseph Tulou's avatar
Joseph Tulou committed
554

555 556 557 558 559
    case VOUT_DISPLAY_CHANGE_SOURCE_CROP:
        /* I don't think it is possible to support with SDL:
         * - crop
         */
        return VLC_EGENERIC;
Joseph Tulou's avatar
Joseph Tulou committed
560

561 562 563
    default:
        msg_Err(vd, "Unsupported query in vout display SDL");
        return VLC_EGENERIC;
Joseph Tulou's avatar
Joseph Tulou committed
564
    }
565
}
Joseph Tulou's avatar
Joseph Tulou committed
566

567 568 569 570 571 572 573
/**
 * Proccess pending event
 */
static void Manage(vout_display_t *vd)
{
    vout_display_sys_t *sys = vd->sys;
    SDL_Event event;
574

575 576 577 578 579 580
    /* */
    while (SDL_PollEvent(&event)) {
        switch (event.type) {
        case SDL_QUIT:
            vout_display_SendEventClose(vd);
            break;
581

582 583 584
        case SDL_KEYDOWN: {
            /* convert the key if possible */
            int key = ConvertKey(event.key.keysym.sym);
585

586 587 588 589 590 591 592 593 594 595 596 597 598 599
            if (!key) {
                /* Find the right caracter */
                if ((event.key.keysym.unicode & 0xff80) == 0) {
                    key = event.key.keysym.unicode & 0x7f;
                    /* FIXME: find a better solution than this
                              hack to find the right caracter */
                    if (key >= 1 && key <= 26)
                        key += 96;
                    else if (key >= 65 && key <= 90)
                        key += 32;
                }
            }
            if (!key)
                break;
600

601 602 603 604 605 606
            if (event.key.keysym.mod & KMOD_SHIFT)
                key |= KEY_MODIFIER_SHIFT;
            if (event.key.keysym.mod & KMOD_CTRL)
                key |= KEY_MODIFIER_CTRL;
            if (event.key.keysym.mod & KMOD_ALT)
                key |= KEY_MODIFIER_ALT;
607
            vout_display_SendEventKey(vd, key);
608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638
            break;
        }

        case SDL_MOUSEBUTTONDOWN:
        case SDL_MOUSEBUTTONUP: {
            static const struct { int sdl; int vlc; } buttons[] = {
                { SDL_BUTTON_LEFT,      MOUSE_BUTTON_LEFT },
                { SDL_BUTTON_MIDDLE,    MOUSE_BUTTON_CENTER },
                { SDL_BUTTON_RIGHT,     MOUSE_BUTTON_RIGHT },
                { SDL_BUTTON_WHEELUP,   MOUSE_BUTTON_WHEEL_UP },
                { SDL_BUTTON_WHEELDOWN, MOUSE_BUTTON_WHEEL_DOWN },
                { -1, -1 },
            };

            SDL_ShowCursor(1);
            for (int i = 0; buttons[i].sdl != -1; i++) {
                if (buttons[i].sdl == event.button.button) {
                    if (event.type == SDL_MOUSEBUTTONDOWN)
                        vout_display_SendEventMousePressed(vd, buttons[i].vlc);
                    else
                        vout_display_SendEventMouseReleased(vd, buttons[i].vlc);
                }
            }
            break;
        }

        case SDL_MOUSEMOTION: {
            if (sys->place.width <= 0 || sys->place.height <= 0)
                break;

            SDL_ShowCursor(1);
639 640 641 642

            vout_display_SendMouseMovedDisplayCoordinates(vd, ORIENT_NORMAL,
                                                          event.motion.x, event.motion.y,
                                                          &sys->place);
643 644 645 646
            break;
        }

        case SDL_VIDEORESIZE:
647
            vout_display_SendEventDisplaySize(vd, event.resize.w, event.resize.h);
648 649 650 651 652
            break;

        default:
            break;
        }
653 654 655 656
    }

}

657
static const struct {
658
    SDLKey sdl_key;
659 660 661
    int    vlckey;

} sdlkeys_to_vlckeys[] = {
662 663 664 665 666 667 668 669 670 671 672 673 674 675 676
    { SDLK_F1,  KEY_F1 },
    { SDLK_F2,  KEY_F2 },
    { SDLK_F3,  KEY_F3 },
    { SDLK_F4,  KEY_F4 },
    { SDLK_F5,  KEY_F5 },
    { SDLK_F6,  KEY_F6 },
    { SDLK_F7,  KEY_F7 },
    { SDLK_F8,  KEY_F8 },
    { SDLK_F9,  KEY_F9 },
    { SDLK_F10, KEY_F10 },
    { SDLK_F11, KEY_F11 },
    { SDLK_F12, KEY_F12 },

    { SDLK_RETURN, KEY_ENTER },
    { SDLK_KP_ENTER, KEY_ENTER },
677
    { SDLK_SPACE, ' ' },
678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704
    { SDLK_ESCAPE, KEY_ESC },

    { SDLK_MENU, KEY_MENU },
    { SDLK_LEFT, KEY_LEFT },
    { SDLK_RIGHT, KEY_RIGHT },
    { SDLK_UP, KEY_UP },
    { SDLK_DOWN, KEY_DOWN },

    { SDLK_HOME, KEY_HOME },
    { SDLK_END, KEY_END },
    { SDLK_PAGEUP, KEY_PAGEUP },
    { SDLK_PAGEDOWN,  KEY_PAGEDOWN },

    { SDLK_INSERT, KEY_INSERT },
    { SDLK_DELETE, KEY_DELETE },
    /*TODO: find a equivalent for SDL 
    { , KEY_MEDIA_NEXT_TRACK }
    { , KEY_MEDIA_PREV_TRACK }
    { , KEY_VOLUME_MUTE }
    { , KEY_VOLUME_DOWN }
    { , KEY_VOLUME_UP }
    { , KEY_MEDIA_PLAY_PAUSE }
    { , KEY_MEDIA_PLAY_PAUSE }*/

    { 0, 0 }
};

705
static int ConvertKey(SDLKey sdl_key)
706
{
707 708 709
    for (int i = 0; sdlkeys_to_vlckeys[i].sdl_key != 0; i++) {
        if (sdlkeys_to_vlckeys[i].sdl_key == sdl_key)
            return sdlkeys_to_vlckeys[i].vlckey;
710 711 712
    }
    return 0;
}
713