vout_sdl.c 27.7 KB
Newer Older
Pierre Baillet's avatar
Pierre Baillet committed
1 2 3 4
/*****************************************************************************
 * vout_sdl.c: SDL video output display method
 *****************************************************************************
 * Copyright (C) 1998, 1999, 2000 VideoLAN
5
 * $Id: vout_sdl.c,v 1.60 2001/07/27 16:40:20 massiot Exp $
Pierre Baillet's avatar
Pierre Baillet committed
6
 *
Sam Hocevar's avatar
 
Sam Hocevar committed
7 8 9
 * Authors: Samuel Hocevar <sam@zoy.org>
 *          Pierre Baillet <oct@zoy.org>
 *          Arnaud de Bossoreille de Ribou <bozo@via.ecp.fr>
Pierre Baillet's avatar
Pierre Baillet committed
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
 *****************************************************************************/

Sam Hocevar's avatar
 
Sam Hocevar committed
26 27 28
#define MODULE_NAME sdl
#include "modules_inner.h"

Pierre Baillet's avatar
Pierre Baillet committed
29 30 31 32 33 34 35 36 37
/*****************************************************************************
 * Preamble
 *****************************************************************************/
#include "defs.h"

#include <errno.h>                                                 /* ENOMEM */
#include <stdlib.h>                                                /* free() */
#include <string.h>                                            /* strerror() */

Sam Hocevar's avatar
 
Sam Hocevar committed
38
#include <sys/types.h>
Sam Hocevar's avatar
 
Sam Hocevar committed
39
#ifndef WIN32
Sam Hocevar's avatar
 
Sam Hocevar committed
40
#   include <netinet/in.h>                            /* BSD: struct in_addr */
Sam Hocevar's avatar
 
Sam Hocevar committed
41 42
#endif

43
#if HAVE_SDL_SDL_H
44
#   include <SDL/SDL.h>
45
#elif HAVE_SDL11_SDL_H
46
#   include <SDL11/SDL.h>
47
#elif HAVE_SDL12_SDL_H
48 49
#   include <SDL12/SDL.h>
#else
50
#   error
51
#endif
Pierre Baillet's avatar
Pierre Baillet committed
52 53 54 55 56

#include "config.h"
#include "common.h"
#include "threads.h"
#include "mtime.h"
Sam Hocevar's avatar
 
Sam Hocevar committed
57 58
#include "tests.h"

Pierre Baillet's avatar
Pierre Baillet committed
59 60 61 62
#include "video.h"
#include "video_output.h"

#include "intf_msg.h"
Sam Hocevar's avatar
 
Sam Hocevar committed
63 64 65
#include "interface.h"
/* FIXME: get rid of this */
#include "keystrokes.h"
66
#include "main.h"
Henri Fallon's avatar
 
Henri Fallon committed
67
#include "netutils.h"
Pierre Baillet's avatar
Pierre Baillet committed
68

Sam Hocevar's avatar
 
Sam Hocevar committed
69 70 71
#include "modules.h"
#include "modules_export.h"

Sam Hocevar's avatar
 
Sam Hocevar committed
72 73 74
/*****************************************************************************
 * FIXME: this file is ...                                                   *
 *                                                                           *
Sam Hocevar's avatar
 
Sam Hocevar committed
75 76 77 78 79 80
 *              XXX   XXX     FIXME     XXX     XXX   XXX   XXX              *
 *              XXX   XXX   XXX   XXX   XXX     XXX   XXX   XXX              *
 *              XXX   XXX   XXX         XXX       FIXME     XXX              *
 *              XXX   XXX   XXX  TODO   XXX        XXX      XXX              *
 *              XXX   XXX   XXX   XXX   XXX        XXX                       *
 *                FIXME       FIXME       FIXME    XXX      XXX              *
Sam Hocevar's avatar
 
Sam Hocevar committed
81 82 83
 *                                                                           *
 *****************************************************************************/

Pierre Baillet's avatar
Pierre Baillet committed
84 85 86 87 88 89 90 91
/*****************************************************************************
 * vout_sys_t: video output SDL method descriptor
 *****************************************************************************
 * This structure is part of the video output thread descriptor.
 * It describes the SDL specific properties of an output thread.
 *****************************************************************************/
typedef struct vout_sys_s
{
92 93
    int i_width;
    int i_height;
Sam Hocevar's avatar
 
Sam Hocevar committed
94

Pierre Baillet's avatar
Pierre Baillet committed
95
    SDL_Surface *   p_display;                             /* display device */
96
    SDL_Overlay *   p_overlay;                             /* overlay device */
Sam Hocevar's avatar
 
Sam Hocevar committed
97

Sam Hocevar's avatar
 
Sam Hocevar committed
98
    boolean_t   b_overlay;
99
    boolean_t   b_cursor;
100
    boolean_t   b_reopen_display;
Sam Hocevar's avatar
 
Sam Hocevar committed
101 102 103 104

    boolean_t   b_cursor_autohidden;
    mtime_t     i_lastmoved;

Sam Hocevar's avatar
 
Sam Hocevar committed
105
    Uint8   *   p_sdl_buf[2];                          /* Buffer information */
Sam Hocevar's avatar
 
Sam Hocevar committed
106

Sam Hocevar's avatar
 
Sam Hocevar committed
107
} vout_sys_t;
Pierre Baillet's avatar
Pierre Baillet committed
108 109

/*****************************************************************************
Sam Hocevar's avatar
 
Sam Hocevar committed
110 111 112 113 114 115 116 117 118
 * Local prototypes.
 *****************************************************************************/
static int  vout_Probe     ( probedata_t *p_data );
static int  vout_Create    ( struct vout_thread_s * );
static int  vout_Init      ( struct vout_thread_s * );
static void vout_End       ( struct vout_thread_s * );
static void vout_Destroy   ( struct vout_thread_s * );
static int  vout_Manage    ( struct vout_thread_s * );
static void vout_Display   ( struct vout_thread_s * );
119 120
static void vout_SetPalette( p_vout_thread_t p_vout, u16 *red, u16 *green,
                             u16 *blue, u16 *transp );
Sam Hocevar's avatar
 
Sam Hocevar committed
121 122 123 124 125 126 127

static int  SDLOpenDisplay      ( vout_thread_t *p_vout );
static void SDLCloseDisplay     ( vout_thread_t *p_vout );

/*****************************************************************************
 * Functions exported as capabilities. They are declared as static so that
 * we don't pollute the namespace too much.
Pierre Baillet's avatar
Pierre Baillet committed
128
 *****************************************************************************/
Sam Hocevar's avatar
 
Sam Hocevar committed
129
void _M( vout_getfunctions )( function_list_t * p_function_list )
Sam Hocevar's avatar
 
Sam Hocevar committed
130 131 132 133 134 135 136 137
{
    p_function_list->pf_probe = vout_Probe;
    p_function_list->functions.vout.pf_create     = vout_Create;
    p_function_list->functions.vout.pf_init       = vout_Init;
    p_function_list->functions.vout.pf_end        = vout_End;
    p_function_list->functions.vout.pf_destroy    = vout_Destroy;
    p_function_list->functions.vout.pf_manage     = vout_Manage;
    p_function_list->functions.vout.pf_display    = vout_Display;
138
    p_function_list->functions.vout.pf_setpalette = vout_SetPalette;
Sam Hocevar's avatar
 
Sam Hocevar committed
139 140
}

Pierre Baillet's avatar
Pierre Baillet committed
141
/*****************************************************************************
Sam Hocevar's avatar
 
Sam Hocevar committed
142
 * vout_Probe: probe the video driver and return a score
Sam Hocevar's avatar
 
Sam Hocevar committed
143 144 145 146 147 148 149 150 151 152 153
 *****************************************************************************
 * This function tries to initialize SDL and returns a score to the
 * plugin manager so that it can select the best plugin.
 *****************************************************************************/
static int vout_Probe( probedata_t *p_data )
{
    if( TestMethod( VOUT_METHOD_VAR, "sdl" ) )
    {
        return( 999 );
    }

Sam Hocevar's avatar
 
Sam Hocevar committed
154
    return( 100 );
Sam Hocevar's avatar
 
Sam Hocevar committed
155 156 157 158
}

/*****************************************************************************
 * vout_Create: allocate SDL video thread output method
Pierre Baillet's avatar
Pierre Baillet committed
159 160 161 162 163
 *****************************************************************************
 * This function allocate and initialize a SDL vout method. It uses some of the
 * vout properties to choose the correct mode, and change them according to the
 * mode actually used.
 *****************************************************************************/
164
static int vout_Create( vout_thread_t *p_vout )
Pierre Baillet's avatar
Pierre Baillet committed
165 166 167 168 169
{
    /* Allocate structure */
    p_vout->p_sys = malloc( sizeof( vout_sys_t ) );
    if( p_vout->p_sys == NULL )
    {
Sam Hocevar's avatar
 
Sam Hocevar committed
170
        intf_ErrMsg( "vout error: can't create p_sys (%s)", strerror(ENOMEM) );
Pierre Baillet's avatar
Pierre Baillet committed
171 172 173
        return( 1 );
    }

174
    /* Initialize library */
Sam Hocevar's avatar
 
Sam Hocevar committed
175 176 177 178 179
    if( SDL_Init( SDL_INIT_VIDEO
#ifndef WIN32
    /* Win32 SDL implementation doesn't support SDL_INIT_EVENTTHREAD yet*/
                | SDL_INIT_EVENTTHREAD
#endif
180 181 182 183 184 185
#ifdef DEBUG
    /* In debug mode you may want vlc to dump a core instead of staying
     * stuck */
                | SDL_INIT_NOPARACHUTE
#endif
                ) < 0 )
Pierre Baillet's avatar
Pierre Baillet committed
186
    {
Sam Hocevar's avatar
 
Sam Hocevar committed
187
        intf_ErrMsg( "vout error: can't initialize SDL (%s)", SDL_GetError() );
Pierre Baillet's avatar
Pierre Baillet committed
188 189 190
        free( p_vout->p_sys );
        return( 1 );
    }
191

Sam Hocevar's avatar
 
Sam Hocevar committed
192
    p_vout->p_sys->b_cursor = 1; /* TODO should be done with a main_GetInt.. */
Sam Hocevar's avatar
 
Sam Hocevar committed
193 194 195 196

    p_vout->p_sys->b_cursor_autohidden = 0;
    p_vout->p_sys->i_lastmoved = mdate();

197
    p_vout->b_fullscreen = main_GetIntVariable( VOUT_FULLSCREEN_VAR,
Sam Hocevar's avatar
 
Sam Hocevar committed
198 199 200
                                VOUT_FULLSCREEN_DEFAULT );
    p_vout->p_sys->b_overlay = main_GetIntVariable( VOUT_OVERLAY_VAR,
                                VOUT_OVERLAY_DEFAULT );
201 202 203 204
    p_vout->p_sys->i_width = main_GetIntVariable( VOUT_WIDTH_VAR, 
                                VOUT_WIDTH_DEFAULT );
    p_vout->p_sys->i_height = main_GetIntVariable( VOUT_HEIGHT_VAR,
                                VOUT_HEIGHT_DEFAULT );
205

Sam Hocevar's avatar
 
Sam Hocevar committed
206 207 208
    p_vout->p_sys->p_display = NULL;
    p_vout->p_sys->p_overlay = NULL;

209 210
    if( SDLOpenDisplay(p_vout) )
    {
Sam Hocevar's avatar
 
Sam Hocevar committed
211
        intf_ErrMsg( "vout error: can't set up SDL (%s)", SDL_GetError() );
Sam Hocevar's avatar
 
Sam Hocevar committed
212 213
        free( p_vout->p_sys );
        return( 1 );
214 215
    }

Sam Hocevar's avatar
 
Sam Hocevar committed
216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239
    /* FIXME: get rid of this ASAP, it's FUCKING UGLY */
    { intf_thread_t * p_intf = p_main->p_intf;
    intf_AssignKey(p_intf, SDLK_q,      INTF_KEY_QUIT, 0);
    intf_AssignKey(p_intf, SDLK_ESCAPE, INTF_KEY_QUIT, 0);
    /* intf_AssignKey(p_intf,3,'Q'); */
    intf_AssignKey(p_intf, SDLK_0,      INTF_KEY_SET_CHANNEL,0);
    intf_AssignKey(p_intf, SDLK_1,      INTF_KEY_SET_CHANNEL,1);
    intf_AssignKey(p_intf, SDLK_2,      INTF_KEY_SET_CHANNEL,2);
    intf_AssignKey(p_intf, SDLK_3,      INTF_KEY_SET_CHANNEL,3);
    intf_AssignKey(p_intf, SDLK_4,      INTF_KEY_SET_CHANNEL,4);
    intf_AssignKey(p_intf, SDLK_5,      INTF_KEY_SET_CHANNEL,5);
    intf_AssignKey(p_intf, SDLK_6,      INTF_KEY_SET_CHANNEL,6);
    intf_AssignKey(p_intf, SDLK_7,      INTF_KEY_SET_CHANNEL,7);
    intf_AssignKey(p_intf, SDLK_8,      INTF_KEY_SET_CHANNEL,8);
    intf_AssignKey(p_intf, SDLK_9,      INTF_KEY_SET_CHANNEL,9);
    intf_AssignKey(p_intf, SDLK_PLUS,   INTF_KEY_INC_VOLUME, 0);
    intf_AssignKey(p_intf, SDLK_MINUS,  INTF_KEY_DEC_VOLUME, 0);
    intf_AssignKey(p_intf, SDLK_m,      INTF_KEY_TOGGLE_VOLUME, 0);
    /* intf_AssignKey(p_intf,'M','M'); */
    intf_AssignKey(p_intf, SDLK_g,      INTF_KEY_DEC_GAMMA, 0);
    /* intf_AssignKey(p_intf,'G','G'); */
    intf_AssignKey(p_intf, SDLK_c,      INTF_KEY_TOGGLE_GRAYSCALE, 0);
    intf_AssignKey(p_intf, SDLK_SPACE,  INTF_KEY_TOGGLE_INTERFACE, 0);
    intf_AssignKey(p_intf, SDLK_i,      INTF_KEY_TOGGLE_INFO, 0);
240 241
    intf_AssignKey(p_intf, SDLK_s,      INTF_KEY_TOGGLE_SCALING, 0);
    intf_AssignKey(p_intf, SDLK_d,      INTF_KEY_DUMP_STREAM, 0); }
Sam Hocevar's avatar
 
Sam Hocevar committed
242

Pierre Baillet's avatar
Pierre Baillet committed
243
    return( 0 );
Arnaud de Bossoreille de Ribou's avatar
Arnaud de Bossoreille de Ribou committed
244
}
Pierre Baillet's avatar
Pierre Baillet committed
245 246

/*****************************************************************************
Sam Hocevar's avatar
 
Sam Hocevar committed
247
 * vout_Init: initialize SDL video thread output method
Pierre Baillet's avatar
Pierre Baillet committed
248 249 250
 *****************************************************************************
 * This function initialize the SDL display device.
 *****************************************************************************/
251
static int vout_Init( vout_thread_t *p_vout )
Pierre Baillet's avatar
Pierre Baillet committed
252
{
253 254 255
    /* This hack is hugly, but hey, you are, too. */

    SDL_Overlay *   p_overlay;
Pierre Baillet's avatar
Pierre Baillet committed
256 257 258 259
    
    p_overlay = SDL_CreateYUVOverlay( 
           main_GetIntVariable( VOUT_WIDTH_VAR,VOUT_WIDTH_DEFAULT ),
           main_GetIntVariable( VOUT_HEIGHT_VAR,VOUT_HEIGHT_DEFAULT ),
260 261
                                      SDL_YV12_OVERLAY, 
                                      p_vout->p_sys->p_display );
Sam Hocevar's avatar
 
Sam Hocevar committed
262 263 264 265 266 267 268 269

    if( p_overlay == NULL )
    {
        intf_ErrMsg( "vout error: could not create SDL overlay" );
        p_vout->b_need_render = 1;
        return( 0 );
    }

270
    intf_WarnMsg( 2, "vout: YUV acceleration %s",
271 272 273 274 275
              p_overlay->hw_overlay ? "activated" : "unavailable !" ); 
    p_vout->b_need_render = !p_overlay->hw_overlay;

    SDL_FreeYUVOverlay( p_overlay );

Pierre Baillet's avatar
Pierre Baillet committed
276 277 278 279
    return( 0 );
}

/*****************************************************************************
Sam Hocevar's avatar
 
Sam Hocevar committed
280
 * vout_End: terminate Sys video thread output method
Pierre Baillet's avatar
Pierre Baillet committed
281 282 283
 *****************************************************************************
 * Terminate an output method created by vout_SDLCreate
 *****************************************************************************/
284
static void vout_End( vout_thread_t *p_vout )
Pierre Baillet's avatar
Pierre Baillet committed
285
{
286
    SDLCloseDisplay( p_vout );
Sam Hocevar's avatar
 
Sam Hocevar committed
287
    SDL_QuitSubSystem( SDL_INIT_VIDEO );
Pierre Baillet's avatar
Pierre Baillet committed
288 289 290
}

/*****************************************************************************
Sam Hocevar's avatar
 
Sam Hocevar committed
291
 * vout_Destroy: destroy Sys video thread output method
Pierre Baillet's avatar
Pierre Baillet committed
292 293 294
 *****************************************************************************
 * Terminate an output method created by vout_SDLCreate
 *****************************************************************************/
295
static void vout_Destroy( vout_thread_t *p_vout )
Pierre Baillet's avatar
Pierre Baillet committed
296 297 298 299 300
{
    free( p_vout->p_sys );
}

/*****************************************************************************
Sam Hocevar's avatar
 
Sam Hocevar committed
301
 * vout_Manage: handle Sys events
Pierre Baillet's avatar
Pierre Baillet committed
302 303 304 305
 *****************************************************************************
 * This function should be called regularly by video output thread. It returns
 * a non null value if an error occured.
 *****************************************************************************/
306
static int vout_Manage( vout_thread_t *p_vout )
Pierre Baillet's avatar
Pierre Baillet committed
307
{
Sam Hocevar's avatar
 
Sam Hocevar committed
308
    SDL_Event event;                                            /* SDL event */
Henri Fallon's avatar
 
Henri Fallon committed
309
    char *    p_key;
Sam Hocevar's avatar
 
Sam Hocevar committed
310 311 312 313 314 315 316 317 318 319 320 321

    /* Process events */
    while( SDL_PollEvent(&event) )
    {
        switch( event.type )
        {
        case SDL_VIDEORESIZE:                          /* Resizing of window */
            p_vout->i_width = event.resize.w;
            p_vout->i_height = event.resize.h;
            p_vout->i_changes |= VOUT_SIZE_CHANGE;
            break;

Sam Hocevar's avatar
 
Sam Hocevar committed
322 323 324 325 326 327 328 329 330
        case SDL_MOUSEMOTION:
            if( p_vout->p_sys->b_cursor &&
                (abs(event.motion.xrel) > 2 || abs(event.motion.yrel) > 2) )
            {
                if( p_vout->p_sys->b_cursor_autohidden )
                {
                    p_vout->p_sys->b_cursor_autohidden = 0;
                    SDL_ShowCursor( 1 );
                }
Sam Hocevar's avatar
 
Sam Hocevar committed
331
                else
Sam Hocevar's avatar
 
Sam Hocevar committed
332 333 334 335 336 337
                {
                    p_vout->p_sys->i_lastmoved = mdate();
                }
            }
            break;

Sam Hocevar's avatar
 
Sam Hocevar committed
338 339 340 341 342 343 344 345 346
        case SDL_MOUSEBUTTONUP:
            switch( event.button.button )
            {
            case SDL_BUTTON_RIGHT:
                p_main->p_intf->b_menu_change = 1;
                break;
            }
            break;

Sam Hocevar's avatar
 
Sam Hocevar committed
347 348 349 350 351 352 353 354 355 356 357 358 359 360 361
        case SDL_MOUSEBUTTONDOWN:
            switch( event.button.button )
            {
            case SDL_BUTTON_MIDDLE:
                p_vout->i_changes |= VOUT_CURSOR_CHANGE;
                break;
            }
            break;

        case SDL_QUIT:
            intf_ProcessKey( p_main->p_intf, SDLK_q );
            break;

        case SDL_KEYDOWN:                             /* if a key is pressed */

Henri Fallon's avatar
 
Henri Fallon committed
362
            switch( event.key.keysym.sym )
Sam Hocevar's avatar
 
Sam Hocevar committed
363 364 365 366 367 368 369 370 371 372 373
            {
            case SDLK_f:                             /* switch to fullscreen */
                p_vout->i_changes |= VOUT_FULLSCREEN_CHANGE;
                break;

            case SDLK_y:                               /* switch to hard YUV */
                p_vout->i_changes |= VOUT_YUV_CHANGE;
                break;

            case SDLK_c:                                 /* toggle grayscale */
                p_vout->b_grayscale = ! p_vout->b_grayscale;
Sam Hocevar's avatar
 
Sam Hocevar committed
374
                p_vout->i_changes |= VOUT_GRAYSCALE_CHANGE;
Sam Hocevar's avatar
 
Sam Hocevar committed
375 376 377 378
                break;

            case SDLK_i:                                      /* toggle info */
                p_vout->b_info = ! p_vout->b_info;
Sam Hocevar's avatar
 
Sam Hocevar committed
379
                p_vout->i_changes |= VOUT_INFO_CHANGE;
Sam Hocevar's avatar
 
Sam Hocevar committed
380 381
                break;

Sam Hocevar's avatar
 
Sam Hocevar committed
382
            case SDLK_s:                                   /* toggle scaling */
Sam Hocevar's avatar
 
Sam Hocevar committed
383
                p_vout->b_scale = ! p_vout->b_scale;
Sam Hocevar's avatar
 
Sam Hocevar committed
384
                p_vout->i_changes |= VOUT_SCALE_CHANGE;
Sam Hocevar's avatar
 
Sam Hocevar committed
385 386
                break;

Sam Hocevar's avatar
 
Sam Hocevar committed
387
            case SDLK_SPACE:                             /* toggle interface */
Sam Hocevar's avatar
 
Sam Hocevar committed
388
                p_vout->b_interface = ! p_vout->b_interface;
Sam Hocevar's avatar
 
Sam Hocevar committed
389
                p_vout->i_changes |= VOUT_INTF_CHANGE;
Sam Hocevar's avatar
 
Sam Hocevar committed
390
                break;
Henri Fallon's avatar
 
Henri Fallon committed
391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421
            
            case SDLK_F10:
                network_ChannelJoin( 0 );
                break;
            case SDLK_F1:
                network_ChannelJoin( 1 );
                break;
            case SDLK_F2:
                network_ChannelJoin( 2 );
                break;
            case SDLK_F3:
                network_ChannelJoin( 3 );
                break;
            case SDLK_F4:
                network_ChannelJoin( 4 );
                break;
            case SDLK_F5:
                network_ChannelJoin( 5 );
                break;
            case SDLK_F6:
                network_ChannelJoin( 6 );
                break;
            case SDLK_F7:
                network_ChannelJoin( 7 );
                break;
            case SDLK_F8:
                network_ChannelJoin( 8 );
                break;
            case SDLK_F9:
                network_ChannelJoin( 9 );
                break;
Sam Hocevar's avatar
 
Sam Hocevar committed
422

Henri Fallon's avatar
 
Henri Fallon committed
423 424 425 426
            case SDLK_MENU:
                p_main->p_intf->b_menu_change = 1;
                break;
                
Sam Hocevar's avatar
 
Sam Hocevar committed
427
            default:
Henri Fallon's avatar
 
Henri Fallon committed
428 429 430
                p_key = SDL_GetKeyName( event.key.keysym.sym ) ;
                if( intf_ProcessKey( p_main->p_intf, 
                                     (char )event.key.keysym.sym ) )
Sam Hocevar's avatar
 
Sam Hocevar committed
431
                {
Henri Fallon's avatar
 
Henri Fallon committed
432 433 434 435
                   intf_DbgMsg( "unhandled key '%c' (%i)", 
                                (char)event.key.keysym.sym, 
                                event.key.keysym.sym );                
                }
Sam Hocevar's avatar
 
Sam Hocevar committed
436 437 438 439 440 441 442 443
                break;
            }
            break;

        default:
            break;
        }
    }
444 445 446 447

    /*
     * Size Change 
     */
Sam Hocevar's avatar
 
Sam Hocevar committed
448
    if( p_vout->i_changes & VOUT_SIZE_CHANGE )
449
    {
450 451
        p_vout->p_sys->i_width = p_vout->i_width;
        p_vout->p_sys->i_height = p_vout->i_height;
452

453 454
        /* Need to reopen display */
        SDLCloseDisplay( p_vout );
Sam Hocevar's avatar
 
Sam Hocevar committed
455
        if( SDLOpenDisplay( p_vout ) )
456
        {
Sam Hocevar's avatar
 
Sam Hocevar committed
457
          intf_ErrMsg( "vout error: can't reopen display after resize" );
458
          return( 1 );
459
        }
460
        p_vout->i_changes &= ~VOUT_SIZE_CHANGE;
461
    }
462 463 464 465
    
    /*
     * YUV Change 
     */
Sam Hocevar's avatar
 
Sam Hocevar committed
466
    if( p_vout->i_changes & VOUT_YUV_CHANGE )
467
    {
Sam Hocevar's avatar
 
Sam Hocevar committed
468
        p_vout->b_need_render = ! p_vout->b_need_render;
469 470 471
        
        /* Need to reopen display */
        SDLCloseDisplay( p_vout );
Sam Hocevar's avatar
 
Sam Hocevar committed
472
        if( SDLOpenDisplay( p_vout ) )
473
        {
Sam Hocevar's avatar
 
Sam Hocevar committed
474
          intf_ErrMsg( "error: can't reopen display after YUV change" );
475 476 477 478
          return( 1 );
        }
        p_vout->i_changes &= ~VOUT_YUV_CHANGE;
    }
Sam Hocevar's avatar
 
Sam Hocevar committed
479

480 481 482
    /*
     * Fullscreen change
     */
Sam Hocevar's avatar
 
Sam Hocevar committed
483
    if( p_vout->i_changes & VOUT_FULLSCREEN_CHANGE )
484
    {
485
        p_vout->b_fullscreen = ! p_vout->b_fullscreen;
Sam Hocevar's avatar
 
Sam Hocevar committed
486 487 488

        SDL_WM_ToggleFullScreen(p_vout->p_sys->p_display);

Sam Hocevar's avatar
 
Sam Hocevar committed
489 490 491 492
        p_vout->p_sys->b_cursor_autohidden = 0;
        SDL_ShowCursor( p_vout->p_sys->b_cursor &&
                        ! p_vout->p_sys->b_cursor_autohidden );

493
        p_vout->i_changes &= ~VOUT_FULLSCREEN_CHANGE;
494
    }
495 496 497 498

    /*
     * Pointer change
     */
Sam Hocevar's avatar
 
Sam Hocevar committed
499 500 501 502 503 504 505 506
    if( ! p_vout->p_sys->b_cursor_autohidden &&
        ( mdate() - p_vout->p_sys->i_lastmoved > 2000000 ) )
    {
        /* Hide the mouse automatically */
        p_vout->p_sys->b_cursor_autohidden = 1;
        SDL_ShowCursor( 0 );
    }

Sam Hocevar's avatar
 
Sam Hocevar committed
507
    if( p_vout->i_changes & VOUT_CURSOR_CHANGE )
508
    {
Sam Hocevar's avatar
 
Sam Hocevar committed
509 510 511 512 513
        p_vout->p_sys->b_cursor = ! p_vout->p_sys->b_cursor;

        SDL_ShowCursor( p_vout->p_sys->b_cursor &&
                        ! p_vout->p_sys->b_cursor_autohidden );

Sam Hocevar's avatar
 
Sam Hocevar committed
514
        p_vout->i_changes &= ~VOUT_CURSOR_CHANGE;
515 516
    }
    
Pierre Baillet's avatar
Pierre Baillet committed
517 518
    return( 0 );
}
Sam Hocevar's avatar
 
Sam Hocevar committed
519

520
/*****************************************************************************
Sam Hocevar's avatar
 
Sam Hocevar committed
521
 * vout_SetPalette: sets an 8 bpp palette
522 523 524 525 526
 *****************************************************************************
 * This function sets the palette given as an argument. It does not return
 * anything, but could later send information on which colors it was unable
 * to set.
 *****************************************************************************/
527
static void vout_SetPalette( p_vout_thread_t p_vout, u16 *red, u16 *green,
528
                         u16 *blue, u16 *transp)
529 530 531 532 533 534
{
     /* Create a display surface with a grayscale palette */
    SDL_Color colors[256];
    int i;
  
    /* Fill colors with color information */
Sam Hocevar's avatar
 
Sam Hocevar committed
535 536 537 538 539
    for( i = 0; i < 256; i++ )
    {
        colors[ i ].r = red[ i ] >> 8;
        colors[ i ].g = green[ i ] >> 8;
        colors[ i ].b = blue[ i ] >> 8;
540 541 542
    }
    
    /* Set palette */
Sam Hocevar's avatar
 
Sam Hocevar committed
543
    if( SDL_SetColors( p_vout->p_sys->p_display, colors, 0, 256 ) == 0 )
Sam Hocevar's avatar
 
Sam Hocevar committed
544
    {
Sam Hocevar's avatar
 
Sam Hocevar committed
545
        intf_ErrMsg( "vout error: failed setting palette" );
Sam Hocevar's avatar
 
Sam Hocevar committed
546
    }
547 548 549

}

Pierre Baillet's avatar
Pierre Baillet committed
550
/*****************************************************************************
Sam Hocevar's avatar
 
Sam Hocevar committed
551
 * vout_Display: displays previously rendered output
Pierre Baillet's avatar
Pierre Baillet committed
552 553 554 555
 *****************************************************************************
 * This function send the currently rendered image to the display, wait until
 * it is displayed and switch the two rendering buffer, preparing next frame.
 *****************************************************************************/
556
static void vout_Display( vout_thread_t *p_vout )
Pierre Baillet's avatar
Pierre Baillet committed
557
{
Pierre Baillet's avatar
Pierre Baillet committed
558
    SDL_Rect    disp;
559
    if((p_vout->p_sys->p_display != NULL) && !p_vout->p_sys->b_reopen_display)
560
    {
Sam Hocevar's avatar
 
Sam Hocevar committed
561
        if( !p_vout->b_need_render )
562
        {
563 564 565 566
            /*
             * p_vout->p_rendered_pic->p_y/u/v contains the YUV buffers to
             * render 
             */
567 568
            /* TODO: support for streams other than 4:2:0 */
            /* create the overlay if necessary */
569
            if( p_vout->p_sys->p_overlay == NULL )
570 571 572
            {
                p_vout->p_sys->p_overlay = SDL_CreateYUVOverlay( 
                                             p_vout->p_rendered_pic->i_width, 
573
                                             p_vout->p_rendered_pic->i_height,
574
                                             SDL_YV12_OVERLAY, 
Sam Hocevar's avatar
 
Sam Hocevar committed
575 576 577 578 579 580 581 582
                                             p_vout->p_sys->p_display );

                if( p_vout->p_sys->p_overlay != NULL )
                {
                    intf_WarnMsg( 2, "vout: YUV acceleration %s",
                                  p_vout->p_sys->p_overlay->hw_overlay
                                   ? "activated" : "unavailable !" ); 
                }
Sam Hocevar's avatar
 
Sam Hocevar committed
583 584 585 586 587 588 589 590 591 592
            }

            if( p_vout->p_sys->p_overlay == NULL )
            {
                /* Overlay allocation failed, switch back to software mode */
                intf_ErrMsg( "vout error: could not create SDL overlay" );
                p_vout->b_need_render = 1;
            }
            else
            {
Sam Hocevar's avatar
 
Sam Hocevar committed
593
                SDL_LockYUVOverlay( p_vout->p_sys->p_overlay );
Sam Hocevar's avatar
 
Sam Hocevar committed
594 595
                /* copy the data into video buffers */
                /* Y first */
Sam Hocevar's avatar
 
Sam Hocevar committed
596 597 598 599
                memcpy( p_vout->p_sys->p_overlay->pixels[0],
                        p_vout->p_rendered_pic->p_y,
                        p_vout->p_sys->p_overlay->h *
                        p_vout->p_sys->p_overlay->pitches[0] );
Sam Hocevar's avatar
 
Sam Hocevar committed
600
                /* then V */
Sam Hocevar's avatar
 
Sam Hocevar committed
601 602 603 604
                memcpy( p_vout->p_sys->p_overlay->pixels[1],
                        p_vout->p_rendered_pic->p_v,
                        p_vout->p_sys->p_overlay->h *
                        p_vout->p_sys->p_overlay->pitches[1] / 2 );
Sam Hocevar's avatar
 
Sam Hocevar committed
605
                /* and U */
Sam Hocevar's avatar
 
Sam Hocevar committed
606 607 608 609
                memcpy( p_vout->p_sys->p_overlay->pixels[2],
                        p_vout->p_rendered_pic->p_u,
                        p_vout->p_sys->p_overlay->h *
                        p_vout->p_sys->p_overlay->pitches[2] / 2 );
Sam Hocevar's avatar
 
Sam Hocevar committed
610 611 612 613 614 615 616 617 618 619
    
#define BUFFER (&p_vout->p_buffer[p_vout->i_buffer_index])
                disp.w = BUFFER->i_pic_width;
                disp.h = BUFFER->i_pic_height;
#undef BUFFER
                disp.x = (p_vout->i_width - disp.w)/2;
                disp.y = (p_vout->i_height - disp.h)/2;
    
                SDL_DisplayYUVOverlay( p_vout->p_sys->p_overlay , &disp );
                SDL_UnlockYUVOverlay(p_vout->p_sys->p_overlay);
620

Sam Hocevar's avatar
 
Sam Hocevar committed
621 622
                return;
            }
623
        }
Sam Hocevar's avatar
 
Sam Hocevar committed
624 625 626
    
        /* Software YUV: change display frame */
        SDL_Flip( p_vout->p_sys->p_display );
627
    }
Pierre Baillet's avatar
Pierre Baillet committed
628 629 630 631 632 633 634 635 636 637
}

/* following functions are local */

/*****************************************************************************
 * SDLOpenDisplay: open and initialize SDL device
 *****************************************************************************
 * Open and initialize display according to preferences specified in the vout
 * thread fields.
 *****************************************************************************/
638
static int SDLOpenDisplay( vout_thread_t *p_vout )
Pierre Baillet's avatar
Pierre Baillet committed
639
{
640
    SDL_Rect    clipping_rect;
641 642
    Uint32      flags;
    int bpp;
Pierre Baillet's avatar
Pierre Baillet committed
643 644 645
    /* Open display 
     * TODO: Check that we can request for a DOUBLEBUF HWSURFACE display
     */
646 647

    /* init flags and cursor */
648
    flags = SDL_ANYFORMAT | SDL_HWPALETTE;
649

650
    if( p_vout->b_fullscreen )
Sam Hocevar's avatar
 
Sam Hocevar committed
651
    {
652
        flags |= SDL_FULLSCREEN;
Sam Hocevar's avatar
 
Sam Hocevar committed
653
    }
654
    else
Sam Hocevar's avatar
 
Sam Hocevar committed
655
    {
656
        flags |= SDL_RESIZABLE;
Sam Hocevar's avatar
 
Sam Hocevar committed
657
    }
658 659

    if( p_vout->b_need_render )
Sam Hocevar's avatar
 
Sam Hocevar committed
660
    {
661
        flags |= SDL_HWSURFACE | SDL_DOUBLEBUF;
Sam Hocevar's avatar
 
Sam Hocevar committed
662
    }
663
    else
Sam Hocevar's avatar
 
Sam Hocevar committed
664
    {
665
        flags |= SDL_SWSURFACE; /* save video memory */
Sam Hocevar's avatar
 
Sam Hocevar committed
666
    }
667

Sam Hocevar's avatar
 
Sam Hocevar committed
668 669 670
    bpp = SDL_VideoModeOK( p_vout->p_sys->i_width,
                           p_vout->p_sys->i_height,
                           p_vout->i_screen_depth, flags );
671

Sam Hocevar's avatar
 
Sam Hocevar committed
672
    if( bpp == 0 )
Pierre Baillet's avatar
Pierre Baillet committed
673
    {
Sam Hocevar's avatar
 
Sam Hocevar committed
674
        intf_ErrMsg( "vout error: no video mode available" );
675
        return( 1 );
Pierre Baillet's avatar
Pierre Baillet committed
676
    }
677 678 679 680 681

    p_vout->p_sys->p_display = SDL_SetVideoMode(p_vout->p_sys->i_width,
                                                p_vout->p_sys->i_height,
                                                bpp, flags);

Pierre Baillet's avatar
Pierre Baillet committed
682 683
    if( p_vout->p_sys->p_display == NULL )
    {
Sam Hocevar's avatar
 
Sam Hocevar committed
684
        intf_ErrMsg( "vout error: cannot set video mode" );
Pierre Baillet's avatar
Pierre Baillet committed
685 686
        return( 1 );
    }
687

Sam Hocevar's avatar
 
Sam Hocevar committed
688
    SDL_LockSurface( p_vout->p_sys->p_display );
689

Sam Hocevar's avatar
 
Sam Hocevar committed
690 691
    SDL_WM_SetCaption( VOUT_TITLE " (SDL output)",
                       VOUT_TITLE " (SDL output)" );
Sam Hocevar's avatar
 
Sam Hocevar committed
692 693
    SDL_EventState(SDL_KEYUP , SDL_IGNORE);                /* ignore keys up */

694
    if( p_vout->b_need_render )
Pierre Baillet's avatar
Pierre Baillet committed
695
    {
Sam Hocevar's avatar
 
Sam Hocevar committed
696
        p_vout->p_sys->p_sdl_buf[ 0 ] = p_vout->p_sys->p_display->pixels;
697
        SDL_Flip(p_vout->p_sys->p_display);
Sam Hocevar's avatar
 
Sam Hocevar committed
698
        p_vout->p_sys->p_sdl_buf[ 1 ] = p_vout->p_sys->p_display->pixels;
699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723
        SDL_Flip(p_vout->p_sys->p_display);

        /* Set clipping for text */
        clipping_rect.x = 0;
        clipping_rect.y = 0;
        clipping_rect.w = p_vout->p_sys->p_display->w;
        clipping_rect.h = p_vout->p_sys->p_display->h;
        SDL_SetClipRect(p_vout->p_sys->p_display, &clipping_rect);

        /* Set thread information */
        p_vout->i_width =           p_vout->p_sys->p_display->w;
        p_vout->i_height =          p_vout->p_sys->p_display->h;
        p_vout->i_bytes_per_line =  p_vout->p_sys->p_display->pitch;

        p_vout->i_screen_depth =
            p_vout->p_sys->p_display->format->BitsPerPixel;
        p_vout->i_bytes_per_pixel =
            p_vout->p_sys->p_display->format->BytesPerPixel;

        p_vout->i_red_mask =        p_vout->p_sys->p_display->format->Rmask;
        p_vout->i_green_mask =      p_vout->p_sys->p_display->format->Gmask;
        p_vout->i_blue_mask =       p_vout->p_sys->p_display->format->Bmask;

        /* FIXME: palette in 8bpp ?? */
        /* Set and initialize buffers */
Sam Hocevar's avatar
 
Sam Hocevar committed
724 725
        p_vout->pf_setbuffers( p_vout, p_vout->p_sys->p_sdl_buf[ 0 ],
                                       p_vout->p_sys->p_sdl_buf[ 1 ] );
Pierre Baillet's avatar
Pierre Baillet committed
726
    }
727 728
    else
    {
Sam Hocevar's avatar
 
Sam Hocevar committed
729 730
        p_vout->p_sys->p_sdl_buf[ 0 ] = p_vout->p_sys->p_display->pixels;
        p_vout->p_sys->p_sdl_buf[ 1 ] = p_vout->p_sys->p_display->pixels;
731 732 733 734 735 736

        /* Set thread information */
        p_vout->i_width =           p_vout->p_sys->p_display->w;
        p_vout->i_height =          p_vout->p_sys->p_display->h;
        p_vout->i_bytes_per_line =  p_vout->p_sys->p_display->pitch;

Sam Hocevar's avatar
 
Sam Hocevar committed
737 738
        p_vout->pf_setbuffers( p_vout, p_vout->p_sys->p_sdl_buf[ 0 ],
                                       p_vout->p_sys->p_sdl_buf[ 1 ] );
739 740
    }

741
    p_vout->p_sys->b_reopen_display = 0;
Pierre Baillet's avatar
Pierre Baillet committed
742 743 744 745 746 747 748 749 750 751 752 753

    return( 0 );
}

/*****************************************************************************
 * SDLCloseDisplay: close and reset SDL device
 *****************************************************************************
 * This function returns all resources allocated by SDLOpenDisplay and restore
 * the original state of the device.
 *****************************************************************************/
static void SDLCloseDisplay( vout_thread_t *p_vout )
{
Pierre Baillet's avatar
Pierre Baillet committed
754
    if( p_vout->p_sys->p_display != NULL )
755
    {
Pierre Baillet's avatar
Pierre Baillet committed
756 757
        if( p_vout->p_sys->p_overlay != NULL )
        {            
Sam Hocevar's avatar
 
Sam Hocevar committed
758
            SDL_FreeYUVOverlay( p_vout->p_sys->p_overlay );
759 760
            p_vout->p_sys->p_overlay = NULL;
        }
Sam Hocevar's avatar
 
Sam Hocevar committed
761

762
        SDL_UnlockSurface ( p_vout->p_sys->p_display );
763 764 765
        SDL_FreeSurface( p_vout->p_sys->p_display );
        p_vout->p_sys->p_display = NULL;
    }
Pierre Baillet's avatar
Pierre Baillet committed
766 767
}