Browse Source

vlm: remove "schedule"

The schedule feature was essentially just for fun at the ECP campus and
never really worked. In practice people do (or at least did) schedule
broadcasts with VLC, but they that with soem kind of higher-level
management process starting and stopping VLC (and/or sending VLM broadcast
commands) - not with VLM schedules.

Note that this does _not_ remove VLM broadcasts. That code is still
required to support the streaming output bridge and mosaic bridge or simply
to test multiple inputs in a single process. Whilst #27733 implies that
VLM broadcasts are not currently working either, they are outside the
scope of this changeset either way.

Known problems with the schedules:
- Neither daylight saving and time zones are not supported so this fails
  at least twice a year if you have daylight savings.
- (Day of) Month-based scheduling actually worked (the calculation was
  just plain wrong).
- Clock adjustments broke it.
- It required realtime clock-based condition variable sleep which most
  operating systems don't support.

Closes #25063, #25064, #25065, #25066, #25067, #25068, #25069, #25070.
pull/188/head
Rémi Denis-Courmont 10 months ago
parent
commit
0ec628ea6d
  1. 56
      doc/vlm.txt
  2. 13
      include/vlc_vlm.h
  3. 103
      src/input/vlm.c
  4. 25
      src/input/vlm_internal.h
  5. 604
      src/input/vlmshell.c

56
doc/vlm.txt

@ -17,21 +17,14 @@ I - Interfaces
Access it from http://127.0.0.1:8080/vlm.html
II - VLM Elements
1) Medias
A media is composed with a list of inputs (the videos and audios you
want to stream), an output (where you want to stream them), and some
options. It is very close to a TV program, or channel: it is
launched, stopped, paused by the administrator (or a schedule), may
be repeated several times etc.
2) Schedules
A Schedule is a script with a date. When the current date is the
schedule date, the script is launched. There are of course other
options, like a period, a number of repetitions, etc. for the
schedule to be launched several times (or endlessly) automatically.
options. It is very close to a TV program, or channel: it is launched,
stopped, paused by the administrator, may be repeated several times etc.
III - Command line syntax:
Note: an element is a media or a schedule.
Note: the only type of element in this version is media.
1) Command lines:
help
Displays an exhaustive commmand lines list.
@ -58,14 +51,13 @@ Note: an element is a media or a schedule.
"del (name)" destroys the (name) element.
"del all" destroys all elements.
"del media" destroys all medias.
"del schedule" destroys all schedules.
control (name) [instance_name] (command)
Changes the state of the (instance_name) instance of (name) media.
If (instance_name) is not specified, the control command affects the
default instance.
See Commands section for more information.
save (config_file)
Saves all media and schedule configurations in the (config_file)
Saves all media configurations in the (config_file)
configuration file. the "save" command overwrites the file if it
already exists. States (playing, paused, stop) are not saved.
See Configuration File section for more information.
@ -97,45 +89,13 @@ Note: an element is a media or a schedule.
media.
enabled|disabled
Enable or Disable the media.
If a media is disabled, it can not be streamed, paused,
launched by a schedule.
If a media is disabled, it can not be streamed, paused.
loop|unloop
Used for broadcast only.
If a media with "loop" option receives the "play" command
and finally finishes to play the last input of the list, it
will automatically restart to play the input list.
Schedule Properties Syntax:
enabled|disabled
A disabled schedule will never be launched.
append (command)
Adds a command to the command line list.
The command line can be every command the VLM can understand.
Note: the rest of the line will be considered as part of the
command line. You cannot put another option after the
"append" one.
date (year)/(month)/(day)-(hour):(minutes):(seconds)|now
Specifies the first date the schedule should be launched.
the date must have the explicit form:
(year)/(month)/(day)-(hour):(minutes):(seconds)
For example: 2004/03/07-12:42:30
If you write "now" instead of a date, the schedule will be
launch as soon as possible (as soon as it is enabled), and
the current date will be used as the first date of the
schedule (for repeating).
period (years)/(months)/(days)-(hours):(minutes):(seconds)
Specifies the period of time a schedule must wait for
launching itself another time.
For now, the period has a very close syntax to a date:
months are considered as 30 days
years are considered as 12 months.
If a period is specified without a "repeat", it will be
launched endlessly.
repeat (number_of_repetitions)
Specifies the number of times the schedule has to be launch
again. For example, if a schedule has "repeat 3", it will be
launched 4 times.
3) Control Commands Syntax:
play
Starts a broadcast media. The media begins to launch the first
@ -157,7 +117,7 @@ IV - The configuration file
example, if you put a "load pouet" in a pouet file, and you launch the
"load pouet" command, then pouet will be loaded endlessly, and VLC
will crash (at least).
The load command converts the medias and schedules configurations into
command lines, and writes them into a file.
The load command converts the medias configurations into command lines,
and writes them into a file.
Any line where the first non white space character is a '#' is considered
as a comment.

13
include/vlc_vlm.h

@ -33,7 +33,7 @@
* VLC stream manager
*
* VLM is the server core in vlc that allows streaming of multiple media streams
* at the same time. It provides broadcast, schedule and video on demand features
* at the same time. It provides broadcast features
* for streaming using several streaming and network protocols.
* @{
* \file
@ -75,13 +75,6 @@ typedef struct
float f_rate; // normal is 1.0f
} vlm_media_instance_t;
#if 0
typedef struct
{
} vlm_schedule_t
#endif
/** VLM events
* You can catch vlm event by adding a callback on the variable "intf-event"
* of the VLM object.
@ -159,10 +152,6 @@ enum vlm_query_e
/* Set instance position ([0.0 .. 1.0]) */
VLM_SET_MEDIA_INSTANCE_POSITION, /* arg1=int64_t id, arg2=const char *psz_instance_name arg3=double */
/* Schedule control */
VLM_CLEAR_SCHEDULES, /* no arg */
/* TODO: missing schedule control */
/* */
};

103
src/input/vlm.c

@ -151,7 +151,6 @@ vlm_t *vlm_New( libvlc_int_t *libvlc, const char *psz_vlmconf )
p_vlm->exiting = false;
p_vlm->i_id = 1;
TAB_INIT( p_vlm->i_media, p_vlm->media );
TAB_INIT( p_vlm->i_schedule, p_vlm->schedule );
var_Create( p_vlm, "intf-event", VLC_VAR_ADDRESS );
if( vlc_clone( &p_vlm->thread, Manage, p_vlm ) )
@ -211,10 +210,6 @@ void vlm_Delete( vlm_t *p_vlm )
vlm_ControlInternal( p_vlm, VLM_CLEAR_MEDIAS );
TAB_CLEAN( p_vlm->i_media, p_vlm->media );
vlm_ControlInternal( p_vlm, VLM_CLEAR_SCHEDULES );
TAB_CLEAN( p_vlm->i_schedule, p_vlm->schedule );
vlc_mutex_unlock( &p_vlm->lock );
vlc_mutex_lock( &p_vlm->lock_manage );
p_vlm->exiting = true;
vlc_cond_signal( &p_vlm->wait_manage );
@ -250,16 +245,10 @@ static void* Manage( void* p_object )
vlc_thread_set_name("vlc-vlm");
vlm_t *vlm = (vlm_t*)p_object;
time_t lastcheck;
bool exiting;
time(&lastcheck);
do
{
char **ppsz_scheduled_commands = NULL;
int i_scheduled_commands = 0;
/* destroy the inputs that wants to die, and launch the next input */
vlc_mutex_lock( &vlm->lock );
for( int i = 0; i < vlm->i_media; i++ )
@ -293,89 +282,12 @@ static void* Manage( void* p_object )
}
}
/* scheduling */
time_t now, nextschedule = 0;
time(&now);
for( int i = 0; i < vlm->i_schedule; i++ )
{
time_t real_date = vlm->schedule[i]->date;
if( vlm->schedule[i]->b_enabled )
{
bool b_now = false;
if( vlm->schedule[i]->date == 0 ) // now !
{
vlm->schedule[i]->date = now;
real_date = now;
b_now = true;
}
else if( vlm->schedule[i]->period != 0 )
{
int j = 0;
while( ((vlm->schedule[i]->date + j *
vlm->schedule[i]->period) <= lastcheck) &&
( vlm->schedule[i]->i_repeat > j ||
vlm->schedule[i]->i_repeat < 0 ) )
{
j++;
}
real_date = vlm->schedule[i]->date + j *
vlm->schedule[i]->period;
}
if( real_date <= now )
{
if( real_date > lastcheck || b_now )
{
for( int j = 0; j < vlm->schedule[i]->i_command; j++ )
{
TAB_APPEND( i_scheduled_commands,
ppsz_scheduled_commands,
strdup(vlm->schedule[i]->command[j] ) );
}
}
}
else if( nextschedule == 0 || real_date < nextschedule )
{
nextschedule = real_date;
}
}
}
while( i_scheduled_commands )
{
vlm_message_t *message = NULL;
char *psz_command = ppsz_scheduled_commands[0];
ExecuteCommand( vlm, psz_command,&message );
/* for now, drop the message */
vlm_MessageDelete( message );
TAB_REMOVE( i_scheduled_commands,
ppsz_scheduled_commands,
psz_command );
free( psz_command );
}
lastcheck = now;
vlc_mutex_unlock( &vlm->lock );
vlc_mutex_lock( &vlm->lock_manage );
while( !vlm->input_state_changed && !(exiting = vlm->exiting) )
{
if( nextschedule )
{
if( vlc_cond_timedwait_daytime( &vlm->wait_manage,
&vlm->lock_manage,
nextschedule ) )
break;
}
else
vlc_cond_wait( &vlm->wait_manage, &vlm->lock_manage );
}
vlc_cond_wait( &vlm->wait_manage, &vlm->lock_manage );
vlm->input_state_changed = false;
vlc_mutex_unlock( &vlm->lock_manage );
}
@ -421,7 +333,7 @@ static vlm_media_sys_t *vlm_ControlMediaGetByName( vlm_t *p_vlm, const char *psz
static int vlm_MediaDescriptionCheck( vlm_t *p_vlm, vlm_media_t *p_cfg )
{
if( !p_cfg || !p_cfg->psz_name ||
!strcmp( p_cfg->psz_name, "all" ) || !strcmp( p_cfg->psz_name, "media" ) || !strcmp( p_cfg->psz_name, "schedule" ) )
!strcmp( p_cfg->psz_name, "all" ) || !strcmp( p_cfg->psz_name, "media" ))
return VLC_EGENERIC;
for( int i = 0; i < p_vlm->i_media; i++ )
@ -831,14 +743,6 @@ static int vlm_ControlMediaInstanceClear( vlm_t *p_vlm, int64_t id )
return VLC_SUCCESS;
}
static int vlm_ControlScheduleClear( vlm_t *p_vlm )
{
while( p_vlm->i_schedule > 0 )
vlm_ScheduleDelete( p_vlm, p_vlm->schedule[0] );
return VLC_SUCCESS;
}
static int vlm_vaControlInternal( vlm_t *p_vlm, int i_query, va_list args )
{
vlm_media_t *p_dsc;
@ -941,9 +845,6 @@ static int vlm_vaControlInternal( vlm_t *p_vlm, int i_query, va_list args )
d_double = (double)va_arg( args, double );
return vlm_ControlMediaInstanceSetTimePosition( p_vlm, id, psz_id, -1, d_double );
case VLM_CLEAR_SCHEDULES:
return vlm_ControlScheduleClear( p_vlm );
default:
msg_Err( p_vlm, "unknown VLM query" );
return VLC_EGENERIC;

25
src/input/vlm_internal.h

@ -52,26 +52,6 @@ typedef struct
vlm_media_instance_sys_t **instance;
} vlm_media_sys_t;
typedef struct
{
/* names "schedule" is reserved */
char *psz_name;
bool b_enabled;
/* list of commands to execute on date */
int i_command;
char **command;
/* the date of 1st execution */
time_t date;
/* if != 0, repeat period in seconds */
time_t period;
/* number of times you have to repeat
i_repeat < 0 : endless repeat */
int i_repeat;
} vlm_schedule_sys_t;
struct vlm_t
{
struct vlc_object_t obj;
@ -91,14 +71,9 @@ struct vlm_t
/* Media list */
int i_media;
vlm_media_sys_t **media;
/* Schedule list */
int i_schedule;
vlm_schedule_sys_t **schedule;
};
int vlm_ControlInternal( vlm_t *p_vlm, int i_query, ... );
int ExecuteCommand( vlm_t *, const char *, vlm_message_t ** );
void vlm_ScheduleDelete( vlm_t *vlm, vlm_schedule_sys_t *sched );
#endif

604
src/input/vlmshell.c

@ -57,17 +57,11 @@
*****************************************************************************/
/* */
static vlm_message_t *vlm_Show( vlm_t *, vlm_media_sys_t *, vlm_schedule_sys_t *, const char * );
static vlm_schedule_sys_t *vlm_ScheduleSearch( vlm_t *, const char * );
static vlm_message_t *vlm_Show( vlm_t *, vlm_media_sys_t *, const char * );
VLC_MALLOC static char *Save( vlm_t * );
static int Load( vlm_t *, char * );
static vlm_schedule_sys_t *vlm_ScheduleNew( vlm_t *vlm, const char *psz_name );
static int vlm_ScheduleSetup( vlm_t *vlm, vlm_schedule_sys_t *schedule,
const char *psz_cmd, const char *psz_value );
/* */
static vlm_media_sys_t *vlm_MediaSearch( vlm_t *, const char *);
@ -222,26 +216,14 @@ static bool ExecuteIsMedia( vlm_t *p_vlm, const char *psz_name )
return false;
return true;
}
static bool ExecuteIsSchedule( vlm_t *p_vlm, const char *psz_name )
{
if( !psz_name || !vlm_ScheduleSearch( p_vlm, psz_name ) )
return false;
return true;
}
static int ExecuteDel( vlm_t *p_vlm, const char *psz_name, vlm_message_t **pp_status )
{
vlm_media_sys_t *p_media;
vlm_schedule_sys_t *p_schedule;
p_media = vlm_MediaSearch( p_vlm, psz_name );
p_schedule = vlm_ScheduleSearch( p_vlm, psz_name );
if( p_schedule != NULL )
{
vlm_ScheduleDelete( p_vlm, p_schedule );
}
else if( p_media != NULL )
if( p_media != NULL )
{
vlm_ControlInternal( p_vlm, VLM_DEL_MEDIA, p_media->cfg.id );
}
@ -249,14 +231,9 @@ static int ExecuteDel( vlm_t *p_vlm, const char *psz_name, vlm_message_t **pp_st
{
vlm_ControlInternal( p_vlm, VLM_CLEAR_MEDIAS );
}
else if( !strcmp(psz_name, "schedule") )
{
vlm_ControlInternal( p_vlm, VLM_CLEAR_SCHEDULES );
}
else if( !strcmp(psz_name, "all") )
{
vlm_ControlInternal( p_vlm, VLM_CLEAR_MEDIAS );
vlm_ControlInternal( p_vlm, VLM_CLEAR_SCHEDULES );
}
else
{
@ -271,23 +248,19 @@ static int ExecuteDel( vlm_t *p_vlm, const char *psz_name, vlm_message_t **pp_st
static int ExecuteShow( vlm_t *p_vlm, const char *psz_name, vlm_message_t **pp_status )
{
vlm_media_sys_t *p_media;
vlm_schedule_sys_t *p_schedule;
if( !psz_name )
{
*pp_status = vlm_Show( p_vlm, NULL, NULL, NULL );
*pp_status = vlm_Show( p_vlm, NULL, NULL );
return VLC_SUCCESS;
}
p_media = vlm_MediaSearch( p_vlm, psz_name );
p_schedule = vlm_ScheduleSearch( p_vlm, psz_name );
if( p_schedule != NULL )
*pp_status = vlm_Show( p_vlm, NULL, p_schedule, NULL );
else if( p_media != NULL )
*pp_status = vlm_Show( p_vlm, p_media, NULL, NULL );
if( p_media != NULL )
*pp_status = vlm_Show( p_vlm, p_media, NULL );
else
*pp_status = vlm_Show( p_vlm, NULL, NULL, psz_name );
*pp_status = vlm_Show( p_vlm, NULL, psz_name );
return VLC_SUCCESS;
}
@ -304,10 +277,10 @@ static int ExecuteHelp( vlm_message_t **pp_status )
*pp_status = vlm_MessageSimpleNew( "help" );
message_child = MessageAdd( "Commands Syntax:" );
MessageAddChild( "new (name) broadcast|schedule [properties]" );
MessageAddChild( "new (name) broadcast [properties]" );
MessageAddChild( "setup (name) (properties)" );
MessageAddChild( "show [(name)|media|schedule]" );
MessageAddChild( "del (name)|all|media|schedule" );
MessageAddChild( "show [(name)|media]" );
MessageAddChild( "del (name)|all|media" );
MessageAddChild( "control (name) [instance_name] (command)" );
MessageAddChild( "save (config_file)" );
MessageAddChild( "export" );
@ -322,15 +295,6 @@ static int ExecuteHelp( vlm_message_t **pp_status )
MessageAddChild( "enabled|disabled" );
MessageAddChild( "loop|unloop" );
message_child = MessageAdd( "Schedule Proprieties Syntax:" );
MessageAddChild( "enabled|disabled" );
MessageAddChild( "append (command_until_rest_of_the_line)" );
MessageAddChild( "date (year)/(month)/(day)-(hour):(minutes):"
"(seconds)|now" );
MessageAddChild( "period (years_aka_12_months)/(months_aka_30_days)/"
"(days)-(hours):(minutes):(seconds)" );
MessageAddChild( "repeat (number_of_repetitions)" );
message_child = MessageAdd( "Control Commands Syntax:" );
MessageAddChild( "play [input_number]" );
MessageAddChild( "pause" );
@ -560,88 +524,6 @@ static int ExecuteLoad( vlm_t *p_vlm, const char *psz_path, vlm_message_t **pp_s
return VLC_SUCCESS;
}
static int ExecuteScheduleProperty( vlm_t *p_vlm, vlm_schedule_sys_t *p_schedule, bool b_new,
const int i_property, char *ppsz_property[], vlm_message_t **pp_status )
{
const char *psz_cmd = b_new ? "new" : "setup";
int i;
for( i = 0; i < i_property; i++ )
{
if( !strcmp( ppsz_property[i], "enabled" ) ||
!strcmp( ppsz_property[i], "disabled" ) )
{
if ( vlm_ScheduleSetup( p_vlm, p_schedule, ppsz_property[i], NULL ) )
goto error;
}
else if( !strcmp( ppsz_property[i], "append" ) )
{
char *psz_line, *psz_realloc;
int j, i_ret = VLC_SUCCESS;
/* Beware: everything behind append is considered as
* command line */
if( ++i >= i_property )
break;
psz_line = strdup( ppsz_property[i] );
if( unlikely(psz_line == NULL) )
goto error;
for( j = i+1; j < i_property; j++ )
{
psz_realloc = realloc( psz_line,
strlen(psz_line) + strlen(ppsz_property[j]) + 1 + 1 );
if( likely(psz_realloc) )
{
psz_line = psz_realloc;
strcat( psz_line, " " );
strcat( psz_line, ppsz_property[j] );
}
else
{
i_ret = VLC_ENOMEM;
break;
}
}
if( i_ret == VLC_SUCCESS )
i_ret = vlm_ScheduleSetup( p_vlm, p_schedule, "append", psz_line );
free( psz_line );
if( i_ret )
goto error;
break;
}
else
{
if( i + 1 >= i_property )
{
if( b_new )
vlm_ScheduleDelete( p_vlm, p_schedule );
return ExecuteSyntaxError( psz_cmd, pp_status );
}
if( vlm_ScheduleSetup( p_vlm, p_schedule, ppsz_property[i], ppsz_property[i+1] ) )
goto error;
i++;
}
}
*pp_status = vlm_MessageSimpleNew( psz_cmd );
vlc_mutex_lock( &p_vlm->lock_manage );
p_vlm->input_state_changed = true;
vlc_cond_signal( &p_vlm->wait_manage );
vlc_mutex_unlock( &p_vlm->lock_manage );
return VLC_SUCCESS;
error:
*pp_status = vlm_MessageNew( psz_cmd, "Error while setting the property '%s' to the schedule",
ppsz_property[i] );
return VLC_EGENERIC;
}
static int ExecuteMediaProperty( vlm_t *p_vlm, int64_t id, bool b_new,
const int i_property, char *ppsz_property[], vlm_message_t **pp_status )
{
@ -759,28 +641,18 @@ error:
static int ExecuteNew( vlm_t *p_vlm, const char *psz_name, const char *psz_type, const int i_property, char *ppsz_property[], vlm_message_t **pp_status )
{
/* Check name */
if( !strcmp( psz_name, "all" ) || !strcmp( psz_name, "media" ) || !strcmp( psz_name, "schedule" ) )
if( !strcmp( psz_name, "all" ) || !strcmp( psz_name, "media" ) )
{
*pp_status = vlm_MessageNew( "new", "\"all\", \"media\" and \"schedule\" are reserved names" );
*pp_status = vlm_MessageNew( "new", "\"all\" and \"media\" are reserved names" );
return VLC_EGENERIC;
}
if( ExecuteIsMedia( p_vlm, psz_name ) || ExecuteIsSchedule( p_vlm, psz_name ) )
if( ExecuteIsMedia( p_vlm, psz_name ) )
{
*pp_status = vlm_MessageNew( "new", "%s: Name already in use", psz_name );
return VLC_EGENERIC;
}
/* */
if( !strcmp( psz_type, "schedule" ) )
{
vlm_schedule_sys_t *p_schedule = vlm_ScheduleNew( p_vlm, psz_name );
if( !p_schedule )
{
*pp_status = vlm_MessageNew( "new", "could not create schedule" );
return VLC_EGENERIC;
}
return ExecuteScheduleProperty( p_vlm, p_schedule, true, i_property, ppsz_property, pp_status );
}
else if( !strcmp( psz_type, "broadcast" ) )
if( !strcmp( psz_type, "broadcast" ) )
{
vlm_media_t cfg;
int64_t id;
@ -797,26 +669,16 @@ static int ExecuteNew( vlm_t *p_vlm, const char *psz_name, const char *psz_type,
vlm_media_Clean( &cfg );
return ExecuteMediaProperty( p_vlm, id, true, i_property, ppsz_property, pp_status );
}
else if( !strcmp( psz_type, "vod" ) )
{
*pp_status = vlm_MessageNew( "new", "VoD support was removed" );
return VLC_EGENERIC;
}
else
{
*pp_status = vlm_MessageNew( "new", "%s: Choose between broadcast or schedule", psz_type );
*pp_status = vlm_MessageNew( "new", "%s: unsupported type", psz_type );
return VLC_EGENERIC;
}
}
static int ExecuteSetup( vlm_t *p_vlm, const char *psz_name, const int i_property, char *ppsz_property[], vlm_message_t **pp_status )
{
if( ExecuteIsSchedule( p_vlm, psz_name ) )
{
vlm_schedule_sys_t *p_schedule = vlm_ScheduleSearch( p_vlm, psz_name );
return ExecuteScheduleProperty( p_vlm, p_schedule, false, i_property, ppsz_property, pp_status );
}
else if( ExecuteIsMedia( p_vlm, psz_name ) )
if( ExecuteIsMedia( p_vlm, psz_name ) )
{
int64_t id;
if( vlm_ControlInternal( p_vlm, VLM_GET_MEDIA_ID, psz_name, &id ) )
@ -950,252 +812,6 @@ vlm_media_sys_t *vlm_MediaSearch( vlm_t *vlm, const char *psz_name )
return NULL;
}
/*****************************************************************************
* Schedule handling
*****************************************************************************/
static vlm_schedule_sys_t *vlm_ScheduleNew( vlm_t *vlm, const char *psz_name )
{
if( !psz_name )
return NULL;
vlm_schedule_sys_t *p_sched = malloc( sizeof( vlm_schedule_sys_t ) );
if( !p_sched )
return NULL;
p_sched->psz_name = strdup( psz_name );
p_sched->b_enabled = false;
p_sched->i_command = 0;
p_sched->command = NULL;
p_sched->date = 0;
p_sched->period = 0;
p_sched->i_repeat = -1;
TAB_APPEND( vlm->i_schedule, vlm->schedule, p_sched );
return p_sched;
}
/* for now, simple delete. After, del with options (last arg) */
void vlm_ScheduleDelete( vlm_t *vlm, vlm_schedule_sys_t *sched )
{
int i;
if( sched == NULL ) return;
TAB_REMOVE( vlm->i_schedule, vlm->schedule, sched );
if( vlm->i_schedule == 0 ) free( vlm->schedule );
free( sched->psz_name );
for ( i = 0; i < sched->i_command; i++ )
free( sched->command[i] );
free( sched->command );
free( sched );
}
static vlm_schedule_sys_t *vlm_ScheduleSearch( vlm_t *vlm, const char *psz_name )
{
int i;
for( i = 0; i < vlm->i_schedule; i++ )
{
if( strcmp( psz_name, vlm->schedule[i]->psz_name ) == 0 )
{
return vlm->schedule[i];
}
}
return NULL;
}
/* Ok, setup schedule command will be able to support only one (argument value) at a time */
static int vlm_ScheduleSetup( vlm_t *vlm, vlm_schedule_sys_t *schedule,
const char *psz_cmd, const char *psz_value )
{
if( !strcmp( psz_cmd, "enabled" ) )
{
schedule->b_enabled = true;
}
else if( !strcmp( psz_cmd, "disabled" ) )
{
schedule->b_enabled = false;
}
else if( !strcmp( psz_cmd, "date" ) )
{
struct tm time;
const char *p;
time.tm_sec = 0; /* seconds */
time.tm_min = 0; /* minutes */
time.tm_hour = 0; /* hours */
time.tm_mday = 0; /* day of the month */
time.tm_mon = 0; /* month */
time.tm_year = 0; /* year */
time.tm_wday = 0; /* day of the week */
time.tm_yday = 0; /* day in the year */
time.tm_isdst = -1; /* daylight saving time */
/* date should be year/month/day-hour:minutes:seconds */
p = strchr( psz_value, '-' );
if( !strcmp( psz_value, "now" ) )
{
schedule->date = 0;
}
else if(p == NULL)
{
return 1;
}
else
{
unsigned i,j,k;
switch( sscanf( p + 1, "%u:%u:%u", &i, &j, &k ) )
{
case 1:
time.tm_sec = i;
break;
case 2:
time.tm_min = i;
time.tm_sec = j;
break;
case 3:
time.tm_hour = i;
time.tm_min = j;
time.tm_sec = k;
break;
default:
return 1;
}
switch( sscanf( psz_value, "%d/%d/%d", &i, &j, &k ) )
{
case 1:
time.tm_mday = i;
break;
case 2:
time.tm_mon = i - 1;
time.tm_mday = j;
break;
case 3:
time.tm_year = i - 1900;
time.tm_mon = j - 1;
time.tm_mday = k;
break;
default:
return 1;
}
schedule->date = mktime(&time);
}
}
else if( !strcmp( psz_cmd, "period" ) )
{
struct tm time;
const char *p;
const char *psz_time = NULL, *psz_date = NULL;
unsigned i,j,k;
/* First, if date or period are modified, repeat should be equal to -1 */
schedule->i_repeat = -1;
time.tm_sec = 0; /* seconds */
time.tm_min = 0; /* minutes */
time.tm_hour = 0; /* hours */
time.tm_mday = 0; /* day of the month */
time.tm_mon = 0; /* month */
time.tm_year = 0; /* year */
time.tm_wday = 0; /* day of the week */
time.tm_yday = 0; /* day in the year */
time.tm_isdst = -1; /* daylight saving time */
/* date should be year/month/day-hour:minutes:seconds */
p = strchr( psz_value, '-' );
if( p )
{
psz_date = psz_value;
psz_time = p + 1;
}
else
{
psz_time = psz_value;
}
switch( sscanf( psz_time, "%u:%u:%u", &i, &j, &k ) )
{
case 1:
time.tm_sec = i;
break;
case 2:
time.tm_min = i;
time.tm_sec = j;
break;
case 3:
time.tm_hour = i;
time.tm_min = j;
time.tm_sec = k;
break;
default:
return 1;
}
if( psz_date )
{
switch( sscanf( psz_date, "%u/%u/%u", &i, &j, &k ) )
{
case 1:
time.tm_mday = i;
break;
case 2:
time.tm_mon = i;
time.tm_mday = j;
break;
case 3:
time.tm_year = i;
time.tm_mon = j;
time.tm_mday = k;
break;
default:
return 1;
}
}
/* ok, that's stupid... who is going to schedule streams every 42 years ? */
schedule->period = ((((time.tm_year * 12 + time.tm_mon) * 30
+ time.tm_mday) * 24 + time.tm_hour) * 60 + time.tm_min) * 60
+ time.tm_sec;
if( schedule->period >= 86400 || ( schedule->period > 0 &&
86400 % schedule->period == 0 && 3600 % schedule->period != 0 ) )
{
msg_Warn( vlm, "Repeating VLM schedules neither adjust for DST nor properly count calendar months or years" );
}
}
else if( !strcmp( psz_cmd, "repeat" ) )
{
int i;
if( sscanf( psz_value, "%d", &i ) == 1 )
{
schedule->i_repeat = i;
}
else
{
return 1;
}
}
else if( !strcmp( psz_cmd, "append" ) )
{
char *command = strdup( psz_value );
TAB_APPEND( schedule->i_command, schedule->command, command );
}
else
{
return 1;
}
return 0;
}
/*****************************************************************************
* Message handling functions
*****************************************************************************/
@ -1350,7 +966,6 @@ static vlm_message_t *vlm_ShowMedia( vlm_media_sys_t *p_media )
}
static vlm_message_t *vlm_Show( vlm_t *vlm, vlm_media_sys_t *media,
vlm_schedule_sys_t *schedule,
const char *psz_filter )
{
if( media != NULL )
@ -1361,80 +976,6 @@ static vlm_message_t *vlm_Show( vlm_t *vlm, vlm_media_sys_t *media,
return p_msg;
}
else if( schedule != NULL )
{
int i;
vlm_message_t *msg;
vlm_message_t *msg_schedule;
vlm_message_t *msg_child;
char buffer[100];
msg = vlm_MessageSimpleNew( "show" );
msg_schedule =
vlm_MessageAdd( msg, vlm_MessageSimpleNew( schedule->psz_name ) );
vlm_MessageAdd( msg_schedule, vlm_MessageNew("type", "schedule") );
vlm_MessageAdd( msg_schedule,
vlm_MessageNew( "enabled", schedule->b_enabled ?
"yes" : "no" ) );
if( schedule->date != 0 )
{
struct tm date;
localtime_r( &schedule->date, &date);
vlm_MessageAdd( msg_schedule,
vlm_MessageNew( "date", "%d/%d/%d-%d:%d:%d",
date.tm_year + 1900, date.tm_mon + 1,
date.tm_mday, date.tm_hour, date.tm_min,
date.tm_sec ) );
}
else
vlm_MessageAdd( msg_schedule, vlm_MessageNew("date", "now") );
if( schedule->period != 0 )
{
div_t d;
struct tm date;
d = div(schedule->period, 60);
date.tm_sec = d.rem;
d = div(d.quot, 60);
date.tm_min = d.rem;
d = div(d.quot, 24);
date.tm_hour = d.rem;
/* okay, okay, months are not always 30 days long */
d = div(d.quot, 30);
date.tm_mday = d.rem;
d = div(d.quot, 12);
date.tm_mon = d.rem;
date.tm_year = d.quot;
sprintf( buffer, "%d/%d/%d-%d:%d:%d", date.tm_year, date.tm_mon,
date.tm_mday, date.tm_hour, date.tm_min, date.tm_sec);
vlm_MessageAdd( msg_schedule, vlm_MessageNew("period", "%s", buffer) );
}
else
vlm_MessageAdd( msg_schedule, vlm_MessageNew("period", "0") );
sprintf( buffer, "%d", schedule->i_repeat );
vlm_MessageAdd( msg_schedule, vlm_MessageNew( "repeat", "%s", buffer ) );
msg_child =
vlm_MessageAdd( msg_schedule, vlm_MessageSimpleNew("commands" ) );
for( i = 0; i < schedule->i_command; i++ )
{
vlm_MessageAdd( msg_child,
vlm_MessageSimpleNew( schedule->command[i] ) );
}
return msg;
}
else if( psz_filter && !strcmp( psz_filter, "media" ) )
{
vlm_message_t *p_msg;
@ -1451,72 +992,9 @@ static vlm_message_t *vlm_Show( vlm_t *vlm, vlm_media_sys_t *media,
return p_msg;
}
else if( psz_filter && !strcmp( psz_filter, "schedule" ) )
else if( ( psz_filter == NULL ) && ( media == NULL ) )
{
int i;
vlm_message_t *msg;
vlm_message_t *msg_child;
msg = vlm_MessageSimpleNew( "show" );
msg_child = vlm_MessageAdd( msg, vlm_MessageSimpleNew( "schedule" ) );
for( i = 0; i < vlm->i_schedule; i++ )
{
vlm_schedule_sys_t *s = vlm->schedule[i];
vlm_message_t *msg_schedule;
time_t now, next_date;
msg_schedule = vlm_MessageAdd( msg_child,
vlm_MessageSimpleNew( s->psz_name ) );
vlm_MessageAdd( msg_schedule,
vlm_MessageNew( "enabled", s->b_enabled ?
"yes" : "no" ) );
/* calculate next date */
time(&now);
next_date = s->date;
if( s->period != 0 )
{
int j = 0;
while( ((s->date + j * s->period) <= now) &&
( s->i_repeat > j || s->i_repeat < 0 ) )
{
j++;
}
next_date = s->date + j * s->period;
}
if( next_date > now )
{
struct tm tm;
char psz_date[32];
strftime( psz_date, sizeof(psz_date), "%Y-%m-%d %H:%M:%S (%a)",
localtime_r( &next_date, &tm ) );
vlm_MessageAdd( msg_schedule,
vlm_MessageNew( "next launch", "%s", psz_date ) );
}
}
return msg;
}
else if( ( psz_filter == NULL ) && ( media == NULL ) && ( schedule == NULL ) )
{
vlm_message_t *show1 = vlm_Show( vlm, NULL, NULL, "media" );
vlm_message_t *show2 = vlm_Show( vlm, NULL, NULL, "schedule" );
vlm_MessageAdd( show1, show2->child[0] );
/* We must destroy the parent node "show" of show2
* and not the children */
free( show2->child );
free( show2->psz_name );
free( show2 );
return show1;
return vlm_Show( vlm, NULL, "media" );
}
else
@ -1607,54 +1085,6 @@ VLC_MALLOC static char *Save( vlm_t *vlm )
p_cfg->psz_name, p_cfg->ppsz_option[j] );
}
/* and now, the schedule scripts */
for( int i = 0; i < vlm->i_schedule; i++ )
{
vlm_schedule_sys_t *schedule = vlm->schedule[i];
struct tm tm;
localtime_r( &schedule->date, &tm );
vlc_memstream_printf( &stream, "new %s schedule date "
"%d/%d/%d-%d:%d:%d %sabled\n",
schedule->psz_name,
tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
tm.tm_hour, tm.tm_min, tm.tm_sec,
schedule->b_enabled ? "en" : "dis" );
if( schedule->period != 0 )
{
div_t d;
d = div(schedule->period, 60);
tm.tm_sec = d.rem;
d = div(d.quot, 60);
tm.tm_min = d.rem;
d = div(d.quot, 24);
tm.tm_hour = d.rem;
d = div(d.quot, 30);
tm.tm_mday = d.rem;
/* okay, okay, months are not always 30 days long */
d = div(d.quot, 12);
tm.tm_mon = d.rem;
tm.tm_year = d.quot;
vlc_memstream_printf( &stream, "setup %s "
"period %d/%d/%d-%d:%d:%d\n",
schedule->psz_name,
tm.tm_year, tm.tm_mon, tm.tm_mday,
tm.tm_hour, tm.tm_min, tm.tm_sec);
}
if( schedule->i_repeat >= 0 )
vlc_memstream_printf( &stream, "setup %s repeat %d",
schedule->psz_name, schedule->i_repeat );
vlc_memstream_putc( &stream, '\n' );
for( int j = 0; j < schedule->i_command; j++ )
vlc_memstream_printf( &stream, "setup %s append %s\n",
schedule->psz_name, schedule->command[j] );
}
if( vlc_memstream_close( &stream ) )
return NULL;
return stream.ptr;

Loading…
Cancel
Save