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