]> git.sesse.net Git - vlc/blob - modules/control/telnet/vlm.c
4d7459c0bd1ebe6c6f125e8fd353e5eef4b3460b
[vlc] / modules / control / telnet / vlm.c
1 /*****************************************************************************
2  * vlm.c: VLM interface plugin
3  *****************************************************************************
4  * Copyright (C) 2000, 2001 VideoLAN
5  * $Id$
6  *
7  * Authors: Simon Latapie <garf@videolan.org>
8  *          Laurent Aimar <fenrir@videolan.org>
9  *
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.
14  *
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.
19  *
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  *****************************************************************************/
24
25 /*****************************************************************************
26  * Preamble
27  *****************************************************************************/
28 #include <stdlib.h>                                      /* malloc(), free() */
29
30 #include <vlc/vlc.h>
31 #include <vlc/intf.h>
32
33 #include <vlc/input.h>
34
35 #ifdef HAVE_TIME_H
36 #   include <time.h>                                              /* ctime() */
37 #endif
38
39 #include "vlm.h"
40
41 /*****************************************************************************
42  * Local prototypes.
43  *****************************************************************************/
44 static char *vlm_Save( vlm_t * );
45 static int   vlm_Load( vlm_t *, char *);
46 static vlm_media_t *vlm_MediaNew( vlm_t *, char *, int );
47 static int vlm_MediaDelete( vlm_t *, vlm_media_t *, char * );
48 static vlm_media_t *vlm_MediaSearch( vlm_t *, char * );
49 static int vlm_MediaSetup( vlm_media_t *, char *, char * );
50 static int vlm_MediaControl( vlm_t *, vlm_media_t *, char *, char * );
51 static vlm_message_t *vlm_Show( vlm_t *, vlm_media_t *, vlm_schedule_t *, char * );
52 static vlm_message_t *vlm_Help( vlm_t *, char * );
53
54 static vlm_message_t* vlm_MessageNew( char * , char * );
55 static vlm_message_t* vlm_MessageAdd( vlm_message_t*, vlm_message_t* );
56
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 *);
61
62 static int ExecuteCommand( vlm_t *, char * , vlm_message_t **);
63
64 static int Manage( vlc_object_t* );
65
66 #if 1
67 static char *FindEndCommand( char *psz )
68 {
69     char *s_sent = psz;
70
71     switch( *s_sent )
72     {
73         case '\"':
74         {
75             s_sent++;
76
77             while( ( *s_sent != '\"' ) && ( *s_sent != '\0' ) )
78             {
79                 if( *s_sent == '\'' )
80                 {
81                     s_sent = FindEndCommand( s_sent );
82
83                     if( s_sent == NULL )
84                     {
85                         return NULL;
86                     }
87                 }
88                 else
89                 {
90                     s_sent++;
91                 }
92             }
93
94             if( *s_sent == '\"' )
95             {
96                 s_sent++;
97                 return s_sent;
98             }
99             else  /* *s_sent == '\0' , which means the number of " is incorrect */
100             {
101                 return NULL;
102             }
103             break;
104         }
105         case '\'':
106         {
107             s_sent++;
108
109             while( ( *s_sent != '\'' ) && ( *s_sent != '\0' ) )
110             {
111                 if( *s_sent == '\"' )
112                 {
113                     s_sent = FindEndCommand( s_sent );
114
115                     if( s_sent == NULL )
116                     {
117                         return NULL;
118                     }
119                 }
120                 else
121                 {
122                     s_sent++;
123                 }
124             }
125
126             if( *s_sent == '\'' )
127             {
128                 s_sent++;
129                 return s_sent;
130             }
131             else  /* *s_sent == '\0' , which means the number of ' is incorrect */
132             {
133                 return NULL;
134             }
135             break;
136         }
137         default: /* now we can look for spaces */
138         {
139             while( ( *s_sent != ' ' ) && ( *s_sent != '\0' ) )
140             {
141                 if( ( *s_sent == '\'' ) || ( *s_sent == '\"' ) )
142                 {
143                     s_sent = FindEndCommand( s_sent );
144                 }
145                 else
146                 {
147                     s_sent++;
148                 }
149             }
150             return s_sent;
151         }
152     }
153 }
154 #else
155 static char *FindEndCommand( char *psz )
156 {
157     char *s_sent = psz;
158
159     while( *psz &&
160             *psz != ' ' && *psz != '\t' &&
161             *psz != '\n' && *psz != '\r' )
162     {
163         if( *psz == '\'' || *psz == '"' )
164         {
165             char d = *psz++;
166
167             while( *psz && *psz != d && *psz != *psz != '\n' && *psz != '\r' )
168             {
169                 if( ( d == '\'' && *psz == '"' ) ||
170                     ( d == '"' && *psz == '\'' ) )
171                 {
172                     psz = FindEndCommand( psz );
173                 }
174             }
175             if( psz != d )
176             {
177                 return NULL;
178             }
179         }
180         psz++;
181     }
182 }
183 #endif
184
185
186 int vlm_ExecuteCommand( vlm_t *vlm, char *command, vlm_message_t **message)
187 {
188     int result;
189
190     vlc_mutex_lock( &vlm->lock );
191     result = ExecuteCommand( vlm, command, message );
192     vlc_mutex_unlock( &vlm->lock );
193
194     return result;
195 }
196
197 /* Execute a command which ends by '\0' (string) */
198 int ExecuteCommand( vlm_t *vlm, char *command , vlm_message_t **p_message)
199 {
200     int i_return = 0;
201     int i_command = 0;
202     char **p_command = NULL;
203     char *cmd = command;
204     int i;
205     vlm_message_t * message = NULL;
206
207     /* First, parse the line and cut it */
208     while( *cmd != '\0' )
209     {
210
211         if( *cmd == ' ' )
212         {
213             cmd++;
214         }
215         else
216         {
217             char *p_temp;
218             int   i_temp;
219
220             p_temp = FindEndCommand( cmd );
221
222             if( p_temp == NULL )
223             {
224                 i_return = 1;
225                 goto end_seq;
226             }
227
228             i_temp = p_temp - cmd;
229
230             p_command = realloc( p_command , (i_command + 1) * sizeof( char* ) );
231             p_command[ i_command ] = malloc( (i_temp + 1) * sizeof( char ) ); // don't forget the '\0'
232             strncpy( p_command[ i_command ] , cmd , i_temp );
233             (p_command[ i_command ])[ i_temp ] = '\0';
234
235             i_command++;
236             cmd = p_temp;
237         }
238     }
239
240     /* And then Interpret it */
241
242     if( i_command == 0 )
243     {
244         message = vlm_MessageNew( "" , NULL );
245         i_return = 0;
246         goto end_seq;
247     }
248
249     if( strcmp(p_command[0] , "segfault") == 0 )
250     {
251         /* the only command we really need */
252         *((int *)NULL) = 42;
253     }
254     else if( strcmp(p_command[0] , "new") == 0 )
255     {
256         if( i_command >= 3 )
257         {
258             int i_type;
259             vlm_media_t *media;
260             vlm_schedule_t *schedule;
261
262             if( strcmp(p_command[2] , "schedule") == 0 )
263             {
264                 /* new vlm_schedule */
265                 if( vlm_ScheduleSearch( vlm , p_command[1] ) != NULL || strcmp(p_command[1] , "schedule") == 0 )
266                 {
267                     char *error_message = malloc( strlen(p_command[1]) + strlen(" is already used") + 1 );
268                     sprintf( error_message, "%s is already used" , p_command[1] );
269                     message = vlm_MessageNew( "new" , error_message );
270                     free( error_message );
271                     i_return = 1;
272                     goto end_seq;
273                 }
274
275                 schedule = vlm_ScheduleNew( vlm , p_command[1] );
276
277
278                 if( i_command > 3 ) // hey, there are properties
279                 {
280                     for( i = 3 ; i < i_command ; i++ )
281                     {
282                         if( strcmp( p_command[i] , "enabled" ) == 0 || strcmp( p_command[i] , "disabled" ) == 0 )
283                         {
284                             vlm_ScheduleSetup( schedule, p_command[i], NULL );
285                         }
286                         /* Beware: evrything behind append is considered as command line */
287                         else if( strcmp( p_command[i] , "append" ) == 0 )
288                         {
289                             i++;
290
291                             if( i < i_command )
292                             {
293                                 int j;
294                                 for( j = (i + 1); j < i_command; j++ )
295                                 {
296                                     p_command[i] = realloc( p_command[i], strlen(p_command[i]) + strlen(p_command[j]) + 1 + 1);
297                                     strcat( p_command[i], " " );
298                                     strcat( p_command[i], p_command[j] );
299                                 }
300
301                                 vlm_ScheduleSetup( schedule, p_command[i - 1], p_command[i] );
302                             }
303                             i = i_command;
304                         }
305                         else
306                         {
307                             if( (i+1) < i_command )
308                             {
309                                 vlm_ScheduleSetup( schedule, p_command[i], p_command[i+1] );
310                                 i++;
311                             }
312                             else
313                             {
314                                 vlm_ScheduleDelete( vlm, schedule, NULL );
315                                 message = vlm_MessageNew( p_command[i], "Wrong properties syntax" );
316                                 i_return = 1;
317                                 goto end_seq;
318                             }
319                         }
320                     }
321
322                     message = vlm_MessageNew( "new" , NULL );
323                     i_return = 0;
324                     goto end_seq;
325                 }
326
327                 message = vlm_MessageNew( "new" , NULL );
328                 i_return = 0;
329                 goto end_seq;
330             }
331
332             if( strcmp(p_command[2] , "vod") == 0 )
333             {
334                 i_type = VOD_TYPE;
335             }
336             else if( strcmp(p_command[2] , "broadcast") == 0 )
337             {
338                 i_type = BROADCAST_TYPE;
339             }
340             else
341             {
342                 char *error_message = malloc( strlen(p_command[1]) + strlen(": Choose between vod or broadcast") + 1 );
343                 sprintf( error_message, "%s: Choose between vod or broadcast" , p_command[1] );
344                 message = vlm_MessageNew( "new" , error_message );
345                 free( error_message );
346                 i_return = 1;
347                 goto end_seq;
348             }
349
350             /* new vlm_media */
351             if( vlm_MediaSearch( vlm , p_command[1] ) != NULL || strcmp(p_command[1] , "media") == 0 )
352             {
353                 char *error_message = malloc( strlen(p_command[1]) + strlen(" is already used") + 1 );
354                 sprintf( error_message, "%s is already used" , p_command[1] );
355                 message = vlm_MessageNew( "new" , error_message );
356                 free( error_message );
357                 i_return = 1;
358                 goto end_seq;
359             }
360
361             media = vlm_MediaNew( vlm , p_command[1] , i_type );
362
363             if( i_command > 3 ) // hey, there are properties
364             {
365                 for( i = 3 ; i < i_command ; i++ )
366                 {
367                     if( strcmp( p_command[i] , "enabled" ) == 0 || strcmp( p_command[i] , "disabled" ) == 0 )
368                     {
369                         vlm_MediaSetup( media, p_command[i], NULL );
370                     }
371                     else
372                     {
373                         if( (i+1) < i_command )
374                         {
375                             vlm_MediaSetup( media, p_command[i], p_command[i+1] );
376                             i++;
377                         }
378                         else
379                         {
380                             vlm_MediaDelete( vlm, media, NULL );
381                             message = vlm_MessageNew( p_command[i] , "Wrong properties syntax" );
382                             i_return = 1;
383                             goto end_seq;
384                         }
385                     }
386                 }
387
388                 message = vlm_MessageNew( "new" , NULL );
389                 i_return = 0;
390                 goto end_seq;
391             }
392
393             message = vlm_MessageNew( "new" , NULL );
394             i_return = 0;
395             goto end_seq;
396         }
397         else
398         {
399             message = vlm_MessageNew( "new" , "Wrong command syntax" );
400             i_return = 1;
401             goto end_seq;
402         }
403     }
404     else if( strcmp(p_command[0] , "del") == 0 )
405     {
406         if( i_command >= 2 )
407         {
408             vlm_media_t *media;
409             vlm_schedule_t *schedule;
410
411             media = vlm_MediaSearch( vlm , p_command[1] );
412             schedule = vlm_ScheduleSearch( vlm , p_command[1] );
413
414             if( schedule != NULL )
415             {
416                 vlm_ScheduleDelete( vlm, schedule, NULL );
417                 message = vlm_MessageNew( "del" , NULL );
418                 i_return = 0;
419                 goto end_seq;
420             }
421             else if( media != NULL )
422             {
423                 vlm_MediaDelete( vlm, media, NULL );
424                 message = vlm_MessageNew( "del" , NULL );
425                 i_return = 0;
426                 goto end_seq;
427             }
428             else if( strcmp(p_command[1] , "media") == 0 )
429             {
430                 for( i = 0; i < vlm->i_media; i++ )
431                 {
432                     vlm_MediaDelete( vlm, vlm->media[i], NULL );
433                 }
434             }
435             else if( strcmp(p_command[1] , "schedule") == 0 )
436             {
437                 for( i = 0; i < vlm->i_schedule; i++ )
438                 {
439                     vlm_ScheduleDelete( vlm, vlm->schedule[i], NULL );
440                 }
441             }
442             else if( strcmp(p_command[1] , "all") == 0 )
443             {
444                 for( i = 0; i < vlm->i_media; i++ )
445                 {
446                     vlm_MediaDelete( vlm, vlm->media[i], NULL );
447                 }
448
449                 for( i = 0; i < vlm->i_schedule; i++ )
450                 {
451                     vlm_ScheduleDelete( vlm, vlm->schedule[i], NULL );
452                 }
453             }
454             else
455             {
456                 char *error_message = malloc( strlen(p_command[1]) + strlen(": media unknown") + 1 );
457                 sprintf( error_message, "%s: media unknown" , p_command[1] );
458                 message = vlm_MessageNew( "del" , error_message );
459                 free( error_message );
460                 i_return = 1;
461                 goto end_seq;
462             }
463         }
464         else
465         {
466             message = vlm_MessageNew( "setup" , "Wrong command syntax" );
467             i_return = 1;
468             goto end_seq;
469         }
470     }
471     else if( strcmp(p_command[0] , "show") == 0 )
472     {
473         if( i_command == 1 )
474         {
475             message = vlm_Show( vlm, NULL , NULL, NULL );
476             i_return = 0;
477             goto end_seq;
478         }
479         else if( i_command == 2 )
480         {
481             vlm_media_t *media;
482             vlm_schedule_t *schedule;
483
484             media = vlm_MediaSearch( vlm , p_command[1] );
485             schedule = vlm_ScheduleSearch( vlm , p_command[1] );
486
487             if( schedule != NULL )
488             {
489                 message = vlm_Show( vlm, NULL, schedule, NULL );
490             }
491             else if( media != NULL )
492             {
493                 message = vlm_Show( vlm, media, NULL, NULL );
494             }
495             else
496             {
497                 message = vlm_Show( vlm, NULL, NULL, p_command[1] );
498             }
499
500             i_return = 0;
501             goto end_seq;
502         }
503         else
504         {
505             message = vlm_MessageNew( "show" , "Wrong command syntax" );
506             i_return = 1;
507             goto end_seq;
508         }
509     }
510     else if( strcmp(p_command[0] , "help") == 0 )
511     {
512         if( i_command == 1 )
513         {
514             message = vlm_Help( vlm, NULL );
515             i_return = 0;
516             goto end_seq;
517         }
518         else
519         {
520             message = vlm_MessageNew( "help" , "Wrong command syntax" );
521             i_return = 1;
522             goto end_seq;
523         }
524     }
525     else if( strcmp(p_command[0] , "setup") == 0 )
526     {
527         if( i_command >= 2 )
528         {
529             vlm_media_t *media;
530             vlm_schedule_t *schedule;
531
532             media = vlm_MediaSearch( vlm , p_command[1] );
533             schedule = vlm_ScheduleSearch( vlm , p_command[1] );
534
535             if( schedule != NULL )
536             {
537                 for( i = 2 ; i < i_command ; i++ )
538                 {
539                     if( strcmp( p_command[i] , "enabled" ) == 0 || strcmp( p_command[i] , "disabled" ) == 0 )
540                     {
541                         vlm_ScheduleSetup( schedule, p_command[i], NULL );
542                     }
543                     /* Beware: evrything behind append is considered as command line */
544                     else if( strcmp( p_command[i] , "append" ) == 0 )
545                     {
546                         i++;
547
548                         if( i < i_command )
549                         {
550                             int j;
551                             for( j = (i + 1); j < i_command; j++ )
552                             {
553                                 p_command[i] = realloc( p_command[i], strlen(p_command[i]) + strlen(p_command[j]) + 1 + 1);
554                                 strcat( p_command[i], " " );
555                                 strcat( p_command[i], p_command[j] );
556                             }
557
558                             vlm_ScheduleSetup( schedule, p_command[i - 1], p_command[i] );
559                         }
560                         i = i_command;
561                     }
562                     else
563                     {
564                         if( (i+1) < i_command )
565                         {
566                             vlm_ScheduleSetup( schedule, p_command[i], p_command[i+1] );
567                             i++;
568                         }
569                         else
570                         {
571                             vlm_ScheduleDelete( vlm, schedule, NULL );
572                             message = vlm_MessageNew( "setup" , "Wrong properties syntax" );
573                             i_return = 1;
574                             goto end_seq;
575                         }
576                     }
577                 }
578
579                 message = vlm_MessageNew( "setup" , NULL );
580                 i_return = 0;
581                 goto end_seq;
582             }
583             else if( media != NULL )
584             {
585                 for( i = 2 ; i < i_command ; i++ )
586                 {
587                     if( strcmp( p_command[i] , "enabled" ) == 0 || strcmp( p_command[i] , "disabled" ) == 0 )
588                     {   /* only one argument */
589                         vlm_MediaSetup( media, p_command[i], NULL );
590                     }
591                     else if( strcmp( p_command[i] , "loop" ) == 0 || strcmp( p_command[i] , "unloop" ) == 0 )
592                     {
593                         if( media->i_type != BROADCAST_TYPE )
594                         {
595                             message = vlm_MessageNew( "setup" , "lool only available for broadcast" );
596                             i_return = 1;
597                             goto end_seq;
598                         }
599                         else
600                         {
601                             vlm_MediaSetup( media, p_command[i], NULL );
602                         }
603                     }
604                     else
605                     {
606                         if( (i+1) < i_command )
607                         {
608                             vlm_MediaSetup( media, p_command[i], p_command[i+1] );
609                             i++;
610                         }
611                         else
612                         {
613                             vlm_MediaDelete( vlm, media, NULL );
614                             message = vlm_MessageNew( "setup" , "Wrong properties syntax" );
615                             i_return = 1;
616                             goto end_seq;
617                         }
618                     }
619                 }
620
621                 message = vlm_MessageNew( "setup" , NULL );
622                 i_return = 0;
623                 goto end_seq;
624             }
625             else
626             {
627                 char *error_message = malloc( strlen(p_command[1]) + strlen(" unknown") + 1 );
628                 sprintf( error_message, "%s unknown" , p_command[1] );
629                 message = vlm_MessageNew( "setup" , error_message );
630                 free( error_message );
631                 i_return = 1;
632                 goto end_seq;
633             }
634
635         }
636         else
637         {
638             message = vlm_MessageNew( "setup" , "Wrong command syntax" );
639             i_return = 1;
640             goto end_seq;
641         }
642     }
643     else if( strcmp(p_command[0] , "control") == 0 )
644     {
645
646         if( i_command >= 3 )
647         {
648             vlm_media_t *media;
649
650             media = vlm_MediaSearch( vlm , p_command[1] );
651
652             if( media == NULL )
653             {
654                 char *error_message = malloc( strlen(p_command[1]) + strlen(": media unknown") + 1 );
655                 sprintf( error_message, "%s: media unknown" , p_command[1] );
656                 message = vlm_MessageNew( "control" , error_message );
657                 free( error_message );
658                 i_return = 1;
659                 goto end_seq;
660             }
661             else
662             {
663                 char *psz_args;
664
665                 if( i_command >= 4 )
666                 {
667                     psz_args = p_command[3];
668                 }
669                 else
670                 {
671                     psz_args = NULL;
672                 }
673
674                 /* for now */
675                 vlm_MediaControl( vlm, media, p_command[2], psz_args );
676                 message = vlm_MessageNew( "control" , NULL );
677                 i_return = 0;
678                 goto end_seq;
679             }
680         }
681         else
682         {
683             message = vlm_MessageNew( "control" , "Wrong command syntax" );
684             i_return = 1;
685             goto end_seq;
686         }
687     }
688     else if( strcmp(p_command[0] , "save") == 0 )
689     {
690         if( i_command == 2 )
691         {
692             FILE *file;
693
694
695             file = fopen( p_command[1], "w" );
696
697             if( file == NULL )
698             {
699                 message = vlm_MessageNew( "save" , "Unable to save file" );
700                 i_return = 1;
701                 goto end_seq;
702             }
703             else
704             {
705                 char *save;
706
707                 save = vlm_Save( vlm );
708
709                 fwrite( save, strlen( save ) , 1 , file );
710                 fclose( file );
711                 free( save );
712                 message = vlm_MessageNew( "save" , NULL );
713                 i_return = 0;
714                 goto end_seq;
715             }
716         }
717         else
718         {
719             message = vlm_MessageNew( "save" , "Wrong command" );
720             i_return = 1;
721             goto end_seq;
722         }
723     }
724     else if( strcmp(p_command[0] , "load") == 0 )
725     {
726
727         if( i_command == 2 )
728         {
729             FILE *file;
730
731             file = fopen( p_command[1], "r" );
732
733             if( file == NULL )
734             {
735                 message = vlm_MessageNew( "load" , "Unable to load file" );
736                 i_return = 1;
737                 goto end_seq;
738             }
739             else
740             {
741                 int64_t size;
742                 char *buffer;
743
744                 if( fseek( file, 0, SEEK_END) == 0 )
745                 {
746                     size = ftell( file );
747                     fseek( file, 0, SEEK_SET);
748                     buffer = malloc( size + 1 );
749                     fread( buffer, 1, size, file);
750                     buffer[ size ] = '\0';
751                     if( vlm_Load( vlm, buffer ) )
752                     {
753                         free( buffer );
754                         message = vlm_MessageNew( "load" , "error while loading file" );
755                         i_return = 1;
756                         goto end_seq;
757                     }
758                     free( buffer );
759                 }
760                 else
761                 {
762                     message = vlm_MessageNew( "load" , "read file error" );
763                     i_return = 1;
764                     goto end_seq;
765                 }
766                 fclose( file );
767                 message = vlm_MessageNew( "load" , NULL );
768                 i_return = 0;
769                 goto end_seq;
770             }
771         }
772         else
773         {
774             message = vlm_MessageNew( "load" , "Wrong command" );
775             i_return = 1;
776             goto end_seq;
777         }
778     }
779     else
780     {
781         message = vlm_MessageNew( p_command[0] , "Unknown comand" );
782         i_return = 1;
783         goto end_seq;
784     }
785
786 end_seq:
787
788     for( i = 0 ; i < i_command ; i++ )
789     {
790         free( p_command[i] );
791     }
792
793     *p_message = message;
794
795     return i_return;
796 }
797
798
799 static vlm_media_t *vlm_MediaSearch( vlm_t *vlm, char *psz_name )
800 {
801     int i;
802
803     for( i = 0; i < vlm->i_media; i++ )
804     {
805         if( strcmp( psz_name, vlm->media[i]->psz_name ) == 0 )
806         {
807             return vlm->media[i];
808         }
809     }
810
811     return NULL;
812 }
813
814
815 static vlm_media_t *vlm_MediaNew( vlm_t *vlm , char *psz_name, int i_type )
816 {
817     vlm_media_t *media= malloc( sizeof( vlm_media_t ));
818
819     media->psz_name = strdup( psz_name );
820     media->b_enabled = VLC_FALSE;
821     media->b_loop = VLC_FALSE;
822     media->i_input = 0;
823     media->input = NULL;
824     media->i_index = 0;
825     media->psz_output = NULL;
826     media->i_option = 0;
827     media->option = NULL;
828     media->i_input_option = 0;
829     media->input_option = NULL;
830     media->i_type = i_type;
831     media->p_input = NULL;
832
833     TAB_APPEND( vlm->i_media , vlm->media , media );
834
835     return media;
836 }
837
838
839 /* for now, simple delete. After, del with options (last arg) */
840 static int vlm_MediaDelete( vlm_t *vlm, vlm_media_t *media, char *psz_name )
841 {
842     int i;
843
844     if( media == NULL )
845     {
846         return 1;
847     }
848
849     if( media->p_input )
850     {
851         input_StopThread( media->p_input );
852
853         input_DestroyThread( media->p_input );
854         vlc_object_detach( media->p_input );
855         vlc_object_destroy( media->p_input );
856     }
857
858     TAB_REMOVE( vlm->i_media, vlm->media , media );
859
860     if( vlm->i_media == 0 && vlm->media ) free( vlm->media );
861
862     free( media->psz_name );
863
864     for( i = 0; i < media->i_input; i++ )
865     {
866         free( media->input[i] );
867     }
868     if( media->input ) free( media->input );
869
870     if( media->psz_output ) free( media->psz_output );
871
872     for( i = 0; i < media->i_option; i++ )
873     {
874         free( media->option[i] );
875     }
876     if(media->option) free( media->option );
877
878     for( i = 0; i < media->i_input_option; i++ )
879     {
880         free( media->input_option[i] );
881     }
882     if( media->input_option ) free( media->input_option );
883
884     free( media );
885
886     return 0;
887 }
888
889
890 static int vlm_MediaSetup( vlm_media_t *media, char *psz_cmd, char *psz_value )
891 {
892     if( strcmp( psz_cmd, "loop" ) == 0 )
893     {
894         media->b_loop = VLC_TRUE;
895     }
896     else if( strcmp( psz_cmd, "unloop" ) == 0 )
897     {
898         media->b_loop = VLC_FALSE;
899     }
900     else if( strcmp( psz_cmd, "enabled" ) == 0 )
901     {
902         media->b_enabled = VLC_TRUE;
903     }
904     else if( strcmp( psz_cmd, "disabled" ) == 0 )
905     {
906         media->b_enabled = VLC_FALSE;
907     }
908     else if( strcmp( psz_cmd, "input" ) == 0 )
909     {
910         char *input;
911
912         if( psz_value != NULL && strlen(psz_value) > 1 && ( psz_value[0] == '\'' || psz_value[0] == '\"' ) 
913             && ( psz_value[ strlen(psz_value) - 1 ] == '\'' || psz_value[ strlen(psz_value) - 1 ] == '\"' )  )
914         {
915             input = malloc( strlen(psz_value) - 1 );
916
917             memcpy( input , psz_value + 1 , strlen(psz_value) - 2 );
918             input[ strlen(psz_value) - 2 ] = '\0';
919         }
920         else
921         {
922             input = strdup( psz_value );
923         }
924
925         TAB_APPEND( media->i_input, media->input, input );
926     }
927     else if( strcmp( psz_cmd, "output" ) == 0 )
928     {
929         if( media->psz_output != NULL )
930         {
931             free( media->psz_output );
932         }
933         media->psz_output = strdup( psz_value );
934     }
935     else if( strcmp( psz_cmd, "option" ) == 0 )
936     {
937         char *option;
938         option = strdup( psz_value );
939
940         TAB_APPEND( media->i_option, media->option, option );
941     }
942     else
943     {
944         return 1;
945     }
946     return 0;
947 }
948
949 static int vlm_MediaControl( vlm_t *vlm, vlm_media_t *media, char *psz_name, char *psz_args )
950 {
951     if( strcmp( psz_name, "play" ) == 0 )
952     {
953         int i;
954
955         if( media->b_enabled == VLC_TRUE )
956         {
957             if( psz_args != NULL && sscanf( psz_args, "%d", &i ) == 1 && i < media->i_input )
958             {
959                 media->i_index = i;
960             }
961             else
962             {
963                 media->i_index = 0;
964             }
965
966             if( media->psz_output != NULL )
967             {
968                 media->input_option = malloc( sizeof( char* ) );
969                 media->input_option[0] = malloc( strlen(media->psz_output) + 1 + 6 );
970                 sprintf( media->input_option[0], ":sout=%s" , media->psz_output );
971                 media->i_input_option = 1;
972             }
973             else
974             {
975                 media->input_option = NULL;
976                 media->i_input_option = 0;
977             }
978
979             for( i=0 ; i < media->i_option ; i++ )
980             {
981                 media->i_input_option++;
982                 media->input_option = realloc( media->input_option, (media->i_input_option) * sizeof( char* ) );
983                 media->input_option[ media->i_input_option - 1 ] = malloc( strlen(media->option[i]) + 1 + 1 );
984                 sprintf( media->input_option[ media->i_input_option - 1 ], ":%s" , media->option[i] );
985             }
986
987             media->p_input = input_CreateThread( vlm, media->input[media->i_index], media->input_option, media->i_input_option );
988
989             return 0;
990         }
991         else
992         {
993             return 1;
994         }
995     }
996     else if( strcmp( psz_name, "seek" ) == 0 )
997     {
998         vlc_value_t val;
999         float f_percentage;
1000
1001         if( psz_args && sscanf( psz_args, "%f", &f_percentage ) == 1 )
1002         {
1003             val.f_float = f_percentage / 100.0 ;
1004             var_Set( media->p_input, "position", val );
1005             return 0;
1006         }
1007     }
1008     else if( strcmp( psz_name, "stop" ) == 0 )
1009     {
1010         int i;
1011
1012         if( media->p_input )
1013         {
1014             input_StopThread( media->p_input );
1015             input_DestroyThread( media->p_input );
1016             vlc_object_detach( media->p_input );
1017             vlc_object_destroy( media->p_input );
1018             media->p_input = NULL;
1019
1020             for( i=0 ; i < media->i_input_option ; i++ )
1021             {
1022                 free( media->input_option[i] );
1023             }
1024             if( media->input_option) free( media->input_option );
1025
1026             media->input_option = NULL;
1027             media->i_input_option = 0;
1028         }
1029
1030         return 0;
1031     }
1032     else if( strcmp( psz_name, "pause" ) == 0 )
1033     {
1034         vlc_value_t val;
1035
1036         val.i_int = 0;
1037
1038         if( media->p_input != NULL )
1039         {
1040             var_Get( media->p_input, "state", &val );
1041         }
1042
1043         if( val.i_int == PAUSE_S )
1044         {
1045             if( media->p_input )
1046             {
1047                 val.i_int = PLAYING_S;
1048                 var_Set( media->p_input, "state", val );
1049             }
1050         }
1051         else
1052         {
1053             if( media->p_input )
1054             {
1055                 val.i_int = PAUSE_S;
1056                 var_Set( media->p_input, "state", val );
1057             }
1058         }
1059         return 0;
1060     }
1061
1062     return 1;
1063 }
1064
1065 static vlm_message_t *vlm_Show( vlm_t *vlm, vlm_media_t *media, vlm_schedule_t *schedule, char *psz_filter )
1066 {
1067
1068     if( media != NULL )
1069     {
1070         int i;
1071         vlm_message_t *message;
1072         vlm_message_t *message_media;
1073         vlm_message_t *message_child;
1074
1075         message = vlm_MessageNew( "show" , NULL );
1076         message_media = vlm_MessageAdd( message , vlm_MessageNew( media->psz_name , NULL ) );
1077
1078         if( media->i_type == VOD_TYPE )
1079         {
1080             vlm_MessageAdd( message_media , vlm_MessageNew( "type" , "vod" ) );
1081         }
1082         else
1083         {
1084             vlm_MessageAdd( message_media , vlm_MessageNew( "type" , "broadcast" ) );
1085         }
1086
1087         if( media->b_enabled == VLC_TRUE )
1088         {
1089             vlm_MessageAdd( message_media , vlm_MessageNew( "enabled" , "yes" ) );
1090         }
1091         else
1092         {
1093             vlm_MessageAdd( message_media , vlm_MessageNew( "enabled" , "no" ) );
1094         }
1095
1096         if( media->b_loop == VLC_TRUE )
1097         {
1098             vlm_MessageAdd( message_media , vlm_MessageNew( "loop" , "yes" ) );
1099         }
1100
1101         message_child = vlm_MessageAdd( message_media , vlm_MessageNew( "inputs" , NULL ) );
1102
1103         for( i=0 ; i < (media->i_input) ; i++ )
1104         {
1105             vlm_MessageAdd( message_child , vlm_MessageNew( media->input[i] , NULL ) );
1106         }
1107
1108         if( media->psz_output != NULL )
1109         {
1110             vlm_MessageAdd( message_media , vlm_MessageNew( "output" , media->psz_output ) );
1111         }
1112
1113         message_child = vlm_MessageAdd( message_media , vlm_MessageNew( "options" , NULL ) );
1114
1115         for( i=0 ; i < (media->i_option) ; i++ )
1116         {
1117             vlm_MessageAdd( message_child , vlm_MessageNew( media->option[i] , NULL ) );
1118         }
1119
1120         if( media->p_input != NULL )
1121         {
1122             vlc_value_t val;
1123
1124             var_Get( media->p_input, "state", &val );
1125
1126             if( val.i_int == PLAYING_S )
1127             {
1128                 vlm_MessageAdd( message_media , vlm_MessageNew( "state" , "playing" ) );
1129             }
1130             else if( val.i_int == PAUSE_S )
1131             {
1132                 vlm_MessageAdd( message_media , vlm_MessageNew( "state" , "paused" ) );
1133             }
1134             else
1135             {
1136                 vlm_MessageAdd( message_media , vlm_MessageNew( "state" , "stop" ) );
1137             }
1138         }
1139         else
1140         {
1141             vlm_MessageAdd( message_media , vlm_MessageNew( "state" , "stop" ) );
1142         }
1143
1144         return message;
1145
1146     }
1147     else if( schedule != NULL )
1148     {
1149         int i;
1150         vlm_message_t *message;
1151         vlm_message_t *message_schedule;
1152         vlm_message_t *message_child;
1153
1154         message = vlm_MessageNew( "show" , NULL );
1155         message_schedule = vlm_MessageAdd( message , vlm_MessageNew( schedule->psz_name , NULL ) );
1156
1157         vlm_MessageAdd( message_schedule , vlm_MessageNew( "type" , "schedule" ) );
1158
1159         if( schedule->b_enabled == VLC_TRUE )
1160         {
1161             vlm_MessageAdd( message_schedule , vlm_MessageNew( "enabled" , "yes" ) );
1162         }
1163         else
1164         {
1165             vlm_MessageAdd( message_schedule , vlm_MessageNew( "enabled" , "no" ) );
1166         }
1167
1168         if( schedule->i_date != 0 )
1169         {
1170             time_t i_time = schedule->i_date / (int64_t)1000000;
1171
1172 #ifdef HAVE_CTIME_R
1173             char psz_date[500];
1174             ctime_r( &i_time, psz_date );
1175 #else
1176             char *psz_date = ctime( &i_time );
1177 #endif
1178             vlm_MessageAdd( message_schedule , vlm_MessageNew( "date" , psz_date ) );
1179         }
1180         else
1181         {
1182             vlm_MessageAdd( message_schedule , vlm_MessageNew( "date" , "now" ) );
1183         }
1184
1185         if( schedule->i_period != 0 )
1186         {
1187             char buffer[100];
1188             time_t i_time = (time_t) ( schedule->i_period / 1000000 );
1189             struct tm date;
1190
1191             date.tm_sec = (int)( i_time % 60 );
1192             i_time = i_time / 60;
1193             date.tm_min = (int)( i_time % 60 );
1194             i_time = i_time / 60;
1195             date.tm_hour = (int)( i_time % 24 );
1196             i_time = i_time / 24;
1197             date.tm_mday = (int)( i_time % 30 );
1198             i_time = i_time / 30;
1199             /* okay, okay, months are not always 30 days long */
1200             date.tm_mon = (int)( i_time % 12 );
1201             i_time = i_time / 12;
1202             date.tm_year = (int)i_time;
1203
1204             sprintf( buffer, "%d years %d months %d days %d hours %d minutes %d seconds", date.tm_year ,
1205                                                                                           date.tm_mon,
1206                                                                                           date.tm_mday,
1207                                                                                           date.tm_hour,
1208                                                                                           date.tm_min,
1209                                                                                           date.tm_sec);
1210
1211             vlm_MessageAdd( message_schedule , vlm_MessageNew( "period" , buffer ) );
1212
1213             if( schedule->i_repeat >= 0 )
1214             {
1215                 sprintf( buffer, "%d" , schedule->i_repeat );
1216                 vlm_MessageAdd( message_schedule , vlm_MessageNew( "repeat" , buffer ) );
1217             }
1218         }
1219
1220         message_child = vlm_MessageAdd( message_schedule , vlm_MessageNew( "commands" , NULL ) );
1221
1222         for( i=0 ; i < (schedule->i_command) ; i++ )
1223         {
1224            vlm_MessageAdd( message_child , vlm_MessageNew( schedule->command[i] , NULL ) );
1225         }
1226
1227         return message;
1228
1229     }
1230     else if( psz_filter && strcmp( psz_filter , "media") == 0 )
1231     {
1232         int i;
1233         vlm_message_t *message;
1234         vlm_message_t *message_child;
1235
1236         message = vlm_MessageNew( "show" , NULL );
1237         message_child = vlm_MessageAdd( message , vlm_MessageNew( "media" , NULL ) );
1238
1239         for( i = 0; i < vlm->i_media; i++ )
1240         {
1241             vlm_media_t *m = vlm->media[i];
1242             vlm_message_t *message_media = vlm_MessageAdd( message_child , vlm_MessageNew( m->psz_name , NULL ) );
1243
1244             if( m->i_type == VOD_TYPE )
1245             {
1246                 vlm_MessageAdd( message_media , vlm_MessageNew( "type" , "vod" ) );
1247             }
1248             else
1249             {
1250                 vlm_MessageAdd( message_media , vlm_MessageNew( "type" , "broadcast" ) );
1251             }
1252
1253             if( m->b_enabled == VLC_TRUE )
1254             {
1255                 vlm_MessageAdd( message_media , vlm_MessageNew( "enabled" , "yes" ) );
1256             }
1257             else
1258             {
1259                 vlm_MessageAdd( message_media , vlm_MessageNew( "enabled" , "no" ) );
1260             }
1261
1262             if( m->p_input != NULL )
1263             {
1264                 vlc_value_t val;
1265
1266                 var_Get( m->p_input, "state", &val );
1267
1268                 if( val.i_int == PLAYING_S )
1269                 {
1270                     vlm_MessageAdd( message_media , vlm_MessageNew( "state" , "playing" ) );
1271                 }
1272                 else if( val.i_int == PAUSE_S )
1273                 {
1274                     vlm_MessageAdd( message_media , vlm_MessageNew( "state" , "paused" ) );
1275                 }
1276                 else
1277                 {
1278                     vlm_MessageAdd( message_media , vlm_MessageNew( "state" , "stop" ) );
1279                 }
1280             }
1281             else
1282             {
1283                 vlm_MessageAdd( message_media , vlm_MessageNew( "state" , "stop" ) );
1284             }
1285         }
1286
1287         return message;
1288     }
1289     else if( psz_filter && strcmp( psz_filter , "schedule") == 0 )
1290     {
1291         int i;
1292         vlm_message_t *message;
1293         vlm_message_t *message_child;
1294
1295         message = vlm_MessageNew( "show" , NULL );
1296         message_child = vlm_MessageAdd( message , vlm_MessageNew( "schedule" , NULL ) );
1297
1298         for( i = 0; i < vlm->i_schedule; i++ )
1299         {
1300             vlm_schedule_t *s = vlm->schedule[i];
1301             vlm_message_t *message_schedule = vlm_MessageAdd( message_child , vlm_MessageNew( s->psz_name , NULL ) ); 
1302
1303             if( s->b_enabled == VLC_TRUE )
1304             {
1305                 mtime_t i_time;
1306                 mtime_t i_next_date;
1307
1308                 vlm_MessageAdd( message_schedule , vlm_MessageNew( "enabled" , "yes" ) );
1309
1310                 /* calculate next date */
1311                 i_time = mdate();
1312
1313                 i_next_date = s->i_date;
1314
1315                 if( s->i_period != 0 )
1316                 {
1317                     int j = 0;
1318                     while( s->i_date + j * s->i_period <= i_time && s->i_repeat > j )
1319                     {
1320                         j++;
1321                     }
1322
1323                     i_next_date = s->i_date + j * s->i_period;
1324                 }
1325
1326                 if( i_next_date > i_time )
1327                 {
1328                     time_t i_date = (time_t) (i_next_date / 1000000) ;
1329
1330 #ifdef HAVE_CTIME_R
1331                     char psz_date[500];
1332                     ctime_r( &i_date, psz_date );
1333 #else
1334                     char *psz_date = ctime( &i_date );
1335 #endif
1336
1337                     vlm_MessageAdd( message_schedule , vlm_MessageNew( "next launch" , psz_date ) );
1338                 }
1339             }
1340             else
1341             {
1342                 vlm_MessageAdd( message_schedule , vlm_MessageNew( "enabled" , "no" ) );
1343             }
1344         }
1345
1346         return message;
1347     }
1348     else if( psz_filter == NULL && media == NULL && schedule == NULL )
1349     {
1350         vlm_message_t *show1 = vlm_Show( vlm, NULL, NULL, "media" );
1351         vlm_message_t *show2 = vlm_Show( vlm, NULL, NULL, "schedule" );
1352
1353         vlm_MessageAdd( show1 , show2->child[0] );
1354
1355         /* we must destroy the parent node "show" of show2, and not the children */
1356         free( show2->psz_name );
1357         free( show2 );
1358
1359         return show1;
1360     }
1361     else
1362     {
1363         return vlm_MessageNew( "show" , NULL );
1364     }
1365 }
1366
1367 static vlm_message_t *vlm_Help( vlm_t *vlm, char *psz_filter )
1368 {
1369     vlm_message_t *message;
1370
1371     if( psz_filter == NULL )
1372     {
1373         char *help = malloc( strlen( "Commands Syntax:" ) +
1374                      strlen( "\n new (name) vod|broadcast|schedule [properties]" ) +
1375                      strlen( "\n setup (name) (properties)" ) +
1376                      strlen( "\n show [(name)|media|schedule]" ) +
1377                      strlen( "\n del (name)|all|media|schedule" ) +
1378                      strlen( "\n control (name) (command)" ) +
1379                      strlen( "\n save (config_file)" ) +
1380                      strlen( "\n load (config_file)" ) +
1381                      strlen( "\nMedia Proprieties Syntax:" ) +
1382                      strlen( "\n input (input_name)" ) +
1383                      strlen( "\n output (output_name)" ) +
1384                      strlen( "\n option (option_name)[=value]" ) +
1385                      strlen( "\n enabled|disabled" ) +
1386                      strlen( "\n loop|unloop (broadcast only)" ) +
1387                      strlen( "\nSchedule Proprieties Syntax:" ) +
1388                      strlen( "\n enabled|disabled" ) +
1389                      strlen( "\n append (command_until_rest_of_the_line)" ) +
1390                      strlen( "\n date (year)/(month)/(day)-(hour):(minutes):(seconds)|now" ) +
1391                      strlen( "\n period (years_aka_12_months)/(months_aka_30_days)/(days)-(hours):(minutes):(seconds)" ) +
1392                      strlen( "\n repeat (number_of_repetitions)" ) +
1393                      strlen( "\nControl Commands Syntax:" ) +
1394                      strlen( "\n play\n pause\n stop\n seek (percentage)\n" ) + 1 );
1395
1396         sprintf( help,
1397                  "Commands Syntax:"
1398                  "\n new (name) vod|broadcast|schedule [properties]"
1399                  "\n setup (name) (properties)"
1400                  "\n show [(name)|media|schedule]"
1401                  "\n del (name)|all|media|schedule"
1402                  "\n control (name) (command)"
1403                  "\n save (config_file)"
1404                  "\n load (config_file)"
1405                  "\nMedia Proprieties Syntax:"
1406                  "\n input (input_name)"
1407                  "\n output (output_name)"
1408                  "\n option (option_name)[=value]"
1409                  "\n enabled|disabled"
1410                  "\n loop|unloop (broadcast only)"
1411                  "\nSchedule Proprieties Syntax:"
1412                  "\n enabled|disabled"
1413                  "\n append (command_until_rest_of_the_line)"
1414                  "\n date (year)/(month)/(day)-(hour):(minutes):(seconds)|now"
1415                  "\n period (years_aka_12_months)/(months_aka_30_days)/(days)-(hours):(minutes):(seconds)"
1416                  "\n repeat (number_of_repetitions)"
1417                  "\nControl Commands Syntax:"
1418                  "\n play\n pause\n stop\n seek (percentage)\n" );
1419
1420         message = vlm_MessageNew( "help" , NULL );
1421         vlm_MessageAdd( message , vlm_MessageNew( "Help" , help ) );
1422         free( help );
1423         return message;
1424     }
1425
1426     return vlm_MessageNew( "help" , NULL );
1427 }
1428
1429 /* file must end by '\0' */
1430 static int vlm_Load( vlm_t *vlm, char *file )
1431 {
1432     char *pf = file;
1433
1434     while( *pf != '\0' )
1435     {
1436         vlm_message_t *message = NULL;
1437         int i_temp = 0;
1438         int i_next;
1439
1440         while( pf[i_temp] != '\n' && pf[i_temp] != '\0' && pf[i_temp] != '\r' )
1441         {
1442             i_temp++;
1443         }
1444
1445         if( pf[i_temp] == '\r' || pf[i_temp] == '\n' )
1446         {
1447             pf[i_temp] = '\0';
1448             i_next = i_temp + 1;
1449         }
1450         else
1451         {
1452             i_next = i_temp;
1453         }
1454
1455         if( ExecuteCommand( vlm, pf, &message ) )
1456         {
1457             free( message );
1458             return 1;
1459         }
1460         free( message );
1461
1462         pf += i_next;
1463     }
1464     return 0;
1465 }
1466
1467 static char *vlm_Save( vlm_t *vlm )
1468 {
1469     char *save = NULL;
1470     char *p;
1471     int i,j;
1472     int i_length = 0;
1473
1474     for( i = 0; i < vlm->i_media; i++ )
1475     {
1476         vlm_media_t *media = vlm->media[i];
1477
1478         if( media->i_type == VOD_TYPE )
1479         {
1480             i_length += strlen( "new  vod " ) + strlen(media->psz_name);
1481         }
1482         else
1483         {
1484             i_length += strlen( "new  broadcast " ) + strlen(media->psz_name);
1485         }
1486
1487         if( media->b_enabled == VLC_TRUE )
1488         {
1489             i_length += strlen( "enabled" );
1490         }
1491         else
1492         {
1493             i_length += strlen( "disabled" );
1494         }
1495
1496         if( media->b_loop == VLC_TRUE )
1497         {
1498             i_length += strlen( " loop\n" );
1499         }
1500         else
1501         {
1502             i_length += strlen( "\n" );
1503         }
1504
1505         for( j = 0; j < media->i_input; j++ )
1506         {
1507             i_length += strlen( "setup  input \"\"\n" ) + strlen( media->psz_name ) + strlen( media->input[j] );
1508         }
1509
1510         if( media->psz_output != NULL )
1511         {
1512             i_length += strlen(media->psz_name) + strlen(media->psz_output) + strlen( "setup  output \n" );
1513         }
1514
1515         for( j=0 ; j < media->i_option ; j++ )
1516         {
1517             i_length += strlen(media->psz_name) + strlen(media->option[j]) + strlen("setup  option \n");
1518         }
1519     }
1520
1521     for( i = 0; i < vlm->i_schedule; i++ )
1522     {
1523         vlm_schedule_t *schedule = vlm->schedule[i];
1524
1525         i_length += strlen( "new  schedule " ) + strlen( schedule->psz_name );
1526
1527         if( schedule->b_enabled == VLC_TRUE )
1528         {
1529             i_length += strlen( "date //-:: enabled\n" ) + 14;
1530         }
1531         else
1532         {
1533             i_length += strlen( "date //-:: disabled\n" ) + 14;
1534         }
1535
1536
1537         if( schedule->i_period != 0 )
1538         {
1539             i_length += strlen( "setup  " ) + strlen( schedule->psz_name ) + strlen( "period //-::\n" ) + 14;
1540         }
1541
1542         if( schedule->i_repeat >= 0 )
1543         {
1544             char buffer[12];
1545
1546             sprintf( buffer, "%d", schedule->i_repeat );
1547             i_length += strlen( "setup  repeat \n" ) + strlen( schedule->psz_name ) + strlen( buffer );
1548         }
1549         else
1550         {
1551             i_length++;
1552         }
1553
1554         for( j = 0; j < schedule->i_command; j++ )
1555         {
1556             i_length += strlen( "setup  append \n" ) + strlen( schedule->psz_name ) + strlen( schedule->command[j] );
1557         }
1558
1559     }
1560
1561     /* Don't forget the '\0' */
1562     i_length++;
1563     /* now we have the length of save */
1564
1565     p = save = malloc( i_length );
1566     *save = '\0';
1567
1568     /* finally we can write in it */
1569     for( i = 0; i < vlm->i_media; i++ )
1570     {
1571         vlm_media_t *media = vlm->media[i];
1572
1573         if( media->i_type == VOD_TYPE )
1574         {
1575             p += sprintf( p, "new %s vod ", media->psz_name);
1576         }
1577         else
1578         {
1579             p += sprintf( p, "new %s broadcast ", media->psz_name);
1580         }
1581
1582         if( media->b_enabled == VLC_TRUE )
1583         {
1584             p += sprintf( p, "enabled" );
1585         }
1586         else
1587         {
1588             p += sprintf( p, "disabled" );
1589         }
1590
1591         if( media->b_loop == VLC_TRUE )
1592         {
1593             p += sprintf( p, " loop\n" );
1594         }
1595         else
1596         {
1597             p += sprintf( p, "\n" );
1598         }
1599
1600         for( j = 0; j < media->i_input; j++ )
1601         {
1602             p += sprintf( p, "setup %s input \"%s\"\n", media->psz_name, media->input[j] );
1603         }
1604
1605         if( media->psz_output != NULL )
1606         {
1607             p += sprintf( p, "setup %s output %s\n", media->psz_name, media->psz_output );
1608         }
1609
1610         for( j = 0; j < media->i_option; j++ )
1611         {
1612             p += sprintf( p, "setup %s option %s\n", media->psz_name, media->option[j] );
1613         }
1614     }
1615
1616     /* and now, the schedule scripts */
1617
1618     for( i = 0; i < vlm->i_schedule; i++ )
1619     {
1620         vlm_schedule_t *schedule = vlm->schedule[i];
1621         struct tm date;
1622         time_t i_time = (time_t) ( schedule->i_date / 1000000 );
1623
1624 #ifdef HAVE_LOCALTIME_R
1625         localtime_r( &i_time, &date);
1626 #else
1627         struct tm *p_date = localtime( &i_time );
1628         date = *p_date;
1629 #endif
1630
1631         p += sprintf( p, "new %s schedule ", schedule->psz_name);
1632
1633         if( schedule->b_enabled == VLC_TRUE )
1634         {
1635             p += sprintf( p, "date %d/%d/%d-%d:%d:%d enabled\n",
1636                           date.tm_year + 1900, date.tm_mon + 1, date.tm_mday,
1637                           date.tm_hour, date.tm_min, date.tm_sec );
1638         }
1639         else
1640         {
1641             p += sprintf( p, "date %d/%d/%d-%d:%d:%d disabled\n",
1642                           date.tm_year + 1900, date.tm_mon + 1, date.tm_mday,
1643                           date.tm_hour, date.tm_min, date.tm_sec);
1644         }
1645
1646
1647         if( schedule->i_period != 0 )
1648         {
1649             p += sprintf( p, "setup %s ", schedule->psz_name );
1650
1651             i_time = (time_t) ( schedule->i_period / 1000000 );
1652
1653             date.tm_sec = (int)( i_time % 60 );
1654             i_time = i_time / 60;
1655             date.tm_min = (int)( i_time % 60 );
1656             i_time = i_time / 60;
1657             date.tm_hour = (int)( i_time % 24 );
1658             i_time = i_time / 24;
1659             date.tm_mday = (int)( i_time % 30 );
1660             i_time = i_time / 30;
1661             /* okay, okay, months are not always 30 days long */
1662             date.tm_mon = (int)( i_time % 12 );
1663             i_time = i_time / 12;
1664             date.tm_year = (int)i_time;
1665
1666             p += sprintf( p, "period %d/%d/%d-%d:%d:%d\n", date.tm_year ,
1667                                                            date.tm_mon,
1668                                                            date.tm_mday,
1669                                                            date.tm_hour,
1670                                                            date.tm_min,
1671                                                            date.tm_sec);
1672         }
1673
1674         if( schedule->i_repeat >= 0 )
1675         {
1676             p += sprintf( p, "setup %s repeat %d\n", schedule->psz_name, schedule->i_repeat );
1677         }
1678         else
1679         {
1680             p += sprintf( p, "\n" );
1681         }
1682
1683         for( j = 0; j < schedule->i_command; j++ )
1684         {
1685             p += sprintf( p, "setup %s append %s\n", schedule->psz_name, schedule->command[j] );
1686         }
1687
1688     }
1689
1690     return save;
1691 }
1692
1693 /*****************************************************************************
1694  * vlm_New:
1695  *****************************************************************************/
1696 vlm_t *__vlm_New ( vlc_object_t *p_object )
1697 {
1698     vlm_t *vlm = vlc_object_create( p_object , sizeof( vlm_t ) );
1699
1700     vlc_mutex_init( p_object->p_vlc, &vlm->lock );
1701     vlm->i_media      = 0;
1702     vlm->media        = NULL;
1703     vlm->i_schedule   = 0;
1704     vlm->schedule     = NULL;
1705
1706     if( vlc_thread_create( vlm, "vlm thread",
1707                            Manage, VLC_THREAD_PRIORITY_LOW, VLC_FALSE ) )
1708     {
1709
1710         vlc_mutex_destroy( &vlm->lock );
1711         vlc_object_destroy( vlm );
1712         return NULL;
1713     }
1714     return vlm;
1715 }
1716
1717 /*****************************************************************************
1718  * vlm_Delete:
1719  *****************************************************************************/
1720 void vlm_Delete( vlm_t *vlm )
1721 {
1722     int i;
1723
1724     vlm->b_die = VLC_TRUE;
1725     vlc_thread_join( vlm );
1726
1727     vlc_mutex_destroy( &vlm->lock );
1728
1729     for( i = 0; i < vlm->i_media; i++ )
1730     {
1731         vlm_media_t *media = vlm->media[i];
1732
1733         vlm_MediaDelete( vlm, media, NULL );
1734     }
1735
1736     if( vlm->media ) free( vlm->media );
1737
1738     for( i = 0; i < vlm->i_schedule; i++ )
1739     {
1740         vlm_ScheduleDelete( vlm, vlm->schedule[i], NULL );
1741     }
1742
1743     if( vlm->schedule ) free( vlm->schedule );
1744
1745     vlc_object_destroy( vlm );
1746 }
1747
1748 static vlm_schedule_t *vlm_ScheduleNew( vlm_t *vlm , char *psz_name )
1749 {
1750     vlm_schedule_t *sched= malloc( sizeof( vlm_schedule_t ));
1751
1752     sched->psz_name = strdup( psz_name );
1753     sched->b_enabled = VLC_FALSE;
1754     sched->i_command = 0;
1755     sched->command = NULL;
1756     sched->i_date = 0;
1757     sched->i_period = 0;
1758     sched->i_repeat = 0;
1759
1760     TAB_APPEND( vlm->i_schedule , vlm->schedule , sched );
1761
1762     return sched;
1763 }
1764
1765 /* for now, simple delete. After, del with options (last arg) */
1766 static int vlm_ScheduleDelete( vlm_t *vlm, vlm_schedule_t *sched, char *psz_name )
1767 {
1768     int i;
1769
1770     if( sched == NULL )
1771     {
1772         return 1;
1773     }
1774
1775     TAB_REMOVE( vlm->i_schedule, vlm->schedule , sched );
1776
1777     if( vlm->i_schedule == 0 && vlm->schedule ) free( vlm->schedule );
1778
1779     free( sched->psz_name );
1780
1781     for( i = 0; i < sched->i_command; i++ )
1782     {
1783         free( sched->command[i] );
1784     }
1785
1786     free( sched );
1787
1788     return 0;
1789 }
1790
1791 static vlm_schedule_t *vlm_ScheduleSearch( vlm_t *vlm, char *psz_name )
1792 {
1793     int i;
1794
1795     for( i = 0; i < vlm->i_schedule; i++ )
1796     {
1797         if( strcmp( psz_name, vlm->schedule[i]->psz_name ) == 0 )
1798         {
1799             return vlm->schedule[i];
1800         }
1801     }
1802
1803     return NULL;
1804 }
1805
1806 /* Ok, setup schedule command will be able to support only one (argument value) at a time  */
1807 static int vlm_ScheduleSetup( vlm_schedule_t *schedule, char *psz_cmd, char *psz_value )
1808 {
1809     if( strcmp( psz_cmd, "enabled" ) == 0 )
1810     {
1811         schedule->b_enabled = VLC_TRUE;
1812     }
1813     else if( strcmp( psz_cmd, "disabled" ) == 0 )
1814     {
1815         schedule->b_enabled = VLC_FALSE;
1816     }
1817     else if( strcmp( psz_cmd, "date" ) == 0 )
1818     {
1819         struct tm time;
1820         char *p;
1821         time_t date;
1822
1823         time.tm_sec = 0;         /* seconds */
1824         time.tm_min = 0;         /* minutes */
1825         time.tm_hour = 0;        /* hours */
1826         time.tm_mday = 0;        /* day of the month */
1827         time.tm_mon = 0;         /* month */
1828         time.tm_year = 0;        /* year */
1829         time.tm_wday = 0;        /* day of the week */
1830         time.tm_yday = 0;        /* day in the year */
1831         time.tm_isdst = 0;       /* daylight saving time */
1832
1833         /* date should be year/month/day-hour:minutes:seconds */
1834         p = strchr( psz_value , '-' );
1835
1836         if( strcmp( psz_value, "now" ) == 0 )
1837         {
1838             schedule->i_date = 0;
1839         }
1840         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 */
1841         {
1842             return 1;
1843         }
1844         else
1845         {
1846             int i,j,k;
1847
1848             switch( sscanf( p + 1, "%d:%d:%d" , &i, &j, &k ) )
1849             {
1850                 case 1:
1851                     time.tm_sec = i;
1852                     break;
1853                 case 2:
1854                     time.tm_min = i;
1855                     time.tm_sec = j;
1856                     break;
1857                 case 3:
1858                     time.tm_hour = i;
1859                     time.tm_min = j;
1860                     time.tm_sec = k;
1861                     break;
1862                 default:
1863                     return 1;
1864             }
1865
1866             *p = '\0';
1867
1868             switch( sscanf( psz_value, "%d/%d/%d" , &i, &j, &k ) )
1869             {
1870                 case 1:
1871                     time.tm_mday = i;
1872                     break;
1873                 case 2:
1874                     time.tm_mon = i - 1;
1875                     time.tm_mday = j;
1876                     break;
1877                 case 3:
1878                     time.tm_year = i - 1900;
1879                     time.tm_mon = j - 1;
1880                     time.tm_mday = k;
1881                     break;
1882                 default:
1883                     return 1;
1884             }
1885
1886             date = mktime( &time );
1887             schedule->i_date = ((mtime_t) date) * 1000000;
1888         }
1889     }
1890     else if( strcmp( psz_cmd, "period" ) == 0 )
1891     {
1892         struct tm time;
1893         char *p;
1894         time_t date;
1895
1896         /* First, if date or period are modified, repeat should be equal to -1 */
1897         schedule->i_repeat = -1;
1898
1899         time.tm_sec = 0;         /* seconds */
1900         time.tm_min = 0;         /* minutes */
1901         time.tm_hour = 0;        /* hours */
1902         time.tm_mday = 0;        /* day of the month */
1903         time.tm_mon = 0;         /* month */
1904         time.tm_year = 0;        /* year */
1905         time.tm_wday = 0;        /* day of the week */
1906         time.tm_yday = 0;        /* day in the year */
1907         time.tm_isdst = 0;       /* daylight saving time */
1908
1909         /* date should be year/month/day-hour:minutes:seconds */
1910         p = strchr( psz_value , '-' );
1911
1912         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 */
1913         {
1914             return 1;
1915         }
1916         else
1917         {
1918             int i,j,k;
1919
1920             switch( sscanf( p + 1, "%d:%d:%d" , &i, &j, &k ) )
1921             {
1922                 case 1:
1923                     time.tm_sec = i;
1924                     break;
1925                 case 2:
1926                     time.tm_min = i;
1927                     time.tm_sec = j;
1928                     break;
1929                 case 3:
1930                     time.tm_hour = i;
1931                     time.tm_min = j;
1932                     time.tm_sec = k;
1933                     break;
1934                 default:
1935                     return 1;
1936             }
1937
1938             *p = '\0';
1939
1940             switch( sscanf( psz_value, "%d/%d/%d" , &i, &j, &k ) )
1941             {
1942                 case 1:
1943                     time.tm_mday = i;
1944                     break;
1945                 case 2:
1946                     time.tm_mon = i;
1947                     time.tm_mday = j;
1948                     break;
1949                 case 3:
1950                     time.tm_year = i;
1951                     time.tm_mon = j;
1952                     time.tm_mday = k;
1953                     break;
1954                 default:
1955                     return 1;
1956             }
1957         }
1958
1959         /* ok, that's stupid... who is going to schedule streams every 42 years ? */
1960         date = (((( time.tm_year * 12 + time.tm_mon ) * 30 + time.tm_mday ) * 24 + time.tm_hour ) * 60 + time.tm_min ) * 60 + time.tm_sec ;
1961         schedule->i_period = ((mtime_t) date) * 1000000;
1962     }
1963     else if( strcmp( psz_cmd, "repeat" ) == 0 )
1964     {
1965         int i;
1966
1967         if( sscanf( psz_value, "%d" , &i ) == 1 )
1968         {
1969             schedule->i_repeat = i;
1970         }
1971         else
1972         {
1973             return 1;
1974         }
1975     }
1976     else if( strcmp( psz_cmd, "append" ) == 0 )
1977     {
1978         char *command = strdup( psz_value );
1979
1980         TAB_APPEND( schedule->i_command, schedule->command, command );
1981     }
1982     else
1983     {
1984         return 1;
1985     }
1986     return 0;
1987 }
1988
1989 /*****************************************************************************
1990  * Manage:
1991  *****************************************************************************/
1992 static int Manage( vlc_object_t* p_object )
1993 {
1994     vlm_t *vlm = (vlm_t*)p_object;
1995     int i,j;
1996     mtime_t i_lastcheck;
1997     mtime_t i_time;
1998
1999     i_lastcheck = mdate();
2000
2001     msleep( 100000 );
2002
2003     while( !vlm->b_die )
2004     {
2005         vlc_mutex_lock( &vlm->lock );
2006
2007         /* destroy the inputs that wants to die, and launch the next input */
2008         for( i = 0; i < vlm->i_media; i++ )
2009         {
2010             vlm_media_t *media = vlm->media[i];
2011
2012             if( media->p_input != NULL && ( media->p_input->b_eof || media->p_input->b_error ) )
2013             {
2014                 input_StopThread( media->p_input );
2015
2016                 input_DestroyThread( media->p_input );
2017                 vlc_object_detach( media->p_input );
2018                 vlc_object_destroy( media->p_input );
2019                 media->p_input = NULL;
2020                 media->i_index++;
2021
2022                 if( media->i_index == media->i_input && media->b_loop == VLC_TRUE )
2023                 {
2024                     media->i_index = 0;
2025                 }
2026
2027                 if( media->i_index < media->i_input )
2028                 {
2029                     char buffer[12];
2030
2031                     sprintf( buffer, "%d", media->i_index );
2032                     vlm_MediaControl( vlm, media, "play", buffer );
2033                 }
2034             }
2035         }
2036
2037         /* scheduling */
2038         i_time = mdate();
2039
2040         for( i = 0; i < vlm->i_schedule; i++ )
2041         {
2042             mtime_t i_real_date = vlm->schedule[i]->i_date;
2043
2044             if( vlm->schedule[i]->i_date == 0 ) // now !
2045             {
2046                 vlm->schedule[i]->i_date = (i_time / 1000000) * 1000000 ;
2047                 i_real_date = i_time;
2048             }
2049             else if( vlm->schedule[i]->i_period != 0 )
2050             {
2051                 int j = 0;
2052                 while( vlm->schedule[i]->i_date + j * vlm->schedule[i]->i_period <= i_lastcheck &&
2053                        ( vlm->schedule[i]->i_repeat > j || vlm->schedule[i]->i_repeat == -1 ) )
2054                 {
2055                     j++;
2056                 }
2057
2058                 i_real_date = vlm->schedule[i]->i_date + j * vlm->schedule[i]->i_period;
2059             }
2060
2061             if( vlm->schedule[i]->b_enabled == VLC_TRUE )
2062             {
2063                 if( i_real_date <= i_time && i_real_date > i_lastcheck )
2064                 {
2065                     for( j = 0 ; j < vlm->schedule[i]->i_command ; j++ )
2066                     {
2067                         vlm_message_t *message = NULL;
2068
2069                         ExecuteCommand( vlm, vlm->schedule[i]->command[j] , &message );
2070
2071                         /* for now, drop the message */
2072                         free( message );
2073                     }
2074                 }
2075             }
2076         }
2077
2078         i_lastcheck = i_time;
2079
2080         vlc_mutex_unlock( &vlm->lock );
2081
2082         msleep( 100000 );
2083     }
2084
2085     return VLC_SUCCESS;
2086 }
2087
2088
2089 void vlm_MessageDelete( vlm_message_t* message )
2090 {
2091     int i;
2092
2093     if( message->psz_name ) free( message->psz_name );
2094     if( message->psz_value ) free( message->psz_value );
2095
2096     for( i = 0; i < message->i_child; i++)
2097     {
2098         vlm_MessageDelete( message->child[i] );
2099     }
2100
2101     free( message );
2102 }
2103
2104 static vlm_message_t* vlm_MessageNew( char *psz_name , char *psz_value )
2105 {
2106     vlm_message_t *message = malloc( sizeof(vlm_message_t) );
2107
2108     if( psz_name )
2109     {
2110         message->psz_name = strdup( psz_name );
2111     }
2112     else
2113     {
2114         return NULL;
2115     }
2116
2117     if( psz_value )
2118     {
2119         message->psz_value = strdup( psz_value );
2120     }
2121     else
2122     {
2123         message->psz_value = NULL;
2124     }
2125
2126     message->i_child = 0;
2127     message->child = NULL;
2128
2129     return message;
2130 }
2131
2132 /* add a child */
2133 static vlm_message_t* vlm_MessageAdd( vlm_message_t* message , vlm_message_t* child )
2134 {
2135     if( message == NULL ) return NULL;
2136
2137     if( child )
2138     {
2139         TAB_APPEND( message->i_child , message->child , child );
2140     }
2141
2142     return child;
2143 }
2144