vlm.c
上传用户:riyaled888
上传日期:2009-03-27
资源大小:7338k
文件大小:66k
源码类别:

多媒体

开发平台:

MultiPlatform

  1. /*****************************************************************************
  2.  * vlm.c: VLM interface plugin
  3.  *****************************************************************************
  4.  * Copyright (C) 2000, 2001 VideoLAN
  5.  * $Id: vlm.c 9083 2004-10-30 10:36:07Z gbazin $
  6.  *
  7.  * Authors: Simon Latapie <garf@videolan.org>
  8.  *          Laurent Aimar <fenrir@videolan.org>
  9.  *          Gildas Bazin <gbazin@videolan.org>
  10.  *
  11.  * This program is free software; you can redistribute it and/or modify
  12.  * it under the terms of the GNU General Public License as published by
  13.  * the Free Software Foundation; either version 2 of the License, or
  14.  * (at your option) any later version.
  15.  *
  16.  * This program is distributed in the hope that it will be useful,
  17.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  19.  * GNU General Public License for more details.
  20.  *
  21.  * You should have received a copy of the GNU General Public License
  22.  * along with this program; if not, write to the Free Software
  23.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
  24.  *****************************************************************************/
  25. /*****************************************************************************
  26.  * Preamble
  27.  *****************************************************************************/
  28. #include <stdlib.h>                                      /* malloc(), free() */
  29. #include <ctype.h>                                              /* tolower() */
  30. #include <vlc/vlc.h>
  31. #ifdef ENABLE_VLM
  32. #include <vlc/intf.h>
  33. #include <vlc/input.h>
  34. #ifdef HAVE_TIME_H
  35. #   include <time.h>                                              /* ctime() */
  36. #endif
  37. #include "vlc_vlm.h"
  38. #include "vlc_vod.h"
  39. /*****************************************************************************
  40.  * Local prototypes.
  41.  *****************************************************************************/
  42. static char          *vlm_Save( vlm_t * );
  43. static int            vlm_Load( vlm_t *, char *);
  44. static vlm_message_t *vlm_Show( vlm_t *, vlm_media_t *, vlm_schedule_t *, char * );
  45. static vlm_message_t *vlm_Help( vlm_t *, char * );
  46. static vlm_media_t *vlm_MediaNew    ( vlm_t *, char *, int );
  47. static void         vlm_MediaDelete ( vlm_t *, vlm_media_t *, char * );
  48. static vlm_media_t *vlm_MediaSearch ( vlm_t *, char * );
  49. static int          vlm_MediaSetup  ( vlm_t *, vlm_media_t *, char *, char * );
  50. static int          vlm_MediaControl( vlm_t *, vlm_media_t *, char *, char *, char * );
  51. static vlm_media_instance_t *vlm_MediaInstanceSearch( vlm_t *, vlm_media_t *, char * );
  52. static vlm_message_t *vlm_MessageNew( char *, const char *, ... );
  53. static vlm_message_t *vlm_MessageAdd( vlm_message_t*, vlm_message_t* );
  54. static vlm_schedule_t *vlm_ScheduleNew( vlm_t *, char *);
  55. static void            vlm_ScheduleDelete( vlm_t *, vlm_schedule_t *, char *);
  56. static int             vlm_ScheduleSetup( vlm_schedule_t *, char *, char *);
  57. static vlm_schedule_t *vlm_ScheduleSearch( vlm_t *, char *);
  58. static int vlm_MediaVodControl( void *, vod_media_t *, char *, int, va_list );
  59. static int ExecuteCommand( vlm_t *, char *, vlm_message_t **);
  60. static int Manage( vlc_object_t* );
  61. /*****************************************************************************
  62.  * vlm_New:
  63.  *****************************************************************************/
  64. vlm_t *__vlm_New ( vlc_object_t *p_this )
  65. {
  66.     vlc_value_t lockval;
  67.     vlm_t *vlm = NULL;
  68.     /* to be sure to avoid multiple creation */
  69.     var_Create( p_this->p_libvlc, "vlm_mutex", VLC_VAR_MUTEX );
  70.     var_Get( p_this->p_libvlc, "vlm_mutex", &lockval );
  71.     vlc_mutex_lock( lockval.p_address );
  72.     if( !(vlm = vlc_object_find( p_this, VLC_OBJECT_VLM, FIND_ANYWHERE )) )
  73.     {
  74.         msg_Info( p_this, "creating vlm" );
  75.         if( ( vlm = vlc_object_create( p_this, VLC_OBJECT_VLM ) ) == NULL )
  76.         {
  77.             vlc_mutex_unlock( lockval.p_address );
  78.             return NULL;
  79.         }
  80.         vlc_mutex_init( p_this->p_vlc, &vlm->lock );
  81.         vlm->i_media      = 0;
  82.         vlm->media        = NULL;
  83.         vlm->i_vod        = 0;
  84.         vlm->i_schedule   = 0;
  85.         vlm->schedule     = NULL;
  86.         vlc_object_yield( vlm );
  87.         vlc_object_attach( vlm, p_this->p_vlc );
  88.     }
  89.     vlc_mutex_unlock( lockval.p_address );
  90.     if( vlc_thread_create( vlm, "vlm thread",
  91.                            Manage, VLC_THREAD_PRIORITY_LOW, VLC_FALSE ) )
  92.     {
  93.         vlc_mutex_destroy( &vlm->lock );
  94.         vlc_object_destroy( vlm );
  95.         return NULL;
  96.     }
  97.     return vlm;
  98. }
  99. /*****************************************************************************
  100.  * vlm_Delete:
  101.  *****************************************************************************/
  102. void vlm_Delete( vlm_t *vlm )
  103. {
  104.     vlc_value_t lockval;
  105.     var_Get( vlm->p_libvlc, "vlm_mutex", &lockval );
  106.     vlc_mutex_lock( lockval.p_address );
  107.     vlc_object_release( vlm );
  108.     if( vlm->i_refcount > 0 )
  109.     {
  110.         vlc_mutex_unlock( lockval.p_address );
  111.         return;
  112.     }
  113.     vlm->b_die = VLC_TRUE;
  114.     vlc_thread_join( vlm );
  115.     vlc_mutex_destroy( &vlm->lock );
  116.     while( vlm->i_media ) vlm_MediaDelete( vlm, vlm->media[0], NULL );
  117.     if( vlm->media ) free( vlm->media );
  118.     while( vlm->i_schedule ) vlm_ScheduleDelete( vlm, vlm->schedule[0], NULL );
  119.     if( vlm->schedule ) free( vlm->schedule );
  120.     vlc_object_detach( vlm );
  121.     vlc_object_destroy( vlm );
  122.     vlc_mutex_unlock( lockval.p_address );
  123. }
  124. /*****************************************************************************
  125.  * vlm_ExecuteCommand:
  126.  *****************************************************************************/
  127. int vlm_ExecuteCommand( vlm_t *vlm, char *command, vlm_message_t **message)
  128. {
  129.     int result;
  130.     vlc_mutex_lock( &vlm->lock );
  131.     result = ExecuteCommand( vlm, command, message );
  132.     vlc_mutex_unlock( &vlm->lock );
  133.     return result;
  134. }
  135. /*****************************************************************************
  136.  * FindEndCommand
  137.  *****************************************************************************/
  138. static char *FindEndCommand( char *psz )
  139. {
  140.     char *psz_sent = psz;
  141.     switch( *psz_sent )
  142.     {
  143.     case '"':
  144.         psz_sent++;
  145.         while( ( *psz_sent != '"' ) && ( *psz_sent != '' ) )
  146.         {
  147.             if( *psz_sent == ''' )
  148.             {
  149.                 psz_sent = FindEndCommand( psz_sent );
  150.                 if( psz_sent == NULL ) return NULL;
  151.             }
  152.             else psz_sent++;
  153.         }
  154.         if( *psz_sent == '"' )
  155.         {
  156.             psz_sent++;
  157.             return psz_sent;
  158.         }
  159.         /* *psz_sent == '' -> number of " is incorrect */
  160.         else return NULL;
  161.         break;
  162.     case ''':
  163.         psz_sent++;
  164.         while( ( *psz_sent != ''' ) && ( *psz_sent != '' ) )
  165.         {
  166.             if( *psz_sent == '"' )
  167.             {
  168.                 psz_sent = FindEndCommand( psz_sent );
  169.                 if( psz_sent == NULL ) return NULL;
  170.             }
  171.             else psz_sent++;
  172.         }
  173.         if( *psz_sent == ''' )
  174.         {
  175.             psz_sent++;
  176.             return psz_sent;
  177.         }
  178.         /* *psz_sent == '' -> number of " is incorrect */
  179.         else return NULL;
  180.         break;
  181.     default: /* now we can look for spaces */
  182.         while( ( *psz_sent != ' ' ) && ( *psz_sent != '' ) )
  183.         {
  184.             if( ( *psz_sent == ''' ) || ( *psz_sent == '"' ) )
  185.             {
  186.                 psz_sent = FindEndCommand( psz_sent );
  187.             }
  188.             else psz_sent++;
  189.         }
  190.         return psz_sent;
  191.     }
  192. }
  193. /*****************************************************************************
  194.  * ExecuteCommand: The main state machine
  195.  *****************************************************************************
  196.  * Execute a command which ends with '' (string)
  197.  *****************************************************************************/
  198. static int ExecuteCommand(vlm_t *vlm, char *command, vlm_message_t **p_message)
  199. {
  200.     int i_command = 0;
  201.     char **p_command = NULL;
  202.     char *cmd = command;
  203.     vlm_message_t *message = NULL;
  204.     int i, j;
  205.     /* First, parse the line and cut it */
  206.     while( *cmd != '' )
  207.     {
  208.         if( *cmd == ' ' )
  209.         {
  210.             cmd++;
  211.         }
  212.         else
  213.         {
  214.             char *p_temp;
  215.             int   i_temp;
  216.             p_temp = FindEndCommand( cmd );
  217.             if( p_temp == NULL ) goto error;
  218.             i_temp = p_temp - cmd;
  219.             p_command = realloc( p_command, (i_command + 1) * sizeof(char*) );
  220.             p_command[ i_command ] = malloc( (i_temp + 1) * sizeof(char) );
  221.             strncpy( p_command[ i_command ], cmd, i_temp );
  222.             p_command[ i_command ][ i_temp ] = '';
  223.             i_command++;
  224.             cmd = p_temp;
  225.         }
  226.     }
  227.     /*
  228.      * And then Interpret it
  229.      */
  230.     if( i_command == 0 )
  231.     {
  232.         message = vlm_MessageNew( "", NULL );
  233.         goto success;
  234.     }
  235.     if( strcmp(p_command[0], "new") == 0 )
  236.     {
  237.         int i_type;
  238.         /* Check the number of arguments */
  239.         if( i_command < 3 ) goto syntax_error;
  240.         /* Get type */
  241.         if( strcmp(p_command[2], "vod") == 0 )
  242.         {
  243.             i_type = VOD_TYPE;
  244.         }
  245.         else if( strcmp(p_command[2], "broadcast") == 0 )
  246.         {
  247.             i_type = BROADCAST_TYPE;
  248.         }
  249.         else if( strcmp(p_command[2], "schedule") == 0 )
  250.         {
  251.             i_type = SCHEDULE_TYPE;
  252.         }
  253.         else
  254.         {
  255.             message = vlm_MessageNew( "new", "%s: Choose between vod, "
  256.                                       "broadcast or schedule", p_command[1] );
  257.             goto error;
  258.         }
  259.         /* Check for forbidden media names */
  260.         if( strcmp(p_command[1], "all") == 0 ||
  261.             strcmp(p_command[1], "media") == 0 ||
  262.             strcmp(p_command[1], "schedule") == 0 )
  263.         {
  264.             message = vlm_MessageNew( "new", ""all", "media" and "
  265.                                       ""schedule" are reserved names" );
  266.             goto error;
  267.         }
  268.         /* Check the name is not already in use */
  269.         if( vlm_ScheduleSearch( vlm, p_command[1] ) ||
  270.             vlm_MediaSearch( vlm, p_command[1] ) )
  271.         {
  272.             message = vlm_MessageNew( "new", "%s: Name already in use",
  273.                                       p_command[1] );
  274.             goto error;
  275.         }
  276.         /* Schedule */
  277.         if( i_type == SCHEDULE_TYPE )
  278.         {
  279.             vlm_schedule_t *schedule;
  280.             schedule = vlm_ScheduleNew( vlm, p_command[1] );
  281.             if( !schedule )
  282.             {
  283.                 message = vlm_MessageNew( "new", "could not create schedule" );
  284.                 goto error;
  285.             }
  286.         }
  287.         /* Media */
  288.         else
  289.         {
  290.             vlm_media_t *media;
  291.             media = vlm_MediaNew( vlm, p_command[1], i_type );
  292.             if( !media )
  293.             {
  294.                 message = vlm_MessageNew( "new", "could not create media" );
  295.                 goto error;
  296.             }
  297.         }
  298.         if( i_command <= 3 )
  299.         {
  300.             message = vlm_MessageNew( "new", NULL );
  301.             goto success;
  302.         }
  303.         /* Properties will be dealt with later on */
  304.     }
  305.     else if( strcmp(p_command[0], "setup") == 0 )
  306.     {
  307.         if( i_command < 2 ) goto syntax_error;
  308.         /* Properties will be dealt with later on */
  309.     }
  310.  
  311.     else if( strcmp(p_command[0], "del") == 0 )
  312.     {
  313.         vlm_media_t *media;
  314.         vlm_schedule_t *schedule;
  315.         if( i_command < 2 ) goto syntax_error;
  316.         media = vlm_MediaSearch( vlm, p_command[1] );
  317.         schedule = vlm_ScheduleSearch( vlm, p_command[1] );
  318.         if( schedule != NULL )
  319.         {
  320.             vlm_ScheduleDelete( vlm, schedule, NULL );
  321.         }
  322.         else if( media != NULL )
  323.         {
  324.             vlm_MediaDelete( vlm, media, NULL );
  325.         }
  326.         else if( strcmp(p_command[1], "media") == 0 )
  327.         {
  328.             while( vlm->i_media ) vlm_MediaDelete( vlm, vlm->media[0], NULL );
  329.         }
  330.         else if( strcmp(p_command[1], "schedule") == 0 )
  331.         {
  332.             while( vlm->i_schedule )
  333.                 vlm_ScheduleDelete( vlm, vlm->schedule[0], NULL );
  334.         }
  335.         else if( strcmp(p_command[1], "all") == 0 )
  336.         {
  337.             while( vlm->i_media ) vlm_MediaDelete( vlm, vlm->media[0], NULL );
  338.             while( vlm->i_schedule )
  339.                 vlm_ScheduleDelete( vlm, vlm->schedule[0], NULL );
  340.         }
  341.         else
  342.         {
  343.             message = vlm_MessageNew( "del", "%s: media unknown",
  344.                                       p_command[1] );
  345.             goto error;
  346.         }
  347.         message = vlm_MessageNew( "del", NULL );
  348.         goto success;
  349.     }
  350.     else if( strcmp(p_command[0], "show") == 0 )
  351.     {
  352.         vlm_media_t *media;
  353.         vlm_schedule_t *schedule;
  354.         if( i_command == 1 )
  355.         {
  356.             message = vlm_Show( vlm, NULL, NULL, NULL );
  357.             goto success;
  358.         }
  359.         else if( i_command > 2 ) goto syntax_error;
  360.         media = vlm_MediaSearch( vlm, p_command[1] );
  361.         schedule = vlm_ScheduleSearch( vlm, p_command[1] );
  362.         if( schedule != NULL )
  363.         {
  364.             message = vlm_Show( vlm, NULL, schedule, NULL );
  365.         }
  366.         else if( media != NULL )
  367.         {
  368.             message = vlm_Show( vlm, media, NULL, NULL );
  369.         }
  370.         else
  371.         {
  372.             message = vlm_Show( vlm, NULL, NULL, p_command[1] );
  373.         }
  374.         goto success;
  375.     }
  376.     else if( strcmp(p_command[0], "help") == 0 )
  377.     {
  378.         if( i_command != 1 ) goto syntax_error;
  379.         message = vlm_Help( vlm, NULL );
  380.         goto success;
  381.     }
  382.     else if( strcmp(p_command[0], "control") == 0 )
  383.     {
  384.         vlm_media_t *media;
  385.         if( i_command < 3 ) goto syntax_error;
  386.         if( !(media = vlm_MediaSearch( vlm, p_command[1] ) ) )
  387.         {
  388.             message = vlm_MessageNew( "control", "%s: media unknown",
  389.                                       p_command[1] );
  390.             goto error;
  391.         }
  392.         else
  393.         {
  394.             char *psz_command, *psz_arg = 0, *psz_instance = 0;
  395.             int i_index = 2;
  396.             if( strcmp(p_command[2], "play") && strcmp(p_command[2], "stop") &&
  397.                 strcmp(p_command[2], "pause") && strcmp(p_command[2], "seek") )
  398.             {
  399.                 i_index++;
  400.                 psz_instance = p_command[2];
  401.                 if( i_command < 4 ) goto syntax_error;
  402.             }
  403.             psz_command = p_command[i_index];
  404.             if( i_command >= i_index + 2 ) psz_arg = p_command[i_index + 1];
  405.             vlm_MediaControl( vlm, media, psz_instance, psz_command, psz_arg );
  406.             message = vlm_MessageNew( "control", NULL );
  407.             goto success;
  408.         }
  409.     }
  410.     else if( strcmp(p_command[0], "save") == 0 )
  411.     {
  412.         FILE *file;
  413.         if( i_command != 2 ) goto syntax_error;
  414.         file = fopen( p_command[1], "w" );
  415.         if( file == NULL )
  416.         {
  417.             message = vlm_MessageNew( "save", "Unable to save file" );
  418.             goto error;
  419.         }
  420.         else
  421.         {
  422.             char *save = vlm_Save( vlm );
  423.             fwrite( save, strlen( save ), 1, file );
  424.             fclose( file );
  425.             free( save );
  426.             message = vlm_MessageNew( "save", NULL );
  427.             goto success;
  428.         }
  429.     }
  430.     else if( strcmp(p_command[0], "load") == 0 )
  431.     {
  432.         FILE *file;
  433.         if( i_command != 2 ) goto syntax_error;
  434.         file = fopen( p_command[1], "r" );
  435.         if( file == NULL )
  436.         {
  437.             message = vlm_MessageNew( "load", "Unable to load file" );
  438.             goto error;
  439.         }
  440.         else
  441.         {
  442.             int64_t size;
  443.             char *buffer;
  444.             if( fseek( file, 0, SEEK_END) == 0 )
  445.             {
  446.                 size = ftell( file );
  447.                 fseek( file, 0, SEEK_SET);
  448.                 buffer = malloc( size + 1 );
  449.                 fread( buffer, 1, size, file);
  450.                 buffer[ size ] = '';
  451.                 if( vlm_Load( vlm, buffer ) )
  452.                 {
  453.                     free( buffer );
  454.                     message = vlm_MessageNew( "load", "error while loading "
  455.                                               "file" );
  456.                     goto error;
  457.                 }
  458.                 free( buffer );
  459.             }
  460.             else
  461.             {
  462.                 message = vlm_MessageNew( "load", "read file error" );
  463.                 goto error;
  464.             }
  465.             fclose( file );
  466.             message = vlm_MessageNew( "load", NULL );
  467.             goto success;
  468.         }
  469.     }
  470.     else
  471.     {
  472.         message = vlm_MessageNew( p_command[0], "Unknown command" );
  473.         goto error;
  474.     }
  475.     /* Common code between "new" and "setup" */
  476.     if( strcmp(p_command[0], "new") == 0 ||
  477.         strcmp(p_command[0], "setup") == 0 )
  478.     {
  479.         int i_command_start = strcmp(p_command[0], "new") ? 2 : 3;
  480.         vlm_media_t *media;
  481.         vlm_schedule_t *schedule;
  482.         if( i_command < i_command_start ) goto syntax_error;
  483.         media = vlm_MediaSearch( vlm, p_command[1] );
  484.         schedule = vlm_ScheduleSearch( vlm, p_command[1] );
  485.         if( !media && !schedule )
  486.         {
  487.             message = vlm_MessageNew( p_command[0], "%s unknown",
  488.                                       p_command[1] );
  489.             goto error;
  490.         }
  491.         if( schedule != NULL )
  492.         {
  493.             for( i = i_command_start ; i < i_command ; i++ )
  494.             {
  495.                 if( strcmp( p_command[i], "enabled" ) == 0 ||
  496.                     strcmp( p_command[i], "disabled" ) == 0 )
  497.                 {
  498.                     vlm_ScheduleSetup( schedule, p_command[i], NULL );
  499.                 }
  500.                 /* Beware: everything behind append is considered as 
  501.                  * command line */
  502.                 else if( strcmp( p_command[i], "append" ) == 0 )
  503.                 {
  504.                     if( ++i >= i_command ) break;
  505.                     for( j = i + 1; j < i_command; j++ )
  506.                     {
  507.                         p_command[i] =
  508.                             realloc( p_command[i], strlen(p_command[i]) +
  509.                                      strlen(p_command[j]) + 1 + 1 );
  510.                         strcat( p_command[i], " " );
  511.                         strcat( p_command[i], p_command[j] );
  512.                     }
  513.                     vlm_ScheduleSetup( schedule, p_command[i - 1],
  514.                                        p_command[i] );
  515.                     break;
  516.                 }
  517.                 else
  518.                 {
  519.                     if( i + 1 >= i_command && !strcmp(p_command[0], "new") )
  520.                     {
  521.                         vlm_ScheduleDelete( vlm, schedule, NULL );
  522.                         message = vlm_MessageNew( p_command[0],
  523.                                                   "Wrong properties syntax" );
  524.                         goto error;
  525.                     }
  526.                     else if( i + 1 >= i_command )
  527.                     {
  528.                         message = vlm_MessageNew( p_command[0],
  529.                                                   "Wrong properties syntax" );
  530.                         goto error;
  531.                     }
  532.                     vlm_ScheduleSetup( schedule, p_command[i],
  533.                                        p_command[i+1] );
  534.                     i++;
  535.                 }
  536.             }
  537.         }
  538.         else if( media != NULL )
  539.         {
  540.             for( i = i_command_start ; i < i_command ; i++ )
  541.             {
  542.                 if( strcmp( p_command[i], "enabled" ) == 0 ||
  543.                     strcmp( p_command[i], "disabled" ) == 0 )
  544.                 {
  545.                     vlm_MediaSetup( vlm, media, p_command[i], NULL );
  546.                 }
  547.                 else if( i + 1 >= i_command && !strcmp( p_command[i], "mux" ) )
  548.                 {
  549.                     if( media->i_type != VOD_TYPE )
  550.                     {
  551.                         message = vlm_MessageNew( p_command[0],
  552.                                   "mux only available for broadcast" );
  553.                     }
  554.                     else
  555.                     {
  556.                         vlm_MediaSetup( vlm, media, p_command[i],
  557.                                         p_command[i+1] );
  558.                         i++;
  559.                     }
  560.                 }
  561.                 else if( strcmp( p_command[i], "loop" ) == 0 ||
  562.                          strcmp( p_command[i], "unloop" ) == 0 )
  563.                 {
  564.                     if( media->i_type != BROADCAST_TYPE )
  565.                     {
  566.                         message = vlm_MessageNew( p_command[0],
  567.                                   "loop only available for broadcast" );
  568.                     }
  569.                     else
  570.                     {
  571.                         vlm_MediaSetup( vlm, media, p_command[i], NULL );
  572.                     }
  573.                 }
  574.                 else
  575.                 {
  576.                     if( i + 1 >= i_command && !strcmp(p_command[0], "new") )
  577.                     {
  578.                         vlm_MediaDelete( vlm, media, NULL );
  579.                         message = vlm_MessageNew( p_command[0],
  580.                                                   "Wrong properties syntax" );
  581.                         goto error;
  582.                     }
  583.                     else if( i + 1 >= i_command )
  584.                     {
  585.                         message = vlm_MessageNew( p_command[0],
  586.                                                   "Wrong properties syntax" );
  587.                         goto error;
  588.                     }
  589.                     vlm_MediaSetup( vlm, media, p_command[i], p_command[i+1] );
  590.                     i++;
  591.                 }
  592.             }
  593.         }
  594.         message = vlm_MessageNew( p_command[0], NULL );
  595.         goto success;
  596.     }
  597. success:
  598.     for( i = 0 ; i < i_command ; i++ ) free( p_command[i] );
  599.     if( p_command ) free( p_command );
  600.     *p_message = message;
  601.     return VLC_SUCCESS;
  602. syntax_error:
  603.     message = vlm_MessageNew( p_command[0], "Wrong command syntax" );
  604. error:
  605.     for( i = 0 ; i < i_command ; i++ ) free( p_command[i] );
  606.     if( p_command ) free( p_command );
  607.     *p_message = message;
  608.     return VLC_EGENERIC;
  609. }
  610. static vlm_media_t *vlm_MediaSearch( vlm_t *vlm, char *psz_name )
  611. {
  612.     int i;
  613.     for( i = 0; i < vlm->i_media; i++ )
  614.     {
  615.         if( strcmp( psz_name, vlm->media[i]->psz_name ) == 0 )
  616.         {
  617.             return vlm->media[i];
  618.         }
  619.     }
  620.     return NULL;
  621. }
  622. /*****************************************************************************
  623.  * Media handling
  624.  *****************************************************************************/
  625. static vlm_media_instance_t *
  626. vlm_MediaInstanceSearch( vlm_t *vlm, vlm_media_t *media, char *psz_name )
  627. {
  628.     int i;
  629.     for( i = 0; i < media->i_instance; i++ )
  630.     {
  631.         if( ( !psz_name && !media->instance[i]->psz_name ) ||
  632.             ( psz_name && media->instance[i]->psz_name &&
  633.               !strcmp( psz_name, media->instance[i]->psz_name ) ) )
  634.         {
  635.             return media->instance[i];
  636.         }
  637.     }
  638.     return NULL;
  639. }
  640. static vlm_media_t *vlm_MediaNew( vlm_t *vlm, char *psz_name, int i_type )
  641. {
  642.     vlm_media_t *media = malloc( sizeof( vlm_media_t ) );
  643.     /* Check if we need to load the VOD server */
  644.     if( i_type == VOD_TYPE && !vlm->i_vod )
  645.     {
  646.         vlm->vod = vlc_object_create( vlm, VLC_OBJECT_VOD );
  647.         vlc_object_attach( vlm->vod, vlm );
  648.         vlm->vod->p_module = module_Need( vlm->vod, "vod server", 0, 0 );
  649.         if( !vlm->vod->p_module )
  650.         {
  651.             msg_Err( vlm, "cannot find vod server" );
  652.             vlc_object_detach( vlm->vod );
  653.             vlc_object_destroy( vlm->vod );
  654.             vlm->vod = 0;
  655.             free( media );
  656.             return NULL;
  657.         }
  658.         vlm->vod->p_data = vlm;
  659.         vlm->vod->pf_media_control = vlm_MediaVodControl;
  660.     }
  661.     if( i_type == VOD_TYPE ) vlm->i_vod++;
  662.     media->psz_name = strdup( psz_name );
  663.     media->b_enabled = VLC_FALSE;
  664.     media->b_loop = VLC_FALSE;
  665.     media->vod_media = NULL;
  666.     media->psz_vod_output = NULL;
  667.     media->psz_mux = NULL;
  668.     media->i_input = 0;
  669.     media->input = NULL;
  670.     media->psz_output = NULL;
  671.     media->i_option = 0;
  672.     media->option = NULL;
  673.     media->i_type = i_type;
  674.     media->i_instance = 0;
  675.     media->instance = NULL;
  676.     media->item.psz_uri = strdup( psz_name );
  677.     vlc_input_item_Init( VLC_OBJECT(vlm), &media->item );
  678.     TAB_APPEND( vlm->i_media, vlm->media, media );
  679.     return media;
  680. }
  681. /* for now, simple delete. After, del with options (last arg) */
  682. static void vlm_MediaDelete( vlm_t *vlm, vlm_media_t *media, char *psz_name )
  683. {
  684.     if( media == NULL ) return;
  685.     while( media->i_instance )
  686.     {
  687.         vlm_media_instance_t *p_instance = media->instance[0];
  688.         vlm_MediaControl( vlm, media, p_instance->psz_name, "stop", 0 );
  689.     }
  690.     TAB_REMOVE( vlm->i_media, vlm->media, media );
  691.     if( media->i_type == VOD_TYPE )
  692.     {
  693.         vlm_MediaSetup( vlm, media, "disabled", 0 );
  694.         vlm->i_vod--;
  695.     }
  696.     /* Check if we need to unload the VOD server */
  697.     if( media->i_type == VOD_TYPE && !vlm->i_vod )
  698.     {
  699.         module_Unneed( vlm->vod, vlm->vod->p_module );
  700.         vlc_object_detach( vlm->vod );
  701.         vlc_object_destroy( vlm->vod );
  702.         vlm->vod = 0;
  703.     }
  704.     if( vlm->i_media == 0 && vlm->media ) free( vlm->media );
  705.     free( media->psz_name );
  706.     while( media->i_input-- ) free( media->input[media->i_input] );
  707.     if( media->input ) free( media->input );
  708.     if( media->psz_output ) free( media->psz_output );
  709.     if( media->psz_mux ) free( media->psz_mux );
  710.     while( media->i_option-- ) free( media->option[media->i_option] );
  711.     if( media->option ) free( media->option );
  712.     vlc_input_item_Clean( &media->item );
  713.     free( media );
  714. }
  715. static int vlm_MediaSetup( vlm_t *vlm, vlm_media_t *media, char *psz_cmd,
  716.                            char *psz_value )
  717. {
  718.     if( strcmp( psz_cmd, "loop" ) == 0 )
  719.     {
  720.         media->b_loop = VLC_TRUE;
  721.     }
  722.     else if( strcmp( psz_cmd, "unloop" ) == 0 )
  723.     {
  724.         media->b_loop = VLC_FALSE;
  725.     }
  726.     else if( strcmp( psz_cmd, "enabled" ) == 0 )
  727.     {
  728.         media->b_enabled = VLC_TRUE;
  729.     }
  730.     else if( strcmp( psz_cmd, "disabled" ) == 0 )
  731.     {
  732.         media->b_enabled = VLC_FALSE;
  733.     }
  734.     else if( strcmp( psz_cmd, "mux" ) == 0 )
  735.     {
  736.         if( media->psz_mux ) free( media->psz_mux );
  737.         media->psz_mux = NULL;
  738.         if( psz_value ) media->psz_mux = strdup( psz_value );
  739.     }
  740.     else if( strcmp( psz_cmd, "input" ) == 0 )
  741.     {
  742.         char *input;
  743.         if( psz_value != NULL && strlen(psz_value) > 1 &&
  744.             ( psz_value[0] == ''' || psz_value[0] == '"' ) &&
  745.             ( psz_value[ strlen(psz_value) - 1 ] == ''' ||
  746.               psz_value[ strlen(psz_value) - 1 ] == '"' )  )
  747.         {
  748.             input = malloc( strlen(psz_value) - 1 );
  749.             memcpy( input, psz_value + 1, strlen(psz_value) - 2 );
  750.             input[ strlen(psz_value) - 2 ] = '';
  751.         }
  752.         else
  753.         {
  754.             input = strdup( psz_value );
  755.         }
  756.         TAB_APPEND( media->i_input, media->input, input );
  757.     }
  758.     else if( strcmp( psz_cmd, "output" ) == 0 )
  759.     {
  760.         if( media->psz_output != NULL )
  761.         {
  762.             free( media->psz_output );
  763.         }
  764.         media->psz_output = strdup( psz_value );
  765.     }
  766.     else if( strcmp( psz_cmd, "option" ) == 0 )
  767.     {
  768.         char *option;
  769.         option = strdup( psz_value );
  770.         TAB_APPEND( media->i_option, media->option, option );
  771.     }
  772.     else
  773.     {
  774.         return VLC_EGENERIC;
  775.     }
  776.     /* Check if we need to create/delete a vod media */
  777.     if( media->i_type == VOD_TYPE )
  778.     {
  779.         if( !media->b_enabled && media->vod_media )
  780.         {
  781.             vlm->vod->pf_media_del( vlm->vod, media->vod_media );
  782.             media->vod_media = 0;
  783.         }
  784.         else if( media->b_enabled && !media->vod_media && media->i_input )
  785.         {
  786.             /* Pre-parse the input */
  787.             input_thread_t *p_input;
  788.             char *psz_output;
  789.             int i;
  790.             vlc_input_item_Clean( &media->item );
  791.             vlc_input_item_Init( VLC_OBJECT(vlm), &media->item );
  792.             if( media->psz_output )
  793.                 asprintf( &psz_output, "%s:description", media->psz_output );
  794.             else
  795.                 asprintf( &psz_output, "#description" );
  796.             media->item.psz_uri = strdup( media->input[0] );
  797.             media->item.ppsz_options = malloc( sizeof( char* ) );
  798.             asprintf( &media->item.ppsz_options[0], "sout=%s", psz_output);
  799.             media->item.i_options = 1;
  800.             for( i = 0; i < media->i_option; i++ )
  801.             {
  802.                 media->item.i_options++;
  803.                 media->item.ppsz_options =
  804.                     realloc( media->item.ppsz_options,
  805.                              media->item.i_options * sizeof( char* ) );
  806.                 media->item.ppsz_options[ media->item.i_options - 1 ] =
  807.                     strdup( media->option[i] );
  808.             }
  809.             if( (p_input = input_CreateThread( vlm, &media->item ) ) )
  810.             {
  811.                 while( !p_input->b_eof && !p_input->b_error ) msleep( 100000 );
  812.                 input_StopThread( p_input );
  813.                 input_DestroyThread( p_input );
  814.                 vlc_object_detach( p_input );
  815.                 vlc_object_destroy( p_input );
  816.             }
  817.             free( psz_output );
  818.             if( media->psz_mux )
  819.             {
  820.                 input_item_t item;
  821.                 es_format_t es, *p_es = &es;
  822.                 char fourcc[5];
  823.                 sprintf( fourcc, "%4.4s", media->psz_mux );
  824.                 fourcc[0] = tolower(fourcc[0]); fourcc[1] = tolower(fourcc[1]);
  825.                 fourcc[2] = tolower(fourcc[2]); fourcc[3] = tolower(fourcc[3]);
  826.                 item = media->item;
  827.                 item.i_es = 1;
  828.                 item.es = &p_es;
  829.                 es_format_Init( &es, VIDEO_ES, *((int *)fourcc) );
  830.                 media->vod_media =
  831.                   vlm->vod->pf_media_new( vlm->vod, media->psz_name, &item );
  832.                 return VLC_SUCCESS;
  833.             }
  834.             media->vod_media =
  835.                 vlm->vod->pf_media_new( vlm->vod, media->psz_name,
  836.                                         &media->item );
  837.         }
  838.     }
  839.     return VLC_SUCCESS;
  840. }
  841. static int vlm_MediaControl( vlm_t *vlm, vlm_media_t *media, char *psz_id,
  842.                              char *psz_command, char *psz_args )
  843. {
  844.     vlm_media_instance_t *p_instance;
  845.     int i;
  846.     p_instance = vlm_MediaInstanceSearch( vlm, media, psz_id );
  847.     if( strcmp( psz_command, "play" ) == 0 && !p_instance )
  848.     {
  849.         if( !media->b_enabled || media->i_input == 0 ) return 0;
  850.         if( !p_instance )
  851.         {
  852.             p_instance = malloc( sizeof(vlm_media_instance_t) );
  853.             memset( p_instance, 0, sizeof(vlm_media_instance_t) );
  854.             vlc_input_item_Init( VLC_OBJECT(vlm), &p_instance->item );
  855.             p_instance->p_input = 0;
  856.             if( media->psz_output != NULL || media->psz_vod_output != NULL )
  857.             {
  858.                 p_instance->item.ppsz_options = malloc( sizeof( char* ) );
  859.                 asprintf( &p_instance->item.ppsz_options[0], "sout=%s%s%s",
  860.                           media->psz_output ? media->psz_output : "",
  861.                           (media->psz_output && media->psz_vod_output) ?
  862.                           ":" : media->psz_vod_output ? "#" : "",
  863.                           media->psz_vod_output ? media->psz_vod_output : "" );
  864.                 p_instance->item.i_options = 1;
  865.             }
  866.             for( i = 0; i < media->i_option; i++ )
  867.             {
  868.                 p_instance->item.i_options++;
  869.                 p_instance->item.ppsz_options =
  870.                     realloc( p_instance->item.ppsz_options,
  871.                              p_instance->item.i_options * sizeof( char* ) );
  872.                 p_instance->item.ppsz_options[p_instance->item.i_options - 1] =
  873.                     strdup( media->option[i] );
  874.             }
  875.             p_instance->psz_name = psz_id ? strdup(psz_id) : 0;
  876.             TAB_APPEND( media->i_instance, media->instance, p_instance );
  877.         }
  878.         if( psz_args && sscanf(psz_args, "%d", &i) == 1 && i < media->i_input )
  879.         {
  880.             p_instance->i_index = i;
  881.         }
  882.         if( p_instance->item.psz_uri ) free( p_instance->item.psz_uri );
  883.         p_instance->item.psz_uri =
  884.             strdup( media->input[p_instance->i_index] );
  885.         if( p_instance->p_input )
  886.         {
  887.             input_StopThread( p_instance->p_input );
  888.             input_DestroyThread( p_instance->p_input );
  889.             vlc_object_detach( p_instance->p_input );
  890.             vlc_object_destroy( p_instance->p_input );
  891.         }
  892.         p_instance->p_input = input_CreateThread( vlm, &p_instance->item );
  893.         if( !p_instance->p_input )
  894.         {
  895.             TAB_REMOVE( media->i_instance, media->instance, p_instance );
  896.             vlc_input_item_Clean( &p_instance->item );
  897.             if( p_instance->psz_name ) free( p_instance->psz_name );
  898.         }
  899.         return VLC_SUCCESS;
  900.     }
  901.     if( !p_instance ) return VLC_EGENERIC;
  902.     if( strcmp( psz_command, "seek" ) == 0 )
  903.     {
  904.         vlc_value_t val;
  905.         float f_percentage;
  906.         if( psz_args && sscanf( psz_args, "%f", &f_percentage ) == 1 )
  907.         {
  908.             val.f_float = f_percentage / 100.0 ;
  909.             var_Set( p_instance->p_input, "position", val );
  910.             return VLC_SUCCESS;
  911.         }
  912.     }
  913.     else if( strcmp( psz_command, "stop" ) == 0 )
  914.     {
  915.         TAB_REMOVE( media->i_instance, media->instance, p_instance );
  916.         if( p_instance->p_input )
  917.         {
  918.             input_StopThread( p_instance->p_input );
  919.             input_DestroyThread( p_instance->p_input );
  920.             vlc_object_detach( p_instance->p_input );
  921.             vlc_object_destroy( p_instance->p_input );
  922.         }
  923.         vlc_input_item_Clean( &p_instance->item );
  924.         if( p_instance->psz_name ) free( p_instance->psz_name );
  925.         free( p_instance );
  926.         return VLC_SUCCESS;
  927.     }
  928.     else if( strcmp( psz_command, "pause" ) == 0 )
  929.     {
  930.         vlc_value_t val;
  931.         if( !p_instance->p_input ) return VLC_SUCCESS;
  932.         var_Get( p_instance->p_input, "state", &val );
  933.         if( val.i_int == PAUSE_S ) val.i_int = PLAYING_S;
  934.         else val.i_int = PAUSE_S;
  935.         var_Set( p_instance->p_input, "state", val );
  936.         return VLC_SUCCESS;
  937.     }
  938.     return VLC_EGENERIC;
  939. }
  940. /*****************************************************************************
  941.  * Schedule handling
  942.  *****************************************************************************/
  943. static vlm_schedule_t *vlm_ScheduleNew( vlm_t *vlm, char *psz_name )
  944. {
  945.     vlm_schedule_t *sched = malloc( sizeof( vlm_schedule_t ) );
  946.     sched->psz_name = strdup( psz_name );
  947.     sched->b_enabled = VLC_FALSE;
  948.     sched->i_command = 0;
  949.     sched->command = NULL;
  950.     sched->i_date = 0;
  951.     sched->i_period = 0;
  952.     sched->i_repeat = -1;
  953.     TAB_APPEND( vlm->i_schedule, vlm->schedule, sched );
  954.     return sched;
  955. }
  956. /* for now, simple delete. After, del with options (last arg) */
  957. static void vlm_ScheduleDelete( vlm_t *vlm, vlm_schedule_t *sched,
  958.                                 char *psz_name )
  959. {
  960.     if( sched == NULL ) return;
  961.     TAB_REMOVE( vlm->i_schedule, vlm->schedule, sched );
  962.     if( vlm->i_schedule == 0 && vlm->schedule ) free( vlm->schedule );
  963.     free( sched->psz_name );
  964.     while( sched->i_command-- ) free( sched->command[sched->i_command] );
  965.     free( sched );
  966. }
  967. static vlm_schedule_t *vlm_ScheduleSearch( vlm_t *vlm, char *psz_name )
  968. {
  969.     int i;
  970.     for( i = 0; i < vlm->i_schedule; i++ )
  971.     {
  972.         if( strcmp( psz_name, vlm->schedule[i]->psz_name ) == 0 )
  973.         {
  974.             return vlm->schedule[i];
  975.         }
  976.     }
  977.     return NULL;
  978. }
  979. /* Ok, setup schedule command will be able to support only one (argument value) at a time  */
  980. static int vlm_ScheduleSetup( vlm_schedule_t *schedule, char *psz_cmd,
  981.                               char *psz_value )
  982. {
  983.     if( strcmp( psz_cmd, "enabled" ) == 0 )
  984.     {
  985.         schedule->b_enabled = VLC_TRUE;
  986.     }
  987.     else if( strcmp( psz_cmd, "disabled" ) == 0 )
  988.     {
  989.         schedule->b_enabled = VLC_FALSE;
  990.     }
  991. #if !defined( UNDER_CE )
  992.     else if( strcmp( psz_cmd, "date" ) == 0 )
  993.     {
  994.         struct tm time;
  995.         char *p;
  996.         time_t date;
  997.         time.tm_sec = 0;         /* seconds */
  998.         time.tm_min = 0;         /* minutes */
  999.         time.tm_hour = 0;        /* hours */
  1000.         time.tm_mday = 0;        /* day of the month */
  1001.         time.tm_mon = 0;         /* month */
  1002.         time.tm_year = 0;        /* year */
  1003.         time.tm_wday = 0;        /* day of the week */
  1004.         time.tm_yday = 0;        /* day in the year */
  1005.         time.tm_isdst = 0;       /* daylight saving time */
  1006.         /* date should be year/month/day-hour:minutes:seconds */
  1007.         p = strchr( psz_value, '-' );
  1008.         if( strcmp( psz_value, "now" ) == 0 )
  1009.         {
  1010.             schedule->i_date = 0;
  1011.         }
  1012.         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 */
  1013.         {
  1014.             return 1;
  1015.         }
  1016.         else
  1017.         {
  1018.             int i,j,k;
  1019.             switch( sscanf( p + 1, "%d:%d:%d", &i, &j, &k ) )
  1020.             {
  1021.                 case 1:
  1022.                     time.tm_sec = i;
  1023.                     break;
  1024.                 case 2:
  1025.                     time.tm_min = i;
  1026.                     time.tm_sec = j;
  1027.                     break;
  1028.                 case 3:
  1029.                     time.tm_hour = i;
  1030.                     time.tm_min = j;
  1031.                     time.tm_sec = k;
  1032.                     break;
  1033.                 default:
  1034.                     return 1;
  1035.             }
  1036.             *p = '';
  1037.             switch( sscanf( psz_value, "%d/%d/%d", &i, &j, &k ) )
  1038.             {
  1039.                 case 1:
  1040.                     time.tm_mday = i;
  1041.                     break;
  1042.                 case 2:
  1043.                     time.tm_mon = i - 1;
  1044.                     time.tm_mday = j;
  1045.                     break;
  1046.                 case 3:
  1047.                     time.tm_year = i - 1900;
  1048.                     time.tm_mon = j - 1;
  1049.                     time.tm_mday = k;
  1050.                     break;
  1051.                 default:
  1052.                     return 1;
  1053.             }
  1054.             date = mktime( &time );
  1055.             schedule->i_date = ((mtime_t) date) * 1000000;
  1056.         }
  1057.     }
  1058.     else if( strcmp( psz_cmd, "period" ) == 0 )
  1059.     {
  1060.         struct tm time;
  1061.         char *p;
  1062.         char *psz_time = NULL, *psz_date = NULL;
  1063.         time_t date;
  1064.         int i,j,k;
  1065.         /* First, if date or period are modified, repeat should be equal to -1 */
  1066.         schedule->i_repeat = -1;
  1067.         time.tm_sec = 0;         /* seconds */
  1068.         time.tm_min = 0;         /* minutes */
  1069.         time.tm_hour = 0;        /* hours */
  1070.         time.tm_mday = 0;        /* day of the month */
  1071.         time.tm_mon = 0;         /* month */
  1072.         time.tm_year = 0;        /* year */
  1073.         time.tm_wday = 0;        /* day of the week */
  1074.         time.tm_yday = 0;        /* day in the year */
  1075.         time.tm_isdst = 0;       /* daylight saving time */
  1076.         /* date should be year/month/day-hour:minutes:seconds */
  1077.         p = strchr( psz_value, '-' );
  1078.         if( p )
  1079.         {
  1080.             psz_date = psz_value;
  1081.             psz_time = p + 1;
  1082.             *p = '';
  1083.         }
  1084.         else
  1085.         {
  1086.             psz_time = psz_value;
  1087.         }
  1088.         switch( sscanf( psz_time, "%d:%d:%d", &i, &j, &k ) )
  1089.         {
  1090.             case 1:
  1091.                 time.tm_sec = i;
  1092.                 break;
  1093.             case 2:
  1094.                 time.tm_min = i;
  1095.                 time.tm_sec = j;
  1096.                 break;
  1097.             case 3:
  1098.                 time.tm_hour = i;
  1099.                 time.tm_min = j;
  1100.                 time.tm_sec = k;
  1101.                 break;
  1102.             default:
  1103.                 return 1;
  1104.         }
  1105.         if( psz_date )
  1106.         {
  1107.             switch( sscanf( psz_date, "%d/%d/%d", &i, &j, &k ) )
  1108.             {
  1109.                 case 1:
  1110.                     time.tm_mday = i;
  1111.                     break;
  1112.                 case 2:
  1113.                     time.tm_mon = i;
  1114.                     time.tm_mday = j;
  1115.                     break;
  1116.                 case 3:
  1117.                     time.tm_year = i;
  1118.                     time.tm_mon = j;
  1119.                     time.tm_mday = k;
  1120.                     break;
  1121.                 default:
  1122.                     return 1;
  1123.             }
  1124.         }
  1125.         /* ok, that's stupid... who is going to schedule streams every 42 years ? */
  1126.         date = (((( time.tm_year * 12 + time.tm_mon ) * 30 + time.tm_mday ) * 24 + time.tm_hour ) * 60 + time.tm_min ) * 60 + time.tm_sec ;
  1127.         schedule->i_period = ((mtime_t) date) * 1000000;
  1128.     }
  1129. #endif /* UNDER_CE */
  1130.     else if( strcmp( psz_cmd, "repeat" ) == 0 )
  1131.     {
  1132.         int i;
  1133.         if( sscanf( psz_value, "%d", &i ) == 1 )
  1134.         {
  1135.             schedule->i_repeat = i;
  1136.         }
  1137.         else
  1138.         {
  1139.             return 1;
  1140.         }
  1141.     }
  1142.     else if( strcmp( psz_cmd, "append" ) == 0 )
  1143.     {
  1144.         char *command = strdup( psz_value );
  1145.         TAB_APPEND( schedule->i_command, schedule->command, command );
  1146.     }
  1147.     else
  1148.     {
  1149.         return 1;
  1150.     }
  1151.     return 0;
  1152. }
  1153. /*****************************************************************************
  1154.  * Message handling functions
  1155.  *****************************************************************************/
  1156. static vlm_message_t *vlm_MessageNew( char *psz_name,
  1157.                                       const char *psz_format, ... )
  1158. {
  1159.     vlm_message_t *p_message;
  1160.     va_list args;
  1161.     if( !psz_name ) return 0;
  1162.     p_message = malloc( sizeof(vlm_message_t) );
  1163.     p_message->psz_value = 0;
  1164.     if( psz_format )
  1165.     {
  1166.         va_start( args, psz_format );
  1167.         if( vasprintf( &p_message->psz_value, psz_format, args ) < 0 )
  1168.         {
  1169.             va_end( args );
  1170.             free( p_message );
  1171.             return 0;
  1172.         }
  1173.         va_end( args );
  1174.     }
  1175.     p_message->psz_name = strdup( psz_name );
  1176.     p_message->i_child = 0;
  1177.     p_message->child = NULL;
  1178.     return p_message;
  1179. }
  1180. void vlm_MessageDelete( vlm_message_t *p_message )
  1181. {
  1182.     if( p_message->psz_name ) free( p_message->psz_name );
  1183.     if( p_message->psz_value ) free( p_message->psz_value );
  1184.     while( p_message->i_child-- )
  1185.         vlm_MessageDelete( p_message->child[p_message->i_child] );
  1186.     if( p_message->child ) free( p_message->child );
  1187.     free( p_message );
  1188. }
  1189. /* Add a child */
  1190. static vlm_message_t *vlm_MessageAdd( vlm_message_t *p_message,
  1191.                                       vlm_message_t *p_child )
  1192. {
  1193.     if( p_message == NULL ) return NULL;
  1194.     if( p_child )
  1195.     {
  1196.         TAB_APPEND( p_message->i_child, p_message->child, p_child );
  1197.     }
  1198.     return p_child;
  1199. }
  1200. /*****************************************************************************
  1201.  * Misc utility functions
  1202.  *****************************************************************************/
  1203. static vlm_message_t *vlm_Show( vlm_t *vlm, vlm_media_t *media,
  1204.                                 vlm_schedule_t *schedule, char *psz_filter )
  1205. {
  1206.     if( media != NULL )
  1207.     {
  1208.         int i;
  1209.         vlm_message_t *msg;
  1210.         vlm_message_t *msg_media;
  1211.         vlm_message_t *msg_child;
  1212.         msg = vlm_MessageNew( "show", NULL );
  1213.         msg_media = vlm_MessageAdd( msg, vlm_MessageNew( media->psz_name, 0 ));
  1214.         vlm_MessageAdd( msg_media,
  1215.                         vlm_MessageNew( "type", media->i_type == VOD_TYPE ?
  1216.                                         "vod" : "broadcast" ) );
  1217.         vlm_MessageAdd( msg_media,
  1218.                         vlm_MessageNew( "enabled", media->b_enabled ?
  1219.                                         "yes" : "no" ) );
  1220.         vlm_MessageAdd( msg_media,
  1221.                         vlm_MessageNew( "loop", media->b_loop ?
  1222.                                         "yes" : "no" ) );
  1223.         if( media->i_type == VOD_TYPE && media->psz_mux )
  1224.             vlm_MessageAdd( msg_media,
  1225.                             vlm_MessageNew( "mux", media->psz_mux ) );
  1226.         msg_child = vlm_MessageAdd( msg_media,
  1227.                                     vlm_MessageNew( "inputs", NULL ) );
  1228.         for( i = 0; i < media->i_input; i++ )
  1229.         {
  1230.             vlm_MessageAdd( msg_child,
  1231.                             vlm_MessageNew( media->input[i], NULL ) );
  1232.         }
  1233.         vlm_MessageAdd( msg_media,
  1234.                         vlm_MessageNew( "output", media->psz_output ?
  1235.                                         media->psz_output : "" ) );
  1236.         msg_child = vlm_MessageAdd( msg_media, vlm_MessageNew( "options", 0 ));
  1237.         for( i = 0; i < media->i_option; i++ )
  1238.         {
  1239.             vlm_MessageAdd( msg_child, vlm_MessageNew( media->option[i], 0 ) );
  1240.         }
  1241.         msg_child = vlm_MessageAdd( msg_media,
  1242.                                     vlm_MessageNew( "instances", NULL ) );
  1243.         for( i = 0; i < media->i_instance; i++ )
  1244.         {
  1245.             vlm_media_instance_t *p_instance = media->instance[i];
  1246.             vlc_value_t val;
  1247.             if( !p_instance->p_input ) val.i_int = END_S;
  1248.             else var_Get( p_instance->p_input, "state", &val );
  1249.             vlm_MessageAdd( msg_child,
  1250.                 vlm_MessageNew( p_instance->psz_name ?
  1251.                                 p_instance->psz_name : "default",
  1252.                                 val.i_int == PLAYING_S ? "playing" :
  1253.                                 val.i_int == PAUSE_S ? "paused" :
  1254.                                 "stopped" ) );
  1255.         }
  1256.         return msg;
  1257.     }
  1258.     else if( schedule != NULL )
  1259.     {
  1260.         int i;
  1261.         vlm_message_t *msg;
  1262.         vlm_message_t *msg_schedule;
  1263.         vlm_message_t *msg_child;
  1264.         char buffer[100];
  1265.         msg = vlm_MessageNew( "show", NULL );
  1266.         msg_schedule =
  1267.             vlm_MessageAdd( msg, vlm_MessageNew( schedule->psz_name, 0 ) );
  1268.         vlm_MessageAdd( msg_schedule, vlm_MessageNew("type", "schedule") );
  1269.         vlm_MessageAdd( msg_schedule,
  1270.                         vlm_MessageNew( "enabled", schedule->b_enabled ?
  1271.                                         "yes" : "no" ) );
  1272. #if !defined( UNDER_CE )
  1273.         if( schedule->i_date != 0 )
  1274.         {
  1275.             struct tm date;
  1276.             time_t i_time = (time_t)( schedule->i_date / 1000000 );
  1277.             char *psz_date;
  1278. #ifdef HAVE_LOCALTIME_R
  1279.             localtime_r( &i_time, &date);
  1280. #else
  1281.             struct tm *p_date = localtime( &i_time );
  1282.             date = *p_date;
  1283. #endif
  1284.             asprintf( &psz_date, "%d/%d/%d-%d:%d:%d",
  1285.                       date.tm_year + 1900, date.tm_mon + 1, date.tm_mday,
  1286.                       date.tm_hour, date.tm_min, date.tm_sec );
  1287.             vlm_MessageAdd( msg_schedule,
  1288.                             vlm_MessageNew( "date", psz_date ) );
  1289.             free( psz_date );
  1290.         }
  1291.         else
  1292.         {
  1293.             vlm_MessageAdd( msg_schedule, vlm_MessageNew("date", "now") );
  1294.         }
  1295.         if( schedule->i_period != 0 )
  1296.         {
  1297.             time_t i_time = (time_t) ( schedule->i_period / 1000000 );
  1298.             struct tm date;
  1299.             date.tm_sec = (int)( i_time % 60 );
  1300.             i_time = i_time / 60;
  1301.             date.tm_min = (int)( i_time % 60 );
  1302.             i_time = i_time / 60;
  1303.             date.tm_hour = (int)( i_time % 24 );
  1304.             i_time = i_time / 24;
  1305.             date.tm_mday = (int)( i_time % 30 );
  1306.             i_time = i_time / 30;
  1307.             /* okay, okay, months are not always 30 days long */
  1308.             date.tm_mon = (int)( i_time % 12 );
  1309.             i_time = i_time / 12;
  1310.             date.tm_year = (int)i_time;
  1311.             sprintf( buffer, "%d/%d/%d-%d:%d:%d", date.tm_year, date.tm_mon,
  1312.                      date.tm_mday, date.tm_hour, date.tm_min, date.tm_sec);
  1313.             vlm_MessageAdd( msg_schedule, vlm_MessageNew("period", buffer) );
  1314.         }
  1315.         else
  1316.         {
  1317.             vlm_MessageAdd( msg_schedule, vlm_MessageNew("period", "0") );
  1318.         }
  1319. #endif /* UNDER_CE */
  1320.         sprintf( buffer, "%d", schedule->i_repeat );
  1321.         vlm_MessageAdd( msg_schedule, vlm_MessageNew( "repeat", buffer ) );
  1322.         msg_child =
  1323.             vlm_MessageAdd( msg_schedule, vlm_MessageNew("commands", 0) );
  1324.         for( i = 0; i < schedule->i_command; i++ )
  1325.         {
  1326.            vlm_MessageAdd( msg_child,
  1327.                            vlm_MessageNew( schedule->command[i], NULL ) );
  1328.         }
  1329.         return msg;
  1330.     }
  1331.     else if( psz_filter && strcmp( psz_filter, "media" ) == 0 )
  1332.     {
  1333.         int i, j;
  1334.         vlm_message_t *msg;
  1335.         vlm_message_t *msg_child;
  1336.         msg = vlm_MessageNew( "show", NULL );
  1337.         msg_child = vlm_MessageAdd( msg, vlm_MessageNew( "media", NULL ) );
  1338.         for( i = 0; i < vlm->i_media; i++ )
  1339.         {
  1340.             vlm_media_t *m = vlm->media[i];
  1341.             vlm_message_t *msg_media, *msg_instance;
  1342.             msg_media = vlm_MessageAdd( msg_child,
  1343.                                         vlm_MessageNew( m->psz_name, 0 ) );
  1344.             vlm_MessageAdd( msg_media,
  1345.                             vlm_MessageNew( "type", m->i_type == VOD_TYPE ?
  1346.                                             "vod" : "broadcast" ) );
  1347.             vlm_MessageAdd( msg_media,
  1348.                             vlm_MessageNew( "enabled", m->b_enabled ?
  1349.                                             "yes" : "no" ) );
  1350.             if( m->i_type == VOD_TYPE && m->psz_mux )
  1351.                 vlm_MessageAdd( msg_media,
  1352.                                 vlm_MessageNew( "mux", m->psz_mux ) );
  1353.             msg_instance = vlm_MessageAdd( msg_media,
  1354.                                            vlm_MessageNew( "instances", 0 ) );
  1355.             for( j = 0; j < m->i_instance; j++ )
  1356.             {
  1357.                 vlm_media_instance_t *p_instance = m->instance[j];
  1358.                 vlc_value_t val;
  1359.                 if( !p_instance->p_input ) val.i_int = END_S;
  1360.                 else var_Get( p_instance->p_input, "state", &val );
  1361.                 vlm_MessageAdd( msg_instance,
  1362.                     vlm_MessageNew( p_instance->psz_name ?
  1363.                                     p_instance->psz_name : "default",
  1364.                                     val.i_int == PLAYING_S ? "playing" :
  1365.                                     val.i_int == PAUSE_S ? "paused" :
  1366.                                     "stopped" ) );
  1367.             }
  1368.         }
  1369.         return msg;
  1370.     }
  1371.     else if( psz_filter && strcmp( psz_filter, "schedule") == 0 )
  1372.     {
  1373.         int i;
  1374.         vlm_message_t *msg;
  1375.         vlm_message_t *msg_child;
  1376.         msg = vlm_MessageNew( "show", NULL );
  1377.         msg_child = vlm_MessageAdd( msg, vlm_MessageNew( "schedule", NULL ) );
  1378.         for( i = 0; i < vlm->i_schedule; i++ )
  1379.         {
  1380.             vlm_schedule_t *s = vlm->schedule[i];
  1381.             vlm_message_t *msg_schedule;
  1382.             mtime_t i_time, i_next_date;
  1383.             msg_schedule = vlm_MessageAdd( msg_child,
  1384.                                            vlm_MessageNew( s->psz_name, 0 ) );
  1385.             vlm_MessageAdd( msg_schedule,
  1386.                             vlm_MessageNew( "enabled", s->b_enabled ?
  1387.                                             "yes" : "no" ) );
  1388.             if( !s->b_enabled ) return msg;
  1389.             vlm_MessageAdd( msg_schedule,
  1390.                             vlm_MessageNew( "enabled", "yes" ) );
  1391.             /* calculate next date */
  1392.             i_time = mdate();
  1393.             i_next_date = s->i_date;
  1394.             if( s->i_period != 0 )
  1395.             {
  1396.                 int j = 0;
  1397.                 while( s->i_date + j * s->i_period <= i_time &&
  1398.                        s->i_repeat > j )
  1399.                 {
  1400.                     j++;
  1401.                 }
  1402.                 i_next_date = s->i_date + j * s->i_period;
  1403.             }
  1404.             if( i_next_date > i_time )
  1405.             {
  1406.                 time_t i_date = (time_t) (i_next_date / 1000000) ;
  1407. #if !defined( UNDER_CE )
  1408. #ifdef HAVE_CTIME_R
  1409.                 char psz_date[500];
  1410.                 ctime_r( &i_date, psz_date );
  1411. #else
  1412.                 char *psz_date = ctime( &i_date );
  1413. #endif
  1414.                 vlm_MessageAdd( msg_schedule,
  1415.                                 vlm_MessageNew( "next launch", psz_date ) );
  1416. #endif
  1417.             }
  1418.         }
  1419.         return msg;
  1420.     }
  1421.     else if( psz_filter == NULL && media == NULL && schedule == NULL )
  1422.     {
  1423.         vlm_message_t *show1 = vlm_Show( vlm, NULL, NULL, "media" );
  1424.         vlm_message_t *show2 = vlm_Show( vlm, NULL, NULL, "schedule" );
  1425.         vlm_MessageAdd( show1, show2->child[0] );
  1426.         /* We must destroy the parent node "show" of show2
  1427.          * and not the children */
  1428.         free( show2->psz_name );
  1429.         free( show2 );
  1430.         return show1;
  1431.     }
  1432.     else
  1433.     {
  1434.         return vlm_MessageNew( "show", NULL );
  1435.     }
  1436. }
  1437. static vlm_message_t *vlm_Help( vlm_t *vlm, char *psz_filter )
  1438. {
  1439.     vlm_message_t *message, *message_child;
  1440. #define MessageAdd( a ) 
  1441.         vlm_MessageAdd( message, vlm_MessageNew( a, NULL ) );
  1442. #define MessageAddChild( a ) 
  1443.         vlm_MessageAdd( message_child, vlm_MessageNew( a, NULL ) );
  1444.     if( psz_filter == NULL )
  1445.     {
  1446.         message = vlm_MessageNew( "help", NULL );
  1447.         message_child = MessageAdd( "Commands Syntax:" );
  1448.         MessageAddChild( "new (name) vod|broadcast|schedule [properties]" );
  1449.         MessageAddChild( "setup (name) (properties)" );
  1450.         MessageAddChild( "show [(name)|media|schedule]" );
  1451.         MessageAddChild( "del (name)|all|media|schedule" );
  1452.         MessageAddChild( "control (name) [instance_name] (command)" );
  1453.         MessageAddChild( "save (config_file)" );
  1454.         MessageAddChild( "load (config_file)" );
  1455.         message_child = MessageAdd( "Media Proprieties Syntax:" );
  1456.         MessageAddChild( "input (input_name)" );
  1457.         MessageAddChild( "output (output_name)" );
  1458.         MessageAddChild( "enabled|disabled" );
  1459.         MessageAddChild( "loop|unloop (broadcast only)" );
  1460.         MessageAddChild( "mux (mux_name)" );
  1461.         message_child = MessageAdd( "Schedule Proprieties Syntax:" );
  1462.         MessageAddChild( "enabled|disabled" );
  1463.         MessageAddChild( "append (command_until_rest_of_the_line)" );
  1464.         MessageAddChild( "date (year)/(month)/(day)-(hour):(minutes):"
  1465.                          "(seconds)|now" );
  1466.         MessageAddChild( "period (years_aka_12_months)/(months_aka_30_days)/"
  1467.                          "(days)-(hours):(minutes):(seconds)" );
  1468.         MessageAddChild( "repeat (number_of_repetitions)" );
  1469.         message_child = MessageAdd( "Control Commands Syntax:" );
  1470.         MessageAddChild( "play" );
  1471.         MessageAddChild( "pause" );
  1472.         MessageAddChild( "stop" );
  1473.         MessageAddChild( "seek (percentage)" );
  1474.         return message;
  1475.     }
  1476.     return vlm_MessageNew( "help", NULL );
  1477. }
  1478. /*****************************************************************************
  1479.  * Config handling functions
  1480.  *****************************************************************************/
  1481. static int vlm_Load( vlm_t *vlm, char *file )
  1482. {
  1483.     char *pf = file;
  1484.     while( *pf != '' )
  1485.     {
  1486.         vlm_message_t *message = NULL;
  1487.         int i_temp = 0;
  1488.         int i_next;
  1489.         while( pf[i_temp] != 'n' && pf[i_temp] != '' && pf[i_temp] != 'r' )
  1490.         {
  1491.             i_temp++;
  1492.         }
  1493.         if( pf[i_temp] == 'r' || pf[i_temp] == 'n' )
  1494.         {
  1495.             pf[i_temp] = '';
  1496.             i_next = i_temp + 1;
  1497.         }
  1498.         else
  1499.         {
  1500.             i_next = i_temp;
  1501.         }
  1502.         if( ExecuteCommand( vlm, pf, &message ) )
  1503.         {
  1504.             free( message );
  1505.             return 1;
  1506.         }
  1507.         free( message );
  1508.         pf += i_next;
  1509.     }
  1510.     return 0;
  1511. }
  1512. static char *vlm_Save( vlm_t *vlm )
  1513. {
  1514.     char *save = NULL;
  1515.     char *p;
  1516.     int i,j;
  1517.     int i_length = 0;
  1518.     for( i = 0; i < vlm->i_media; i++ )
  1519.     {
  1520.         vlm_media_t *media = vlm->media[i];
  1521.         if( media->i_type == VOD_TYPE )
  1522.         {
  1523.             i_length += strlen( "new  vod " ) + strlen(media->psz_name);
  1524.         }
  1525.         else
  1526.         {
  1527.             i_length += strlen( "new  broadcast " ) + strlen(media->psz_name);
  1528.         }
  1529.         if( media->b_enabled == VLC_TRUE )
  1530.         {
  1531.             i_length += strlen( "enabled" );
  1532.         }
  1533.         else
  1534.         {
  1535.             i_length += strlen( "disabled" );
  1536.         }
  1537.         if( media->b_loop == VLC_TRUE )
  1538.         {
  1539.             i_length += strlen( " loopn" );
  1540.         }
  1541.         else
  1542.         {
  1543.             i_length += strlen( "n" );
  1544.         }
  1545.         for( j = 0; j < media->i_input; j++ )
  1546.         {
  1547.             i_length += strlen( "setup  input ""n" ) +
  1548.                 strlen( media->psz_name ) + strlen( media->input[j] );
  1549.         }
  1550.         if( media->psz_output != NULL )
  1551.         {
  1552.             i_length += strlen(media->psz_name) + strlen(media->psz_output) +
  1553.                 strlen( "setup  output n" );
  1554.         }
  1555.         for( j=0 ; j < media->i_option ; j++ )
  1556.         {
  1557.             i_length += strlen(media->psz_name) + strlen(media->option[j]) +
  1558.                 strlen("setup  option n");
  1559.         }
  1560.     }
  1561.     for( i = 0; i < vlm->i_schedule; i++ )
  1562.     {
  1563.         vlm_schedule_t *schedule = vlm->schedule[i];
  1564.         i_length += strlen( "new  schedule " ) + strlen( schedule->psz_name );
  1565.         if( schedule->b_enabled == VLC_TRUE )
  1566.         {
  1567.             i_length += strlen( "date //-:: enabledn" ) + 14;
  1568.         }
  1569.         else
  1570.         {
  1571.             i_length += strlen( "date //-:: disabledn" ) + 14;
  1572.         }
  1573.         if( schedule->i_period != 0 )
  1574.         {
  1575.             i_length += strlen( "setup  " ) + strlen( schedule->psz_name ) +
  1576.                 strlen( "period //-::n" ) + 14;
  1577.         }
  1578.         if( schedule->i_repeat >= 0 )
  1579.         {
  1580.             char buffer[12];
  1581.             sprintf( buffer, "%d", schedule->i_repeat );
  1582.             i_length += strlen( "setup  repeat n" ) +
  1583.                 strlen( schedule->psz_name ) + strlen( buffer );
  1584.         }
  1585.         else
  1586.         {
  1587.             i_length++;
  1588.         }
  1589.         for( j = 0; j < schedule->i_command; j++ )
  1590.         {
  1591.             i_length += strlen( "setup  append n" ) +
  1592.                 strlen( schedule->psz_name ) + strlen( schedule->command[j] );
  1593.         }
  1594.     }
  1595.     /* Don't forget the '' */
  1596.     i_length++;
  1597.     /* now we have the length of save */
  1598.     p = save = malloc( i_length );
  1599.     *save = '';
  1600.     /* finally we can write in it */
  1601.     for( i = 0; i < vlm->i_media; i++ )
  1602.     {
  1603.         vlm_media_t *media = vlm->media[i];
  1604.         if( media->i_type == VOD_TYPE )
  1605.         {
  1606.             p += sprintf( p, "new %s vod ", media->psz_name);
  1607.         }
  1608.         else
  1609.         {
  1610.             p += sprintf( p, "new %s broadcast ", media->psz_name);
  1611.         }
  1612.         if( media->b_enabled == VLC_TRUE )
  1613.         {
  1614.             p += sprintf( p, "enabled" );
  1615.         }
  1616.         else
  1617.         {
  1618.             p += sprintf( p, "disabled" );
  1619.         }
  1620.         if( media->b_loop == VLC_TRUE )
  1621.         {
  1622.             p += sprintf( p, " loopn" );
  1623.         }
  1624.         else
  1625.         {
  1626.             p += sprintf( p, "n" );
  1627.         }
  1628.         for( j = 0; j < media->i_input; j++ )
  1629.         {
  1630.             p += sprintf( p, "setup %s input "%s"n", media->psz_name,
  1631.                           media->input[j] );
  1632.         }
  1633.         if( media->psz_output != NULL )
  1634.         {
  1635.             p += sprintf( p, "setup %s output %sn", media->psz_name,
  1636.                           media->psz_output );
  1637.         }
  1638.         for( j = 0; j < media->i_option; j++ )
  1639.         {
  1640.             p += sprintf( p, "setup %s option %sn", media->psz_name,
  1641.                           media->option[j] );
  1642.         }
  1643.     }
  1644.     /* and now, the schedule scripts */
  1645. #if !defined( UNDER_CE )
  1646.     for( i = 0; i < vlm->i_schedule; i++ )
  1647.     {
  1648.         vlm_schedule_t *schedule = vlm->schedule[i];
  1649.         struct tm date;
  1650.         time_t i_time = (time_t) ( schedule->i_date / 1000000 );
  1651. #ifdef HAVE_LOCALTIME_R
  1652.         localtime_r( &i_time, &date);
  1653. #else
  1654.         struct tm *p_date = localtime( &i_time );
  1655.         date = *p_date;
  1656. #endif
  1657.         p += sprintf( p, "new %s schedule ", schedule->psz_name);
  1658.         if( schedule->b_enabled == VLC_TRUE )
  1659.         {
  1660.             p += sprintf( p, "date %d/%d/%d-%d:%d:%d enabledn",
  1661.                           date.tm_year + 1900, date.tm_mon + 1, date.tm_mday,
  1662.                           date.tm_hour, date.tm_min, date.tm_sec );
  1663.         }
  1664.         else
  1665.         {
  1666.             p += sprintf( p, "date %d/%d/%d-%d:%d:%d disabledn",
  1667.                           date.tm_year + 1900, date.tm_mon + 1, date.tm_mday,
  1668.                           date.tm_hour, date.tm_min, date.tm_sec);
  1669.         }
  1670.         if( schedule->i_period != 0 )
  1671.         {
  1672.             p += sprintf( p, "setup %s ", schedule->psz_name );
  1673.             i_time = (time_t) ( schedule->i_period / 1000000 );
  1674.             date.tm_sec = (int)( i_time % 60 );
  1675.             i_time = i_time / 60;
  1676.             date.tm_min = (int)( i_time % 60 );
  1677.             i_time = i_time / 60;
  1678.             date.tm_hour = (int)( i_time % 24 );
  1679.             i_time = i_time / 24;
  1680.             date.tm_mday = (int)( i_time % 30 );
  1681.             i_time = i_time / 30;
  1682.             /* okay, okay, months are not always 30 days long */
  1683.             date.tm_mon = (int)( i_time % 12 );
  1684.             i_time = i_time / 12;
  1685.             date.tm_year = (int)i_time;
  1686.             p += sprintf( p, "period %d/%d/%d-%d:%d:%dn",
  1687.                           date.tm_year, date.tm_mon, date.tm_mday,
  1688.                           date.tm_hour, date.tm_min, date.tm_sec);
  1689.         }
  1690.         if( schedule->i_repeat >= 0 )
  1691.         {
  1692.             p += sprintf( p, "setup %s repeat %dn",
  1693.                           schedule->psz_name, schedule->i_repeat );
  1694.         }
  1695.         else
  1696.         {
  1697.             p += sprintf( p, "n" );
  1698.         }
  1699.         for( j = 0; j < schedule->i_command; j++ )
  1700.         {
  1701.             p += sprintf( p, "setup %s append %sn",
  1702.                           schedule->psz_name, schedule->command[j] );
  1703.         }
  1704.     }
  1705. #endif /* UNDER_CE */
  1706.     return save;
  1707. }
  1708. /*****************************************************************************
  1709.  * Manage:
  1710.  *****************************************************************************/
  1711. static int vlm_MediaVodControl( void *p_private, vod_media_t *p_vod_media,
  1712.                                 char *psz_id, int i_query, va_list args )
  1713. {
  1714.     vlm_t *vlm = (vlm_t *)p_private;
  1715.     int i, i_ret = VLC_EGENERIC;
  1716.     if( !p_private || !p_vod_media ) return VLC_EGENERIC;
  1717.     vlc_mutex_lock( &vlm->lock );
  1718.     /* Find media */
  1719.     for( i = 0; i < vlm->i_media; i++ )
  1720.     {
  1721.         if( p_vod_media == vlm->media[i]->vod_media ) break;
  1722.     }
  1723.     if( i == vlm->i_media )
  1724.     {
  1725.         vlc_mutex_unlock( &vlm->lock );
  1726.         return VLC_EGENERIC;
  1727.     }
  1728.     switch( i_query )
  1729.     {
  1730.     case VOD_MEDIA_PLAY:
  1731.         vlm->media[i]->psz_vod_output = (char *)va_arg( args, char * );
  1732.         i_ret = vlm_MediaControl( vlm, vlm->media[i], psz_id, "play", 0 );
  1733.         vlm->media[i]->psz_vod_output = 0;
  1734.         break;
  1735.     case VOD_MEDIA_PAUSE:
  1736.         i_ret = vlm_MediaControl( vlm, vlm->media[i], psz_id, "pause", 0 );
  1737.         break;
  1738.     case VOD_MEDIA_STOP:
  1739.         i_ret = vlm_MediaControl( vlm, vlm->media[i], psz_id, "stop", 0 );
  1740.         break;
  1741.     default:
  1742.         break;
  1743.     }
  1744.     vlc_mutex_unlock( &vlm->lock );
  1745.     return i_ret;
  1746. }
  1747. /*****************************************************************************
  1748.  * Manage:
  1749.  *****************************************************************************/
  1750. static int Manage( vlc_object_t* p_object )
  1751. {
  1752.     vlm_t *vlm = (vlm_t*)p_object;
  1753.     int i, j;
  1754.     mtime_t i_lastcheck;
  1755.     mtime_t i_time;
  1756.     i_lastcheck = mdate();
  1757.     msleep( 100000 );
  1758.     while( !vlm->b_die )
  1759.     {
  1760.         vlc_mutex_lock( &vlm->lock );
  1761.         /* destroy the inputs that wants to die, and launch the next input */
  1762.         for( i = 0; i < vlm->i_media; i++ )
  1763.         {
  1764.             vlm_media_t *p_media = vlm->media[i];
  1765.             for( j = 0; j < p_media->i_instance; j++ )
  1766.             {
  1767.                 vlm_media_instance_t *p_instance = p_media->instance[j];
  1768.                 if( !p_instance->p_input ||
  1769.                     ( !p_instance->p_input->b_eof &&
  1770.                       !p_instance->p_input->b_error ) ) continue;
  1771.                 input_StopThread( p_instance->p_input );
  1772.                 input_DestroyThread( p_instance->p_input );
  1773.                 vlc_object_detach( p_instance->p_input );
  1774.                 vlc_object_destroy( p_instance->p_input );
  1775.                 p_instance->i_index++;
  1776.                 if( p_instance->i_index == p_media->i_input &&
  1777.                     p_media->b_loop ) p_instance->i_index = 0;
  1778.                 if( p_instance->i_index < p_media->i_input )
  1779.                 {
  1780.                     /* FIXME, find a way to select the right instance */
  1781.                     char buffer[12];
  1782.                     sprintf( buffer, "%d", p_instance->i_index );
  1783.                     vlm_MediaControl( vlm, p_media, p_instance->psz_name,
  1784.                                       "play", buffer );
  1785.                 }
  1786.                 else
  1787.                 {
  1788.                     if( vlm_MediaControl( vlm, p_media, p_instance->psz_name,
  1789.                                           "stop", 0 ) == VLC_SUCCESS ) i--;
  1790.                 }
  1791.             }
  1792.         }
  1793.         /* scheduling */
  1794.         i_time = mdate();
  1795.         for( i = 0; i < vlm->i_schedule; i++ )
  1796.         {
  1797.             mtime_t i_real_date = vlm->schedule[i]->i_date;
  1798.             if( vlm->schedule[i]->b_enabled == VLC_TRUE )
  1799.             {
  1800.                 if( vlm->schedule[i]->i_date == 0 ) // now !
  1801.                 {
  1802.                     vlm->schedule[i]->i_date = (i_time / 1000000) * 1000000 ;
  1803.                     i_real_date = i_time;
  1804.                 }
  1805.                 else if( vlm->schedule[i]->i_period != 0 )
  1806.                 {
  1807.                     int j = 0;
  1808.                     while( vlm->schedule[i]->i_date + j *
  1809.                            vlm->schedule[i]->i_period <= i_lastcheck &&
  1810.                            ( vlm->schedule[i]->i_repeat > j ||
  1811.                              vlm->schedule[i]->i_repeat == -1 ) )
  1812.                     {
  1813.                         j++;
  1814.                     }
  1815.                     i_real_date = vlm->schedule[i]->i_date + j *
  1816.                         vlm->schedule[i]->i_period;
  1817.                 }
  1818.                 if( i_real_date <= i_time && i_real_date > i_lastcheck )
  1819.                 {
  1820.                     for( j = 0; j < vlm->schedule[i]->i_command; j++ )
  1821.                     {
  1822.                         vlm_message_t *message = NULL;
  1823.                         ExecuteCommand( vlm, vlm->schedule[i]->command[j],
  1824.                                         &message );
  1825.                         /* for now, drop the message */
  1826.                         free( message );
  1827.                     }
  1828.                 }
  1829.             }
  1830.         }
  1831.         i_lastcheck = i_time;
  1832.         vlc_mutex_unlock( &vlm->lock );
  1833.         msleep( 100000 );
  1834.     }
  1835.     return VLC_SUCCESS;
  1836. }
  1837. #else /* ENABLE_VLM */
  1838. /* We just define an empty wrapper */
  1839. vlm_t *__vlm_New( vlc_object_t *a )
  1840. {
  1841.     msg_Err( a, "VideoLAN manager support is disabled" );
  1842.     return 0;
  1843. }
  1844. void vlm_Delete( vlm_t *a ){}
  1845. int vlm_ExecuteCommand( vlm_t *a, char *b, vlm_message_t **c ){ return -1; }
  1846. void vlm_MessageDelete( vlm_message_t *a ){}
  1847. #endif /* ENABLE_VLM */