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