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() */
36 #include <vlc/input.h>
39 # include <time.h> /* ctime() */
45 /*****************************************************************************
47 *****************************************************************************/
48 static char *vlm_Save( vlm_t * );
49 static int vlm_Load( vlm_t *, char *);
50 static vlm_message_t *vlm_Show( vlm_t *, vlm_media_t *, vlm_schedule_t *, char * );
51 static vlm_message_t *vlm_Help( vlm_t *, char * );
53 static vlm_media_t *vlm_MediaNew ( vlm_t *, char *, int );
54 static void vlm_MediaDelete ( vlm_t *, vlm_media_t *, char * );
55 static vlm_media_t *vlm_MediaSearch ( vlm_t *, char * );
56 static int vlm_MediaSetup ( vlm_t *, vlm_media_t *, char *, char * );
57 static int vlm_MediaControl( vlm_t *, vlm_media_t *, char *, char *, char * );
58 static vlm_media_instance_t *vlm_MediaInstanceSearch( vlm_t *, vlm_media_t *, char * );
60 static vlm_message_t *vlm_MessageNew( char *, const char *, ... );
61 static vlm_message_t *vlm_MessageAdd( vlm_message_t*, vlm_message_t* );
63 static vlm_schedule_t *vlm_ScheduleNew( vlm_t *, char *);
64 static void vlm_ScheduleDelete( vlm_t *, vlm_schedule_t *, char *);
65 static int vlm_ScheduleSetup( vlm_schedule_t *, char *, char *);
66 static vlm_schedule_t *vlm_ScheduleSearch( vlm_t *, char *);
68 static int vlm_MediaVodControl( void *, vod_media_t *, char *, int, va_list );
70 static int ExecuteCommand( vlm_t *, char *, vlm_message_t **);
71 static int Manage( vlc_object_t* );
73 /*****************************************************************************
75 *****************************************************************************/
76 vlm_t *__vlm_New ( vlc_object_t *p_this )
81 /* to be sure to avoid multiple creation */
82 var_Create( p_this->p_libvlc, "vlm_mutex", VLC_VAR_MUTEX );
83 var_Get( p_this->p_libvlc, "vlm_mutex", &lockval );
84 vlc_mutex_lock( lockval.p_address );
86 if( !(vlm = vlc_object_find( p_this, VLC_OBJECT_VLM, FIND_ANYWHERE )) )
88 msg_Info( p_this, "creating vlm" );
89 if( ( vlm = vlc_object_create( p_this, VLC_OBJECT_VLM ) ) == NULL )
91 vlc_mutex_unlock( lockval.p_address );
95 vlc_mutex_init( p_this->p_vlc, &vlm->lock );
100 vlm->schedule = NULL;
102 vlc_object_yield( vlm );
103 vlc_object_attach( vlm, p_this->p_vlc );
105 vlc_mutex_unlock( lockval.p_address );
107 if( vlc_thread_create( vlm, "vlm thread",
108 Manage, VLC_THREAD_PRIORITY_LOW, VLC_FALSE ) )
110 vlc_mutex_destroy( &vlm->lock );
111 vlc_object_destroy( vlm );
118 /*****************************************************************************
120 *****************************************************************************/
121 void vlm_Delete( vlm_t *vlm )
125 var_Get( vlm->p_libvlc, "vlm_mutex", &lockval );
126 vlc_mutex_lock( lockval.p_address );
128 vlc_object_release( vlm );
130 if( vlm->i_refcount > 0 )
132 vlc_mutex_unlock( lockval.p_address );
136 vlm->b_die = VLC_TRUE;
137 vlc_thread_join( vlm );
139 vlc_mutex_destroy( &vlm->lock );
141 while( vlm->i_media ) vlm_MediaDelete( vlm, vlm->media[0], NULL );
142 if( vlm->media ) free( vlm->media );
144 while( vlm->i_schedule ) vlm_ScheduleDelete( vlm, vlm->schedule[0], NULL );
145 if( vlm->schedule ) free( vlm->schedule );
147 vlc_object_detach( vlm );
148 vlc_object_destroy( vlm );
149 vlc_mutex_unlock( lockval.p_address );
152 /*****************************************************************************
153 * vlm_ExecuteCommand:
154 *****************************************************************************/
155 int vlm_ExecuteCommand( vlm_t *vlm, char *command, vlm_message_t **message)
159 vlc_mutex_lock( &vlm->lock );
160 result = ExecuteCommand( vlm, command, message );
161 vlc_mutex_unlock( &vlm->lock );
166 /*****************************************************************************
168 *****************************************************************************/
169 static char *FindEndCommand( char *psz )
171 char *psz_sent = psz;
178 while( ( *psz_sent != '\"' ) && ( *psz_sent != '\0' ) )
180 if( *psz_sent == '\'' )
182 psz_sent = FindEndCommand( psz_sent );
183 if( psz_sent == NULL ) return NULL;
188 if( *psz_sent == '\"' )
194 /* *psz_sent == '\0' -> number of " is incorrect */
202 while( ( *psz_sent != '\'' ) && ( *psz_sent != '\0' ) )
204 if( *psz_sent == '\"' )
206 psz_sent = FindEndCommand( psz_sent );
207 if( psz_sent == NULL ) return NULL;
212 if( *psz_sent == '\'' )
218 /* *psz_sent == '\0' -> number of " is incorrect */
223 default: /* now we can look for spaces */
224 while( ( *psz_sent != ' ' ) && ( *psz_sent != '\0' ) )
226 if( ( *psz_sent == '\'' ) || ( *psz_sent == '\"' ) )
228 psz_sent = FindEndCommand( psz_sent );
237 /*****************************************************************************
238 * ExecuteCommand: The main state machine
239 *****************************************************************************
240 * Execute a command which ends with '\0' (string)
241 *****************************************************************************/
242 static int ExecuteCommand(vlm_t *vlm, char *command, vlm_message_t **p_message)
245 char **p_command = NULL;
247 vlm_message_t *message = NULL;
250 /* First, parse the line and cut it */
251 while( *cmd != '\0' )
263 p_temp = FindEndCommand( cmd );
265 if( p_temp == NULL ) goto error;
267 i_temp = p_temp - cmd;
269 p_command = realloc( p_command, (i_command + 1) * sizeof(char*) );
270 p_command[ i_command ] = malloc( (i_temp + 1) * sizeof(char) );
271 strncpy( p_command[ i_command ], cmd, i_temp );
272 p_command[ i_command ][ i_temp ] = '\0';
280 * And then Interpret it
285 message = vlm_MessageNew( "", NULL );
289 if( strcmp(p_command[0], "new") == 0 )
293 /* Check the number of arguments */
294 if( i_command < 3 ) goto syntax_error;
297 if( strcmp(p_command[2], "vod") == 0 )
301 else if( strcmp(p_command[2], "broadcast") == 0 )
303 i_type = BROADCAST_TYPE;
305 else if( strcmp(p_command[2], "schedule") == 0 )
307 i_type = SCHEDULE_TYPE;
311 message = vlm_MessageNew( "new", "%s: Choose between vod, "
312 "broadcast or schedule", p_command[1] );
316 /* Check for forbidden media names */
317 if( strcmp(p_command[1], "all") == 0 ||
318 strcmp(p_command[1], "media") == 0 ||
319 strcmp(p_command[1], "schedule") == 0 )
321 message = vlm_MessageNew( "new", "\"all\", \"media\" and "
322 "\"schedule\" are reserved names" );
326 /* Check the name is not already in use */
327 if( vlm_ScheduleSearch( vlm, p_command[1] ) ||
328 vlm_MediaSearch( vlm, p_command[1] ) )
330 message = vlm_MessageNew( "new", "%s: Name already in use",
336 if( i_type == SCHEDULE_TYPE )
338 vlm_schedule_t *schedule;
339 schedule = vlm_ScheduleNew( vlm, p_command[1] );
342 message = vlm_MessageNew( "new", "could not create schedule" );
351 media = vlm_MediaNew( vlm, p_command[1], i_type );
354 message = vlm_MessageNew( "new", "could not create media" );
361 message = vlm_MessageNew( "new", NULL );
365 /* Properties will be dealt with later on */
368 else if( strcmp(p_command[0], "setup") == 0 )
370 if( i_command < 2 ) goto syntax_error;
372 /* Properties will be dealt with later on */
375 else if( strcmp(p_command[0], "del") == 0 )
378 vlm_schedule_t *schedule;
380 if( i_command < 2 ) goto syntax_error;
382 media = vlm_MediaSearch( vlm, p_command[1] );
383 schedule = vlm_ScheduleSearch( vlm, p_command[1] );
385 if( schedule != NULL )
387 vlm_ScheduleDelete( vlm, schedule, NULL );
389 else if( media != NULL )
391 vlm_MediaDelete( vlm, media, NULL );
393 else if( strcmp(p_command[1], "media") == 0 )
395 while( vlm->i_media ) vlm_MediaDelete( vlm, vlm->media[0], NULL );
397 else if( strcmp(p_command[1], "schedule") == 0 )
399 while( vlm->i_schedule )
400 vlm_ScheduleDelete( vlm, vlm->schedule[0], NULL );
402 else if( strcmp(p_command[1], "all") == 0 )
404 while( vlm->i_media ) vlm_MediaDelete( vlm, vlm->media[0], NULL );
406 while( vlm->i_schedule )
407 vlm_ScheduleDelete( vlm, vlm->schedule[0], NULL );
411 message = vlm_MessageNew( "del", "%s: media unknown",
416 message = vlm_MessageNew( "del", NULL );
420 else if( strcmp(p_command[0], "show") == 0 )
423 vlm_schedule_t *schedule;
427 message = vlm_Show( vlm, NULL, NULL, NULL );
430 else if( i_command > 2 ) goto syntax_error;
432 media = vlm_MediaSearch( vlm, p_command[1] );
433 schedule = vlm_ScheduleSearch( vlm, p_command[1] );
435 if( schedule != NULL )
437 message = vlm_Show( vlm, NULL, schedule, NULL );
439 else if( media != NULL )
441 message = vlm_Show( vlm, media, NULL, NULL );
445 message = vlm_Show( vlm, NULL, NULL, p_command[1] );
451 else if( strcmp(p_command[0], "help") == 0 )
453 if( i_command != 1 ) goto syntax_error;
455 message = vlm_Help( vlm, NULL );
459 else if( strcmp(p_command[0], "control") == 0 )
463 if( i_command < 3 ) goto syntax_error;
465 if( !(media = vlm_MediaSearch( vlm, p_command[1] ) ) )
467 message = vlm_MessageNew( "control", "%s: media unknown",
473 char *psz_command, *psz_arg = 0, *psz_instance = 0;
476 if( strcmp(p_command[2], "play") && strcmp(p_command[2], "stop") &&
477 strcmp(p_command[2], "pause") && strcmp(p_command[2], "seek") )
480 psz_instance = p_command[2];
482 if( i_command < 4 ) goto syntax_error;
485 psz_command = p_command[i_index];
487 if( i_command >= i_index + 2 ) psz_arg = p_command[i_index + 1];
489 vlm_MediaControl( vlm, media, psz_instance, psz_command, psz_arg );
490 message = vlm_MessageNew( "control", NULL );
495 else if( strcmp(p_command[0], "save") == 0 )
499 if( i_command != 2 ) goto syntax_error;
501 file = fopen( p_command[1], "w" );
504 message = vlm_MessageNew( "save", "Unable to save file" );
509 char *save = vlm_Save( vlm );
510 fwrite( save, strlen( save ), 1, file );
513 message = vlm_MessageNew( "save", NULL );
518 else if( strcmp(p_command[0], "load") == 0 )
522 if( i_command != 2 ) goto syntax_error;
524 file = fopen( p_command[1], "r" );
528 message = vlm_MessageNew( "load", "Unable to load file" );
536 if( fseek( file, 0, SEEK_END) == 0 )
538 size = ftell( file );
539 fseek( file, 0, SEEK_SET);
540 buffer = malloc( size + 1 );
541 fread( buffer, 1, size, file);
542 buffer[ size ] = '\0';
543 if( vlm_Load( vlm, buffer ) )
546 message = vlm_MessageNew( "load", "error while loading "
554 message = vlm_MessageNew( "load", "read file error" );
559 message = vlm_MessageNew( "load", NULL );
566 message = vlm_MessageNew( p_command[0], "Unknown command" );
570 /* Common code between "new" and "setup" */
571 if( strcmp(p_command[0], "new") == 0 ||
572 strcmp(p_command[0], "setup") == 0 )
574 int i_command_start = strcmp(p_command[0], "new") ? 2 : 3;
576 vlm_schedule_t *schedule;
578 if( i_command < i_command_start ) goto syntax_error;
580 media = vlm_MediaSearch( vlm, p_command[1] );
581 schedule = vlm_ScheduleSearch( vlm, p_command[1] );
583 if( !media && !schedule )
585 message = vlm_MessageNew( p_command[0], "%s unknown",
590 if( schedule != NULL )
592 for( i = i_command_start ; i < i_command ; i++ )
594 if( strcmp( p_command[i], "enabled" ) == 0 ||
595 strcmp( p_command[i], "disabled" ) == 0 )
597 vlm_ScheduleSetup( schedule, p_command[i], NULL );
600 /* Beware: everything behind append is considered as
602 else if( strcmp( p_command[i], "append" ) == 0 )
604 if( ++i >= i_command ) break;
606 for( j = i + 1; j < i_command; j++ )
609 realloc( p_command[i], strlen(p_command[i]) +
610 strlen(p_command[j]) + 1 + 1 );
611 strcat( p_command[i], " " );
612 strcat( p_command[i], p_command[j] );
615 vlm_ScheduleSetup( schedule, p_command[i - 1],
621 if( i + 1 >= i_command && !strcmp(p_command[0], "new") )
623 vlm_ScheduleDelete( vlm, schedule, NULL );
624 message = vlm_MessageNew( p_command[0],
625 "Wrong properties syntax" );
628 else if( i + 1 >= i_command )
630 message = vlm_MessageNew( p_command[0],
631 "Wrong properties syntax" );
635 vlm_ScheduleSetup( schedule, p_command[i],
642 else if( media != NULL )
644 for( i = i_command_start ; i < i_command ; i++ )
646 if( strcmp( p_command[i], "enabled" ) == 0 ||
647 strcmp( p_command[i], "disabled" ) == 0 )
649 vlm_MediaSetup( vlm, media, p_command[i], NULL );
651 else if( strcmp( p_command[i], "loop" ) == 0 ||
652 strcmp( p_command[i], "unloop" ) == 0 )
654 if( media->i_type != BROADCAST_TYPE )
656 message = vlm_MessageNew( p_command[0],
657 "loop only available for broadcast" );
661 vlm_MediaSetup( vlm, media, p_command[i], NULL );
666 if( i + 1 >= i_command && !strcmp(p_command[0], "new") )
668 vlm_MediaDelete( vlm, media, NULL );
669 message = vlm_MessageNew( p_command[0],
670 "Wrong properties syntax" );
673 else if( i + 1 >= i_command )
675 message = vlm_MessageNew( p_command[0],
676 "Wrong properties syntax" );
680 vlm_MediaSetup( vlm, media, p_command[i], p_command[i+1] );
686 message = vlm_MessageNew( p_command[0], NULL );
691 for( i = 0 ; i < i_command ; i++ ) free( p_command[i] );
692 if( p_command ) free( p_command );
693 *p_message = message;
698 message = vlm_MessageNew( p_command[0], "Wrong command syntax" );
701 for( i = 0 ; i < i_command ; i++ ) free( p_command[i] );
702 if( p_command ) free( p_command );
703 *p_message = message;
708 static vlm_media_t *vlm_MediaSearch( vlm_t *vlm, char *psz_name )
712 for( i = 0; i < vlm->i_media; i++ )
714 if( strcmp( psz_name, vlm->media[i]->psz_name ) == 0 )
716 return vlm->media[i];
723 /*****************************************************************************
725 *****************************************************************************/
726 static vlm_media_instance_t *
727 vlm_MediaInstanceSearch( vlm_t *vlm, vlm_media_t *media, char *psz_name )
731 for( i = 0; i < media->i_instance; i++ )
733 if( ( !psz_name && !media->instance[i]->psz_name ) ||
734 ( psz_name && media->instance[i]->psz_name &&
735 !strcmp( psz_name, media->instance[i]->psz_name ) ) )
737 return media->instance[i];
744 static vlm_media_t *vlm_MediaNew( vlm_t *vlm, char *psz_name, int i_type )
746 vlm_media_t *media = malloc( sizeof( vlm_media_t ) );
748 /* Check if we need to load the VOD server */
749 if( i_type == VOD_TYPE && !vlm->i_vod )
751 vlm->vod = vlc_object_create( vlm, VLC_OBJECT_VOD );
752 vlc_object_attach( vlm->vod, vlm );
753 vlm->vod->p_module = module_Need( vlm->vod, "vod server", 0, 0 );
754 if( !vlm->vod->p_module )
756 msg_Err( vlm, "cannot find vod server" );
757 vlc_object_detach( vlm->vod );
758 vlc_object_destroy( vlm->vod );
764 vlm->vod->p_data = vlm;
765 vlm->vod->pf_media_control = vlm_MediaVodControl;
767 if( i_type == VOD_TYPE ) vlm->i_vod++;
769 media->psz_name = strdup( psz_name );
770 media->b_enabled = VLC_FALSE;
771 media->b_loop = VLC_FALSE;
772 media->vod_media = NULL;
773 media->psz_vod_output = NULL;
776 media->psz_output = NULL;
778 media->option = NULL;
779 media->i_type = i_type;
780 media->i_instance = 0;
781 media->instance = NULL;
783 media->item.psz_uri = strdup( psz_name );
784 vlc_input_item_Init( VLC_OBJECT(vlm), &media->item );
786 TAB_APPEND( vlm->i_media, vlm->media, media );
791 /* for now, simple delete. After, del with options (last arg) */
792 static void vlm_MediaDelete( vlm_t *vlm, vlm_media_t *media, char *psz_name )
794 if( media == NULL ) return;
796 while( media->i_instance )
798 vlm_media_instance_t *p_instance = media->instance[0];
799 vlm_MediaControl( vlm, media, p_instance->psz_name, "stop", 0 );
802 TAB_REMOVE( vlm->i_media, vlm->media, media );
804 if( media->i_type == VOD_TYPE )
806 vlm_MediaSetup( vlm, media, "disabled", 0 );
810 /* Check if we need to unload the VOD server */
811 if( media->i_type == VOD_TYPE && !vlm->i_vod )
813 module_Unneed( vlm->vod, vlm->vod->p_module );
814 vlc_object_detach( vlm->vod );
815 vlc_object_destroy( vlm->vod );
819 if( vlm->i_media == 0 && vlm->media ) free( vlm->media );
821 free( media->psz_name );
823 while( media->i_input-- ) free( media->input[media->i_input] );
824 if( media->input ) free( media->input );
826 if( media->psz_output ) free( media->psz_output );
828 while( media->i_option-- ) free( media->option[media->i_option] );
829 if( media->option ) free( media->option );
831 vlc_input_item_Clean( &media->item );
836 static int vlm_MediaSetup( vlm_t *vlm, vlm_media_t *media, char *psz_cmd,
839 if( strcmp( psz_cmd, "loop" ) == 0 )
841 media->b_loop = VLC_TRUE;
843 else if( strcmp( psz_cmd, "unloop" ) == 0 )
845 media->b_loop = VLC_FALSE;
847 else if( strcmp( psz_cmd, "enabled" ) == 0 )
849 media->b_enabled = VLC_TRUE;
851 else if( strcmp( psz_cmd, "disabled" ) == 0 )
853 media->b_enabled = VLC_FALSE;
855 else if( strcmp( psz_cmd, "input" ) == 0 )
859 if( psz_value != NULL && strlen(psz_value) > 1 &&
860 ( psz_value[0] == '\'' || psz_value[0] == '\"' ) &&
861 ( psz_value[ strlen(psz_value) - 1 ] == '\'' ||
862 psz_value[ strlen(psz_value) - 1 ] == '\"' ) )
864 input = malloc( strlen(psz_value) - 1 );
866 memcpy( input, psz_value + 1, strlen(psz_value) - 2 );
867 input[ strlen(psz_value) - 2 ] = '\0';
871 input = strdup( psz_value );
874 TAB_APPEND( media->i_input, media->input, input );
876 else if( strcmp( psz_cmd, "output" ) == 0 )
878 if( media->psz_output != NULL )
880 free( media->psz_output );
882 media->psz_output = strdup( psz_value );
884 else if( strcmp( psz_cmd, "option" ) == 0 )
887 option = strdup( psz_value );
889 TAB_APPEND( media->i_option, media->option, option );
896 /* Check if we need to create/delete a vod media */
897 if( media->i_type == VOD_TYPE )
899 if( !media->b_enabled && media->vod_media )
901 vlm->vod->pf_media_del( vlm->vod, media->vod_media );
902 media->vod_media = 0;
904 else if( media->b_enabled && !media->vod_media && media->i_input )
906 /* Pre-parse the input */
907 input_thread_t *p_input;
911 vlc_input_item_Clean( &media->item );
912 vlc_input_item_Init( VLC_OBJECT(vlm), &media->item );
914 if( media->psz_output )
915 asprintf( &psz_output, "%s:description", media->psz_output );
917 asprintf( &psz_output, "#description" );
919 media->item.psz_uri = strdup( media->input[0] );
920 media->item.ppsz_options = malloc( sizeof( char* ) );
921 asprintf( &media->item.ppsz_options[0], "sout=%s", psz_output);
922 media->item.i_options = 1;
923 for( i = 0; i < media->i_option; i++ )
925 media->item.i_options++;
926 media->item.ppsz_options =
927 realloc( media->item.ppsz_options,
928 media->item.i_options * sizeof( char* ) );
929 media->item.ppsz_options[ media->item.i_options - 1 ] =
930 strdup( media->option[i] );
933 if( (p_input = input_CreateThread( vlm, &media->item ) ) )
935 while( !p_input->b_eof && !p_input->b_error ) msleep( 100000 );
937 input_StopThread( p_input );
938 input_DestroyThread( p_input );
939 vlc_object_detach( p_input );
940 vlc_object_destroy( p_input );
945 vlm->vod->pf_media_new( vlm->vod, media->psz_name,
953 static int vlm_MediaControl( vlm_t *vlm, vlm_media_t *media, char *psz_id,
954 char *psz_command, char *psz_args )
956 vlm_media_instance_t *p_instance;
959 p_instance = vlm_MediaInstanceSearch( vlm, media, psz_id );
961 if( strcmp( psz_command, "play" ) == 0 && !p_instance )
963 if( !media->b_enabled || media->i_input == 0 ) return 0;
967 p_instance = malloc( sizeof(vlm_media_instance_t) );
968 memset( p_instance, 0, sizeof(vlm_media_instance_t) );
969 vlc_input_item_Init( VLC_OBJECT(vlm), &p_instance->item );
970 p_instance->p_input = 0;
972 if( media->psz_output != NULL || media->psz_vod_output != NULL )
974 p_instance->item.ppsz_options = malloc( sizeof( char* ) );
975 asprintf( &p_instance->item.ppsz_options[0], "sout=%s%s%s",
976 media->psz_output ? media->psz_output : "",
977 (media->psz_output && media->psz_vod_output) ?
978 ":" : media->psz_vod_output ? "#" : "",
979 media->psz_vod_output ? media->psz_vod_output : "" );
980 p_instance->item.i_options = 1;
983 for( i = 0; i < media->i_option; i++ )
985 p_instance->item.i_options++;
986 p_instance->item.ppsz_options =
987 realloc( p_instance->item.ppsz_options,
988 p_instance->item.i_options * sizeof( char* ) );
989 p_instance->item.ppsz_options[p_instance->item.i_options - 1] =
990 strdup( media->option[i] );
993 p_instance->psz_name = psz_id ? strdup(psz_id) : 0;
994 TAB_APPEND( media->i_instance, media->instance, p_instance );
997 if( psz_args && sscanf(psz_args, "%d", &i) == 1 && i < media->i_input )
999 p_instance->i_index = i;
1002 if( p_instance->item.psz_uri ) free( p_instance->item.psz_uri );
1003 p_instance->item.psz_uri =
1004 strdup( media->input[p_instance->i_index] );
1006 if( p_instance->p_input )
1008 input_StopThread( p_instance->p_input );
1009 input_DestroyThread( p_instance->p_input );
1010 vlc_object_detach( p_instance->p_input );
1011 vlc_object_destroy( p_instance->p_input );
1014 p_instance->p_input = input_CreateThread( vlm, &p_instance->item );
1015 if( !p_instance->p_input )
1017 TAB_REMOVE( media->i_instance, media->instance, p_instance );
1018 vlc_input_item_Clean( &p_instance->item );
1019 if( p_instance->psz_name ) free( p_instance->psz_name );
1025 if( !p_instance ) return VLC_EGENERIC;
1027 if( strcmp( psz_command, "seek" ) == 0 )
1032 if( psz_args && sscanf( psz_args, "%f", &f_percentage ) == 1 )
1034 val.f_float = f_percentage / 100.0 ;
1035 var_Set( p_instance->p_input, "position", val );
1039 else if( strcmp( psz_command, "stop" ) == 0 )
1041 TAB_REMOVE( media->i_instance, media->instance, p_instance );
1043 if( p_instance->p_input )
1045 input_StopThread( p_instance->p_input );
1046 input_DestroyThread( p_instance->p_input );
1047 vlc_object_detach( p_instance->p_input );
1048 vlc_object_destroy( p_instance->p_input );
1051 vlc_input_item_Clean( &p_instance->item );
1052 if( p_instance->psz_name ) free( p_instance->psz_name );
1057 else if( strcmp( psz_command, "pause" ) == 0 )
1061 if( !p_instance->p_input ) return VLC_SUCCESS;
1063 var_Get( p_instance->p_input, "state", &val );
1065 if( val.i_int == PAUSE_S ) val.i_int = PLAYING_S;
1066 else val.i_int = PAUSE_S;
1067 var_Set( p_instance->p_input, "state", val );
1072 return VLC_EGENERIC;
1075 /*****************************************************************************
1077 *****************************************************************************/
1078 static vlm_schedule_t *vlm_ScheduleNew( vlm_t *vlm, char *psz_name )
1080 vlm_schedule_t *sched = malloc( sizeof( vlm_schedule_t ) );
1082 sched->psz_name = strdup( psz_name );
1083 sched->b_enabled = VLC_FALSE;
1084 sched->i_command = 0;
1085 sched->command = NULL;
1087 sched->i_period = 0;
1088 sched->i_repeat = -1;
1090 TAB_APPEND( vlm->i_schedule, vlm->schedule, sched );
1095 /* for now, simple delete. After, del with options (last arg) */
1096 static void vlm_ScheduleDelete( vlm_t *vlm, vlm_schedule_t *sched,
1099 if( sched == NULL ) return;
1101 TAB_REMOVE( vlm->i_schedule, vlm->schedule, sched );
1103 if( vlm->i_schedule == 0 && vlm->schedule ) free( vlm->schedule );
1104 free( sched->psz_name );
1105 while( sched->i_command-- ) free( sched->command[sched->i_command] );
1109 static vlm_schedule_t *vlm_ScheduleSearch( vlm_t *vlm, char *psz_name )
1113 for( i = 0; i < vlm->i_schedule; i++ )
1115 if( strcmp( psz_name, vlm->schedule[i]->psz_name ) == 0 )
1117 return vlm->schedule[i];
1124 /* Ok, setup schedule command will be able to support only one (argument value) at a time */
1125 static int vlm_ScheduleSetup( vlm_schedule_t *schedule, char *psz_cmd,
1128 if( strcmp( psz_cmd, "enabled" ) == 0 )
1130 schedule->b_enabled = VLC_TRUE;
1132 else if( strcmp( psz_cmd, "disabled" ) == 0 )
1134 schedule->b_enabled = VLC_FALSE;
1136 #if !defined( UNDER_CE )
1137 else if( strcmp( psz_cmd, "date" ) == 0 )
1143 time.tm_sec = 0; /* seconds */
1144 time.tm_min = 0; /* minutes */
1145 time.tm_hour = 0; /* hours */
1146 time.tm_mday = 0; /* day of the month */
1147 time.tm_mon = 0; /* month */
1148 time.tm_year = 0; /* year */
1149 time.tm_wday = 0; /* day of the week */
1150 time.tm_yday = 0; /* day in the year */
1151 time.tm_isdst = 0; /* daylight saving time */
1153 /* date should be year/month/day-hour:minutes:seconds */
1154 p = strchr( psz_value, '-' );
1156 if( strcmp( psz_value, "now" ) == 0 )
1158 schedule->i_date = 0;
1160 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 */
1168 switch( sscanf( p + 1, "%d:%d:%d", &i, &j, &k ) )
1188 switch( sscanf( psz_value, "%d/%d/%d", &i, &j, &k ) )
1194 time.tm_mon = i - 1;
1198 time.tm_year = i - 1900;
1199 time.tm_mon = j - 1;
1206 date = mktime( &time );
1207 schedule->i_date = ((mtime_t) date) * 1000000;
1210 else if( strcmp( psz_cmd, "period" ) == 0 )
1214 char *psz_time = NULL, *psz_date = NULL;
1218 /* First, if date or period are modified, repeat should be equal to -1 */
1219 schedule->i_repeat = -1;
1221 time.tm_sec = 0; /* seconds */
1222 time.tm_min = 0; /* minutes */
1223 time.tm_hour = 0; /* hours */
1224 time.tm_mday = 0; /* day of the month */
1225 time.tm_mon = 0; /* month */
1226 time.tm_year = 0; /* year */
1227 time.tm_wday = 0; /* day of the week */
1228 time.tm_yday = 0; /* day in the year */
1229 time.tm_isdst = 0; /* daylight saving time */
1231 /* date should be year/month/day-hour:minutes:seconds */
1232 p = strchr( psz_value, '-' );
1235 psz_date = psz_value;
1242 psz_time = psz_value;
1246 switch( sscanf( psz_time, "%d:%d:%d", &i, &j, &k ) )
1265 switch( sscanf( psz_date, "%d/%d/%d", &i, &j, &k ) )
1284 /* ok, that's stupid... who is going to schedule streams every 42 years ? */
1285 date = (((( time.tm_year * 12 + time.tm_mon ) * 30 + time.tm_mday ) * 24 + time.tm_hour ) * 60 + time.tm_min ) * 60 + time.tm_sec ;
1286 schedule->i_period = ((mtime_t) date) * 1000000;
1288 #endif /* UNDER_CE */
1289 else if( strcmp( psz_cmd, "repeat" ) == 0 )
1293 if( sscanf( psz_value, "%d", &i ) == 1 )
1295 schedule->i_repeat = i;
1302 else if( strcmp( psz_cmd, "append" ) == 0 )
1304 char *command = strdup( psz_value );
1306 TAB_APPEND( schedule->i_command, schedule->command, command );
1315 /*****************************************************************************
1316 * Message handling functions
1317 *****************************************************************************/
1318 static vlm_message_t *vlm_MessageNew( char *psz_name,
1319 const char *psz_format, ... )
1321 vlm_message_t *p_message;
1324 if( !psz_name ) return 0;
1326 p_message = malloc( sizeof(vlm_message_t) );
1327 p_message->psz_value = 0;
1331 va_start( args, psz_format );
1332 if( vasprintf( &p_message->psz_value, psz_format, args ) < 0 )
1341 p_message->psz_name = strdup( psz_name );
1342 p_message->i_child = 0;
1343 p_message->child = NULL;
1348 void vlm_MessageDelete( vlm_message_t *p_message )
1350 if( p_message->psz_name ) free( p_message->psz_name );
1351 if( p_message->psz_value ) free( p_message->psz_value );
1352 while( p_message->i_child-- )
1353 vlm_MessageDelete( p_message->child[p_message->i_child] );
1354 if( p_message->child ) free( p_message->child );
1359 static vlm_message_t *vlm_MessageAdd( vlm_message_t *p_message,
1360 vlm_message_t *p_child )
1362 if( p_message == NULL ) return NULL;
1366 TAB_APPEND( p_message->i_child, p_message->child, p_child );
1372 /*****************************************************************************
1373 * Misc utility functions
1374 *****************************************************************************/
1375 static vlm_message_t *vlm_Show( vlm_t *vlm, vlm_media_t *media,
1376 vlm_schedule_t *schedule, char *psz_filter )
1382 vlm_message_t *msg_media;
1383 vlm_message_t *msg_child;
1385 msg = vlm_MessageNew( "show", NULL );
1386 msg_media = vlm_MessageAdd( msg, vlm_MessageNew( media->psz_name, 0 ));
1388 vlm_MessageAdd( msg_media,
1389 vlm_MessageNew( "type", media->i_type == VOD_TYPE ?
1390 "vod" : "broadcast" ) );
1391 vlm_MessageAdd( msg_media,
1392 vlm_MessageNew( "enabled", media->b_enabled ?
1395 vlm_MessageAdd( msg_media,
1396 vlm_MessageNew( "loop", media->b_loop ?
1399 msg_child = vlm_MessageAdd( msg_media,
1400 vlm_MessageNew( "inputs", NULL ) );
1402 for( i = 0; i < media->i_input; i++ )
1404 vlm_MessageAdd( msg_child,
1405 vlm_MessageNew( media->input[i], NULL ) );
1408 vlm_MessageAdd( msg_media,
1409 vlm_MessageNew( "output", media->psz_output ?
1410 media->psz_output : "" ) );
1412 msg_child = vlm_MessageAdd( msg_media, vlm_MessageNew( "options", 0 ));
1414 for( i = 0; i < media->i_option; i++ )
1416 vlm_MessageAdd( msg_child, vlm_MessageNew( media->option[i], 0 ) );
1419 msg_child = vlm_MessageAdd( msg_media,
1420 vlm_MessageNew( "instances", NULL ) );
1422 for( i = 0; i < media->i_instance; i++ )
1424 vlm_media_instance_t *p_instance = media->instance[i];
1427 if( !p_instance->p_input ) val.i_int = END_S;
1428 else var_Get( p_instance->p_input, "state", &val );
1430 vlm_MessageAdd( msg_child,
1431 vlm_MessageNew( p_instance->psz_name ?
1432 p_instance->psz_name : "default",
1433 val.i_int == PLAYING_S ? "playing" :
1434 val.i_int == PAUSE_S ? "paused" :
1442 else if( schedule != NULL )
1446 vlm_message_t *msg_schedule;
1447 vlm_message_t *msg_child;
1450 msg = vlm_MessageNew( "show", NULL );
1452 vlm_MessageAdd( msg, vlm_MessageNew( schedule->psz_name, 0 ) );
1454 vlm_MessageAdd( msg_schedule, vlm_MessageNew("type", "schedule") );
1456 vlm_MessageAdd( msg_schedule,
1457 vlm_MessageNew( "enabled", schedule->b_enabled ?
1460 #if !defined( UNDER_CE )
1461 if( schedule->i_date != 0 )
1464 time_t i_time = (time_t)( schedule->i_date / 1000000 );
1467 #ifdef HAVE_LOCALTIME_R
1468 localtime_r( &i_time, &date);
1470 struct tm *p_date = localtime( &i_time );
1474 asprintf( &psz_date, "%d/%d/%d-%d:%d:%d",
1475 date.tm_year + 1900, date.tm_mon + 1, date.tm_mday,
1476 date.tm_hour, date.tm_min, date.tm_sec );
1478 vlm_MessageAdd( msg_schedule,
1479 vlm_MessageNew( "date", psz_date ) );
1484 vlm_MessageAdd( msg_schedule, vlm_MessageNew("date", "now") );
1487 if( schedule->i_period != 0 )
1489 time_t i_time = (time_t) ( schedule->i_period / 1000000 );
1492 date.tm_sec = (int)( i_time % 60 );
1493 i_time = i_time / 60;
1494 date.tm_min = (int)( i_time % 60 );
1495 i_time = i_time / 60;
1496 date.tm_hour = (int)( i_time % 24 );
1497 i_time = i_time / 24;
1498 date.tm_mday = (int)( i_time % 30 );
1499 i_time = i_time / 30;
1500 /* okay, okay, months are not always 30 days long */
1501 date.tm_mon = (int)( i_time % 12 );
1502 i_time = i_time / 12;
1503 date.tm_year = (int)i_time;
1505 sprintf( buffer, "%d/%d/%d-%d:%d:%d", date.tm_year, date.tm_mon,
1506 date.tm_mday, date.tm_hour, date.tm_min, date.tm_sec);
1508 vlm_MessageAdd( msg_schedule, vlm_MessageNew("period", buffer) );
1512 vlm_MessageAdd( msg_schedule, vlm_MessageNew("period", "0") );
1514 #endif /* UNDER_CE */
1516 sprintf( buffer, "%d", schedule->i_repeat );
1517 vlm_MessageAdd( msg_schedule, vlm_MessageNew( "repeat", buffer ) );
1520 vlm_MessageAdd( msg_schedule, vlm_MessageNew("commands", 0) );
1522 for( i = 0; i < schedule->i_command; i++ )
1524 vlm_MessageAdd( msg_child,
1525 vlm_MessageNew( schedule->command[i], NULL ) );
1532 else if( psz_filter && strcmp( psz_filter, "media") == 0 )
1536 vlm_message_t *msg_child;
1538 msg = vlm_MessageNew( "show", NULL );
1539 msg_child = vlm_MessageAdd( msg, vlm_MessageNew( "media", NULL ) );
1541 for( i = 0; i < vlm->i_media; i++ )
1543 vlm_media_t *m = vlm->media[i];
1544 vlm_message_t *msg_media, *msg_instance;
1546 msg_media = vlm_MessageAdd( msg_child,
1547 vlm_MessageNew( m->psz_name, 0 ) );
1549 vlm_MessageAdd( msg_media,
1550 vlm_MessageNew( "type", m->i_type == VOD_TYPE ?
1551 "vod" : "broadcast" ) );
1553 vlm_MessageAdd( msg_media,
1554 vlm_MessageNew( "enabled", m->b_enabled ?
1557 msg_instance = vlm_MessageAdd( msg_media,
1558 vlm_MessageNew( "instances", 0 ) );
1560 for( j = 0; j < m->i_instance; j++ )
1562 vlm_media_instance_t *p_instance = m->instance[j];
1565 if( !p_instance->p_input ) val.i_int = END_S;
1566 else var_Get( p_instance->p_input, "state", &val );
1568 vlm_MessageAdd( msg_instance,
1569 vlm_MessageNew( p_instance->psz_name ?
1570 p_instance->psz_name : "default",
1571 val.i_int == PLAYING_S ? "playing" :
1572 val.i_int == PAUSE_S ? "paused" :
1580 else if( psz_filter && strcmp( psz_filter, "schedule") == 0 )
1584 vlm_message_t *msg_child;
1586 msg = vlm_MessageNew( "show", NULL );
1587 msg_child = vlm_MessageAdd( msg, vlm_MessageNew( "schedule", NULL ) );
1589 for( i = 0; i < vlm->i_schedule; i++ )
1591 vlm_schedule_t *s = vlm->schedule[i];
1592 vlm_message_t *msg_schedule;
1593 mtime_t i_time, i_next_date;
1595 msg_schedule = vlm_MessageAdd( msg_child,
1596 vlm_MessageNew( s->psz_name, 0 ) );
1597 vlm_MessageAdd( msg_schedule,
1598 vlm_MessageNew( "enabled", s->b_enabled ?
1601 if( !s->b_enabled ) return msg;
1604 vlm_MessageAdd( msg_schedule,
1605 vlm_MessageNew( "enabled", "yes" ) );
1607 /* calculate next date */
1609 i_next_date = s->i_date;
1611 if( s->i_period != 0 )
1614 while( s->i_date + j * s->i_period <= i_time &&
1620 i_next_date = s->i_date + j * s->i_period;
1623 if( i_next_date > i_time )
1625 time_t i_date = (time_t) (i_next_date / 1000000) ;
1627 #if !defined( UNDER_CE )
1630 ctime_r( &i_date, psz_date );
1632 char *psz_date = ctime( &i_date );
1635 vlm_MessageAdd( msg_schedule,
1636 vlm_MessageNew( "next launch", psz_date ) );
1644 else if( psz_filter == NULL && media == NULL && schedule == NULL )
1646 vlm_message_t *show1 = vlm_Show( vlm, NULL, NULL, "media" );
1647 vlm_message_t *show2 = vlm_Show( vlm, NULL, NULL, "schedule" );
1649 vlm_MessageAdd( show1, show2->child[0] );
1651 /* We must destroy the parent node "show" of show2
1652 * and not the children */
1653 free( show2->psz_name );
1661 return vlm_MessageNew( "show", NULL );
1665 static vlm_message_t *vlm_Help( vlm_t *vlm, char *psz_filter )
1667 vlm_message_t *message;
1669 if( psz_filter == NULL )
1673 "\n new (name) vod|broadcast|schedule [properties]"
1674 "\n setup (name) (properties)"
1675 "\n show [(name)|media|schedule]"
1676 "\n del (name)|all|media|schedule"
1677 "\n control (name) (command)"
1678 "\n save (config_file)"
1679 "\n load (config_file)"
1680 "\nMedia Proprieties Syntax:"
1681 "\n input (input_name)"
1682 "\n output (output_name)"
1683 "\n option (option_name)[=value]"
1684 "\n enabled|disabled"
1685 "\n loop|unloop (broadcast only)"
1686 "\nSchedule Proprieties Syntax:"
1687 "\n enabled|disabled"
1688 "\n append (command_until_rest_of_the_line)"
1689 "\n date (year)/(month)/(day)-(hour):(minutes):(seconds)|now"
1690 "\n period (years_aka_12_months)/(months_aka_30_days)/(days)-(hours):(minutes):(seconds)"
1691 "\n repeat (number_of_repetitions)"
1692 "\nControl Commands Syntax:"
1693 "\n play\n pause\n stop\n seek (percentage)\n" );
1695 message = vlm_MessageNew( "help", NULL );
1696 vlm_MessageAdd( message, vlm_MessageNew( "Help", help ) );
1701 return vlm_MessageNew( "help", NULL );
1704 /*****************************************************************************
1705 * Config handling functions
1706 *****************************************************************************/
1707 static int vlm_Load( vlm_t *vlm, char *file )
1711 while( *pf != '\0' )
1713 vlm_message_t *message = NULL;
1717 while( pf[i_temp] != '\n' && pf[i_temp] != '\0' && pf[i_temp] != '\r' )
1722 if( pf[i_temp] == '\r' || pf[i_temp] == '\n' )
1725 i_next = i_temp + 1;
1732 if( ExecuteCommand( vlm, pf, &message ) )
1745 static char *vlm_Save( vlm_t *vlm )
1752 for( i = 0; i < vlm->i_media; i++ )
1754 vlm_media_t *media = vlm->media[i];
1756 if( media->i_type == VOD_TYPE )
1758 i_length += strlen( "new vod " ) + strlen(media->psz_name);
1762 i_length += strlen( "new broadcast " ) + strlen(media->psz_name);
1765 if( media->b_enabled == VLC_TRUE )
1767 i_length += strlen( "enabled" );
1771 i_length += strlen( "disabled" );
1774 if( media->b_loop == VLC_TRUE )
1776 i_length += strlen( " loop\n" );
1780 i_length += strlen( "\n" );
1783 for( j = 0; j < media->i_input; j++ )
1785 i_length += strlen( "setup input \"\"\n" ) +
1786 strlen( media->psz_name ) + strlen( media->input[j] );
1789 if( media->psz_output != NULL )
1791 i_length += strlen(media->psz_name) + strlen(media->psz_output) +
1792 strlen( "setup output \n" );
1795 for( j=0 ; j < media->i_option ; j++ )
1797 i_length += strlen(media->psz_name) + strlen(media->option[j]) +
1798 strlen("setup option \n");
1802 for( i = 0; i < vlm->i_schedule; i++ )
1804 vlm_schedule_t *schedule = vlm->schedule[i];
1806 i_length += strlen( "new schedule " ) + strlen( schedule->psz_name );
1808 if( schedule->b_enabled == VLC_TRUE )
1810 i_length += strlen( "date //-:: enabled\n" ) + 14;
1814 i_length += strlen( "date //-:: disabled\n" ) + 14;
1818 if( schedule->i_period != 0 )
1820 i_length += strlen( "setup " ) + strlen( schedule->psz_name ) +
1821 strlen( "period //-::\n" ) + 14;
1824 if( schedule->i_repeat >= 0 )
1828 sprintf( buffer, "%d", schedule->i_repeat );
1829 i_length += strlen( "setup repeat \n" ) +
1830 strlen( schedule->psz_name ) + strlen( buffer );
1837 for( j = 0; j < schedule->i_command; j++ )
1839 i_length += strlen( "setup append \n" ) +
1840 strlen( schedule->psz_name ) + strlen( schedule->command[j] );
1845 /* Don't forget the '\0' */
1847 /* now we have the length of save */
1849 p = save = malloc( i_length );
1852 /* finally we can write in it */
1853 for( i = 0; i < vlm->i_media; i++ )
1855 vlm_media_t *media = vlm->media[i];
1857 if( media->i_type == VOD_TYPE )
1859 p += sprintf( p, "new %s vod ", media->psz_name);
1863 p += sprintf( p, "new %s broadcast ", media->psz_name);
1866 if( media->b_enabled == VLC_TRUE )
1868 p += sprintf( p, "enabled" );
1872 p += sprintf( p, "disabled" );
1875 if( media->b_loop == VLC_TRUE )
1877 p += sprintf( p, " loop\n" );
1881 p += sprintf( p, "\n" );
1884 for( j = 0; j < media->i_input; j++ )
1886 p += sprintf( p, "setup %s input \"%s\"\n", media->psz_name,
1890 if( media->psz_output != NULL )
1892 p += sprintf( p, "setup %s output %s\n", media->psz_name,
1893 media->psz_output );
1896 for( j = 0; j < media->i_option; j++ )
1898 p += sprintf( p, "setup %s option %s\n", media->psz_name,
1903 /* and now, the schedule scripts */
1904 #if !defined( UNDER_CE )
1905 for( i = 0; i < vlm->i_schedule; i++ )
1907 vlm_schedule_t *schedule = vlm->schedule[i];
1909 time_t i_time = (time_t) ( schedule->i_date / 1000000 );
1911 #ifdef HAVE_LOCALTIME_R
1912 localtime_r( &i_time, &date);
1914 struct tm *p_date = localtime( &i_time );
1918 p += sprintf( p, "new %s schedule ", schedule->psz_name);
1920 if( schedule->b_enabled == VLC_TRUE )
1922 p += sprintf( p, "date %d/%d/%d-%d:%d:%d enabled\n",
1923 date.tm_year + 1900, date.tm_mon + 1, date.tm_mday,
1924 date.tm_hour, date.tm_min, date.tm_sec );
1928 p += sprintf( p, "date %d/%d/%d-%d:%d:%d disabled\n",
1929 date.tm_year + 1900, date.tm_mon + 1, date.tm_mday,
1930 date.tm_hour, date.tm_min, date.tm_sec);
1933 if( schedule->i_period != 0 )
1935 p += sprintf( p, "setup %s ", schedule->psz_name );
1937 i_time = (time_t) ( schedule->i_period / 1000000 );
1939 date.tm_sec = (int)( i_time % 60 );
1940 i_time = i_time / 60;
1941 date.tm_min = (int)( i_time % 60 );
1942 i_time = i_time / 60;
1943 date.tm_hour = (int)( i_time % 24 );
1944 i_time = i_time / 24;
1945 date.tm_mday = (int)( i_time % 30 );
1946 i_time = i_time / 30;
1947 /* okay, okay, months are not always 30 days long */
1948 date.tm_mon = (int)( i_time % 12 );
1949 i_time = i_time / 12;
1950 date.tm_year = (int)i_time;
1952 p += sprintf( p, "period %d/%d/%d-%d:%d:%d\n",
1953 date.tm_year, date.tm_mon, date.tm_mday,
1954 date.tm_hour, date.tm_min, date.tm_sec);
1957 if( schedule->i_repeat >= 0 )
1959 p += sprintf( p, "setup %s repeat %d\n",
1960 schedule->psz_name, schedule->i_repeat );
1964 p += sprintf( p, "\n" );
1967 for( j = 0; j < schedule->i_command; j++ )
1969 p += sprintf( p, "setup %s append %s\n",
1970 schedule->psz_name, schedule->command[j] );
1974 #endif /* UNDER_CE */
1979 /*****************************************************************************
1981 *****************************************************************************/
1982 static int vlm_MediaVodControl( void *p_private, vod_media_t *p_vod_media,
1983 char *psz_id, int i_query, va_list args )
1985 vlm_t *vlm = (vlm_t *)p_private;
1986 int i, i_ret = VLC_EGENERIC;
1988 if( !p_private || !p_vod_media ) return VLC_EGENERIC;
1990 vlc_mutex_lock( &vlm->lock );
1993 for( i = 0; i < vlm->i_media; i++ )
1995 if( p_vod_media == vlm->media[i]->vod_media ) break;
1998 if( i == vlm->i_media )
2000 vlc_mutex_unlock( &vlm->lock );
2001 return VLC_EGENERIC;
2006 case VOD_MEDIA_PLAY:
2007 vlm->media[i]->psz_vod_output = (char *)va_arg( args, char * );
2008 i_ret = vlm_MediaControl( vlm, vlm->media[i], psz_id, "play", 0 );
2009 vlm->media[i]->psz_vod_output = 0;
2012 case VOD_MEDIA_PAUSE:
2013 i_ret = vlm_MediaControl( vlm, vlm->media[i], psz_id, "pause", 0 );
2016 case VOD_MEDIA_STOP:
2017 i_ret = vlm_MediaControl( vlm, vlm->media[i], psz_id, "stop", 0 );
2024 vlc_mutex_unlock( &vlm->lock );
2029 /*****************************************************************************
2031 *****************************************************************************/
2032 static int Manage( vlc_object_t* p_object )
2034 vlm_t *vlm = (vlm_t*)p_object;
2036 mtime_t i_lastcheck;
2039 i_lastcheck = mdate();
2043 while( !vlm->b_die )
2045 vlc_mutex_lock( &vlm->lock );
2047 /* destroy the inputs that wants to die, and launch the next input */
2048 for( i = 0; i < vlm->i_media; i++ )
2050 vlm_media_t *p_media = vlm->media[i];
2052 for( j = 0; j < p_media->i_instance; j++ )
2054 vlm_media_instance_t *p_instance = p_media->instance[j];
2056 if( !p_instance->p_input ||
2057 ( !p_instance->p_input->b_eof &&
2058 !p_instance->p_input->b_error ) ) continue;
2060 input_StopThread( p_instance->p_input );
2061 input_DestroyThread( p_instance->p_input );
2062 vlc_object_detach( p_instance->p_input );
2063 vlc_object_destroy( p_instance->p_input );
2065 p_instance->i_index++;
2066 if( p_instance->i_index == p_media->i_input &&
2067 p_media->b_loop ) p_instance->i_index = 0;
2069 if( p_instance->i_index < p_media->i_input )
2071 /* FIXME, find a way to select the right instance */
2073 sprintf( buffer, "%d", p_instance->i_index );
2074 vlm_MediaControl( vlm, p_media, p_instance->psz_name,
2079 if( vlm_MediaControl( vlm, p_media, p_instance->psz_name,
2080 "stop", 0 ) == VLC_SUCCESS ) i--;
2088 for( i = 0; i < vlm->i_schedule; i++ )
2090 mtime_t i_real_date = vlm->schedule[i]->i_date;
2092 if( vlm->schedule[i]->b_enabled == VLC_TRUE )
2094 if( vlm->schedule[i]->i_date == 0 ) // now !
2096 vlm->schedule[i]->i_date = (i_time / 1000000) * 1000000 ;
2097 i_real_date = i_time;
2099 else if( vlm->schedule[i]->i_period != 0 )
2102 while( vlm->schedule[i]->i_date + j *
2103 vlm->schedule[i]->i_period <= i_lastcheck &&
2104 ( vlm->schedule[i]->i_repeat > j ||
2105 vlm->schedule[i]->i_repeat == -1 ) )
2110 i_real_date = vlm->schedule[i]->i_date + j *
2111 vlm->schedule[i]->i_period;
2114 if( i_real_date <= i_time && i_real_date > i_lastcheck )
2116 for( j = 0; j < vlm->schedule[i]->i_command; j++ )
2118 vlm_message_t *message = NULL;
2120 ExecuteCommand( vlm, vlm->schedule[i]->command[j],
2123 /* for now, drop the message */
2130 i_lastcheck = i_time;
2132 vlc_mutex_unlock( &vlm->lock );
2140 #else /* ENABLE_VLM */
2142 /* We just define an empty wrapper */
2143 vlm_t *__vlm_New( vlc_object_t *a )
2145 msg_Err( a, "VideoLAN manager support is disabled" );
2148 void vlm_Delete( vlm_t *a ){}
2149 int vlm_ExecuteCommand( vlm_t *a, char *b, vlm_message_t **c ){ return -1; }
2150 void vlm_MessageDelete( vlm_message_t *a ){}
2152 #endif /* ENABLE_VLM */