1 /*****************************************************************************
2 * vlm.c: VLM interface plugin
3 *****************************************************************************
4 * Copyright (C) 2000, 2001 VideoLAN
7 * Authors: Simon Latapie <garf@videolan.org>
8 * Laurent Aimar <fenrir@videolan.org>
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
23 *****************************************************************************/
25 /*****************************************************************************
27 *****************************************************************************/
28 #include <stdlib.h> /* malloc(), free() */
32 #include <vlc/input.h>
35 # include <time.h> /* ctime() */
40 /*****************************************************************************
42 *****************************************************************************/
43 static char *vlm_Save( vlm_t * );
44 static int vlm_Load( vlm_t *, char *);
45 static vlm_message_t *vlm_Show( vlm_t *, vlm_media_t *, vlm_schedule_t *, char * );
46 static vlm_message_t *vlm_Help( vlm_t *, char * );
48 static vlm_media_t *vlm_MediaNew ( vlm_t *, char *, int );
49 static int vlm_MediaDelete ( vlm_t *, vlm_media_t *, char * );
50 static vlm_media_t *vlm_MediaSearch ( vlm_t *, char * );
51 static int vlm_MediaSetup ( vlm_media_t *, char *, char * );
52 static int vlm_MediaControl( vlm_t *, vlm_media_t *, char *, char * );
54 static vlm_message_t* vlm_MessageNew( char * , char * );
55 static vlm_message_t* vlm_MessageAdd( vlm_message_t*, vlm_message_t* );
57 static vlm_schedule_t *vlm_ScheduleNew( vlm_t *, char *);
58 static int vlm_ScheduleDelete( vlm_t *, vlm_schedule_t *, char *);
59 static int vlm_ScheduleSetup( vlm_schedule_t *, char *, char *);
60 static vlm_schedule_t *vlm_ScheduleSearch( vlm_t *, char *);
63 static int ExecuteCommand( vlm_t *, char * , vlm_message_t **);
65 static int Manage( vlc_object_t* );
67 /*****************************************************************************
69 *****************************************************************************/
70 vlm_t *__vlm_New ( vlc_object_t *p_this )
75 /* to be sure to avoid multiple creation */
76 var_Create( p_this->p_libvlc, "vlm_mutex", VLC_VAR_MUTEX );
77 var_Get( p_this->p_libvlc, "vlm_mutex", &lockval );
78 vlc_mutex_lock( lockval.p_address );
80 if( !(vlm = vlc_object_find( p_this, VLC_OBJECT_VLM, FIND_ANYWHERE )) )
82 msg_Info( p_this, "creating vlm" );
83 if( ( vlm = vlc_object_create( p_this, VLC_OBJECT_VLM ) ) == NULL )
85 vlc_mutex_unlock( lockval.p_address );
89 vlc_mutex_init( p_this->p_vlc, &vlm->lock );
95 vlc_object_yield( vlm );
96 vlc_object_attach( vlm, p_this->p_vlc );
98 vlc_mutex_unlock( lockval.p_address );
101 if( vlc_thread_create( vlm, "vlm thread",
102 Manage, VLC_THREAD_PRIORITY_LOW, VLC_FALSE ) )
104 vlc_mutex_destroy( &vlm->lock );
105 vlc_object_destroy( vlm );
111 /*****************************************************************************
113 *****************************************************************************/
114 void vlm_Delete( vlm_t *vlm )
119 var_Get( vlm->p_libvlc, "vlm_mutex", &lockval );
120 vlc_mutex_lock( lockval.p_address );
122 vlc_object_release( vlm );
124 if( vlm->i_refcount > 0 )
126 vlc_mutex_unlock( lockval.p_address );
130 vlm->b_die = VLC_TRUE;
131 vlc_thread_join( vlm );
133 vlc_mutex_destroy( &vlm->lock );
135 for( i = 0; i < vlm->i_media; i++ )
137 vlm_media_t *media = vlm->media[i];
139 vlm_MediaDelete( vlm, media, NULL );
142 if( vlm->media ) free( vlm->media );
144 for( i = 0; i < vlm->i_schedule; i++ )
146 vlm_ScheduleDelete( vlm, vlm->schedule[i], NULL );
149 if( vlm->schedule ) free( vlm->schedule );
151 vlc_object_detach( vlm );
152 vlc_object_destroy( vlm );
153 vlc_mutex_unlock( lockval.p_address );
156 /*****************************************************************************
157 * vlm_ExecuteCommand:
158 *****************************************************************************/
159 int vlm_ExecuteCommand( vlm_t *vlm, char *command, vlm_message_t **message)
163 vlc_mutex_lock( &vlm->lock );
164 result = ExecuteCommand( vlm, command, message );
165 vlc_mutex_unlock( &vlm->lock );
171 /*****************************************************************************
173 *****************************************************************************/
175 static char *FindEndCommand( char *psz )
185 while( ( *s_sent != '\"' ) && ( *s_sent != '\0' ) )
187 if( *s_sent == '\'' )
189 s_sent = FindEndCommand( s_sent );
202 if( *s_sent == '\"' )
207 else /* *s_sent == '\0' , which means the number of " is incorrect */
217 while( ( *s_sent != '\'' ) && ( *s_sent != '\0' ) )
219 if( *s_sent == '\"' )
221 s_sent = FindEndCommand( s_sent );
234 if( *s_sent == '\'' )
239 else /* *s_sent == '\0' , which means the number of ' is incorrect */
245 default: /* now we can look for spaces */
247 while( ( *s_sent != ' ' ) && ( *s_sent != '\0' ) )
249 if( ( *s_sent == '\'' ) || ( *s_sent == '\"' ) )
251 s_sent = FindEndCommand( s_sent );
263 static char *FindEndCommand( char *psz )
268 *psz != ' ' && *psz != '\t' &&
269 *psz != '\n' && *psz != '\r' )
271 if( *psz == '\'' || *psz == '"' )
275 while( *psz && *psz != d && *psz != *psz != '\n' && *psz != '\r' )
277 if( ( d == '\'' && *psz == '"' ) ||
278 ( d == '"' && *psz == '\'' ) )
280 psz = FindEndCommand( psz );
294 /* Execute a command which ends by '\0' (string) */
295 static int ExecuteCommand( vlm_t *vlm, char *command , vlm_message_t **p_message)
299 char **p_command = NULL;
302 vlm_message_t * message = NULL;
304 /* First, parse the line and cut it */
305 while( *cmd != '\0' )
317 p_temp = FindEndCommand( cmd );
325 i_temp = p_temp - cmd;
327 p_command = realloc( p_command , (i_command + 1) * sizeof( char* ) );
328 p_command[ i_command ] = malloc( (i_temp + 1) * sizeof( char ) ); // don't forget the '\0'
329 strncpy( p_command[ i_command ] , cmd , i_temp );
330 (p_command[ i_command ])[ i_temp ] = '\0';
337 /* And then Interpret it */
341 message = vlm_MessageNew( "" , NULL );
346 if( strcmp(p_command[0] , "segfault") == 0 )
348 /* the only command we really need */
351 else if( strcmp(p_command[0] , "new") == 0 )
357 vlm_schedule_t *schedule;
359 if( strcmp(p_command[2] , "schedule") == 0 )
361 /* new vlm_schedule */
362 if( vlm_ScheduleSearch( vlm , p_command[1] ) != NULL || strcmp(p_command[1] , "schedule") == 0 )
364 char *error_message = malloc( strlen(p_command[1]) + strlen(" is already used") + 1 );
365 sprintf( error_message, "%s is already used" , p_command[1] );
366 message = vlm_MessageNew( "new" , error_message );
367 free( error_message );
372 schedule = vlm_ScheduleNew( vlm , p_command[1] );
375 if( i_command > 3 ) // hey, there are properties
377 for( i = 3 ; i < i_command ; i++ )
379 if( strcmp( p_command[i] , "enabled" ) == 0 || strcmp( p_command[i] , "disabled" ) == 0 )
381 vlm_ScheduleSetup( schedule, p_command[i], NULL );
383 /* Beware: evrything behind append is considered as command line */
384 else if( strcmp( p_command[i] , "append" ) == 0 )
391 for( j = (i + 1); j < i_command; j++ )
393 p_command[i] = realloc( p_command[i], strlen(p_command[i]) + strlen(p_command[j]) + 1 + 1);
394 strcat( p_command[i], " " );
395 strcat( p_command[i], p_command[j] );
398 vlm_ScheduleSetup( schedule, p_command[i - 1], p_command[i] );
404 if( (i+1) < i_command )
406 vlm_ScheduleSetup( schedule, p_command[i], p_command[i+1] );
411 vlm_ScheduleDelete( vlm, schedule, NULL );
412 message = vlm_MessageNew( p_command[i], "Wrong properties syntax" );
419 message = vlm_MessageNew( "new" , NULL );
424 message = vlm_MessageNew( "new" , NULL );
429 if( strcmp(p_command[2] , "vod") == 0 )
433 else if( strcmp(p_command[2] , "broadcast") == 0 )
435 i_type = BROADCAST_TYPE;
439 char *error_message = malloc( strlen(p_command[1]) + strlen(": Choose between vod or broadcast") + 1 );
440 sprintf( error_message, "%s: Choose between vod or broadcast" , p_command[1] );
441 message = vlm_MessageNew( "new" , error_message );
442 free( error_message );
448 if( vlm_MediaSearch( vlm , p_command[1] ) != NULL || strcmp(p_command[1] , "media") == 0 )
450 char *error_message = malloc( strlen(p_command[1]) + strlen(" is already used") + 1 );
451 sprintf( error_message, "%s is already used" , p_command[1] );
452 message = vlm_MessageNew( "new" , error_message );
453 free( error_message );
458 media = vlm_MediaNew( vlm , p_command[1] , i_type );
460 if( i_command > 3 ) // hey, there are properties
462 for( i = 3 ; i < i_command ; i++ )
464 if( strcmp( p_command[i] , "enabled" ) == 0 || strcmp( p_command[i] , "disabled" ) == 0 )
466 vlm_MediaSetup( media, p_command[i], NULL );
470 if( (i+1) < i_command )
472 vlm_MediaSetup( media, p_command[i], p_command[i+1] );
477 vlm_MediaDelete( vlm, media, NULL );
478 message = vlm_MessageNew( p_command[i] , "Wrong properties syntax" );
485 message = vlm_MessageNew( "new" , NULL );
490 message = vlm_MessageNew( "new" , NULL );
496 message = vlm_MessageNew( "new" , "Wrong command syntax" );
501 else if( strcmp(p_command[0] , "del") == 0 )
506 vlm_schedule_t *schedule;
508 media = vlm_MediaSearch( vlm , p_command[1] );
509 schedule = vlm_ScheduleSearch( vlm , p_command[1] );
511 if( schedule != NULL )
513 vlm_ScheduleDelete( vlm, schedule, NULL );
514 message = vlm_MessageNew( "del" , NULL );
518 else if( media != NULL )
520 vlm_MediaDelete( vlm, media, NULL );
521 message = vlm_MessageNew( "del" , NULL );
525 else if( strcmp(p_command[1] , "media") == 0 )
527 for( i = 0; i < vlm->i_media; i++ )
529 vlm_MediaDelete( vlm, vlm->media[i], NULL );
532 else if( strcmp(p_command[1] , "schedule") == 0 )
534 for( i = 0; i < vlm->i_schedule; i++ )
536 vlm_ScheduleDelete( vlm, vlm->schedule[i], NULL );
539 else if( strcmp(p_command[1] , "all") == 0 )
541 for( i = 0; i < vlm->i_media; i++ )
543 vlm_MediaDelete( vlm, vlm->media[i], NULL );
546 for( i = 0; i < vlm->i_schedule; i++ )
548 vlm_ScheduleDelete( vlm, vlm->schedule[i], NULL );
553 char *error_message = malloc( strlen(p_command[1]) + strlen(": media unknown") + 1 );
554 sprintf( error_message, "%s: media unknown" , p_command[1] );
555 message = vlm_MessageNew( "del" , error_message );
556 free( error_message );
563 message = vlm_MessageNew( "setup" , "Wrong command syntax" );
568 else if( strcmp(p_command[0] , "show") == 0 )
572 message = vlm_Show( vlm, NULL , NULL, NULL );
576 else if( i_command == 2 )
579 vlm_schedule_t *schedule;
581 media = vlm_MediaSearch( vlm , p_command[1] );
582 schedule = vlm_ScheduleSearch( vlm , p_command[1] );
584 if( schedule != NULL )
586 message = vlm_Show( vlm, NULL, schedule, NULL );
588 else if( media != NULL )
590 message = vlm_Show( vlm, media, NULL, NULL );
594 message = vlm_Show( vlm, NULL, NULL, p_command[1] );
602 message = vlm_MessageNew( "show" , "Wrong command syntax" );
607 else if( strcmp(p_command[0] , "help") == 0 )
611 message = vlm_Help( vlm, NULL );
617 message = vlm_MessageNew( "help" , "Wrong command syntax" );
622 else if( strcmp(p_command[0] , "setup") == 0 )
627 vlm_schedule_t *schedule;
629 media = vlm_MediaSearch( vlm , p_command[1] );
630 schedule = vlm_ScheduleSearch( vlm , p_command[1] );
632 if( schedule != NULL )
634 for( i = 2 ; i < i_command ; i++ )
636 if( strcmp( p_command[i] , "enabled" ) == 0 || strcmp( p_command[i] , "disabled" ) == 0 )
638 vlm_ScheduleSetup( schedule, p_command[i], NULL );
640 /* Beware: evrything behind append is considered as command line */
641 else if( strcmp( p_command[i] , "append" ) == 0 )
648 for( j = (i + 1); j < i_command; j++ )
650 p_command[i] = realloc( p_command[i], strlen(p_command[i]) + strlen(p_command[j]) + 1 + 1);
651 strcat( p_command[i], " " );
652 strcat( p_command[i], p_command[j] );
655 vlm_ScheduleSetup( schedule, p_command[i - 1], p_command[i] );
661 if( (i+1) < i_command )
663 vlm_ScheduleSetup( schedule, p_command[i], p_command[i+1] );
668 vlm_ScheduleDelete( vlm, schedule, NULL );
669 message = vlm_MessageNew( "setup" , "Wrong properties syntax" );
676 message = vlm_MessageNew( "setup" , NULL );
680 else if( media != NULL )
682 for( i = 2 ; i < i_command ; i++ )
684 if( strcmp( p_command[i] , "enabled" ) == 0 || strcmp( p_command[i] , "disabled" ) == 0 )
685 { /* only one argument */
686 vlm_MediaSetup( media, p_command[i], NULL );
688 else if( strcmp( p_command[i] , "loop" ) == 0 || strcmp( p_command[i] , "unloop" ) == 0 )
690 if( media->i_type != BROADCAST_TYPE )
692 message = vlm_MessageNew( "setup" , "lool only available for broadcast" );
698 vlm_MediaSetup( media, p_command[i], NULL );
703 if( (i+1) < i_command )
705 vlm_MediaSetup( media, p_command[i], p_command[i+1] );
710 vlm_MediaDelete( vlm, media, NULL );
711 message = vlm_MessageNew( "setup" , "Wrong properties syntax" );
718 message = vlm_MessageNew( "setup" , NULL );
724 char *error_message = malloc( strlen(p_command[1]) + strlen(" unknown") + 1 );
725 sprintf( error_message, "%s unknown" , p_command[1] );
726 message = vlm_MessageNew( "setup" , error_message );
727 free( error_message );
735 message = vlm_MessageNew( "setup" , "Wrong command syntax" );
740 else if( strcmp(p_command[0] , "control") == 0 )
747 media = vlm_MediaSearch( vlm , p_command[1] );
751 char *error_message = malloc( strlen(p_command[1]) + strlen(": media unknown") + 1 );
752 sprintf( error_message, "%s: media unknown" , p_command[1] );
753 message = vlm_MessageNew( "control" , error_message );
754 free( error_message );
764 psz_args = p_command[3];
772 vlm_MediaControl( vlm, media, p_command[2], psz_args );
773 message = vlm_MessageNew( "control" , NULL );
780 message = vlm_MessageNew( "control" , "Wrong command syntax" );
785 else if( strcmp(p_command[0] , "save") == 0 )
792 file = fopen( p_command[1], "w" );
796 message = vlm_MessageNew( "save" , "Unable to save file" );
804 save = vlm_Save( vlm );
806 fwrite( save, strlen( save ) , 1 , file );
809 message = vlm_MessageNew( "save" , NULL );
816 message = vlm_MessageNew( "save" , "Wrong command" );
821 else if( strcmp(p_command[0] , "load") == 0 )
828 file = fopen( p_command[1], "r" );
832 message = vlm_MessageNew( "load" , "Unable to load file" );
841 if( fseek( file, 0, SEEK_END) == 0 )
843 size = ftell( file );
844 fseek( file, 0, SEEK_SET);
845 buffer = malloc( size + 1 );
846 fread( buffer, 1, size, file);
847 buffer[ size ] = '\0';
848 if( vlm_Load( vlm, buffer ) )
851 message = vlm_MessageNew( "load" , "error while loading file" );
859 message = vlm_MessageNew( "load" , "read file error" );
864 message = vlm_MessageNew( "load" , NULL );
871 message = vlm_MessageNew( "load" , "Wrong command" );
878 message = vlm_MessageNew( p_command[0] , "Unknown comand" );
885 for( i = 0 ; i < i_command ; i++ )
887 free( p_command[i] );
890 *p_message = message;
896 static vlm_media_t *vlm_MediaSearch( vlm_t *vlm, char *psz_name )
900 for( i = 0; i < vlm->i_media; i++ )
902 if( strcmp( psz_name, vlm->media[i]->psz_name ) == 0 )
904 return vlm->media[i];
912 static vlm_media_t *vlm_MediaNew( vlm_t *vlm , char *psz_name, int i_type )
914 vlm_media_t *media= malloc( sizeof( vlm_media_t ));
916 media->psz_name = strdup( psz_name );
917 media->b_enabled = VLC_FALSE;
918 media->b_loop = VLC_FALSE;
922 media->psz_output = NULL;
924 media->option = NULL;
925 media->i_input_option = 0;
926 media->input_option = NULL;
927 media->i_type = i_type;
928 media->p_input = NULL;
930 TAB_APPEND( vlm->i_media , vlm->media , media );
936 /* for now, simple delete. After, del with options (last arg) */
937 static int vlm_MediaDelete( vlm_t *vlm, vlm_media_t *media, char *psz_name )
948 input_StopThread( media->p_input );
950 input_DestroyThread( media->p_input );
951 vlc_object_detach( media->p_input );
952 vlc_object_destroy( media->p_input );
955 TAB_REMOVE( vlm->i_media, vlm->media , media );
957 if( vlm->i_media == 0 && vlm->media ) free( vlm->media );
959 free( media->psz_name );
961 for( i = 0; i < media->i_input; i++ )
963 free( media->input[i] );
965 if( media->input ) free( media->input );
967 if( media->psz_output ) free( media->psz_output );
969 for( i = 0; i < media->i_option; i++ )
971 free( media->option[i] );
973 if(media->option) free( media->option );
975 for( i = 0; i < media->i_input_option; i++ )
977 free( media->input_option[i] );
979 if( media->input_option ) free( media->input_option );
987 static int vlm_MediaSetup( vlm_media_t *media, char *psz_cmd, char *psz_value )
989 if( strcmp( psz_cmd, "loop" ) == 0 )
991 media->b_loop = VLC_TRUE;
993 else if( strcmp( psz_cmd, "unloop" ) == 0 )
995 media->b_loop = VLC_FALSE;
997 else if( strcmp( psz_cmd, "enabled" ) == 0 )
999 media->b_enabled = VLC_TRUE;
1001 else if( strcmp( psz_cmd, "disabled" ) == 0 )
1003 media->b_enabled = VLC_FALSE;
1005 else if( strcmp( psz_cmd, "input" ) == 0 )
1009 if( psz_value != NULL && strlen(psz_value) > 1 && ( psz_value[0] == '\'' || psz_value[0] == '\"' )
1010 && ( psz_value[ strlen(psz_value) - 1 ] == '\'' || psz_value[ strlen(psz_value) - 1 ] == '\"' ) )
1012 input = malloc( strlen(psz_value) - 1 );
1014 memcpy( input , psz_value + 1 , strlen(psz_value) - 2 );
1015 input[ strlen(psz_value) - 2 ] = '\0';
1019 input = strdup( psz_value );
1022 TAB_APPEND( media->i_input, media->input, input );
1024 else if( strcmp( psz_cmd, "output" ) == 0 )
1026 if( media->psz_output != NULL )
1028 free( media->psz_output );
1030 media->psz_output = strdup( psz_value );
1032 else if( strcmp( psz_cmd, "option" ) == 0 )
1035 option = strdup( psz_value );
1037 TAB_APPEND( media->i_option, media->option, option );
1046 static int vlm_MediaControl( vlm_t *vlm, vlm_media_t *media, char *psz_name, char *psz_args )
1048 if( strcmp( psz_name, "play" ) == 0 )
1052 if( media->b_enabled == VLC_TRUE )
1054 if( psz_args != NULL && sscanf( psz_args, "%d", &i ) == 1 && i < media->i_input )
1063 if( media->psz_output != NULL )
1065 media->input_option = malloc( sizeof( char* ) );
1066 media->input_option[0] = malloc( strlen(media->psz_output) + 1 + 6 );
1067 sprintf( media->input_option[0], ":sout=%s" , media->psz_output );
1068 media->i_input_option = 1;
1072 media->input_option = NULL;
1073 media->i_input_option = 0;
1076 for( i=0 ; i < media->i_option ; i++ )
1078 media->i_input_option++;
1079 media->input_option = realloc( media->input_option, (media->i_input_option) * sizeof( char* ) );
1080 media->input_option[ media->i_input_option - 1 ] = malloc( strlen(media->option[i]) + 1 + 1 );
1081 sprintf( media->input_option[ media->i_input_option - 1 ], ":%s" , media->option[i] );
1084 media->p_input = input_CreateThread( vlm, media->input[media->i_index], media->input_option, media->i_input_option );
1093 else if( strcmp( psz_name, "seek" ) == 0 )
1098 if( psz_args && sscanf( psz_args, "%f", &f_percentage ) == 1 )
1100 val.f_float = f_percentage / 100.0 ;
1101 var_Set( media->p_input, "position", val );
1105 else if( strcmp( psz_name, "stop" ) == 0 )
1109 if( media->p_input );
1111 input_StopThread( media->p_input );
1112 input_DestroyThread( media->p_input );
1113 vlc_object_detach( media->p_input );
1114 vlc_object_destroy( media->p_input );
1115 media->p_input = NULL;
1117 for( i=0 ; i < media->i_input_option ; i++ )
1119 free( media->input_option[i] );
1121 if( media->input_option) free( media->input_option );
1123 media->input_option = NULL;
1124 media->i_input_option = 0;
1129 else if( strcmp( psz_name, "pause" ) == 0 )
1135 if( media->p_input != NULL )
1137 var_Get( media->p_input, "state", &val );
1140 if( val.i_int == PAUSE_S )
1142 if( media->p_input )
1144 val.i_int = PLAYING_S;
1145 var_Set( media->p_input, "state", val );
1150 if( media->p_input )
1152 val.i_int = PAUSE_S;
1153 var_Set( media->p_input, "state", val );
1162 static vlm_message_t *vlm_Show( vlm_t *vlm, vlm_media_t *media, vlm_schedule_t *schedule, char *psz_filter )
1168 vlm_message_t *message;
1169 vlm_message_t *message_media;
1170 vlm_message_t *message_child;
1172 message = vlm_MessageNew( "show" , NULL );
1173 message_media = vlm_MessageAdd( message , vlm_MessageNew( media->psz_name , NULL ) );
1175 if( media->i_type == VOD_TYPE )
1177 vlm_MessageAdd( message_media , vlm_MessageNew( "type" , "vod" ) );
1181 vlm_MessageAdd( message_media , vlm_MessageNew( "type" , "broadcast" ) );
1184 if( media->b_enabled == VLC_TRUE )
1186 vlm_MessageAdd( message_media , vlm_MessageNew( "enabled" , "yes" ) );
1190 vlm_MessageAdd( message_media , vlm_MessageNew( "enabled" , "no" ) );
1193 if( media->b_loop == VLC_TRUE )
1195 vlm_MessageAdd( message_media , vlm_MessageNew( "loop" , "yes" ) );
1198 message_child = vlm_MessageAdd( message_media , vlm_MessageNew( "inputs" , NULL ) );
1200 for( i=0 ; i < (media->i_input) ; i++ )
1202 vlm_MessageAdd( message_child , vlm_MessageNew( media->input[i] , NULL ) );
1205 if( media->psz_output != NULL )
1207 vlm_MessageAdd( message_media , vlm_MessageNew( "output" , media->psz_output ) );
1210 message_child = vlm_MessageAdd( message_media , vlm_MessageNew( "options" , NULL ) );
1212 for( i=0 ; i < (media->i_option) ; i++ )
1214 vlm_MessageAdd( message_child , vlm_MessageNew( media->option[i] , NULL ) );
1217 if( media->p_input != NULL )
1221 var_Get( media->p_input, "state", &val );
1223 if( val.i_int == PLAYING_S )
1225 vlm_MessageAdd( message_media , vlm_MessageNew( "state" , "playing" ) );
1227 else if( val.i_int == PAUSE_S )
1229 vlm_MessageAdd( message_media , vlm_MessageNew( "state" , "paused" ) );
1233 vlm_MessageAdd( message_media , vlm_MessageNew( "state" , "stop" ) );
1238 vlm_MessageAdd( message_media , vlm_MessageNew( "state" , "stop" ) );
1244 else if( schedule != NULL )
1247 vlm_message_t *message;
1248 vlm_message_t *message_schedule;
1249 vlm_message_t *message_child;
1251 message = vlm_MessageNew( "show" , NULL );
1252 message_schedule = vlm_MessageAdd( message , vlm_MessageNew( schedule->psz_name , NULL ) );
1254 vlm_MessageAdd( message_schedule , vlm_MessageNew( "type" , "schedule" ) );
1256 if( schedule->b_enabled == VLC_TRUE )
1258 vlm_MessageAdd( message_schedule , vlm_MessageNew( "enabled" , "yes" ) );
1262 vlm_MessageAdd( message_schedule , vlm_MessageNew( "enabled" , "no" ) );
1265 if( schedule->i_date != 0 )
1267 time_t i_time = schedule->i_date / (int64_t)1000000;
1271 ctime_r( &i_time, psz_date );
1273 char *psz_date = ctime( &i_time );
1275 vlm_MessageAdd( message_schedule , vlm_MessageNew( "date" , psz_date ) );
1279 vlm_MessageAdd( message_schedule , vlm_MessageNew( "date" , "now" ) );
1282 if( schedule->i_period != 0 )
1285 time_t i_time = (time_t) ( schedule->i_period / 1000000 );
1288 date.tm_sec = (int)( i_time % 60 );
1289 i_time = i_time / 60;
1290 date.tm_min = (int)( i_time % 60 );
1291 i_time = i_time / 60;
1292 date.tm_hour = (int)( i_time % 24 );
1293 i_time = i_time / 24;
1294 date.tm_mday = (int)( i_time % 30 );
1295 i_time = i_time / 30;
1296 /* okay, okay, months are not always 30 days long */
1297 date.tm_mon = (int)( i_time % 12 );
1298 i_time = i_time / 12;
1299 date.tm_year = (int)i_time;
1301 sprintf( buffer, "%d years %d months %d days %d hours %d minutes %d seconds", date.tm_year ,
1308 vlm_MessageAdd( message_schedule , vlm_MessageNew( "period" , buffer ) );
1310 if( schedule->i_repeat >= 0 )
1312 sprintf( buffer, "%d" , schedule->i_repeat );
1313 vlm_MessageAdd( message_schedule , vlm_MessageNew( "repeat" , buffer ) );
1317 message_child = vlm_MessageAdd( message_schedule , vlm_MessageNew( "commands" , NULL ) );
1319 for( i=0 ; i < (schedule->i_command) ; i++ )
1321 vlm_MessageAdd( message_child , vlm_MessageNew( schedule->command[i] , NULL ) );
1327 else if( psz_filter && strcmp( psz_filter , "media") == 0 )
1330 vlm_message_t *message;
1331 vlm_message_t *message_child;
1333 message = vlm_MessageNew( "show" , NULL );
1334 message_child = vlm_MessageAdd( message , vlm_MessageNew( "media" , NULL ) );
1336 for( i = 0; i < vlm->i_media; i++ )
1338 vlm_media_t *m = vlm->media[i];
1339 vlm_message_t *message_media = vlm_MessageAdd( message_child , vlm_MessageNew( m->psz_name , NULL ) );
1341 if( m->i_type == VOD_TYPE )
1343 vlm_MessageAdd( message_media , vlm_MessageNew( "type" , "vod" ) );
1347 vlm_MessageAdd( message_media , vlm_MessageNew( "type" , "broadcast" ) );
1350 if( m->b_enabled == VLC_TRUE )
1352 vlm_MessageAdd( message_media , vlm_MessageNew( "enabled" , "yes" ) );
1356 vlm_MessageAdd( message_media , vlm_MessageNew( "enabled" , "no" ) );
1359 if( m->p_input != NULL )
1363 var_Get( m->p_input, "state", &val );
1365 if( val.i_int == PLAYING_S )
1367 vlm_MessageAdd( message_media , vlm_MessageNew( "state" , "playing" ) );
1369 else if( val.i_int == PAUSE_S )
1371 vlm_MessageAdd( message_media , vlm_MessageNew( "state" , "paused" ) );
1375 vlm_MessageAdd( message_media , vlm_MessageNew( "state" , "stop" ) );
1380 vlm_MessageAdd( message_media , vlm_MessageNew( "state" , "stop" ) );
1386 else if( psz_filter && strcmp( psz_filter , "schedule") == 0 )
1389 vlm_message_t *message;
1390 vlm_message_t *message_child;
1392 message = vlm_MessageNew( "show" , NULL );
1393 message_child = vlm_MessageAdd( message , vlm_MessageNew( "schedule" , NULL ) );
1395 for( i = 0; i < vlm->i_schedule; i++ )
1397 vlm_schedule_t *s = vlm->schedule[i];
1398 vlm_message_t *message_schedule = vlm_MessageAdd( message_child , vlm_MessageNew( s->psz_name , NULL ) );
1400 if( s->b_enabled == VLC_TRUE )
1403 mtime_t i_next_date;
1405 vlm_MessageAdd( message_schedule , vlm_MessageNew( "enabled" , "yes" ) );
1407 /* calculate next date */
1410 i_next_date = s->i_date;
1412 if( s->i_period != 0 )
1415 while( s->i_date + j * s->i_period <= i_time && s->i_repeat > j )
1420 i_next_date = s->i_date + j * s->i_period;
1423 if( i_next_date > i_time )
1425 time_t i_date = (time_t) (i_next_date / 1000000) ;
1429 ctime_r( &i_date, psz_date );
1431 char *psz_date = ctime( &i_date );
1434 vlm_MessageAdd( message_schedule , vlm_MessageNew( "next launch" , psz_date ) );
1439 vlm_MessageAdd( message_schedule , vlm_MessageNew( "enabled" , "no" ) );
1445 else if( psz_filter == NULL && media == NULL && schedule == NULL )
1447 vlm_message_t *show1 = vlm_Show( vlm, NULL, NULL, "media" );
1448 vlm_message_t *show2 = vlm_Show( vlm, NULL, NULL, "schedule" );
1450 vlm_MessageAdd( show1 , show2->child[0] );
1452 /* we must destroy the parent node "show" of show2, and not the children */
1453 free( show2->psz_name );
1460 return vlm_MessageNew( "show" , NULL );
1464 static vlm_message_t *vlm_Help( vlm_t *vlm, char *psz_filter )
1466 vlm_message_t *message;
1468 if( psz_filter == NULL )
1470 char *help = malloc( strlen( "Commands Syntax:" ) +
1471 strlen( "\n new (name) vod|broadcast|schedule [properties]" ) +
1472 strlen( "\n setup (name) (properties)" ) +
1473 strlen( "\n show [(name)|media|schedule]" ) +
1474 strlen( "\n del (name)|all|media|schedule" ) +
1475 strlen( "\n control (name) (command)" ) +
1476 strlen( "\n save (config_file)" ) +
1477 strlen( "\n load (config_file)" ) +
1478 strlen( "\nMedia Proprieties Syntax:" ) +
1479 strlen( "\n input (input_name)" ) +
1480 strlen( "\n output (output_name)" ) +
1481 strlen( "\n option (option_name)[=value]" ) +
1482 strlen( "\n enabled|disabled" ) +
1483 strlen( "\n loop|unloop (broadcast only)" ) +
1484 strlen( "\nSchedule Proprieties Syntax:" ) +
1485 strlen( "\n enabled|disabled" ) +
1486 strlen( "\n append (command_until_rest_of_the_line)" ) +
1487 strlen( "\n date (year)/(month)/(day)-(hour):(minutes):(seconds)|now" ) +
1488 strlen( "\n period (years_aka_12_months)/(months_aka_30_days)/(days)-(hours):(minutes):(seconds)" ) +
1489 strlen( "\n repeat (number_of_repetitions)" ) +
1490 strlen( "\nControl Commands Syntax:" ) +
1491 strlen( "\n play\n pause\n stop\n seek (percentage)\n" ) + 1 );
1495 "\n new (name) vod|broadcast|schedule [properties]"
1496 "\n setup (name) (properties)"
1497 "\n show [(name)|media|schedule]"
1498 "\n del (name)|all|media|schedule"
1499 "\n control (name) (command)"
1500 "\n save (config_file)"
1501 "\n load (config_file)"
1502 "\nMedia Proprieties Syntax:"
1503 "\n input (input_name)"
1504 "\n output (output_name)"
1505 "\n option (option_name)[=value]"
1506 "\n enabled|disabled"
1507 "\n loop|unloop (broadcast only)"
1508 "\nSchedule Proprieties Syntax:"
1509 "\n enabled|disabled"
1510 "\n append (command_until_rest_of_the_line)"
1511 "\n date (year)/(month)/(day)-(hour):(minutes):(seconds)|now"
1512 "\n period (years_aka_12_months)/(months_aka_30_days)/(days)-(hours):(minutes):(seconds)"
1513 "\n repeat (number_of_repetitions)"
1514 "\nControl Commands Syntax:"
1515 "\n play\n pause\n stop\n seek (percentage)\n" );
1517 message = vlm_MessageNew( "help" , NULL );
1518 vlm_MessageAdd( message , vlm_MessageNew( "Help" , help ) );
1523 return vlm_MessageNew( "help" , NULL );
1526 /* file must end by '\0' */
1527 static int vlm_Load( vlm_t *vlm, char *file )
1531 while( *pf != '\0' )
1533 vlm_message_t *message = NULL;
1537 while( pf[i_temp] != '\n' && pf[i_temp] != '\0' && pf[i_temp] != '\r' )
1542 if( pf[i_temp] == '\r' || pf[i_temp] == '\n' )
1545 i_next = i_temp + 1;
1552 if( ExecuteCommand( vlm, pf, &message ) )
1564 static char *vlm_Save( vlm_t *vlm )
1571 for( i = 0; i < vlm->i_media; i++ )
1573 vlm_media_t *media = vlm->media[i];
1575 if( media->i_type == VOD_TYPE )
1577 i_length += strlen( "new vod " ) + strlen(media->psz_name);
1581 i_length += strlen( "new broadcast " ) + strlen(media->psz_name);
1584 if( media->b_enabled == VLC_TRUE )
1586 i_length += strlen( "enabled" );
1590 i_length += strlen( "disabled" );
1593 if( media->b_loop == VLC_TRUE )
1595 i_length += strlen( " loop\n" );
1599 i_length += strlen( "\n" );
1602 for( j = 0; j < media->i_input; j++ )
1604 i_length += strlen( "setup input \"\"\n" ) + strlen( media->psz_name ) + strlen( media->input[j] );
1607 if( media->psz_output != NULL )
1609 i_length += strlen(media->psz_name) + strlen(media->psz_output) + strlen( "setup output \n" );
1612 for( j=0 ; j < media->i_option ; j++ )
1614 i_length += strlen(media->psz_name) + strlen(media->option[j]) + strlen("setup option \n");
1618 for( i = 0; i < vlm->i_schedule; i++ )
1620 vlm_schedule_t *schedule = vlm->schedule[i];
1622 i_length += strlen( "new schedule " ) + strlen( schedule->psz_name );
1624 if( schedule->b_enabled == VLC_TRUE )
1626 i_length += strlen( "date //-:: enabled\n" ) + 14;
1630 i_length += strlen( "date //-:: disabled\n" ) + 14;
1634 if( schedule->i_period != 0 )
1636 i_length += strlen( "setup " ) + strlen( schedule->psz_name ) + strlen( "period //-::\n" ) + 14;
1639 if( schedule->i_repeat >= 0 )
1643 sprintf( buffer, "%d", schedule->i_repeat );
1644 i_length += strlen( "setup repeat \n" ) + strlen( schedule->psz_name ) + strlen( buffer );
1651 for( j = 0; j < schedule->i_command; j++ )
1653 i_length += strlen( "setup append \n" ) + strlen( schedule->psz_name ) + strlen( schedule->command[j] );
1658 /* Don't forget the '\0' */
1660 /* now we have the length of save */
1662 p = save = malloc( i_length );
1665 /* finally we can write in it */
1666 for( i = 0; i < vlm->i_media; i++ )
1668 vlm_media_t *media = vlm->media[i];
1670 if( media->i_type == VOD_TYPE )
1672 p += sprintf( p, "new %s vod ", media->psz_name);
1676 p += sprintf( p, "new %s broadcast ", media->psz_name);
1679 if( media->b_enabled == VLC_TRUE )
1681 p += sprintf( p, "enabled" );
1685 p += sprintf( p, "disabled" );
1688 if( media->b_loop == VLC_TRUE )
1690 p += sprintf( p, " loop\n" );
1694 p += sprintf( p, "\n" );
1697 for( j = 0; j < media->i_input; j++ )
1699 p += sprintf( p, "setup %s input \"%s\"\n", media->psz_name, media->input[j] );
1702 if( media->psz_output != NULL )
1704 p += sprintf( p, "setup %s output %s\n", media->psz_name, media->psz_output );
1707 for( j = 0; j < media->i_option; j++ )
1709 p += sprintf( p, "setup %s option %s\n", media->psz_name, media->option[j] );
1713 /* and now, the schedule scripts */
1715 for( i = 0; i < vlm->i_schedule; i++ )
1717 vlm_schedule_t *schedule = vlm->schedule[i];
1719 time_t i_time = (time_t) ( schedule->i_date / 1000000 );
1721 #ifdef HAVE_LOCALTIME_R
1722 localtime_r( &i_time, &date);
1724 struct tm *p_date = localtime( &i_time );
1728 p += sprintf( p, "new %s schedule ", schedule->psz_name);
1730 if( schedule->b_enabled == VLC_TRUE )
1732 p += sprintf( p, "date %d/%d/%d-%d:%d:%d enabled\n",
1733 date.tm_year + 1900, date.tm_mon + 1, date.tm_mday,
1734 date.tm_hour, date.tm_min, date.tm_sec );
1738 p += sprintf( p, "date %d/%d/%d-%d:%d:%d disabled\n",
1739 date.tm_year + 1900, date.tm_mon + 1, date.tm_mday,
1740 date.tm_hour, date.tm_min, date.tm_sec);
1744 if( schedule->i_period != 0 )
1746 p += sprintf( p, "setup %s ", schedule->psz_name );
1748 i_time = (time_t) ( schedule->i_period / 1000000 );
1750 date.tm_sec = (int)( i_time % 60 );
1751 i_time = i_time / 60;
1752 date.tm_min = (int)( i_time % 60 );
1753 i_time = i_time / 60;
1754 date.tm_hour = (int)( i_time % 24 );
1755 i_time = i_time / 24;
1756 date.tm_mday = (int)( i_time % 30 );
1757 i_time = i_time / 30;
1758 /* okay, okay, months are not always 30 days long */
1759 date.tm_mon = (int)( i_time % 12 );
1760 i_time = i_time / 12;
1761 date.tm_year = (int)i_time;
1763 p += sprintf( p, "period %d/%d/%d-%d:%d:%d\n", date.tm_year ,
1771 if( schedule->i_repeat >= 0 )
1773 p += sprintf( p, "setup %s repeat %d\n", schedule->psz_name, schedule->i_repeat );
1777 p += sprintf( p, "\n" );
1780 for( j = 0; j < schedule->i_command; j++ )
1782 p += sprintf( p, "setup %s append %s\n", schedule->psz_name, schedule->command[j] );
1790 static vlm_schedule_t *vlm_ScheduleNew( vlm_t *vlm , char *psz_name )
1792 vlm_schedule_t *sched= malloc( sizeof( vlm_schedule_t ));
1794 sched->psz_name = strdup( psz_name );
1795 sched->b_enabled = VLC_FALSE;
1796 sched->i_command = 0;
1797 sched->command = NULL;
1799 sched->i_period = 0;
1800 sched->i_repeat = 0;
1802 TAB_APPEND( vlm->i_schedule , vlm->schedule , sched );
1807 /* for now, simple delete. After, del with options (last arg) */
1808 static int vlm_ScheduleDelete( vlm_t *vlm, vlm_schedule_t *sched, char *psz_name )
1817 TAB_REMOVE( vlm->i_schedule, vlm->schedule , sched );
1819 if( vlm->i_schedule == 0 && vlm->schedule ) free( vlm->schedule );
1821 free( sched->psz_name );
1823 for( i = 0; i < sched->i_command; i++ )
1825 free( sched->command[i] );
1833 static vlm_schedule_t *vlm_ScheduleSearch( vlm_t *vlm, char *psz_name )
1837 for( i = 0; i < vlm->i_schedule; i++ )
1839 if( strcmp( psz_name, vlm->schedule[i]->psz_name ) == 0 )
1841 return vlm->schedule[i];
1848 /* Ok, setup schedule command will be able to support only one (argument value) at a time */
1849 static int vlm_ScheduleSetup( vlm_schedule_t *schedule, char *psz_cmd, char *psz_value )
1851 if( strcmp( psz_cmd, "enabled" ) == 0 )
1853 schedule->b_enabled = VLC_TRUE;
1855 else if( strcmp( psz_cmd, "disabled" ) == 0 )
1857 schedule->b_enabled = VLC_FALSE;
1859 else if( strcmp( psz_cmd, "date" ) == 0 )
1865 time.tm_sec = 0; /* seconds */
1866 time.tm_min = 0; /* minutes */
1867 time.tm_hour = 0; /* hours */
1868 time.tm_mday = 0; /* day of the month */
1869 time.tm_mon = 0; /* month */
1870 time.tm_year = 0; /* year */
1871 time.tm_wday = 0; /* day of the week */
1872 time.tm_yday = 0; /* day in the year */
1873 time.tm_isdst = 0; /* daylight saving time */
1875 /* date should be year/month/day-hour:minutes:seconds */
1876 p = strchr( psz_value , '-' );
1878 if( strcmp( psz_value, "now" ) == 0 )
1880 schedule->i_date = 0;
1882 else if( p == NULL && sscanf( psz_value, "%d:%d:%d" , &time.tm_hour, &time.tm_min, &time.tm_sec ) != 3 ) /* it must be a hour:minutes:seconds */
1890 switch( sscanf( p + 1, "%d:%d:%d" , &i, &j, &k ) )
1910 switch( sscanf( psz_value, "%d/%d/%d" , &i, &j, &k ) )
1916 time.tm_mon = i - 1;
1920 time.tm_year = i - 1900;
1921 time.tm_mon = j - 1;
1928 date = mktime( &time );
1929 schedule->i_date = ((mtime_t) date) * 1000000;
1932 else if( strcmp( psz_cmd, "period" ) == 0 )
1936 char *psz_time = NULL, *psz_date = NULL;
1940 /* First, if date or period are modified, repeat should be equal to -1 */
1941 schedule->i_repeat = -1;
1943 time.tm_sec = 0; /* seconds */
1944 time.tm_min = 0; /* minutes */
1945 time.tm_hour = 0; /* hours */
1946 time.tm_mday = 0; /* day of the month */
1947 time.tm_mon = 0; /* month */
1948 time.tm_year = 0; /* year */
1949 time.tm_wday = 0; /* day of the week */
1950 time.tm_yday = 0; /* day in the year */
1951 time.tm_isdst = 0; /* daylight saving time */
1953 /* date should be year/month/day-hour:minutes:seconds */
1954 p = strchr( psz_value , '-' );
1957 psz_date = psz_value;
1964 psz_time = psz_value;
1968 switch( sscanf( psz_time, "%d:%d:%d" , &i, &j, &k ) )
1987 switch( sscanf( psz_date, "%d/%d/%d" , &i, &j, &k ) )
2006 /* ok, that's stupid... who is going to schedule streams every 42 years ? */
2007 date = (((( time.tm_year * 12 + time.tm_mon ) * 30 + time.tm_mday ) * 24 + time.tm_hour ) * 60 + time.tm_min ) * 60 + time.tm_sec ;
2008 schedule->i_period = ((mtime_t) date) * 1000000;
2010 else if( strcmp( psz_cmd, "repeat" ) == 0 )
2014 if( sscanf( psz_value, "%d" , &i ) == 1 )
2016 schedule->i_repeat = i;
2023 else if( strcmp( psz_cmd, "append" ) == 0 )
2025 char *command = strdup( psz_value );
2027 TAB_APPEND( schedule->i_command, schedule->command, command );
2036 /*****************************************************************************
2038 *****************************************************************************/
2039 static int Manage( vlc_object_t* p_object )
2041 vlm_t *vlm = (vlm_t*)p_object;
2043 mtime_t i_lastcheck;
2046 i_lastcheck = mdate();
2050 while( !vlm->b_die )
2052 vlc_mutex_lock( &vlm->lock );
2054 /* destroy the inputs that wants to die, and launch the next input */
2055 for( i = 0; i < vlm->i_media; i++ )
2057 vlm_media_t *media = vlm->media[i];
2059 if( media->p_input != NULL && ( media->p_input->b_eof || media->p_input->b_error ) )
2061 input_StopThread( media->p_input );
2063 input_DestroyThread( media->p_input );
2064 vlc_object_detach( media->p_input );
2065 vlc_object_destroy( media->p_input );
2066 media->p_input = NULL;
2069 if( media->i_index == media->i_input && media->b_loop == VLC_TRUE )
2074 if( media->i_index < media->i_input )
2078 sprintf( buffer, "%d", media->i_index );
2079 vlm_MediaControl( vlm, media, "play", buffer );
2087 for( i = 0; i < vlm->i_schedule; i++ )
2089 mtime_t i_real_date = vlm->schedule[i]->i_date;
2091 if( vlm->schedule[i]->i_date == 0 ) // now !
2093 vlm->schedule[i]->i_date = (i_time / 1000000) * 1000000 ;
2094 i_real_date = i_time;
2096 else if( vlm->schedule[i]->i_period != 0 )
2099 while( vlm->schedule[i]->i_date + j * vlm->schedule[i]->i_period <= i_lastcheck &&
2100 ( vlm->schedule[i]->i_repeat > j || vlm->schedule[i]->i_repeat == -1 ) )
2105 i_real_date = vlm->schedule[i]->i_date + j * vlm->schedule[i]->i_period;
2108 if( vlm->schedule[i]->b_enabled == VLC_TRUE )
2110 if( i_real_date <= i_time && i_real_date > i_lastcheck )
2112 for( j = 0 ; j < vlm->schedule[i]->i_command ; j++ )
2114 vlm_message_t *message = NULL;
2116 ExecuteCommand( vlm, vlm->schedule[i]->command[j] , &message );
2118 /* for now, drop the message */
2125 i_lastcheck = i_time;
2127 vlc_mutex_unlock( &vlm->lock );
2136 static vlm_message_t* vlm_MessageNew( char *psz_name , char *psz_value )
2138 vlm_message_t *message = malloc( sizeof(vlm_message_t) );
2142 message->psz_name = strdup( psz_name );
2151 message->psz_value = strdup( psz_value );
2155 message->psz_value = NULL;
2158 message->i_child = 0;
2159 message->child = NULL;
2164 void vlm_MessageDelete( vlm_message_t* message )
2168 if( message->psz_name ) free( message->psz_name );
2169 if( message->psz_value ) free( message->psz_value );
2171 for( i = 0; i < message->i_child; i++)
2173 vlm_MessageDelete( message->child[i] );
2180 static vlm_message_t* vlm_MessageAdd( vlm_message_t* message , vlm_message_t* child )
2182 if( message == NULL ) return NULL;
2186 TAB_APPEND( message->i_child , message->child , child );