Main Page | Modules | Class Hierarchy | Class List | Directories | File List | Class Members | File Members | Related Pages

vlm.c

00001 /*****************************************************************************
00002  * vlm.c: VLM interface plugin
00003  *****************************************************************************
00004  * Copyright (C) 2000, 2001 the VideoLAN team
00005  * $Id: vlm.c 13133 2005-11-04 21:10:24Z courmisch $
00006  *
00007  * Authors: Simon Latapie <[email protected]>
00008  *          Laurent Aimar <[email protected]>
00009  *          Gildas Bazin <[email protected]>
00010  *
00011  * This program is free software; you can redistribute it and/or modify
00012  * it under the terms of the GNU General Public License as published by
00013  * the Free Software Foundation; either version 2 of the License, or
00014  * (at your option) any later version.
00015  *
00016  * This program is distributed in the hope that it will be useful,
00017  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00018  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019  * GNU General Public License for more details.
00020  *
00021  * You should have received a copy of the GNU General Public License
00022  * along with this program; if not, write to the Free Software
00023  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
00024  *****************************************************************************/
00025 
00026 /*****************************************************************************
00027  * Preamble
00028  *****************************************************************************/
00029 #include <stdlib.h>                                      /* malloc(), free() */
00030 #include <ctype.h>                                              /* tolower() */
00031 
00032 #include <vlc/vlc.h>
00033 
00034 #ifdef ENABLE_VLM
00035 
00036 #include <vlc/intf.h>
00037 #include <vlc/input.h>
00038 
00039 #ifdef HAVE_TIME_H
00040 #   include <time.h>                                              /* ctime() */
00041 #   include <sys/timeb.h>                                         /* ftime() */
00042 #endif
00043 
00044 #include "vlc_vlm.h"
00045 #include "vlc_vod.h"
00046 
00047 #define FREE( p ) \
00048         if( p ) { free( p ); (p) = NULL; }
00049 
00050 /*****************************************************************************
00051  * Local prototypes.
00052  *****************************************************************************/
00053 static vlm_message_t *vlm_Show( vlm_t *, vlm_media_t *, vlm_schedule_t *, char * );
00054 static vlm_message_t *vlm_Help( vlm_t *, char * );
00055 
00056 static vlm_media_t *vlm_MediaSearch ( vlm_t *, char * );
00057 static vlm_media_instance_t *vlm_MediaInstanceSearch( vlm_t *, vlm_media_t *, char * );
00058 
00059 static vlm_message_t *vlm_MessageNew( char *, const char *, ... );
00060 static vlm_message_t *vlm_MessageAdd( vlm_message_t *, vlm_message_t * );
00061 
00062 static vlm_schedule_t *vlm_ScheduleSearch( vlm_t *, char * );
00063 
00064 static char *Save( vlm_t * );
00065 static int Load( vlm_t *, char * );
00066 static int ExecuteCommand( vlm_t *, char *, vlm_message_t ** );
00067 static int Manage( vlc_object_t * );
00068 
00069 /*****************************************************************************
00070  * vlm_New:
00071  *****************************************************************************/
00072 vlm_t *__vlm_New ( vlc_object_t *p_this )
00073 {
00074     vlc_value_t lockval;
00075     vlm_t *p_vlm = NULL;
00076     char *psz_vlmconf;
00077 
00078     /* to be sure to avoid multiple creation */
00079     var_Create( p_this->p_libvlc, "vlm_mutex", VLC_VAR_MUTEX );
00080     var_Get( p_this->p_libvlc, "vlm_mutex", &lockval );
00081     vlc_mutex_lock( lockval.p_address );
00082 
00083     if( !(p_vlm = vlc_object_find( p_this, VLC_OBJECT_VLM, FIND_ANYWHERE )) )
00084     {
00085         msg_Info( p_this, "creating vlm" );
00086         if( ( p_vlm = vlc_object_create( p_this, VLC_OBJECT_VLM ) ) == NULL )
00087         {
00088             vlc_mutex_unlock( lockval.p_address );
00089             return NULL;
00090         }
00091 
00092         vlc_mutex_init( p_this->p_vlc, &p_vlm->lock );
00093         p_vlm->i_media      = 0;
00094         p_vlm->media        = NULL;
00095         p_vlm->i_vod        = 0;
00096         p_vlm->i_schedule   = 0;
00097         p_vlm->schedule     = NULL;
00098 
00099         vlc_object_yield( p_vlm );
00100         vlc_object_attach( p_vlm, p_this->p_vlc );
00101     }
00102     vlc_mutex_unlock( lockval.p_address );
00103 
00104     if( vlc_thread_create( p_vlm, "vlm thread",
00105                            Manage, VLC_THREAD_PRIORITY_LOW, VLC_FALSE ) )
00106     {
00107         vlc_mutex_destroy( &p_vlm->lock );
00108         vlc_object_destroy( p_vlm );
00109         return NULL;
00110     }
00111 
00112     /* Try loading the vlm conf file given by --vlm-conf */
00113     psz_vlmconf = config_GetPsz( p_vlm, "vlm-conf" );
00114 
00115     if( psz_vlmconf && *psz_vlmconf )
00116     {
00117         vlm_message_t *p_message = NULL;
00118         char *psz_buffer = NULL;
00119 
00120         msg_Dbg( p_this, "loading vlm conf ..." );
00121         asprintf(&psz_buffer, "load %s", psz_vlmconf );
00122         if( psz_buffer )
00123         {
00124             msg_Dbg( p_this, psz_buffer);
00125             if( vlm_ExecuteCommand( p_vlm, psz_buffer, &p_message ) ){
00126                 msg_Warn( p_this, "error while loading the vlm conf file" );
00127             }
00128             free(p_message);
00129             free(psz_buffer);
00130         }
00131    }
00132    free(psz_vlmconf);
00133 
00134    return p_vlm;
00135 }
00136 
00137 /*****************************************************************************
00138  * vlm_Delete:
00139  *****************************************************************************/
00140 void vlm_Delete( vlm_t *p_vlm )
00141 {
00142     vlc_value_t lockval;
00143 
00144     var_Get( p_vlm->p_libvlc, "vlm_mutex", &lockval );
00145     vlc_mutex_lock( lockval.p_address );
00146 
00147     vlc_object_release( p_vlm );
00148 
00149     if( p_vlm->i_refcount > 0 )
00150     {
00151         vlc_mutex_unlock( lockval.p_address );
00152         return;
00153     }
00154 
00155     p_vlm->b_die = VLC_TRUE;
00156     vlc_thread_join( p_vlm );
00157 
00158     vlc_mutex_destroy( &p_vlm->lock );
00159 
00160     while( p_vlm->i_media ) vlm_MediaDelete( p_vlm, p_vlm->media[0], NULL );
00161     FREE( p_vlm->media );
00162 
00163     while( p_vlm->i_schedule ) vlm_ScheduleDelete( p_vlm,
00164                                                    p_vlm->schedule[0], NULL );
00165     FREE( p_vlm->schedule );
00166 
00167     vlc_object_detach( p_vlm );
00168     vlc_object_destroy( p_vlm );
00169     vlc_mutex_unlock( lockval.p_address );
00170 }
00171 
00172 /*****************************************************************************
00173  * vlm_ExecuteCommand:
00174  *****************************************************************************/
00175 int vlm_ExecuteCommand( vlm_t *p_vlm, char *psz_command,
00176                         vlm_message_t **pp_message)
00177 {
00178     int i_result;
00179 
00180     vlc_mutex_lock( &p_vlm->lock );
00181     i_result = ExecuteCommand( p_vlm, psz_command, pp_message );
00182     vlc_mutex_unlock( &p_vlm->lock );
00183 
00184     return i_result;
00185 }
00186 
00187 /*****************************************************************************
00188  * vlm_Save:
00189  *****************************************************************************/
00190 int vlm_Save( vlm_t *p_vlm, char *psz_file )
00191 {
00192     FILE *file;
00193     char *psz_save;
00194 
00195     if( !p_vlm || !psz_file ) return 1;
00196 
00197     file = fopen( psz_file, "wt" );
00198     if( file == NULL ) return 1;
00199 
00200     psz_save = Save( p_vlm );
00201     if( psz_save == NULL )
00202     {
00203         fclose( file );
00204         return 1;
00205     }
00206     fwrite( psz_save, strlen( psz_save ), 1, file );
00207     fclose( file );
00208     free( psz_save );
00209 
00210     return 0;
00211 }
00212 
00213 /*****************************************************************************
00214  * vlm_Load:
00215  *****************************************************************************/
00216 int vlm_Load( vlm_t *p_vlm, char *psz_file )
00217 {
00218     FILE *file;
00219     int64_t i_size;
00220     char *psz_buffer;
00221 
00222     if( !p_vlm || !psz_file ) return 1;
00223 
00224     file = fopen( psz_file, "r" );
00225     if( file == NULL ) return 1;
00226 
00227     if( fseek( file, 0, SEEK_END) != 0 )
00228     {
00229         fclose( file );
00230         return 2;
00231     }
00232 
00233     i_size = ftell( file );
00234     fseek( file, 0, SEEK_SET );
00235     psz_buffer = malloc( i_size + 1 );
00236     if( !psz_buffer )
00237     {
00238         fclose( file );
00239         return 2;
00240     }
00241     fread( psz_buffer, 1, i_size, file );
00242     psz_buffer[ i_size ] = '\0';
00243     if( Load( p_vlm, psz_buffer ) )
00244     {
00245         fclose( file );
00246         free( psz_buffer );
00247         return 3;
00248     }
00249 
00250     free( psz_buffer );
00251     fclose( file );
00252 
00253     return 0;
00254 }
00255 
00256 /*****************************************************************************
00257  * FindEndCommand
00258  *****************************************************************************/
00259 static char *FindEndCommand( char *psz )
00260 {
00261     char *psz_sent = psz;
00262 
00263     switch( *psz_sent )
00264     {
00265     case '\"':
00266         psz_sent++;
00267 
00268         while( ( *psz_sent != '\"' ) && ( *psz_sent != '\0' ) )
00269         {
00270             if( *psz_sent == '\'' )
00271             {
00272                 psz_sent = FindEndCommand( psz_sent );
00273                 if( psz_sent == NULL ) return NULL;
00274             }
00275             else psz_sent++;
00276         }
00277 
00278         if( *psz_sent == '\"' )
00279         {
00280             psz_sent++;
00281             return psz_sent;
00282         }
00283 
00284         /* *psz_sent == '\0' -> number of " is incorrect */
00285         else return NULL;
00286 
00287         break;
00288 
00289     case '\'':
00290         psz_sent++;
00291 
00292         while( ( *psz_sent != '\'' ) && ( *psz_sent != '\0' ) )
00293         {
00294             if( *psz_sent == '\"' )
00295             {
00296                 psz_sent = FindEndCommand( psz_sent );
00297                 if( psz_sent == NULL ) return NULL;
00298             }
00299             else psz_sent++;
00300         }
00301 
00302         if( *psz_sent == '\'' )
00303         {
00304             psz_sent++;
00305             return psz_sent;
00306         }
00307 
00308         /* *psz_sent == '\0' -> number of " is incorrect */
00309         else return NULL;
00310 
00311         break;
00312 
00313     default: /* now we can look for spaces */
00314         while( ( *psz_sent != ' ' ) && ( *psz_sent != '\0' ) )
00315         {
00316             if( ( *psz_sent == '\'' ) || ( *psz_sent == '\"' ) )
00317             {
00318                 psz_sent = FindEndCommand( psz_sent );
00319             }
00320             else psz_sent++;
00321         }
00322 
00323         return psz_sent;
00324     }
00325 }
00326 
00327 /*****************************************************************************
00328  * ExecuteCommand: The main state machine
00329  *****************************************************************************
00330  * Execute a command which ends with '\0' (string)
00331  *****************************************************************************/
00332 static int ExecuteCommand( vlm_t *p_vlm, char *psz_command,
00333                            vlm_message_t **pp_message )
00334 {
00335     int i_command = 0;
00336     char **ppsz_command = NULL;
00337     char *psz_cmd = psz_command;
00338     vlm_message_t *p_message = NULL;
00339     int i, j;
00340 
00341     /* First, parse the line and cut it */
00342     while( *psz_cmd != '\0' )
00343     {
00344 
00345         if( *psz_cmd == ' ' || *psz_cmd == '\t' )
00346         {
00347             psz_cmd++;
00348         }
00349         else
00350         {
00351             char *psz_temp;
00352             int   i_temp;
00353 
00354             /* support for comments */
00355             if( i_command == 0 && *psz_cmd == '#')
00356             {
00357                 p_message = vlm_MessageNew( "", NULL );
00358                 goto success;
00359             }
00360 
00361             psz_temp = FindEndCommand( psz_cmd );
00362 
00363             if( psz_temp == NULL )
00364             {
00365                 p_message = vlm_MessageNew( "Incomplete command", psz_cmd );
00366                 goto error;
00367             }
00368 
00369             i_temp = psz_temp - psz_cmd;
00370 
00371             ppsz_command = realloc( ppsz_command, (i_command + 1) *
00372                                     sizeof(char*) );
00373             ppsz_command[ i_command ] = malloc( (i_temp + 1) * sizeof(char) );
00374             strncpy( ppsz_command[ i_command ], psz_cmd, i_temp );
00375             ppsz_command[ i_command ][ i_temp ] = '\0';
00376 
00377             i_command++;
00378 
00379             psz_cmd = psz_temp;
00380         }
00381     }
00382 
00383     /*
00384      * And then Interpret it
00385      */
00386 
00387     if( i_command == 0 )
00388     {
00389         p_message = vlm_MessageNew( "", NULL );
00390         goto success;
00391     }
00392 
00393     if( !strcmp(ppsz_command[0], "new") )
00394     {
00395         int i_type;
00396 
00397         /* Check the number of arguments */
00398         if( i_command < 3 ) goto syntax_error;
00399 
00400         /* Get type */
00401         if( !strcmp(ppsz_command[2], "vod") )
00402         {
00403             i_type = VOD_TYPE;
00404         }
00405         else if( !strcmp(ppsz_command[2], "broadcast") )
00406         {
00407             i_type = BROADCAST_TYPE;
00408         }
00409         else if( !strcmp(ppsz_command[2], "schedule") )
00410         {
00411             i_type = SCHEDULE_TYPE;
00412         }
00413         else
00414         {
00415             p_message =
00416                 vlm_MessageNew( "new", "%s: Choose between vod, "
00417                                 "broadcast or schedule", ppsz_command[1] );
00418             goto error;
00419         }
00420 
00421         /* Check for forbidden media names */
00422         if( !strcmp(ppsz_command[1], "all") ||
00423             !strcmp(ppsz_command[1], "media") ||
00424             !strcmp(ppsz_command[1], "schedule") )
00425         {
00426             p_message = vlm_MessageNew( "new", "\"all\", \"media\" and "
00427                                         "\"schedule\" are reserved names" );
00428             goto error;
00429         }
00430 
00431         /* Check the name is not already in use */
00432         if( vlm_ScheduleSearch( p_vlm, ppsz_command[1] ) ||
00433             vlm_MediaSearch( p_vlm, ppsz_command[1] ) )
00434         {
00435             p_message = vlm_MessageNew( "new", "%s: Name already in use",
00436                                         ppsz_command[1] );
00437             goto error;
00438         }
00439 
00440         /* Schedule */
00441         if( i_type == SCHEDULE_TYPE )
00442         {
00443             vlm_schedule_t *p_schedule;
00444             p_schedule = vlm_ScheduleNew( p_vlm, ppsz_command[1] );
00445             if( !p_schedule )
00446             {
00447                 p_message = vlm_MessageNew( "new", "could not create schedule" );
00448                 goto error;
00449             }
00450         }
00451 
00452         /* Media */
00453         else
00454         {
00455             vlm_media_t *p_media;
00456             p_media = vlm_MediaNew( p_vlm, ppsz_command[1], i_type );
00457             if( !p_media )
00458             {
00459                 p_message = vlm_MessageNew( "new", "could not create media" );
00460                 goto error;
00461             }
00462         }
00463 
00464         if( i_command <= 3 )
00465         {
00466             p_message = vlm_MessageNew( "new", NULL );
00467             goto success;
00468         }
00469 
00470         /* Properties will be dealt with later on */
00471     }
00472 
00473     else if( !strcmp(ppsz_command[0], "setup") )
00474     {
00475         if( i_command < 2 ) goto syntax_error;
00476 
00477         /* Properties will be dealt with later on */
00478     }
00479 
00480     else if( !strcmp(ppsz_command[0], "del") )
00481     {
00482         vlm_media_t *p_media;
00483         vlm_schedule_t *p_schedule;
00484 
00485         if( i_command < 2 ) goto syntax_error;
00486 
00487         p_media = vlm_MediaSearch( p_vlm, ppsz_command[1] );
00488         p_schedule = vlm_ScheduleSearch( p_vlm, ppsz_command[1] );
00489 
00490         if( p_schedule != NULL )
00491         {
00492             vlm_ScheduleDelete( p_vlm, p_schedule, NULL );
00493         }
00494         else if( p_media != NULL )
00495         {
00496             vlm_MediaDelete( p_vlm, p_media, NULL );
00497         }
00498         else if( !strcmp(ppsz_command[1], "media") )
00499         {
00500             while( p_vlm->i_media ) vlm_MediaDelete( p_vlm, p_vlm->media[0],
00501                                                      NULL );
00502         }
00503         else if( !strcmp(ppsz_command[1], "schedule") )
00504         {
00505             while( p_vlm->i_schedule )
00506                 vlm_ScheduleDelete( p_vlm, p_vlm->schedule[0], NULL );
00507         }
00508         else if( !strcmp(ppsz_command[1], "all") )
00509         {
00510             while( p_vlm->i_media ) vlm_MediaDelete( p_vlm, p_vlm->media[0],
00511                                                      NULL );
00512 
00513             while( p_vlm->i_schedule )
00514                 vlm_ScheduleDelete( p_vlm, p_vlm->schedule[0], NULL );
00515         }
00516         else
00517         {
00518             p_message = vlm_MessageNew( "del", "%s: media unknown",
00519                                       ppsz_command[1] );
00520             goto error;
00521         }
00522 
00523         p_message = vlm_MessageNew( "del", NULL );
00524         goto success;
00525     }
00526 
00527     else if( !strcmp(ppsz_command[0], "show") )
00528     {
00529         vlm_media_t *p_media;
00530         vlm_schedule_t *p_schedule;
00531 
00532         if( i_command == 1 )
00533         {
00534             p_message = vlm_Show( p_vlm, NULL, NULL, NULL );
00535             goto success;
00536         }
00537         else if( i_command > 2 ) goto syntax_error;
00538 
00539         p_media = vlm_MediaSearch( p_vlm, ppsz_command[1] );
00540         p_schedule = vlm_ScheduleSearch( p_vlm, ppsz_command[1] );
00541 
00542         if( p_schedule != NULL )
00543         {
00544             p_message = vlm_Show( p_vlm, NULL, p_schedule, NULL );
00545         }
00546         else if( p_media != NULL )
00547         {
00548             p_message = vlm_Show( p_vlm, p_media, NULL, NULL );
00549         }
00550         else
00551         {
00552             p_message = vlm_Show( p_vlm, NULL, NULL, ppsz_command[1] );
00553         }
00554 
00555         goto success;
00556     }
00557 
00558     else if( !strcmp(ppsz_command[0], "help") )
00559     {
00560         if( i_command != 1 ) goto syntax_error;
00561 
00562         p_message = vlm_Help( p_vlm, NULL );
00563         goto success;
00564     }
00565 
00566     else if( !strcmp(ppsz_command[0], "control") )
00567     {
00568         vlm_media_t *p_media;
00569 
00570         if( i_command < 3 ) goto syntax_error;
00571 
00572         if( !(p_media = vlm_MediaSearch( p_vlm, ppsz_command[1] ) ) )
00573         {
00574             p_message = vlm_MessageNew( "control", "%s: media unknown",
00575                                       ppsz_command[1] );
00576             goto error;
00577         }
00578         else
00579         {
00580             char *psz_command, *psz_arg = 0, *psz_instance = 0;
00581             int i_index = 2;
00582 
00583             if( strcmp( ppsz_command[2], "play" ) &&
00584                 strcmp( ppsz_command[2], "stop" ) &&
00585                 strcmp( ppsz_command[2], "pause" ) &&
00586                 strcmp( ppsz_command[2], "seek" ) )
00587             {
00588                 i_index++;
00589                 psz_instance = ppsz_command[2];
00590 
00591                 if( i_command < 4 ) goto syntax_error;
00592             }
00593 
00594             psz_command = ppsz_command[i_index];
00595 
00596             if( i_command >= i_index + 2 ) psz_arg = ppsz_command[i_index + 1];
00597 
00598             vlm_MediaControl( p_vlm, p_media, psz_instance, psz_command,
00599                              psz_arg );
00600             p_message = vlm_MessageNew( "control", NULL );
00601             goto success;
00602         }
00603     }
00604 
00605     else if( !strcmp(ppsz_command[0], "save") )
00606     {
00607         if( i_command != 2 ) goto syntax_error;
00608 
00609         if( vlm_Save( p_vlm, ppsz_command[1] ) )
00610         {
00611             p_message = vlm_MessageNew( "save", "Unable to save to file" );
00612             goto error;
00613         }
00614         else
00615         {
00616             p_message = vlm_MessageNew( "save", NULL );
00617             goto success;
00618         }
00619     }
00620 
00621     else if( !strcmp(ppsz_command[0], "load") )
00622     {
00623         if( i_command != 2 ) goto syntax_error;
00624 
00625         switch( vlm_Load( p_vlm, ppsz_command[1] ) )
00626         {
00627             case 0:
00628                 p_message = vlm_MessageNew( "load", NULL );
00629                 goto success;
00630             case 2:
00631                 p_message = vlm_MessageNew( "load", "read file error" );
00632                 goto error;
00633             case 3:
00634                 p_message =
00635                     vlm_MessageNew( "load", "error while loading file" );
00636                 goto error;
00637             default:
00638                 p_message =
00639                     vlm_MessageNew( "load", "Unable to load from file" );
00640                 goto error;
00641         }
00642     }
00643 
00644     else
00645     {
00646         p_message = vlm_MessageNew( ppsz_command[0], "Unknown command" );
00647         goto error;
00648     }
00649 
00650     /* Common code between "new" and "setup" */
00651     if( !strcmp(ppsz_command[0], "new") ||
00652         !strcmp(ppsz_command[0], "setup") )
00653     {
00654         int i_command_start = strcmp(ppsz_command[0], "new") ? 2 : 3;
00655         vlm_media_t *p_media;
00656         vlm_schedule_t *p_schedule;
00657 
00658         if( i_command < i_command_start ) goto syntax_error;
00659 
00660         p_media = vlm_MediaSearch( p_vlm, ppsz_command[1] );
00661         p_schedule = vlm_ScheduleSearch( p_vlm, ppsz_command[1] );
00662 
00663         if( !p_media && !p_schedule )
00664         {
00665             p_message = vlm_MessageNew( ppsz_command[0], "%s unknown",
00666                                         ppsz_command[1] );
00667             goto error;
00668         }
00669 
00670         if( p_schedule != NULL )
00671         {
00672             for( i = i_command_start ; i < i_command ; i++ )
00673             {
00674                 if( !strcmp( ppsz_command[i], "enabled" ) ||
00675                     !strcmp( ppsz_command[i], "disabled" ) )
00676                 {
00677                     vlm_ScheduleSetup( p_schedule, ppsz_command[i], NULL );
00678                 }
00679 
00680                 /* Beware: everything behind append is considered as
00681                  * command line */
00682                 else if( !strcmp( ppsz_command[i], "append" ) )
00683                 {
00684                     if( ++i >= i_command ) break;
00685 
00686                     for( j = i + 1; j < i_command; j++ )
00687                     {
00688                         ppsz_command[i] =
00689                             realloc( ppsz_command[i], strlen(ppsz_command[i]) +
00690                                      strlen(ppsz_command[j]) + 1 + 1 );
00691                         strcat( ppsz_command[i], " " );
00692                         strcat( ppsz_command[i], ppsz_command[j] );
00693                     }
00694 
00695                     vlm_ScheduleSetup( p_schedule, ppsz_command[i - 1],
00696                                        ppsz_command[i] );
00697                     break;
00698                 }
00699                 else
00700                 {
00701                     if( i + 1 >= i_command && !strcmp(ppsz_command[0], "new") )
00702                     {
00703                         vlm_ScheduleDelete( p_vlm, p_schedule, NULL );
00704                         p_message =
00705                             vlm_MessageNew( ppsz_command[0],
00706                                             "Wrong properties syntax" );
00707                         goto error;
00708                     }
00709                     else if( i + 1 >= i_command )
00710                     {
00711                         p_message =
00712                             vlm_MessageNew( ppsz_command[0],
00713                                             "Wrong properties syntax" );
00714                         goto error;
00715                     }
00716 
00717                     vlm_ScheduleSetup( p_schedule, ppsz_command[i],
00718                                        ppsz_command[i+1] );
00719                     i++;
00720                 }
00721             }
00722         }
00723 
00724         else if( p_media != NULL )
00725         {
00726             for( i = i_command_start ; i < i_command ; i++ )
00727             {
00728                 if( !strcmp( ppsz_command[i], "enabled" ) ||
00729                     !strcmp( ppsz_command[i], "disabled" ) )
00730                 {
00731                     vlm_MediaSetup( p_vlm, p_media, ppsz_command[i], NULL );
00732                 }
00733                 else if( i + 1 >= i_command &&
00734                          !strcmp( ppsz_command[i], "mux") )
00735                 {
00736                     if( p_media->i_type != VOD_TYPE )
00737                     {
00738                         p_message = vlm_MessageNew( ppsz_command[0],
00739                                   "mux only available for broadcast" );
00740                     }
00741                     else
00742                     {
00743                         vlm_MediaSetup( p_vlm, p_media, ppsz_command[i],
00744                                         ppsz_command[i+1] );
00745                         i++;
00746                     }
00747                 }
00748                 else if( !strcmp( ppsz_command[i], "loop" ) ||
00749                          !strcmp( ppsz_command[i], "unloop" ) )
00750                 {
00751                     if( p_media->i_type != BROADCAST_TYPE )
00752                     {
00753                         p_message = vlm_MessageNew( ppsz_command[0],
00754                                   "loop only available for broadcast" );
00755                     }
00756                     else
00757                     {
00758                         vlm_MediaSetup( p_vlm, p_media, ppsz_command[i], NULL );
00759                     }
00760                 }
00761                 else
00762                 {
00763                     if( i + 1 >= i_command &&
00764                         !strcmp(ppsz_command[0], "new") )
00765                     {
00766                         vlm_MediaDelete( p_vlm, p_media, NULL );
00767                         p_message =
00768                             vlm_MessageNew( ppsz_command[0],
00769                                             "Wrong properties syntax" );
00770                         goto error;
00771                     }
00772                     else if( i + 1 >= i_command )
00773                     {
00774                         p_message =
00775                             vlm_MessageNew( ppsz_command[0],
00776                                             "Wrong properties syntax" );
00777                         goto error;
00778                     }
00779 
00780                     vlm_MediaSetup( p_vlm, p_media, ppsz_command[i],
00781                                     ppsz_command[i+1] );
00782                     i++;
00783                 }
00784             }
00785         }
00786 
00787         p_message = vlm_MessageNew( ppsz_command[0], NULL );
00788         goto success;
00789     }
00790 
00791 success:
00792     for( i = 0 ; i < i_command ; i++ ) FREE( ppsz_command[i] );
00793     FREE( ppsz_command );
00794     *pp_message = p_message;
00795 
00796     return VLC_SUCCESS;
00797 
00798 syntax_error:
00799     p_message = vlm_MessageNew( ppsz_command[0], "Wrong command syntax" );
00800 
00801 error:
00802     for( i = 0 ; i < i_command ; i++ ) FREE( ppsz_command[i] );
00803     FREE( ppsz_command );
00804     *pp_message = p_message;
00805 
00806     return VLC_EGENERIC;
00807 }
00808 
00809 static vlm_media_t *vlm_MediaSearch( vlm_t *vlm, char *psz_name )
00810 {
00811     int i;
00812 
00813     for( i = 0; i < vlm->i_media; i++ )
00814     {
00815         if( strcmp( psz_name, vlm->media[i]->psz_name ) == 0 )
00816         {
00817             return vlm->media[i];
00818         }
00819     }
00820 
00821     return NULL;
00822 }
00823 
00824 /*****************************************************************************
00825  * Media handling
00826  *****************************************************************************/
00827 static vlm_media_instance_t *
00828 vlm_MediaInstanceSearch( vlm_t *vlm, vlm_media_t *media, char *psz_name )
00829 {
00830     int i;
00831 
00832     for( i = 0; i < media->i_instance; i++ )
00833     {
00834         if( ( !psz_name && !media->instance[i]->psz_name ) ||
00835             ( psz_name && media->instance[i]->psz_name &&
00836               !strcmp( psz_name, media->instance[i]->psz_name ) ) )
00837         {
00838             return media->instance[i];
00839         }
00840     }
00841 
00842     return NULL;
00843 }
00844 
00845 vlm_media_t *vlm_MediaNew( vlm_t *vlm, char *psz_name, int i_type )
00846 {
00847     vlm_media_t *media = malloc( sizeof( vlm_media_t ) );
00848 
00849     if( !media )
00850     {
00851         msg_Err( vlm, "out of memory" );
00852         return NULL;
00853     }
00854 
00855     /* Check if we need to load the VOD server */
00856     if( i_type == VOD_TYPE && !vlm->i_vod )
00857     {
00858         vlm->vod = vlc_object_create( vlm, VLC_OBJECT_VOD );
00859         vlc_object_attach( vlm->vod, vlm );
00860         vlm->vod->p_module = module_Need( vlm->vod, "vod server", 0, 0 );
00861         if( !vlm->vod->p_module )
00862         {
00863             msg_Err( vlm, "cannot find vod server" );
00864             vlc_object_detach( vlm->vod );
00865             vlc_object_destroy( vlm->vod );
00866             vlm->vod = 0;
00867             free( media );
00868             return NULL;
00869         }
00870 
00871         vlm->vod->p_data = vlm;
00872         vlm->vod->pf_media_control = vlm_MediaVodControl;
00873     }
00874 
00875     if( i_type == VOD_TYPE ) vlm->i_vod++;
00876 
00877     media->psz_name = strdup( psz_name );
00878     media->b_enabled = VLC_FALSE;
00879     media->b_loop = VLC_FALSE;
00880     media->vod_media = NULL;
00881     media->psz_vod_output = NULL;
00882     media->psz_mux = NULL;
00883     media->i_input = 0;
00884     media->input = NULL;
00885     media->psz_output = NULL;
00886     media->i_option = 0;
00887     media->option = NULL;
00888     media->i_type = i_type;
00889     media->i_instance = 0;
00890     media->instance = NULL;
00891 
00892     media->item.psz_uri = strdup( psz_name );
00893     vlc_input_item_Init( VLC_OBJECT(vlm), &media->item );
00894 
00895     TAB_APPEND( vlm->i_media, vlm->media, media );
00896 
00897     return media;
00898 }
00899 
00900 /* for now, simple delete. After, del with options (last arg) */
00901 void vlm_MediaDelete( vlm_t *vlm, vlm_media_t *media, char *psz_name )
00902 {
00903     if( media == NULL ) return;
00904 
00905     while( media->i_instance )
00906     {
00907         vlm_media_instance_t *p_instance = media->instance[0];
00908         vlm_MediaControl( vlm, media, p_instance->psz_name, "stop", 0 );
00909     }
00910 
00911     TAB_REMOVE( vlm->i_media, vlm->media, media );
00912 
00913     if( media->i_type == VOD_TYPE )
00914     {
00915         vlm_MediaSetup( vlm, media, "disabled", 0 );
00916         vlm->i_vod--;
00917     }
00918 
00919     /* Check if we need to unload the VOD server */
00920     if( media->i_type == VOD_TYPE && !vlm->i_vod )
00921     {
00922         module_Unneed( vlm->vod, vlm->vod->p_module );
00923         vlc_object_detach( vlm->vod );
00924         vlc_object_destroy( vlm->vod );
00925         vlm->vod = 0;
00926     }
00927 
00928     if( vlm->i_media == 0 && vlm->media ) free( vlm->media );
00929 
00930     free( media->psz_name );
00931 
00932     while( media->i_input-- ) free( media->input[media->i_input] );
00933     if( media->input ) free( media->input );
00934 
00935     if( media->psz_output ) free( media->psz_output );
00936     if( media->psz_mux ) free( media->psz_mux );
00937 
00938     while( media->i_option-- ) free( media->option[media->i_option] );
00939     if( media->option ) free( media->option );
00940 
00941     vlc_input_item_Clean( &media->item );
00942 
00943     free( media );
00944 }
00945 
00946 int vlm_MediaSetup( vlm_t *vlm, vlm_media_t *media, char *psz_cmd,
00947                     char *psz_value )
00948 {
00949     if( !psz_cmd) return VLC_EGENERIC;
00950 
00951     if( !strcmp( psz_cmd, "loop" ) )
00952     {
00953         media->b_loop = VLC_TRUE;
00954     }
00955     else if( !strcmp( psz_cmd, "unloop" ) )
00956     {
00957         media->b_loop = VLC_FALSE;
00958     }
00959     else if( !strcmp( psz_cmd, "enabled" ) )
00960     {
00961         media->b_enabled = VLC_TRUE;
00962     }
00963     else if( !strcmp( psz_cmd, "disabled" ) )
00964     {
00965         media->b_enabled = VLC_FALSE;
00966     }
00967     else if( !strcmp( psz_cmd, "mux" ) )
00968     {
00969         if( media->psz_mux ) free( media->psz_mux );
00970         media->psz_mux = NULL;
00971         if( psz_value ) media->psz_mux = strdup( psz_value );
00972     }
00973     else if( !strcmp( psz_cmd, "input" ) )
00974     {
00975         char *input;
00976 
00977         if( psz_value != NULL && strlen(psz_value) > 1 &&
00978             ( psz_value[0] == '\'' || psz_value[0] == '\"' ) &&
00979             ( psz_value[ strlen(psz_value) - 1 ] == '\'' ||
00980               psz_value[ strlen(psz_value) - 1 ] == '\"' )  )
00981         {
00982             input = malloc( strlen(psz_value) - 1 );
00983 
00984             memcpy( input, psz_value + 1, strlen(psz_value) - 2 );
00985             input[ strlen(psz_value) - 2 ] = '\0';
00986         }
00987         else
00988         {
00989             input = strdup( psz_value );
00990         }
00991 
00992         TAB_APPEND( media->i_input, media->input, input );
00993     }
00994     else if( !strcmp( psz_cmd, "inputdel" ) && !strcmp( psz_value, "all" ) )
00995     {
00996         while( media->i_input > 0 )
00997         {
00998             TAB_REMOVE( media->i_input, media->input, media->input[0] );
00999         }
01000     }
01001     else if( !strcmp( psz_cmd, "inputdel" ) )
01002     {
01003         char *input;
01004         int i;
01005 
01006         if( psz_value != NULL && strlen(psz_value) > 1 &&
01007             ( psz_value[0] == '\'' || psz_value[0] == '\"' ) &&
01008             ( psz_value[ strlen(psz_value) - 1 ] == '\'' ||
01009               psz_value[ strlen(psz_value) - 1 ] == '\"' )  )
01010         {
01011             input = malloc( strlen(psz_value) - 1 );
01012 
01013             memcpy( input, psz_value + 1, strlen(psz_value) - 2 );
01014             input[ strlen(psz_value) - 2 ] = '\0';
01015         }
01016         else
01017         {
01018             input = strdup( psz_value );
01019         }
01020 
01021         for( i = 0; i < media->i_input; i++ )
01022         {
01023             if( !strcmp( input, media->input[i] ) )
01024             {
01025                 TAB_REMOVE( media->i_input, media->input, media->input[i] );
01026                 break;
01027             }
01028         }
01029     }
01030     else if( !strcmp( psz_cmd, "inputdeln" ) )
01031     {
01032         int index = atoi( psz_value );
01033         if( index > 0 && index <= media->i_input )
01034         {
01035             TAB_REMOVE( media->i_input, media->input, media->input[index-1] );
01036         }
01037     }
01038     else if( !strcmp( psz_cmd, "output" ) )
01039     {
01040         if( media->psz_output != NULL )
01041         {
01042             free( media->psz_output );
01043         }
01044         media->psz_output = strdup( psz_value );
01045     }
01046     else if( !strcmp( psz_cmd, "option" ) )
01047     {
01048         char *psz_option;
01049         psz_option = strdup( psz_value );
01050 
01051         TAB_APPEND( media->i_option, media->option, psz_option );
01052     }
01053     else
01054     {
01055         return VLC_EGENERIC;
01056     }
01057 
01058     /* Check if we need to create/delete a vod media */
01059     if( media->i_type == VOD_TYPE )
01060     {
01061         if( !media->b_enabled && media->vod_media )
01062         {
01063             vlm->vod->pf_media_del( vlm->vod, media->vod_media );
01064             media->vod_media = 0;
01065         }
01066         else if( media->b_enabled && !media->vod_media && media->i_input )
01067         {
01068             /* Pre-parse the input */
01069             input_thread_t *p_input;
01070             char *psz_output;
01071             int i;
01072 
01073             vlc_input_item_Clean( &media->item );
01074             vlc_input_item_Init( VLC_OBJECT(vlm), &media->item );
01075 
01076             if( media->psz_output )
01077                 asprintf( &psz_output, "%s:description", media->psz_output );
01078             else
01079                 asprintf( &psz_output, "#description" );
01080 
01081             media->item.psz_uri = strdup( media->input[0] );
01082             media->item.ppsz_options = malloc( sizeof( char* ) );
01083             asprintf( &media->item.ppsz_options[0], "sout=%s", psz_output);
01084             media->item.i_options = 1;
01085             for( i = 0; i < media->i_option; i++ )
01086             {
01087                 media->item.i_options++;
01088                 media->item.ppsz_options =
01089                     realloc( media->item.ppsz_options,
01090                              media->item.i_options * sizeof( char* ) );
01091                 media->item.ppsz_options[ media->item.i_options - 1 ] =
01092                     strdup( media->option[i] );
01093             }
01094 
01095             if( (p_input = input_CreateThread( vlm, &media->item ) ) )
01096             {
01097                 while( !p_input->b_eof && !p_input->b_error ) msleep( 100000 );
01098 
01099                 input_StopThread( p_input );
01100                 input_DestroyThread( p_input );
01101                 vlc_object_detach( p_input );
01102                 vlc_object_destroy( p_input );
01103             }
01104             free( psz_output );
01105 
01106             if( media->psz_mux )
01107             {
01108                 input_item_t item;
01109                 es_format_t es, *p_es = &es;
01110                 char fourcc[5];
01111 
01112                 sprintf( fourcc, "%4.4s", media->psz_mux );
01113                 fourcc[0] = tolower(fourcc[0]); fourcc[1] = tolower(fourcc[1]);
01114                 fourcc[2] = tolower(fourcc[2]); fourcc[3] = tolower(fourcc[3]);
01115 
01116                 item = media->item;
01117                 item.i_es = 1;
01118                 item.es = &p_es;
01119                 es_format_Init( &es, VIDEO_ES, *((int *)fourcc) );
01120 
01121                 media->vod_media =
01122                   vlm->vod->pf_media_new( vlm->vod, media->psz_name, &item );
01123                 return VLC_SUCCESS;
01124             }
01125 
01126             media->vod_media =
01127                 vlm->vod->pf_media_new( vlm->vod, media->psz_name,
01128                                         &media->item );
01129         }
01130     }
01131 
01132     return VLC_SUCCESS;
01133 }
01134 
01135 int vlm_MediaControl( vlm_t *vlm, vlm_media_t *media, char *psz_id,
01136                       char *psz_command, char *psz_args )
01137 {
01138     vlm_media_instance_t *p_instance;
01139     int i;
01140 
01141     p_instance = vlm_MediaInstanceSearch( vlm, media, psz_id );
01142 
01143     if( !strcmp( psz_command, "play" ) )
01144     {
01145         if( !media->b_enabled || media->i_input == 0 ) return 0;
01146 
01147         if( !p_instance )
01148         {
01149             p_instance = malloc( sizeof(vlm_media_instance_t) );
01150             if( !p_instance ) return VLC_EGENERIC;
01151             memset( p_instance, 0, sizeof(vlm_media_instance_t) );
01152             vlc_input_item_Init( VLC_OBJECT(vlm), &p_instance->item );
01153             p_instance->p_input = NULL;
01154 
01155             if( media->psz_output != NULL || media->psz_vod_output != NULL )
01156             {
01157                 p_instance->item.ppsz_options = malloc( sizeof( char* ) );
01158                 asprintf( &p_instance->item.ppsz_options[0], "sout=%s%s%s",
01159                           media->psz_output ? media->psz_output : "",
01160                           (media->psz_output && media->psz_vod_output) ?
01161                           ":" : media->psz_vod_output ? "#" : "",
01162                           media->psz_vod_output ? media->psz_vod_output : "" );
01163                 p_instance->item.i_options = 1;
01164             }
01165 
01166             for( i = 0; i < media->i_option; i++ )
01167             {
01168                 p_instance->item.i_options++;
01169                 p_instance->item.ppsz_options =
01170                     realloc( p_instance->item.ppsz_options,
01171                              p_instance->item.i_options * sizeof( char* ) );
01172                 p_instance->item.ppsz_options[p_instance->item.i_options - 1] =
01173                     strdup( media->option[i] );
01174             }
01175 
01176             p_instance->psz_name = psz_id ? strdup( psz_id ) : NULL;
01177             TAB_APPEND( media->i_instance, media->instance, p_instance );
01178         }
01179 
01180         if( psz_args && sscanf(psz_args, "%d", &i) == 1 && i < media->i_input )
01181         {
01182             p_instance->i_index = i;
01183         }
01184 
01185         if( p_instance->item.psz_uri ) free( p_instance->item.psz_uri );
01186         p_instance->item.psz_uri =
01187             strdup( media->input[p_instance->i_index] );
01188 
01189         if( p_instance->p_input )
01190         {
01191             input_StopThread( p_instance->p_input );
01192             input_DestroyThread( p_instance->p_input );
01193             vlc_object_detach( p_instance->p_input );
01194             vlc_object_destroy( p_instance->p_input );
01195         }
01196 
01197         p_instance->p_input = input_CreateThread( vlm, &p_instance->item );
01198         if( !p_instance->p_input )
01199         {
01200             TAB_REMOVE( media->i_instance, media->instance, p_instance );
01201             vlc_input_item_Clean( &p_instance->item );
01202             if( p_instance->psz_name ) free( p_instance->psz_name );
01203         }
01204 
01205         return VLC_SUCCESS;
01206     }
01207 
01208     if( !p_instance ) return VLC_EGENERIC;
01209 
01210     if( !strcmp( psz_command, "seek" ) )
01211     {
01212         vlc_value_t val;
01213         float f_percentage;
01214 
01215         if( psz_args && sscanf( psz_args, "%f", &f_percentage ) == 1 )
01216         {
01217             val.f_float = f_percentage / 100.0 ;
01218             var_Set( p_instance->p_input, "position", val );
01219             return VLC_SUCCESS;
01220         }
01221     }
01222     else if( !strcmp( psz_command, "stop" ) )
01223     {
01224         TAB_REMOVE( media->i_instance, media->instance, p_instance );
01225 
01226         if( p_instance->p_input )
01227         {
01228             input_StopThread( p_instance->p_input );
01229             input_DestroyThread( p_instance->p_input );
01230             vlc_object_detach( p_instance->p_input );
01231             vlc_object_destroy( p_instance->p_input );
01232         }
01233 
01234         vlc_input_item_Clean( &p_instance->item );
01235         if( p_instance->psz_name ) free( p_instance->psz_name );
01236         free( p_instance );
01237 
01238         return VLC_SUCCESS;
01239     }
01240     else if( !strcmp( psz_command, "pause" ) )
01241     {
01242         vlc_value_t val;
01243 
01244         if( !p_instance->p_input ) return VLC_SUCCESS;
01245 
01246         var_Get( p_instance->p_input, "state", &val );
01247 
01248         if( val.i_int == PAUSE_S ) val.i_int = PLAYING_S;
01249         else val.i_int = PAUSE_S;
01250         var_Set( p_instance->p_input, "state", val );
01251 
01252         return VLC_SUCCESS;
01253     }
01254 
01255     return VLC_EGENERIC;
01256 }
01257 
01258 /*****************************************************************************
01259  * Schedule handling
01260  *****************************************************************************/
01261 static int64_t vlm_Date()
01262 {
01263 #ifdef WIN32
01264     struct timeb tm;
01265     ftime( &tm );
01266     return ((int64_t)tm.time) * 1000000 + ((int64_t)tm.millitm) * 1000;
01267 #else
01268     return mdate();
01269 #endif
01270 }
01271 
01272 vlm_schedule_t *vlm_ScheduleNew( vlm_t *vlm, char *psz_name )
01273 {
01274     vlm_schedule_t *p_sched = malloc( sizeof( vlm_schedule_t ) );
01275 
01276     if( !p_sched )
01277     {
01278         return NULL;
01279     }
01280 
01281     if( !psz_name )
01282     {
01283         return NULL;
01284     }
01285 
01286     p_sched->psz_name = strdup( psz_name );
01287     p_sched->b_enabled = VLC_FALSE;
01288     p_sched->i_command = 0;
01289     p_sched->command = NULL;
01290     p_sched->i_date = 0;
01291     p_sched->i_period = 0;
01292     p_sched->i_repeat = -1;
01293 
01294     TAB_APPEND( vlm->i_schedule, vlm->schedule, p_sched );
01295 
01296     return p_sched;
01297 }
01298 
01299 /* for now, simple delete. After, del with options (last arg) */
01300 void vlm_ScheduleDelete( vlm_t *vlm, vlm_schedule_t *sched,
01301                          char *psz_name )
01302 {
01303     if( sched == NULL ) return;
01304 
01305     TAB_REMOVE( vlm->i_schedule, vlm->schedule, sched );
01306 
01307     if( vlm->i_schedule == 0 && vlm->schedule ) free( vlm->schedule );
01308     free( sched->psz_name );
01309     while( sched->i_command-- ) free( sched->command[sched->i_command] );
01310     free( sched );
01311 }
01312 
01313 static vlm_schedule_t *vlm_ScheduleSearch( vlm_t *vlm, char *psz_name )
01314 {
01315     int i;
01316 
01317     for( i = 0; i < vlm->i_schedule; i++ )
01318     {
01319         if( strcmp( psz_name, vlm->schedule[i]->psz_name ) == 0 )
01320         {
01321             return vlm->schedule[i];
01322         }
01323     }
01324 
01325     return NULL;
01326 }
01327 
01328 /* Ok, setup schedule command will be able to support only one (argument value) at a time  */
01329 int vlm_ScheduleSetup( vlm_schedule_t *schedule, char *psz_cmd,
01330                        char *psz_value )
01331 {
01332     if( !strcmp( psz_cmd, "enabled" ) )
01333     {
01334         schedule->b_enabled = VLC_TRUE;
01335     }
01336     else if( !strcmp( psz_cmd, "disabled" ) )
01337     {
01338         schedule->b_enabled = VLC_FALSE;
01339     }
01340 #if !defined( UNDER_CE )
01341     else if( !strcmp( psz_cmd, "date" ) )
01342     {
01343         struct tm time;
01344         char *p;
01345         time_t date;
01346 
01347         time.tm_sec = 0;         /* seconds */
01348         time.tm_min = 0;         /* minutes */
01349         time.tm_hour = 0;        /* hours */
01350         time.tm_mday = 0;        /* day of the month */
01351         time.tm_mon = 0;         /* month */
01352         time.tm_year = 0;        /* year */
01353         time.tm_wday = 0;        /* day of the week */
01354         time.tm_yday = 0;        /* day in the year */
01355         time.tm_isdst = -1;       /* daylight saving time */
01356 
01357         /* date should be year/month/day-hour:minutes:seconds */
01358         p = strchr( psz_value, '-' );
01359 
01360         if( !strcmp( psz_value, "now" ) )
01361         {
01362             schedule->i_date = 0;
01363         }
01364         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 */
01365         {
01366             return 1;
01367         }
01368         else
01369         {
01370             int i,j,k;
01371 
01372             switch( sscanf( p + 1, "%d:%d:%d", &i, &j, &k ) )
01373             {
01374                 case 1:
01375                     time.tm_sec = i;
01376                     break;
01377                 case 2:
01378                     time.tm_min = i;
01379                     time.tm_sec = j;
01380                     break;
01381                 case 3:
01382                     time.tm_hour = i;
01383                     time.tm_min = j;
01384                     time.tm_sec = k;
01385                     break;
01386                 default:
01387                     return 1;
01388             }
01389 
01390             *p = '\0';
01391 
01392             switch( sscanf( psz_value, "%d/%d/%d", &i, &j, &k ) )
01393             {
01394                 case 1:
01395                     time.tm_mday = i;
01396                     break;
01397                 case 2:
01398                     time.tm_mon = i - 1;
01399                     time.tm_mday = j;
01400                     break;
01401                 case 3:
01402                     time.tm_year = i - 1900;
01403                     time.tm_mon = j - 1;
01404                     time.tm_mday = k;
01405                     break;
01406                 default:
01407                     return 1;
01408             }
01409 
01410             date = mktime( &time );
01411             schedule->i_date = ((mtime_t) date) * 1000000;
01412         }
01413     }
01414     else if( !strcmp( psz_cmd, "period" ) )
01415     {
01416         struct tm time;
01417         char *p;
01418         char *psz_time = NULL, *psz_date = NULL;
01419         time_t date;
01420         int i,j,k;
01421 
01422         /* First, if date or period are modified, repeat should be equal to -1 */
01423         schedule->i_repeat = -1;
01424 
01425         time.tm_sec = 0;         /* seconds */
01426         time.tm_min = 0;         /* minutes */
01427         time.tm_hour = 0;        /* hours */
01428         time.tm_mday = 0;        /* day of the month */
01429         time.tm_mon = 0;         /* month */
01430         time.tm_year = 0;        /* year */
01431         time.tm_wday = 0;        /* day of the week */
01432         time.tm_yday = 0;        /* day in the year */
01433         time.tm_isdst = -1;       /* daylight saving time */
01434 
01435         /* date should be year/month/day-hour:minutes:seconds */
01436         p = strchr( psz_value, '-' );
01437         if( p )
01438         {
01439             psz_date = psz_value;
01440             psz_time = p + 1;
01441 
01442             *p = '\0';
01443         }
01444         else
01445         {
01446             psz_time = psz_value;
01447         }
01448 
01449 
01450         switch( sscanf( psz_time, "%d:%d:%d", &i, &j, &k ) )
01451         {
01452             case 1:
01453                 time.tm_sec = i;
01454                 break;
01455             case 2:
01456                 time.tm_min = i;
01457                 time.tm_sec = j;
01458                 break;
01459             case 3:
01460                 time.tm_hour = i;
01461                 time.tm_min = j;
01462                 time.tm_sec = k;
01463                 break;
01464             default:
01465                 return 1;
01466         }
01467         if( psz_date )
01468         {
01469             switch( sscanf( psz_date, "%d/%d/%d", &i, &j, &k ) )
01470             {
01471                 case 1:
01472                     time.tm_mday = i;
01473                     break;
01474                 case 2:
01475                     time.tm_mon = i;
01476                     time.tm_mday = j;
01477                     break;
01478                 case 3:
01479                     time.tm_year = i;
01480                     time.tm_mon = j;
01481                     time.tm_mday = k;
01482                     break;
01483                 default:
01484                     return 1;
01485             }
01486         }
01487 
01488         /* ok, that's stupid... who is going to schedule streams every 42 years ? */
01489         date = (((( time.tm_year * 12 + time.tm_mon ) * 30 + time.tm_mday ) * 24 + time.tm_hour ) * 60 + time.tm_min ) * 60 + time.tm_sec ;
01490         schedule->i_period = ((mtime_t) date) * 1000000;
01491     }
01492 #endif /* UNDER_CE */
01493     else if( !strcmp( psz_cmd, "repeat" ) )
01494     {
01495         int i;
01496 
01497         if( sscanf( psz_value, "%d", &i ) == 1 )
01498         {
01499             schedule->i_repeat = i;
01500         }
01501         else
01502         {
01503             return 1;
01504         }
01505     }
01506     else if( !strcmp( psz_cmd, "append" ) )
01507     {
01508         char *command = strdup( psz_value );
01509 
01510         TAB_APPEND( schedule->i_command, schedule->command, command );
01511     }
01512     else
01513     {
01514         return 1;
01515     }
01516     return 0;
01517 }
01518 
01519 /*****************************************************************************
01520  * Message handling functions
01521  *****************************************************************************/
01522 static vlm_message_t *vlm_MessageNew( char *psz_name,
01523                                       const char *psz_format, ... )
01524 {
01525     vlm_message_t *p_message;
01526     va_list args;
01527 
01528     if( !psz_name ) return 0;
01529 
01530     p_message = malloc( sizeof(vlm_message_t) );
01531     if( !p_message)
01532     {
01533         return NULL;
01534     }
01535 
01536     p_message->psz_value = 0;
01537 
01538     if( psz_format )
01539     {
01540         va_start( args, psz_format );
01541         if( vasprintf( &p_message->psz_value, psz_format, args ) < 0 )
01542         {
01543             va_end( args );
01544             free( p_message );
01545             return 0;
01546         }
01547         va_end( args );
01548     }
01549 
01550     p_message->psz_name = strdup( psz_name );
01551     p_message->i_child = 0;
01552     p_message->child = NULL;
01553 
01554     return p_message;
01555 }
01556 
01557 void vlm_MessageDelete( vlm_message_t *p_message )
01558 {
01559     if( p_message->psz_name ) free( p_message->psz_name );
01560     if( p_message->psz_value ) free( p_message->psz_value );
01561     while( p_message->i_child-- )
01562         vlm_MessageDelete( p_message->child[p_message->i_child] );
01563     if( p_message->child ) free( p_message->child );
01564     free( p_message );
01565 }
01566 
01567 /* Add a child */
01568 static vlm_message_t *vlm_MessageAdd( vlm_message_t *p_message,
01569                                       vlm_message_t *p_child )
01570 {
01571     if( p_message == NULL ) return NULL;
01572 
01573     if( p_child )
01574     {
01575         TAB_APPEND( p_message->i_child, p_message->child, p_child );
01576     }
01577 
01578     return p_child;
01579 }
01580 
01581 /*****************************************************************************
01582  * Misc utility functions
01583  *****************************************************************************/
01584 static vlm_message_t *vlm_Show( vlm_t *vlm, vlm_media_t *media,
01585                                 vlm_schedule_t *schedule, char *psz_filter )
01586 {
01587     if( media != NULL )
01588     {
01589         int i;
01590         vlm_message_t *msg;
01591         vlm_message_t *msg_media;
01592         vlm_message_t *msg_child;
01593 
01594         msg = vlm_MessageNew( "show", NULL );
01595         msg_media = vlm_MessageAdd( msg, vlm_MessageNew( media->psz_name, 0 ));
01596 
01597         vlm_MessageAdd( msg_media,
01598                         vlm_MessageNew( "type", media->i_type == VOD_TYPE ?
01599                                         "vod" : "broadcast" ) );
01600         vlm_MessageAdd( msg_media,
01601                         vlm_MessageNew( "enabled", media->b_enabled ?
01602                                         "yes" : "no" ) );
01603 
01604         vlm_MessageAdd( msg_media,
01605                         vlm_MessageNew( "loop", media->b_loop ?
01606                                         "yes" : "no" ) );
01607 
01608         if( media->i_type == VOD_TYPE && media->psz_mux )
01609             vlm_MessageAdd( msg_media,
01610                             vlm_MessageNew( "mux", media->psz_mux ) );
01611 
01612         msg_child = vlm_MessageAdd( msg_media,
01613                                     vlm_MessageNew( "inputs", NULL ) );
01614 
01615         for( i = 0; i < media->i_input; i++ )
01616         {
01617             vlm_MessageAdd( msg_child,
01618                             vlm_MessageNew( media->input[i], NULL ) );
01619         }
01620 
01621         vlm_MessageAdd( msg_media,
01622                         vlm_MessageNew( "output", media->psz_output ?
01623                                         media->psz_output : "" ) );
01624 
01625         msg_child = vlm_MessageAdd( msg_media, vlm_MessageNew( "options", 0 ));
01626 
01627         for( i = 0; i < media->i_option; i++ )
01628         {
01629             vlm_MessageAdd( msg_child, vlm_MessageNew( media->option[i], 0 ) );
01630         }
01631 
01632         msg_child = vlm_MessageAdd( msg_media,
01633                                     vlm_MessageNew( "instances", NULL ) );
01634 
01635         for( i = 0; i < media->i_instance; i++ )
01636         {
01637             vlm_media_instance_t *p_instance = media->instance[i];
01638             vlc_value_t val;
01639 
01640             if( !p_instance->p_input ) val.i_int = END_S;
01641             else var_Get( p_instance->p_input, "state", &val );
01642 
01643             vlm_MessageAdd( msg_child,
01644                 vlm_MessageNew( p_instance->psz_name ?
01645                                 p_instance->psz_name : "default",
01646                                 val.i_int == PLAYING_S ? "playing" :
01647                                 val.i_int == PAUSE_S ? "paused" :
01648                                 "stopped" ) );
01649         }
01650 
01651         return msg;
01652 
01653     }
01654 
01655     else if( schedule != NULL )
01656     {
01657         int i;
01658         vlm_message_t *msg;
01659         vlm_message_t *msg_schedule;
01660         vlm_message_t *msg_child;
01661         char buffer[100];
01662 
01663         msg = vlm_MessageNew( "show", NULL );
01664         msg_schedule =
01665             vlm_MessageAdd( msg, vlm_MessageNew( schedule->psz_name, 0 ) );
01666 
01667         vlm_MessageAdd( msg_schedule, vlm_MessageNew("type", "schedule") );
01668 
01669         vlm_MessageAdd( msg_schedule,
01670                         vlm_MessageNew( "enabled", schedule->b_enabled ?
01671                                         "yes" : "no" ) );
01672 
01673 #if !defined( UNDER_CE )
01674         if( schedule->i_date != 0 )
01675         {
01676             struct tm date;
01677             time_t i_time = (time_t)( schedule->i_date / 1000000 );
01678             char *psz_date;
01679 
01680 #ifdef HAVE_LOCALTIME_R
01681             localtime_r( &i_time, &date);
01682 #else
01683             struct tm *p_date = localtime( &i_time );
01684             date = *p_date;
01685 #endif
01686 
01687             asprintf( &psz_date, "%d/%d/%d-%d:%d:%d",
01688                       date.tm_year + 1900, date.tm_mon + 1, date.tm_mday,
01689                       date.tm_hour, date.tm_min, date.tm_sec );
01690 
01691             vlm_MessageAdd( msg_schedule,
01692                             vlm_MessageNew( "date", psz_date ) );
01693             free( psz_date );
01694         }
01695         else
01696         {
01697             vlm_MessageAdd( msg_schedule, vlm_MessageNew("date", "now") );
01698         }
01699 
01700         if( schedule->i_period != 0 )
01701         {
01702             time_t i_time = (time_t) ( schedule->i_period / 1000000 );
01703             struct tm date;
01704 
01705             date.tm_sec = (int)( i_time % 60 );
01706             i_time = i_time / 60;
01707             date.tm_min = (int)( i_time % 60 );
01708             i_time = i_time / 60;
01709             date.tm_hour = (int)( i_time % 24 );
01710             i_time = i_time / 24;
01711             date.tm_mday = (int)( i_time % 30 );
01712             i_time = i_time / 30;
01713             /* okay, okay, months are not always 30 days long */
01714             date.tm_mon = (int)( i_time % 12 );
01715             i_time = i_time / 12;
01716             date.tm_year = (int)i_time;
01717 
01718             sprintf( buffer, "%d/%d/%d-%d:%d:%d", date.tm_year, date.tm_mon,
01719                      date.tm_mday, date.tm_hour, date.tm_min, date.tm_sec);
01720 
01721             vlm_MessageAdd( msg_schedule, vlm_MessageNew("period", buffer) );
01722         }
01723         else
01724         {
01725             vlm_MessageAdd( msg_schedule, vlm_MessageNew("period", "0") );
01726         }
01727 #endif /* UNDER_CE */
01728 
01729         sprintf( buffer, "%d", schedule->i_repeat );
01730         vlm_MessageAdd( msg_schedule, vlm_MessageNew( "repeat", buffer ) );
01731 
01732         msg_child =
01733             vlm_MessageAdd( msg_schedule, vlm_MessageNew("commands", 0) );
01734 
01735         for( i = 0; i < schedule->i_command; i++ )
01736         {
01737            vlm_MessageAdd( msg_child,
01738                            vlm_MessageNew( schedule->command[i], NULL ) );
01739         }
01740 
01741         return msg;
01742 
01743     }
01744 
01745     else if( psz_filter && !strcmp( psz_filter, "media" ) )
01746     {
01747         int i, j;
01748         vlm_message_t *msg;
01749         vlm_message_t *msg_child;
01750         int i_vod = 0, i_broadcast = 0;
01751         char *psz_count;
01752 
01753         for( i = 0; i < vlm->i_media; i++ )
01754         {
01755             if( vlm->media[i]->i_type == VOD_TYPE )
01756                 i_vod ++;
01757             else
01758                 i_broadcast ++;
01759         }
01760 
01761         asprintf( &psz_count, "( %d broadcast - %d vod )", i_broadcast, i_vod);
01762 
01763         msg = vlm_MessageNew( "show", NULL );
01764         msg_child = vlm_MessageAdd( msg, vlm_MessageNew( "media", psz_count ) );
01765         free( psz_count );
01766 
01767         for( i = 0; i < vlm->i_media; i++ )
01768         {
01769             vlm_media_t *m = vlm->media[i];
01770             vlm_message_t *msg_media, *msg_instance;
01771 
01772             msg_media = vlm_MessageAdd( msg_child,
01773                                         vlm_MessageNew( m->psz_name, 0 ) );
01774 
01775             vlm_MessageAdd( msg_media,
01776                             vlm_MessageNew( "type", m->i_type == VOD_TYPE ?
01777                                             "vod" : "broadcast" ) );
01778 
01779             vlm_MessageAdd( msg_media,
01780                             vlm_MessageNew( "enabled", m->b_enabled ?
01781                                             "yes" : "no" ) );
01782 
01783             if( m->i_type == VOD_TYPE && m->psz_mux )
01784                 vlm_MessageAdd( msg_media,
01785                                 vlm_MessageNew( "mux", m->psz_mux ) );
01786 
01787             msg_instance = vlm_MessageAdd( msg_media,
01788                                            vlm_MessageNew( "instances", 0 ) );
01789 
01790             for( j = 0; j < m->i_instance; j++ )
01791             {
01792                 vlm_media_instance_t *p_instance = m->instance[j];
01793                 vlc_value_t val;
01794 
01795                 if( !p_instance->p_input ) val.i_int = END_S;
01796                 else var_Get( p_instance->p_input, "state", &val );
01797 
01798                 vlm_MessageAdd( msg_instance,
01799                     vlm_MessageNew( p_instance->psz_name ?
01800                                     p_instance->psz_name : "default",
01801                                     val.i_int == PLAYING_S ? "playing" :
01802                                     val.i_int == PAUSE_S ? "paused" :
01803                                     "stopped" ) );
01804             }
01805         }
01806 
01807         return msg;
01808     }
01809 
01810     else if( psz_filter && !strcmp( psz_filter, "schedule" ) )
01811     {
01812         int i;
01813         vlm_message_t *msg;
01814         vlm_message_t *msg_child;
01815 
01816         msg = vlm_MessageNew( "show", NULL );
01817         msg_child = vlm_MessageAdd( msg, vlm_MessageNew( "schedule", NULL ) );
01818 
01819         for( i = 0; i < vlm->i_schedule; i++ )
01820         {
01821             vlm_schedule_t *s = vlm->schedule[i];
01822             vlm_message_t *msg_schedule;
01823             mtime_t i_time, i_next_date;
01824 
01825             msg_schedule = vlm_MessageAdd( msg_child,
01826                                            vlm_MessageNew( s->psz_name, 0 ) );
01827             vlm_MessageAdd( msg_schedule,
01828                             vlm_MessageNew( "enabled", s->b_enabled ?
01829                                             "yes" : "no" ) );
01830 
01831             if( !s->b_enabled ) return msg;
01832 
01833 
01834             vlm_MessageAdd( msg_schedule,
01835                             vlm_MessageNew( "enabled", "yes" ) );
01836 
01837             /* calculate next date */
01838             i_time = vlm_Date();
01839             i_next_date = s->i_date;
01840 
01841             if( s->i_period != 0 )
01842             {
01843                 int j = 0;
01844                 while( s->i_date + j * s->i_period <= i_time &&
01845                        s->i_repeat > j )
01846                 {
01847                     j++;
01848                 }
01849 
01850                 i_next_date = s->i_date + j * s->i_period;
01851             }
01852 
01853             if( i_next_date > i_time )
01854             {
01855                 time_t i_date = (time_t) (i_next_date / 1000000) ;
01856 
01857 #if !defined( UNDER_CE )
01858 #ifdef HAVE_CTIME_R
01859                 char psz_date[500];
01860                 ctime_r( &i_date, psz_date );
01861 #else
01862                 char *psz_date = ctime( &i_date );
01863 #endif
01864 
01865                 vlm_MessageAdd( msg_schedule,
01866                                 vlm_MessageNew( "next launch", psz_date ) );
01867 #endif
01868             }
01869         }
01870 
01871         return msg;
01872     }
01873 
01874     else if( psz_filter == NULL && media == NULL && schedule == NULL )
01875     {
01876         vlm_message_t *show1 = vlm_Show( vlm, NULL, NULL, "media" );
01877         vlm_message_t *show2 = vlm_Show( vlm, NULL, NULL, "schedule" );
01878 
01879         vlm_MessageAdd( show1, show2->child[0] );
01880 
01881         /* We must destroy the parent node "show" of show2
01882          * and not the children */
01883         free( show2->psz_name );
01884         free( show2 );
01885 
01886         return show1;
01887     }
01888 
01889     else
01890     {
01891         return vlm_MessageNew( "show", NULL );
01892     }
01893 }
01894 
01895 static vlm_message_t *vlm_Help( vlm_t *vlm, char *psz_filter )
01896 {
01897     vlm_message_t *message, *message_child;
01898 
01899 #define MessageAdd( a ) \
01900         vlm_MessageAdd( message, vlm_MessageNew( a, NULL ) );
01901 #define MessageAddChild( a ) \
01902         vlm_MessageAdd( message_child, vlm_MessageNew( a, NULL ) );
01903 
01904     if( psz_filter == NULL )
01905     {
01906         message = vlm_MessageNew( "help", NULL );
01907 
01908         message_child = MessageAdd( "Commands Syntax:" );
01909         MessageAddChild( "new (name) vod|broadcast|schedule [properties]" );
01910         MessageAddChild( "setup (name) (properties)" );
01911         MessageAddChild( "show [(name)|media|schedule]" );
01912         MessageAddChild( "del (name)|all|media|schedule" );
01913         MessageAddChild( "control (name) [instance_name] (command)" );
01914         MessageAddChild( "save (config_file)" );
01915         MessageAddChild( "load (config_file)" );
01916 
01917         message_child = MessageAdd( "Media Proprieties Syntax:" );
01918         MessageAddChild( "input (input_name)" );
01919         MessageAddChild( "inputdel (input_name)|all" );
01920         MessageAddChild( "inputdeln input_number" );
01921         MessageAddChild( "output (output_name)" );
01922         MessageAddChild( "option (option_name)[=value]" );
01923         MessageAddChild( "enabled|disabled" );
01924         MessageAddChild( "loop|unloop (broadcast only)" );
01925         MessageAddChild( "mux (mux_name)" );
01926 
01927         message_child = MessageAdd( "Schedule Proprieties Syntax:" );
01928         MessageAddChild( "enabled|disabled" );
01929         MessageAddChild( "append (command_until_rest_of_the_line)" );
01930         MessageAddChild( "date (year)/(month)/(day)-(hour):(minutes):"
01931                          "(seconds)|now" );
01932         MessageAddChild( "period (years_aka_12_months)/(months_aka_30_days)/"
01933                          "(days)-(hours):(minutes):(seconds)" );
01934         MessageAddChild( "repeat (number_of_repetitions)" );
01935 
01936         message_child = MessageAdd( "Control Commands Syntax:" );
01937         MessageAddChild( "play" );
01938         MessageAddChild( "pause" );
01939         MessageAddChild( "stop" );
01940         MessageAddChild( "seek (percentage)" );
01941 
01942         return message;
01943     }
01944 
01945     return vlm_MessageNew( "help", NULL );
01946 }
01947 
01948 /*****************************************************************************
01949  * Config handling functions
01950  *****************************************************************************/
01951 static int Load( vlm_t *vlm, char *file )
01952 {
01953     char *pf = file;
01954 
01955     while( *pf != '\0' )
01956     {
01957         vlm_message_t *message = NULL;
01958         int i_end = 0;
01959 
01960         while( pf[i_end] != '\n' && pf[i_end] != '\0' && pf[i_end] != '\r' )
01961         {
01962             i_end++;
01963         }
01964 
01965         if( pf[i_end] == '\r' || pf[i_end] == '\n' )
01966         {
01967             pf[i_end] = '\0';
01968             i_end++;
01969             if( pf[i_end] == '\n' ) i_end++;
01970         }
01971 
01972         if( *pf && ExecuteCommand( vlm, pf, &message ) )
01973         {
01974             if( message ) free( message );
01975             return 1;
01976         }
01977         if( message ) free( message );
01978 
01979         pf += i_end;
01980     }
01981 
01982     return 0;
01983 }
01984 
01985 static char *Save( vlm_t *vlm )
01986 {
01987     char *save = NULL;
01988     char *p;
01989     int i,j;
01990     int i_length = 0;
01991 
01992     for( i = 0; i < vlm->i_media; i++ )
01993     {
01994         vlm_media_t *media = vlm->media[i];
01995 
01996         if( media->i_type == VOD_TYPE )
01997         {
01998             i_length += strlen( "new  vod " ) + strlen(media->psz_name);
01999         }
02000         else
02001         {
02002             i_length += strlen( "new  broadcast " ) + strlen(media->psz_name);
02003         }
02004 
02005         if( media->b_enabled == VLC_TRUE )
02006         {
02007             i_length += strlen( "enabled" );
02008         }
02009         else
02010         {
02011             i_length += strlen( "disabled" );
02012         }
02013 
02014         if( media->b_loop == VLC_TRUE )
02015         {
02016             i_length += strlen( " loop\n" );
02017         }
02018         else
02019         {
02020             i_length += strlen( "\n" );
02021         }
02022 
02023         for( j = 0; j < media->i_input; j++ )
02024         {
02025             i_length += strlen( "setup  input \"\"\n" ) +
02026                 strlen( media->psz_name ) + strlen( media->input[j] );
02027         }
02028 
02029         if( media->psz_output != NULL )
02030         {
02031             i_length += strlen(media->psz_name) + strlen(media->psz_output) +
02032                 strlen( "setup  output \n" );
02033         }
02034 
02035         for( j=0 ; j < media->i_option ; j++ )
02036         {
02037             i_length += strlen(media->psz_name) + strlen(media->option[j]) +
02038                 strlen("setup  option \n");
02039         }
02040     }
02041 
02042     for( i = 0; i < vlm->i_schedule; i++ )
02043     {
02044         vlm_schedule_t *schedule = vlm->schedule[i];
02045 
02046         i_length += strlen( "new  schedule " ) + strlen( schedule->psz_name );
02047 
02048         if( schedule->b_enabled == VLC_TRUE )
02049         {
02050             i_length += strlen( "date //-:: enabled\n" ) + 14;
02051         }
02052         else
02053         {
02054             i_length += strlen( "date //-:: disabled\n" ) + 14;
02055         }
02056 
02057 
02058         if( schedule->i_period != 0 )
02059         {
02060             i_length += strlen( "setup  " ) + strlen( schedule->psz_name ) +
02061                 strlen( "period //-::\n" ) + 14;
02062         }
02063 
02064         if( schedule->i_repeat >= 0 )
02065         {
02066             char buffer[12];
02067 
02068             sprintf( buffer, "%d", schedule->i_repeat );
02069             i_length += strlen( "setup  repeat \n" ) +
02070                 strlen( schedule->psz_name ) + strlen( buffer );
02071         }
02072         else
02073         {
02074             i_length++;
02075         }
02076 
02077         for( j = 0; j < schedule->i_command; j++ )
02078         {
02079             i_length += strlen( "setup  append \n" ) +
02080                 strlen( schedule->psz_name ) + strlen( schedule->command[j] );
02081         }
02082 
02083     }
02084 
02085     /* Don't forget the '\0' */
02086     i_length++;
02087     /* now we have the length of save */
02088 
02089     p = save = malloc( i_length );
02090     *save = '\0';
02091 
02092     /* finally we can write in it */
02093     for( i = 0; i < vlm->i_media; i++ )
02094     {
02095         vlm_media_t *media = vlm->media[i];
02096 
02097         if( media->i_type == VOD_TYPE )
02098         {
02099             p += sprintf( p, "new %s vod ", media->psz_name);
02100         }
02101         else
02102         {
02103             p += sprintf( p, "new %s broadcast ", media->psz_name);
02104         }
02105 
02106         if( media->b_enabled == VLC_TRUE )
02107         {
02108             p += sprintf( p, "enabled" );
02109         }
02110         else
02111         {
02112             p += sprintf( p, "disabled" );
02113         }
02114 
02115         if( media->b_loop == VLC_TRUE )
02116         {
02117             p += sprintf( p, " loop\n" );
02118         }
02119         else
02120         {
02121             p += sprintf( p, "\n" );
02122         }
02123 
02124         for( j = 0; j < media->i_input; j++ )
02125         {
02126             p += sprintf( p, "setup %s input \"%s\"\n", media->psz_name,
02127                           media->input[j] );
02128         }
02129 
02130         if( media->psz_output != NULL )
02131         {
02132             p += sprintf( p, "setup %s output %s\n", media->psz_name,
02133                           media->psz_output );
02134         }
02135 
02136         for( j = 0; j < media->i_option; j++ )
02137         {
02138             p += sprintf( p, "setup %s option %s\n", media->psz_name,
02139                           media->option[j] );
02140         }
02141     }
02142 
02143     /* and now, the schedule scripts */
02144 #if !defined( UNDER_CE )
02145     for( i = 0; i < vlm->i_schedule; i++ )
02146     {
02147         vlm_schedule_t *schedule = vlm->schedule[i];
02148         struct tm date;
02149         time_t i_time = (time_t) ( schedule->i_date / 1000000 );
02150 
02151 #ifdef HAVE_LOCALTIME_R
02152         localtime_r( &i_time, &date);
02153 #else
02154         struct tm *p_date = localtime( &i_time );
02155         date = *p_date;
02156 #endif
02157 
02158         p += sprintf( p, "new %s schedule ", schedule->psz_name);
02159 
02160         if( schedule->b_enabled == VLC_TRUE )
02161         {
02162             p += sprintf( p, "date %d/%d/%d-%d:%d:%d enabled\n",
02163                           date.tm_year + 1900, date.tm_mon + 1, date.tm_mday,
02164                           date.tm_hour, date.tm_min, date.tm_sec );
02165         }
02166         else
02167         {
02168             p += sprintf( p, "date %d/%d/%d-%d:%d:%d disabled\n",
02169                           date.tm_year + 1900, date.tm_mon + 1, date.tm_mday,
02170                           date.tm_hour, date.tm_min, date.tm_sec);
02171         }
02172 
02173         if( schedule->i_period != 0 )
02174         {
02175             p += sprintf( p, "setup %s ", schedule->psz_name );
02176 
02177             i_time = (time_t) ( schedule->i_period / 1000000 );
02178 
02179             date.tm_sec = (int)( i_time % 60 );
02180             i_time = i_time / 60;
02181             date.tm_min = (int)( i_time % 60 );
02182             i_time = i_time / 60;
02183             date.tm_hour = (int)( i_time % 24 );
02184             i_time = i_time / 24;
02185             date.tm_mday = (int)( i_time % 30 );
02186             i_time = i_time / 30;
02187             /* okay, okay, months are not always 30 days long */
02188             date.tm_mon = (int)( i_time % 12 );
02189             i_time = i_time / 12;
02190             date.tm_year = (int)i_time;
02191 
02192             p += sprintf( p, "period %d/%d/%d-%d:%d:%d\n",
02193                           date.tm_year, date.tm_mon, date.tm_mday,
02194                           date.tm_hour, date.tm_min, date.tm_sec);
02195         }
02196 
02197         if( schedule->i_repeat >= 0 )
02198         {
02199             p += sprintf( p, "setup %s repeat %d\n",
02200                           schedule->psz_name, schedule->i_repeat );
02201         }
02202         else
02203         {
02204             p += sprintf( p, "\n" );
02205         }
02206 
02207         for( j = 0; j < schedule->i_command; j++ )
02208         {
02209             p += sprintf( p, "setup %s append %s\n",
02210                           schedule->psz_name, schedule->command[j] );
02211         }
02212 
02213     }
02214 #endif /* UNDER_CE */
02215 
02216     return save;
02217 }
02218 
02219 /*****************************************************************************
02220  * Manage:
02221  *****************************************************************************/
02222 int vlm_MediaVodControl( void *p_private, vod_media_t *p_vod_media,
02223                          char *psz_id, int i_query, va_list args )
02224 {
02225     vlm_t *vlm = (vlm_t *)p_private;
02226     int i, i_ret = VLC_EGENERIC;
02227 
02228     if( !p_private || !p_vod_media ) return VLC_EGENERIC;
02229 
02230     vlc_mutex_lock( &vlm->lock );
02231 
02232     /* Find media */
02233     for( i = 0; i < vlm->i_media; i++ )
02234     {
02235         if( p_vod_media == vlm->media[i]->vod_media ) break;
02236     }
02237 
02238     if( i == vlm->i_media )
02239     {
02240         vlc_mutex_unlock( &vlm->lock );
02241         return VLC_EGENERIC;
02242     }
02243 
02244     switch( i_query )
02245     {
02246     case VOD_MEDIA_PLAY:
02247         vlm->media[i]->psz_vod_output = (char *)va_arg( args, char * );
02248         i_ret = vlm_MediaControl( vlm, vlm->media[i], psz_id, "play", 0 );
02249         vlm->media[i]->psz_vod_output = 0;
02250         break;
02251 
02252     case VOD_MEDIA_PAUSE:
02253         i_ret = vlm_MediaControl( vlm, vlm->media[i], psz_id, "pause", 0 );
02254         break;
02255 
02256     case VOD_MEDIA_STOP:
02257         i_ret = vlm_MediaControl( vlm, vlm->media[i], psz_id, "stop", 0 );
02258         break;
02259 
02260     case VOD_MEDIA_SEEK:
02261     {
02262         double f_pos = (double)va_arg( args, double );
02263         char psz_pos[50];
02264 
02265         sprintf( psz_pos, "%f", f_pos );
02266         i_ret = vlm_MediaControl( vlm, vlm->media[i], psz_id, "seek", psz_pos);
02267         break;
02268     }
02269 
02270     default:
02271         break;
02272     }
02273 
02274     vlc_mutex_unlock( &vlm->lock );
02275 
02276     return i_ret;
02277 }
02278 
02279 /*****************************************************************************
02280  * Manage:
02281  *****************************************************************************/
02282 static int Manage( vlc_object_t* p_object )
02283 {
02284     vlm_t *vlm = (vlm_t*)p_object;
02285     int i, j;
02286     mtime_t i_lastcheck;
02287     mtime_t i_time;
02288 
02289     i_lastcheck = vlm_Date();
02290 
02291     msleep( 100000 );
02292 
02293     while( !vlm->b_die )
02294     {
02295         vlc_mutex_lock( &vlm->lock );
02296 
02297         /* destroy the inputs that wants to die, and launch the next input */
02298         for( i = 0; i < vlm->i_media; i++ )
02299         {
02300             vlm_media_t *p_media = vlm->media[i];
02301 
02302             for( j = 0; j < p_media->i_instance; j++ )
02303             {
02304                 vlm_media_instance_t *p_instance = p_media->instance[j];
02305 
02306                 if( !p_instance->p_input ||
02307                     ( !p_instance->p_input->b_eof &&
02308                       !p_instance->p_input->b_error ) ) continue;
02309 
02310                 input_StopThread( p_instance->p_input );
02311                 input_DestroyThread( p_instance->p_input );
02312                 vlc_object_detach( p_instance->p_input );
02313                 vlc_object_destroy( p_instance->p_input );
02314 
02315                 p_instance->i_index++;
02316                 if( p_instance->i_index == p_media->i_input &&
02317                     p_media->b_loop ) p_instance->i_index = 0;
02318 
02319                 if( p_instance->i_index < p_media->i_input )
02320                 {
02321                     /* FIXME, find a way to select the right instance */
02322                     char buffer[12];
02323                     sprintf( buffer, "%d", p_instance->i_index );
02324                     vlm_MediaControl( vlm, p_media, p_instance->psz_name,
02325                                       "play", buffer );
02326                 }
02327                 else
02328                 {
02329                     if( vlm_MediaControl( vlm, p_media, p_instance->psz_name,
02330                                           "stop", 0 ) == VLC_SUCCESS ) i--;
02331                 }
02332             }
02333         }
02334 
02335         /* scheduling */
02336         i_time = vlm_Date();
02337 
02338         for( i = 0; i < vlm->i_schedule; i++ )
02339         {
02340             mtime_t i_real_date = vlm->schedule[i]->i_date;
02341 
02342             if( vlm->schedule[i]->b_enabled == VLC_TRUE )
02343             {
02344                 if( vlm->schedule[i]->i_date == 0 ) // now !
02345                 {
02346                     vlm->schedule[i]->i_date = (i_time / 1000000) * 1000000 ;
02347                     i_real_date = i_time;
02348                 }
02349                 else if( vlm->schedule[i]->i_period != 0 )
02350                 {
02351                     int j = 0;
02352                     while( vlm->schedule[i]->i_date + j *
02353                            vlm->schedule[i]->i_period <= i_lastcheck &&
02354                            ( vlm->schedule[i]->i_repeat > j ||
02355                              vlm->schedule[i]->i_repeat == -1 ) )
02356                     {
02357                         j++;
02358                     }
02359 
02360                     i_real_date = vlm->schedule[i]->i_date + j *
02361                         vlm->schedule[i]->i_period;
02362                 }
02363 
02364                 if( i_real_date <= i_time && i_real_date > i_lastcheck )
02365                 {
02366                     for( j = 0; j < vlm->schedule[i]->i_command; j++ )
02367                     {
02368                         vlm_message_t *message = NULL;
02369 
02370                         ExecuteCommand( vlm, vlm->schedule[i]->command[j],
02371                                         &message );
02372 
02373                         /* for now, drop the message */
02374                         free( message );
02375                     }
02376                 }
02377             }
02378         }
02379 
02380         i_lastcheck = i_time;
02381 
02382         vlc_mutex_unlock( &vlm->lock );
02383 
02384         msleep( 100000 );
02385     }
02386 
02387     return VLC_SUCCESS;
02388 }
02389 
02390 #else /* ENABLE_VLM */
02391 
02392 /* We just define an empty wrapper */
02393 vlm_t *__vlm_New( vlc_object_t *a )
02394 {
02395     msg_Err( a, "VideoLAN manager support is disabled" );
02396     return 0;
02397 }
02398 void vlm_Delete( vlm_t *a ){}
02399 int vlm_ExecuteCommand( vlm_t *a, char *b, vlm_message_t **c ){ return -1; }
02400 void vlm_MessageDelete( vlm_message_t *a ){}
02401 vlm_media_t *vlm_MediaNew( vlm_t *a, char *b, int c ){ return NULL; }
02402 void vlm_MediaDelete( vlm_t *a, vlm_media_t *b, char *c ){}
02403 int vlm_MediaSetup( vlm_t *a, vlm_media_t *b, char *c, char *d ){ return -1; }
02404 int vlm_MediaControl( vlm_t *a, vlm_media_t *b, char *c, char *d, char *e )
02405     { return -1; }
02406 vlm_schedule_t * vlm_ScheduleNew( vlm_t *a, char *b ){ return NULL; }
02407 void  vlm_ScheduleDelete( vlm_t *a, vlm_schedule_t *b, char *c ){}
02408 int vlm_ScheduleSetup( vlm_schedule_t *a, char *b, char *c ){ return -1; }
02409 int vlm_MediaVodControl( void *a, vod_media_t *b, char *c, int d, va_list e )
02410     { return -1; }
02411 int vlm_Save( vlm_t *a, char *b ){ return -1; }
02412 int vlm_Load( vlm_t *a, char *b ){ return -1; }
02413 
02414 #endif /* ENABLE_VLM */

Generated on Tue Dec 20 10:15:01 2005 for vlc-0.8.4a by  doxygen 1.4.2