Changeset 8e18f5c6cdc3d3dba06a3e04d1f460ee694634a4

Show
Ignore:
Timestamp:
05/12/08 21:53:21 (4 months ago)
Author:
Rémi Denis-Courmont <rem@videolan.org>
git-committer:
Rémi Denis-Courmont <rem@videolan.org> 1210622001 +0300
git-parent:

[5ab3b81401389f1834b9957eaa9b715a94833046]

git-author:
Rémi Denis-Courmont <rem@videolan.org> 1210622001 +0300
Message:

Try to split the mind boggingly big vlm.c

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • src/Makefile.am

    r862c17f r8e18f5c  
    372372SOURCES_libvlc_sout = \ 
    373373    input/vlm.c \ 
     374    input/vlmshell.c \ 
    374375    stream_output/stream_output.c \ 
    375376    stream_output/stream_output.h \ 
  • src/input/vlm.c

    rb8fb4bc r8e18f5c  
    6464 *****************************************************************************/ 
    6565 
    66 /* ugly kludge to avoid "null format string" warnings, 
    67  * even if we handle NULL format string in vlm_MessageNew() */ 
    68 static const char *vlm_NULL = NULL; 
    69  
    7066static void vlm_Destructor( vlm_t *p_vlm ); 
    71  
    72 /* */ 
    73 static int vlm_ControlInternal( vlm_t *, int, ... ); 
    74  
    75 /* */ 
    76 static vlm_message_t *vlm_Show( vlm_t *, vlm_media_sys_t *, vlm_schedule_sys_t *, const char * ); 
    77  
    78 static vlm_schedule_sys_t *vlm_ScheduleSearch( vlm_t *, const char * ); 
    79  
    80 static char *Save( vlm_t * ); 
    81 static int Load( vlm_t *, char * ); 
    82  
    83 static int ExecuteCommand( vlm_t *, const char *, vlm_message_t ** ); 
    84  
    8567static int Manage( vlc_object_t * ); 
    86  
    87 static vlm_schedule_sys_t *vlm_ScheduleNew( vlm_t *vlm, const char *psz_name ); 
    88 static void vlm_ScheduleDelete( vlm_t *vlm, vlm_schedule_sys_t *sched ); 
    89 static int vlm_ScheduleSetup( vlm_schedule_sys_t *schedule, const char *psz_cmd, 
    90                               const char *psz_value ); 
    91  
    9268static int vlm_MediaVodControl( void *, vod_media_t *, const char *, int, va_list ); 
    93  
    94 /* */ 
    95 static vlm_media_sys_t *vlm_MediaSearch( vlm_t *, const char *); 
    9669 
    9770/***************************************************************************** 
     
    223196 
    224197 
    225 static const char quotes[] = "\"'"; 
    226 /** 
    227  * FindCommandEnd: look for the end of a possibly quoted string 
    228  * @return NULL on mal-formatted string, 
    229  * pointer past the last character otherwise. 
    230  */ 
    231 static const char *FindCommandEnd( const char *psz_sent ) 
    232 
    233     char c, quote = 0; 
    234  
    235     while( (c = *psz_sent) != '\0' ) 
    236     { 
    237         if( !quote ) 
    238         { 
    239             if( strchr(quotes,c) )   // opening quote 
    240                 quote = c; 
    241             else if( isspace(c) )         // non-escaped space 
    242                 return psz_sent; 
    243             else if( c == '\\' ) 
    244             { 
    245                 psz_sent++;         // skip escaped character 
    246                 if( *psz_sent == '\0' ) 
    247                     return psz_sent; 
    248             } 
    249         } 
    250         else 
    251         { 
    252             if( c == quote )         // non-escaped matching quote 
    253                 quote = 0; 
    254             else if( (quote == '"') && (c == '\\') ) 
    255             { 
    256                 psz_sent++;         // skip escaped character 
    257                 if (*psz_sent == '\0') 
    258                     return NULL;    // error, closing quote missing 
    259             } 
    260         } 
    261         psz_sent++; 
    262     } 
    263  
    264     // error (NULL) if we could not find a matching quote 
    265     return quote ? NULL : psz_sent; 
    266 
    267  
    268  
    269 /** 
    270  * Unescape a nul-terminated string. 
    271  * Note that in and out can be identical. 
    272  * 
    273  * @param out output buffer (at least <strlen (in) + 1> characters long) 
    274  * @param in nul-terminated string to be unescaped 
    275  * 
    276  * @return 0 on success, -1 on error. 
    277  */ 
    278 static int Unescape( char *out, const char *in ) 
    279 
    280     char c, quote = 0; 
    281  
    282     while( (c = *in++) != '\0' ) 
    283     { 
    284         if( !quote ) 
    285         { 
    286             if (strchr(quotes,c))   // opening quote 
    287             { 
    288                 quote = c; 
    289                 continue; 
    290             } 
    291             else if( c == '\\' ) 
    292             { 
    293                 switch (c = *in++) 
    294                 { 
    295                     case '"': 
    296                     case '\'': 
    297                     case '\\': 
    298                         *out++ = c; 
    299                         continue; 
    300  
    301                     case '\0': 
    302                         *out = '\0'; 
    303                         return 0; 
    304                 } 
    305                 if( isspace(c) ) 
    306                 { 
    307                     *out++ = c; 
    308                     continue; 
    309                 } 
    310                 /* None of the special cases - copy the backslash */ 
    311                 *out++ = '\\'; 
    312             } 
    313         } 
    314         else 
    315         { 
    316             if( c == quote )         // non-escaped matching quote 
    317             { 
    318                 quote = 0; 
    319                 continue; 
    320             } 
    321             if( (quote == '"') && (c == '\\') ) 
    322             { 
    323                 switch( c = *in++ ) 
    324                 { 
    325                     case '"': 
    326                     case '\\': 
    327                         *out++ = c; 
    328                         continue; 
    329  
    330                     case '\0':   // should never happen 
    331                         *out = '\0'; 
    332                         return -1; 
    333                 } 
    334                 /* None of the special cases - copy the backslash */ 
    335                 *out++ = '\\'; 
    336             } 
    337         } 
    338         *out++ = c; 
    339     } 
    340  
    341     *out = '\0'; 
    342     return 0; 
    343 
    344  
    345  
    346 /***************************************************************************** 
    347  * ExecuteCommand: The main state machine 
    348  ***************************************************************************** 
    349  * Execute a command which ends with '\0' (string) 
    350  *****************************************************************************/ 
    351 static int ExecuteSyntaxError( const char *psz_cmd, vlm_message_t **pp_status ) 
    352 
    353     *pp_status = vlm_MessageNew( psz_cmd, "Wrong command syntax" ); 
    354     return VLC_EGENERIC; 
    355 
    356  
    357 static bool ExecuteIsMedia( vlm_t *p_vlm, const char *psz_name ) 
    358 
    359     int64_t id; 
    360  
    361     if( !psz_name || vlm_ControlInternal( p_vlm, VLM_GET_MEDIA_ID, psz_name, &id ) ) 
    362         return false; 
    363     return true; 
    364 
    365 static bool ExecuteIsSchedule( vlm_t *p_vlm, const char *psz_name ) 
    366 
    367     if( !psz_name || !vlm_ScheduleSearch( p_vlm, psz_name ) ) 
    368         return false; 
    369     return true; 
    370 
    371  
    372 static int ExecuteDel( vlm_t *p_vlm, const char *psz_name, vlm_message_t **pp_status ) 
    373 
    374     vlm_media_sys_t *p_media; 
    375     vlm_schedule_sys_t *p_schedule; 
    376  
    377     p_media = vlm_MediaSearch( p_vlm, psz_name ); 
    378     p_schedule = vlm_ScheduleSearch( p_vlm, psz_name ); 
    379  
    380     if( p_schedule != NULL ) 
    381     { 
    382         vlm_ScheduleDelete( p_vlm, p_schedule ); 
    383     } 
    384     else if( p_media != NULL ) 
    385     { 
    386         vlm_ControlInternal( p_vlm, VLM_DEL_MEDIA, p_media->cfg.id ); 
    387     } 
    388     else if( !strcmp(psz_name, "media") ) 
    389     { 
    390         vlm_ControlInternal( p_vlm, VLM_CLEAR_MEDIAS ); 
    391     } 
    392     else if( !strcmp(psz_name, "schedule") ) 
    393     { 
    394         vlm_ControlInternal( p_vlm, VLM_CLEAR_SCHEDULES ); 
    395     } 
    396     else if( !strcmp(psz_name, "all") ) 
    397     { 
    398         vlm_ControlInternal( p_vlm, VLM_CLEAR_MEDIAS ); 
    399         vlm_ControlInternal( p_vlm, VLM_CLEAR_SCHEDULES ); 
    400     } 
    401     else 
    402     { 
    403         *pp_status = vlm_MessageNew( "del", "%s: media unknown", psz_name ); 
    404         return VLC_EGENERIC; 
    405     } 
    406  
    407     *pp_status = vlm_MessageNew( "del", vlm_NULL ); 
    408     return VLC_SUCCESS; 
    409 
    410  
    411 static int ExecuteShow( vlm_t *p_vlm, const char *psz_name, vlm_message_t **pp_status ) 
    412 
    413     vlm_media_sys_t *p_media; 
    414     vlm_schedule_sys_t *p_schedule; 
    415  
    416     if( !psz_name ) 
    417     { 
    418         *pp_status = vlm_Show( p_vlm, NULL, NULL, NULL ); 
    419         return VLC_SUCCESS; 
    420     } 
    421  
    422     p_media = vlm_MediaSearch( p_vlm, psz_name ); 
    423     p_schedule = vlm_ScheduleSearch( p_vlm, psz_name ); 
    424  
    425     if( p_schedule != NULL ) 
    426         *pp_status = vlm_Show( p_vlm, NULL, p_schedule, NULL ); 
    427     else if( p_media != NULL ) 
    428         *pp_status = vlm_Show( p_vlm, p_media, NULL, NULL ); 
    429     else 
    430         *pp_status = vlm_Show( p_vlm, NULL, NULL, psz_name ); 
    431  
    432     return VLC_SUCCESS; 
    433 
    434  
    435 static int ExecuteHelp( vlm_message_t **pp_status ) 
    436 
    437     vlm_message_t *message_child; 
    438  
    439 #define MessageAdd( a ) \ 
    440         vlm_MessageAdd( *pp_status, vlm_MessageNew( a, vlm_NULL ) ); 
    441 #define MessageAddChild( a ) \ 
    442         vlm_MessageAdd( message_child, vlm_MessageNew( a, vlm_NULL ) ); 
    443  
    444     *pp_status = vlm_MessageNew( "help", vlm_NULL ); 
    445  
    446     message_child = MessageAdd( "Commands Syntax:" ); 
    447     MessageAddChild( "new (name) vod|broadcast|schedule [properties]" ); 
    448     MessageAddChild( "setup (name) (properties)" ); 
    449     MessageAddChild( "show [(name)|media|schedule]" ); 
    450     MessageAddChild( "del (name)|all|media|schedule" ); 
    451     MessageAddChild( "control (name) [instance_name] (command)" ); 
    452     MessageAddChild( "save (config_file)" ); 
    453     MessageAddChild( "export" ); 
    454     MessageAddChild( "load (config_file)" ); 
    455  
    456     message_child = MessageAdd( "Media Proprieties Syntax:" ); 
    457     MessageAddChild( "input (input_name)" ); 
    458     MessageAddChild( "inputdel (input_name)|all" ); 
    459     MessageAddChild( "inputdeln input_number" ); 
    460     MessageAddChild( "output (output_name)" ); 
    461     MessageAddChild( "option (option_name)[=value]" ); 
    462     MessageAddChild( "enabled|disabled" ); 
    463     MessageAddChild( "loop|unloop (broadcast only)" ); 
    464     MessageAddChild( "mux (mux_name)" ); 
    465  
    466     message_child = MessageAdd( "Schedule Proprieties Syntax:" ); 
    467     MessageAddChild( "enabled|disabled" ); 
    468     MessageAddChild( "append (command_until_rest_of_the_line)" ); 
    469     MessageAddChild( "date (year)/(month)/(day)-(hour):(minutes):" 
    470                      "(seconds)|now" ); 
    471     MessageAddChild( "period (years_aka_12_months)/(months_aka_30_days)/" 
    472                      "(days)-(hours):(minutes):(seconds)" ); 
    473     MessageAddChild( "repeat (number_of_repetitions)" ); 
    474  
    475     message_child = MessageAdd( "Control Commands Syntax:" ); 
    476     MessageAddChild( "play [input_number]" ); 
    477     MessageAddChild( "pause" ); 
    478     MessageAddChild( "stop" ); 
    479     MessageAddChild( "seek [+-](percentage) | [+-](seconds)s | [+-](miliseconds)ms" ); 
    480  
    481     return VLC_SUCCESS; 
    482 
    483  
    484 static int ExecuteControl( vlm_t *p_vlm, const char *psz_name, const int i_arg, char ** ppsz_arg, vlm_message_t **pp_status ) 
    485 
    486     vlm_media_sys_t *p_media; 
    487     const char *psz_control = NULL; 
    488     const char *psz_instance = NULL; 
    489     const char *psz_argument = NULL; 
    490     int i_index; 
    491     int i_result; 
    492  
    493     if( !ExecuteIsMedia( p_vlm, psz_name ) ) 
    494     { 
    495         *pp_status = vlm_MessageNew( "control", "%s: media unknown", psz_name ); 
    496         return VLC_EGENERIC; 
    497     } 
    498  
    499     assert( i_arg > 0 ); 
    500  
    501 #define IS(txt) ( !strcmp( ppsz_arg[i_index], (txt) ) ) 
    502     i_index = 0; 
    503     if( !IS("play") && !IS("stop") && !IS("pause") && !IS("seek") ) 
    504     { 
    505         i_index = 1; 
    506         psz_instance = ppsz_arg[0]; 
    507  
    508         if( i_index >= i_arg || ( !IS("play") && !IS("stop") && !IS("pause") && !IS("seek") ) ) 
    509             return ExecuteSyntaxError( "control", pp_status ); 
    510     } 
    511 #undef IS 
    512     psz_control = ppsz_arg[i_index]; 
    513  
    514     if( i_index+1 < i_arg ) 
    515         psz_argument = ppsz_arg[i_index+1]; 
    516  
    517     p_media = vlm_MediaSearch( p_vlm, psz_name ); 
    518     assert( p_media ); 
    519  
    520     if( !strcmp( psz_control, "play" ) ) 
    521     { 
    522         int i_input_index = 0; 
    523         int i; 
    524  
    525         if( ( psz_argument && sscanf(psz_argument, "%d", &i) == 1 ) && i > 0 && i-1 < p_media->cfg.i_input ) 
    526         { 
    527             i_input_index = i-1; 
    528         } 
    529         else if( psz_argument ) 
    530         { 
    531             int j; 
    532             vlm_media_t *p_cfg = &p_media->cfg; 
    533             for ( j=0; j < p_cfg->i_input; j++) 
    534             { 
    535                 if( !strcmp( p_cfg->ppsz_input[j], psz_argument ) ) 
    536                 { 
    537                     i_input_index = j; 
    538                     break; 
    539                 } 
    540             } 
    541         } 
    542  
    543         if( p_media->cfg.b_vod ) 
    544             i_result = vlm_ControlInternal( p_vlm, VLM_START_MEDIA_VOD_INSTANCE, p_media->cfg.id, psz_instance, i_input_index, NULL );    // we should get here now 
    545         else 
    546             i_result = vlm_ControlInternal( p_vlm, VLM_START_MEDIA_BROADCAST_INSTANCE, p_media->cfg.id, psz_instance, i_input_index ); 
    547     } 
    548     else if( !strcmp( psz_control, "seek" ) ) 
    549     { 
    550         if( psz_argument ) 
    551         { 
    552             bool b_relative; 
    553             if( psz_argument[0] == '+' || psz_argument[0] == '-' ) 
    554                 b_relative = true; 
    555             else 
    556                 b_relative = false; 
    557  
    558             if( strstr( psz_argument, "ms" ) || strstr( psz_argument, "s" ) ) 
    559             { 
    560                 /* Time (ms or s) */ 
    561                 int64_t i_new_time; 
    562  
    563                 if( strstr( psz_argument, "ms" ) ) 
    564                     i_new_time =  1000 * (int64_t)atoi( psz_argument ); 
    565                 else 
    566                     i_new_time = 1000000 * (int64_t)atoi( psz_argument ); 
    567  
    568                 if( b_relative ) 
    569                 { 
    570                     int64_t i_time = 0; 
    571                     vlm_ControlInternal( p_vlm, VLM_GET_MEDIA_INSTANCE_TIME, p_media->cfg.id, psz_instance, &i_time ); 
    572                     i_new_time += i_time; 
    573                 } 
    574                 if( i_new_time < 0 ) 
    575                     i_new_time = 0; 
    576                 i_result = vlm_ControlInternal( p_vlm, VLM_SET_MEDIA_INSTANCE_TIME, p_media->cfg.id, psz_instance, i_new_time ); 
    577             } 
    578             else 
    579             { 
    580                 /* Percent */ 
    581                 double d_new_position = i18n_atof( psz_argument ) / 100.0; 
    582  
    583                 if( b_relative ) 
    584                 { 
    585                     double d_position = 0.0; 
    586  
    587                     vlm_ControlInternal( p_vlm, VLM_GET_MEDIA_INSTANCE_POSITION, p_media->cfg.id, psz_instance, &d_position ); 
    588                     d_new_position += d_position; 
    589                 } 
    590                 if( d_new_position < 0.0 ) 
    591                     d_new_position = 0.0; 
    592                 else if( d_new_position > 1.0 ) 
    593                     d_new_position = 1.0; 
    594                 i_result = vlm_ControlInternal( p_vlm, VLM_SET_MEDIA_INSTANCE_POSITION, p_media->cfg.id, psz_instance, d_new_position ); 
    595             } 
    596         } 
    597         else 
    598         { 
    599             i_result = VLC_EGENERIC; 
    600         } 
    601     } 
    602     else if( !strcmp( psz_control, "rewind" ) ) 
    603     { 
    604         if( psz_argument ) 
    605         { 
    606             const double d_scale = i18n_atof( psz_argument ); 
    607             double d_position; 
    608  
    609             vlm_ControlInternal( p_vlm, VLM_GET_MEDIA_INSTANCE_POSITION, p_media->cfg.id, psz_instance, &d_position ); 
    610             d_position -= (d_scale / 1000.0); 
    611             if( d_position < 0.0 ) 
    612                 d_position = 0.0; 
    613             i_result = vlm_ControlInternal( p_vlm, VLM_SET_MEDIA_INSTANCE_POSITION, p_media->cfg.id, psz_instance, d_position ); 
    614         } 
    615         else 
    616         { 
    617             i_result = VLC_EGENERIC; 
    618         } 
    619     } 
    620     else if( !strcmp( psz_control, "forward" ) ) 
    621     { 
    622         if( psz_argument ) 
    623         { 
    624             const double d_scale = i18n_atof( psz_argument ); 
    625             double d_position; 
    626  
    627             vlm_ControlInternal( p_vlm, VLM_GET_MEDIA_INSTANCE_POSITION, p_media->cfg.id, psz_instance, &d_position ); 
    628             d_position += (d_scale / 1000.0); 
    629             if( d_position > 1.0 ) 
    630                 d_position = 1.0; 
    631             i_result = vlm_ControlInternal( p_vlm, VLM_SET_MEDIA_INSTANCE_POSITION, p_media->cfg.id, psz_instance, d_position ); 
    632  
    633         } 
    634         else 
    635         { 
    636             i_result = VLC_EGENERIC; 
    637         } 
    638     } 
    639     else if( !strcmp( psz_control, "stop" ) ) 
    640     { 
    641         i_result = vlm_ControlInternal( p_vlm, VLM_STOP_MEDIA_INSTANCE, p_media->cfg.id, psz_instance ); 
    642     } 
    643     else if( !strcmp( psz_control, "pause" ) ) 
    644     { 
    645         i_result = vlm_ControlInternal( p_vlm, VLM_PAUSE_MEDIA_INSTANCE, p_media->cfg.id, psz_instance ); 
    646     } 
    647     else 
    648     { 
    649         i_result = VLC_EGENERIC; 
    650     } 
    651  
    652     if( i_result ) 
    653     { 
    654         *pp_status = vlm_MessageNew( "control", "unknown error" ); 
    655         return VLC_SUCCESS; 
    656     } 
    657     *pp_status = vlm_MessageNew( "control", vlm_NULL ); 
    658     return VLC_SUCCESS; 
    659 
    660  
    661 static int ExecuteExport( vlm_t *p_vlm, vlm_message_t **pp_status ) 
    662 
    663     char *psz_export = Save( p_vlm ); 
    664  
    665     *pp_status = vlm_MessageNew( "export", psz_export ); 
    666     free( psz_export ); 
    667     return VLC_SUCCESS; 
    668 
    669  
    670 static int ExecuteSave( vlm_t *p_vlm, const char *psz_file, vlm_message_t **pp_status ) 
    671 
    672     FILE *f = utf8_fopen( psz_file, "wt" ); 
    673     char *psz_save = NULL; 
    674  
    675     if( !f ) 
    676         goto error; 
    677  
    678     psz_save = Save( p_vlm ); 
    679     if( psz_save == NULL ) 
    680         goto error; 
    681     if( fputs( psz_save, f ) == EOF ) 
    682         goto error;; 
    683     if( fclose( f ) ) 
    684     { 
    685         f = NULL; 
    686         goto error; 
    687     } 
    688  
    689     free( psz_save ); 
    690  
    691     *pp_status = vlm_MessageNew( "save", vlm_NULL ); 
    692     return VLC_SUCCESS; 
    693  
    694 error: 
    695     free( psz_save ); 
    696     if( f ) 
    697          fclose( f ); 
    698     *pp_status = vlm_MessageNew( "save", "Unable to save to file"); 
    699     return VLC_EGENERIC; 
    700 
    701  
    702 static int ExecuteLoad( vlm_t *p_vlm, const char *psz_url, vlm_message_t **pp_status ) 
    703 
    704     stream_t *p_stream = stream_UrlNew( p_vlm, psz_url ); 
    705     int64_t i_size; 
    706     char *psz_buffer; 
    707  
    708     if( !p_stream ) 
    709     { 
    710         *pp_status = vlm_MessageNew( "load", "Unable to load from file" ); 
    711         return VLC_EGENERIC; 
    712     } 
    713  
    714     /* FIXME needed ? */ 
    715     if( stream_Seek( p_stream, 0 ) != 0 ) 
    716     { 
    717         stream_Delete( p_stream ); 
    718  
    719         *pp_status = vlm_MessageNew( "load", "Read file error" ); 
    720         return VLC_EGENERIC; 
    721     } 
    722  
    723     i_size = stream_Size( p_stream ); 
    724  
    725     psz_buffer = malloc( i_size + 1 ); 
    726     if( !psz_buffer ) 
    727     { 
    728         stream_Delete( p_stream ); 
    729  
    730         *pp_status = vlm_MessageNew( "load", "Read file error" ); 
    731         return VLC_EGENERIC; 
    732     } 
    733  
    734     stream_Read( p_stream, psz_buffer, i_size ); 
    735     psz_buffer[i_size] = '\0'; 
    736  
    737     stream_Delete( p_stream ); 
    738  
    739     if( Load( p_vlm, psz_buffer ) ) 
    740     { 
    741         free( psz_buffer ); 
    742  
    743         *pp_status = vlm_MessageNew( "load", "Error while loading file" ); 
    744         return VLC_EGENERIC; 
    745     } 
    746  
    747     free( psz_buffer ); 
    748  
    749     *pp_status = vlm_MessageNew( "load", vlm_NULL ); 
    750     return VLC_SUCCESS; 
    751 
    752  
    753 static int ExecuteScheduleProperty( vlm_t *p_vlm, vlm_schedule_sys_t *p_schedule, bool b_new, 
    754                                     const int i_property, char *ppsz_property[], vlm_message_t **pp_status ) 
    755 
    756     const char *psz_cmd = b_new ? "new" : "setup"; 
    757     int i; 
    758  
    759     for( i = 0; i < i_property; i++ ) 
    760     { 
    761         if( !strcmp( ppsz_property[i], "enabled" ) || 
    762             !strcmp( ppsz_property[i], "disabled" ) ) 
    763         { 
    764             vlm_ScheduleSetup( p_schedule, ppsz_property[i], NULL ); 
    765         } 
    766         else if( !strcmp( ppsz_property[i], "append" ) ) 
    767         { 
    768             char *psz_line; 
    769             int j; 
    770             /* Beware: everything behind append is considered as 
    771              * command line */ 
    772  
    773             if( ++i >= i_property ) 
    774                 break; 
    775  
    776             psz_line = strdup( ppsz_property[i] ); 
    777             for( j = i+1; j < i_property; j++ ) 
    778             { 
    779                 psz_line = realloc( psz_line, strlen(psz_line) + strlen(ppsz_property[j]) + 1 + 1 ); 
    780                 strcat( psz_line, " " ); 
    781                 strcat( psz_line, ppsz_property[j] ); 
    782             } 
    783  
    784             vlm_ScheduleSetup( p_schedule, "append", psz_line ); 
    785             break; 
    786         } 
    787         else 
    788         { 
    789             if( i + 1 >= i_property ) 
    790             { 
    791                 if( b_new ) 
    792                     vlm_ScheduleDelete( p_vlm, p_schedule ); 
    793                 return ExecuteSyntaxError( psz_cmd, pp_status ); 
    794             } 
    795  
    796             vlm_ScheduleSetup( p_schedule, ppsz_property[i], ppsz_property[i+1] ); 
    797             i++; 
    798         } 
    799     } 
    800     *pp_status = vlm_MessageNew( psz_cmd, vlm_NULL ); 
    801     return VLC_SUCCESS; 
    802 
    803  
    804 static int ExecuteMediaProperty( vlm_t *p_vlm, int64_t id, bool b_new, 
    805                                  const int i_property, char *ppsz_property[], vlm_message_t **pp_status ) 
    806 
    807     const char *psz_cmd = b_new ? "new" : "setup"; 
    808     vlm_media_t *p_cfg = NULL; 
    809     int i_result; 
    810     int i; 
    811  
    812 #undef ERROR 
    813 #undef MISSING 
    814 #define ERROR( txt ) do { *pp_status = vlm_MessageNew( psz_cmd, txt); goto error; } while(0) 
    815     if( vlm_ControlInternal( p_vlm, VLM_GET_MEDIA, id, &p_cfg ) ) 
    816         ERROR( "unknown media" ); 
    817  
    818 #define MISSING(cmd) do { if( !psz_value ) ERROR( "missing argument for " cmd ); } while(0) 
    819     for( i = 0; i < i_property; i++ ) 
    820     { 
    821         const char *psz_option = ppsz_property[i]; 
    822         const char *psz_value = i+1 < i_property ? ppsz_property[i+1] :  NULL; 
    823  
    824         if( !strcmp( psz_option, "enabled" ) ) 
    825         { 
    826             p_cfg->b_enabled = true; 
    827         } 
    828         else if( !strcmp( psz_option, "disabled" ) ) 
    829         { 
    830             p_cfg->b_enabled = false; 
    831         } 
    832         else if( !strcmp( psz_option, "input" ) ) 
    833         { 
    834             MISSING( "input" ); 
    835             TAB_APPEND( p_cfg->i_input, p_cfg->ppsz_input, strdup(psz_value) ); 
    836             i++; 
    837         } 
    838         else if( !strcmp( psz_option, "inputdel" ) && psz_value && !strcmp( psz_value, "all" ) ) 
    839         { 
    840             while( p_cfg->i_input > 0 ) 
    841                 TAB_REMOVE( p_cfg->i_input, p_cfg->ppsz_input, p_cfg->ppsz_input[0] ); 
    842             i++; 
    843         } 
    844         else if( !strcmp( psz_option, "inputdel" ) ) 
    845         { 
    846             int j; 
    847  
    848             MISSING( "inputdel" ); 
    849  
    850             for( j = 0; j < p_cfg->i_input; j++ ) 
    851             { 
    852                 if( !strcmp( p_cfg->ppsz_input[j], psz_value ) ) 
    853                 { 
    854                     TAB_REMOVE( p_cfg->i_input, p_cfg->ppsz_input, p_cfg->ppsz_input[j] ); 
    855                     break; 
    856                 } 
    857             } 
    858             i++; 
    859         } 
    860         else if( !strcmp( psz_option, "inputdeln" ) ) 
    861         { 
    862             int i_index; 
    863  
    864             MISSING( "inputdeln" ); 
    865   
    866             i_index = atoi( psz_value ); 
    867             if( i_index > 0 && i_index <= p_cfg->i_input ) 
    868                 TAB_REMOVE( p_cfg->i_input, p_cfg->ppsz_input, p_cfg->ppsz_input[i_index-1] ); 
    869             i++; 
    870         } 
    871         else if( !strcmp( psz_option, "output" ) ) 
    872         { 
    873             MISSING( "output" ); 
    874  
    875             free( p_cfg->psz_output ); 
    876             p_cfg->psz_output = *psz_value ? strdup( psz_value ) : NULL; 
    877             i++; 
    878         } 
    879         else if( !strcmp( psz_option, "option" ) ) 
    880         { 
    881             MISSING( "option" ); 
    882  
    883             TAB_APPEND( p_cfg->i_option, p_cfg->ppsz_option, strdup( psz_value ) ); 
    884             i++; 
    885         } 
    886         else if( !strcmp( psz_option, "loop" ) ) 
    887         { 
    888             if( p_cfg->b_vod ) 
    889                 ERROR( "invalid loop option for vod" ); 
    890             p_cfg->broadcast.b_loop = true; 
    891         } 
    892         else if( !strcmp( psz_option, "unloop" ) ) 
    893         { 
    894             if( p_cfg->b_vod ) 
    895                 ERROR( "invalid unloop option for vod" ); 
    896             p_cfg->broadcast.b_loop = false; 
    897         } 
    898         else if( !strcmp( psz_option, "mux" ) ) 
    899         { 
    900             MISSING( "mux" ); 
    901             if( !p_cfg->b_vod ) 
    902                 ERROR( "invalid mux option for broadcast" ); 
    903  
    904             free( p_cfg->vod.psz_mux ); 
    905             p_cfg->vod.psz_mux = *psz_value ? strdup( psz_value ) : NULL; 
    906             i++; 
    907         } 
    908         else 
    909         { 
    910             fprintf( stderr, "PROP: name=%s unknown\n", psz_option ); 
    911             ERROR( "Wrong command syntax" ); 
    912         } 
    913     } 
    914 #undef MISSING 
    915 #undef ERROR 
    916  
    917     /* */ 
    918     i_result = vlm_ControlInternal( p_vlm, VLM_CHANGE_MEDIA, p_cfg ); 
    919     vlm_media_Delete( p_cfg ); 
    920  
    921     *pp_status = vlm_MessageNew( psz_cmd, vlm_NULL ); 
    922     return i_result; 
    923  
    924 error: 
    925     if( p_cfg ) 
    926     { 
    927         if( b_new ) 
    928             vlm_ControlInternal( p_vlm, VLM_DEL_MEDIA, p_cfg->id ); 
    929         vlm_media_Delete( p_cfg ); 
    930     } 
    931     return VLC_EGENERIC; 
    932 
    933  
    934 static int ExecuteNew( vlm_t *p_vlm, const char *psz_name, const char *psz_type, const int i_property, char *ppsz_property[], vlm_message_t **pp_status ) 
    935 
    936     /* Check name */ 
    937     if( !strcmp( psz_name, "all" ) || !strcmp( psz_name, "media" ) || !strcmp( psz_name, "schedule" ) ) 
    938     { 
    939         *pp_status = vlm_MessageNew( "new", "\"all\", \"media\" and \"schedule\" are reserved names" ); 
    940         return VLC_EGENERIC; 
    941     } 
    942     if( ExecuteIsMedia( p_vlm, psz_name ) || ExecuteIsSchedule( p_vlm, psz_name ) ) 
    943     { 
    944         *pp_status = vlm_MessageNew( "new", "%s: Name already in use", psz_name ); 
    945         return VLC_EGENERIC; 
    946     } 
    947     /* */ 
    948     if( !strcmp( psz_type, "schedule" ) ) 
    949     { 
    950         vlm_schedule_sys_t *p_schedule = vlm_ScheduleNew( p_vlm, psz_name ); 
    951         if( !p_schedule ) 
    952         { 
    953             *pp_status = vlm_MessageNew( "new", "could not create schedule" ); 
    954             return VLC_EGENERIC; 
    955         } 
    956         return ExecuteScheduleProperty( p_vlm, p_schedule, true, i_property, ppsz_property, pp_status ); 
    957     } 
    958     else if( !strcmp( psz_type, "vod" ) || !strcmp( psz_type, "broadcast" ) ) 
    959     { 
    960         vlm_media_t cfg; 
    961         int64_t id; 
    962  
    963         vlm_media_Init( &cfg ); 
    964         cfg.psz_name = strdup( psz_name ); 
    965         cfg.b_vod = !strcmp( psz_type, "vod" ); 
    966  
    967         if( vlm_ControlInternal( p_vlm, VLM_ADD_MEDIA, &cfg, &id ) ) 
    968         { 
    969             vlm_media_Clean( &cfg ); 
    970             *pp_status = vlm_MessageNew( "new", "could not create media" ); 
    971             return VLC_EGENERIC; 
    972         } 
    973         vlm_media_Clean( &cfg ); 
    974         return ExecuteMediaProperty( p_vlm, id, true, i_property, ppsz_property, pp_status ); 
    975     } 
    976     else 
    977     { 
    978         *pp_status = vlm_MessageNew( "new", "%s: Choose between vod, broadcast or schedule", psz_type ); 
    979         return VLC_EGENERIC; 
    980     } 
    981 
    982  
    983 static int ExecuteSetup( vlm_t *p_vlm, const char *psz_name, const int i_property, char *ppsz_property[], vlm_message_t **pp_status ) 
    984 
    985     if( ExecuteIsSchedule( p_vlm, psz_name ) ) 
    986     { 
    987         vlm_schedule_sys_t *p_schedule = vlm_ScheduleSearch( p_vlm, psz_name ); 
    988         return ExecuteScheduleProperty( p_vlm, p_schedule, false, i_property, ppsz_property, pp_status ); 
    989     } 
    990     else if( ExecuteIsMedia( p_vlm, psz_name ) ) 
    991     { 
    992         int64_t id; 
    993         if( vlm_ControlInternal( p_vlm, VLM_GET_MEDIA_ID, psz_name, &id ) ) 
    994             goto error; 
    995         return ExecuteMediaProperty( p_vlm, id, false, i_property, ppsz_property, pp_status ); 
    996     } 
    997  
    998 error: 
    999     *pp_status = vlm_MessageNew( "setup", "%s unknown", psz_name ); 
    1000     return VLC_EGENERIC; 
    1001 
    1002  
    1003 static int ExecuteCommand( vlm_t *p_vlm, const char *psz_command, 
    1004                            vlm_message_t **pp_message ) 
    1005 
    1006     size_t i_command = 0; 
    1007     char buf[strlen (psz_command) + 1], *psz_buf = buf; 
    1008     char *ppsz_command[3+sizeof (buf) / 2]; 
    1009     vlm_message_t *p_message = NULL; 
    1010  
    1011     /* First, parse the line and cut it */ 
    1012     while( *psz_command != '\0' ) 
    1013     { 
    1014         const char *psz_temp; 
    1015  
    1016         if(isspace (*psz_command)) 
    1017         { 
    1018             psz_command++; 
    1019             continue; 
    1020         } 
    1021  
    1022         /* support for comments */ 
    1023         if( i_command == 0 && *psz_command == '#') 
    1024         { 
    1025             p_message = vlm_MessageNew( "", vlm_NULL ); 
    1026             goto success; 
    1027         } 
    1028  
    1029         psz_temp = FindCommandEnd( psz_command ); 
    1030  
    1031         if( psz_temp == NULL ) 
    1032         { 
    1033             p_message = vlm_MessageNew( "Incomplete command", psz_command ); 
    1034             goto error; 
    1035         } 
    1036  
    1037         assert (i_command < (sizeof (ppsz_command) / sizeof (ppsz_command[0]))); 
    1038  
    1039         ppsz_command[i_command] = psz_buf; 
    1040         memcpy (psz_buf, psz_command, psz_temp - psz_command); 
    1041         psz_buf[psz_temp - psz_command] = '\0'; 
    1042  
    1043         Unescape (psz_buf, psz_buf); 
    1044  
    1045         i_command++; 
    1046         psz_buf += psz_temp - psz_command + 1; 
    1047         psz_command = psz_temp; 
    1048  
    1049         assert (buf + sizeof (buf) >= psz_buf); 
    1050     } 
    1051  
    1052     /* 
    1053      * And then Interpret it 
    1054      */ 
    1055  
    1056 #define IF_EXECUTE( name, check, cmd ) if( !strcmp(ppsz_command[0], name ) ) { if( (check) ) goto syntax_error;  if( (cmd) ) goto error; goto success; } 
    1057     if( i_command == 0 ) 
    1058     { 
    1059         p_message = vlm_MessageNew( "", vlm_NULL ); 
    1060         goto success; 
    1061     } 
    1062     else IF_EXECUTE( "del",     (i_command != 2),   ExecuteDel(p_vlm, ppsz_command[1], &p_message) ) 
    1063     else IF_EXECUTE( "show",    (i_command > 2),    ExecuteShow(p_vlm, i_command > 1 ? ppsz_command[1] : NULL, &p_message) ) 
    1064     else IF_EXECUTE( "help",    (i_command != 1),   ExecuteHelp( &p_message ) ) 
    1065     else IF_EXECUTE( "control", (i_command < 3),    ExecuteControl(p_vlm, ppsz_command[1], i_command - 2, &ppsz_command[2], &p_message) ) 
    1066     else IF_EXECUTE( "save",    (i_command != 2),   ExecuteSave(p_vlm, ppsz_command[1], &p_message) ) 
    1067     else IF_EXECUTE( "export",  (i_command != 1),   ExecuteExport(p_vlm, &p_message) ) 
    1068     else IF_EXECUTE( "load",    (i_command != 2),   ExecuteLoad(p_vlm, ppsz_command[1], &p_message) ) 
    1069     else IF_EXECUTE( "new",     (i_command < 3),    ExecuteNew(p_vlm, ppsz_command[1], ppsz_command[2], i_command-3, &ppsz_command[3], &p_message) ) 
    1070     else IF_EXECUTE( "setup",   (i_command < 2),    ExecuteSetup(p_vlm, ppsz_command[1], i_command-2, &ppsz_command[2], &p_message) ) 
    1071     else 
    1072     { 
    1073         p_message = vlm_MessageNew( ppsz_command[0], "Unknown command" ); 
    1074         goto error; 
    1075     } 
    1076 #undef IF_EXECUTE 
    1077  
    1078 success: 
    1079     *pp_message = p_message; 
    1080     return VLC_SUCCESS; 
    1081  
    1082 syntax_error: 
    1083     return ExecuteSyntaxError( ppsz_command[0], pp_message ); 
    1084  
    1085 error: 
    1086     *pp_message = p_message; 
    1087     return VLC_EGENERIC; 
    1088 
    1089  
    1090 /***************************************************************************** 
    1091  * Media handling 
    1092  *****************************************************************************/ 
    1093 vlm_media_sys_t *vlm_MediaSearch( vlm_t *vlm, const char *psz_name ) 
    1094 
    1095     int i; 
    1096  
    1097     for( i = 0; i < vlm->i_media; i++ ) 
    1098     { 
    1099         if( strcmp( psz_name, vlm->media[i]->cfg.psz_name ) == 0 ) 
    1100             return vlm->media[i]; 
    1101     } 
    1102  
    1103     return NULL; 
    1104 
    1105  
    1106 /***************************************************************************** 
    1107  * Schedule handling 
    1108  *****************************************************************************/ 
    1109 static int64_t vlm_Date(void) 
     198int64_t vlm_Date(void) 
    1110199{ 
    1111200#ifdef WIN32 
     
    1122211} 
    1123212 
    1124 static vlm_schedule_sys_t *vlm_ScheduleNew( vlm_t *vlm, const char *psz_name ) 
    1125 { 
    1126     vlm_schedule_sys_t *p_sched = malloc( sizeof( vlm_schedule_sys_t ) ); 
    1127  
    1128     if( !p_sched ) 
    1129     { 
    1130         return NULL; 
    1131     } 
    1132  
    1133     if( !psz_name ) 
    1134     { 
    1135         return NULL; 
    1136     } 
    1137  
    1138     p_sched->psz_name = strdup( psz_name ); 
    1139     p_sched->b_enabled = false; 
    1140     p_sched->i_command = 0; 
    1141     p_sched->command = NULL; 
    1142     p_sched->i_date = 0; 
    1143     p_sched->i_period = 0; 
    1144     p_sched->i_repeat = -1; 
    1145  
    1146     TAB_APPEND( vlm->i_schedule, vlm->schedule, p_sched ); 
    1147  
    1148     return p_sched; 
    1149 } 
    1150  
    1151 /* for now, simple delete. After, del with options (last arg) */ 
    1152 static void vlm_ScheduleDelete( vlm_t *vlm, vlm_schedule_sys_t *sched ) 
    1153 { 
    1154     if( sched == NULL ) return; 
    1155  
    1156     TAB_REMOVE( vlm->i_schedule, vlm->schedule, sched ); 
    1157  
    1158     if( vlm->i_schedule == 0 ) free( vlm->schedule ); 
    1159     free( sched->psz_name ); 
    1160     while( sched->i_command ) 
    1161     { 
    1162         char *psz_cmd = sched->command[0]; 
    1163         TAB_REMOVE( sched->i_command, sched->command, psz_cmd ); 
    1164         free( psz_cmd ); 
    1165     } 
    1166     free( sched ); 
    1167 } 
    1168  
    1169 static vlm_schedule_sys_t *vlm_ScheduleSearch( vlm_t *vlm, const char *psz_name ) 
    1170 { 
    1171     int i; 
    1172  
    1173     for( i = 0; i < vlm->i_schedule; i++ ) 
    1174     { 
    1175         if( strcmp( psz_name, vlm->schedule[i]->psz_name ) == 0 ) 
    1176         { 
    1177             return vlm->schedule[i]; 
    1178         } 
    1179     } 
    1180  
    1181     return NULL; 
    1182 } 
    1183  
    1184 /* Ok, setup schedule command will be able to support only one (argument value) at a time  */ 
    1185 static int vlm_ScheduleSetup( vlm_schedule_sys_t *schedule, const char *psz_cmd, 
    1186                        const char *psz_value ) 
    1187 { 
    1188     if( !strcmp( psz_cmd, "enabled" ) ) 
    1189     { 
    1190         schedule->b_enabled = true; 
    1191     } 
    1192     else if( !strcmp( psz_cmd, "disabled" ) ) 
    1193     { 
    1194         schedule->b_enabled = false; 
    1195     } 
    1196 #if !defined( UNDER_CE ) 
    1197     else if( !strcmp( psz_cmd, "date" ) ) 
    1198     { 
    1199         struct tm time; 
    1200         const char *p; 
    1201         time_t date; 
    1202  
    1203         time.tm_sec = 0;         /* seconds */ 
    1204         time.tm_min = 0;         /* minutes */ 
    1205         time.tm_hour = 0;        /* hours */ 
    1206         time.tm_mday = 0;        /* day of the month */ 
    1207         time.tm_mon = 0;         /* month */ 
    1208         time.tm_year = 0;        /* year */ 
    1209         time.tm_wday = 0;        /* day of the week */ 
    1210         time.tm_yday = 0;        /* day in the year */ 
    1211         time.tm_isdst = -1;       /* daylight saving time */ 
    1212  
    1213         /* date should be year/month/day-hour:minutes:seconds */ 
    1214         p = strchr( psz_value, '-' ); 
    1215  
    1216         if( !strcmp( psz_value, "now" ) ) 
    1217         { 
    1218             schedule->i_date = 0; 
    1219         } 
    1220         else if( (p == NULL) && sscanf( psz_value, "%d:%d:%d", &time.tm_hour, 
    1221                                         &time.tm_min, &time.tm_sec ) != 3 ) 
    1222                                         /* it must be a hour:minutes:seconds */ 
    1223         { 
    1224             return 1; 
    1225         } 
    1226         else 
    1227         { 
    1228             unsigned i,j,k; 
    1229  
    1230             switch( sscanf( p + 1, "%u:%u:%u", &i, &j, &k ) ) 
    1231             { 
    1232                 case 1: 
    1233                     time.tm_sec = i; 
    1234                     break; 
    1235                 case 2: 
    1236                     time.tm_min = i; 
    1237                     time.tm_sec = j; 
    1238                     break; 
    1239                 case 3: 
    1240                     time.tm_hour = i; 
    1241                     time.tm_min = j; 
    1242                     time.tm_sec = k; 
    1243                     break; 
    1244                 default: 
    1245                     return 1; 
    1246             } 
    1247  
    1248             switch( sscanf( psz_value, "%d/%d/%d", &i, &j, &k ) ) 
    1249             { 
    1250                 case 1: 
    1251                     time.tm_mday = i; 
    1252                     break; 
    1253                 case 2: 
    1254                     time.tm_mon = i - 1; 
    1255                     time.tm_mday = j; 
    1256                     break; 
    1257                 case 3: 
    1258                     time.tm_year = i - 1900; 
    1259                     time.tm_mon = j - 1; 
    1260                     time.tm_mday = k; 
    1261                     break; 
    1262                 default: 
    1263                     return 1; 
    1264             } 
    1265  </