Commit 94324e9f authored by Rémi Denis-Courmont's avatar Rémi Denis-Courmont

CMML: do not (ab)use the interface subsystem

Only the core can safely destroy an interface, otherwise, the other
component could race against the core in joining the interface thread
or destroying the interface object.
The fire and forget status of interfaces is by design, and is expected
by -at least- the VLC binary, the NT service plugin and the Remote
Control interface plugin. Anyway, that is pretty the only point of
creating an interface instead of a private thread/object.
parent 9e8ea4a6
...@@ -42,14 +42,6 @@ ...@@ -42,14 +42,6 @@
#undef CMML_DEBUG #undef CMML_DEBUG
/*****************************************************************************
* decoder_sys_t : decoder descriptor
*****************************************************************************/
struct decoder_sys_t
{
intf_thread_t * p_intf;
};
/***************************************************************************** /*****************************************************************************
* Local prototypes * Local prototypes
*****************************************************************************/ *****************************************************************************/
...@@ -63,8 +55,8 @@ static void ParseText ( decoder_t *, block_t * ); ...@@ -63,8 +55,8 @@ static void ParseText ( decoder_t *, block_t * );
/***************************************************************************** /*****************************************************************************
* Exported prototypes * Exported prototypes
*****************************************************************************/ *****************************************************************************/
int OpenIntf ( vlc_object_t * ); decoder_sys_t *OpenIntf( vlc_object_t * );
void CloseIntf ( vlc_object_t * ); void CloseIntf( decoder_sys_t * );
/***************************************************************************** /*****************************************************************************
* Module descriptor. * Module descriptor.
...@@ -91,17 +83,12 @@ static int OpenDecoder( vlc_object_t *p_this ) ...@@ -91,17 +83,12 @@ static int OpenDecoder( vlc_object_t *p_this )
{ {
decoder_t *p_dec = (decoder_t*)p_this; decoder_t *p_dec = (decoder_t*)p_this;
input_thread_t * p_input; input_thread_t * p_input;
decoder_sys_t *p_sys;
if( p_dec->fmt_in.i_codec != VLC_CODEC_CMML ) if( p_dec->fmt_in.i_codec != VLC_CODEC_CMML )
return VLC_EGENERIC; return VLC_EGENERIC;
p_dec->pf_decode_sub = DecodeBlock; p_dec->pf_decode_sub = DecodeBlock;
/* Allocate the memory needed to store the decoder's structure */
if( ( p_dec->p_sys = p_sys = malloc( sizeof(*p_sys) ) ) == NULL )
return VLC_ENOMEM;
/* Let other interested modules know that we're a CMML decoder /* Let other interested modules know that we're a CMML decoder
* We have to set this variable on the input thread, because there's * We have to set this variable on the input thread, because there's
* typically more than one decoder running so we can't find the CMML * typically more than one decoder running so we can't find the CMML
...@@ -125,10 +112,7 @@ static int OpenDecoder( vlc_object_t *p_this ) ...@@ -125,10 +112,7 @@ static int OpenDecoder( vlc_object_t *p_this )
} }
/* initialise the CMML responder interface */ /* initialise the CMML responder interface */
p_sys->p_intf = intf_Create( p_dec, "cmml" ); p_dec->p_sys = OpenIntf( p_dec );
if( p_sys->p_intf )
intf_RunThread( p_sys->p_intf );
p_dec->fmt_out.i_cat = SPU_ES; p_dec->fmt_out.i_cat = SPU_ES;
p_dec->fmt_out.i_codec = 0; p_dec->fmt_out.i_codec = 0;
...@@ -174,18 +158,8 @@ static subpicture_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block ) ...@@ -174,18 +158,8 @@ static subpicture_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block )
static void CloseDecoder( vlc_object_t *p_this ) static void CloseDecoder( vlc_object_t *p_this )
{ {
decoder_t *p_dec = (decoder_t *)p_this; decoder_t *p_dec = (decoder_t *)p_this;
decoder_sys_t *p_sys = p_dec->p_sys;
/* Destroy the interface object/thread */
if( p_sys->p_intf != NULL )
{
intf_thread_t *p_intf = p_sys->p_intf;
intf_StopThread( p_intf );
vlc_object_detach( p_intf );
vlc_object_release( p_intf );
}
free( p_sys ); CloseIntf( p_dec->p_sys );
} }
/***************************************************************************** /*****************************************************************************
......
...@@ -40,7 +40,6 @@ ...@@ -40,7 +40,6 @@
#endif #endif
#include <vlc_codec.h> #include <vlc_codec.h>
#include <vlc_interface.h>
#include <vlc_playlist.h> #include <vlc_playlist.h>
#include <vlc_osd.h> #include <vlc_osd.h>
...@@ -59,14 +58,16 @@ ...@@ -59,14 +58,16 @@
/***************************************************************************** /*****************************************************************************
* intf_sys_t: description and status of interface * intf_sys_t: description and status of interface
*****************************************************************************/ *****************************************************************************/
struct intf_sys_t typedef struct decoder_sys_t
{ {
VLC_COMMON_MEMBERS
vlc_mutex_t lock; vlc_mutex_t lock;
decoder_t * p_cmml_decoder; decoder_t * p_cmml_decoder;
input_thread_t * p_input; input_thread_t * p_input;
int i_key_action; int i_key_action;
}; } intf_thread_t;
struct navigation_history_t struct navigation_history_t
{ {
...@@ -78,8 +79,8 @@ struct navigation_history_t ...@@ -78,8 +79,8 @@ struct navigation_history_t
* Local prototypes. * Local prototypes.
*****************************************************************************/ *****************************************************************************/
int OpenIntf ( vlc_object_t * ); decoder_sys_t *OpenIntf ( vlc_object_t * );
void CloseIntf ( vlc_object_t * ); void CloseIntf ( decoder_sys_t * );
static int InitThread ( intf_thread_t * ); static int InitThread ( intf_thread_t * );
static int MouseEvent ( vlc_object_t *, char const *, static int MouseEvent ( vlc_object_t *, char const *,
...@@ -109,22 +110,18 @@ static int DisplayPendingAnchor ( intf_thread_t *, vout_thread_t * ); ...@@ -109,22 +110,18 @@ static int DisplayPendingAnchor ( intf_thread_t *, vout_thread_t * );
static history_t * GetHistory ( playlist_t * ); static history_t * GetHistory ( playlist_t * );
static void ReplacePlaylistItem ( playlist_t *, char * ); static void ReplacePlaylistItem ( playlist_t *, char * );
/* Exported functions */ static void *RunIntf ( vlc_object_t * );
static void RunIntf ( intf_thread_t *p_intf );
/***************************************************************************** /*****************************************************************************
* OpenIntf: initialize CMML interface * OpenIntf: initialize CMML interface
*****************************************************************************/ *****************************************************************************/
int OpenIntf ( vlc_object_t *p_this ) decoder_sys_t *OpenIntf ( vlc_object_t *p_this )
{ {
intf_thread_t *p_intf = (intf_thread_t *)p_this; decoder_sys_t *p_intf = vlc_object_create( p_this, sizeof( *p_intf ) );
if( p_intf == NULL )
p_intf->p_sys = malloc( sizeof( intf_sys_t ) ); return NULL;
if( p_intf->p_sys == NULL )
return VLC_ENOMEM;
p_intf->pf_run = RunIntf; vlc_mutex_init( &p_intf->lock );
vlc_mutex_init( &p_intf->p_sys->lock );
var_AddCallback( p_intf->p_libvlc, "key-action", KeyEvent, p_intf ); var_AddCallback( p_intf->p_libvlc, "key-action", KeyEvent, p_intf );
/* we also need to add the callback for "mouse-clicked", but do that later /* we also need to add the callback for "mouse-clicked", but do that later
...@@ -140,15 +137,15 @@ int OpenIntf ( vlc_object_t *p_this ) ...@@ -140,15 +137,15 @@ int OpenIntf ( vlc_object_t *p_this )
var_AddCallback( p_intf->p_libvlc, "browse-follow-anchor", var_AddCallback( p_intf->p_libvlc, "browse-follow-anchor",
FollowAnchorCallback, p_intf ); FollowAnchorCallback, p_intf );
return VLC_SUCCESS; vlc_thread_create( p_intf, "cmml", RunIntf, VLC_THREAD_PRIORITY_LOW );
return p_intf;
} }
/***************************************************************************** /*****************************************************************************
* CloseIntf: destroy dummy interface * CloseIntf: destroy dummy interface
*****************************************************************************/ *****************************************************************************/
void CloseIntf ( vlc_object_t *p_this ) void CloseIntf ( decoder_sys_t *p_intf )
{ {
intf_thread_t * p_intf = (intf_thread_t *)p_this;
vout_thread_t * p_vout; vout_thread_t * p_vout;
#ifdef CMML_INTF_DEBUG #ifdef CMML_INTF_DEBUG
...@@ -165,26 +162,29 @@ void CloseIntf ( vlc_object_t *p_this ) ...@@ -165,26 +162,29 @@ void CloseIntf ( vlc_object_t *p_this )
} }
var_DelCallback( p_intf->p_libvlc, "key-action", KeyEvent, p_intf ); var_DelCallback( p_intf->p_libvlc, "key-action", KeyEvent, p_intf );
vlc_object_kill( p_intf );
vlc_thread_join( p_intf );
vlc_object_release( p_intf->p_sys->p_cmml_decoder ); vlc_object_release( p_intf->p_cmml_decoder );
vlc_mutex_destroy( &p_intf->p_sys->lock ); vlc_mutex_destroy( &p_intf->lock );
free( p_intf->p_sys ); vlc_object_release( p_intf );
} }
/***************************************************************************** /*****************************************************************************
* RunIntf: main loop * RunIntf: main loop
*****************************************************************************/ *****************************************************************************/
static void RunIntf( intf_thread_t *p_intf ) static void *RunIntf( vlc_object_t *p_obj )
{ {
decoder_sys_t *p_intf = (decoder_sys_t *)p_obj;
int canc = vlc_savecancel(); int canc = vlc_savecancel();
vout_thread_t * p_vout = NULL; vout_thread_t * p_vout = NULL;
if( InitThread( p_intf ) < 0 ) if( InitThread( p_intf ) < 0 )
{ {
msg_Err( p_intf, "can't initialize CMML interface" ); msg_Err( p_intf, "can't initialize CMML interface" );
return; return NULL;
} }
#ifdef CMML_INTF_DEBUG #ifdef CMML_INTF_DEBUG
msg_Dbg( p_intf, "CMML intf initialized" ); msg_Dbg( p_intf, "CMML intf initialized" );
...@@ -204,7 +204,7 @@ static void RunIntf( intf_thread_t *p_intf ) ...@@ -204,7 +204,7 @@ static void RunIntf( intf_thread_t *p_intf )
/* find a video output if we currently don't have one */ /* find a video output if we currently don't have one */
if( p_vout == NULL ) if( p_vout == NULL )
{ {
p_vout = vlc_object_find( p_intf->p_sys->p_input, p_vout = vlc_object_find( p_intf->p_input,
VLC_OBJECT_VOUT, FIND_CHILD ); VLC_OBJECT_VOUT, FIND_CHILD );
if( p_vout ) if( p_vout )
{ {
...@@ -215,12 +215,12 @@ static void RunIntf( intf_thread_t *p_intf ) ...@@ -215,12 +215,12 @@ static void RunIntf( intf_thread_t *p_intf )
} }
} }
vlc_mutex_lock( &p_intf->p_sys->lock ); vlc_mutex_lock( &p_intf->lock );
/* /*
* keyboard event * keyboard event
*/ */
switch( p_intf->p_sys->i_key_action ) switch( p_intf->i_key_action )
{ {
case ACTIONID_NAV_ACTIVATE: case ACTIONID_NAV_ACTIVATE:
FollowAnchor( p_intf ); FollowAnchor( p_intf );
...@@ -234,8 +234,8 @@ static void RunIntf( intf_thread_t *p_intf ) ...@@ -234,8 +234,8 @@ static void RunIntf( intf_thread_t *p_intf )
default: default:
break; break;
} }
p_intf->p_sys->i_key_action = 0; p_intf->i_key_action = 0;
vlc_mutex_unlock( &p_intf->p_sys->lock ); vlc_mutex_unlock( &p_intf->lock );
(void) DisplayPendingAnchor( p_intf, p_vout ); (void) DisplayPendingAnchor( p_intf, p_vout );
...@@ -251,8 +251,9 @@ static void RunIntf( intf_thread_t *p_intf ) ...@@ -251,8 +251,9 @@ static void RunIntf( intf_thread_t *p_intf )
vlc_object_release( p_vout ); vlc_object_release( p_vout );
} }
vlc_object_release( p_intf->p_sys->p_input ); vlc_object_release( p_intf->p_input );
vlc_restorecancel( canc ); vlc_restorecancel( canc );
return NULL;
} }
/***************************************************************************** /*****************************************************************************
...@@ -265,10 +266,9 @@ static int DisplayPendingAnchor( intf_thread_t *p_intf, vout_thread_t *p_vout ) ...@@ -265,10 +266,9 @@ static int DisplayPendingAnchor( intf_thread_t *p_intf, vout_thread_t *p_vout )
char *psz_description = NULL; char *psz_description = NULL;
char *psz_url = NULL; char *psz_url = NULL;
intf_thread_t *p_primary_intf;
vlc_value_t val; vlc_value_t val;
p_cmml_decoder = p_intf->p_sys->p_cmml_decoder; p_cmml_decoder = p_intf->p_cmml_decoder;
if( var_Get( p_cmml_decoder, "psz-current-anchor-description", &val ) if( var_Get( p_cmml_decoder, "psz-current-anchor-description", &val )
!= VLC_SUCCESS ) != VLC_SUCCESS )
{ {
...@@ -337,14 +337,14 @@ static int InitThread( intf_thread_t * p_intf ) ...@@ -337,14 +337,14 @@ static int InitThread( intf_thread_t * p_intf )
return VLC_EGENERIC; return VLC_EGENERIC;
} }
vlc_mutex_lock( &p_intf->p_sys->lock ); vlc_mutex_lock( &p_intf->lock );
p_intf->p_sys->p_input = p_input; p_intf->p_input = p_input;
p_intf->p_sys->p_cmml_decoder = p_cmml_decoder; p_intf->p_cmml_decoder = p_cmml_decoder;
p_intf->p_sys->i_key_action = 0; p_intf->i_key_action = 0;
vlc_mutex_unlock( &p_intf->p_sys->lock ); vlc_mutex_unlock( &p_intf->lock );
return VLC_SUCCESS; return VLC_SUCCESS;
} }
...@@ -379,11 +379,11 @@ static int KeyEvent( vlc_object_t *p_this, char const *psz_var, ...@@ -379,11 +379,11 @@ static int KeyEvent( vlc_object_t *p_this, char const *psz_var,
intf_thread_t *p_intf = (intf_thread_t *)p_data; intf_thread_t *p_intf = (intf_thread_t *)p_data;
vlc_mutex_lock( &p_intf->p_sys->lock ); vlc_mutex_lock( &p_intf->lock );
/* FIXME: key presses might get lost here... */ /* FIXME: key presses might get lost here... */
p_intf->p_sys->i_key_action = newval.i_int; p_intf->i_key_action = newval.i_int;
vlc_mutex_unlock( &p_intf->p_sys->lock ); vlc_mutex_unlock( &p_intf->lock );
return VLC_SUCCESS; return VLC_SUCCESS;
} }
...@@ -393,15 +393,13 @@ static int KeyEvent( vlc_object_t *p_this, char const *psz_var, ...@@ -393,15 +393,13 @@ static int KeyEvent( vlc_object_t *p_this, char const *psz_var,
*****************************************************************************/ *****************************************************************************/
static void FollowAnchor ( intf_thread_t *p_intf ) static void FollowAnchor ( intf_thread_t *p_intf )
{ {
intf_sys_t *p_sys;
decoder_t *p_cmml_decoder; decoder_t *p_cmml_decoder;
char *psz_url = NULL; char *psz_url = NULL;
vlc_value_t val; vlc_value_t val;
msg_Dbg( p_intf, "User followed anchor" ); msg_Dbg( p_intf, "User followed anchor" );
p_sys = p_intf->p_sys; p_cmml_decoder = p_intf->p_cmml_decoder;
p_cmml_decoder = p_sys->p_cmml_decoder;
if( var_Get( p_cmml_decoder, "psz-current-anchor-url", &val ) == if( var_Get( p_cmml_decoder, "psz-current-anchor-url", &val ) ==
VLC_SUCCESS ) VLC_SUCCESS )
...@@ -437,7 +435,7 @@ static void FollowAnchor ( intf_thread_t *p_intf ) ...@@ -437,7 +435,7 @@ static void FollowAnchor ( intf_thread_t *p_intf )
msg_Dbg( p_intf, "URL to load is \"%s\"", psz_uri_to_load ); msg_Dbg( p_intf, "URL to load is \"%s\"", psz_uri_to_load );
#endif #endif
if( var_Get( p_intf->p_sys->p_input, "time", &time ) ) if( var_Get( p_intf->p_input, "time", &time ) )
{ {
msg_Dbg( p_intf, "couldn't get time from current clip" ); msg_Dbg( p_intf, "couldn't get time from current clip" );
time.i_time = 0; time.i_time = 0;
...@@ -526,7 +524,7 @@ char *GetTimedURLFromPlaylistItem( intf_thread_t *p_intf, ...@@ -526,7 +524,7 @@ char *GetTimedURLFromPlaylistItem( intf_thread_t *p_intf,
psz_url = xstrcat( psz_url, "?" ); psz_url = xstrcat( psz_url, "?" );
/* jump back to 2 seconds before where we are now */ /* jump back to 2 seconds before where we are now */
i_seconds = GetCurrentTimeInSeconds( p_intf->p_sys->p_input ) - 2; i_seconds = GetCurrentTimeInSeconds( p_intf->p_input ) - 2;
psz_seconds = GetTimedURIFragmentForTime( i_seconds < 0 ? 0 : i_seconds ); psz_seconds = GetTimedURIFragmentForTime( i_seconds < 0 ? 0 : i_seconds );
if( psz_seconds ) if( psz_seconds )
{ {
......
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