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>
9 * Gildas Bazin <gbazin@videolan.org>
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
24 *****************************************************************************/
26 /*****************************************************************************
28 *****************************************************************************/
29 #include <stdlib.h> /* malloc(), free() */
33 #include <vlc/input.h>
36 # include <time.h> /* ctime() */
42 /*****************************************************************************
44 *****************************************************************************/
45 static char *vlm_Save( vlm_t * );
46 static int vlm_Load( vlm_t *, char *);
47 static vlm_message_t *vlm_Show( vlm_t *, vlm_media_t *, vlm_schedule_t *, char * );
48 static vlm_message_t *vlm_Help( vlm_t *, char * );
50 static vlm_media_t *vlm_MediaNew ( vlm_t *, char *, int );
51 static void vlm_MediaDelete ( vlm_t *, vlm_media_t *, char * );
52 static vlm_media_t *vlm_MediaSearch ( vlm_t *, char * );
53 static int vlm_MediaSetup ( vlm_t *, vlm_media_t *, char *, char * );
54 static int vlm_MediaControl( vlm_t *, vlm_media_t *, char *, char *, char * );
55 static vlm_media_instance_t *vlm_MediaInstanceSearch( vlm_t *, vlm_media_t *, char * );
57 static vlm_message_t *vlm_MessageNew( char *, const char *, ... );
58 static vlm_message_t *vlm_MessageAdd( vlm_message_t*, vlm_message_t* );
60 static vlm_schedule_t *vlm_ScheduleNew( vlm_t *, char *);
61 static void vlm_ScheduleDelete( vlm_t *, vlm_schedule_t *, char *);
62 static int vlm_ScheduleSetup( vlm_schedule_t *, char *, char *);
63 static vlm_schedule_t *vlm_ScheduleSearch( vlm_t *, char *);
65 static int ExecuteCommand( vlm_t *, char *, vlm_message_t **);
66 static int Manage( vlc_object_t* );
68 /*****************************************************************************
70 *****************************************************************************/
71 vlm_t *__vlm_New ( vlc_object_t *p_this )
76 /* to be sure to avoid multiple creation */
77 var_Create( p_this->p_libvlc, "vlm_mutex", VLC_VAR_MUTEX );
78 var_Get( p_this->p_libvlc, "vlm_mutex", &lockval );
79 vlc_mutex_lock( lockval.p_address );
81 if( !(vlm = vlc_object_find( p_this, VLC_OBJECT_VLM, FIND_ANYWHERE )) )
83 msg_Info( p_this, "creating vlm" );
84 if( ( vlm = vlc_object_create( p_this, VLC_OBJECT_VLM ) ) == NULL )
86 vlc_mutex_unlock( lockval.p_address );
90 vlc_mutex_init( p_this->p_vlc, &vlm->lock );
97 vlc_object_yield( vlm );
98 vlc_object_attach( vlm, p_this->p_vlc );
100 vlc_mutex_unlock( lockval.p_address );
102 if( vlc_thread_create( vlm, "vlm thread",
103 Manage, VLC_THREAD_PRIORITY_LOW, VLC_FALSE ) )
105 vlc_mutex_destroy( &vlm->lock );
106 vlc_object_destroy( vlm );
113 /*****************************************************************************
115 *****************************************************************************/
116 void vlm_Delete( vlm_t *vlm )
120 var_Get( vlm->p_libvlc, "vlm_mutex", &lockval );
121 vlc_mutex_lock( lockval.p_address );
123 vlc_object_release( vlm );
125 if( vlm->i_refcount > 0 )
127 vlc_mutex_unlock( lockval.p_address );
131 vlm->b_die = VLC_TRUE;
132 vlc_thread_join( vlm );
134 vlc_mutex_destroy( &vlm->lock );
136 while( vlm->i_media ) vlm_MediaDelete( vlm, vlm->media[0], NULL );
137 if( vlm->media ) free( vlm->media );
139 while( vlm->i_schedule ) vlm_ScheduleDelete( vlm, vlm->schedule[0], NULL );
140 if( vlm->schedule ) free( vlm->schedule );
142 vlc_object_detach( vlm );
143 vlc_object_destroy( vlm );
144 vlc_mutex_unlock( lockval.p_address );
147 /*****************************************************************************
148 * vlm_ExecuteCommand:
149 *****************************************************************************/
150 int vlm_ExecuteCommand( vlm_t *vlm, char *command, vlm_message_t **message)
154 vlc_mutex_lock( &vlm->lock );
155 result = ExecuteCommand( vlm, command, message );
156 vlc_mutex_unlock( &vlm->lock );
161 /*****************************************************************************
163 *****************************************************************************/
164 static char *FindEndCommand( char *psz )
166 char *psz_sent = psz;
173 while( ( *psz_sent != '\"' ) && ( *psz_sent != '\0' ) )
175 if( *psz_sent == '\'' )
177 psz_sent = FindEndCommand( psz_sent );
178 if( psz_sent == NULL ) return NULL;
183 if( *psz_sent == '\"' )
189 /* *psz_sent == '\0' -> number of " is incorrect */
197 while( ( *psz_sent != '\'' ) && ( *psz_sent != '\0' ) )
199 if( *psz_sent == '\"' )
201 psz_sent = FindEndCommand( psz_sent );
202 if( psz_sent == NULL ) return NULL;
207 if( *psz_sent == '\'' )
213 /* *psz_sent == '\0' -> number of " is incorrect */
218 default: /* now we can look for spaces */
219 while( ( *psz_sent != ' ' ) && ( *psz_sent != '\0' ) )
221 if( ( *psz_sent == '\'' ) || ( *psz_sent == '\"' ) )
223 psz_sent = FindEndCommand( psz_sent );
232 /*****************************************************************************
233 * ExecuteCommand: The main state machine
234 *****************************************************************************
235 * Execute a command which ends with '\0' (string)
236 *****************************************************************************/
237 static int ExecuteCommand(vlm_t *vlm, char *command, vlm_message_t **p_message)
240 char **p_command = NULL;
242 vlm_message_t *message = NULL;
245 /* First, parse the line and cut it */
246 while( *cmd != '\0' )
258 p_temp = FindEndCommand( cmd );
260 if( p_temp == NULL ) goto error;
262 i_temp = p_temp - cmd;
264 p_command = realloc( p_command, (i_command + 1) * sizeof(char*) );
265 p_command[ i_command ] = malloc( (i_temp + 1) * sizeof(char) );
266 strncpy( p_command[ i_command ], cmd, i_temp );
267 p_command[ i_command ][ i_temp ] = '\0';
275 * And then Interpret it
280 message = vlm_MessageNew( "", NULL );
284 if( strcmp(p_command[0], "new") == 0 )
288 /* Check the number of arguments */
289 if( i_command < 3 ) goto syntax_error;
292 if( strcmp(p_command[2], "vod") == 0 )
296 else if( strcmp(p_command[2], "broadcast") == 0 )
298 i_type = BROADCAST_TYPE;
300 else if( strcmp(p_command[2], "schedule") == 0 )
302 i_type = SCHEDULE_TYPE;
306 message = vlm_MessageNew( "new", "%s: Choose between vod, "
307 "broadcast or schedule", p_command[1] );
311 /* Check for forbidden media names */
312 if( strcmp(p_command[1], "all") == 0 ||
313 strcmp(p_command[1], "media") == 0 ||
314 strcmp(p_command[1], "schedule") == 0 )
316 message = vlm_MessageNew( "new", "\"all\", \"media\" and "
317 "\"schedule\" are reserved names" );
321 /* Check the name is not already in use */
322 if( vlm_ScheduleSearch( vlm, p_command[1] ) ||
323 vlm_MediaSearch( vlm, p_command[1] ) )
325 message = vlm_MessageNew( "new", "%s: Name already in use",
331 if( i_type == SCHEDULE_TYPE )
333 vlm_schedule_t *schedule;
334 schedule = vlm_ScheduleNew( vlm, p_command[1] );
337 message = vlm_MessageNew( "new", "could not create schedule" );
346 media = vlm_MediaNew( vlm, p_command[1], i_type );
349 message = vlm_MessageNew( "new", "could not create media" );
356 message = vlm_MessageNew( "new", NULL );
360 /* Properties will be dealt with later on */
363 else if( strcmp(p_command[0], "setup") == 0 )
365 if( i_command < 2 ) goto syntax_error;
367 /* Properties will be dealt with later on */
370 else if( strcmp(p_command[0], "del") == 0 )
373 vlm_schedule_t *schedule;
375 if( i_command < 2 ) goto syntax_error;
377 media = vlm_MediaSearch( vlm, p_command[1] );
378 schedule = vlm_ScheduleSearch( vlm, p_command[1] );
380 if( schedule != NULL )
382 vlm_ScheduleDelete( vlm, schedule, NULL );
384 else if( media != NULL )
386 vlm_MediaDelete( vlm, media, NULL );
388 else if( strcmp(p_command[1], "media") == 0 )
390 while( vlm->i_media ) vlm_MediaDelete( vlm, vlm->media[0], NULL );
392 else if( strcmp(p_command[1], "schedule") == 0 )
394 while( vlm->i_schedule )
395 vlm_ScheduleDelete( vlm, vlm->schedule[0], NULL );
397 else if( strcmp(p_command[1], "all") == 0 )
399 while( vlm->i_media ) vlm_MediaDelete( vlm, vlm->media[0], NULL );
401 while( vlm->i_schedule )
402 vlm_ScheduleDelete( vlm, vlm->schedule[0], NULL );
406 message = vlm_MessageNew( "del", "%s: media unknown",
411 message = vlm_MessageNew( "del", NULL );
415 else if( strcmp(p_command[0], "show") == 0 )
418 vlm_schedule_t *schedule;
422 message = vlm_Show( vlm, NULL, NULL, NULL );
425 else if( i_command > 2 ) goto syntax_error;
427 media = vlm_MediaSearch( vlm, p_command[1] );
428 schedule = vlm_ScheduleSearch( vlm, p_command[1] );
430 if( schedule != NULL )
432 message = vlm_Show( vlm, NULL, schedule, NULL );
434 else if( media != NULL )
436 message = vlm_Show( vlm, media, NULL, NULL );
440 message = vlm_Show( vlm, NULL, NULL, p_command[1] );
446 else if( strcmp(p_command[0], "help") == 0 )
448 if( i_command != 1 ) goto syntax_error;
450 message = vlm_Help( vlm, NULL );
454 else if( strcmp(p_command[0], "control") == 0 )
458 if( i_command < 3 ) goto syntax_error;
460 if( !(media = vlm_MediaSearch( vlm, p_command[1] ) ) )
462 message = vlm_MessageNew( "control", "%s: media unknown",
468 char *psz_command, *psz_arg = 0, *psz_instance = 0;
471 if( strcmp(p_command[2], "play") && strcmp(p_command[2], "stop") &&
472 strcmp(p_command[2], "pause") && strcmp(p_command[2], "seek") )
475 psz_instance = p_command[2];
477 if( i_command < 4 ) goto syntax_error;
480 psz_command = p_command[i_index];
482 if( i_command >= i_index + 2 ) psz_arg = p_command[i_index + 1];
484 vlm_MediaControl( vlm, media, psz_instance, psz_command, psz_arg );
485 message = vlm_MessageNew( "control", NULL );
490 else if( strcmp(p_command[0], "save") == 0 )
494 if( i_command != 2 ) goto syntax_error;
496 file = fopen( p_command[1], "w" );
499 message = vlm_MessageNew( "save", "Unable to save file" );
504 char *save = vlm_Save( vlm );
505 fwrite( save, strlen( save ), 1, file );
508 message = vlm_MessageNew( "save", NULL );
513 else if( strcmp(p_command[0], "load") == 0 )
517 if( i_command != 2 ) goto syntax_error;
519 file = fopen( p_command[1], "r" );
523 message = vlm_MessageNew( "load", "Unable to load file" );
531 if( fseek( file, 0, SEEK_END) == 0 )
533 size = ftell( file );
534 fseek( file, 0, SEEK_SET);
535 buffer = malloc( size + 1 );
536 fread( buffer, 1, size, file);
537 buffer[ size ] = '\0';
538 if( vlm_Load( vlm, buffer ) )
541 message = vlm_MessageNew( "load", "error while loading "
549 message = vlm_MessageNew( "load", "read file error" );
554 message = vlm_MessageNew( "load", NULL );
561 message = vlm_MessageNew( p_command[0], "Unknown command" );
565 /* Common code between "new" and "setup" */
566 if( strcmp(p_command[0], "new") == 0 ||
567 strcmp(p_command[0], "setup") == 0 )
569 int i_command_start = strcmp(p_command[0], "new") ? 2 : 3;
571 vlm_schedule_t *schedule;
573 if( i_command < i_command_start ) goto syntax_error;
575 media = vlm_MediaSearch( vlm, p_command[1] );
576 schedule = vlm_ScheduleSearch( vlm, p_command[1] );
578 if( !media && !schedule )
580 message = vlm_MessageNew( p_command[0], "%s unknown",
585 if( schedule != NULL )
587 for( i = i_command_start ; i < i_command ; i++ )
589 if( strcmp( p_command[i], "enabled" ) == 0 ||
590 strcmp( p_command[i], "disabled" ) == 0 )
592 vlm_ScheduleSetup( schedule, p_command[i], NULL );
595 /* Beware: everything behind append is considered as
597 else if( strcmp( p_command[i], "append" ) == 0 )
599 if( ++i >= i_command ) break;
601 for( j = i + 1; j < i_command; j++ )
604 realloc( p_command[i], strlen(p_command[i]) +
605 strlen(p_command[j]) + 1 + 1 );
606 strcat( p_command[i], " " );
607 strcat( p_command[i], p_command[j] );
610 vlm_ScheduleSetup( schedule, p_command[i - 1],
616 if( i + 1 >= i_command && !strcmp(p_command[0], "new") )
618 vlm_ScheduleDelete( vlm, schedule, NULL );
619 message = vlm_MessageNew( p_command[0],
620 "Wrong properties syntax" );
623 else if( i + 1 >= i_command )
625 message = vlm_MessageNew( p_command[0],
626 "Wrong properties syntax" );
630 vlm_ScheduleSetup( schedule, p_command[i],
637 else if( media != NULL )
639 for( i = i_command_start ; i < i_command ; i++ )
641 if( strcmp( p_command[i], "enabled" ) == 0 ||
642 strcmp( p_command[i], "disabled" ) == 0 )
644 vlm_MediaSetup( vlm, media, p_command[i], NULL );
646 else if( strcmp( p_command[i], "loop" ) == 0 ||
647 strcmp( p_command[i], "unloop" ) == 0 )
649 if( media->i_type != BROADCAST_TYPE )
651 message = vlm_MessageNew( p_command[0],
652 "loop only available for broadcast" );
656 vlm_MediaSetup( vlm, media, p_command[i], NULL );
661 if( i + 1 >= i_command && !strcmp(p_command[0], "new") )
663 vlm_MediaDelete( vlm, media, NULL );
664 message = vlm_MessageNew( p_command[0],
665 "Wrong properties syntax" );
668 else if( i + 1 >= i_command )
670 message = vlm_MessageNew( p_command[0],
671 "Wrong properties syntax" );
675 vlm_MediaSetup( vlm, media, p_command[i], p_command[i+1] );
681 message = vlm_MessageNew( p_command[0], NULL );
686 for( i = 0 ; i < i_command ; i++ ) free( p_command[i] );
687 if( p_command ) free( p_command );
688 *p_message = message;
693 message = vlm_MessageNew( p_command[0], "Wrong command syntax" );
696 for( i = 0 ; i < i_command ; i++ ) free( p_command[i] );
697 if( p_command ) free( p_command );
698 *p_message = message;
703 static vlm_media_t *vlm_MediaSearch( vlm_t *vlm, char *psz_name )
707 for( i = 0; i < vlm->i_media; i++ )
709 if( strcmp( psz_name, vlm->media[i]->psz_name ) == 0 )
711 return vlm->media[i];
718 /*****************************************************************************
720 *****************************************************************************/
721 static vlm_media_instance_t *
722 vlm_MediaInstanceSearch( vlm_t *vlm, vlm_media_t *media, char *psz_name )
726 for( i = 0; i < media->i_instance; i++ )
728 if( ( !psz_name && !media->instance[i]->psz_name ) ||
729 ( psz_name && media->instance[i]->psz_name &&
730 !strcmp( psz_name, media->instance[i]->psz_name ) ) )
732 return media->instance[i];
739 static vlm_media_t *vlm_MediaNew( vlm_t *vlm, char *psz_name, int i_type )
741 vlm_media_t *media = malloc( sizeof( vlm_media_t ) );
743 /* Check if we need to load the VOD server */
744 if( i_type == VOD_TYPE && !vlm->i_vod )
746 vlm->vod = vlc_object_create( vlm, VLC_OBJECT_VOD );
747 vlc_object_attach( vlm->vod, vlm );
748 vlm->vod->p_module = module_Need( vlm->vod, "vod server", 0, 0 );
749 if( !vlm->vod->p_module )
751 msg_Err( vlm, "cannot find vod server" );
752 vlc_object_detach( vlm->vod );
753 vlc_object_destroy( vlm->vod );
759 if( i_type == VOD_TYPE ) vlm->i_vod++;
761 media->psz_name = strdup( psz_name );
762 media->b_enabled = VLC_FALSE;
763 media->b_loop = VLC_FALSE;
764 media->vod_media = NULL;
767 media->psz_output = NULL;
769 media->option = NULL;
770 media->i_type = i_type;
771 media->i_instance = 0;
772 media->instance = NULL;
774 media->item.psz_uri = strdup( psz_name );
775 vlc_input_item_Init( VLC_OBJECT(vlm), &media->item );
777 TAB_APPEND( vlm->i_media, vlm->media, media );
782 /* for now, simple delete. After, del with options (last arg) */
783 static void vlm_MediaDelete( vlm_t *vlm, vlm_media_t *media, char *psz_name )
785 if( media == NULL ) return;
787 while( media->i_instance )
789 vlm_media_instance_t *p_instance = media->instance[0];
790 vlm_MediaControl( vlm, media, p_instance->psz_name, "stop", 0 );
793 TAB_REMOVE( vlm->i_media, vlm->media, media );
795 if( media->i_type == VOD_TYPE )
797 vlm_MediaSetup( vlm, media, "disabled", 0 );
801 /* Check if we need to unload the VOD server */
802 if( media->i_type == VOD_TYPE && !vlm->i_vod )
804 module_Unneed( vlm->vod, vlm->vod->p_module );
805 vlc_object_detach( vlm->vod );
806 vlc_object_destroy( vlm->vod );
810 if( vlm->i_media == 0 && vlm->media ) free( vlm->media );
812 free( media->psz_name );
814 while( media->i_input-- ) free( media->input[media->i_input] );
815 if( media->input ) free( media->input );
817 if( media->psz_output ) free( media->psz_output );
819 while( media->i_option-- ) free( media->option[media->i_option] );
820 if( media->option ) free( media->option );
822 vlc_input_item_Clean( &media->item );
827 static int vlm_MediaSetup( vlm_t *vlm, vlm_media_t *media, char *psz_cmd,
830 if( strcmp( psz_cmd, "loop" ) == 0 )
832 media->b_loop = VLC_TRUE;
834 else if( strcmp( psz_cmd, "unloop" ) == 0 )
836 media->b_loop = VLC_FALSE;
838 else if( strcmp( psz_cmd, "enabled" ) == 0 )
840 media->b_enabled = VLC_TRUE;
842 else if( strcmp( psz_cmd, "disabled" ) == 0 )
844 media->b_enabled = VLC_FALSE;
846 else if( strcmp( psz_cmd, "input" ) == 0 )
850 if( psz_value != NULL && strlen(psz_value) > 1 &&
851 ( psz_value[0] == '\'' || psz_value[0] == '\"' ) &&
852 ( psz_value[ strlen(psz_value) - 1 ] == '\'' ||
853 psz_value[ strlen(psz_value) - 1 ] == '\"' ) )
855 input = malloc( strlen(psz_value) - 1 );
857 memcpy( input, psz_value + 1, strlen(psz_value) - 2 );
858 input[ strlen(psz_value) - 2 ] = '\0';
862 input = strdup( psz_value );
865 TAB_APPEND( media->i_input, media->input, input );
867 else if( strcmp( psz_cmd, "output" ) == 0 )
869 if( media->psz_output != NULL )
871 free( media->psz_output );
873 media->psz_output = strdup( psz_value );
875 else if( strcmp( psz_cmd, "option" ) == 0 )
878 option = strdup( psz_value );
880 TAB_APPEND( media->i_option, media->option, option );
887 /* Check if we need to create/delete a vod media */
888 if( media->i_type == VOD_TYPE )
890 if( !media->b_enabled && media->vod_media )
892 vlm->vod->pf_media_del( vlm->vod, media->vod_media );
893 media->vod_media = 0;
895 else if( media->b_enabled && !media->vod_media && media->i_input )
897 /* Pre-parse the input */
898 input_thread_t *p_input;
902 vlc_input_item_Clean( &media->item );
903 vlc_input_item_Init( VLC_OBJECT(vlm), &media->item );
905 if( media->psz_output )
906 asprintf( &psz_output, "%s:description", media->psz_output );
908 asprintf( &psz_output, "#description" );
910 media->item.psz_uri = strdup( media->input[0] );
911 media->item.ppsz_options = malloc( sizeof( char* ) );
912 asprintf( &media->item.ppsz_options[0], "sout=%s", psz_output);
913 media->item.i_options = 1;
914 for( i = 0; i < media->i_option; i++ )
916 media->item.i_options++;
917 media->item.ppsz_options =
918 realloc( media->item.ppsz_options,
919 media->item.i_options * sizeof( char* ) );
920 media->item.ppsz_options[ media->item.i_options - 1 ] =
921 strdup( media->option[i] );
924 if( (p_input = input_CreateThread( vlm, &media->item ) ) )
926 while( !p_input->b_eof && !p_input->b_error ) msleep( 100000 );
928 input_StopThread( p_input );
929 input_DestroyThread( p_input );
930 vlc_object_detach( p_input );
931 vlc_object_destroy( p_input );
936 vlm->vod->pf_media_new( vlm->vod, media->psz_name,
944 static int vlm_MediaControl( vlm_t *vlm, vlm_media_t *media, char *psz_id,
945 char *psz_command, char *psz_args )
947 vlm_media_instance_t *p_instance;
950 p_instance = vlm_MediaInstanceSearch( vlm, media, psz_id );
952 if( strcmp( psz_command, "play" ) == 0 && !p_instance )
954 if( !media->b_enabled || media->i_input == 0 ) return 0;
958 p_instance = malloc( sizeof(vlm_media_instance_t) );
959 memset( p_instance, 0, sizeof(vlm_media_instance_t) );
960 vlc_input_item_Init( VLC_OBJECT(vlm), &p_instance->item );
961 p_instance->p_input = 0;
963 if( media->psz_output != NULL )
965 p_instance->item.ppsz_options = malloc( sizeof( char* ) );
966 asprintf( &p_instance->item.ppsz_options[0], "sout=%s",
968 p_instance->item.i_options = 1;
971 for( i = 0; i < media->i_option; i++ )
973 p_instance->item.i_options++;
974 p_instance->item.ppsz_options =
975 realloc( p_instance->item.ppsz_options,
976 p_instance->item.i_options * sizeof( char* ) );
977 p_instance->item.ppsz_options[p_instance->item.i_options - 1] =
978 strdup( media->option[i] );
981 p_instance->psz_name = psz_id ? strdup(psz_id) : 0;
982 TAB_APPEND( media->i_instance, media->instance, p_instance );
985 if( psz_args && sscanf(psz_args, "%d", &i) == 1 && i < media->i_input )
987 p_instance->i_index = i;
990 if( p_instance->item.psz_uri ) free( p_instance->item.psz_uri );
991 p_instance->item.psz_uri =
992 strdup( media->input[p_instance->i_index] );
994 if( p_instance->p_input )
996 input_StopThread( p_instance->p_input );
997 input_DestroyThread( p_instance->p_input );
998 vlc_object_detach( p_instance->p_input );
999 vlc_object_destroy( p_instance->p_input );
1002 p_instance->p_input = input_CreateThread( vlm, &p_instance->item );
1003 if( !p_instance->p_input )
1005 TAB_REMOVE( media->i_instance, media->instance, p_instance );
1006 vlc_input_item_Clean( &p_instance->item );
1007 if( p_instance->psz_name ) free( p_instance->psz_name );
1013 if( !p_instance ) return VLC_EGENERIC;
1015 if( strcmp( psz_command, "seek" ) == 0 )
1020 if( psz_args && sscanf( psz_args, "%f", &f_percentage ) == 1 )
1022 val.f_float = f_percentage / 100.0 ;
1023 var_Set( p_instance->p_input, "position", val );
1027 else if( strcmp( psz_command, "stop" ) == 0 )
1029 TAB_REMOVE( media->i_instance, media->instance, p_instance );
1031 if( p_instance->p_input )
1033 input_StopThread( p_instance->p_input );
1034 input_DestroyThread( p_instance->p_input );
1035 vlc_object_detach( p_instance->p_input );
1036 vlc_object_destroy( p_instance->p_input );
1039 vlc_input_item_Clean( &p_instance->item );
1040 if( p_instance->psz_name ) free( p_instance->psz_name );
1045 else if( strcmp( psz_command, "pause" ) == 0 )
1049 if( !p_instance->p_input ) return VLC_SUCCESS;
1051 var_Get( p_instance->p_input, "state", &val );
1053 if( val.i_int == PAUSE_S ) val.i_int = PLAYING_S;
1054 else val.i_int = PAUSE_S;
1055 var_Set( p_instance->p_input, "state", val );
1060 return VLC_EGENERIC;
1063 /*****************************************************************************
1065 *****************************************************************************/
1066 static vlm_schedule_t *vlm_ScheduleNew( vlm_t *vlm, char *psz_name )
1068 vlm_schedule_t *sched = malloc( sizeof( vlm_schedule_t ) );
1070 sched->psz_name = strdup( psz_name );
1071 sched->b_enabled = VLC_FALSE;
1072 sched->i_command = 0;
1073 sched->command = NULL;
1075 sched->i_period = 0;
1076 sched->i_repeat = -1;
1078 TAB_APPEND( vlm->i_schedule, vlm->schedule, sched );
1083 /* for now, simple delete. After, del with options (last arg) */
1084 static void vlm_ScheduleDelete( vlm_t *vlm, vlm_schedule_t *sched,
1087 if( sched == NULL ) return;
1089 TAB_REMOVE( vlm->i_schedule, vlm->schedule, sched );
1091 if( vlm->i_schedule == 0 && vlm->schedule ) free( vlm->schedule );
1092 free( sched->psz_name );
1093 while( sched->i_command-- ) free( sched->command[sched->i_command] );
1097 static vlm_schedule_t *vlm_ScheduleSearch( vlm_t *vlm, char *psz_name )
1101 for( i = 0; i < vlm->i_schedule; i++ )
1103 if( strcmp( psz_name, vlm->schedule[i]->psz_name ) == 0 )
1105 return vlm->schedule[i];
1112 /* Ok, setup schedule command will be able to support only one (argument value) at a time */
1113 static int vlm_ScheduleSetup( vlm_schedule_t *schedule, char *psz_cmd,
1116 if( strcmp( psz_cmd, "enabled" ) == 0 )
1118 schedule->b_enabled = VLC_TRUE;
1120 else if( strcmp( psz_cmd, "disabled" ) == 0 )
1122 schedule->b_enabled = VLC_FALSE;
1124 else if( strcmp( psz_cmd, "date" ) == 0 )
1130 time.tm_sec = 0; /* seconds */
1131 time.tm_min = 0; /* minutes */
1132 time.tm_hour = 0; /* hours */
1133 time.tm_mday = 0; /* day of the month */
1134 time.tm_mon = 0; /* month */
1135 time.tm_year = 0; /* year */
1136 time.tm_wday = 0; /* day of the week */
1137 time.tm_yday = 0; /* day in the year */
1138 time.tm_isdst = 0; /* daylight saving time */
1140 /* date should be year/month/day-hour:minutes:seconds */
1141 p = strchr( psz_value, '-' );
1143 if( strcmp( psz_value, "now" ) == 0 )
1145 schedule->i_date = 0;
1147 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 */
1155 switch( sscanf( p + 1, "%d:%d:%d", &i, &j, &k ) )
1175 switch( sscanf( psz_value, "%d/%d/%d", &i, &j, &k ) )
1181 time.tm_mon = i - 1;
1185 time.tm_year = i - 1900;
1186 time.tm_mon = j - 1;
1193 date = mktime( &time );
1194 schedule->i_date = ((mtime_t) date) * 1000000;
1197 else if( strcmp( psz_cmd, "period" ) == 0 )
1201 char *psz_time = NULL, *psz_date = NULL;
1205 /* First, if date or period are modified, repeat should be equal to -1 */
1206 schedule->i_repeat = -1;
1208 time.tm_sec = 0; /* seconds */
1209 time.tm_min = 0; /* minutes */
1210 time.tm_hour = 0; /* hours */
1211 time.tm_mday = 0; /* day of the month */
1212 time.tm_mon = 0; /* month */
1213 time.tm_year = 0; /* year */
1214 time.tm_wday = 0; /* day of the week */
1215 time.tm_yday = 0; /* day in the year */
1216 time.tm_isdst = 0; /* daylight saving time */
1218 /* date should be year/month/day-hour:minutes:seconds */
1219 p = strchr( psz_value, '-' );
1222 psz_date = psz_value;
1229 psz_time = psz_value;
1233 switch( sscanf( psz_time, "%d:%d:%d", &i, &j, &k ) )
1252 switch( sscanf( psz_date, "%d/%d/%d", &i, &j, &k ) )
1271 /* ok, that's stupid... who is going to schedule streams every 42 years ? */
1272 date = (((( time.tm_year * 12 + time.tm_mon ) * 30 + time.tm_mday ) * 24 + time.tm_hour ) * 60 + time.tm_min ) * 60 + time.tm_sec ;
1273 schedule->i_period = ((mtime_t) date) * 1000000;
1275 else if( strcmp( psz_cmd, "repeat" ) == 0 )
1279 if( sscanf( psz_value, "%d", &i ) == 1 )
1281 schedule->i_repeat = i;
1288 else if( strcmp( psz_cmd, "append" ) == 0 )
1290 char *command = strdup( psz_value );
1292 TAB_APPEND( schedule->i_command, schedule->command, command );
1301 /*****************************************************************************
1302 * Message handling functions
1303 *****************************************************************************/
1304 static vlm_message_t *vlm_MessageNew( char *psz_name,
1305 const char *psz_format, ... )
1307 vlm_message_t *p_message;
1310 if( !psz_name ) return 0;
1312 p_message = malloc( sizeof(vlm_message_t) );
1313 p_message->psz_value = 0;
1317 va_start( args, psz_format );
1318 if( vasprintf( &p_message->psz_value, psz_format, args ) < 0 )
1327 p_message->psz_name = strdup( psz_name );
1328 p_message->i_child = 0;
1329 p_message->child = NULL;
1334 void vlm_MessageDelete( vlm_message_t *p_message )
1336 if( p_message->psz_name ) free( p_message->psz_name );
1337 if( p_message->psz_value ) free( p_message->psz_value );
1338 while( p_message->i_child-- )
1339 vlm_MessageDelete( p_message->child[p_message->i_child] );
1340 if( p_message->child ) free( p_message->child );
1345 static vlm_message_t *vlm_MessageAdd( vlm_message_t *p_message,
1346 vlm_message_t *p_child )
1348 if( p_message == NULL ) return NULL;
1352 TAB_APPEND( p_message->i_child, p_message->child, p_child );
1358 /*****************************************************************************
1359 * Misc utility functions
1360 *****************************************************************************/
1361 static vlm_message_t *vlm_Show( vlm_t *vlm, vlm_media_t *media,
1362 vlm_schedule_t *schedule, char *psz_filter )
1368 vlm_message_t *msg_media;
1369 vlm_message_t *msg_child;
1371 msg = vlm_MessageNew( "show", NULL );
1372 msg_media = vlm_MessageAdd( msg, vlm_MessageNew( media->psz_name, 0 ));
1374 vlm_MessageAdd( msg_media,
1375 vlm_MessageNew( "type", media->i_type == VOD_TYPE ?
1376 "vod" : "broadcast" ) );
1377 vlm_MessageAdd( msg_media,
1378 vlm_MessageNew( "enabled", media->b_enabled ?
1381 vlm_MessageAdd( msg_media,
1382 vlm_MessageNew( "loop", media->b_loop ?
1385 msg_child = vlm_MessageAdd( msg_media,
1386 vlm_MessageNew( "inputs", NULL ) );
1388 for( i = 0; i < media->i_input; i++ )
1390 vlm_MessageAdd( msg_child,
1391 vlm_MessageNew( media->input[i], NULL ) );
1394 vlm_MessageAdd( msg_media,
1395 vlm_MessageNew( "output", media->psz_output ?
1396 media->psz_output : "" ) );
1398 msg_child = vlm_MessageAdd( msg_media, vlm_MessageNew( "options", 0 ));
1400 for( i = 0; i < media->i_option; i++ )
1402 vlm_MessageAdd( msg_child, vlm_MessageNew( media->option[i], 0 ) );
1405 msg_child = vlm_MessageAdd( msg_media,
1406 vlm_MessageNew( "instances", NULL ) );
1408 for( i = 0; i < media->i_instance; i++ )
1410 vlm_media_instance_t *p_instance = media->instance[i];
1413 if( !p_instance->p_input ) val.i_int = END_S;
1414 else var_Get( p_instance->p_input, "state", &val );
1416 vlm_MessageAdd( msg_child,
1417 vlm_MessageNew( p_instance->psz_name ?
1418 p_instance->psz_name : "default",
1419 val.i_int == PLAYING_S ? "playing" :
1420 val.i_int == PAUSE_S ? "paused" :
1428 else if( schedule != NULL )
1432 vlm_message_t *msg_schedule;
1433 vlm_message_t *msg_child;
1436 msg = vlm_MessageNew( "show", NULL );
1438 vlm_MessageAdd( msg, vlm_MessageNew( schedule->psz_name, 0 ) );
1440 vlm_MessageAdd( msg_schedule, vlm_MessageNew("type", "schedule") );
1442 vlm_MessageAdd( msg_schedule,
1443 vlm_MessageNew( "enabled", schedule->b_enabled ?
1446 if( schedule->i_date != 0 )
1449 time_t i_time = (time_t)( schedule->i_date / 1000000 );
1452 #ifdef HAVE_LOCALTIME_R
1453 localtime_r( &i_time, &date);
1455 struct tm *p_date = localtime( &i_time );
1459 asprintf( &psz_date, "%d/%d/%d-%d:%d:%d",
1460 date.tm_year + 1900, date.tm_mon + 1, date.tm_mday,
1461 date.tm_hour, date.tm_min, date.tm_sec );
1463 vlm_MessageAdd( msg_schedule,
1464 vlm_MessageNew( "date", psz_date ) );
1469 vlm_MessageAdd( msg_schedule, vlm_MessageNew("date", "now") );
1472 if( schedule->i_period != 0 )
1474 time_t i_time = (time_t) ( schedule->i_period / 1000000 );
1477 date.tm_sec = (int)( i_time % 60 );
1478 i_time = i_time / 60;
1479 date.tm_min = (int)( i_time % 60 );
1480 i_time = i_time / 60;
1481 date.tm_hour = (int)( i_time % 24 );
1482 i_time = i_time / 24;
1483 date.tm_mday = (int)( i_time % 30 );
1484 i_time = i_time / 30;
1485 /* okay, okay, months are not always 30 days long */
1486 date.tm_mon = (int)( i_time % 12 );
1487 i_time = i_time / 12;
1488 date.tm_year = (int)i_time;
1490 sprintf( buffer, "%d/%d/%d-%d:%d:%d", date.tm_year, date.tm_mon,
1491 date.tm_mday, date.tm_hour, date.tm_min, date.tm_sec);
1493 vlm_MessageAdd( msg_schedule, vlm_MessageNew("period", buffer) );
1497 vlm_MessageAdd( msg_schedule, vlm_MessageNew("period", "0") );
1500 sprintf( buffer, "%d", schedule->i_repeat );
1501 vlm_MessageAdd( msg_schedule, vlm_MessageNew( "repeat", buffer ) );
1504 vlm_MessageAdd( msg_schedule, vlm_MessageNew("commands", 0) );
1506 for( i = 0; i < schedule->i_command; i++ )
1508 vlm_MessageAdd( msg_child,
1509 vlm_MessageNew( schedule->command[i], NULL ) );
1516 else if( psz_filter && strcmp( psz_filter, "media") == 0 )
1520 vlm_message_t *msg_child;
1522 msg = vlm_MessageNew( "show", NULL );
1523 msg_child = vlm_MessageAdd( msg, vlm_MessageNew( "media", NULL ) );
1525 for( i = 0; i < vlm->i_media; i++ )
1527 vlm_media_t *m = vlm->media[i];
1528 vlm_message_t *msg_media, *msg_instance;
1530 msg_media = vlm_MessageAdd( msg_child,
1531 vlm_MessageNew( m->psz_name, 0 ) );
1533 vlm_MessageAdd( msg_media,
1534 vlm_MessageNew( "type", m->i_type == VOD_TYPE ?
1535 "vod" : "broadcast" ) );
1537 vlm_MessageAdd( msg_media,
1538 vlm_MessageNew( "enabled", m->b_enabled ?
1541 msg_instance = vlm_MessageAdd( msg_media,
1542 vlm_MessageNew( "instances", 0 ) );
1544 for( j = 0; j < m->i_instance; j++ )
1546 vlm_media_instance_t *p_instance = m->instance[j];
1549 if( !p_instance->p_input ) val.i_int = END_S;
1550 else var_Get( p_instance->p_input, "state", &val );
1552 vlm_MessageAdd( msg_instance,
1553 vlm_MessageNew( p_instance->psz_name ?
1554 p_instance->psz_name : "default",
1555 val.i_int == PLAYING_S ? "playing" :
1556 val.i_int == PAUSE_S ? "paused" :
1564 else if( psz_filter && strcmp( psz_filter, "schedule") == 0 )
1568 vlm_message_t *msg_child;
1570 msg = vlm_MessageNew( "show", NULL );
1571 msg_child = vlm_MessageAdd( msg, vlm_MessageNew( "schedule", NULL ) );
1573 for( i = 0; i < vlm->i_schedule; i++ )
1575 vlm_schedule_t *s = vlm->schedule[i];
1576 vlm_message_t *msg_schedule;
1577 mtime_t i_time, i_next_date;
1579 msg_schedule = vlm_MessageAdd( msg_child,
1580 vlm_MessageNew( s->psz_name, 0 ) );
1581 vlm_MessageAdd( msg_schedule,
1582 vlm_MessageNew( "enabled", s->b_enabled ?
1585 if( !s->b_enabled ) return msg;
1588 vlm_MessageAdd( msg_schedule,
1589 vlm_MessageNew( "enabled", "yes" ) );
1591 /* calculate next date */
1593 i_next_date = s->i_date;
1595 if( s->i_period != 0 )
1598 while( s->i_date + j * s->i_period <= i_time &&
1604 i_next_date = s->i_date + j * s->i_period;
1607 if( i_next_date > i_time )
1609 time_t i_date = (time_t) (i_next_date / 1000000) ;
1613 ctime_r( &i_date, psz_date );
1615 char *psz_date = ctime( &i_date );
1618 vlm_MessageAdd( msg_schedule,
1619 vlm_MessageNew( "next launch", psz_date ) );
1626 else if( psz_filter == NULL && media == NULL && schedule == NULL )
1628 vlm_message_t *show1 = vlm_Show( vlm, NULL, NULL, "media" );
1629 vlm_message_t *show2 = vlm_Show( vlm, NULL, NULL, "schedule" );
1631 vlm_MessageAdd( show1, show2->child[0] );
1633 /* We must destroy the parent node "show" of show2
1634 * and not the children */
1635 free( show2->psz_name );
1643 return vlm_MessageNew( "show", NULL );
1647 static vlm_message_t *vlm_Help( vlm_t *vlm, char *psz_filter )
1649 vlm_message_t *message;
1651 if( psz_filter == NULL )
1655 "\n new (name) vod|broadcast|schedule [properties]"
1656 "\n setup (name) (properties)"
1657 "\n show [(name)|media|schedule]"
1658 "\n del (name)|all|media|schedule"
1659 "\n control (name) (command)"
1660 "\n save (config_file)"
1661 "\n load (config_file)"
1662 "\nMedia Proprieties Syntax:"
1663 "\n input (input_name)"
1664 "\n output (output_name)"
1665 "\n option (option_name)[=value]"
1666 "\n enabled|disabled"
1667 "\n loop|unloop (broadcast only)"
1668 "\nSchedule Proprieties Syntax:"
1669 "\n enabled|disabled"
1670 "\n append (command_until_rest_of_the_line)"
1671 "\n date (year)/(month)/(day)-(hour):(minutes):(seconds)|now"
1672 "\n period (years_aka_12_months)/(months_aka_30_days)/(days)-(hours):(minutes):(seconds)"
1673 "\n repeat (number_of_repetitions)"
1674 "\nControl Commands Syntax:"
1675 "\n play\n pause\n stop\n seek (percentage)\n" );
1677 message = vlm_MessageNew( "help", NULL );
1678 vlm_MessageAdd( message, vlm_MessageNew( "Help", help ) );
1683 return vlm_MessageNew( "help", NULL );
1686 /*****************************************************************************
1687 * Config handling functions
1688 *****************************************************************************/
1689 static int vlm_Load( vlm_t *vlm, char *file )
1693 while( *pf != '\0' )
1695 vlm_message_t *message = NULL;
1699 while( pf[i_temp] != '\n' && pf[i_temp] != '\0' && pf[i_temp] != '\r' )
1704 if( pf[i_temp] == '\r' || pf[i_temp] == '\n' )
1707 i_next = i_temp + 1;
1714 if( ExecuteCommand( vlm, pf, &message ) )
1727 static char *vlm_Save( vlm_t *vlm )
1734 for( i = 0; i < vlm->i_media; i++ )
1736 vlm_media_t *media = vlm->media[i];
1738 if( media->i_type == VOD_TYPE )
1740 i_length += strlen( "new vod " ) + strlen(media->psz_name);
1744 i_length += strlen( "new broadcast " ) + strlen(media->psz_name);
1747 if( media->b_enabled == VLC_TRUE )
1749 i_length += strlen( "enabled" );
1753 i_length += strlen( "disabled" );
1756 if( media->b_loop == VLC_TRUE )
1758 i_length += strlen( " loop\n" );
1762 i_length += strlen( "\n" );
1765 for( j = 0; j < media->i_input; j++ )
1767 i_length += strlen( "setup input \"\"\n" ) +
1768 strlen( media->psz_name ) + strlen( media->input[j] );
1771 if( media->psz_output != NULL )
1773 i_length += strlen(media->psz_name) + strlen(media->psz_output) +
1774 strlen( "setup output \n" );
1777 for( j=0 ; j < media->i_option ; j++ )
1779 i_length += strlen(media->psz_name) + strlen(media->option[j]) +
1780 strlen("setup option \n");
1784 for( i = 0; i < vlm->i_schedule; i++ )
1786 vlm_schedule_t *schedule = vlm->schedule[i];
1788 i_length += strlen( "new schedule " ) + strlen( schedule->psz_name );
1790 if( schedule->b_enabled == VLC_TRUE )
1792 i_length += strlen( "date //-:: enabled\n" ) + 14;
1796 i_length += strlen( "date //-:: disabled\n" ) + 14;
1800 if( schedule->i_period != 0 )
1802 i_length += strlen( "setup " ) + strlen( schedule->psz_name ) +
1803 strlen( "period //-::\n" ) + 14;
1806 if( schedule->i_repeat >= 0 )
1810 sprintf( buffer, "%d", schedule->i_repeat );
1811 i_length += strlen( "setup repeat \n" ) +
1812 strlen( schedule->psz_name ) + strlen( buffer );
1819 for( j = 0; j < schedule->i_command; j++ )
1821 i_length += strlen( "setup append \n" ) +
1822 strlen( schedule->psz_name ) + strlen( schedule->command[j] );
1827 /* Don't forget the '\0' */
1829 /* now we have the length of save */
1831 p = save = malloc( i_length );
1834 /* finally we can write in it */
1835 for( i = 0; i < vlm->i_media; i++ )
1837 vlm_media_t *media = vlm->media[i];
1839 if( media->i_type == VOD_TYPE )
1841 p += sprintf( p, "new %s vod ", media->psz_name);
1845 p += sprintf( p, "new %s broadcast ", media->psz_name);
1848 if( media->b_enabled == VLC_TRUE )
1850 p += sprintf( p, "enabled" );
1854 p += sprintf( p, "disabled" );
1857 if( media->b_loop == VLC_TRUE )
1859 p += sprintf( p, " loop\n" );
1863 p += sprintf( p, "\n" );
1866 for( j = 0; j < media->i_input; j++ )
1868 p += sprintf( p, "setup %s input \"%s\"\n", media->psz_name,
1872 if( media->psz_output != NULL )
1874 p += sprintf( p, "setup %s output %s\n", media->psz_name,
1875 media->psz_output );
1878 for( j = 0; j < media->i_option; j++ )
1880 p += sprintf( p, "setup %s option %s\n", media->psz_name,
1885 /* and now, the schedule scripts */
1887 for( i = 0; i < vlm->i_schedule; i++ )
1889 vlm_schedule_t *schedule = vlm->schedule[i];
1891 time_t i_time = (time_t) ( schedule->i_date / 1000000 );
1893 #ifdef HAVE_LOCALTIME_R
1894 localtime_r( &i_time, &date);
1896 struct tm *p_date = localtime( &i_time );
1900 p += sprintf( p, "new %s schedule ", schedule->psz_name);
1902 if( schedule->b_enabled == VLC_TRUE )
1904 p += sprintf( p, "date %d/%d/%d-%d:%d:%d enabled\n",
1905 date.tm_year + 1900, date.tm_mon + 1, date.tm_mday,
1906 date.tm_hour, date.tm_min, date.tm_sec );
1910 p += sprintf( p, "date %d/%d/%d-%d:%d:%d disabled\n",
1911 date.tm_year + 1900, date.tm_mon + 1, date.tm_mday,
1912 date.tm_hour, date.tm_min, date.tm_sec);
1915 if( schedule->i_period != 0 )
1917 p += sprintf( p, "setup %s ", schedule->psz_name );
1919 i_time = (time_t) ( schedule->i_period / 1000000 );
1921 date.tm_sec = (int)( i_time % 60 );
1922 i_time = i_time / 60;
1923 date.tm_min = (int)( i_time % 60 );
1924 i_time = i_time / 60;
1925 date.tm_hour = (int)( i_time % 24 );
1926 i_time = i_time / 24;
1927 date.tm_mday = (int)( i_time % 30 );
1928 i_time = i_time / 30;
1929 /* okay, okay, months are not always 30 days long */
1930 date.tm_mon = (int)( i_time % 12 );
1931 i_time = i_time / 12;
1932 date.tm_year = (int)i_time;
1934 p += sprintf( p, "period %d/%d/%d-%d:%d:%d\n",
1935 date.tm_year, date.tm_mon, date.tm_mday,
1936 date.tm_hour, date.tm_min, date.tm_sec);
1939 if( schedule->i_repeat >= 0 )
1941 p += sprintf( p, "setup %s repeat %d\n",
1942 schedule->psz_name, schedule->i_repeat );
1946 p += sprintf( p, "\n" );
1949 for( j = 0; j < schedule->i_command; j++ )
1951 p += sprintf( p, "setup %s append %s\n",
1952 schedule->psz_name, schedule->command[j] );
1960 /*****************************************************************************
1962 *****************************************************************************/
1963 static int Manage( vlc_object_t* p_object )
1965 vlm_t *vlm = (vlm_t*)p_object;
1967 mtime_t i_lastcheck;
1970 i_lastcheck = mdate();
1974 while( !vlm->b_die )
1976 vlc_mutex_lock( &vlm->lock );
1978 /* destroy the inputs that wants to die, and launch the next input */
1979 for( i = 0; i < vlm->i_media; i++ )
1981 vlm_media_t *p_media = vlm->media[i];
1983 for( j = 0; j < p_media->i_instance; j++ )
1985 vlm_media_instance_t *p_instance = p_media->instance[j];
1987 if( !p_instance->p_input ||
1988 ( !p_instance->p_input->b_eof &&
1989 !p_instance->p_input->b_error ) ) continue;
1991 input_StopThread( p_instance->p_input );
1992 input_DestroyThread( p_instance->p_input );
1993 vlc_object_detach( p_instance->p_input );
1994 vlc_object_destroy( p_instance->p_input );
1996 p_instance->i_index++;
1997 if( p_instance->i_index == p_media->i_input &&
1998 p_media->b_loop ) p_instance->i_index = 0;
2000 if( p_instance->i_index < p_media->i_input )
2002 /* FIXME, find a way to select the right instance */
2004 sprintf( buffer, "%d", p_instance->i_index );
2005 vlm_MediaControl( vlm, p_media, p_instance->psz_name,
2010 if( vlm_MediaControl( vlm, p_media, p_instance->psz_name,
2011 "stop", 0 ) == VLC_SUCCESS ) i--;
2019 for( i = 0; i < vlm->i_schedule; i++ )
2021 mtime_t i_real_date = vlm->schedule[i]->i_date;
2023 if( vlm->schedule[i]->b_enabled == VLC_TRUE )
2025 if( vlm->schedule[i]->i_date == 0 ) // now !
2027 vlm->schedule[i]->i_date = (i_time / 1000000) * 1000000 ;
2028 i_real_date = i_time;
2030 else if( vlm->schedule[i]->i_period != 0 )
2033 while( vlm->schedule[i]->i_date + j *
2034 vlm->schedule[i]->i_period <= i_lastcheck &&
2035 ( vlm->schedule[i]->i_repeat > j ||
2036 vlm->schedule[i]->i_repeat == -1 ) )
2041 i_real_date = vlm->schedule[i]->i_date + j *
2042 vlm->schedule[i]->i_period;
2045 if( i_real_date <= i_time && i_real_date > i_lastcheck )
2047 for( j = 0; j < vlm->schedule[i]->i_command; j++ )
2049 vlm_message_t *message = NULL;
2051 ExecuteCommand( vlm, vlm->schedule[i]->command[j],
2054 /* for now, drop the message */
2061 i_lastcheck = i_time;
2063 vlc_mutex_unlock( &vlm->lock );