vout_sdl.c 26.5 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
Henri Fallon's avatar
   
Henri Fallon committed
5
 * $Id: vout_sdl.c,v 1.47 2001/04/11 02:01:24 henri 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
38
39
40
41
42
43
/*****************************************************************************
 * Preamble
 *****************************************************************************/
#include "defs.h"

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

#include <SDL/SDL.h>

#include "config.h"
#include "common.h"
#include "threads.h"
#include "mtime.h"
Sam Hocevar's avatar
   
Sam Hocevar committed
44
45
46
#include "tests.h"
#include "modules.h"

Pierre Baillet's avatar
Pierre Baillet committed
47
48
49
50
#include "video.h"
#include "video_output.h"

#include "intf_msg.h"
Sam Hocevar's avatar
   
Sam Hocevar committed
51
52
53
#include "interface.h"
/* FIXME: get rid of this */
#include "keystrokes.h"
54
#include "main.h"
Henri Fallon's avatar
   
Henri Fallon committed
55
#include "netutils.h"
Pierre Baillet's avatar
Pierre Baillet committed
56

Sam Hocevar's avatar
   
Sam Hocevar committed
57
58
59
/*****************************************************************************
 * FIXME: this file is ...                                                   *
 *                                                                           *
Sam Hocevar's avatar
   
Sam Hocevar committed
60
61
62
63
64
65
 *              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
66
67
68
 *                                                                           *
 *****************************************************************************/

Pierre Baillet's avatar
Pierre Baillet committed
69
70
71
72
73
74
75
76
/*****************************************************************************
 * 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
{
77
78
    int i_width;
    int i_height;
Sam Hocevar's avatar
   
Sam Hocevar committed
79

Pierre Baillet's avatar
Pierre Baillet committed
80
    SDL_Surface *   p_display;                             /* display device */
81
    SDL_Overlay *   p_overlay;                             /* overlay device */
Sam Hocevar's avatar
   
Sam Hocevar committed
82

83
    boolean_t   b_fullscreen;
Sam Hocevar's avatar
   
Sam Hocevar committed
84
    boolean_t   b_overlay;
85
    boolean_t   b_cursor;
86
    boolean_t   b_reopen_display;
Sam Hocevar's avatar
   
Sam Hocevar committed
87
88
89
90

    boolean_t   b_cursor_autohidden;
    mtime_t     i_lastmoved;

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

Sam Hocevar's avatar
   
Sam Hocevar committed
93
} vout_sys_t;
Pierre Baillet's avatar
Pierre Baillet committed
94
95

/*****************************************************************************
Sam Hocevar's avatar
   
Sam Hocevar committed
96
97
98
99
100
101
102
103
104
 * 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 * );
105
106
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
107
108
109
110
111
112
113

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
114
 *****************************************************************************/
Sam Hocevar's avatar
   
Sam Hocevar committed
115
void _M( vout_getfunctions )( function_list_t * p_function_list )
Sam Hocevar's avatar
   
Sam Hocevar committed
116
117
118
119
120
121
122
123
{
    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;
124
    p_function_list->functions.vout.pf_setpalette = vout_SetPalette;
Sam Hocevar's avatar
   
Sam Hocevar committed
125
126
}

Pierre Baillet's avatar
Pierre Baillet committed
127
/*****************************************************************************
Sam Hocevar's avatar
   
Sam Hocevar committed
128
 * vout_Probe: probe the video driver and return a score
Sam Hocevar's avatar
   
Sam Hocevar committed
129
130
131
132
133
134
135
136
137
138
139
 *****************************************************************************
 * 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
140
    return( 100 );
Sam Hocevar's avatar
   
Sam Hocevar committed
141
142
143
144
}

/*****************************************************************************
 * vout_Create: allocate SDL video thread output method
Pierre Baillet's avatar
Pierre Baillet committed
145
146
147
148
149
 *****************************************************************************
 * 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.
 *****************************************************************************/
150
static int vout_Create( vout_thread_t *p_vout )
Pierre Baillet's avatar
Pierre Baillet committed
151
152
153
154
155
{
    /* Allocate structure */
    p_vout->p_sys = malloc( sizeof( vout_sys_t ) );
    if( p_vout->p_sys == NULL )
    {
Sam Hocevar's avatar
   
Sam Hocevar committed
156
        intf_ErrMsg( "vout error: can't create p_sys (%s)", strerror(ENOMEM) );
Pierre Baillet's avatar
Pierre Baillet committed
157
158
159
        return( 1 );
    }

160
    /* Initialize library */
161
162
    if( SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTTHREAD | SDL_INIT_NOPARACHUTE)
            < 0 )
Pierre Baillet's avatar
Pierre Baillet committed
163
    {
Sam Hocevar's avatar
   
Sam Hocevar committed
164
        intf_ErrMsg( "vout error: can't initialize SDL (%s)", SDL_GetError() );
Pierre Baillet's avatar
Pierre Baillet committed
165
166
167
        free( p_vout->p_sys );
        return( 1 );
    }
168

Sam Hocevar's avatar
   
Sam Hocevar committed
169
    p_vout->p_sys->b_cursor = 1; /* TODO should be done with a main_GetInt.. */
Sam Hocevar's avatar
   
Sam Hocevar committed
170
171
172
173

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

Sam Hocevar's avatar
   
Sam Hocevar committed
174
175
176
177
    p_vout->p_sys->b_fullscreen = main_GetIntVariable( VOUT_FULLSCREEN_VAR,
                                VOUT_FULLSCREEN_DEFAULT );
    p_vout->p_sys->b_overlay = main_GetIntVariable( VOUT_OVERLAY_VAR,
                                VOUT_OVERLAY_DEFAULT );
178
179
180
181
    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 );
182

Sam Hocevar's avatar
   
Sam Hocevar committed
183
184
185
    p_vout->p_sys->p_display = NULL;
    p_vout->p_sys->p_overlay = NULL;

186
187
    if( SDLOpenDisplay(p_vout) )
    {
Sam Hocevar's avatar
   
Sam Hocevar committed
188
        intf_ErrMsg( "vout error: can't set up SDL (%s)", SDL_GetError() );
Sam Hocevar's avatar
   
Sam Hocevar committed
189
190
        free( p_vout->p_sys );
        return( 1 );
191
192
    }

Sam Hocevar's avatar
   
Sam Hocevar committed
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
    /* 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);
217
218
    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
219

Pierre Baillet's avatar
Pierre Baillet committed
220
    return( 0 );
221
}
Pierre Baillet's avatar
Pierre Baillet committed
222
223

/*****************************************************************************
Sam Hocevar's avatar
   
Sam Hocevar committed
224
 * vout_Init: initialize SDL video thread output method
Pierre Baillet's avatar
Pierre Baillet committed
225
226
227
 *****************************************************************************
 * This function initialize the SDL display device.
 *****************************************************************************/
228
static int vout_Init( vout_thread_t *p_vout )
Pierre Baillet's avatar
Pierre Baillet committed
229
{
230
231
232
    /* This hack is hugly, but hey, you are, too. */

    SDL_Overlay *   p_overlay;
Pierre Baillet's avatar
Pierre Baillet committed
233
234
235
236
    
    p_overlay = SDL_CreateYUVOverlay( 
           main_GetIntVariable( VOUT_WIDTH_VAR,VOUT_WIDTH_DEFAULT ),
           main_GetIntVariable( VOUT_HEIGHT_VAR,VOUT_HEIGHT_DEFAULT ),
237
238
239
240
241
242
243
244
                                      SDL_YV12_OVERLAY, 
                                      p_vout->p_sys->p_display );
    intf_Msg( "vout: YUV acceleration %s",
              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
245
246
247
248
    return( 0 );
}

/*****************************************************************************
Sam Hocevar's avatar
   
Sam Hocevar committed
249
 * vout_End: terminate Sys video thread output method
Pierre Baillet's avatar
Pierre Baillet committed
250
251
252
 *****************************************************************************
 * Terminate an output method created by vout_SDLCreate
 *****************************************************************************/
253
static void vout_End( vout_thread_t *p_vout )
Pierre Baillet's avatar
Pierre Baillet committed
254
{
255
256
    SDLCloseDisplay( p_vout );
    SDL_Quit();
Pierre Baillet's avatar
Pierre Baillet committed
257
258
259
}

/*****************************************************************************
Sam Hocevar's avatar
   
Sam Hocevar committed
260
 * vout_Destroy: destroy Sys video thread output method
Pierre Baillet's avatar
Pierre Baillet committed
261
262
263
 *****************************************************************************
 * Terminate an output method created by vout_SDLCreate
 *****************************************************************************/
264
static void vout_Destroy( vout_thread_t *p_vout )
Pierre Baillet's avatar
Pierre Baillet committed
265
266
267
268
269
{
    free( p_vout->p_sys );
}

/*****************************************************************************
Sam Hocevar's avatar
   
Sam Hocevar committed
270
 * vout_Manage: handle Sys events
Pierre Baillet's avatar
Pierre Baillet committed
271
272
273
274
 *****************************************************************************
 * This function should be called regularly by video output thread. It returns
 * a non null value if an error occured.
 *****************************************************************************/
275
static int vout_Manage( vout_thread_t *p_vout )
Pierre Baillet's avatar
Pierre Baillet committed
276
{
Sam Hocevar's avatar
   
Sam Hocevar committed
277
    SDL_Event event;                                            /* SDL event */
Henri Fallon's avatar
   
Henri Fallon committed
278
    char *    p_key;
Sam Hocevar's avatar
   
Sam Hocevar committed
279
280
281
282
283
284
285
286
287
288
289
290

    /* 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
291
292
293
294
295
296
297
298
299
        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
300
                else
Sam Hocevar's avatar
   
Sam Hocevar committed
301
302
303
304
305
306
                {
                    p_vout->p_sys->i_lastmoved = mdate();
                }
            }
            break;

Sam Hocevar's avatar
   
Sam Hocevar committed
307
308
309
310
311
312
313
314
315
        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
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
        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
331
            switch( event.key.keysym.sym )
Sam Hocevar's avatar
   
Sam Hocevar committed
332
333
334
335
336
337
338
339
340
341
342
            {
            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
343
                p_vout->i_changes |= VOUT_GRAYSCALE_CHANGE;
Sam Hocevar's avatar
   
Sam Hocevar committed
344
345
346
347
                break;

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

Sam Hocevar's avatar
   
Sam Hocevar committed
351
            case SDLK_s:                                   /* toggle scaling */
Sam Hocevar's avatar
   
Sam Hocevar committed
352
                p_vout->b_scale = ! p_vout->b_scale;
Sam Hocevar's avatar
   
Sam Hocevar committed
353
                p_vout->i_changes |= VOUT_SCALE_CHANGE;
Sam Hocevar's avatar
   
Sam Hocevar committed
354
355
                break;

Sam Hocevar's avatar
   
Sam Hocevar committed
356
            case SDLK_SPACE:                             /* toggle interface */
Sam Hocevar's avatar
   
Sam Hocevar committed
357
                p_vout->b_interface = ! p_vout->b_interface;
Sam Hocevar's avatar
   
Sam Hocevar committed
358
                p_vout->i_changes |= VOUT_INTF_CHANGE;
Sam Hocevar's avatar
   
Sam Hocevar committed
359
                break;
Henri Fallon's avatar
   
Henri Fallon committed
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
            
            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
391

Henri Fallon's avatar
   
Henri Fallon committed
392
393
394
395
            case SDLK_MENU:
                p_main->p_intf->b_menu_change = 1;
                break;
                
Sam Hocevar's avatar
   
Sam Hocevar committed
396
            default:
Henri Fallon's avatar
   
Henri Fallon committed
397
398
399
                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
400
                {
Henri Fallon's avatar
   
Henri Fallon committed
401
402
403
404
                   intf_DbgMsg( "unhandled key '%c' (%i)", 
                                (char)event.key.keysym.sym, 
                                event.key.keysym.sym );                
                }
Sam Hocevar's avatar
   
Sam Hocevar committed
405
406
407
408
409
410
411
412
                break;
            }
            break;

        default:
            break;
        }
    }
413
414
415
416

    /*
     * Size Change 
     */
Sam Hocevar's avatar
   
Sam Hocevar committed
417
    if( p_vout->i_changes & VOUT_SIZE_CHANGE )
418
    {
419
420
        p_vout->p_sys->i_width = p_vout->i_width;
        p_vout->p_sys->i_height = p_vout->i_height;
421

422
423
        /* Need to reopen display */
        SDLCloseDisplay( p_vout );
Sam Hocevar's avatar
   
Sam Hocevar committed
424
        if( SDLOpenDisplay( p_vout ) )
425
        {
Sam Hocevar's avatar
   
Sam Hocevar committed
426
          intf_ErrMsg( "vout error: can't reopen display after resize" );
427
          return( 1 );
428
        }
429
        p_vout->i_changes &= ~VOUT_SIZE_CHANGE;
430
    }
431
432
433
434
    
    /*
     * YUV Change 
     */
Sam Hocevar's avatar
   
Sam Hocevar committed
435
    if( p_vout->i_changes & VOUT_YUV_CHANGE )
436
    {
Sam Hocevar's avatar
   
Sam Hocevar committed
437
        p_vout->b_need_render = ! p_vout->b_need_render;
438
439
440
        
        /* Need to reopen display */
        SDLCloseDisplay( p_vout );
Sam Hocevar's avatar
   
Sam Hocevar committed
441
        if( SDLOpenDisplay( p_vout ) )
442
        {
Sam Hocevar's avatar
   
Sam Hocevar committed
443
          intf_ErrMsg( "error: can't reopen display after YUV change" );
444
445
446
447
          return( 1 );
        }
        p_vout->i_changes &= ~VOUT_YUV_CHANGE;
    }
Sam Hocevar's avatar
   
Sam Hocevar committed
448

449
450
451
    /*
     * Fullscreen change
     */
Sam Hocevar's avatar
   
Sam Hocevar committed
452
    if( p_vout->i_changes & VOUT_FULLSCREEN_CHANGE )
453
    {
Sam Hocevar's avatar
   
Sam Hocevar committed
454
455
456
457
        p_vout->p_sys->b_fullscreen = ! p_vout->p_sys->b_fullscreen;

        SDL_WM_ToggleFullScreen(p_vout->p_sys->p_display);

Sam Hocevar's avatar
   
Sam Hocevar committed
458
459
460
461
        p_vout->p_sys->b_cursor_autohidden = 0;
        SDL_ShowCursor( p_vout->p_sys->b_cursor &&
                        ! p_vout->p_sys->b_cursor_autohidden );

462
        p_vout->i_changes &= ~VOUT_FULLSCREEN_CHANGE;
463
    }
464
465
466
467

    /*
     * Pointer change
     */
Sam Hocevar's avatar
   
Sam Hocevar committed
468
469
470
471
472
473
474
475
    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
476
    if( p_vout->i_changes & VOUT_CURSOR_CHANGE )
477
    {
Sam Hocevar's avatar
   
Sam Hocevar committed
478
479
480
481
482
        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
483
        p_vout->i_changes &= ~VOUT_CURSOR_CHANGE;
484
485
    }
    
Pierre Baillet's avatar
Pierre Baillet committed
486
487
    return( 0 );
}
Sam Hocevar's avatar
   
Sam Hocevar committed
488

489
/*****************************************************************************
Sam Hocevar's avatar
   
Sam Hocevar committed
490
 * vout_SetPalette: sets an 8 bpp palette
491
492
493
494
495
 *****************************************************************************
 * 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.
 *****************************************************************************/
496
static void vout_SetPalette( p_vout_thread_t p_vout, u16 *red, u16 *green,
497
                         u16 *blue, u16 *transp)
498
499
500
501
502
503
{
     /* 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
504
505
506
507
508
    for( i = 0; i < 256; i++ )
    {
        colors[ i ].r = red[ i ] >> 8;
        colors[ i ].g = green[ i ] >> 8;
        colors[ i ].b = blue[ i ] >> 8;
509
510
511
    }
    
    /* Set palette */
Sam Hocevar's avatar
   
Sam Hocevar committed
512
    if( SDL_SetColors( p_vout->p_sys->p_display, colors, 0, 256 ) == 0 )
Sam Hocevar's avatar
   
Sam Hocevar committed
513
    {
Sam Hocevar's avatar
   
Sam Hocevar committed
514
        intf_ErrMsg( "vout error: failed setting palette" );
Sam Hocevar's avatar
   
Sam Hocevar committed
515
    }
516
517
518

}

Pierre Baillet's avatar
Pierre Baillet committed
519
/*****************************************************************************
Sam Hocevar's avatar
   
Sam Hocevar committed
520
 * vout_Display: displays previously rendered output
Pierre Baillet's avatar
Pierre Baillet committed
521
522
523
524
 *****************************************************************************
 * This function send the currently rendered image to the display, wait until
 * it is displayed and switch the two rendering buffer, preparing next frame.
 *****************************************************************************/
525
static void vout_Display( vout_thread_t *p_vout )
Pierre Baillet's avatar
Pierre Baillet committed
526
{
Pierre Baillet's avatar
Pierre Baillet committed
527
    SDL_Rect    disp;
528
    if((p_vout->p_sys->p_display != NULL) && !p_vout->p_sys->b_reopen_display)
529
    {
Sam Hocevar's avatar
   
Sam Hocevar committed
530
        if( p_vout->b_need_render )
531
532
        {  
            /* Change display frame */
Pierre Baillet's avatar
Pierre Baillet committed
533
534
            SDL_Flip( p_vout->p_sys->p_display );
        }
535
        else
536
        {
537
538
539
540
            /*
             * p_vout->p_rendered_pic->p_y/u/v contains the YUV buffers to
             * render 
             */
541
542
            /* TODO: support for streams other than 4:2:0 */
            /* create the overlay if necessary */
543
            if( p_vout->p_sys->p_overlay == NULL )
544
545
546
            {
                p_vout->p_sys->p_overlay = SDL_CreateYUVOverlay( 
                                             p_vout->p_rendered_pic->i_width, 
547
                                             p_vout->p_rendered_pic->i_height,
548
549
550
                                             SDL_YV12_OVERLAY, 
                                             p_vout->p_sys->p_display
                                           );
Sam Hocevar's avatar
   
Sam Hocevar committed
551
552
553
                intf_Msg("vout: YUV acceleration %s",
                            p_vout->p_sys->p_overlay->hw_overlay
                            ? "activated" : "unavailable !" ); 
554
            }
555

556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
            SDL_LockYUVOverlay(p_vout->p_sys->p_overlay);
            /* copy the data into video buffers */
            /* Y first */
            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]);
            /* then V */
            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);
            /* and U */
            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);
573

574
575
576
577
            disp.w = (&p_vout->p_buffer[p_vout->i_buffer_index])->i_pic_width;
            disp.h = (&p_vout->p_buffer[p_vout->i_buffer_index])->i_pic_height;
            disp.x = (p_vout->i_width - disp.w)/2;
            disp.y = (p_vout->i_height - disp.h)/2;
578

579
580
581
582
            SDL_DisplayYUVOverlay( p_vout->p_sys->p_overlay , &disp );
            SDL_UnlockYUVOverlay(p_vout->p_sys->p_overlay);
        }
    }
Pierre Baillet's avatar
Pierre Baillet committed
583
584
585
586
587
588
589
590
591
592
}

/* following functions are local */

/*****************************************************************************
 * SDLOpenDisplay: open and initialize SDL device
 *****************************************************************************
 * Open and initialize display according to preferences specified in the vout
 * thread fields.
 *****************************************************************************/
593
static int SDLOpenDisplay( vout_thread_t *p_vout )
Pierre Baillet's avatar
Pierre Baillet committed
594
{
595
    SDL_Rect    clipping_rect;
596
597
    Uint32      flags;
    int bpp;
Pierre Baillet's avatar
Pierre Baillet committed
598
599
600
    /* Open display 
     * TODO: Check that we can request for a DOUBLEBUF HWSURFACE display
     */
601
602

    /* init flags and cursor */
603
    flags = SDL_ANYFORMAT | SDL_HWPALETTE;
604

605
    if( p_vout->p_sys->b_fullscreen )
Sam Hocevar's avatar
   
Sam Hocevar committed
606
    {
607
        flags |= SDL_FULLSCREEN;
Sam Hocevar's avatar
   
Sam Hocevar committed
608
    }
609
    else
Sam Hocevar's avatar
   
Sam Hocevar committed
610
    {
611
        flags |= SDL_RESIZABLE;
Sam Hocevar's avatar
   
Sam Hocevar committed
612
    }
613
614

    if( p_vout->b_need_render )
Sam Hocevar's avatar
   
Sam Hocevar committed
615
    {
616
        flags |= SDL_HWSURFACE | SDL_DOUBLEBUF;
Sam Hocevar's avatar
   
Sam Hocevar committed
617
    }
618
    else
Sam Hocevar's avatar
   
Sam Hocevar committed
619
    {
620
        flags |= SDL_SWSURFACE; /* save video memory */
Sam Hocevar's avatar
   
Sam Hocevar committed
621
    }
622

Sam Hocevar's avatar
   
Sam Hocevar committed
623
624
625
    bpp = SDL_VideoModeOK( p_vout->p_sys->i_width,
                           p_vout->p_sys->i_height,
                           p_vout->i_screen_depth, flags );
626

Sam Hocevar's avatar
   
Sam Hocevar committed
627
    if( bpp == 0 )
Pierre Baillet's avatar
Pierre Baillet committed
628
    {
Sam Hocevar's avatar
   
Sam Hocevar committed
629
        intf_ErrMsg( "vout error: no video mode available" );
630
        return( 1 );
Pierre Baillet's avatar
Pierre Baillet committed
631
    }
632
633
634
635
636

    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
637
638
    if( p_vout->p_sys->p_display == NULL )
    {
Sam Hocevar's avatar
   
Sam Hocevar committed
639
        intf_ErrMsg( "vout error: cannot set video mode" );
Pierre Baillet's avatar
Pierre Baillet committed
640
641
        return( 1 );
    }
642

Sam Hocevar's avatar
   
Sam Hocevar committed
643
    SDL_LockSurface( p_vout->p_sys->p_display );
644

Sam Hocevar's avatar
   
Sam Hocevar committed
645
646
    SDL_WM_SetCaption( VOUT_TITLE " (SDL output)",
                       VOUT_TITLE " (SDL output)" );
Sam Hocevar's avatar
   
Sam Hocevar committed
647
648
    SDL_EventState(SDL_KEYUP , SDL_IGNORE);                /* ignore keys up */

649
    if( p_vout->b_need_render )
Pierre Baillet's avatar
Pierre Baillet committed
650
    {
Sam Hocevar's avatar
   
Sam Hocevar committed
651
        p_vout->p_sys->p_sdl_buf[ 0 ] = p_vout->p_sys->p_display->pixels;
652
        SDL_Flip(p_vout->p_sys->p_display);
Sam Hocevar's avatar
   
Sam Hocevar committed
653
        p_vout->p_sys->p_sdl_buf[ 1 ] = p_vout->p_sys->p_display->pixels;
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
        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
679
680
        vout_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
681
    }
682
683
    else
    {
Sam Hocevar's avatar
   
Sam Hocevar committed
684
685
        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;
686
687
688
689
690
691

        /* 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
692
693
        vout_SetBuffers( p_vout, p_vout->p_sys->p_sdl_buf[ 0 ],
                                 p_vout->p_sys->p_sdl_buf[ 1 ] );
694
695
    }

696
    p_vout->p_sys->b_reopen_display = 0;
Pierre Baillet's avatar
Pierre Baillet committed
697
698
699
700
701
702
703
704
705
706
707
708

    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
709
    if( p_vout->p_sys->p_display != NULL )
710
    {
Pierre Baillet's avatar
Pierre Baillet committed
711
712
        if( p_vout->p_sys->p_overlay != NULL )
        {            
Sam Hocevar's avatar
   
Sam Hocevar committed
713
            SDL_FreeYUVOverlay( p_vout->p_sys->p_overlay );
714
715
            p_vout->p_sys->p_overlay = NULL;
        }
Sam Hocevar's avatar
   
Sam Hocevar committed
716

717
        SDL_UnlockSurface ( p_vout->p_sys->p_display );
718
719
720
        SDL_FreeSurface( p_vout->p_sys->p_display );
        p_vout->p_sys->p_display = NULL;
    }
Pierre Baillet's avatar
Pierre Baillet committed
721
722
}