#include <vlc_interface.h>
#include <vlc_url.h>
#include <vlc_charset.h>
-#include <vlc_playlist.h>
#ifdef HAVE_SYS_STAT_H
# include <sys/stat.h>
static input_thread_t * Create ( vlc_object_t *, input_item_t *,
const char *, bool, sout_instance_t * );
static int Init ( input_thread_t *p_input );
-static void Error ( input_thread_t *p_input );
+static void WaitDie ( input_thread_t *p_input );
static void End ( input_thread_t *p_input );
static void MainLoop( input_thread_t *p_input );
* - seekable (if you can seek, it doesn't say if 'bar display' has be shown
* or not, for that check position != 0.0)
* - can-pause
+ * - teletext-es to get the index of spu track that is teletext --1 if no teletext)
* * For intf callback upon changes
* - intf-change
* - rate-change for when playback rate changes
p_input = vlc_custom_create( p_parent, sizeof( *p_input ),
VLC_OBJECT_INPUT, input_name );
if( p_input == NULL )
- {
- msg_Err( p_parent, "out of memory" );
return NULL;
- }
/* Construct a nice name for the input timer */
char psz_timer_name[255];
char * psz_name = input_item_GetName( p_item );
snprintf( psz_timer_name, sizeof(psz_timer_name),
"input launching for '%s'", psz_name );
+
+ msg_Dbg( p_input, "Creating an input for '%s'", psz_name);
+
free( psz_name );
/* Start a timer to mesure how long it takes
vlc_event_manager_t * p_em = &p_input->p->event_manager;
vlc_event_manager_init_with_vlc_object( p_em, p_input );
vlc_event_manager_register_event_type( p_em, vlc_InputStateChanged );
+ vlc_event_manager_register_event_type( p_em, vlc_InputSelectedStreamChanged );
/* Init Common fields */
p_input->b_eof = false;
memset( &p_input->p->counters, 0, sizeof( p_input->p->counters ) );
vlc_mutex_init( &p_input->p->counters.counters_lock );
- /* Attach only once we are ready */
- vlc_object_attach( p_input, p_parent );
-
/* Set the destructor when we are sure we are initialized */
vlc_object_set_destructor( p_input, (vlc_destructor_t)Destructor );
+ /* Attach only once we are ready */
+ vlc_object_attach( p_input, p_parent );
+
return p_input;
}
{
input_thread_private_t *priv = p_input->p;
+#ifndef NDEBUG
+ char * psz_name = input_item_GetName( p_input->p->input.p_item );
+ msg_Dbg( p_input, "Destroying the input for '%s'", psz_name);
+ free( psz_name );
+#endif
+
vlc_event_manager_fini( &p_input->p->event_manager );
stats_TimerDump( p_input, STATS_TIMER_INPUT_LAUNCHING );
*
* \param the input thread to stop
*/
-void input_StopThread( input_thread_t *p_input )
+static void ObjectKillChildrens( input_thread_t *p_input, vlc_object_t *p_obj )
{
vlc_list_t *p_list;
int i;
- /* Set die for input */
- vlc_object_kill( p_input );
- /* FIXME: seems to be duplicated in ControlPush(INPUT_CONTROL_SET_DIE) */
-
- /* We cannot touch p_input fields directly (we come from another thread),
- * so use the vlc_object_find way, it's perfectly safe */
-
- /* Set die for all access */
- p_list = vlc_list_find( p_input, VLC_OBJECT_ACCESS, FIND_CHILD );
- for( i = 0; i < p_list->i_count; i++ )
- {
- vlc_object_kill( p_list->p_values[i].p_object );
- }
- vlc_list_release( p_list );
+ if( p_obj->i_object_type == VLC_OBJECT_VOUT ||
+ p_obj->i_object_type == VLC_OBJECT_AOUT ||
+ p_obj == VLC_OBJECT(p_input->p->p_sout) )
+ return;
- /* Set die for all stream */
- p_list = vlc_list_find( p_input, VLC_OBJECT_STREAM, FIND_CHILD );
- for( i = 0; i < p_list->i_count; i++ )
- {
- vlc_object_kill( p_list->p_values[i].p_object );
- }
- vlc_list_release( p_list );
+ vlc_object_kill( p_obj );
- /* Set die for all demux */
- p_list = vlc_list_find( p_input, VLC_OBJECT_DEMUX, FIND_CHILD );
+ p_list = vlc_list_children( p_obj );
for( i = 0; i < p_list->i_count; i++ )
- {
- vlc_object_kill( p_list->p_values[i].p_object );
- }
+ ObjectKillChildrens( p_input, p_list->p_values[i].p_object );
vlc_list_release( p_list );
+}
+void input_StopThread( input_thread_t *p_input )
+{
+ /* Set die for input and ALL of this childrens (even (grand-)grand-childrens)
+ * It is needed here even if it is done in INPUT_CONTROL_SET_DIE handler to
+ * unlock the control loop */
+ ObjectKillChildrens( p_input, VLC_OBJECT(p_input) );
input_ControlPush( p_input, INPUT_CONTROL_SET_DIE, NULL );
}
/* If we failed, wait before we are killed, and exit */
p_input->b_error = true;
- /* FIXME: we don't want to depend on the playlist */
- playlist_t * p_playlist = vlc_object_find( p_input,
- VLC_OBJECT_PLAYLIST, FIND_PARENT );
- if( p_playlist )
- {
- playlist_Signal( p_playlist );
- vlc_object_release( p_playlist );
- }
-
- Error( p_input );
+ WaitDie( p_input );
/* Tell we're dead */
p_input->b_dead = true;
/* We have finished */
p_input->b_eof = true;
- playlist_Signal( libvlc_priv (p_input->p_libvlc)->p_playlist );
+ input_ChangeState( p_input, END_S );
}
/* Wait until we are asked to die */
if( !p_input->b_die )
{
- Error( p_input );
+ WaitDie( p_input );
}
/* Clean up */
{
/* End of file - we do not set b_die because only the
* playlist is allowed to do so. */
- input_ChangeState( p_input, END_S );
msg_Dbg( p_input, "EOF reached" );
p_input->p->input.b_eof = true;
}
}
/*****************************************************************************
- * Error: RunThread() error loop
+ * WaitDie: Wait until we are asked to die.
*****************************************************************************
* This function is called when an error occurred during thread main's loop.
*****************************************************************************/
-static void Error( input_thread_t *p_input )
+static void WaitDie( input_thread_t *p_input )
{
- input_ChangeState( p_input, ERROR_S );
+ input_ChangeState( p_input, p_input->b_error ? ERROR_S : END_S );
while( !p_input->b_die )
{
/* Sleep a while */
input_ChangeState( p_input, END_S );
/* Clean control variables */
- input_ControlVarClean( p_input );
+ input_ControlVarStop( p_input );
/* Clean up master */
InputSourceClean( &p_input->p->input );
{
case INPUT_CONTROL_SET_DIE:
msg_Dbg( p_input, "control: stopping input" );
- /* Mark all submodules to die */
- if( p_input->p->input.p_access )
- vlc_object_kill( p_input->p->input.p_access );
- if( p_input->p->input.p_stream )
- vlc_object_kill( p_input->p->input.p_stream );
- vlc_object_kill( p_input->p->input.p_demux );
- vlc_object_kill( p_input );
+ /* Mark all submodules to die */
+ ObjectKillChildrens( p_input, VLC_OBJECT(p_input) );
break;
case INPUT_CONTROL_SET_POSITION:
b_force_update = true;
/* Switch to play */
- p_input->i_state = PLAYING_S;
- val.i_int = PLAYING_S;
- var_Change( p_input, "state", VLC_VAR_SETVALUE, &val, NULL );
+ input_ChangeStateWithVarCallback( p_input, PLAYING_S, false );
/* */
if( !i_ret )
else if( val.i_int == PAUSE_S && p_input->i_state == PLAYING_S &&
p_input->p->b_can_pause )
{
- int i_ret;
+ int i_ret, state;
if( p_input->p->input.p_access )
i_ret = access_Control( p_input->p->input.p_access,
ACCESS_SET_PAUSE_STATE, true );
if( i_ret )
{
msg_Warn( p_input, "cannot set pause state" );
- val.i_int = p_input->i_state;
+ state = p_input->i_state;
}
else
{
- val.i_int = PAUSE_S;
+ state = PAUSE_S;
}
/* Switch to new state */
- p_input->i_state = val.i_int;
- var_Change( p_input, "state", VLC_VAR_SETVALUE, &val, NULL );
+ input_ChangeStateWithVarCallback( p_input, state, false );
/* */
if( !i_ret )
b_force_update = true;
/* Correct "state" value */
- val.i_int = p_input->i_state;
- var_Change( p_input, "state", VLC_VAR_SETVALUE, &val, NULL );
+ input_ChangeStateWithVarCallback( p_input, p_input->i_state, false );
}
else if( val.i_int != PLAYING_S && val.i_int != PAUSE_S )
{
return true;
}
+
+/*****************************************************************************
+ * input_get_event_manager
+ *****************************************************************************/
+vlc_event_manager_t *
+input_get_event_manager( input_thread_t *p_input )
+{
+ return &p_input->p->event_manager;
+}