Commit c7b1c474 authored by Sam Hocevar's avatar Sam Hocevar

  * ./include/modules_inner.h: replaced _X with __VLC_SYMBOL because _X was
    already a system macro under MacOS X.
  * ./plugins/dummy/dummy.c: fixed vlc:loop, vlc:quit, etc. entries.
  * ./plugins/glide/glide.c: activated double buffering.
  * ./plugins/mga/xmga.c: started writing an xmga plugin; doesn't work yet.
  * ./src/input/input.c: fixed the input memory leak, and the insane thread
    spawning we got with vlc:loop.
  * ./src/misc/intf_eject.c: disc ejection routine courtesy of Julien Blache,
    currently Linux-only.
parent 1ae5bed4
......@@ -38,6 +38,10 @@ E: jobi@via.ecp.fr
C: jobi
D: VCD input
N: Julien Blache
E: jb@technologeek.org
D: Disc ejection code
N: Emmanuel Blindauer
E: manu@agat.net
D: aRts audio output
......
List of known vlc bugs
$Id: BUGS,v 1.3 2002/01/05 16:09:49 sam Exp $
$Id: BUGS,v 1.4 2002/01/09 02:01:14 sam Exp $
Please try to keep this file up to date. Also, grep for FIXME in the
source files for more and more bugs to fix.
......@@ -17,10 +17,7 @@ Core:
Input:
* There is a memory leak in the input because the input thread is
never joined for termination.
* vlc:foo targets don't work anymore.
-
Audio output:
......@@ -37,8 +34,6 @@ Video output:
* The DirectX video output plugin is broken because of vout4.
* The GGI video output plugin is broken because of vout4.
* The BeOS video output plugin is broken because of vout4.
* The QNX video output plugin is broken because of vout4.
......@@ -69,3 +64,8 @@ Gtk interface:
* Saving preferences does not work at all.
Misc:
* The Jin-Roh DVD seems to segfault.
......@@ -100,6 +100,7 @@ PLUGINS_TARGETS := ac3_adec/ac3_adec \
memcpy/memcpymmxext \
memcpy/memcpy3dn \
mga/mga \
mga/xmga \
motion/motion \
motion/motionmmx \
motion/motionmmxext \
......@@ -122,7 +123,7 @@ PLUGINS_TARGETS := ac3_adec/ac3_adec \
#
# C Objects
#
INTERFACE := main interface intf_msg intf_playlist
INTERFACE := main interface intf_msg intf_playlist intf_eject
INPUT := input input_ext-dec input_ext-intf input_dec input_programs input_clock mpeg_system
VIDEO_OUTPUT := video_output video_text vout_pictures vout_subpictures
AUDIO_OUTPUT := audio_output aout_ext-dec aout_u8 aout_s8 aout_u16 aout_s16 aout_spdif
......
......@@ -6439,7 +6439,7 @@ if test "${enable_mga+set}" = set; then
enableval="$enable_mga"
if test x$enable_mga = xyes
then
PLUGINS="${PLUGINS} mga"
PLUGINS="${PLUGINS} mga xmga"
fi
fi
......
......@@ -948,7 +948,7 @@ AC_ARG_ENABLE(mga,
[ --enable-mga Linux kernel Matrox support (default disabled)],
[ if test x$enable_mga = xyes
then
PLUGINS="${PLUGINS} mga"
PLUGINS="${PLUGINS} mga xmga"
fi ])
dnl
......
......@@ -3,7 +3,7 @@
* Collection of useful common types and macros definitions
*****************************************************************************
* Copyright (C) 1998, 1999, 2000 VideoLAN
* $Id: common.h,v 1.66 2002/01/07 02:12:29 sam Exp $
* $Id: common.h,v 1.67 2002/01/09 02:01:14 sam Exp $
*
* Authors: Samuel Hocevar <sam@via.ecp.fr>
* Vincent Seguin <seguin@via.ecp.fr>
......@@ -468,6 +468,7 @@ typedef struct module_symbols_s
void ( * intf_PlaylistDestroy ) ( struct playlist_s * );
void ( * intf_PlaylistJumpto ) ( struct playlist_s *, int );
void ( * intf_UrlDecode ) ( char * );
int ( * intf_Eject ) ( const char * );
void ( * msleep ) ( mtime_t );
mtime_t ( * mdate ) ( void );
......@@ -576,6 +577,7 @@ typedef struct module_symbols_s
struct module_s * ( * module_Need ) ( int, char *, struct probedata_s * );
void ( * module_Unneed ) ( struct module_s * );
} module_symbols_t;
#ifdef PLUGIN
......
......@@ -4,7 +4,7 @@
* control the pace of reading.
*****************************************************************************
* Copyright (C) 1999, 2000 VideoLAN
* $Id: input_ext-intf.h,v 1.56 2002/01/07 02:12:29 sam Exp $
* $Id: input_ext-intf.h,v 1.57 2002/01/09 02:01:14 sam Exp $
*
* Authors: Christophe Massiot <massiot@via.ecp.fr>
*
......@@ -259,7 +259,7 @@ typedef struct input_thread_s
boolean_t b_error;
boolean_t b_eof;
vlc_thread_t thread_id; /* id for thread functions */
int * pi_status; /* temporary status flag */
int i_status; /* status flag */
/* Input module */
struct module_s * p_input_module;
......@@ -343,7 +343,8 @@ void input_EndBank ( void );
struct input_thread_s * input_CreateThread ( struct playlist_item_s *,
int *pi_status );
void input_DestroyThread ( struct input_thread_s *, int *pi_status );
void input_StopThread ( struct input_thread_s *, int *pi_status );
void input_DestroyThread ( struct input_thread_s * );
void input_SetStatus ( struct input_thread_s *, int );
void input_Seek ( struct input_thread_s *, off_t );
......
/*****************************************************************************
* intf_eject.h: CD/DVD-ROM ejection handling functions
*****************************************************************************
* Copyright (C) 2001, 2002 VideoLAN
* $Id: intf_eject.h,v 1.1 2002/01/09 02:01:14 sam Exp $
*
* Author: Julien Blache <jb@technologeek.org>
*
* 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.
*****************************************************************************/
#ifndef PLUGIN
int intf_Eject( const char * );
#else
# define intf_Eject p_symbols->intf_Eject
#endif
......@@ -2,7 +2,7 @@
* modules_inner.h : Macros used from within a module.
*****************************************************************************
* Copyright (C) 2001 VideoLAN
* $Id: modules_inner.h,v 1.10 2001/12/30 07:09:54 sam Exp $
* $Id: modules_inner.h,v 1.11 2002/01/09 02:01:14 sam Exp $
*
* Authors: Samuel Hocevar <sam@zoy.org>
*
......@@ -57,12 +57,12 @@
* of InitModule. Same for Activate- and DeactivateModule. */
#ifdef BUILTIN
# define _M( function ) CONCATENATE( function, MODULE_NAME )
# define _X( function ) CONCATENATE( function, MODULE_NAME )
# define __VLC_SYMBOL( symbol ) CONCATENATE( symbol, MODULE_NAME )
# define DECLARE_SYMBOLS ;
# define STORE_SYMBOLS ;
#else
# define _M( function ) function
# define _X( function ) CONCATENATE( function, MODULE_SYMBOL )
# define __VLC_SYMBOL( symbol ) CONCATENATE( symbol, MODULE_SYMBOL )
# define DECLARE_SYMBOLS module_symbols_t* p_symbols;
# define STORE_SYMBOLS p_symbols = p_module->p_symbols;
#endif
......@@ -75,7 +75,7 @@
* instance the module name, its shortcuts, its capabilities...
*/
#define MODULE_INIT_START \
int _X( InitModule ) ( module_t *p_module ) \
int __VLC_SYMBOL( InitModule ) ( module_t *p_module ) \
{ \
int i_shortcut = 0; \
p_module->psz_name = MODULE_STRING; \
......@@ -115,7 +115,7 @@
#define MODULE_ACTIVATE_START \
DECLARE_SYMBOLS; \
\
int _X( ActivateModule ) ( module_t *p_module ) \
int __VLC_SYMBOL( ActivateModule ) ( module_t *p_module ) \
{ \
p_module->p_functions = \
( module_functions_t * )malloc( sizeof( module_functions_t ) ); \
......@@ -136,7 +136,7 @@
* here.
*/
#define MODULE_DEACTIVATE_START \
int _X( DeactivateModule )( module_t *p_module ) \
int __VLC_SYMBOL( DeactivateModule )( module_t *p_module ) \
{ \
free( p_module->p_functions );
......
......@@ -2,7 +2,7 @@
* dummy.c : dummy plugin for vlc
*****************************************************************************
* Copyright (C) 2000, 2001 VideoLAN
* $Id: dummy.c,v 1.13 2001/12/30 07:09:55 sam Exp $
* $Id: dummy.c,v 1.14 2002/01/09 02:01:14 sam Exp $
*
* Authors: Samuel Hocevar <sam@zoy.org>
*
......@@ -50,10 +50,11 @@ MODULE_INIT_START
SET_DESCRIPTION( "dummy functions module" )
/* Capability score set to 0 because we don't want to be spawned
* unless explicitly requested to */
ADD_CAPABILITY( INPUT, 0 )
ADD_CAPABILITY( AOUT, 0 )
ADD_CAPABILITY( VOUT, 0 )
ADD_CAPABILITY( INTF, 0 )
/* This one is ok. */
ADD_CAPABILITY( INPUT, 100 )
ADD_SHORTCUT( "dummy" )
MODULE_INIT_STOP
......
......@@ -2,7 +2,7 @@
* input_dummy.c: dummy input plugin, to manage "vlc:***" special options
*****************************************************************************
* Copyright (C) 2001 VideoLAN
* $Id: input_dummy.c,v 1.12 2002/01/04 14:01:34 sam Exp $
* $Id: input_dummy.c,v 1.13 2002/01/09 02:01:14 sam Exp $
*
* Authors: Samuel Hocevar <sam@zoy.org>
*
......@@ -89,10 +89,10 @@ static int DummyProbe( probedata_t *p_data )
if( ( strlen(psz_name) > 4 ) && !strncasecmp( psz_name, "vlc:", 4 ) )
{
/* If the user specified "vlc:" then it's probably a file */
return( 100 );
return( 1 );
}
return( 1 );
return( 0 );
}
/*****************************************************************************
......@@ -153,7 +153,6 @@ static void DummyOpen( input_thread_t * p_input )
}
intf_ErrMsg( "input error: unknown command `%s'", psz_name );
}
/*****************************************************************************
......
......@@ -2,7 +2,7 @@
* wall.c : Wall video plugin for vlc
*****************************************************************************
* Copyright (C) 2000, 2001 VideoLAN
* $Id: wall.c,v 1.9 2002/01/07 17:02:07 sam Exp $
* $Id: wall.c,v 1.10 2002/01/09 02:01:14 sam Exp $
*
* Authors: Samuel Hocevar <sam@zoy.org>
*
......@@ -134,8 +134,8 @@ static int vout_Create( vout_thread_t *p_vout )
return( 1 );
}
p_vout->p_sys->i_col = 3;
p_vout->p_sys->i_row = 3;
p_vout->p_sys->i_col = 6;
p_vout->p_sys->i_row = 6;
p_vout->p_sys->pp_vout = malloc( p_vout->p_sys->i_row *
p_vout->p_sys->i_col *
......
......@@ -2,7 +2,7 @@
* glide.c : 3dfx Glide plugin for vlc
*****************************************************************************
* Copyright (C) 2000, 2001 VideoLAN
* $Id: glide.c,v 1.10 2002/01/07 02:12:29 sam Exp $
* $Id: glide.c,v 1.11 2002/01/09 02:01:14 sam Exp $
*
* Authors: Samuel Hocevar <sam@zoy.org>
*
......@@ -60,7 +60,6 @@ static int vout_Manage ( vout_thread_t * );
static void vout_Render ( vout_thread_t *, picture_t * );
static void vout_Display ( vout_thread_t *, picture_t * );
static int NewPicture ( vout_thread_t *, picture_t * );
static int OpenDisplay ( vout_thread_t * );
static void CloseDisplay ( vout_thread_t * );
......@@ -94,9 +93,8 @@ typedef struct vout_sys_s
{
GrLfbInfo_t p_buffer_info; /* back buffer info */
/* Dummy video memory */
byte_t * p_video; /* base adress */
size_t i_page_size; /* page size */
u8* pp_buffer[2];
int i_index;
} vout_sys_t;
......@@ -167,9 +165,6 @@ int vout_Init( vout_thread_t *p_vout )
I_OUTPUTPICTURES = 0;
/* Try to initialize up to 1 direct buffers */
while( I_OUTPUTPICTURES < 1 )
{
p_pic = NULL;
/* Find an empty picture slot */
......@@ -182,21 +177,37 @@ int vout_Init( vout_thread_t *p_vout )
}
}
/* Allocate the picture */
if( p_pic == NULL || NewPicture( p_vout, p_pic ) )
if( p_pic == NULL )
{
break;
return -1;
}
/* We know the chroma, allocate a buffer which will be used
* directly by the decoder */
p_pic->i_planes = 1;
p_pic->p->p_pixels = p_vout->p_sys->pp_buffer[p_vout->p_sys->i_index];
p_pic->p->i_pixel_bytes = GLIDE_BYTES_PER_PIXEL;
p_pic->p->i_lines = GLIDE_HEIGHT;
p_pic->p->b_margin = 1;
p_pic->p->b_hidden = 1;
p_pic->p->i_visible_bytes = GLIDE_WIDTH * GLIDE_BYTES_PER_PIXEL;
p_pic->p->i_pitch = p_vout->p_sys->p_buffer_info.strideInBytes;
/*1024 * GLIDE_BYTES_PER_PIXEL*/
p_pic->p->i_red_mask = 0xf800;
p_pic->p->i_green_mask = 0x07e0;
p_pic->p->i_blue_mask = 0x001f;
p_pic->i_status = DESTROYED_PICTURE;
p_pic->i_type = DIRECT_PICTURE;
PP_OUTPUTPICTURE[ I_OUTPUTPICTURES ] = p_pic;
PP_OUTPUTPICTURE[ 0 ] = p_pic;
I_OUTPUTPICTURES++;
}
I_OUTPUTPICTURES = 1;
return( 0 );
return 0;
}
/*****************************************************************************
......@@ -286,18 +297,6 @@ static int OpenDisplay( vout_thread_t *p_vout )
GrScreenResolution_t resolution = GR_RESOLUTION_800x600;
GrLfbInfo_t p_front_buffer_info; /* front buffer info */
p_vout->p_sys->i_page_size = GLIDE_WIDTH * GLIDE_HEIGHT
* GLIDE_BYTES_PER_PIXEL;
/* Map two framebuffers a the very beginning of the fb */
p_vout->p_sys->p_video = malloc( p_vout->p_sys->i_page_size * 2 );
if( (int)p_vout->p_sys->p_video == -1 )
{
intf_ErrMsg( "vout error: can't map video memory (%s)",
strerror(errno) );
return( 1 );
}
grGlideGetVersion( version );
grGlideInit();
......@@ -308,8 +307,8 @@ static int OpenDisplay( vout_thread_t *p_vout )
}
grSstSelect( 0 );
if( !grSstWinOpen(0, resolution, GR_REFRESH_60Hz,
GR_COLORFORMAT_ABGR, GR_ORIGIN_UPPER_LEFT, 2, 1) )
if( !grSstWinOpen( 0, resolution, GR_REFRESH_60Hz,
GR_COLORFORMAT_ABGR, GR_ORIGIN_UPPER_LEFT, 2, 1 ) )
{
intf_ErrMsg( "vout error: can't open 3dfx screen" );
return( 1 );
......@@ -347,10 +346,14 @@ static int OpenDisplay( vout_thread_t *p_vout )
grGlideShutdown();
return( 1 );
}
grLfbUnlock(GR_LFB_WRITE_ONLY, GR_BUFFER_BACKBUFFER );
grLfbUnlock( GR_LFB_WRITE_ONLY, GR_BUFFER_BACKBUFFER );
grBufferClear( 0, 0, 0 );
p_vout->p_sys->pp_buffer[0] = p_vout->p_sys->p_buffer_info.lfbPtr;
p_vout->p_sys->pp_buffer[1] = p_front_buffer_info.lfbPtr;
p_vout->p_sys->i_index = 0;
return( 0 );
}
......@@ -367,34 +370,5 @@ static void CloseDisplay( vout_thread_t *p_vout )
/* shutdown Glide */
grGlideShutdown();
free( p_vout->p_sys->p_video );
}
/*****************************************************************************
* NewPicture: allocate a picture
*****************************************************************************
* Returns 0 on success, -1 otherwise
*****************************************************************************/
static int NewPicture( vout_thread_t *p_vout, picture_t *p_pic )
{
/* We know the chroma, allocate a buffer which will be used
* directly by the decoder */
p_pic->p->p_pixels = p_vout->p_sys->p_video;
p_pic->p->i_pixel_bytes = GLIDE_BYTES_PER_PIXEL;
p_pic->p->i_lines = GLIDE_HEIGHT;
p_pic->p->b_margin = 1;
p_pic->p->b_hidden = 1;
p_pic->p->i_visible_bytes = GLIDE_WIDTH * GLIDE_BYTES_PER_PIXEL;
p_pic->p->i_pitch = p_vout->p_sys->p_buffer_info.strideInBytes;
/*1024 * GLIDE_BYTES_PER_PIXEL*/
p_pic->p->i_red_mask = 0xf800;
p_pic->p->i_green_mask = 0x07e0;
p_pic->p->i_blue_mask = 0x001f;
p_pic->i_planes = 1;
return 0;
}
......@@ -2,7 +2,7 @@
* gnome.c : Gnome plugin for vlc
*****************************************************************************
* Copyright (C) 2000 VideoLAN
* $Id: gnome.c,v 1.6 2002/01/07 02:12:29 sam Exp $
* $Id: gnome.c,v 1.7 2002/01/09 02:01:14 sam Exp $
*
* Authors: Samuel Hocevar <sam@zoy.org>
*
......@@ -329,6 +329,8 @@ static gint GnomeManage( gpointer p_data )
{
vlc_mutex_lock( &p_input_bank->pp_input[0]->stream.stream_lock );
if( !p_input_bank->pp_input[0]->b_die )
{
/* New input or stream map change */
if( p_input_bank->pp_input[0]->stream.b_changed )
{
......@@ -377,6 +379,7 @@ static gint GnomeManage( gpointer p_data )
p_intf->p_sys->b_chapter_update = 1;
GtkSetupMenus( p_intf );
}
}
vlc_mutex_unlock( &p_input_bank->pp_input[0]->stream.stream_lock );
}
......
......@@ -93,7 +93,6 @@
<signal>
<name>activate</name>
<handler>GnomeMenubarFileOpenActivate</handler>
<data>&quot;intf_window&quot;</data>
<last_modification_time>Sat, 19 May 2001 16:27:02 GMT</last_modification_time>
</signal>
<label>_Open File...</label>
......@@ -108,7 +107,6 @@
<signal>
<name>activate</name>
<handler>GnomeMenubarDiscOpenActivate</handler>
<data>&quot;intf_window&quot;</data>
<last_modification_time>Sat, 19 May 2001 16:27:10 GMT</last_modification_time>
</signal>
<label>Open _Disc...</label>
......@@ -122,9 +120,8 @@
<tooltip>Select a Network Stream</tooltip>
<signal>
<name>activate</name>
<handler>GnomeMenbarNetworkOpenActivate</handler>
<data>&quot;intf_window&quot;</data>
<last_modification_time>Sat, 19 May 2001 16:27:39 GMT</last_modification_time>
<handler>GnomeMenubarNetworkOpenActivate</handler>
<last_modification_time>Fri, 21 Dec 2001 13:11:28 GMT</last_modification_time>
</signal>
<label>_Network Stream...</label>
<right_justify>False</right_justify>
......@@ -137,13 +134,32 @@
<right_justify>False</right_justify>
</widget>
<widget>
<class>GtkPixmapMenuItem</class>
<name>menubar_eject</name>
<tooltip>Eject disc</tooltip>
<signal>
<name>activate</name>
<handler>GnomeMenubarDiscEjectActivate</handler>
<last_modification_time>Fri, 21 Dec 2001 13:11:28 GMT</last_modification_time>
</signal>
<label>_Eject Disc</label>
<right_justify>False</right_justify>
<stock_icon>GNOME_STOCK_MENU_TOP</stock_icon>
</widget>
<widget>
<class>GtkMenuItem</class>
<name>separator15</name>
<right_justify>False</right_justify>
</widget>
<widget>
<class>GtkPixmapMenuItem</class>
<name>menubar_exit</name>
<signal>
<name>activate</name>
<handler>GnomeMenubarExitActivate</handler>
<data>&quot;intf_window&quot;</data>
<last_modification_time>Sat, 19 May 2001 16:27:52 GMT</last_modification_time>
</signal>
<stock_item>GNOMEUIINFO_MENU_EXIT_ITEM</stock_item>
......@@ -166,7 +182,6 @@
<signal>
<name>activate</name>
<handler>GnomeMenubarWindowToggleActivate</handler>
<data>&quot;intf_window&quot;</data>
<last_modification_time>Sat, 19 May 2001 16:28:06 GMT</last_modification_time>
</signal>
<label>_Hide interface</label>
......@@ -179,7 +194,6 @@
<signal>
<name>activate</name>
<handler>GnomeMenubarFullscreenActivate</handler>
<data>&quot;intf_window&quot;</data>
<last_modification_time>Sat, 19 May 2001 16:28:15 GMT</last_modification_time>
</signal>
<label>_Fullscreen</label>
......@@ -232,7 +246,6 @@
<signal>
<name>activate</name>
<handler>GnomeMenubarPlaylistActivate</handler>
<data>&quot;intf_window&quot;</data>
<last_modification_time>Sat, 19 May 2001 16:28:41 GMT</last_modification_time>
</signal>
<label>_Playlist...</label>
......@@ -248,7 +261,6 @@
<signal>
<name>activate</name>
<handler>GnomeMenubarModulesActivate</handler>
<data>&quot;intf_window&quot;</data>
<last_modification_time>Sat, 19 May 2001 16:28:53 GMT</last_modification_time>
</signal>
<label>_Modules...</label>
......@@ -297,7 +309,6 @@
<signal>
<name>activate</name>
<handler>GnomeMenubarPreferencesActivate</handler>
<data>&quot;intf_window&quot;</data>
<last_modification_time>Sat, 19 May 2001 16:29:03 GMT</last_modification_time>
</signal>
<stock_item>GNOMEUIINFO_MENU_PREFERENCES_ITEM</stock_item>
......@@ -320,7 +331,6 @@
<signal>
<name>activate</name>
<handler>GnomeMenubarAboutActivate</handler>
<data>&quot;intf_window&quot;</data>
<last_modification_time>Sat, 19 May 2001 16:29:19 GMT</last_modification_time>
</signal>
<stock_item>GNOMEUIINFO_MENU_ABOUT_ITEM</stock_item>
......@@ -434,6 +444,21 @@
<stock_pixmap>GNOME_STOCK_PIXMAP_STOP</stock_pixmap>
</widget>
<widget>
<class>GtkButton</class>
<child_name>Toolbar:button</child_name>
<name>toolbar_eject</name>
<tooltip>Eject disc</tooltip>
<signal>
<name>button_press_event</name>
<handler>GtkDiscEject</handler>
<data>&quot;intf_window&quot;</data>
<last_modification_time>Fri, 21 Dec 2001 15:24:18 GMT</last_modification_time>
</signal>
<label>Eject</label>
<stock_pixmap>GNOME_STOCK_PIXMAP_TOP</stock_pixmap>
</widget>
<widget>
<class>GtkButton</class>
<child_name>Toolbar:button</child_name>
......
......@@ -30,12 +30,18 @@ GnomeMenubarDiscOpenActivate (GtkMenuItem *menuitem,
void
GnomeMenbarNetworkOpenActivate (GtkMenuItem *menuitem,
GnomeMenubarNetworkOpenActivate (GtkMenuItem *menuitem,
gpointer user_data)
{
GtkNetworkOpenShow( GTK_WIDGET( menuitem ), NULL, "intf_window" );
}
void
GnomeMenubarDiscEjectActivate (GtkMenuItem *menuitem,
gpointer user_data)
{
GtkDiscEject( GTK_WIDGET( menuitem ), NULL, "intf_window" );
}
void
GnomeMenubarExitActivate (GtkMenuItem *menuitem,
......@@ -259,6 +265,3 @@ GnomePopupJumpActivate (GtkMenuItem *menuitem,
{
GtkJumpShow( GTK_WIDGET( menuitem ), NULL, "intf_popup" );
}
......@@ -11,7 +11,11 @@ GnomeMenubarDiscOpenActivate (GtkMenuItem *menuitem,
gpointer user_data);
void
GnomeMenbarNetworkOpenActivate (GtkMenuItem *menuitem,
GnomeMenubarNetworkOpenActivate (GtkMenuItem *menuitem,
gpointer user_data);
void
GnomeMenubarDiscEjectActivate (GtkMenuItem *menuitem,
gpointer user_data);
void
......@@ -141,3 +145,4 @@ GtkNetworkOpenBroadcast (GtkToggleButton *togglebutton,
void
GtkNetworkOpenChannel (GtkToggleButton *togglebutton,
gpointer user_data);
......@@ -32,11 +32,19 @@ static GnomeUIInfo menubar_file_menu_uiinfo[] =
{
GNOME_APP_UI_ITEM, N_("_Network Stream..."),
N_("Select a Network Stream"),
(gpointer) GnomeMenbarNetworkOpenActivate, NULL, NULL,
(gpointer) GnomeMenubarNetworkOpenActivate, NULL, NULL,
GNOME_APP_PIXMAP_STOCK, GNOME_STOCK_MENU_REFRESH,
0, (GdkModifierType) 0, NULL
},
GNOMEUIINFO_SEPARATOR,
{
GNOME_APP_UI_ITEM, N_("_Eject Disc"),
N_("Eject disc"),
(gpointer) GnomeMenubarDiscEjectActivate, NULL, NULL,
GNOME_APP_PIXMAP_STOCK, GNOME_STOCK_MENU_TOP,
0, (GdkModifierType) 0, NULL
},
GNOMEUIINFO_SEPARATOR,
GNOMEUIINFO_MENU_EXIT_ITEM (GnomeMenubarExitActivate, NULL),
GNOMEUIINFO_END
};
......@@ -145,6 +153,7 @@ create_intf_window (void)
GtkWidget *toolbar_network;
GtkWidget *toolbar_back;
GtkWidget *toolbar_stop;
GtkWidget *toolbar_eject;
GtkWidget *toolbar_play;
GtkWidget *toolbar_pause;
GtkWidget *toolbar_slow;
......@@ -220,10 +229,20 @@ create_intf_window (void)
(GtkDestroyNotify) gtk_widget_unref);
gtk_widget_ref (menubar_file_menu_uiinfo[4].widget);
gtk_object_set_data_full (GTK_OBJECT (intf_window), "menubar_exit",
gtk_object_set_data_full (GTK_OBJECT (intf_window), "menubar_eject",
menubar_file_menu_uiinfo[4].widget,
(GtkDestroyNotify) gtk_widget_unref);
gtk_widget_ref (menubar_file_menu_uiinfo[5].widget);
gtk_object_set_data_full (GTK_OBJECT (intf_window), "separator15",
menubar_file_menu_uiinfo[5].widget,
(GtkDestroyNotify) gtk_widget_unref);
gtk_widget_ref (menubar_file_menu_uiinfo[6].widget);
gtk_object_set_data_full (GTK_OBJECT (intf_window), "menubar_exit",
menubar_file_menu_uiinfo[6].widget,
(GtkDestroyNotify) gtk_widget_unref);
gtk_widget_ref (menubar_uiinfo[1].widget);
gtk_object_set_data_full (GTK_OBJECT (intf_window), "menubar_view",
menubar_uiinfo[1].widget,
......@@ -390,6 +409,18 @@ create_intf_window (void)
(GtkDestroyNotify) gtk_widget_unref);
gtk_widget_show (toolbar_stop);
tmp_toolbar_icon = gnome_stock_pixmap_widget (intf_window, GNOME_STOCK_PIXMAP_TOP);
toolbar_eject = gtk_toolbar_append_element (GTK_TOOLBAR (toolbar),
GTK_TOOLBAR_CHILD_BUTTON,
NULL,
_("Eject"),
_("Eject disc"), NULL,
tmp_toolbar_icon, NULL, NULL);
gtk_widget_ref (toolbar_eject);
gtk_object_set_data_full (GTK_OBJECT (intf_window), "toolbar_eject", toolbar_eject,
(GtkDestroyNotify) gtk_widget_unref);
gtk_widget_show (toolbar_eject);
tmp_toolbar_icon = gnome_stock_pixmap_widget (intf_window, GNOME_STOCK_PIXMAP_FORWARD);
toolbar_play = gtk_toolbar_append_element (GTK_TOOLBAR (toolbar),
GTK_TOOLBAR_CHILD_BUTTON,
......@@ -682,6 +713,9 @@ create_intf_window (void)
gtk_signal_connect (GTK_OBJECT (toolbar_stop), "button_press_event",
GTK_SIGNAL_FUNC (GtkControlStop),
"intf_window");
gtk_signal_connect (GTK_OBJECT (toolbar_eject), "button_press_event",
GTK_SIGNAL_FUNC (GtkDiscEject),
"intf_window");
gtk_signal_connect (GTK_OBJECT (toolbar_play), "button_press_event",
GTK_SIGNAL_FUNC (GtkControlPlay),
"intf_window");
......
......@@ -2,7 +2,7 @@
* gtk.c : Gtk+ plugin for vlc
*****************************************************************************
* Copyright (C) 2000-2001 VideoLAN
* $Id: gtk.c,v 1.8 2002/01/07 02:12:29 sam Exp $
* $Id: gtk.c,v 1.9 2002/01/09 02:01:14 sam Exp $
*
* Authors: Samuel Hocevar <sam@zoy.org>
*
......@@ -328,10 +328,12 @@ static gint GtkManage( gpointer p_data )
/* update the playlist */
GtkPlayListManage( p_data );
if( p_input_bank->pp_input[0] != NULL && !p_intf->b_die )
if( p_input_bank->pp_input[0] != NULL )
{
vlc_mutex_lock( &p_input_bank->pp_input[0]->stream.stream_lock );
if( !p_input_bank->pp_input[0]->b_die )
{
/* New input or stream map change */
if( p_input_bank->pp_input[0]->stream.b_changed )
{
......@@ -371,7 +373,7 @@ static gint GtkManage( gpointer p_data )
/* Update the old value */
p_intf->p_sys->f_adj_oldvalue = newvalue;
}
#undef p_area
# undef p_area
}
if( p_intf->p_sys->i_part !=
......@@ -380,9 +382,9 @@ static gint GtkManage( gpointer p_data )
p_intf->p_sys->b_chapter_update = 1;
GtkSetupMenus( p_intf );
}
}
vlc_mutex_unlock( &p_input_bank->pp_input[0]->stream.stream_lock );
}
else if( p_intf->p_sys->b_playing && !p_intf->b_die )
{
......
......@@ -140,6 +140,26 @@
<right_justify>False</right_justify>
</widget>
<widget>
<class>GtkMenuItem</class>
<name>menubar_eject</name>
<tooltip>Eject disc</tooltip>
<signal>
<name>activate</name>
<handler>GtkEjectDiscActivate</handler>
<data>&quot;intf_window&quot;</data>
<last_modification_time>Fri, 21 Dec 2001 12:51:34 GMT</last_modification_time>
</signal>
<label>_Eject Disc</label>
<right_justify>False</right_justify>
</widget>
<widget>
<class>GtkMenuItem</class>
<name>separator14</name>
<right_justify>False</right_justify>
</widget>
<widget>
<class>GtkMenuItem</class>
<name>menubar_exit</name>
......@@ -441,6 +461,19 @@
<label>Stop</label>
</widget>
<widget>
<class>GtkButton</class>
<child_name>Toolbar:button</child_name>
<name>toolbar_eject</name>
<signal>
<name>button_press_event</name>
<handler>GtkDiscEject</handler>
<data>&quot;intf_window&quot;</data>
<last_modification_time>Fri, 21 Dec 2001 15:33:26 GMT</last_modification_time>
</signal>
<label>Eject</label>
</widget>
<widget>
<class>GtkButton</class>
<child_name>Toolbar:button</child_name>
......
......@@ -2,10 +2,11 @@
* gtk_callbacks.c : Callbacks for the Gtk+ plugin.
*****************************************************************************
* Copyright (C) 2000, 2001 VideoLAN
* $Id: gtk_callbacks.c,v 1.30 2002/01/07 02:12:29 sam Exp $
* $Id: gtk_callbacks.c,v 1.31 2002/01/09 02:01:14 sam Exp $
*
* Authors: Samuel Hocevar <sam@zoy.org>
* Stphane Borel <stef@via.ecp.fr>
* Julien BLACHE <jb@technologeek.org>
*
* 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
......@@ -30,6 +31,8 @@
#include <videolan/vlc.h>
#include <unistd.h>
#include <gtk/gtk.h>
#include <string.h>
......@@ -39,6 +42,7 @@
#include "interface.h"
#include "intf_playlist.h"
#include "intf_eject.h"
#include "video.h"
#include "video_output.h"
......@@ -463,3 +467,55 @@ void GtkJumpActivate( GtkMenuItem * menuitem, gpointer user_data )
GtkJumpShow( GTK_WIDGET( menuitem ), NULL, user_data );
}
/****************************************************************************
* Callbacks for disc ejection
****************************************************************************/
gboolean GtkDiscEject ( GtkWidget *widget, GdkEventButton *event,
gpointer user_data )
{
char *psz_device = NULL;
/*
* Get the active input
* Determine whether we can eject a media, ie it's a VCD or DVD
* If it's neither a VCD nor a DVD, then return
*/
/*
* Don't really know if I must lock the stuff here, we're using it read-only
*/
if (p_main->p_playlist->current.psz_name != NULL)
{
if (strncmp(p_main->p_playlist->current.psz_name, "dvd", 3)
|| strncmp(p_main->p_playlist->current.psz_name, "vcd", 3))
{
/* Determine the device name by omitting the first 4 characters */
psz_device = strdup((p_main->p_playlist->current.psz_name + 4));
}
}
if( psz_device == NULL )
{
return TRUE;
}
/* If there's a stream playing, we aren't allowed to eject ! */
if( p_input_bank->pp_input[0] == NULL )
{
intf_WarnMsg( 4, "intf: ejecting %s", psz_device );
intf_Eject( psz_device );
}
free(psz_device);
return TRUE;
}
void GtkEjectDiscActivate ( GtkMenuItem *menuitem, gpointer user_data )
{
fprintf(stderr, "DEBUG: EJECT called from MENU !\n");
GtkDiscEject( GTK_WIDGET( menuitem ), NULL, user_data );
}
......@@ -2,7 +2,7 @@
* gtk_callbacks.h : Callbacks for the gtk plugin.
*****************************************************************************
* Copyright (C) 2000, 2001 VideoLAN
* $Id: gtk_callbacks.h,v 1.15 2001/05/30 23:02:03 stef Exp $
* $Id: gtk_callbacks.h,v 1.16 2002/01/09 02:01:14 sam Exp $
*
* Authors: Samuel Hocevar <sam@zoy.org>
* Stphane Borel <stef@via.ecp.fr>
......@@ -70,3 +70,12 @@ void GtkNetworkJoin ( GtkEditable *, gpointer );
void GtkChannelGo ( GtkButton *, gpointer );
void GtkNetworkOpenChannel ( GtkToggleButton *, gpointer );
void
GtkEjectDiscActivate (GtkMenuItem *menuitem,
gpointer user_data);
gboolean
GtkDiscEject (GtkWidget *widget,
GdkEventButton *event,
gpointer user_data);
......@@ -2,7 +2,7 @@
* gtk_display.c: Gtk+ tools for main interface
*****************************************************************************
* Copyright (C) 1999, 2000 VideoLAN
* $Id: gtk_display.c,v 1.11 2002/01/07 02:12:29 sam Exp $
* $Id: gtk_display.c,v 1.12 2002/01/09 02:01:14 sam Exp $
*
* Authors: Samuel Hocevar <sam@zoy.org>
* Stphane Borel <stef@via.ecp.fr>
......@@ -225,6 +225,7 @@ gint GtkModeManage( intf_thread_t * p_intf )
/* set control items */
gtk_widget_set_sensitive( GETWIDGET(p_window, "toolbar_back"), FALSE );
gtk_widget_set_sensitive( GETWIDGET(p_window, "toolbar_eject"), !b_control);
gtk_widget_set_sensitive( GETWIDGET(p_window, "toolbar_pause"), b_control );
gtk_widget_set_sensitive( GETWIDGET(p_window, "toolbar_slow"), b_control );
gtk_widget_set_sensitive( GETWIDGET(p_window, "toolbar_fast"), b_control );
......
......@@ -29,6 +29,8 @@ create_intf_window (void)
GtkWidget *menubar_disc;
GtkWidget *menubar_network;
GtkWidget *separator4;
GtkWidget *menubar_eject;
GtkWidget *separator14;
GtkWidget *menubar_exit;
GtkWidget *menubar_view;
GtkWidget *menubar_view_menu;
......@@ -60,6 +62,7 @@ create_intf_window (void)
GtkWidget *toolbar_network;
GtkWidget *toolbar_back;
GtkWidget *toolbar_stop;
GtkWidget *toolbar_eject;
GtkWidget *toolbar_play;
GtkWidget *toolbar_pause;
GtkWidget *toolbar_slow;
......@@ -196,6 +199,26 @@ create_intf_window (void)
gtk_container_add (GTK_CONTAINER (menubar_file_menu), separator4);
gtk_widget_set_sensitive (separator4, FALSE);
menubar_eject = gtk_menu_item_new_with_label ("");
tmp_key = gtk_label_parse_uline (GTK_LABEL (GTK_BIN (menubar_eject)->child),
_("_Eject Disc"));
gtk_widget_add_accelerator (menubar_eject, "activate_item", menubar_file_menu_accels,
tmp_key, 0, 0);
gtk_widget_ref (menubar_eject);
gtk_object_set_data_full (GTK_OBJECT (intf_window), "menubar_eject", menubar_eject,
(GtkDestroyNotify) gtk_widget_unref);
gtk_widget_show (menubar_eject);
gtk_container_add (GTK_CONTAINER (menubar_file_menu), menubar_eject);
gtk_tooltips_set_tip (tooltips, menubar_eject, _("Eject disc"), NULL);
separator14 = gtk_menu_item_new ();
gtk_widget_ref (separator14);
gtk_object_set_data_full (GTK_OBJECT (intf_window), "separator14", separator14,
(GtkDestroyNotify) gtk_widget_unref);
gtk_widget_show (separator14);
gtk_container_add (GTK_CONTAINER (menubar_file_menu), separator14);
gtk_widget_set_sensitive (separator14, FALSE);
menubar_exit = gtk_menu_item_new_with_label ("");
tmp_key = gtk_label_parse_uline (GTK_LABEL (GTK_BIN (menubar_exit)->child),
_("E_xit"));
......@@ -500,6 +523,17 @@ create_intf_window (void)
(GtkDestroyNotify) gtk_widget_unref);
gtk_widget_show (toolbar_stop);
toolbar_eject = gtk_toolbar_append_element (GTK_TOOLBAR (toolbar),
GTK_TOOLBAR_CHILD_BUTTON,
NULL,
_("Eject"),
NULL, NULL,
NULL, NULL, NULL);
gtk_widget_ref (toolbar_eject);
gtk_object_set_data_full (GTK_OBJECT (intf_window), "toolbar_eject", toolbar_eject,
(GtkDestroyNotify) gtk_widget_unref);
gtk_widget_show (toolbar_eject);
toolbar_play = gtk_toolbar_append_element (GTK_TOOLBAR (toolbar),
GTK_TOOLBAR_CHILD_BUTTON,
NULL,
......@@ -776,6 +810,9 @@ create_intf_window (void)
gtk_signal_connect (GTK_OBJECT (menubar_network), "activate",
GTK_SIGNAL_FUNC (GtkNetworkOpenActivate),
"intf_window");
gtk_signal_connect (GTK_OBJECT (menubar_eject), "activate",
GTK_SIGNAL_FUNC (GtkEjectDiscActivate),
"intf_window");
gtk_signal_connect (GTK_OBJECT (menubar_exit), "activate",
GTK_SIGNAL_FUNC (GtkExitActivate),
"intf_window");
......@@ -812,6 +849,9 @@ create_intf_window (void)
gtk_signal_connect (GTK_OBJECT (toolbar_stop), "button_press_event",
GTK_SIGNAL_FUNC (GtkControlStop),
"intf_window");
gtk_signal_connect (GTK_OBJECT (toolbar_eject), "button_press_event",
GTK_SIGNAL_FUNC (GtkDiscEject),
"intf_window");
gtk_signal_connect (GTK_OBJECT (toolbar_play), "button_press_event",
GTK_SIGNAL_FUNC (GtkControlPlay),
"intf_window");
......
mga_SOURCES = mga.c
xmga_SOURCES = xmga.c
/*****************************************************************************
* xmga.c : X11 MGA plugin for vlc
*****************************************************************************
* Copyright (C) 1998-2001 VideoLAN
* $Id: xmga.c,v 1.1 2002/01/09 02:01:14 sam Exp $
*
* Authors: Vincent Seguin <seguin@via.ecp.fr>
* Samuel Hocevar <sam@zoy.org>
*
* 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.
*****************************************************************************/
/*****************************************************************************
* Preamble
*****************************************************************************/
#include <errno.h> /* ENOMEM */
#include <stdlib.h> /* free() */
#include <string.h> /* strerror() */
#include <videolan/vlc.h>
#ifdef HAVE_MACHINE_PARAM_H
/* BSD */
#include <machine/param.h>
#include <sys/types.h> /* typedef ushort */
#include <sys/ipc.h>
#endif
#ifndef WIN32
#include <netinet/in.h> /* BSD: struct in_addr */
#endif
#include <sys/shm.h> /* shmget(), shmctl() */
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/keysym.h>
#include <X11/extensions/XShm.h>
#include <X11/extensions/dpms.h>
#include "video.h"
#include "video_output.h"
#include "interface.h"
#include "netutils.h" /* network_ChannelJoin */
#include "stream_control.h" /* needed by input_ext-intf.h... */
#include "input_ext-intf.h"
//#include "mga.h"
/*****************************************************************************
* Local prototypes
*****************************************************************************/
static void vout_getfunctions( function_list_t * );
static int vout_Probe ( probedata_t * );
static int vout_Create ( vout_thread_t * );
static void vout_Destroy ( vout_thread_t * );
static void vout_Render ( vout_thread_t *, picture_t * );
static void vout_Display ( vout_thread_t *, picture_t * );
static int vout_Manage ( vout_thread_t * );
static int vout_Init ( vout_thread_t * );
static void vout_End ( vout_thread_t * );
static int CreateWindow ( vout_thread_t * );
static void DestroyWindow ( vout_thread_t * );
static int NewPicture ( vout_thread_t *, picture_t * );
static void FreePicture ( vout_thread_t *, picture_t * );
static void ToggleFullScreen ( vout_thread_t * );
static void EnableXScreenSaver ( vout_thread_t * );
static void DisableXScreenSaver ( vout_thread_t * );
static void CreateCursor ( vout_thread_t * );
static void DestroyCursor ( vout_thread_t * );
static void ToggleCursor ( vout_thread_t * );
/*****************************************************************************
* Building configuration tree
*****************************************************************************/
MODULE_CONFIG_START
MODULE_CONFIG_STOP
MODULE_INIT_START
SET_DESCRIPTION( "X11 MGA module" )
ADD_CAPABILITY( VOUT, 60 )
ADD_SHORTCUT( "xmga" )
MODULE_INIT_STOP
MODULE_ACTIVATE_START
vout_getfunctions( &p_module->p_functions->vout );
MODULE_ACTIVATE_STOP
MODULE_DEACTIVATE_START
MODULE_DEACTIVATE_STOP
/*****************************************************************************
* vout_sys_t: video output method descriptor
*****************************************************************************
* This structure is part of the video output thread descriptor.
* It describes the X11 and XVideo specific properties of an output thread.
*****************************************************************************/
typedef struct vout_sys_s
{
/* Internal settings and properties */
Display * p_display; /* display pointer */
Visual * p_visual; /* visual pointer */
int i_screen; /* screen number */
Window window; /* root window */
GC gc; /* graphic context instance handler */
boolean_t b_shm; /* shared memory extension flag */
#ifdef MODULE_NAME_IS_xvideo
Window yuv_window; /* sub-window for displaying yuv video
data */
int i_xvport;
#else
Colormap colormap; /* colormap used (8bpp only) */
int i_screen_depth;
int i_bytes_per_pixel;
int i_bytes_per_line;
int i_red_mask;
int i_green_mask;
int i_blue_mask;
#endif
/* X11 generic properties */
Atom wm_protocols;
Atom wm_delete_window;
int i_width; /* width of main window */
int i_height; /* height of main window */
/* Backup of window position and size before fullscreen switch */
int i_width_backup;
int i_height_backup;
int i_xpos_backup;
int i_ypos_backup;
/* Screen saver properties */
int i_ss_timeout; /* timeout */
int i_ss_interval; /* interval between changes */
int i_ss_blanking; /* blanking mode */
int i_ss_exposure; /* exposure mode */
BOOL b_ss_dpms; /* DPMS mode */
/* Mouse pointer properties */
boolean_t b_mouse_pointer_visible;
mtime_t i_time_mouse_last_moved; /* used to auto-hide pointer*/
Cursor blank_cursor; /* the hidden cursor */
Pixmap cursor_pixmap;
} vout_sys_t;
/*****************************************************************************
* picture_sys_t: direct buffer method descriptor
*****************************************************************************
* This structure is part of the picture descriptor, it describes the
* XVideo specific properties of a direct buffer.
*****************************************************************************/
typedef struct picture_sys_s
{
} picture_sys_t;
/*****************************************************************************
* mwmhints_t: window manager hints
*****************************************************************************
* Fullscreen needs to be able to hide the wm decorations so we provide
* this structure to make it easier.
*****************************************************************************/
#define MWM_HINTS_DECORATIONS (1L << 1)
#define PROP_MWM_HINTS_ELEMENTS 5
typedef struct mwmhints_s
{
u32 flags;
u32 functions;
u32 decorations;
s32 input_mode;
u32 status;
} mwmhints_t;
/*****************************************************************************
* Chroma defines
*****************************************************************************/
#ifdef MODULE_NAME_IS_xvideo
# define MAX_DIRECTBUFFERS 5
#else
# define MAX_DIRECTBUFFERS 2
#endif
/*****************************************************************************
* Seeking function TODO: put this in a generic location !
*****************************************************************************/
static __inline__ void vout_Seek( off_t i_seek )
{
off_t i_tell;
vlc_mutex_lock( &p_input_bank->lock );
if( p_input_bank->pp_input[0] != NULL )
{
#define S p_input_bank->pp_input[0]->stream
i_tell = S.p_selected_area->i_tell + i_seek * (off_t)50 * S.i_mux_rate;
i_tell = ( i_tell <= 0 /*S.p_selected_area->i_start*/ )
? 0 /*S.p_selected_area->i_start*/
: ( i_tell >= S.p_selected_area->i_size )
? S.p_selected_area->i_size
: i_tell;
input_Seek( p_input_bank->pp_input[0], i_tell );
#undef S
}
vlc_mutex_unlock( &p_input_bank->lock );
}
/*****************************************************************************
* Functions exported as capabilities. They are declared as static so that
* we don't pollute the namespace too much.
*****************************************************************************/
static void 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_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_render = vout_Render;
p_function_list->functions.vout.pf_display = vout_Display;
}
/*****************************************************************************
* 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.
*****************************************************************************/
static int vout_Probe( probedata_t *p_data )
{
Display *p_display; /* display pointer */
char *psz_display;
#ifdef MODULE_NAME_IS_xvideo
int i_xvport, i_dummy;
#endif
/* Open display, unsing 'vlc_display' or DISPLAY environment variable */
psz_display = XDisplayName( main_GetPszVariable(VOUT_DISPLAY_VAR, NULL) );
p_display = XOpenDisplay( psz_display );
if( p_display == NULL ) /* error */
{
intf_WarnMsg( 3, "vout: cannot open display %s", psz_display );
return( 0 );
}
#ifdef MODULE_NAME_IS_xvideo
/* Check that there is an available XVideo port for this format */
i_xvport = XVideoGetPort( p_display, p_data->vout.i_chroma, &i_dummy );
if( i_xvport < 0 )
{
/* It failed, but it's not completely lost ! We try to open an
* XVideo port for a YUY2 picture */
i_xvport = XVideoGetPort( p_display, FOURCC_YUY2, &i_dummy );
if( i_xvport < 0 )
{
/* It failed, but it's not completely lost ! We try to open an
* XVideo port for a simple 16bpp RGB picture */
i_xvport = XVideoGetPort( p_display, FOURCC_RV16, &i_dummy );
if( i_xvport < 0 )
{
XCloseDisplay( p_display );
return( 0 );
}
}
}
XVideoReleasePort( p_display, i_xvport );
#endif
/* Clean-up everyting */
XCloseDisplay( p_display );
#ifdef MODULE_NAME_IS_xvideo
return( 150 );
#else
return( 50 );
#endif
}
/*****************************************************************************
* vout_Create: allocate X11 video thread output method
*****************************************************************************
* This function allocate and initialize a X11 vout method. It uses some of the
* vout properties to choose the window size, and change them according to the
* actual properties of the display.
*****************************************************************************/
static int vout_Create( vout_thread_t *p_vout )
{
char *psz_display;
/* Allocate structure */
p_vout->p_sys = malloc( sizeof( vout_sys_t ) );
if( p_vout->p_sys == NULL )
{
intf_ErrMsg( "vout error: %s", strerror(ENOMEM) );
return( 1 );
}
/* Open display, unsing 'vlc_display' or DISPLAY environment variable */
psz_display = XDisplayName( main_GetPszVariable( VOUT_DISPLAY_VAR, NULL ) );
p_vout->p_sys->p_display = XOpenDisplay( psz_display );
if( p_vout->p_sys->p_display == NULL ) /* error */
{
intf_ErrMsg( "vout error: cannot open display %s", psz_display );
free( p_vout->p_sys );
return( 1 );
}
p_vout->p_sys->i_screen = DefaultScreen( p_vout->p_sys->p_display );
/* Create blank cursor (for mouse cursor autohiding) */
p_vout->p_sys->b_mouse_pointer_visible = 1;
CreateCursor( p_vout );
/* Spawn base window - this window will include the video output window,
* but also command buttons, subtitles and other indicators */
if( CreateWindow( p_vout ) )
{
intf_ErrMsg( "vout error: cannot create X11 window" );
DestroyCursor( p_vout );
XCloseDisplay( p_vout->p_sys->p_display );
free( p_vout->p_sys );
return( 1 );
}
/* Disable screen saver and return */
DisableXScreenSaver( p_vout );
return( 0 );
}
/*****************************************************************************
* vout_Destroy: destroy X11 video thread output method
*****************************************************************************
* Terminate an output method created by vout_CreateOutputMethod
*****************************************************************************/
static void vout_Destroy( vout_thread_t *p_vout )
{
/* Restore cursor if it was blanked */
if( !p_vout->p_sys->b_mouse_pointer_visible )
{
ToggleCursor( p_vout );
}
DestroyCursor( p_vout );
EnableXScreenSaver( p_vout );
DestroyWindow( p_vout );
XCloseDisplay( p_vout->p_sys->p_display );
/* Destroy structure */
free( p_vout->p_sys );
}
/*****************************************************************************
* vout_Init: initialize X11 video thread output method
*****************************************************************************
* This function create the XImages needed by the output thread. It is called
* at the beginning of the thread, but also each time the window is resized.
*****************************************************************************/
static int vout_Init( vout_thread_t *p_vout )
{
int i_index;
picture_t *p_pic;
I_OUTPUTPICTURES = 0;
#ifdef MODULE_NAME_IS_xvideo
/* Initialize the output structure; we already found an XVideo port,
* and the corresponding chroma we will be using. Since we can
* arbitrary scale, stick to the coordinates and aspect. */
p_vout->output.i_width = p_vout->render.i_width;
p_vout->output.i_height = p_vout->render.i_height;
p_vout->output.i_aspect = p_vout->render.i_aspect;
#else
/* Initialize the output structure: RGB with square pixels, whatever
* the input format is, since it's the only format we know */
switch( p_vout->p_sys->i_screen_depth )
{
case 8: /* FIXME: set the palette */
p_vout->output.i_chroma = FOURCC_BI_RGB; break;
case 15:
p_vout->output.i_chroma = FOURCC_RV15; break;
case 16:
p_vout->output.i_chroma = FOURCC_RV16; break;
case 24:
p_vout->output.i_chroma = FOURCC_BI_BITFIELDS; break;
case 32:
p_vout->output.i_chroma = FOURCC_BI_BITFIELDS; break;
default:
intf_ErrMsg( "vout error: unknown screen depth" );
return( 0 );
}
p_vout->output.i_width = p_vout->p_sys->i_width;
p_vout->output.i_height = p_vout->p_sys->i_height;
/* Assume we have square pixels */
p_vout->output.i_aspect = p_vout->p_sys->i_width
* VOUT_ASPECT_FACTOR / p_vout->p_sys->i_height;
#endif
/* Try to initialize up to MAX_DIRECTBUFFERS direct buffers */
while( I_OUTPUTPICTURES < MAX_DIRECTBUFFERS )
{
p_pic = NULL;
/* Find an empty picture slot */
for( i_index = 0 ; i_index < VOUT_MAX_PICTURES ; i_index++ )
{
if( p_vout->p_picture[ i_index ].i_status == FREE_PICTURE )
{
p_pic = p_vout->p_picture + i_index;
break;
}
}
/* Allocate the picture */
if( p_pic == NULL || NewPicture( p_vout, p_pic ) )
{
break;
}
p_pic->i_status = DESTROYED_PICTURE;
p_pic->i_type = DIRECT_PICTURE;
PP_OUTPUTPICTURE[ I_OUTPUTPICTURES ] = p_pic;
I_OUTPUTPICTURES++;
}
return( 0 );
}
/*****************************************************************************
* vout_Render: render previously calculated output
*****************************************************************************/
static void vout_Render( vout_thread_t *p_vout, picture_t *p_pic )
{
;
}
/*****************************************************************************
* vout_Display: displays previously rendered output
*****************************************************************************
* This function sends the currently rendered image to X11 server.
* (The Xv extension takes care of "double-buffering".)
*****************************************************************************/
static void vout_Display( vout_thread_t *p_vout, picture_t *p_pic )
{
int i_width, i_height, i_x, i_y;
vout_PlacePicture( p_vout, p_vout->p_sys->i_width, p_vout->p_sys->i_height,
&i_x, &i_y, &i_width, &i_height );
}
/*****************************************************************************
* vout_Manage: handle X11 events
*****************************************************************************
* This function should be called regularly by video output thread. It manages
* X11 events and allows window resizing. It returns a non null value on
* error.
*****************************************************************************/
static int vout_Manage( vout_thread_t *p_vout )
{
XEvent xevent; /* X11 event */
boolean_t b_resized; /* window has been resized */
char i_key; /* ISO Latin-1 key */
KeySym x_key_symbol;
/* Handle X11 events: ConfigureNotify events are parsed to know if the
* output window's size changed, MapNotify and UnmapNotify to know if the
* window is mapped (and if the display is useful), and ClientMessages
* to intercept window destruction requests */
b_resized = 0;
while( XCheckWindowEvent( p_vout->p_sys->p_display, p_vout->p_sys->window,
StructureNotifyMask | KeyPressMask |
ButtonPressMask | ButtonReleaseMask |
PointerMotionMask | Button1MotionMask , &xevent )
== True )
{
/* ConfigureNotify event: prepare */
if( (xevent.type == ConfigureNotify)
&& ((xevent.xconfigure.width != p_vout->p_sys->i_width)
|| (xevent.xconfigure.height != p_vout->p_sys->i_height)) )
{
/* Update dimensions */
b_resized = 1;
p_vout->i_changes |= VOUT_SIZE_CHANGE;
p_vout->p_sys->i_width = xevent.xconfigure.width;
p_vout->p_sys->i_height = xevent.xconfigure.height;
}
/* MapNotify event: change window status and disable screen saver */
else if( xevent.type == MapNotify)
{
if( (p_vout != NULL) && !p_vout->b_active )
{
DisableXScreenSaver( p_vout );
p_vout->b_active = 1;
}
}
/* UnmapNotify event: change window status and enable screen saver */
else if( xevent.type == UnmapNotify )
{
if( (p_vout != NULL) && p_vout->b_active )
{
EnableXScreenSaver( p_vout );
p_vout->b_active = 0;
}
}
/* Keyboard event */
else if( xevent.type == KeyPress )
{
/* We may have keys like F1 trough F12, ESC ... */
x_key_symbol = XKeycodeToKeysym( p_vout->p_sys->p_display,
xevent.xkey.keycode, 0 );
switch( x_key_symbol )
{
case XK_Escape:
p_main->p_intf->b_die = 1;
break;
case XK_Menu:
p_main->p_intf->b_menu_change = 1;
break;
case XK_Left:
vout_Seek( -5 );
break;
case XK_Right:
vout_Seek( 5 );
break;
case XK_Up:
vout_Seek( 60 );
break;
case XK_Down:
vout_Seek( -60 );
break;
case XK_Home:
input_Seek( p_input_bank->pp_input[0],
p_input_bank->pp_input[0]->stream.p_selected_area->i_start );
break;
case XK_End:
input_Seek( p_input_bank->pp_input[0],
p_input_bank->pp_input[0]->stream.p_selected_area->i_size );
break;
case XK_Page_Up:
vout_Seek( 900 );
break;
case XK_Page_Down:
vout_Seek( -900 );
break;
case XK_space:
input_SetStatus( p_input_bank->pp_input[0],
INPUT_STATUS_PAUSE );
break;
default:
/* "Normal Keys"
* The reason why I use this instead of XK_0 is that
* with XLookupString, we don't have to care about
* keymaps. */
if( XLookupString( &xevent.xkey, &i_key, 1, NULL, NULL ) )
{
/* FIXME: handle stuff here */
switch( i_key )
{
case 'q':
case 'Q':
p_main->p_intf->b_die = 1;
break;
case 'f':
case 'F':
p_vout->i_changes |= VOUT_FULLSCREEN_CHANGE;
break;
case '0': network_ChannelJoin( 0 ); break;
case '1': network_ChannelJoin( 1 ); break;
case '2': network_ChannelJoin( 2 ); break;
case '3': network_ChannelJoin( 3 ); break;
case '4': network_ChannelJoin( 4 ); break;
case '5': network_ChannelJoin( 5 ); break;
case '6': network_ChannelJoin( 6 ); break;
case '7': network_ChannelJoin( 7 ); break;
case '8': network_ChannelJoin( 8 ); break;
case '9': network_ChannelJoin( 9 ); break;
default:
intf_DbgMsg( "vout: unhandled key '%c' (%i)",
(char)i_key, i_key );
break;
}
}
break;
}
}
/* Mouse click */
else if( xevent.type == ButtonPress )
{
switch( ((XButtonEvent *)&xevent)->button )
{
case Button1:
/* In this part we will eventually manage
* clicks for DVD navigation for instance. For the
* moment just pause the stream. */
input_SetStatus( p_input_bank->pp_input[0],
INPUT_STATUS_PAUSE );
break;
case Button4:
vout_Seek( 15 );
break;
case Button5:
vout_Seek( -15 );
break;
}
}
/* Mouse release */
else if( xevent.type == ButtonRelease )
{
switch( ((XButtonEvent *)&xevent)->button )
{
case Button3:
/* FIXME: need locking ! */
p_main->p_intf->b_menu_change = 1;
break;
}
}
/* Mouse move */
else if( xevent.type == MotionNotify )
{
p_vout->p_sys->i_time_mouse_last_moved = mdate();
if( ! p_vout->p_sys->b_mouse_pointer_visible )
{
ToggleCursor( p_vout );
}
}
/* Other event */
else
{
intf_WarnMsg( 3, "vout: unhandled event %d received", xevent.type );
}
}
/* ClientMessage event - only WM_PROTOCOLS with WM_DELETE_WINDOW data
* are handled - according to the man pages, the format is always 32
* in this case */
while( XCheckTypedEvent( p_vout->p_sys->p_display,
ClientMessage, &xevent ) )
{
if( (xevent.xclient.message_type == p_vout->p_sys->wm_protocols)
&& (xevent.xclient.data.l[0] == p_vout->p_sys->wm_delete_window ) )
{
p_main->p_intf->b_die = 1;
}
else
{
intf_DbgMsg( "vout: unhandled ClientMessage received" );
}
}
/*
* Fullscreen Change
*/
if ( p_vout->i_changes & VOUT_FULLSCREEN_CHANGE )
{
ToggleFullScreen( p_vout );
p_vout->i_changes &= ~VOUT_FULLSCREEN_CHANGE;
}
/*
* Size change
*/
if( p_vout->i_changes & VOUT_SIZE_CHANGE )
{
int i_width, i_height, i_x, i_y;
p_vout->i_changes &= ~VOUT_SIZE_CHANGE;
intf_WarnMsg( 3, "vout: video display resized (%dx%d)",
p_vout->p_sys->i_width,
p_vout->p_sys->i_height );
vout_PlacePicture( p_vout, p_vout->p_sys->i_width,
p_vout->p_sys->i_height,
&i_x, &i_y, &i_width, &i_height );
}
/* Autohide Cursour */
if( mdate() - p_vout->p_sys->i_time_mouse_last_moved > 2000000 )
{
/* Hide the mouse automatically */
if( p_vout->p_sys->b_mouse_pointer_visible )
{
ToggleCursor( p_vout );
}
}
return 0;
}
/*****************************************************************************
* vout_End: terminate X11 video thread output method
*****************************************************************************
* Destroy the X11 XImages created by vout_Init. It is called at the end of
* the thread, but also each time the window is resized.
*****************************************************************************/
static void vout_End( vout_thread_t *p_vout )
{
int i_index;
/* Free the direct buffers we allocated */
for( i_index = I_OUTPUTPICTURES ; i_index ; )
{
i_index--;
FreePicture( p_vout, PP_OUTPUTPICTURE[ i_index ] );
}
}
/* following functions are local */
/*****************************************************************************
* CreateWindow: open and set-up X11 main window
*****************************************************************************/
static int CreateWindow( vout_thread_t *p_vout )
{
XSizeHints xsize_hints;
XSetWindowAttributes xwindow_attributes;
XGCValues xgcvalues;
XEvent xevent;
boolean_t b_expose;
boolean_t b_configure_notify;
boolean_t b_map_notify;
/* Set main window's size */
if( p_vout->render.i_height * p_vout->render.i_aspect
>= p_vout->render.i_width * VOUT_ASPECT_FACTOR )
{
p_vout->p_sys->i_width = p_vout->render.i_height
* p_vout->render.i_aspect / VOUT_ASPECT_FACTOR;
p_vout->p_sys->i_height = p_vout->render.i_height;
}
else
{
p_vout->p_sys->i_width = p_vout->render.i_width;
p_vout->p_sys->i_height = p_vout->render.i_width
* VOUT_ASPECT_FACTOR / p_vout->render.i_aspect;
}
#if 0
if( p_vout->p_sys->i_width <= 300 && p_vout->p_sys->i_height <= 300 )
{
p_vout->p_sys->i_width <<= 1;
p_vout->p_sys->i_height <<= 1;
}
else if( p_vout->p_sys->i_width <= 400
&& p_vout->p_sys->i_height <= 400 )
{
p_vout->p_sys->i_width += p_vout->p_sys->i_width >> 1;
p_vout->p_sys->i_height += p_vout->p_sys->i_height >> 1;
}
#endif
/* Prepare window manager hints and properties */
xsize_hints.base_width = p_vout->p_sys->i_width;
xsize_hints.base_height = p_vout->p_sys->i_height;
xsize_hints.flags = PSize;
p_vout->p_sys->wm_protocols = XInternAtom( p_vout->p_sys->p_display,
"WM_PROTOCOLS", True );
p_vout->p_sys->wm_delete_window = XInternAtom( p_vout->p_sys->p_display,
"WM_DELETE_WINDOW", True );
/* Prepare window attributes */
xwindow_attributes.backing_store = Always; /* save the hidden part */
xwindow_attributes.background_pixel = BlackPixel(p_vout->p_sys->p_display,
p_vout->p_sys->i_screen);
xwindow_attributes.event_mask = ExposureMask | StructureNotifyMask;
/* Create the window and set hints - the window must receive
* ConfigureNotify events, and until it is displayed, Expose and
* MapNotify events. */
p_vout->p_sys->window =
XCreateWindow( p_vout->p_sys->p_display,
DefaultRootWindow( p_vout->p_sys->p_display ),
0, 0,
p_vout->p_sys->i_width,
p_vout->p_sys->i_height,
0,
0, InputOutput, 0,
CWBackingStore | CWBackPixel | CWEventMask,
&xwindow_attributes );
/* Set window manager hints and properties: size hints, command,
* window's name, and accepted protocols */
XSetWMNormalHints( p_vout->p_sys->p_display, p_vout->p_sys->window,
&xsize_hints );
XSetCommand( p_vout->p_sys->p_display, p_vout->p_sys->window,
p_main->ppsz_argv, p_main->i_argc );
XStoreName( p_vout->p_sys->p_display, p_vout->p_sys->window,
VOUT_TITLE " (XMGA output)"
);
if( (p_vout->p_sys->wm_protocols == None) /* use WM_DELETE_WINDOW */
|| (p_vout->p_sys->wm_delete_window == None)
|| !XSetWMProtocols( p_vout->p_sys->p_display, p_vout->p_sys->window,
&p_vout->p_sys->wm_delete_window, 1 ) )
{
/* WM_DELETE_WINDOW is not supported by window manager */
intf_Msg( "vout error: missing or bad window manager" );
}
/* Creation of a graphic context that doesn't generate a GraphicsExpose
* event when using functions like XCopyArea */
xgcvalues.graphics_exposures = False;
p_vout->p_sys->gc = XCreateGC( p_vout->p_sys->p_display,
p_vout->p_sys->window,
GCGraphicsExposures, &xgcvalues);
/* Send orders to server, and wait until window is displayed - three
* events must be received: a MapNotify event, an Expose event allowing
* drawing in the window, and a ConfigureNotify to get the window
* dimensions. Once those events have been received, only ConfigureNotify
* events need to be received. */
b_expose = 0;
b_configure_notify = 0;
b_map_notify = 0;
XMapWindow( p_vout->p_sys->p_display, p_vout->p_sys->window);
do
{
XNextEvent( p_vout->p_sys->p_display, &xevent);
if( (xevent.type == Expose)
&& (xevent.xexpose.window == p_vout->p_sys->window) )
{
b_expose = 1;
}
else if( (xevent.type == MapNotify)
&& (xevent.xmap.window == p_vout->p_sys->window) )
{
b_map_notify = 1;
}
else if( (xevent.type == ConfigureNotify)
&& (xevent.xconfigure.window == p_vout->p_sys->window) )
{
b_configure_notify = 1;
p_vout->p_sys->i_width = xevent.xconfigure.width;
p_vout->p_sys->i_height = xevent.xconfigure.height;
}
} while( !( b_expose && b_configure_notify && b_map_notify ) );
XSelectInput( p_vout->p_sys->p_display, p_vout->p_sys->window,
StructureNotifyMask | KeyPressMask |
ButtonPressMask | ButtonReleaseMask |
PointerMotionMask );
/* If the cursor was formerly blank than blank it again */
if( !p_vout->p_sys->b_mouse_pointer_visible )
{
ToggleCursor( p_vout );
ToggleCursor( p_vout );
}
XSync( p_vout->p_sys->p_display, False );
/* At this stage, the window is open, displayed, and ready to
* receive data */
return( 0 );
}
/*****************************************************************************
* DestroyWindow: destroy the window
*****************************************************************************
*
*****************************************************************************/
static void DestroyWindow( vout_thread_t *p_vout )
{
XSync( p_vout->p_sys->p_display, False );
XUnmapWindow( p_vout->p_sys->p_display, p_vout->p_sys->window );
XFreeGC( p_vout->p_sys->p_display, p_vout->p_sys->gc );
XDestroyWindow( p_vout->p_sys->p_display, p_vout->p_sys->window );
}
/*****************************************************************************
* NewPicture: allocate a picture
*****************************************************************************
* Returns 0 on success, -1 otherwise
*****************************************************************************/
static int NewPicture( vout_thread_t *p_vout, picture_t *p_pic )
{
/* We know the chroma, allocate a buffer which will be used
* directly by the decoder */
p_pic->p_sys = malloc( sizeof( picture_sys_t ) );
if( p_pic->p_sys == NULL )
{
return -1;
}
/* XXX */
switch( p_vout->output.i_chroma )
{
/* XXX ?? */
default:
/* Unknown chroma, tell the guy to get lost */
free( p_pic->p_sys );
intf_ErrMsg( "vout error: never heard of chroma 0x%.8x (%4.4s)",
p_vout->output.i_chroma,
(char*)&p_vout->output.i_chroma );
p_pic->i_planes = 0;
return -1;
}
return 0;
}
/*****************************************************************************
* FreePicture: destroy a picture allocated with NewPicture
*****************************************************************************
* Destroy XImage AND associated data. If using Shm, detach shared memory
* segment from server and process, then free it. The XDestroyImage manpage
* says that both the image structure _and_ the data pointed to by the
* image structure are freed, so no need to free p_image->data.
*****************************************************************************/
static void FreePicture( vout_thread_t *p_vout, picture_t *p_pic )
{
XSync( p_vout->p_sys->p_display, False );
free( p_pic->p_sys );
}
/*****************************************************************************
* ToggleFullScreen: Enable or disable full screen mode
*****************************************************************************
* This function will switch between fullscreen and window mode.
*
*****************************************************************************/
static void ToggleFullScreen ( vout_thread_t *p_vout )
{
Atom prop;
mwmhints_t mwmhints;
int i_xpos, i_ypos, i_width, i_height;
p_vout->b_fullscreen = !p_vout->b_fullscreen;
if( p_vout->b_fullscreen )
{
Window next_parent, parent, *p_dummy, dummy1;
unsigned int dummy2, dummy3;
intf_WarnMsg( 3, "vout: entering fullscreen mode" );
/* Save current window coordinates so they can be restored when
* we exit from fullscreen mode */
/* find the real parent, which means the which is a direct child of
* the root window */
next_parent = parent = p_vout->p_sys->window;
while( next_parent != DefaultRootWindow( p_vout->p_sys->p_display ) )
{
parent = next_parent;
XQueryTree( p_vout->p_sys->p_display,
parent,
&dummy1,
&next_parent,
&p_dummy,
&dummy2 );
XFree((void *)p_dummy);
}
XGetGeometry( p_vout->p_sys->p_display,
p_vout->p_sys->window,
&dummy1,
&dummy2,
&dummy3,
&p_vout->p_sys->i_width_backup,
&p_vout->p_sys->i_height_backup,
&dummy2, &dummy3 );
XTranslateCoordinates( p_vout->p_sys->p_display,
parent,
DefaultRootWindow( p_vout->p_sys->p_display ),
0,
0,
&p_vout->p_sys->i_xpos_backup,
&p_vout->p_sys->i_ypos_backup,
&dummy1 );
mwmhints.flags = MWM_HINTS_DECORATIONS;
mwmhints.decorations = 0;
i_xpos = 0;
i_ypos = 0;
i_width = DisplayWidth( p_vout->p_sys->p_display,
p_vout->p_sys->i_screen );
i_height = DisplayHeight( p_vout->p_sys->p_display,
p_vout->p_sys->i_screen );
#if 0
/* Being a transient window allows us to really be fullscreen (display
* over the taskbar for instance) but then we end-up with the same
* result as with the brute force method */
XSetTransientForHint( p_vout->p_sys->p_display,
p_vout->p_sys->window, None );
#endif
}
else
{
intf_WarnMsg( 3, "vout: leaving fullscreen mode" );
mwmhints.flags = MWM_HINTS_DECORATIONS;
mwmhints.decorations = 1;
i_xpos = p_vout->p_sys->i_xpos_backup;
i_ypos = p_vout->p_sys->i_ypos_backup;
i_width = p_vout->p_sys->i_width_backup;
i_height = p_vout->p_sys->i_height_backup;
}
/* To my knowledge there are two ways to create a borderless window.
* There's the generic way which is to tell x to bypass the window manager,
* but this creates problems with the focus of other applications.
* The other way is to use the motif property "_MOTIF_WM_HINTS" which
* luckily seems to be supported by most window managers.
*/
prop = XInternAtom( p_vout->p_sys->p_display, "_MOTIF_WM_HINTS",
False );
XChangeProperty( p_vout->p_sys->p_display, p_vout->p_sys->window,
prop, prop, 32, PropModeReplace,
(unsigned char *)&mwmhints,
PROP_MWM_HINTS_ELEMENTS );
#if 0 /* brute force way to remove decorations */
XSetWindowAttributes attributes;
attributes.override_redirect = True;
XChangeWindowAttributes( p_vout->p_sys->p_display,
p_vout->p_sys->window,
CWOverrideRedirect,
&attributes);
#endif
/* We need to unmap and remap the window if we want the window
* manager to take our changes into effect */
XUnmapWindow( p_vout->p_sys->p_display, p_vout->p_sys->window);
XMapRaised( p_vout->p_sys->p_display, p_vout->p_sys->window);
XMoveResizeWindow( p_vout->p_sys->p_display,
p_vout->p_sys->window,
i_xpos,
i_ypos,
i_width,
i_height );
XFlush( p_vout->p_sys->p_display );
}
/*****************************************************************************
* EnableXScreenSaver: enable screen saver
*****************************************************************************
* This function enables the screen saver on a display after it has been
* disabled by XDisableScreenSaver.
* FIXME: what happens if multiple vlc sessions are running at the same
* time ???
*****************************************************************************/
static void EnableXScreenSaver( vout_thread_t *p_vout )
{
int dummy;
intf_DbgMsg( "vout: enabling screen saver" );
XSetScreenSaver( p_vout->p_sys->p_display, p_vout->p_sys->i_ss_timeout,
p_vout->p_sys->i_ss_interval,
p_vout->p_sys->i_ss_blanking,
p_vout->p_sys->i_ss_exposure );
/* Restore DPMS settings */
if( DPMSQueryExtension( p_vout->p_sys->p_display, &dummy, &dummy ) )
{
if( p_vout->p_sys->b_ss_dpms )
{
DPMSEnable( p_vout->p_sys->p_display );
}
}
}
/*****************************************************************************
* DisableXScreenSaver: disable screen saver
*****************************************************************************
* See XEnableXScreenSaver
*****************************************************************************/
static void DisableXScreenSaver( vout_thread_t *p_vout )
{
int dummy;
/* Save screen saver informations */
XGetScreenSaver( p_vout->p_sys->p_display, &p_vout->p_sys->i_ss_timeout,
&p_vout->p_sys->i_ss_interval,
&p_vout->p_sys->i_ss_blanking,
&p_vout->p_sys->i_ss_exposure );
/* Disable screen saver */
intf_DbgMsg( "vout: disabling screen saver" );
XSetScreenSaver( p_vout->p_sys->p_display, 0,
p_vout->p_sys->i_ss_interval,
p_vout->p_sys->i_ss_blanking,
p_vout->p_sys->i_ss_exposure );
/* Disable DPMS */
if( DPMSQueryExtension( p_vout->p_sys->p_display, &dummy, &dummy ) )
{
CARD16 dummy;
/* Save DPMS current state */
DPMSInfo( p_vout->p_sys->p_display, &dummy,
&p_vout->p_sys->b_ss_dpms );
intf_DbgMsg( "vout: disabling DPMS" );
DPMSDisable( p_vout->p_sys->p_display );
}
}
/*****************************************************************************
* CreateCursor: create a blank mouse pointer
*****************************************************************************/
static void CreateCursor( vout_thread_t *p_vout )
{
XColor cursor_color;
p_vout->p_sys->cursor_pixmap =
XCreatePixmap( p_vout->p_sys->p_display,
DefaultRootWindow( p_vout->p_sys->p_display ),
1, 1, 1 );
XParseColor( p_vout->p_sys->p_display,
XCreateColormap( p_vout->p_sys->p_display,
DefaultRootWindow(
p_vout->p_sys->p_display ),
DefaultVisual(
p_vout->p_sys->p_display,
p_vout->p_sys->i_screen ),
AllocNone ),
"black", &cursor_color );
p_vout->p_sys->blank_cursor =
XCreatePixmapCursor( p_vout->p_sys->p_display,
p_vout->p_sys->cursor_pixmap,
p_vout->p_sys->cursor_pixmap,
&cursor_color, &cursor_color, 1, 1 );
}
/*****************************************************************************
* DestroyCursor: destroy the blank mouse pointer
*****************************************************************************/
static void DestroyCursor( vout_thread_t *p_vout )
{
XFreePixmap( p_vout->p_sys->p_display, p_vout->p_sys->cursor_pixmap );
}
/*****************************************************************************
* ToggleCursor: hide or show the mouse pointer
*****************************************************************************
* This function hides the X pointer if it is visible by setting the pointer
* sprite to a blank one. To show it again, we disable the sprite.
*****************************************************************************/
static void ToggleCursor( vout_thread_t *p_vout )
{
if( p_vout->p_sys->b_mouse_pointer_visible )
{
XDefineCursor( p_vout->p_sys->p_display,
p_vout->p_sys->window,
p_vout->p_sys->blank_cursor );
p_vout->p_sys->b_mouse_pointer_visible = 0;
}
else
{
XUndefineCursor( p_vout->p_sys->p_display, p_vout->p_sys->window );
p_vout->p_sys->b_mouse_pointer_visible = 1;
}
}
......@@ -4,7 +4,7 @@
* decoders.
*****************************************************************************
* Copyright (C) 1998-2001 VideoLAN
* $Id: input.c,v 1.168 2002/01/07 02:12:29 sam Exp $
* $Id: input.c,v 1.169 2002/01/09 02:01:14 sam Exp $
*
* Authors: Christophe Massiot <massiot@via.ecp.fr>
*
......@@ -113,11 +113,15 @@ void input_InitBank ( void )
*****************************************************************************/
void input_EndBank ( void )
{
int i_input;
/* Ask all remaining video outputs to die */
while( p_input_bank->i_count )
for( i_input = 0; i_input < p_input_bank->i_count; i_input++ )
{
input_StopThread(
p_input_bank->pp_input[ i_input ], NULL );
input_DestroyThread(
p_input_bank->pp_input[ --p_input_bank->i_count ], NULL );
p_input_bank->pp_input[ i_input ] );
}
vlc_mutex_destroy( &p_input_bank->lock );
......@@ -134,7 +138,6 @@ void input_EndBank ( void )
input_thread_t *input_CreateThread ( playlist_item_t *p_item, int *pi_status )
{
input_thread_t * p_input; /* thread descriptor */
int i_status; /* thread status */
/* Allocate descriptor */
p_input = (input_thread_t *)malloc( sizeof(input_thread_t) );
......@@ -153,9 +156,8 @@ input_thread_t *input_CreateThread ( playlist_item_t *p_item, int *pi_status )
/* Set target */
p_input->p_source = p_item->psz_name;
/* I have never understood that stuff --Meuuh */
p_input->pi_status = (pi_status != NULL) ? pi_status : &i_status;
*p_input->pi_status = THREAD_CREATE;
/* Set status */
p_input->i_status = THREAD_CREATE;
/* Initialize stream description */
p_input->stream.i_es_number = 0;
......@@ -196,6 +198,7 @@ input_thread_t *input_CreateThread ( playlist_item_t *p_item, int *pi_status )
return( NULL );
}
#if 0
/* If status is NULL, wait until the thread is created */
if( pi_status == NULL )
{
......@@ -204,36 +207,30 @@ input_thread_t *input_CreateThread ( playlist_item_t *p_item, int *pi_status )
msleep( THREAD_SLEEP );
} while( (i_status != THREAD_READY) && (i_status != THREAD_ERROR)
&& (i_status != THREAD_FATAL) );
if( i_status != THREAD_READY )
{
return( NULL );
}
}
#endif
return( p_input );
}
/*****************************************************************************
* input_DestroyThread: mark an input thread as zombie
* input_StopThread: mark an input thread as zombie
*****************************************************************************
* This function should not return until the thread is effectively cancelled.
*****************************************************************************/
void input_DestroyThread( input_thread_t *p_input, int *pi_status )
void input_StopThread( input_thread_t *p_input, int *pi_status )
{
int i_status; /* thread status */
/* Set status */
p_input->pi_status = (pi_status != NULL) ? pi_status : &i_status;
*p_input->pi_status = THREAD_DESTROY;
/* Make the thread exit from a possible vlc_cond_wait() */
vlc_mutex_lock( &p_input->stream.stream_lock );
/* Request thread destruction */
p_input->b_die = 1;
/* Make the thread exit from a possible vlc_cond_wait() */
vlc_mutex_lock( &p_input->stream.stream_lock );
vlc_cond_signal( &p_input->stream.stream_wait );
vlc_mutex_unlock( &p_input->stream.stream_lock );
/* If status is NULL, wait until thread has been destroyed */
#if 0
if( pi_status == NULL )
{
do
......@@ -242,6 +239,25 @@ void input_DestroyThread( input_thread_t *p_input, int *pi_status )
} while ( (i_status != THREAD_OVER) && (i_status != THREAD_ERROR)
&& (i_status != THREAD_FATAL) );
}
#endif
}
/*****************************************************************************
* input_DestroyThread: mark an input thread as zombie
*****************************************************************************
* This function should not return until the thread is effectively cancelled.
*****************************************************************************/
void input_DestroyThread( input_thread_t *p_input )
{
/* Join the thread */
vlc_thread_join( p_input->thread_id );
/* Destroy Mutex locks */
vlc_mutex_destroy( &p_input->stream.control.control_lock );
vlc_mutex_destroy( &p_input->stream.stream_lock );
/* Free input structure */
free( p_input );
}
/*****************************************************************************
......@@ -254,13 +270,15 @@ static void RunThread( input_thread_t *p_input )
if( InitThread( p_input ) )
{
/* If we failed, wait before we are killed, and exit */
*p_input->pi_status = THREAD_ERROR;
p_input->i_status = THREAD_ERROR;
p_input->b_error = 1;
ErrorThread( p_input );
DestroyThread( p_input );
return;
}
p_input->i_status = THREAD_READY;
/* initialization is complete */
vlc_mutex_lock( &p_input->stream.stream_lock );
p_input->stream.b_changed = 1;
......@@ -507,8 +525,6 @@ static int InitThread( input_thread_t * p_input )
return( -1 );
}
*p_input->pi_status = THREAD_READY;
return( 0 );
}
......@@ -531,11 +547,8 @@ static void ErrorThread( input_thread_t *p_input )
*****************************************************************************/
static void EndThread( input_thread_t * p_input )
{
int * pi_status; /* thread status */
/* Store status */
pi_status = p_input->pi_status;
*pi_status = THREAD_END;
p_input->i_status = THREAD_END;
if( p_main->b_stats )
{
......@@ -605,20 +618,8 @@ static void CloseThread( input_thread_t * p_input )
*****************************************************************************/
static void DestroyThread( input_thread_t * p_input )
{
int * pi_status; /* thread status */
/* Store status */
pi_status = p_input->pi_status;
/* Destroy Mutex locks */
vlc_mutex_destroy( &p_input->stream.control.control_lock );
vlc_mutex_destroy( &p_input->stream.stream_lock );
/* Free input structure */
free( p_input );
/* Update status */
*pi_status = THREAD_OVER;
p_input->i_status = THREAD_OVER;
}
/*****************************************************************************
......
......@@ -4,7 +4,7 @@
* interface, such as command line.
*****************************************************************************
* Copyright (C) 1998-2001 VideoLAN
* $Id: interface.c,v 1.86 2002/01/07 02:12:30 sam Exp $
* $Id: interface.c,v 1.87 2002/01/09 02:01:14 sam Exp $
*
* Authors: Vincent Seguin <seguin@via.ecp.fr>
*
......@@ -128,18 +128,33 @@ static void intf_Manage( intf_thread_t *p_intf )
vlc_mutex_lock( &p_input_bank->lock );
if( p_input_bank->i_count
&& ( p_input_bank->pp_input[0]->b_error
|| p_input_bank->pp_input[0]->b_eof ) )
if( p_input_bank->i_count )
{
intf_WarnMsg( 3, "intf: input thread destroyed" );
input_DestroyThread( p_input_bank->pp_input[0], NULL );
p_input_bank->pp_input[0] = NULL;
int i_input;
input_thread_t *p_input;
for( i_input = 0; i_input < p_input_bank->i_count; i_input++ )
{
p_input = p_input_bank->pp_input[i_input];
if( p_input->i_status == THREAD_OVER )
{
/* XXX: completely stupid ! */
input_DestroyThread( p_input );
p_input_bank->pp_input[i_input] = NULL;
p_input_bank->i_count--;
}
else if( ( p_input->i_status == THREAD_READY
|| p_input->i_status == THREAD_ERROR )
&& ( p_input->b_error || p_input->b_eof ) )
{
input_StopThread( p_input, NULL );
}
}
}
/* If no stream is being played, try to find one */
if( !p_input_bank->i_count && !p_intf->b_die )
else
{
// vlc_mutex_lock( &p_main->p_playlist->change_lock );
......@@ -155,16 +170,22 @@ static void intf_Manage( intf_thread_t *p_intf )
}
else
{
input_thread_t *p_input;
p_main->p_playlist->b_stopped = 0;
p_main->p_playlist->i_mode = PLAYLIST_FORWARD +
main_GetIntVariable( PLAYLIST_LOOP_VAR,
PLAYLIST_LOOP_DEFAULT );
intf_WarnMsg( 3, "intf: creating new input thread" );
p_input_bank->pp_input[0] =
input_CreateThread( &p_main->p_playlist->current, NULL );
p_input = input_CreateThread( &p_main->p_playlist->current,
NULL );
if( p_input != NULL )
{
p_input_bank->pp_input[ p_input_bank->i_count ] = p_input;
p_input_bank->i_count++;
}
}
}
else
{
/* playing has been stopped: we no longer need outputs */
......
/*****************************************************************************
* intf_eject.c: CD/DVD-ROM ejection handling functions
*****************************************************************************
* Copyright (C) 2001, 2002 VideoLAN
* $Id: intf_eject.c,v 1.1 2002/01/09 02:01:14 sam Exp $
*
* Author: Julien Blache <jb@technologeek.org> for the Linux part
* with code taken from the Linux "eject" command
*
* 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.
*****************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <videolan/vlc.h>
#ifdef SYS_LINUX
/* This code could be extended to support CD/DVD-ROM chargers */
# include <linux/version.h>
/* handy macro found in 2.1 kernels, but not in older ones */
# ifndef KERNEL_VERSION
# define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
# endif
# include <sys/types.h>
# include <sys/stat.h>
# include <sys/ioctl.h>
# include <fcntl.h>
# include <sys/ioctl.h>
# include <linux/cdrom.h>
# if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,0)
# include <linux/ucdrom.h>
# endif
# include <sys/mount.h>
# include <scsi/scsi.h>
# include <scsi/sg.h>
# include <scsi/scsi_ioctl.h>
#endif
static int EjectCdrom( int i_fd );
static int EjectScsi ( int i_fd );
/*
* Eject using CDROMEJECT ioctl. Return 0 if successful
*/
static int EjectCdrom( int i_fd )
{
int i_status;
i_status = ioctl( i_fd, CDROMEJECT );
return i_status;
}
/*
* Eject using SCSI commands. Return 0 if successful
*/
static int EjectScsi( int i_fd )
{
int i_status;
struct sdata
{
int inlen;
int outlen;
char cmd[256];
} scsi_cmd;
scsi_cmd.inlen = 0;
scsi_cmd.outlen = 0;
scsi_cmd.cmd[0] = ALLOW_MEDIUM_REMOVAL;
scsi_cmd.cmd[1] = 0;
scsi_cmd.cmd[2] = 0;
scsi_cmd.cmd[3] = 0;
scsi_cmd.cmd[4] = 0;
scsi_cmd.cmd[5] = 0;
i_status = ioctl( i_fd, SCSI_IOCTL_SEND_COMMAND, (void *)&scsi_cmd );
if( i_status != 0 )
{
return 1;
}
scsi_cmd.inlen = 0;
scsi_cmd.outlen = 0;
scsi_cmd.cmd[0] = START_STOP;
scsi_cmd.cmd[1] = 0;
scsi_cmd.cmd[2] = 0;
scsi_cmd.cmd[3] = 0;
scsi_cmd.cmd[4] = 1;
scsi_cmd.cmd[5] = 0;
i_status = ioctl( i_fd, SCSI_IOCTL_SEND_COMMAND, (void *)&scsi_cmd );
if( i_status != 0 )
{
return 1;
}
scsi_cmd.inlen = 0;
scsi_cmd.outlen = 0;
scsi_cmd.cmd[0] = START_STOP;
scsi_cmd.cmd[1] = 0;
scsi_cmd.cmd[2] = 0;
scsi_cmd.cmd[3] = 0;
scsi_cmd.cmd[4] = 2;
scsi_cmd.cmd[5] = 0;
i_status = ioctl( i_fd, SCSI_IOCTL_SEND_COMMAND, (void *)&scsi_cmd );
if( i_status != 0 )
{
return 1;
}
/* Force kernel to reread partition table when new disc inserted */
i_status = ioctl( i_fd, BLKRRPART );
return i_status;
}
/*
* returns 0 on success
* returns 1 on failure
* returns -1 if not implemented
*
* Modify eject_disc() prototype as needed for portability
*/
int intf_Eject( const char *psz_device )
{
int i_ret;
#ifdef SYS_LINUX
int i_fd = 0;
i_fd = open( psz_device, O_RDONLY | O_NONBLOCK );
if( i_fd == -1 )
{
intf_ErrMsg( "intf error: couldn't open device %s", psz_device );
return 1;
}
if( EjectCdrom(i_fd) == 0 )
{
i_ret = 0;
}
else if( EjectScsi(i_fd) == 0 )
{
i_ret = 0;
}
else
{
intf_ErrMsg( "intf error: couldn't eject %s", psz_device );
i_ret = 1;
}
close( i_fd );
#else
i_ret = -1;
#endif
return i_ret;
}
......@@ -2,7 +2,7 @@
* modules.c : Built-in and plugin modules management functions
*****************************************************************************
* Copyright (C) 2001 VideoLAN
* $Id: modules.c,v 1.46 2001/12/30 07:09:56 sam Exp $
* $Id: modules.c,v 1.47 2002/01/09 02:01:14 sam Exp $
*
* Authors: Samuel Hocevar <sam@zoy.org>
* Ethan C. Baldridge <BaldridgeE@cadmus.com>
......@@ -54,6 +54,7 @@
#include "interface.h"
#include "intf_playlist.h"
#include "intf_eject.h"
#include "stream_control.h"
#include "input_ext-intf.h"
......
......@@ -2,7 +2,7 @@
* modules_plugin.h : Plugin management functions used by the core application.
*****************************************************************************
* Copyright (C) 2001 VideoLAN
* $Id: modules_plugin.h,v 1.3 2002/01/07 02:12:30 sam Exp $
* $Id: modules_plugin.h,v 1.4 2002/01/09 02:01:14 sam Exp $
*
* Authors: Samuel Hocevar <sam@zoy.org>
*
......@@ -174,6 +174,7 @@ module_error( void )
(p_symbols)->intf_PlaylistDestroy = intf_PlaylistDestroy; \
(p_symbols)->intf_PlaylistJumpto = intf_PlaylistJumpto; \
(p_symbols)->intf_UrlDecode = intf_UrlDecode; \
(p_symbols)->intf_Eject = intf_Eject; \
(p_symbols)->msleep = msleep; \
(p_symbols)->mdate = mdate; \
(p_symbols)->network_ChannelCreate = network_ChannelCreate; \
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment