/*****************************************************************************
* sdl.c: SDL video output display method
*****************************************************************************
- * Copyright (C) 1998-2001 VideoLAN
- * $Id: sdl.c,v 1.2 2002/09/19 21:56:40 massiot Exp $
+ * Copyright (C) 1998-2001 VideoLAN (Centrale Réseaux) and its contributors
+ * $Id$
*
* Authors: Samuel Hocevar <sam@zoy.org>
* Pierre Baillet <oct@zoy.org>
* 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
#include <vlc/vlc.h>
#include <vlc/intf.h>
#include <vlc/vout.h>
+#include <vlc/aout.h>
#include <sys/types.h>
#ifndef WIN32
#include SDL_INCLUDE_FILE
-#include "netutils.h"
-
#define SDL_MAX_DIRECTBUFFERS 10
#define SDL_DEFAULT_BPP 16
static int OpenDisplay ( vout_thread_t * );
static void CloseDisplay ( vout_thread_t * );
static int NewPicture ( vout_thread_t *, picture_t * );
-static void SetPalette ( vout_thread_t *, u16 *, u16 *, u16 * );
+static void SetPalette ( vout_thread_t *,
+ uint16_t *, uint16_t *, uint16_t * );
/*****************************************************************************
* Module descriptor
*****************************************************************************/
vlc_module_begin();
- set_description( _("Simple DirectMedia Layer video module") );
- set_capability( "video output", 40 );
+ set_shortname( "SDL" );
+ set_category( CAT_VIDEO );
+ set_subcategory( SUBCAT_VIDEO_VOUT );
+ set_description( _("Simple DirectMedia Layer video output") );
+ set_capability( "video output", 60 );
+ add_shortcut( "sdl" );
set_callbacks( Open, Close );
+ /* XXX: check for conflicts with the SDL audio output */
+ var_Create( p_module->p_libvlc, "sdl", VLC_VAR_MUTEX );
+#if defined( __i386__ ) || defined( __x86_64__ )
+ /* On i386, SDL is linked against svgalib */
+ linked_with_a_crap_library_which_uses_atexit();
+#endif
vlc_module_end();
/*****************************************************************************
* vout properties to choose the correct mode, and change them according to the
* mode actually used.
*****************************************************************************/
-static int Open ( vlc_object_t *p_this )
+static int Open ( vlc_object_t *p_this )
{
- vout_thread_t * p_vout = (vout_thread_t *)p_this;
+ vout_thread_t * p_vout = (vout_thread_t *)p_this;
+ vlc_value_t lockval;
#ifdef HAVE_SETENV
char *psz_method;
#endif
+ var_Get( p_this->p_libvlc, "sdl", &lockval );
+ vlc_mutex_lock( lockval.p_address );
+
if( SDL_WasInit( SDL_INIT_VIDEO ) != 0 )
{
- return( 1 );
+ vlc_mutex_unlock( lockval.p_address );
+ return VLC_EGENERIC;
}
/* Allocate structure */
if( p_vout->p_sys == NULL )
{
msg_Err( p_vout, "out of memory" );
- return( 1 );
+ vlc_mutex_unlock( lockval.p_address );
+ return VLC_ENOMEM;
}
p_vout->pf_init = Init;
{
msg_Err( p_vout, "cannot initialize SDL (%s)", SDL_GetError() );
free( p_vout->p_sys );
- return( 1 );
+ vlc_mutex_unlock( lockval.p_address );
+ return VLC_EGENERIC;
}
+ vlc_mutex_unlock( lockval.p_address );
+
p_vout->p_sys->b_cursor = 1;
p_vout->p_sys->b_cursor_autohidden = 0;
p_vout->p_sys->i_lastmoved = mdate();
msg_Err( p_vout, "cannot set up SDL (%s)", SDL_GetError() );
SDL_QuitSubSystem( SDL_INIT_VIDEO );
free( p_vout->p_sys );
- return( 1 );
+ return VLC_EGENERIC;
}
- return( 0 );
+ return VLC_SUCCESS;
}
/*****************************************************************************
I_OUTPUTPICTURES++;
}
- return( 0 );
+ return VLC_SUCCESS;
}
/*****************************************************************************
*****************************************************************************
* Terminate an output method created by vout_SDLCreate
*****************************************************************************/
-static void Close ( vlc_object_t *p_this )
+static void Close ( vlc_object_t *p_this )
{
- vout_thread_t * p_vout = (vout_thread_t *)p_this;
+ vout_thread_t * p_vout = (vout_thread_t *)p_this;
CloseDisplay( p_vout );
SDL_QuitSubSystem( SDL_INIT_VIDEO );
* Manage: handle Sys events
*****************************************************************************
* This function should be called regularly by video output thread. It returns
- * a non null value if an error occured.
+ * a non null value if an error occurred.
*****************************************************************************/
static int Manage( vout_thread_t *p_vout )
{
SDL_Event event; /* SDL event */
+ vlc_value_t val;
+ int i_width, i_height, i_x, i_y;
/* Process events */
while( SDL_PollEvent(&event) )
break;
case SDL_MOUSEMOTION:
+ vout_PlacePicture( p_vout, p_vout->p_sys->i_width,
+ p_vout->p_sys->i_height,
+ &i_x, &i_y, &i_width, &i_height );
+
+ val.i_int = ( event.motion.x - i_x )
+ * p_vout->render.i_width / i_width;
+ var_Set( p_vout, "mouse-x", val );
+ val.i_int = ( event.motion.y - i_y )
+ * p_vout->render.i_height / i_height;
+ var_Set( p_vout, "mouse-y", val );
+
+ val.b_bool = VLC_TRUE;
+ var_Set( p_vout, "mouse-moved", val );
+
if( p_vout->p_sys->b_cursor &&
(abs(event.motion.xrel) > 2 || abs(event.motion.yrel) > 2) )
{
case SDL_MOUSEBUTTONUP:
switch( event.button.button )
{
+ case SDL_BUTTON_LEFT:
+ val.b_bool = VLC_TRUE;
+ var_Set( p_vout, "mouse-clicked", val );
+ break;
+
case SDL_BUTTON_RIGHT:
{
intf_thread_t *p_intf;
break;
case 4:
- input_Seek( p_vout, 15, INPUT_SEEK_SECONDS | INPUT_SEEK_CUR );
break;
case 5:
- input_Seek( p_vout, -15, INPUT_SEEK_SECONDS | INPUT_SEEK_CUR );
break;
}
break;
p_vout->b_interface = ! p_vout->b_interface;
p_vout->i_changes |= VOUT_INTF_CHANGE;
break;
-
+
case SDLK_MENU:
{
intf_thread_t *p_intf;
break;
case SDLK_LEFT:
- input_Seek( p_vout, -5, INPUT_SEEK_SECONDS | INPUT_SEEK_CUR );
break;
case SDLK_RIGHT:
- input_Seek( p_vout, 5, INPUT_SEEK_SECONDS | INPUT_SEEK_CUR );
break;
case SDLK_UP:
- input_Seek( p_vout, 60, INPUT_SEEK_SECONDS | INPUT_SEEK_CUR );
break;
case SDLK_DOWN:
- input_Seek( p_vout, -60, INPUT_SEEK_SECONDS | INPUT_SEEK_CUR );
break;
- case SDLK_F1: network_ChannelJoin( p_vout, 1 ); break;
- case SDLK_F2: network_ChannelJoin( p_vout, 2 ); break;
- case SDLK_F3: network_ChannelJoin( p_vout, 3 ); break;
- case SDLK_F4: network_ChannelJoin( p_vout, 4 ); break;
- case SDLK_F5: network_ChannelJoin( p_vout, 5 ); break;
- case SDLK_F6: network_ChannelJoin( p_vout, 6 ); break;
- case SDLK_F7: network_ChannelJoin( p_vout, 7 ); break;
- case SDLK_F8: network_ChannelJoin( p_vout, 8 ); break;
- case SDLK_F9: network_ChannelJoin( p_vout, 9 ); break;
- case SDLK_F10: network_ChannelJoin( p_vout, 10 ); break;
- case SDLK_F11: network_ChannelJoin( p_vout, 11 ); break;
- case SDLK_F12: network_ChannelJoin( p_vout, 12 ); break;
-
case SDLK_b:
{
- aout_instance_t * p_aout;
audio_volume_t i_volume;
- p_aout = vlc_object_find( p_vout, VLC_OBJECT_AOUT,
- FIND_ANYWHERE );
- if( p_aout != NULL )
+ if ( !aout_VolumeDown( p_vout, 1, &i_volume ) )
{
- if ( !aout_VolumeDown( p_aout, 1, &i_volume ) )
- {
- msg_Dbg( p_vout, "audio volume is now %d", i_volume );
- }
- else
- {
- msg_Dbg( p_vout, "audio volume: operation not supported" );
- }
- vlc_object_release( (vlc_object_t *)p_aout );
+ msg_Dbg( p_vout, "audio volume is now %d", i_volume );
+ }
+ else
+ {
+ msg_Dbg( p_vout, "audio volume: operation not supported" );
}
}
break;
case SDLK_n:
{
- aout_instance_t * p_aout;
audio_volume_t i_volume;
- p_aout = vlc_object_find( p_vout, VLC_OBJECT_AOUT,
- FIND_ANYWHERE );
- if( p_aout != NULL )
+ if ( !aout_VolumeUp( p_vout, 1, &i_volume ) )
{
- if ( !aout_VolumeUp( p_aout, 1, &i_volume ) )
- {
- msg_Dbg( p_vout, "audio volume is now %d", i_volume );
- }
- else
- {
- msg_Dbg( p_vout, "audio volume: operation not supported" );
- }
- vlc_object_release( (vlc_object_t *)p_aout );
+ msg_Dbg( p_vout, "audio volume is now %d", i_volume );
+ }
+ else
+ {
+ msg_Dbg( p_vout, "audio volume: operation not supported" );
}
}
break;
{
msg_Dbg( p_vout, "video display resized (%dx%d)",
p_vout->p_sys->i_width, p_vout->p_sys->i_height );
-
+
CloseDisplay( p_vout );
OpenDisplay( p_vout );
SDL_ShowCursor( 0 );
}
- return( 0 );
+ return VLC_SUCCESS;
}
/*****************************************************************************
*****************************************************************************/
static int OpenDisplay( vout_thread_t *p_vout )
{
- Uint32 i_flags;
- int i_bpp;
+ uint32_t i_flags;
+ int i_bpp;
+
+ /* SDL fucked up fourcc definitions on bigendian machines */
+ uint32_t i_sdl_chroma;
/* Set main window's size */
p_vout->p_sys->i_width = p_vout->b_fullscreen ? p_vout->output.i_width :
if( i_bpp == 0 )
{
msg_Err( p_vout, "no video mode available" );
- return( 1 );
+ return VLC_EGENERIC;
}
p_vout->p_sys->p_display = SDL_SetVideoMode( p_vout->p_sys->i_width,
if( p_vout->p_sys->p_display == NULL )
{
msg_Err( p_vout, "cannot set video mode" );
- return( 1 );
+ return VLC_EGENERIC;
}
SDL_LockSurface( p_vout->p_sys->p_display );
{
case VLC_FOURCC('Y','U','Y','2'):
case VLC_FOURCC('Y','U','N','V'):
- p_vout->output.i_chroma = SDL_YUY2_OVERLAY;
+ p_vout->output.i_chroma = VLC_FOURCC('Y','U','Y','2');
+ i_sdl_chroma = SDL_YUY2_OVERLAY;
break;
case VLC_FOURCC('U','Y','V','Y'):
case VLC_FOURCC('U','Y','N','V'):
case VLC_FOURCC('Y','4','2','2'):
- p_vout->output.i_chroma = SDL_UYVY_OVERLAY;
+ p_vout->output.i_chroma = VLC_FOURCC('U','Y','V','Y');
+ i_sdl_chroma = SDL_UYVY_OVERLAY;
break;
case VLC_FOURCC('Y','V','Y','U'):
- p_vout->output.i_chroma = SDL_YVYU_OVERLAY;
+ p_vout->output.i_chroma = VLC_FOURCC('Y','V','Y','U');
+ i_sdl_chroma = SDL_YVYU_OVERLAY;
break;
case VLC_FOURCC('Y','V','1','2'):
case VLC_FOURCC('I','4','2','0'):
case VLC_FOURCC('I','Y','U','V'):
default:
- p_vout->output.i_chroma = SDL_YV12_OVERLAY;
+ p_vout->output.i_chroma = VLC_FOURCC('Y','V','1','2');
+ i_sdl_chroma = SDL_YV12_OVERLAY;
break;
}
p_vout->p_sys->p_overlay =
- SDL_CreateYUVOverlay( 32, 32, p_vout->output.i_chroma,
- p_vout->p_sys->p_display );
+ SDL_CreateYUVOverlay( 32, 32, i_sdl_chroma, p_vout->p_sys->p_display );
/* FIXME: if the first overlay we find is software, don't stop,
* because we may find a hardware one later ... */
/* If this best choice failed, fall back to other chromas */
if( p_vout->p_sys->p_overlay == NULL )
{
- p_vout->output.i_chroma = SDL_IYUV_OVERLAY;
+ p_vout->output.i_chroma = VLC_FOURCC('I','Y','U','V');
p_vout->p_sys->p_overlay =
- SDL_CreateYUVOverlay( 32, 32, p_vout->output.i_chroma,
+ SDL_CreateYUVOverlay( 32, 32, SDL_IYUV_OVERLAY,
p_vout->p_sys->p_display );
}
if( p_vout->p_sys->p_overlay == NULL )
{
- p_vout->output.i_chroma = SDL_YV12_OVERLAY;
+ p_vout->output.i_chroma = VLC_FOURCC('Y','V','1','2');
p_vout->p_sys->p_overlay =
- SDL_CreateYUVOverlay( 32, 32, p_vout->output.i_chroma,
+ SDL_CreateYUVOverlay( 32, 32, SDL_YV12_OVERLAY,
p_vout->p_sys->p_display );
}
if( p_vout->p_sys->p_overlay == NULL )
{
- p_vout->output.i_chroma = SDL_YUY2_OVERLAY;
+ p_vout->output.i_chroma = VLC_FOURCC('Y','U','Y','2');
p_vout->p_sys->p_overlay =
- SDL_CreateYUVOverlay( 32, 32, p_vout->output.i_chroma,
+ SDL_CreateYUVOverlay( 32, 32, SDL_YUY2_OVERLAY,
p_vout->p_sys->p_display );
}
p_vout->p_sys->p_display->format->BitsPerPixel );
SDL_UnlockSurface( p_vout->p_sys->p_display );
SDL_FreeSurface( p_vout->p_sys->p_display );
- return( -1 );
+ return VLC_EGENERIC;
}
p_vout->output.i_rmask = p_vout->p_sys->p_display->format->Rmask;
SDL_EventState( SDL_KEYUP, SDL_IGNORE ); /* ignore keys up */
- return( 0 );
+ return VLC_SUCCESS;
}
/*****************************************************************************
if( p_vout->p_sys->i_surfaces )
{
/* We already allocated this surface, return */
- return -1;
+ return VLC_EGENERIC;
}
p_pic->p_sys = malloc( sizeof( picture_sys_t ) );
if( p_pic->p_sys == NULL )
{
- return -1;
+ return VLC_ENOMEM;
}
switch( p_vout->p_sys->p_display->format->BitsPerPixel )
p_pic->p->i_pixel_pitch = 4;
break;
default:
- return( -1 );
+ return VLC_EGENERIC;
}
p_pic->p->p_pixels = p_vout->p_sys->p_display->pixels;
p_pic->p->i_lines = p_vout->p_sys->p_display->h;
+ p_pic->p->i_visible_lines = p_vout->p_sys->p_display->h;
p_pic->p->i_pitch = p_vout->p_sys->p_display->pitch;
p_pic->p->i_visible_pitch =
p_pic->p->i_pixel_pitch * p_vout->p_sys->p_display->w;
if( p_pic->p_sys == NULL )
{
- return -1;
+ return VLC_ENOMEM;
}
p_pic->p_sys->p_overlay =
if( p_pic->p_sys->p_overlay == NULL )
{
free( p_pic->p_sys );
- return -1;
+ return VLC_EGENERIC;
}
SDL_LockYUVOverlay( p_pic->p_sys->p_overlay );
p_pic->Y_PIXELS = p_pic->p_sys->p_overlay->pixels[0];
p_pic->p[Y_PLANE].i_lines = p_pic->p_sys->p_overlay->h;
+ p_pic->p[Y_PLANE].i_visible_lines = p_pic->p_sys->p_overlay->h;
p_pic->p[Y_PLANE].i_pitch = p_pic->p_sys->p_overlay->pitches[0];
switch( p_vout->output.i_chroma )
{
case SDL_YV12_OVERLAY:
p_pic->p[Y_PLANE].i_pixel_pitch = 1;
- p_pic->p[Y_PLANE].i_visible_pitch = p_pic->p[Y_PLANE].i_pitch;
+ p_pic->p[Y_PLANE].i_visible_pitch = p_pic->p_sys->p_overlay->w;
p_pic->U_PIXELS = p_pic->p_sys->p_overlay->pixels[2];
p_pic->p[U_PLANE].i_lines = p_pic->p_sys->p_overlay->h / 2;
+ p_pic->p[U_PLANE].i_visible_lines = p_pic->p_sys->p_overlay->h / 2;
p_pic->p[U_PLANE].i_pitch = p_pic->p_sys->p_overlay->pitches[2];
p_pic->p[U_PLANE].i_pixel_pitch = 1;
- p_pic->p[U_PLANE].i_visible_pitch = p_pic->p[U_PLANE].i_pitch;
+ p_pic->p[U_PLANE].i_visible_pitch = p_pic->p_sys->p_overlay->w / 2;
p_pic->V_PIXELS = p_pic->p_sys->p_overlay->pixels[1];
p_pic->p[V_PLANE].i_lines = p_pic->p_sys->p_overlay->h / 2;
+ p_pic->p[V_PLANE].i_visible_lines = p_pic->p_sys->p_overlay->h / 2;
p_pic->p[V_PLANE].i_pitch = p_pic->p_sys->p_overlay->pitches[1];
p_pic->p[V_PLANE].i_pixel_pitch = 1;
- p_pic->p[V_PLANE].i_visible_pitch = p_pic->p[V_PLANE].i_pitch;
+ p_pic->p[V_PLANE].i_visible_pitch = p_pic->p_sys->p_overlay->w / 2;
p_pic->i_planes = 3;
break;
case SDL_IYUV_OVERLAY:
p_pic->p[Y_PLANE].i_pixel_pitch = 1;
- p_pic->p[Y_PLANE].i_visible_pitch = p_pic->p[Y_PLANE].i_pitch;
+ p_pic->p[Y_PLANE].i_visible_pitch = p_pic->p_sys->p_overlay->w;
p_pic->U_PIXELS = p_pic->p_sys->p_overlay->pixels[1];
p_pic->p[U_PLANE].i_lines = p_pic->p_sys->p_overlay->h / 2;
+ p_pic->p[U_PLANE].i_visible_lines = p_pic->p_sys->p_overlay->h / 2;
p_pic->p[U_PLANE].i_pitch = p_pic->p_sys->p_overlay->pitches[1];
p_pic->p[U_PLANE].i_pixel_pitch = 1;
- p_pic->p[U_PLANE].i_visible_pitch = p_pic->p[U_PLANE].i_pitch;
+ p_pic->p[U_PLANE].i_visible_pitch = p_pic->p_sys->p_overlay->w / 2;
p_pic->V_PIXELS = p_pic->p_sys->p_overlay->pixels[2];
p_pic->p[V_PLANE].i_lines = p_pic->p_sys->p_overlay->h / 2;
+ p_pic->p[V_PLANE].i_visible_lines = p_pic->p_sys->p_overlay->h / 2;
p_pic->p[V_PLANE].i_pitch = p_pic->p_sys->p_overlay->pitches[2];
p_pic->p[V_PLANE].i_pixel_pitch = 1;
- p_pic->p[V_PLANE].i_visible_pitch = p_pic->p[V_PLANE].i_pitch;
+ p_pic->p[V_PLANE].i_visible_pitch = p_pic->p_sys->p_overlay->w / 2;
p_pic->i_planes = 3;
break;
default:
p_pic->p[Y_PLANE].i_pixel_pitch = 2;
- p_pic->p[Y_PLANE].i_visible_pitch = p_pic->p[Y_PLANE].i_pitch;
+ p_pic->p[U_PLANE].i_visible_pitch = p_pic->p_sys->p_overlay->w * 2;
p_pic->i_planes = 1;
break;
}
}
- return 0;
+ return VLC_SUCCESS;
}
/*****************************************************************************
* SetPalette: sets an 8 bpp palette
*****************************************************************************/
-static void SetPalette( vout_thread_t *p_vout, u16 *red, u16 *green, u16 *blue )
+static void SetPalette( vout_thread_t *p_vout,
+ uint16_t *red, uint16_t *green, uint16_t *blue )
{
SDL_Color colors[256];
int i;
-
+
/* Fill colors with color information */
for( i = 0; i < 256; i++ )
{