Commit 8cfee3e8 authored by Laurent Aimar's avatar Laurent Aimar

Implemented sout-keep per media support.

You have to use sout-keep option on your broadcast media using 
 > setup your_media option sout-keep
The default value is no-sout-keep and command line option --sout-keep
will not activate it (on purpose).
parent c6957ea9
...@@ -48,6 +48,8 @@ ...@@ -48,6 +48,8 @@
#include "vlm_internal.h" #include "vlm_internal.h"
#include <vlc_vod.h> #include <vlc_vod.h>
#include <vlc_charset.h> #include <vlc_charset.h>
#include <vlc_sout.h>
#include "../stream_output/stream_output.h"
/***************************************************************************** /*****************************************************************************
* Local prototypes. * Local prototypes.
...@@ -76,6 +78,12 @@ static int vlm_ScheduleSetup( vlm_schedule_t *schedule, const char *psz_cmd, ...@@ -76,6 +78,12 @@ static int vlm_ScheduleSetup( vlm_schedule_t *schedule, const char *psz_cmd,
static int vlm_MediaVodControl( void *, vod_media_t *, const char *, int, va_list ); static int vlm_MediaVodControl( void *, vod_media_t *, const char *, int, va_list );
static vlm_media_t *vlm_MediaNew( vlm_t *, const char *, int );
static void vlm_MediaDelete( vlm_t *, vlm_media_t *, const char * );
static int vlm_MediaSetup( vlm_t *, vlm_media_t *, const char *, const char * );
static int vlm_MediaControl( vlm_t *, vlm_media_t *, const char *, const char *, const char * );
static vlm_media_t *vlm_MediaSearch( vlm_t *, const char *);
/***************************************************************************** /*****************************************************************************
* vlm_New: * vlm_New:
*****************************************************************************/ *****************************************************************************/
...@@ -158,7 +166,6 @@ void vlm_Delete( vlm_t *p_vlm ) ...@@ -158,7 +166,6 @@ void vlm_Delete( vlm_t *p_vlm )
{ {
vlc_value_t lockval; vlc_value_t lockval;
msg_Err( p_vlm, "vlm_Delete called" );
var_Get( p_vlm->p_libvlc_global, "vlm_mutex", &lockval ); var_Get( p_vlm->p_libvlc_global, "vlm_mutex", &lockval );
vlc_mutex_lock( lockval.p_address ); vlc_mutex_lock( lockval.p_address );
...@@ -175,8 +182,6 @@ void vlm_Delete( vlm_t *p_vlm ) ...@@ -175,8 +182,6 @@ void vlm_Delete( vlm_t *p_vlm )
vlc_object_detach( p_vlm ); vlc_object_detach( p_vlm );
vlc_mutex_destroy( &p_vlm->lock );
while( p_vlm->i_media ) while( p_vlm->i_media )
vlm_MediaDelete( p_vlm, p_vlm->media[0], NULL ); vlm_MediaDelete( p_vlm, p_vlm->media[0], NULL );
TAB_CLEAN( p_vlm->i_media, p_vlm->media ); TAB_CLEAN( p_vlm->i_media, p_vlm->media );
...@@ -185,6 +190,8 @@ void vlm_Delete( vlm_t *p_vlm ) ...@@ -185,6 +190,8 @@ void vlm_Delete( vlm_t *p_vlm )
vlm_ScheduleDelete( p_vlm, p_vlm->schedule[0], NULL ); vlm_ScheduleDelete( p_vlm, p_vlm->schedule[0], NULL );
TAB_CLEAN( p_vlm->schedule, p_vlm->schedule ); TAB_CLEAN( p_vlm->schedule, p_vlm->schedule );
vlc_mutex_destroy( &p_vlm->lock );
vlc_object_destroy( p_vlm ); vlc_object_destroy( p_vlm );
vlc_mutex_unlock( lockval.p_address ); vlc_mutex_unlock( lockval.p_address );
} }
...@@ -211,40 +218,36 @@ static const char quotes[] = "\"'"; ...@@ -211,40 +218,36 @@ static const char quotes[] = "\"'";
* @return NULL on mal-formatted string, * @return NULL on mal-formatted string,
* pointer past the last character otherwise. * pointer past the last character otherwise.
*/ */
static const char *FindCommandEnd (const char *psz_sent) static const char *FindCommandEnd( const char *psz_sent )
{ {
char c, quote = 0; char c, quote = 0;
while ((c = *psz_sent) != '\0') while( (c = *psz_sent) != '\0' )
{ {
if (!quote) if( !quote )
{ {
if (strchr(quotes,c)) // opening quote if( strchr(quotes,c) ) // opening quote
quote = c; quote = c;
else else if( isspace(c) ) // non-escaped space
if (isspace(c)) // non-escaped space
return psz_sent; return psz_sent;
else else if( c == '\\' )
if( c == '\\' )
{ {
psz_sent++; // skip escaped character psz_sent++; // skip escaped character
if (*psz_sent == '\0') if( *psz_sent == '\0' )
return psz_sent; return psz_sent;
} }
} }
else else
{ {
if (c == quote) // non-escaped matching quote if( c == quote ) // non-escaped matching quote
quote = 0; quote = 0;
else else if( (quote == '"') && (c == '\\') )
if ((quote == '"') && (c == '\\'))
{ {
psz_sent++; // skip escaped character psz_sent++; // skip escaped character
if (*psz_sent == '\0') if (*psz_sent == '\0')
return NULL; // error, closing quote missing return NULL; // error, closing quote missing
} }
} }
psz_sent++; psz_sent++;
} }
...@@ -262,21 +265,20 @@ static const char *FindCommandEnd (const char *psz_sent) ...@@ -262,21 +265,20 @@ static const char *FindCommandEnd (const char *psz_sent)
* *
* @return 0 on success, -1 on error. * @return 0 on success, -1 on error.
*/ */
static int Unescape (char *out, const char *in) static int Unescape( char *out, const char *in )
{ {
char c, quote = 0; char c, quote = 0;
while ((c = *in++) != '\0') while( (c = *in++) != '\0' )
{ {
if (!quote) if( !quote )
{ {
if (strchr(quotes,c)) // opening quote if (strchr(quotes,c)) // opening quote
{ {
quote = c; quote = c;
continue; continue;
} }
else else if( c == '\\' )
if( c == '\\' )
{ {
switch (c = *in++) switch (c = *in++)
{ {
...@@ -290,7 +292,7 @@ static int Unescape (char *out, const char *in) ...@@ -290,7 +292,7 @@ static int Unescape (char *out, const char *in)
*out = '\0'; *out = '\0';
return 0; return 0;
} }
if (isspace(c)) if( isspace(c) )
{ {
*out++ = c; *out++ = c;
continue; continue;
...@@ -301,14 +303,14 @@ static int Unescape (char *out, const char *in) ...@@ -301,14 +303,14 @@ static int Unescape (char *out, const char *in)
} }
else else
{ {
if (c == quote) // non-escaped matching quote if( c == quote ) // non-escaped matching quote
{ {
quote = 0; quote = 0;
continue; continue;
} }
if ((quote == '"') && (c == '\\')) if( (quote == '"') && (c == '\\') )
{ {
switch (c = *in++) switch( c = *in++ )
{ {
case '"': case '"':
case '\\': case '\\':
...@@ -836,9 +838,7 @@ vlm_media_t *vlm_MediaSearch( vlm_t *vlm, const char *psz_name ) ...@@ -836,9 +838,7 @@ vlm_media_t *vlm_MediaSearch( vlm_t *vlm, const char *psz_name )
for( i = 0; i < vlm->i_media; i++ ) for( i = 0; i < vlm->i_media; i++ )
{ {
if( strcmp( psz_name, vlm->media[i]->psz_name ) == 0 ) if( strcmp( psz_name, vlm->media[i]->psz_name ) == 0 )
{
return vlm->media[i]; return vlm->media[i];
}
} }
return NULL; return NULL;
...@@ -940,7 +940,7 @@ vlm_MediaInstanceSearch( vlm_t *vlm, vlm_media_t *media, ...@@ -940,7 +940,7 @@ vlm_MediaInstanceSearch( vlm_t *vlm, vlm_media_t *media,
return NULL; return NULL;
} }
vlm_media_t *vlm_MediaNew( vlm_t *vlm, const char *psz_name, int i_type ) static vlm_media_t *vlm_MediaNew( vlm_t *vlm, const char *psz_name, int i_type )
{ {
vlm_media_t *media = malloc( sizeof( vlm_media_t ) ); vlm_media_t *media = malloc( sizeof( vlm_media_t ) );
...@@ -995,7 +995,7 @@ vlm_media_t *vlm_MediaNew( vlm_t *vlm, const char *psz_name, int i_type ) ...@@ -995,7 +995,7 @@ vlm_media_t *vlm_MediaNew( vlm_t *vlm, const char *psz_name, int i_type )
} }
/* for now, simple delete. After, del with options (last arg) */ /* for now, simple delete. After, del with options (last arg) */
void vlm_MediaDelete( vlm_t *vlm, vlm_media_t *media, const char *psz_name ) static void vlm_MediaDelete( vlm_t *vlm, vlm_media_t *media, const char *psz_name )
{ {
if( media == NULL ) return; if( media == NULL ) return;
...@@ -1040,7 +1040,7 @@ void vlm_MediaDelete( vlm_t *vlm, vlm_media_t *media, const char *psz_name ) ...@@ -1040,7 +1040,7 @@ void vlm_MediaDelete( vlm_t *vlm, vlm_media_t *media, const char *psz_name )
free( media ); free( media );
} }
int vlm_MediaSetup( vlm_t *vlm, vlm_media_t *media, const char *psz_cmd, static int vlm_MediaSetup( vlm_t *vlm, vlm_media_t *media, const char *psz_cmd,
const char *psz_value ) const char *psz_value )
{ {
if( !psz_cmd) return VLC_EGENERIC; if( !psz_cmd) return VLC_EGENERIC;
...@@ -1207,7 +1207,44 @@ int vlm_MediaSetup( vlm_t *vlm, vlm_media_t *media, const char *psz_cmd, ...@@ -1207,7 +1207,44 @@ int vlm_MediaSetup( vlm_t *vlm, vlm_media_t *media, const char *psz_cmd,
return VLC_SUCCESS; return VLC_SUCCESS;
} }
int vlm_MediaControl( vlm_t *vlm, vlm_media_t *media, const char *psz_id, static vlm_media_instance_t *vlm_MediaInstanceNew( vlm_t *p_vlm, const char *psz_name )
{
vlm_media_instance_t *p_instance = malloc( sizeof(vlm_media_instance_t) );
if( !p_instance )
return NULL;
memset( p_instance, 0, sizeof(vlm_media_instance_t) );
p_instance->psz_name = NULL;
if( psz_name )
p_instance->psz_name = strdup( psz_name );
input_ItemInit( VLC_OBJECT(p_vlm), &p_instance->item );
p_instance->i_index = 0;
p_instance->b_sout_keep = VLC_FALSE;
p_instance->p_input = NULL;
p_instance->p_sout = NULL;
return p_instance;
}
static void vlm_MediaInstanceDelete( vlm_media_instance_t *p_instance )
{
if( p_instance->p_input )
{
input_StopThread( p_instance->p_input );
input_DestroyThreadExtended( p_instance->p_input, &p_instance->p_sout );
}
if( p_instance->p_sout )
sout_DeleteInstance( p_instance->p_sout );
input_ItemClean( &p_instance->item );
if( p_instance->psz_name )
free( p_instance->psz_name );
free( p_instance );
}
static int vlm_MediaControl( vlm_t *vlm, vlm_media_t *media, const char *psz_id,
const char *psz_command, const char *psz_args ) const char *psz_command, const char *psz_args )
{ {
vlm_media_instance_t *p_instance; vlm_media_instance_t *p_instance;
...@@ -1224,16 +1261,10 @@ int vlm_MediaControl( vlm_t *vlm, vlm_media_t *media, const char *psz_id, ...@@ -1224,16 +1261,10 @@ int vlm_MediaControl( vlm_t *vlm, vlm_media_t *media, const char *psz_id,
{ {
char *psz_dup; char *psz_dup;
p_instance = malloc( sizeof(vlm_media_instance_t) ); p_instance = vlm_MediaInstanceNew( vlm, psz_id );
if( !p_instance ) if( !p_instance )
return VLC_ENOMEM; return VLC_ENOMEM;
memset( p_instance, 0, sizeof(vlm_media_instance_t) );
p_instance->psz_name = psz_id ? strdup( psz_id ) : NULL;
input_ItemInit( VLC_OBJECT(vlm), &p_instance->item );
p_instance->p_input = NULL;
TAB_INIT( p_instance->item.i_options, p_instance->item.ppsz_options ); TAB_INIT( p_instance->item.i_options, p_instance->item.ppsz_options );
if( media->psz_output != NULL || media->psz_vod_output != NULL ) if( media->psz_output != NULL || media->psz_vod_output != NULL )
...@@ -1247,10 +1278,25 @@ int vlm_MediaControl( vlm_t *vlm, vlm_media_t *media, const char *psz_id, ...@@ -1247,10 +1278,25 @@ int vlm_MediaControl( vlm_t *vlm, vlm_media_t *media, const char *psz_id,
for( i = 0; i < media->i_option; i++ ) for( i = 0; i < media->i_option; i++ )
{ {
psz_dup = strdup( media->option[i] ); if( !strcmp( media->option[i], "sout-keep" ) )
TAB_APPEND( p_instance->item.i_options, p_instance->item.ppsz_options, psz_dup ); {
p_instance->b_sout_keep = VLC_TRUE;
}
else if( !strcmp( media->option[i], "nosout-keep" ) || !strcmp( media->option[i], "no-sout-keep" ) )
{
p_instance->b_sout_keep = VLC_FALSE;
}
else
{
psz_dup = strdup( media->option[i] );
TAB_APPEND( p_instance->item.i_options, p_instance->item.ppsz_options, psz_dup );
}
} }
psz_dup = strdup( "no-sout-keep" ); /* We force the right sout-keep value (avoid using the sout-keep from the global configuration) */
if( media->i_type != VOD_TYPE && p_instance->b_sout_keep )
psz_dup = strdup( "sout-keep" );
else
psz_dup = strdup( "no-sout-keep" );
TAB_APPEND( p_instance->item.i_options, p_instance->item.ppsz_options, psz_dup ); TAB_APPEND( p_instance->item.i_options, p_instance->item.ppsz_options, psz_dup );
TAB_APPEND( media->i_instance, media->instance, p_instance ); TAB_APPEND( media->i_instance, media->instance, p_instance );
...@@ -1261,30 +1307,36 @@ int vlm_MediaControl( vlm_t *vlm, vlm_media_t *media, const char *psz_id, ...@@ -1261,30 +1307,36 @@ int vlm_MediaControl( vlm_t *vlm, vlm_media_t *media, const char *psz_id,
p_instance->i_index = i-1; p_instance->i_index = i-1;
} }
if( p_instance->item.psz_uri ) free( p_instance->item.psz_uri ); if( p_instance->item.psz_uri )
free( p_instance->item.psz_uri );
p_instance->item.psz_uri = p_instance->item.psz_uri =
strdup( media->input[p_instance->i_index] ); strdup( media->input[p_instance->i_index] );
if( p_instance->p_input ) if( p_instance->p_input )
{ {
input_StopThread( p_instance->p_input ); input_StopThread( p_instance->p_input );
input_DestroyThreadExtended( p_instance->p_input, NULL ); input_DestroyThreadExtended( p_instance->p_input, &p_instance->p_sout );
if( !p_instance->b_sout_keep && p_instance->p_sout )
{
sout_DeleteInstance( p_instance->p_sout );
p_instance->p_sout = NULL;
}
} }
asprintf( &psz_header, _("Media: %s"), media->psz_name ); asprintf( &psz_header, _("Media: %s"), media->psz_name );
p_instance->p_input = input_CreateThreadExtended( vlm, &p_instance->item, psz_header, NULL ); p_instance->p_input = input_CreateThreadExtended( vlm, &p_instance->item, psz_header, p_instance->p_sout );
if( !p_instance->p_input ) if( !p_instance->p_input )
{ {
TAB_REMOVE( media->i_instance, media->instance, p_instance ); TAB_REMOVE( media->i_instance, media->instance, p_instance );
input_ItemClean( &p_instance->item ); vlm_MediaInstanceDelete( p_instance );
if( p_instance->psz_name ) free( p_instance->psz_name );
} }
free( psz_header ); free( psz_header );
return VLC_SUCCESS; return VLC_SUCCESS;
} }
if( !p_instance ) return VLC_EGENERIC; if( !p_instance )
return VLC_EGENERIC;
if( !strcmp( psz_command, "seek" ) ) if( !strcmp( psz_command, "seek" ) )
{ {
...@@ -1383,16 +1435,7 @@ int vlm_MediaControl( vlm_t *vlm, vlm_media_t *media, const char *psz_id, ...@@ -1383,16 +1435,7 @@ int vlm_MediaControl( vlm_t *vlm, vlm_media_t *media, const char *psz_id,
{ {
TAB_REMOVE( media->i_instance, media->instance, p_instance ); TAB_REMOVE( media->i_instance, media->instance, p_instance );
if( p_instance->p_input ) vlm_MediaInstanceDelete( p_instance );
{
input_StopThread( p_instance->p_input );
input_DestroyThreadExtended( p_instance->p_input, NULL );
}
input_ItemClean( &p_instance->item );
if( p_instance->psz_name ) free( p_instance->psz_name );
free( p_instance );
return VLC_SUCCESS; return VLC_SUCCESS;
} }
else if( !strcmp( psz_command, "pause" ) ) else if( !strcmp( psz_command, "pause" ) )
...@@ -2497,8 +2540,6 @@ static int Manage( vlc_object_t* p_object ) ...@@ -2497,8 +2540,6 @@ static int Manage( vlc_object_t* p_object )
i_lastcheck = vlm_Date(); i_lastcheck = vlm_Date();
msleep( 100000 );
while( !vlm->b_die ) while( !vlm->b_die )
{ {
char **ppsz_scheduled_commands = NULL; char **ppsz_scheduled_commands = NULL;
...@@ -2524,17 +2565,12 @@ static int Manage( vlc_object_t* p_object ) ...@@ -2524,17 +2565,12 @@ static int Manage( vlc_object_t* p_object )
if( p_instance->i_index < p_media->i_input ) if( p_instance->i_index < p_media->i_input )
{ {
char buffer[12]; char psz_index[32];
input_StopThread( p_instance->p_input );
input_DestroyThreadExtended( p_instance->p_input, NULL );
p_instance->p_input = NULL;
/* FIXME, find a way to select the right instance */ /* FIXME, find a way to select the right instance */
sprintf( buffer, "%d", p_instance->i_index+1 ); snprintf( psz_index, sizeof(psz_index), "%d", p_instance->i_index+1 );
vlm_MediaControl( vlm, p_media, p_instance->psz_name, vlm_MediaControl( vlm, p_media, p_instance->psz_name,
"play", buffer ); "play", psz_index );
} }
else else
{ {
......
...@@ -42,8 +42,11 @@ typedef struct ...@@ -42,8 +42,11 @@ typedef struct
/* "playlist" index */ /* "playlist" index */
int i_index; int i_index;
input_item_t item; vlc_bool_t b_sout_keep;
input_thread_t *p_input;
input_item_t item;
input_thread_t *p_input;
sout_instance_t *p_sout;
} vlm_media_instance_t; } vlm_media_instance_t;
...@@ -114,10 +117,4 @@ struct vlm_t ...@@ -114,10 +117,4 @@ struct vlm_t
vlm_schedule_t **schedule; vlm_schedule_t **schedule;
}; };
vlm_media_t *vlm_MediaNew( vlm_t *, const char *, int );
void vlm_MediaDelete( vlm_t *, vlm_media_t *, const char * );
int vlm_MediaSetup( vlm_t *, vlm_media_t *, const char *, const char * );
int vlm_MediaControl( vlm_t *, vlm_media_t *, const char *, const char *, const char * );
vlm_media_t *vlm_MediaSearch( vlm_t *, const char *);
#endif #endif
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