Commit 03d925fd authored by Sam Hocevar's avatar Sam Hocevar

 . moved the playlist handling from input/input.c to interface/interface.c
 . fixed a few warnings at compile-time
 . fixed sound channel selection in playlist mode
 . added a color message in the plugin bank because on peut bien d�conner
   cinq minutes, quand-m�me
 . we now spawn a new input thread for each file
 . added a missing pf_close() because it's always cool to close files
   after we read them
parent e754b097
......@@ -3,7 +3,7 @@
* Collection of useful common types and macros definitions
*****************************************************************************
* Copyright (C) 1998, 1999, 2000 VideoLAN
* $Id: common.h,v 1.27 2001/02/08 04:43:27 sam Exp $
* $Id: common.h,v 1.28 2001/02/08 07:24:25 sam Exp $
*
* Authors: Samuel Hocevar <sam@via.ecp.fr>
* Vincent Seguin <seguin@via.ecp.fr>
......@@ -79,10 +79,12 @@ struct plugin_info_s;
typedef struct plugin_bank_s * p_plugin_bank_t;
typedef struct plugin_info_s * p_plugin_info_t;
/* Playlist */
/* Plugins */
struct playlist_s;
struct playlist_item_s;
typedef struct playlist_s * p_playlist_t;
typedef struct playlist_item_s * p_playlist_item_t;
/* Interface */
struct intf_thread_s;
......
......@@ -4,7 +4,7 @@
* control the pace of reading.
*****************************************************************************
* Copyright (C) 1999, 2000 VideoLAN
* $Id: input_ext-intf.h,v 1.14 2001/02/08 04:43:27 sam Exp $
* $Id: input_ext-intf.h,v 1.15 2001/02/08 07:24:25 sam Exp $
*
* Authors:
*
......@@ -297,8 +297,9 @@ typedef struct input_config_s
/*****************************************************************************
* Prototypes
*****************************************************************************/
struct input_thread_s * input_CreateThread( int *pi_status );
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_Play( struct input_thread_s * );
void input_Play ( struct input_thread_s * );
void input_Forward( struct input_thread_s *, int );
......@@ -3,7 +3,7 @@
*****************************************************************************
* Copyright (C) 1999, 2000 VideoLAN
*
* Authors:
* Authors: 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
......
......@@ -68,12 +68,12 @@ typedef struct function_list_s
/* Input plugin */
struct
{
int ( * pf_init ) ( struct input_thread_s * );
void ( * pf_open ) ( struct input_thread_s * );
void ( * pf_close ) ( struct input_thread_s * );
void ( * pf_init ) ( struct input_thread_s * );
void ( * pf_open ) ( struct input_thread_s * );
void ( * pf_close )( struct input_thread_s * );
void ( * pf_end ) ( struct input_thread_s * );
void ( * pf_read ) ( struct input_thread_s *,
int ( * pf_read ) ( struct input_thread_s *,
struct data_packet_s *
pp_packets[] );
void ( * pf_demux )( struct input_thread_s *,
......@@ -81,8 +81,8 @@ typedef struct function_list_s
struct data_packet_s * ( * pf_new_packet ) ( void *, size_t );
struct pes_packet_s * ( * pf_new_pes ) ( void * );
void ( * pf_delete_packet ) ( struct data_packet_s * );
void ( * pf_delete_pes ) ( struct pes_packet_s * );
void ( * pf_delete_packet ) ( void *, struct data_packet_s * );
void ( * pf_delete_pes ) ( void *, struct pes_packet_s * );
int ( * pf_rewind ) ( struct input_thread_s * );
int ( * pf_seek ) ( struct input_thread_s *, off_t );
......
......@@ -2,7 +2,7 @@
* input_ps.c: PS demux and packet management
*****************************************************************************
* Copyright (C) 1998, 1999, 2000 VideoLAN
* $Id: input_ps.c,v 1.1 2001/02/08 04:43:27 sam Exp $
* $Id: input_ps.c,v 1.2 2001/02/08 07:24:25 sam Exp $
*
* Authors:
*
......@@ -210,21 +210,27 @@ static void PSInit( input_thread_t * p_input )
case MPEG1_AUDIO_ES:
case MPEG2_AUDIO_ES:
if( main_GetIntVariable( INPUT_DVD_AUDIO_VAR, 0 )
== REQUESTED_MPEG
&& main_GetIntVariable( INPUT_DVD_CHANNEL_VAR, 0 )
if( main_GetIntVariable( INPUT_DVD_CHANNEL_VAR, 0 )
== (p_es->i_id & 0x1F) )
switch( main_GetIntVariable( INPUT_DVD_AUDIO_VAR, 0 ) )
{
case 0:
main_PutIntVariable( INPUT_DVD_CHANNEL_VAR,
REQUESTED_MPEG );
case REQUESTED_MPEG:
input_SelectES( p_input, p_es );
}
break;
case AC3_AUDIO_ES:
if( main_GetIntVariable( INPUT_DVD_AUDIO_VAR, 0 )
== REQUESTED_AC3
&& main_GetIntVariable( INPUT_DVD_CHANNEL_VAR, 0 )
if( main_GetIntVariable( INPUT_DVD_CHANNEL_VAR, 0 )
== ((p_es->i_id & 0xF00) >> 8) )
switch( main_GetIntVariable( INPUT_DVD_AUDIO_VAR, 0 ) )
{
case 0:
main_PutIntVariable( INPUT_DVD_CHANNEL_VAR,
REQUESTED_AC3 );
case REQUESTED_AC3:
input_SelectES( p_input, p_es );
}
break;
......
......@@ -4,7 +4,7 @@
* decoders.
*****************************************************************************
* Copyright (C) 1998, 1999, 2000 VideoLAN
* $Id: input.c,v 1.75 2001/02/08 04:43:27 sam Exp $
* $Id: input.c,v 1.76 2001/02/08 07:24:25 sam Exp $
*
* Authors:
*
......@@ -62,8 +62,7 @@
* Local prototypes
*****************************************************************************/
static void RunThread ( input_thread_t *p_input );
static void InitLoop ( input_thread_t *p_input );
static void StopLoop ( input_thread_t *p_input );
static void InitThread ( input_thread_t *p_input );
static void ErrorThread ( input_thread_t *p_input );
static void EndThread ( input_thread_t *p_input );
......@@ -75,7 +74,7 @@ static void EndThread ( input_thread_t *p_input );
* If pi_status is NULL, then the function will block until the thread is ready.
* If not, it will be updated using one of the THREAD_* constants.
*****************************************************************************/
input_thread_t *input_CreateThread ( int *pi_status )
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 */
......@@ -92,6 +91,11 @@ input_thread_t *input_CreateThread ( int *pi_status )
/* Initialize thread properties */
p_input->b_die = 0;
p_input->b_error = 0;
p_input->b_eof = 0;
/* 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;
......@@ -132,7 +136,7 @@ input_thread_t *input_CreateThread ( int *pi_status )
{
msleep( THREAD_SLEEP );
} while( (i_status != THREAD_READY) && (i_status != THREAD_ERROR)
&& (i_status != THREAD_FATAL) && (i_status != THREAD_OVER) );
&& (i_status != THREAD_FATAL) );
if( i_status != THREAD_READY )
{
return( NULL );
......@@ -178,64 +182,49 @@ static void RunThread( input_thread_t *p_input )
data_packet_t * pp_packets[INPUT_READ_ONCE];
int i_error, i;
*p_input->pi_status = THREAD_READY;
InitThread( p_input );
while( !p_input->b_die && !p_input->b_error )
while( !p_input->b_die && !p_input->b_error && !p_input->b_eof )
{
InitLoop( p_input );
if( p_input->b_die || p_input->b_error )
{
break;
}
while( !p_input->b_die && !p_input->b_error && !p_input->b_eof )
{
#ifdef STATS
p_input->c_loops++;
p_input->c_loops++;
#endif
vlc_mutex_lock( &p_input->stream.control.control_lock );
if( p_input->stream.control.i_status == BACKWARD_S
&& p_input->pf_rewind != NULL )
{
p_input->pf_rewind( p_input );
/* FIXME: probably don't do it every loop, but when ? */
}
vlc_mutex_unlock( &p_input->stream.control.control_lock );
vlc_mutex_lock( &p_input->stream.control.control_lock );
if( p_input->stream.control.i_status == BACKWARD_S
&& p_input->pf_rewind != NULL )
{
p_input->pf_rewind( p_input );
/* FIXME: probably don't do it every loop, but when ? */
}
vlc_mutex_unlock( &p_input->stream.control.control_lock );
i_error = p_input->pf_read( p_input, pp_packets );
i_error = p_input->pf_read( p_input, pp_packets );
/* Demultiplex read packets. */
for( i = 0; i < INPUT_READ_ONCE && pp_packets[i] != NULL; i++ )
{
p_input->pf_demux( p_input, pp_packets[i] );
}
/* Demultiplex read packets. */
for( i = 0; i < INPUT_READ_ONCE && pp_packets[i] != NULL; i++ )
if( i_error )
{
if( i_error == 1 )
{
p_input->pf_demux( p_input, pp_packets[i] );
/* End of file - we do not set b_die because only the
* interface is allowed to do so. */
intf_WarnMsg( 1, "End of file reached" );
p_input->b_eof = 1;
}
if( i_error )
else
{
if( i_error == 1 )
{
/* End of file */
intf_WarnMsg( 1, "End of file reached" );
/* FIXME: don't treat that as an error */
p_input->b_eof = 1;
}
else
{
p_input->b_error = 1;
}
p_input->b_error = 1;
}
}
/* Free all ES and destroy all decoder threads */
input_EndStream( p_input );
StopLoop( p_input );
}
if( p_input->b_error )
if( p_input->b_error || p_input->b_eof )
{
ErrorThread( p_input );
}
......@@ -245,22 +234,10 @@ static void RunThread( input_thread_t *p_input )
}
/*****************************************************************************
* InitLoop: init the input loop
* InitThread: init the input Thread
*****************************************************************************/
static void InitLoop( input_thread_t * p_input )
static void InitThread( input_thread_t * p_input )
{
playlist_Next( p_main->p_playlist );
if( p_main->p_playlist->i_index == -1 )
{
/* FIXME: wait for user to add stuff to playlist ? */
/* FIXME II: we shouldn't set b_error but rather b_die */
intf_Msg( "playlist: end" );
p_input->b_error = 1;
return;
}
p_input->p_source = p_main->p_playlist->current.psz_name;
#ifdef STATS
/* Initialize statistics */
......@@ -296,40 +273,18 @@ static void InitLoop( input_thread_t * p_input )
p_input->pf_seek = f.pf_seek;
#undef f
p_input->b_eof = 0;
p_input->pf_open( p_input );
if( p_input->b_error )
{
module_Unneed( p_main->p_module_bank, p_input->p_input_module );
return;
}
p_input->pf_init( p_input );
return;
}
/*****************************************************************************
* StopLoop: stop the input loop
*****************************************************************************/
static void StopLoop( input_thread_t * p_input )
{
#ifdef STATS
else
{
struct tms cpu_usage;
times( &cpu_usage );
intf_Msg("input stats: cpu usage (user: %d, system: %d)",
cpu_usage.tms_utime, cpu_usage.tms_stime);
p_input->pf_init( p_input );
}
#endif
/* Free demultiplexer's data */
p_input->pf_end( p_input );
/* Release modules */
module_Unneed( p_main->p_module_bank, p_input->p_input_module );
*p_input->pi_status = THREAD_READY;
}
/*****************************************************************************
......@@ -357,6 +312,28 @@ static void EndThread( input_thread_t * p_input )
pi_status = p_input->pi_status;
*pi_status = THREAD_END;
#ifdef STATS
{
struct tms cpu_usage;
times( &cpu_usage );
intf_Msg("input stats: cpu usage (user: %d, system: %d)",
cpu_usage.tms_utime, cpu_usage.tms_stime);
}
#endif
/* Free all ES and destroy all decoder threads */
input_EndStream( p_input );
/* Close stream */
p_input->pf_close( p_input );
/* Free demultiplexer's data */
p_input->pf_end( p_input );
/* Release modules */
module_Unneed( p_main->p_module_bank, p_input->p_input_module );
/* Destroy Mutex locks */
vlc_mutex_destroy( &p_input->stream.control.control_lock );
vlc_mutex_destroy( &p_input->stream.stream_lock );
......
......@@ -43,7 +43,7 @@
*****************************************************************************/
void input_Play( input_thread_t * p_input )
{
intf_Msg( "Playing normally" );
intf_Msg( "input: playing at normal rate" );
vlc_mutex_lock( &p_input->stream.stream_lock );
p_input->stream.i_new_status = PLAYING_S;
vlc_mutex_unlock( &p_input->stream.stream_lock );
......@@ -56,12 +56,24 @@ void input_Play( input_thread_t * p_input )
*****************************************************************************/
void input_Forward( input_thread_t * p_input, int i_rate )
{
if ( i_rate > 1000 )
intf_Msg( "Forward enabled at 1/%d",i_rate/1000 );
if ( i_rate > DEFAULT_RATE )
{
intf_Msg( "input: playing at 1:%i slow motion", i_rate / 1000 );
}
else if( i_rate < DEFAULT_RATE )
{
intf_Msg( "input: playing at %i:1 fast forward", 1000 / i_rate );
}
else
intf_Msg( "Forward enabled at %d/1",1000/i_rate );
{
/* Not very joli, but this is going to disappear soon anyway */
input_Play( p_input );
return;
}
vlc_mutex_lock( &p_input->stream.stream_lock );
p_input->stream.i_new_status = FORWARD_S;
p_input->stream.i_new_rate = i_rate;
vlc_mutex_unlock( &p_input->stream.stream_lock );
}
......@@ -182,36 +182,53 @@ void intf_Run( intf_thread_t *p_intf )
/* Flush messages before spawning input */
intf_FlushMsg();
p_intf->p_input = input_CreateThread( NULL );
/* Main loop */
while(!p_intf->b_die && (p_intf->p_input != NULL) )
while( !p_intf->b_die )
{
/* Flush waiting messages */
intf_FlushMsg();
/* Manage specific interface */
p_intf->p_sys_manage( p_intf );
/* Select the next playlist item */
playlist_Next( p_main->p_playlist );
/* Manage module bank */
module_ManageBank( p_main->p_module_bank );
/* Check attached threads status */
if( (p_intf->p_vout != NULL) && p_intf->p_vout->b_error )
if( p_main->p_playlist->i_index == -1 )
{
/* FIXME: add aout error detection ?? */
/* FIXME: wait for user to add stuff to playlist ? */
p_intf->b_die = 1;
return;
}
if( (p_intf->p_input != NULL) && p_intf->p_input->b_error )
p_intf->p_input =
input_CreateThread( &p_main->p_playlist->current, NULL );
/* Main loop */
while( !p_intf->b_die && (p_intf->p_input != NULL) )
{
input_DestroyThread( p_intf->p_input, NULL );
p_intf->p_input = NULL;
intf_DbgMsg("Input thread destroyed");
}
/* Flush waiting messages */
intf_FlushMsg();
/* Manage specific interface */
p_intf->p_sys_manage( p_intf );
/* Manage module bank */
module_ManageBank( p_main->p_module_bank );
/* Sleep to avoid using all CPU - since some interfaces needs to access
* keyboard events, a 100ms delay is a good compromise */
msleep( INTF_IDLE_SLEEP );
/* Check attached threads status */
if( (p_intf->p_vout != NULL) && p_intf->p_vout->b_error )
{
/* FIXME: add aout error detection ?? */
p_intf->b_die = 1;
}
if( ( p_intf->p_input != NULL ) &&
( p_intf->p_input->b_error || p_intf->p_input->b_eof ) )
{
input_DestroyThread( p_intf->p_input, NULL );
p_intf->p_input = NULL;
intf_DbgMsg("Input thread destroyed");
}
/* Sleep to avoid using all CPU - since some interfaces needs
* to access keyboard events, a 100ms delay is a good compromise */
msleep( INTF_IDLE_SLEEP );
}
}
}
......
......@@ -3,7 +3,7 @@
*****************************************************************************
* Copyright (C) 1999, 2000 VideoLAN
*
* Authors:
* Authors: 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
......@@ -46,7 +46,8 @@ playlist_t * playlist_Create ( void )
p_playlist = malloc( sizeof( playlist_t ) );
if( !p_playlist )
{
intf_ErrMsg("playlist error: %s", strerror( ENOMEM ) );
intf_ErrMsg( "intf error: couldn't create playlist (%s)",
strerror( ENOMEM ) );
return( NULL );
}
......@@ -71,7 +72,7 @@ void playlist_Init ( playlist_t * p_playlist )
/* The playlist is empty */
p_playlist->p_item = NULL;
intf_Msg("playlist: playlist created");
intf_Msg("intf: playlist initialized");
}
int playlist_Add( playlist_t * p_playlist, int i_pos, char * psz_item )
......@@ -87,7 +88,7 @@ int playlist_Add( playlist_t * p_playlist, int i_pos, char * psz_item )
}
else if( i_pos > p_playlist->i_size )
{
intf_ErrMsg( "playlist error: inserting item beyond playlist size" );
intf_ErrMsg( "intf error: inserting item beyond playlist size" );
vlc_mutex_unlock( &p_playlist->change_lock );
return( -1 );
}
......@@ -110,7 +111,7 @@ int playlist_Add( playlist_t * p_playlist, int i_pos, char * psz_item )
p_item->i_status = 0;
p_item->psz_name = strdup( psz_item );
intf_Msg( "playlist: added %s", psz_item );
intf_WarnMsg( 1, "intf: added %s to playlist", psz_item );
vlc_mutex_unlock( &p_playlist->change_lock );
......@@ -146,7 +147,7 @@ int playlist_Delete( playlist_t * p_playlist, int i_pos )
if( !p_playlist->i_size || i_pos >= p_playlist->i_size )
{
intf_ErrMsg( "playlist error: deleting item beyond playlist size" );
intf_ErrMsg( "intf error: deleting item beyond playlist size" );
vlc_mutex_unlock( &p_playlist->change_lock );
return( -1 );
}
......@@ -165,7 +166,7 @@ int playlist_Delete( playlist_t * p_playlist, int i_pos )
p_playlist->p_item = realloc( p_playlist->p_item,
p_playlist->i_size * sizeof( playlist_item_t ) );
intf_Msg( "playlist: removed %s", psz_name );
intf_WarnMsg( 1, "intf: removed %s from playlist", psz_name );
/* Delete the item */
free( psz_name );
......@@ -193,7 +194,7 @@ void playlist_Destroy( playlist_t * p_playlist )
free( p_playlist );
intf_Msg("playlist: playlist destroyed");
intf_Msg("intf: playlist destroyed");
}
static void NextItem( playlist_t * p_playlist )
......
......@@ -76,7 +76,6 @@ plugin_bank_t * bank_Create( void )
}
p_bank->i_plugin_count = MAX_PLUGIN_COUNT;
intf_Msg("plugin: bank initialized");
return( p_bank );
}
......@@ -106,8 +105,9 @@ void bank_Init( plugin_bank_t * p_bank )
/* Dummy plugin */
SEEK_PLUGIN( "dummy" );
#undef SEEK_PLUGIN
intf_Msg("plugin: plugin bank initialized [OBSOLETE]");
}
void bank_Destroy( plugin_bank_t * p_bank )
......
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