vout_sdl.c 27.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
5
 * $Id: vout_sdl.c,v 1.58 2001/07/16 14:33:40 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

Pierre Baillet's avatar
Pierre Baillet committed
43
44
45
46
47
48
#include <SDL/SDL.h>

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

Pierre Baillet's avatar
Pierre Baillet committed
51
52
53
54
#include "video.h"
#include "video_output.h"

#include "intf_msg.h"
Sam Hocevar's avatar
   
Sam Hocevar committed
55
56
57
#include "interface.h"
/* FIXME: get rid of this */
#include "keystrokes.h"
58
#include "main.h"
Henri Fallon's avatar
   
Henri Fallon committed
59
#include "netutils.h"
Pierre Baillet's avatar
Pierre Baillet committed
60

Sam Hocevar's avatar
   
Sam Hocevar committed
61
62
63
#include "modules.h"
#include "modules_export.h"

Sam Hocevar's avatar
   
Sam Hocevar committed
64
65
66
/*****************************************************************************
 * FIXME: this file is ...                                                   *
 *                                                                           *
Sam Hocevar's avatar
   
Sam Hocevar committed
67
68
69
70
71
72
 *              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
73
74
75
 *                                                                           *
 *****************************************************************************/

Pierre Baillet's avatar
Pierre Baillet committed
76
77
78
79
80
81
82
83
/*****************************************************************************
 * 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
{
84
85
    int i_width;
    int i_height;
Sam Hocevar's avatar
   
Sam Hocevar committed
86

Pierre Baillet's avatar
Pierre Baillet committed
87
    SDL_Surface *   p_display;                             /* display device */
88
    SDL_Overlay *   p_overlay;                             /* overlay device */
Sam Hocevar's avatar
   
Sam Hocevar committed
89

Sam Hocevar's avatar
   
Sam Hocevar committed
90
    boolean_t   b_overlay;
91
    boolean_t   b_cursor;
92
    boolean_t   b_reopen_display;
Sam Hocevar's avatar
   
Sam Hocevar committed
93
94
95
96

    boolean_t   b_cursor_autohidden;
    mtime_t     i_lastmoved;

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

Sam Hocevar's avatar
   
Sam Hocevar committed
99
} vout_sys_t;
Pierre Baillet's avatar
Pierre Baillet committed
100
101

/*****************************************************************************
Sam Hocevar's avatar
   
Sam Hocevar committed
102
103
104
105
106
107
108
109
110
 * 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 * );
111
112
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
113
114
115
116
117
118
119

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
120
 *****************************************************************************/
Sam Hocevar's avatar
   
Sam Hocevar committed
121
void _M( vout_getfunctions )( function_list_t * p_function_list )
Sam Hocevar's avatar
   
Sam Hocevar committed
122
123
124
125
126
127
128
129
{
    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;
130
    p_function_list->functions.vout.pf_setpalette = vout_SetPalette;
Sam Hocevar's avatar
   
Sam Hocevar committed
131
132
}

Pierre Baillet's avatar
Pierre Baillet committed
133
/*****************************************************************************
Sam Hocevar's avatar
   
Sam Hocevar committed
134
 * vout_Probe: probe the video driver and return a score
Sam Hocevar's avatar
   
Sam Hocevar committed
135
136
137
138
139
140
141
142
143
144
145
 *****************************************************************************
 * 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
146
    return( 100 );
Sam Hocevar's avatar
   
Sam Hocevar committed
147
148
149
150
}

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

166
    /* Initialize library */
Sam Hocevar's avatar
   
Sam Hocevar committed
167
168
169
170
171
    if( SDL_Init( SDL_INIT_VIDEO
#ifndef WIN32
    /* Win32 SDL implementation doesn't support SDL_INIT_EVENTTHREAD yet*/
                | SDL_INIT_EVENTTHREAD
#endif
172
173
174
175
176
177
#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
178
    {
Sam Hocevar's avatar
   
Sam Hocevar committed
179
        intf_ErrMsg( "vout error: can't initialize SDL (%s)", SDL_GetError() );
Pierre Baillet's avatar
Pierre Baillet committed
180
181
182
        free( p_vout->p_sys );
        return( 1 );
    }
183

Sam Hocevar's avatar
   
Sam Hocevar committed
184
    p_vout->p_sys->b_cursor = 1; /* TODO should be done with a main_GetInt.. */
Sam Hocevar's avatar
   
Sam Hocevar committed
185
186
187
188

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

189
    p_vout->b_fullscreen = main_GetIntVariable( VOUT_FULLSCREEN_VAR,
Sam Hocevar's avatar
   
Sam Hocevar committed
190
191
192
                                VOUT_FULLSCREEN_DEFAULT );
    p_vout->p_sys->b_overlay = main_GetIntVariable( VOUT_OVERLAY_VAR,
                                VOUT_OVERLAY_DEFAULT );
193
194
195
196
    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 );
197

Sam Hocevar's avatar
   
Sam Hocevar committed
198
199
200
    p_vout->p_sys->p_display = NULL;
    p_vout->p_sys->p_overlay = NULL;

201
202
    if( SDLOpenDisplay(p_vout) )
    {
Sam Hocevar's avatar
   
Sam Hocevar committed
203
        intf_ErrMsg( "vout error: can't set up SDL (%s)", SDL_GetError() );
Sam Hocevar's avatar
   
Sam Hocevar committed
204
205
        free( p_vout->p_sys );
        return( 1 );
206
207
    }

Sam Hocevar's avatar
   
Sam Hocevar committed
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
    /* 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);
232
233
    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
234

Pierre Baillet's avatar
Pierre Baillet committed
235
    return( 0 );
236
}
Pierre Baillet's avatar
Pierre Baillet committed
237
238

/*****************************************************************************
Sam Hocevar's avatar
   
Sam Hocevar committed
239
 * vout_Init: initialize SDL video thread output method
Pierre Baillet's avatar
Pierre Baillet committed
240
241
242
 *****************************************************************************
 * This function initialize the SDL display device.
 *****************************************************************************/
243
static int vout_Init( vout_thread_t *p_vout )
Pierre Baillet's avatar
Pierre Baillet committed
244
{
245
246
247
    /* This hack is hugly, but hey, you are, too. */

    SDL_Overlay *   p_overlay;
Pierre Baillet's avatar
Pierre Baillet committed
248
249
250
251
    
    p_overlay = SDL_CreateYUVOverlay( 
           main_GetIntVariable( VOUT_WIDTH_VAR,VOUT_WIDTH_DEFAULT ),
           main_GetIntVariable( VOUT_HEIGHT_VAR,VOUT_HEIGHT_DEFAULT ),
252
253
                                      SDL_YV12_OVERLAY, 
                                      p_vout->p_sys->p_display );
Sam Hocevar's avatar
   
Sam Hocevar committed
254
255
256
257
258
259
260
261

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

262
    intf_WarnMsg( 2, "vout: YUV acceleration %s",
263
264
265
266
267
              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
268
269
270
271
    return( 0 );
}

/*****************************************************************************
Sam Hocevar's avatar
   
Sam Hocevar committed
272
 * vout_End: terminate Sys video thread output method
Pierre Baillet's avatar
Pierre Baillet committed
273
274
275
 *****************************************************************************
 * Terminate an output method created by vout_SDLCreate
 *****************************************************************************/
276
static void vout_End( vout_thread_t *p_vout )
Pierre Baillet's avatar
Pierre Baillet committed
277
{
278
    SDLCloseDisplay( p_vout );
Sam Hocevar's avatar
   
Sam Hocevar committed
279
    SDL_QuitSubSystem( SDL_INIT_VIDEO );
Pierre Baillet's avatar
Pierre Baillet committed
280
281
282
}

/*****************************************************************************
Sam Hocevar's avatar
   
Sam Hocevar committed
283
 * vout_Destroy: destroy Sys video thread output method
Pierre Baillet's avatar
Pierre Baillet committed
284
285
286
 *****************************************************************************
 * Terminate an output method created by vout_SDLCreate
 *****************************************************************************/
287
static void vout_Destroy( vout_thread_t *p_vout )
Pierre Baillet's avatar
Pierre Baillet committed
288
289
290
291
292
{
    free( p_vout->p_sys );
}

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

    /* 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
314
315
316
317
318
319
320
321
322
        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
323
                else
Sam Hocevar's avatar
   
Sam Hocevar committed
324
325
326
327
328
329
                {
                    p_vout->p_sys->i_lastmoved = mdate();
                }
            }
            break;

Sam Hocevar's avatar
   
Sam Hocevar committed
330
331
332
333
334
335
336
337
338
        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
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
        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
354
            switch( event.key.keysym.sym )
Sam Hocevar's avatar
   
Sam Hocevar committed
355
356
357
358
359
360
361
362
363
364
365
            {
            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
366
                p_vout->i_changes |= VOUT_GRAYSCALE_CHANGE;
Sam Hocevar's avatar
   
Sam Hocevar committed
367
368
369
370
                break;

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

Sam Hocevar's avatar
   
Sam Hocevar committed
374
            case SDLK_s:                                   /* toggle scaling */
Sam Hocevar's avatar
   
Sam Hocevar committed
375
                p_vout->b_scale = ! p_vout->b_scale;
Sam Hocevar's avatar
   
Sam Hocevar committed
376
                p_vout->i_changes |= VOUT_SCALE_CHANGE;
Sam Hocevar's avatar
   
Sam Hocevar committed
377
378
                break;

Sam Hocevar's avatar
   
Sam Hocevar committed
379
            case SDLK_SPACE:                             /* toggle interface */
Sam Hocevar's avatar
   
Sam Hocevar committed
380
                p_vout->b_interface = ! p_vout->b_interface;
Sam Hocevar's avatar
   
Sam Hocevar committed
381
                p_vout->i_changes |= VOUT_INTF_CHANGE;
Sam Hocevar's avatar
   
Sam Hocevar committed
382
                break;
Henri Fallon's avatar
   
Henri Fallon committed
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
            
            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
414

Henri Fallon's avatar
   
Henri Fallon committed
415
416
417
418
            case SDLK_MENU:
                p_main->p_intf->b_menu_change = 1;
                break;
                
Sam Hocevar's avatar
   
Sam Hocevar committed
419
            default:
Henri Fallon's avatar
   
Henri Fallon committed
420
421
422
                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
423
                {
Henri Fallon's avatar
   
Henri Fallon committed
424
425
426
427
                   intf_DbgMsg( "unhandled key '%c' (%i)", 
                                (char)event.key.keysym.sym, 
                                event.key.keysym.sym );                
                }
Sam Hocevar's avatar
   
Sam Hocevar committed
428
429
430
431
432
433
434
435
                break;
            }
            break;

        default:
            break;
        }
    }
436
437
438
439

    /*
     * Size Change 
     */
Sam Hocevar's avatar
   
Sam Hocevar committed
440
    if( p_vout->i_changes & VOUT_SIZE_CHANGE )
441
    {
442
443
        p_vout->p_sys->i_width = p_vout->i_width;
        p_vout->p_sys->i_height = p_vout->i_height;
444

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

472
473
474
    /*
     * Fullscreen change
     */
Sam Hocevar's avatar
   
Sam Hocevar committed
475
    if( p_vout->i_changes & VOUT_FULLSCREEN_CHANGE )
476
    {
477
        p_vout->b_fullscreen = ! p_vout->b_fullscreen;
Sam Hocevar's avatar
   
Sam Hocevar committed
478
479
480

        SDL_WM_ToggleFullScreen(p_vout->p_sys->p_display);

Sam Hocevar's avatar
   
Sam Hocevar committed
481
482
483
484
        p_vout->p_sys->b_cursor_autohidden = 0;
        SDL_ShowCursor( p_vout->p_sys->b_cursor &&
                        ! p_vout->p_sys->b_cursor_autohidden );

485
        p_vout->i_changes &= ~VOUT_FULLSCREEN_CHANGE;
486
    }
487
488
489
490

    /*
     * Pointer change
     */
Sam Hocevar's avatar
   
Sam Hocevar committed
491
492
493
494
495
496
497
498
    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
499
    if( p_vout->i_changes & VOUT_CURSOR_CHANGE )
500
    {
Sam Hocevar's avatar
   
Sam Hocevar committed
501
502
503
504
505
        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
506
        p_vout->i_changes &= ~VOUT_CURSOR_CHANGE;
507
508
    }
    
Pierre Baillet's avatar
Pierre Baillet committed
509
510
    return( 0 );
}
Sam Hocevar's avatar
   
Sam Hocevar committed
511

512
/*****************************************************************************
Sam Hocevar's avatar
   
Sam Hocevar committed
513
 * vout_SetPalette: sets an 8 bpp palette
514
515
516
517
518
 *****************************************************************************
 * 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.
 *****************************************************************************/
519
static void vout_SetPalette( p_vout_thread_t p_vout, u16 *red, u16 *green,
520
                         u16 *blue, u16 *transp)
521
522
523
524
525
526
{
     /* 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
527
528
529
530
531
    for( i = 0; i < 256; i++ )
    {
        colors[ i ].r = red[ i ] >> 8;
        colors[ i ].g = green[ i ] >> 8;
        colors[ i ].b = blue[ i ] >> 8;
532
533
534
    }
    
    /* Set palette */
Sam Hocevar's avatar
   
Sam Hocevar committed
535
    if( SDL_SetColors( p_vout->p_sys->p_display, colors, 0, 256 ) == 0 )
Sam Hocevar's avatar
   
Sam Hocevar committed
536
    {
Sam Hocevar's avatar
   
Sam Hocevar committed
537
        intf_ErrMsg( "vout error: failed setting palette" );
Sam Hocevar's avatar
   
Sam Hocevar committed
538
    }
539
540
541

}

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

            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
585
                SDL_LockYUVOverlay( p_vout->p_sys->p_overlay );
Sam Hocevar's avatar
   
Sam Hocevar committed
586
587
                /* copy the data into video buffers */
                /* Y first */
Sam Hocevar's avatar
   
Sam Hocevar committed
588
589
590
591
                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
592
                /* then V */
Sam Hocevar's avatar
   
Sam Hocevar committed
593
594
595
596
                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
597
                /* and U */
Sam Hocevar's avatar
   
Sam Hocevar committed
598
599
600
601
                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
602
603
604
605
606
607
608
609
610
611
    
#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);
612

Sam Hocevar's avatar
   
Sam Hocevar committed
613
614
                return;
            }
615
        }
Sam Hocevar's avatar
   
Sam Hocevar committed
616
617
618
    
        /* Software YUV: change display frame */
        SDL_Flip( p_vout->p_sys->p_display );
619
    }
Pierre Baillet's avatar
Pierre Baillet committed
620
621
622
623
624
625
626
627
628
629
}

/* following functions are local */

/*****************************************************************************
 * SDLOpenDisplay: open and initialize SDL device
 *****************************************************************************
 * Open and initialize display according to preferences specified in the vout
 * thread fields.
 *****************************************************************************/
630
static int SDLOpenDisplay( vout_thread_t *p_vout )
Pierre Baillet's avatar
Pierre Baillet committed
631
{
632
    SDL_Rect    clipping_rect;
633
634
    Uint32      flags;
    int bpp;
Pierre Baillet's avatar
Pierre Baillet committed
635
636
637
    /* Open display 
     * TODO: Check that we can request for a DOUBLEBUF HWSURFACE display
     */
638
639

    /* init flags and cursor */
640
    flags = SDL_ANYFORMAT | SDL_HWPALETTE;
641

642
    if( p_vout->b_fullscreen )
Sam Hocevar's avatar
   
Sam Hocevar committed
643
    {
644
        flags |= SDL_FULLSCREEN;
Sam Hocevar's avatar
   
Sam Hocevar committed
645
    }
646
    else
Sam Hocevar's avatar
   
Sam Hocevar committed
647
    {
648
        flags |= SDL_RESIZABLE;
Sam Hocevar's avatar
   
Sam Hocevar committed
649
    }
650
651

    if( p_vout->b_need_render )
Sam Hocevar's avatar
   
Sam Hocevar committed
652
    {
653
        flags |= SDL_HWSURFACE | SDL_DOUBLEBUF;
Sam Hocevar's avatar
   
Sam Hocevar committed
654
    }
655
    else
Sam Hocevar's avatar
   
Sam Hocevar committed
656
    {
657
        flags |= SDL_SWSURFACE; /* save video memory */
Sam Hocevar's avatar
   
Sam Hocevar committed
658
    }
659

Sam Hocevar's avatar
   
Sam Hocevar committed
660
661
662
    bpp = SDL_VideoModeOK( p_vout->p_sys->i_width,
                           p_vout->p_sys->i_height,
                           p_vout->i_screen_depth, flags );
663

Sam Hocevar's avatar
   
Sam Hocevar committed
664
    if( bpp == 0 )
Pierre Baillet's avatar
Pierre Baillet committed
665
    {
Sam Hocevar's avatar
   
Sam Hocevar committed
666
        intf_ErrMsg( "vout error: no video mode available" );
667
        return( 1 );
Pierre Baillet's avatar
Pierre Baillet committed
668
    }
669
670
671
672
673

    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
674
675
    if( p_vout->p_sys->p_display == NULL )
    {
Sam Hocevar's avatar
   
Sam Hocevar committed
676
        intf_ErrMsg( "vout error: cannot set video mode" );
Pierre Baillet's avatar
Pierre Baillet committed
677
678
        return( 1 );
    }
679

Sam Hocevar's avatar
   
Sam Hocevar committed
680
    SDL_LockSurface( p_vout->p_sys->p_display );
681

Sam Hocevar's avatar
   
Sam Hocevar committed
682
683
    SDL_WM_SetCaption( VOUT_TITLE " (SDL output)",
                       VOUT_TITLE " (SDL output)" );
Sam Hocevar's avatar
   
Sam Hocevar committed
684
685
    SDL_EventState(SDL_KEYUP , SDL_IGNORE);                /* ignore keys up */

686
    if( p_vout->b_need_render )
Pierre Baillet's avatar
Pierre Baillet committed
687
    {
Sam Hocevar's avatar
   
Sam Hocevar committed
688
        p_vout->p_sys->p_sdl_buf[ 0 ] = p_vout->p_sys->p_display->pixels;
689
        SDL_Flip(p_vout->p_sys->p_display);
Sam Hocevar's avatar
   
Sam Hocevar committed
690
        p_vout->p_sys->p_sdl_buf[ 1 ] = p_vout->p_sys->p_display->pixels;
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
        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
716
717
        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
718
    }
719
720
    else
    {
Sam Hocevar's avatar
   
Sam Hocevar committed
721
722
        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;
723
724
725
726
727
728

        /* 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
729
730
        p_vout->pf_setbuffers( p_vout, p_vout->p_sys->p_sdl_buf[ 0 ],
                                       p_vout->p_sys->p_sdl_buf[ 1 ] );
731
732
    }

733
    p_vout->p_sys->b_reopen_display = 0;
Pierre Baillet's avatar
Pierre Baillet committed
734
735
736
737
738
739
740
741
742
743
744
745

    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
746
    if( p_vout->p_sys->p_display != NULL )
747
    {
Pierre Baillet's avatar
Pierre Baillet committed
748
749
        if( p_vout->p_sys->p_overlay != NULL )
        {            
Sam Hocevar's avatar
   
Sam Hocevar committed
750
            SDL_FreeYUVOverlay( p_vout->p_sys->p_overlay );
751
752
            p_vout->p_sys->p_overlay = NULL;
        }
Sam Hocevar's avatar
   
Sam Hocevar committed
753

754
        SDL_UnlockSurface ( p_vout->p_sys->p_display );
755
756
757
        SDL_FreeSurface( p_vout->p_sys->p_display );
        p_vout->p_sys->p_display = NULL;
    }
Pierre Baillet's avatar
Pierre Baillet committed
758
759
}