* vout_sdl.c: SDL video output display method
*****************************************************************************
* Copyright (C) 1998, 1999, 2000 VideoLAN
+ * $Id: vout_sdl.c,v 1.53 2001/05/30 17:03:12 sam Exp $
*
- * Authors:
+ * Authors: Samuel Hocevar <sam@zoy.org>
+ * Pierre Baillet <oct@zoy.org>
+ * Arnaud de Bossoreille de Ribou <bozo@via.ecp.fr>
*
* 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
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
*****************************************************************************/
+#define MODULE_NAME sdl
+#include "modules_inner.h"
+
/*****************************************************************************
* Preamble
*****************************************************************************/
#include <stdlib.h> /* free() */
#include <string.h> /* strerror() */
+#ifndef WIN32
+#include <netinet/in.h> /* BSD: struct in_addr */
+#endif
+
#include <SDL/SDL.h>
#include "config.h"
#include "threads.h"
#include "mtime.h"
#include "tests.h"
-#include "modules.h"
-
-/* FIXME: it's up to the _interface_ to do this, not the video output */
-#include "stream_control.h"
-#include "input_ext-intf.h"
#include "video.h"
#include "video_output.h"
/* FIXME: get rid of this */
#include "keystrokes.h"
#include "main.h"
+#include "netutils.h"
+
+#include "modules.h"
+#include "modules_export.h"
/*****************************************************************************
* FIXME: this file is ... *
* *
- * XXX XXX XXX XXX XXX XXX XXX XXX *
- * XXX XXX XXX XXX XXX XXX XXX *
- * XXX XXX XXX XXX XXX XXX *
- * XXX XXX XXX XXX XXX XXX XXX *
- * XXX XXX XXX XXX XXX XXX *
- * XXX XXX XXX XXX XXX XXX XXX *
+ * 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 *
* *
*****************************************************************************/
{
int i_width;
int i_height;
+
SDL_Surface * p_display; /* display device */
SDL_Overlay * p_overlay; /* overlay device */
- boolean_t b_fullscreen;
+
boolean_t b_overlay;
boolean_t b_cursor;
boolean_t b_reopen_display;
- Uint8 * p_buffer[2];
- /* Buffers informations */
-} vout_sys_t;
+
+ boolean_t b_cursor_autohidden;
+ mtime_t i_lastmoved;
+
+ Uint8 * p_sdl_buf[2]; /* Buffer information */
+
+} vout_sys_t;
/*****************************************************************************
* Local prototypes.
static void vout_Destroy ( struct vout_thread_s * );
static int vout_Manage ( struct vout_thread_s * );
static void vout_Display ( struct vout_thread_s * );
+static void vout_SetPalette( p_vout_thread_t p_vout, u16 *red, u16 *green,
+ u16 *blue, u16 *transp );
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.
*****************************************************************************/
-void vout_getfunctions( function_list_t * p_function_list )
+void _M( vout_getfunctions )( function_list_t * p_function_list )
{
p_function_list->pf_probe = vout_Probe;
p_function_list->functions.vout.pf_create = vout_Create;
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;
- p_function_list->functions.vout.pf_setpalette = NULL;
+ p_function_list->functions.vout.pf_setpalette = vout_SetPalette;
}
/*****************************************************************************
- * intf_Probe: probe the video driver and return a score
+ * vout_Probe: probe the video driver and return a score
*****************************************************************************
* This function tries to initialize SDL and returns a score to the
* plugin manager so that it can select the best plugin.
return( 999 );
}
- return( 40 );
+ return( 100 );
}
/*****************************************************************************
* vout properties to choose the correct mode, and change them according to the
* mode actually used.
*****************************************************************************/
-int vout_Create( vout_thread_t *p_vout )
+static int vout_Create( vout_thread_t *p_vout )
{
/* Allocate structure */
p_vout->p_sys = malloc( sizeof( vout_sys_t ) );
}
/* Initialize library */
- if( SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTTHREAD | SDL_INIT_NOPARACHUTE)
- < 0 )
+ if( SDL_Init( SDL_INIT_VIDEO
+#ifndef WIN32
+ /* Win32 SDL implementation doesn't support SDL_INIT_EVENTTHREAD yet*/
+ | SDL_INIT_EVENTTHREAD
+#endif
+ | SDL_INIT_NOPARACHUTE ) < 0 )
{
intf_ErrMsg( "vout error: can't initialize SDL (%s)", SDL_GetError() );
free( p_vout->p_sys );
return( 1 );
}
- /* Force the software yuv even if it is not used */
- /* If we don't do this, p_vout is not correctly initialized
- and it's impossible to switch between soft/hard yuv */
- /* FIXME: this is a broken way to do !! fix this !! */
- p_vout->b_need_render = 1;
-
p_vout->p_sys->b_cursor = 1; /* TODO should be done with a main_GetInt.. */
- p_vout->p_sys->b_fullscreen = main_GetIntVariable( VOUT_FULLSCREEN_VAR,
+
+ p_vout->p_sys->b_cursor_autohidden = 0;
+ p_vout->p_sys->i_lastmoved = mdate();
+
+ p_vout->b_fullscreen = main_GetIntVariable( VOUT_FULLSCREEN_VAR,
VOUT_FULLSCREEN_DEFAULT );
p_vout->p_sys->b_overlay = main_GetIntVariable( VOUT_OVERLAY_VAR,
VOUT_OVERLAY_DEFAULT );
if( SDLOpenDisplay(p_vout) )
{
- intf_ErrMsg( "vout error: can't initialize SDL (%s)", SDL_GetError() );
+ intf_ErrMsg( "vout error: can't set up SDL (%s)", SDL_GetError() );
free( p_vout->p_sys );
return( 1 );
}
/* FIXME: get rid of this ASAP, it's FUCKING UGLY */
{ intf_thread_t * p_intf = p_main->p_intf;
- /* p_intf->p_intf_getKey = intf_getKey; */
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_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);
- intf_AssignKey(p_intf, SDLK_s, INTF_KEY_TOGGLE_SCALING, 0); }
+ intf_AssignKey(p_intf, SDLK_s, INTF_KEY_TOGGLE_SCALING, 0);
+ intf_AssignKey(p_intf, SDLK_d, INTF_KEY_DUMP_STREAM, 0); }
return( 0 );
}
*****************************************************************************
* This function initialize the SDL display device.
*****************************************************************************/
-int vout_Init( vout_thread_t *p_vout )
+static int vout_Init( vout_thread_t *p_vout )
{
+ /* This hack is hugly, but hey, you are, too. */
+
+ SDL_Overlay * p_overlay;
+
+ p_overlay = SDL_CreateYUVOverlay(
+ main_GetIntVariable( VOUT_WIDTH_VAR,VOUT_WIDTH_DEFAULT ),
+ main_GetIntVariable( VOUT_HEIGHT_VAR,VOUT_HEIGHT_DEFAULT ),
+ SDL_YV12_OVERLAY,
+ p_vout->p_sys->p_display );
+ intf_WarnMsg( 2, "vout: YUV acceleration %s",
+ p_overlay->hw_overlay ? "activated" : "unavailable !" );
+ p_vout->b_need_render = !p_overlay->hw_overlay;
+
+ SDL_FreeYUVOverlay( p_overlay );
+
return( 0 );
}
*****************************************************************************
* Terminate an output method created by vout_SDLCreate
*****************************************************************************/
-void vout_End( vout_thread_t *p_vout )
+static void vout_End( vout_thread_t *p_vout )
{
SDLCloseDisplay( p_vout );
SDL_Quit();
*****************************************************************************
* Terminate an output method created by vout_SDLCreate
*****************************************************************************/
-void vout_Destroy( vout_thread_t *p_vout )
+static void vout_Destroy( vout_thread_t *p_vout )
{
free( p_vout->p_sys );
}
* This function should be called regularly by video output thread. It returns
* a non null value if an error occured.
*****************************************************************************/
-int vout_Manage( vout_thread_t *p_vout )
+static int vout_Manage( vout_thread_t *p_vout )
{
SDL_Event event; /* SDL event */
- Uint8 i_key;
- int i_rate;
-
- /* FIXME: do this nicely */
- input_thread_t * p_input = p_main->p_intf->p_input;
+ char * p_key;
/* Process events */
while( SDL_PollEvent(&event) )
p_vout->i_changes |= VOUT_SIZE_CHANGE;
break;
+ 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 );
+ }
+ else
+ {
+ p_vout->p_sys->i_lastmoved = mdate();
+ }
+ }
+ break;
+
+ case SDL_MOUSEBUTTONUP:
+ switch( event.button.button )
+ {
+ case SDL_BUTTON_RIGHT:
+ p_main->p_intf->b_menu_change = 1;
+ break;
+ }
+ break;
+
case SDL_MOUSEBUTTONDOWN:
switch( event.button.button )
{
case SDL_BUTTON_MIDDLE:
p_vout->i_changes |= VOUT_CURSOR_CHANGE;
break;
-
- case SDL_BUTTON_RIGHT:
- p_main->p_intf->b_menu_change = 1;
- break;
}
break;
break;
case SDL_KEYDOWN: /* if a key is pressed */
- i_key = event.key.keysym.sym;
- switch( i_key )
+ switch( event.key.keysym.sym )
{
case SDLK_f: /* switch to fullscreen */
p_vout->i_changes |= VOUT_FULLSCREEN_CHANGE;
case SDLK_c: /* toggle grayscale */
p_vout->b_grayscale = ! p_vout->b_grayscale;
- p_vout->i_changes |= VOUT_GRAYSCALE_CHANGE;
+ p_vout->i_changes |= VOUT_GRAYSCALE_CHANGE;
break;
case SDLK_i: /* toggle info */
p_vout->b_info = ! p_vout->b_info;
- p_vout->i_changes |= VOUT_INFO_CHANGE;
+ p_vout->i_changes |= VOUT_INFO_CHANGE;
break;
- case SDLK_s: /* toggle scaling */
+ case SDLK_s: /* toggle scaling */
p_vout->b_scale = ! p_vout->b_scale;
- p_vout->i_changes |= VOUT_SCALE_CHANGE;
+ p_vout->i_changes |= VOUT_SCALE_CHANGE;
break;
- case SDLK_SPACE: /* toggle interface */
+ case SDLK_SPACE: /* toggle interface */
p_vout->b_interface = ! p_vout->b_interface;
- p_vout->i_changes |= VOUT_INTF_CHANGE;
+ p_vout->i_changes |= VOUT_INTF_CHANGE;
break;
-
- /* FIXME : this is temporary */
- case SDLK_p:
- if( p_input->stream.control.i_status == PLAYING_S )
- {
- input_Pause( p_input );
- }
- else
- {
- input_Play( p_input );
- }
+
+ case SDLK_F10:
+ network_ChannelJoin( 0 );
break;
-
- case SDLK_a:
- i_rate = p_input->stream.control.i_rate/2;
- if ( i_rate >= MINIMAL_RATE )
- {
- input_Forward( p_input, i_rate );
- }
+ case SDLK_F1:
+ network_ChannelJoin( 1 );
break;
-
- case SDLK_z:
- i_rate = p_input->stream.control.i_rate*2;
- if ( i_rate <= MAXIMAL_RATE )
- {
- /* Compensation of int truncature */
- if ( i_rate > 500 && i_rate < 1000 )
- i_rate = 1000;
- input_Forward( p_input, i_rate );
- }
+ case SDLK_F2:
+ network_ChannelJoin( 2 );
break;
-
- case SDLK_j:
- /* Jump forwards */
- input_Seek( p_input, p_input->stream.i_tell
- + p_input->stream.i_size / 20 );
- /* gabuzomeu */
+ case SDLK_F3:
+ network_ChannelJoin( 3 );
break;
-
- case SDLK_b:
- /* Jump backwards */
- input_Seek( p_input, p_input->stream.i_tell
- - p_input->stream.i_size / 20 );
+ 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;
+ case SDLK_MENU:
+ p_main->p_intf->b_menu_change = 1;
+ break;
+
default:
- if( intf_ProcessKey( p_main->p_intf, (char )i_key ) )
+ p_key = SDL_GetKeyName( event.key.keysym.sym ) ;
+ if( intf_ProcessKey( p_main->p_intf,
+ (char )event.key.keysym.sym ) )
{
- intf_DbgMsg( "unhandled key '%c' (%i)", (char)i_key, i_key ); }
+ intf_DbgMsg( "unhandled key '%c' (%i)",
+ (char)event.key.keysym.sym,
+ event.key.keysym.sym );
+ }
break;
}
break;
SDLCloseDisplay( p_vout );
if( SDLOpenDisplay( p_vout ) )
{
- intf_ErrMsg( "error: can't open DISPLAY default display" );
+ intf_ErrMsg( "vout error: can't reopen display after resize" );
return( 1 );
}
p_vout->i_changes &= ~VOUT_SIZE_CHANGE;
SDLCloseDisplay( p_vout );
if( SDLOpenDisplay( p_vout ) )
{
- intf_ErrMsg( "error: can't open DISPLAY default display" );
+ intf_ErrMsg( "error: can't reopen display after YUV change" );
return( 1 );
}
p_vout->i_changes &= ~VOUT_YUV_CHANGE;
*/
if( p_vout->i_changes & VOUT_FULLSCREEN_CHANGE )
{
- p_vout->p_sys->b_fullscreen = ! p_vout->p_sys->b_fullscreen;
-
- if( p_vout->p_sys->b_fullscreen )
- {
- p_vout->p_sys->b_fullscreen = 0;
- p_vout->p_sys->b_cursor = 1;
- SDL_ShowCursor( 1 );
- }
- else
- {
- p_vout->p_sys->b_fullscreen = 1;
- p_vout->p_sys->b_cursor = 0;
- SDL_ShowCursor( 0 );
- }
+ p_vout->b_fullscreen = ! p_vout->b_fullscreen;
SDL_WM_ToggleFullScreen(p_vout->p_sys->p_display);
+ p_vout->p_sys->b_cursor_autohidden = 0;
+ SDL_ShowCursor( p_vout->p_sys->b_cursor &&
+ ! p_vout->p_sys->b_cursor_autohidden );
+
p_vout->i_changes &= ~VOUT_FULLSCREEN_CHANGE;
}
/*
* Pointer change
*/
+ 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 );
+ }
+
if( p_vout->i_changes & VOUT_CURSOR_CHANGE )
{
- if( p_vout->p_sys->b_cursor )
- {
- SDL_ShowCursor( 0 );
- p_vout->p_sys->b_cursor = 0;
- }
- else
- {
- SDL_ShowCursor( 1 );
- p_vout->p_sys->b_cursor = 1;
- }
+ 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 );
+
p_vout->i_changes &= ~VOUT_CURSOR_CHANGE;
}
* anything, but could later send information on which colors it was unable
* to set.
*****************************************************************************/
-void vout_SetPalette( p_vout_thread_t p_vout, u16 *red, u16 *green,
+static void vout_SetPalette( p_vout_thread_t p_vout, u16 *red, u16 *green,
u16 *blue, u16 *transp)
{
/* Create a display surface with a grayscale palette */
* This function send the currently rendered image to the display, wait until
* it is displayed and switch the two rendering buffer, preparing next frame.
*****************************************************************************/
-void vout_Display( vout_thread_t *p_vout )
+static void vout_Display( vout_thread_t *p_vout )
{
SDL_Rect disp;
if((p_vout->p_sys->p_display != NULL) && !p_vout->p_sys->b_reopen_display)
}
else
{
-
/*
* p_vout->p_rendered_pic->p_y/u/v contains the YUV buffers to
* render
SDL_YV12_OVERLAY,
p_vout->p_sys->p_display
);
- intf_Msg("vout: YUV acceleration %s",
- p_vout->p_sys->p_overlay->hw_overlay
+ intf_WarnMsg( 2, "vout: YUV acceleration %s",
+ p_vout->p_sys->p_overlay->hw_overlay
? "activated" : "unavailable !" );
}
/* init flags and cursor */
flags = SDL_ANYFORMAT | SDL_HWPALETTE;
- if( p_vout->p_sys->b_fullscreen )
+ if( p_vout->b_fullscreen )
+ {
flags |= SDL_FULLSCREEN;
+ }
else
+ {
flags |= SDL_RESIZABLE;
+ }
if( p_vout->b_need_render )
+ {
flags |= SDL_HWSURFACE | SDL_DOUBLEBUF;
+ }
else
+ {
flags |= SDL_SWSURFACE; /* save video memory */
+ }
- bpp = SDL_VideoModeOK(p_vout->p_sys->i_width,
- p_vout->p_sys->i_height,
- p_vout->i_screen_depth, flags);
+ bpp = SDL_VideoModeOK( p_vout->p_sys->i_width,
+ p_vout->p_sys->i_height,
+ p_vout->i_screen_depth, flags );
- if(bpp == 0)
+ if( bpp == 0 )
{
- intf_ErrMsg( "error: can't open DISPLAY default display" );
+ intf_ErrMsg( "vout error: no video mode available" );
return( 1 );
}
if( p_vout->p_sys->p_display == NULL )
{
- intf_ErrMsg( "error: can't open DISPLAY default display" );
+ intf_ErrMsg( "vout error: cannot set video mode" );
return( 1 );
}
- SDL_LockSurface(p_vout->p_sys->p_display);
-
- if( p_vout->p_sys->b_fullscreen )
- SDL_ShowCursor( 0 );
- else
- SDL_ShowCursor( 1 );
+ SDL_LockSurface( p_vout->p_sys->p_display );
- SDL_WM_SetCaption( VOUT_TITLE , VOUT_TITLE );
+ SDL_WM_SetCaption( VOUT_TITLE " (SDL output)",
+ VOUT_TITLE " (SDL output)" );
SDL_EventState(SDL_KEYUP , SDL_IGNORE); /* ignore keys up */
- SDL_EventState(SDL_MOUSEBUTTONUP, SDL_IGNORE);
if( p_vout->b_need_render )
{
- p_vout->p_sys->p_buffer[ 0 ] = p_vout->p_sys->p_display->pixels;
+ p_vout->p_sys->p_sdl_buf[ 0 ] = p_vout->p_sys->p_display->pixels;
SDL_Flip(p_vout->p_sys->p_display);
- p_vout->p_sys->p_buffer[ 1 ] = p_vout->p_sys->p_display->pixels;
+ p_vout->p_sys->p_sdl_buf[ 1 ] = p_vout->p_sys->p_display->pixels;
SDL_Flip(p_vout->p_sys->p_display);
/* Set clipping for text */
/* FIXME: palette in 8bpp ?? */
/* Set and initialize buffers */
- vout_SetBuffers( p_vout, p_vout->p_sys->p_buffer[ 0 ],
- p_vout->p_sys->p_buffer[ 1 ] );
+ p_vout->pf_setbuffers( p_vout, p_vout->p_sys->p_sdl_buf[ 0 ],
+ p_vout->p_sys->p_sdl_buf[ 1 ] );
}
else
{
- p_vout->p_sys->p_buffer[ 0 ] = p_vout->p_sys->p_display->pixels;
- p_vout->p_sys->p_buffer[ 1 ] = p_vout->p_sys->p_display->pixels;
+ 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;
/* 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;
- vout_SetBuffers( p_vout, p_vout->p_sys->p_buffer[ 0 ],
- p_vout->p_sys->p_buffer[ 1 ] );
+ p_vout->pf_setbuffers( p_vout, p_vout->p_sys->p_sdl_buf[ 0 ],
+ p_vout->p_sys->p_sdl_buf[ 1 ] );
}
p_vout->p_sys->b_reopen_display = 0;