/***************************************************************************** * End: terminate logo video thread output method *****************************************************************************/ static void End( vout_thread_t *p_vout ) { vout_sys_t *p_sys = p_vout->p_sys; int i_index; /* Free the fake output buffers we allocated */ for( i_index = I_OUTPUTPICTURES ; i_index ; ) { i_index--; free( PP_OUTPUTPICTURE[ i_index ]->p_data_orig ); } var_DelCallback( p_sys->p_vout, "mouse-x", MouseEvent, p_vout); var_DelCallback( p_sys->p_vout, "mouse-y", MouseEvent, p_vout); if( p_sys->p_vout ) { DEL_CALLBACKS( p_sys->p_vout, SendEvents ); vlc_object_detach( p_sys->p_vout ); vout_Destroy( p_sys->p_vout ); } if( p_sys->p_blend->p_module ) module_Unneed( p_sys->p_blend, p_sys->p_blend->p_module ); vlc_object_detach( p_sys->p_blend ); vlc_object_destroy( p_sys->p_blend ); }
/***************************************************************************** * RemoveAllVout: destroy all the child video output threads *****************************************************************************/ static void RemoveAllVout( vout_thread_t *p_vout ) { while( p_vout->p_sys->i_clones ) { --p_vout->p_sys->i_clones; DEL_CALLBACKS( p_vout->p_sys->pp_vout[p_vout->p_sys->i_clones], SendEvents ); vlc_object_detach( p_vout->p_sys->pp_vout[p_vout->p_sys->i_clones] ); vout_Destroy( p_vout->p_sys->pp_vout[p_vout->p_sys->i_clones] ); } }
/***************************************************************************** * Destroy: destroy Transform video thread output method ***************************************************************************** * Terminate an output method created by TransformCreateOutputMethod *****************************************************************************/ static void Destroy( vlc_object_t *p_this ) { vout_thread_t *p_vout = (vout_thread_t *)p_this; if( p_vout->p_sys->p_vout ) { DEL_CALLBACKS( p_vout->p_sys->p_vout, SendEvents ); vlc_object_detach( p_vout->p_sys->p_vout ); vout_Destroy( p_vout->p_sys->p_vout ); } DEL_PARENT_CALLBACKS( SendEventsToChild ); free( p_vout->p_sys ); }
/***************************************************************************** * RemoveAllVout: destroy all the child video output threads *****************************************************************************/ static void RemoveAllVout( vout_thread_t *p_vout ) { while( p_vout->p_sys->i_vout ) { --p_vout->p_sys->i_vout; if( p_vout->p_sys->pp_vout[ p_vout->p_sys->i_vout ].b_active ) { DEL_CALLBACKS( p_vout->p_sys->pp_vout[ p_vout->p_sys->i_vout ].p_vout, SendEvents ); vlc_object_detach( p_vout->p_sys->pp_vout[ p_vout->p_sys->i_vout ].p_vout ); vout_Destroy( p_vout->p_sys->pp_vout[ p_vout->p_sys->i_vout ].p_vout ); } } }
static mtime_t ObjectGarbageCollector( playlist_t *p_playlist, int i_type, mtime_t destroy_date ) { vlc_object_t *p_obj; if( destroy_date > mdate() ) return destroy_date; if( destroy_date == 0 ) { /* give a little time */ return mdate() + I64C(1000000); } else { while( ( p_obj = vlc_object_find( p_playlist, i_type, FIND_CHILD ) ) ) { if( p_obj->p_parent != (vlc_object_t*)p_playlist ) { /* only first child (ie unused) */ vlc_object_release( p_obj ); break; } if( i_type == VLC_OBJECT_VOUT ) { msg_Dbg( p_playlist, "garbage collector destroying 1 vout" ); vlc_object_detach( p_obj ); vlc_object_release( p_obj ); vout_Destroy( (vout_thread_t *)p_obj ); } else if( i_type == VLC_OBJECT_SOUT ) { vlc_object_release( p_obj ); sout_DeleteInstance( (sout_instance_t*)p_obj ); } } return 0; } }
/***************************************************************************** * RunThread: main playlist thread *****************************************************************************/ static void RunThread ( playlist_t *p_playlist ) { vlc_object_t *p_obj; vlc_value_t val; mtime_t i_vout_destroyed_date = 0; mtime_t i_sout_destroyed_date = 0; playlist_item_t *p_autodelete_item = 0; /* Tell above that we're ready */ vlc_thread_ready( p_playlist ); while( !p_playlist->b_die ) { vlc_mutex_lock( &p_playlist->object_lock ); /* If there is an input, check that it doesn't need to die. */ if( p_playlist->p_input ) { /* This input is dead. Remove it ! */ if( p_playlist->p_input->b_dead ) { input_thread_t *p_input; p_input = p_playlist->p_input; p_playlist->p_input = NULL; /* Release the playlist lock, because we may get stuck * in input_DestroyThread() for some time. */ vlc_mutex_unlock( &p_playlist->object_lock ); /* Destroy input */ input_DestroyThread( p_input ); /* Unlink current input * (_after_ input_DestroyThread for vout garbage collector) */ vlc_object_detach( p_input ); /* Destroy object */ vlc_object_destroy( p_input ); i_vout_destroyed_date = 0; i_sout_destroyed_date = 0; /* Check for autodeletion */ if( p_autodelete_item ) { playlist_ItemDelete( p_autodelete_item ); p_autodelete_item = 0; } continue; } /* This input is dying, let him do */ else if( p_playlist->p_input->b_die ) { ; } /* This input has finished, ask him to die ! */ else if( p_playlist->p_input->b_error || p_playlist->p_input->b_eof ) { input_StopThread( p_playlist->p_input ); if( p_playlist->pp_items[p_playlist->i_index]->b_autodeletion ) { /* This ain't pretty but hey it works */ p_autodelete_item = p_playlist->pp_items[p_playlist->i_index]; p_playlist->pp_items[p_playlist->i_index] = playlist_ItemNew( p_playlist, p_autodelete_item->input.psz_uri, 0); vlc_mutex_unlock( &p_playlist->object_lock ); p_playlist->i_status = PLAYLIST_STOPPED; playlist_Delete( p_playlist, p_playlist->i_index ); p_playlist->i_status = PLAYLIST_RUNNING; vlc_mutex_lock( &p_playlist->object_lock ); } SkipItem( p_playlist, 1 ); vlc_mutex_unlock( &p_playlist->object_lock ); continue; } else if( p_playlist->p_input->i_state != INIT_S ) { vlc_mutex_unlock( &p_playlist->object_lock ); i_vout_destroyed_date = ObjectGarbageCollector( p_playlist, VLC_OBJECT_VOUT, i_vout_destroyed_date ); i_sout_destroyed_date = ObjectGarbageCollector( p_playlist, VLC_OBJECT_SOUT, i_sout_destroyed_date ); vlc_mutex_lock( &p_playlist->object_lock ); } } else if( p_playlist->i_status != PLAYLIST_STOPPED ) { /* Start another input. Let's check if that item has * been forced. In that case, we override random (by not skipping) * and play-and-stop */ vlc_bool_t b_forced; var_Get( p_playlist, "prevent-skip", &val ); b_forced = val.b_bool; if( val.b_bool == VLC_FALSE ) { SkipItem( p_playlist, 0 ); } /* Reset forced status */ val.b_bool = VLC_FALSE; var_Set( p_playlist, "prevent-skip", val ); /* Check for play-and-stop */ var_Get( p_playlist, "play-and-stop", &val ); if( val.b_bool == VLC_FALSE || b_forced == VLC_TRUE ) { PlayItem( p_playlist ); } } else if( p_playlist->i_status == PLAYLIST_STOPPED ) { vlc_mutex_unlock( &p_playlist->object_lock ); i_sout_destroyed_date = ObjectGarbageCollector( p_playlist, VLC_OBJECT_SOUT, mdate() ); i_vout_destroyed_date = ObjectGarbageCollector( p_playlist, VLC_OBJECT_VOUT, mdate() ); vlc_mutex_lock( &p_playlist->object_lock ); } vlc_mutex_unlock( &p_playlist->object_lock ); msleep( INTF_IDLE_SLEEP ); } /* If there is an input, kill it */ while( 1 ) { vlc_mutex_lock( &p_playlist->object_lock ); if( p_playlist->p_input == NULL ) { vlc_mutex_unlock( &p_playlist->object_lock ); break; } if( p_playlist->p_input->b_dead ) { input_thread_t *p_input; /* Unlink current input */ p_input = p_playlist->p_input; p_playlist->p_input = NULL; vlc_mutex_unlock( &p_playlist->object_lock ); /* Destroy input */ input_DestroyThread( p_input ); /* Unlink current input (_after_ input_DestroyThread for vout * garbage collector)*/ vlc_object_detach( p_input ); /* Destroy object */ vlc_object_destroy( p_input ); continue; } else if( p_playlist->p_input->b_die ) { /* This input is dying, leave him alone */ ; } else if( p_playlist->p_input->b_error || p_playlist->p_input->b_eof ) { input_StopThread( p_playlist->p_input ); vlc_mutex_unlock( &p_playlist->object_lock ); continue; } else { p_playlist->p_input->b_eof = 1; } vlc_mutex_unlock( &p_playlist->object_lock ); msleep( INTF_IDLE_SLEEP ); } /* close all remaining sout */ while( ( p_obj = vlc_object_find( p_playlist, VLC_OBJECT_SOUT, FIND_CHILD ) ) ) { vlc_object_release( p_obj ); sout_DeleteInstance( (sout_instance_t*)p_obj ); } /* close all remaining vout */ while( ( p_obj = vlc_object_find( p_playlist, VLC_OBJECT_VOUT, FIND_CHILD ) ) ) { vlc_object_detach( p_obj ); vlc_object_release( p_obj ); vout_Destroy( (vout_thread_t *)p_obj ); } }
/***************************************************************************** * Open: open a scope effect plugin *****************************************************************************/ static int Open( vlc_object_t *p_this ) { aout_filter_t *p_filter = (aout_filter_t *)p_this; aout_filter_sys_t *p_sys; goom_thread_t *p_thread; vlc_value_t width, height; if ( p_filter->input.i_format != VLC_FOURCC('f','l','3','2' ) || p_filter->output.i_format != VLC_FOURCC('f','l','3','2') ) { msg_Warn( p_filter, "Bad input or output format" ); return VLC_EGENERIC; } if ( !AOUT_FMTS_SIMILAR( &p_filter->input, &p_filter->output ) ) { msg_Warn( p_filter, "input and output formats are not similar" ); return VLC_EGENERIC; } p_filter->pf_do_work = DoWork; p_filter->b_in_place = 1; /* Allocate structure */ p_sys = p_filter->p_sys = malloc( sizeof( aout_filter_sys_t ) ); /* Create goom thread */ p_sys->p_thread = p_thread = vlc_object_create( p_filter, sizeof( goom_thread_t ) ); vlc_object_attach( p_thread, p_this ); var_Create( p_thread, "goom-width", VLC_VAR_INTEGER|VLC_VAR_DOINHERIT ); var_Get( p_thread, "goom-width", &width ); var_Create( p_thread, "goom-height", VLC_VAR_INTEGER|VLC_VAR_DOINHERIT ); var_Get( p_thread, "goom-height", &height ); p_thread->p_vout = vout_Request( p_filter, NULL, width.i_int, height.i_int, VLC_FOURCC('R','V','3','2'), VOUT_ASPECT_FACTOR * width.i_int/height.i_int ); if( p_thread->p_vout == NULL ) { msg_Err( p_filter, "no suitable vout module" ); vlc_object_detach( p_thread ); vlc_object_destroy( p_thread ); free( p_sys ); return VLC_EGENERIC; } vlc_mutex_init( p_filter, &p_thread->lock ); vlc_cond_init( p_filter, &p_thread->wait ); p_thread->i_blocks = 0; aout_DateInit( &p_thread->date, p_filter->output.i_rate ); aout_DateSet( &p_thread->date, 0 ); p_thread->i_channels = aout_FormatNbChannels( &p_filter->input ); p_thread->psz_title = TitleGet( VLC_OBJECT( p_filter ) ); if( vlc_thread_create( p_thread, "Goom Update Thread", Thread, VLC_THREAD_PRIORITY_LOW, VLC_FALSE ) ) { msg_Err( p_filter, "cannot lauch goom thread" ); vout_Destroy( p_thread->p_vout ); vlc_mutex_destroy( &p_thread->lock ); vlc_cond_destroy( &p_thread->wait ); if( p_thread->psz_title ) free( p_thread->psz_title ); vlc_object_detach( p_thread ); vlc_object_destroy( p_thread ); free( p_sys ); return VLC_EGENERIC; } return VLC_SUCCESS; }