]> git.sesse.net Git - vlc/commitdiff
* src/misc/vlm.c:
authorGildas Bazin <gbazin@videolan.org>
Sun, 19 Sep 2004 21:38:12 +0000 (21:38 +0000)
committerGildas Bazin <gbazin@videolan.org>
Sun, 19 Sep 2004 21:38:12 +0000 (21:38 +0000)
   + major cleanup and bug fixing.
   + added support for spawning and controlling several media instances.

include/vlc_vlm.h
src/misc/vlm.c

index 46c07e7c05c7e54e16b3f5480aaacbdb255abe6d..49ca30298211b33da7bf9b4b2081e5081c43a062 100644 (file)
 enum
 {
     VOD_TYPE = 0,
-    BROADCAST_TYPE = 1,
+    BROADCAST_TYPE,
+    SCHEDULE_TYPE,
 };
 
+typedef struct
+{
+    /* instance name */
+    char *psz_name;
+
+    /* "playlist" index */
+    int i_index;
+
+    input_item_t   item;
+    input_thread_t *p_input;
+
+} vlm_media_instance_t;
+
 typedef struct
 {
     vlc_bool_t b_enabled;
@@ -39,27 +53,26 @@ typedef struct
 
     /* name "media" is reserved */
     char    *psz_name;
+    input_item_t item;
 
+    /* "playlist" */
     int     i_input;
     char    **input;
 
+    int     i_option;
+    char    **option;
+
+    char    *psz_output;
+
     /* only for broadcast */
     vlc_bool_t b_loop;
 
     /* only for vod */
     vod_media_t *vod_media;
 
-    /* "playlist" index */
-    int     i_index;
-
-    char    *psz_output;
-
-    int     i_option;
-    char    **option;
-
-    /* global options for all inputs */
-    input_item_t    item;
-    input_thread_t  *p_input;
+    /* actual input instances */
+    int                  i_instance;
+    vlm_media_instance_t **instance;
 
 } vlm_media_t;
 
index 0fb7d79ba4e913a3b6d8378d24b5b18d6b1afec7..4a5dbd78344a2167f8d427a5ff046d2bee8b40e7 100644 (file)
@@ -6,6 +6,7 @@
  *
  * Authors: Simon Latapie <garf@videolan.org>
  *          Laurent Aimar <fenrir@videolan.org>
+ *          Gildas Bazin <gbazin@videolan.org>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -47,16 +48,17 @@ static vlm_message_t *vlm_Show( vlm_t *, vlm_media_t *, vlm_schedule_t *, char *
 static vlm_message_t *vlm_Help( vlm_t *, char * );
 
 static vlm_media_t *vlm_MediaNew    ( vlm_t *, char *, int );
-static int          vlm_MediaDelete ( vlm_t *, vlm_media_t *, char * );
+static void         vlm_MediaDelete ( vlm_t *, vlm_media_t *, char * );
 static vlm_media_t *vlm_MediaSearch ( vlm_t *, char * );
 static int          vlm_MediaSetup  ( vlm_t *, vlm_media_t *, char *, char * );
-static int          vlm_MediaControl( vlm_t *, vlm_media_t *, char *, char * );
+static int          vlm_MediaControl( vlm_t *, vlm_media_t *, char *, char *, char * );
+static vlm_media_instance_t *vlm_MediaInstanceSearch( vlm_t *, vlm_media_t *, char * );
 
-static vlm_message_t* vlm_MessageNew( char *, char * );
-static vlm_message_tvlm_MessageAdd( vlm_message_t*, vlm_message_t* );
+static vlm_message_t *vlm_MessageNew( char *, const char *, ... );
+static vlm_message_t *vlm_MessageAdd( vlm_message_t*, vlm_message_t* );
 
 static vlm_schedule_t *vlm_ScheduleNew( vlm_t *, char *);
-static int             vlm_ScheduleDelete( vlm_t *, vlm_schedule_t *, char *);
+static void            vlm_ScheduleDelete( vlm_t *, vlm_schedule_t *, char *);
 static int             vlm_ScheduleSetup( vlm_schedule_t *, char *, char *);
 static vlm_schedule_t *vlm_ScheduleSearch( vlm_t *, char *);
 
@@ -114,7 +116,6 @@ vlm_t *__vlm_New ( vlc_object_t *p_this )
 void vlm_Delete( vlm_t *vlm )
 {
     vlc_value_t lockval;
-    int i;
 
     var_Get( vlm->p_libvlc, "vlm_mutex", &lockval );
     vlc_mutex_lock( lockval.p_address );
@@ -132,20 +133,10 @@ void vlm_Delete( vlm_t *vlm )
 
     vlc_mutex_destroy( &vlm->lock );
 
-    for( i = 0; i < vlm->i_media; i++ )
-    {
-        vlm_media_t *media = vlm->media[i];
-
-        vlm_MediaDelete( vlm, media, NULL );
-    }
-
+    while( vlm->i_media ) vlm_MediaDelete( vlm, vlm->media[0], NULL );
     if( vlm->media ) free( vlm->media );
 
-    for( i = 0; i < vlm->i_schedule; i++ )
-    {
-        vlm_ScheduleDelete( vlm, vlm->schedule[i], NULL );
-    }
-
+    while( vlm->i_schedule ) vlm_ScheduleDelete( vlm, vlm->schedule[0], NULL );
     if( vlm->schedule ) free( vlm->schedule );
 
     vlc_object_detach( vlm );
@@ -168,136 +159,88 @@ int vlm_ExecuteCommand( vlm_t *vlm, char *command, vlm_message_t **message)
 }
 
 /*****************************************************************************
- *
+ * FindEndCommand
  *****************************************************************************/
-#if 1
 static char *FindEndCommand( char *psz )
 {
-    char *s_sent = psz;
+    char *psz_sent = psz;
 
-    switch( *s_sent )
+    switch( *psz_sent )
     {
-        case '\"':
-        {
-            s_sent++;
-
-            while( ( *s_sent != '\"' ) && ( *s_sent != '\0' ) )
-            {
-                if( *s_sent == '\'' )
-                {
-                    s_sent = FindEndCommand( s_sent );
+    case '\"':
+        psz_sent++;
 
-                    if( s_sent == NULL )
-                    {
-                        return NULL;
-                    }
-                }
-                else
-                {
-                    s_sent++;
-                }
-            }
-
-            if( *s_sent == '\"' )
-            {
-                s_sent++;
-                return s_sent;
-            }
-            else  /* *s_sent == '\0' , which means the number of " is incorrect */
+        while( ( *psz_sent != '\"' ) && ( *psz_sent != '\0' ) )
+        {
+            if( *psz_sent == '\'' )
             {
-                return NULL;
+                psz_sent = FindEndCommand( psz_sent );
+                if( psz_sent == NULL ) return NULL;
             }
-            break;
+            else psz_sent++;
         }
-        case '\'':
+
+        if( *psz_sent == '\"' )
         {
-            s_sent++;
+            psz_sent++;
+            return psz_sent;
+        }
 
-            while( ( *s_sent != '\'' ) && ( *s_sent != '\0' ) )
-            {
-                if( *s_sent == '\"' )
-                {
-                    s_sent = FindEndCommand( s_sent );
+        /* *psz_sent == '\0' -> number of " is incorrect */
+        else return NULL;
 
-                    if( s_sent == NULL )
-                    {
-                        return NULL;
-                    }
-                }
-                else
-                {
-                    s_sent++;
-                }
-            }
+        break;
 
-            if( *s_sent == '\'' )
-            {
-                s_sent++;
-                return s_sent;
-            }
-            else  /* *s_sent == '\0' , which means the number of ' is incorrect */
-            {
-                return NULL;
-            }
-            break;
-        }
-        default: /* now we can look for spaces */
+    case '\'':
+        psz_sent++;
+
+        while( ( *psz_sent != '\'' ) && ( *psz_sent != '\0' ) )
         {
-            while( ( *s_sent != ' ' ) && ( *s_sent != '\0' ) )
+            if( *psz_sent == '\"' )
             {
-                if( ( *s_sent == '\'' ) || ( *s_sent == '\"' ) )
-                {
-                    s_sent = FindEndCommand( s_sent );
-                }
-                else
-                {
-                    s_sent++;
-                }
+                psz_sent = FindEndCommand( psz_sent );
+                if( psz_sent == NULL ) return NULL;
             }
-            return s_sent;
+            else psz_sent++;
         }
-    }
-}
-#else
-static char *FindEndCommand( char *psz )
-{
-    char *s_sent = psz;
 
-    while( *psz &&
-            *psz != ' ' && *psz != '\t' &&
-            *psz != '\n' && *psz != '\r' )
-    {
-        if( *psz == '\'' || *psz == '"' )
+        if( *psz_sent == '\'' )
         {
-            char d = *psz++;
+            psz_sent++;
+            return psz_sent;
+        }
 
-            while( *psz && *psz != d && *psz != *psz != '\n' && *psz != '\r' )
-            {
-                if( ( d == '\'' && *psz == '"' ) ||
-                    ( d == '"' && *psz == '\'' ) )
-                {
-                    psz = FindEndCommand( psz );
-                }
-            }
-            if( psz != d )
+        /* *psz_sent == '\0' -> number of " is incorrect */
+        else return NULL;
+
+        break;
+
+    default: /* now we can look for spaces */
+        while( ( *psz_sent != ' ' ) && ( *psz_sent != '\0' ) )
+        {
+            if( ( *psz_sent == '\'' ) || ( *psz_sent == '\"' ) )
             {
-                return NULL;
+                psz_sent = FindEndCommand( psz_sent );
             }
+            else psz_sent++;
         }
-        psz++;
+
+        return psz_sent;
     }
 }
-#endif
 
-/* Execute a command which ends by '\0' (string) */
+/*****************************************************************************
+ * ExecuteCommand: The main state machine
+ *****************************************************************************
+ * Execute a command which ends with '\0' (string)
+ *****************************************************************************/
 static int ExecuteCommand(vlm_t *vlm, char *command, vlm_message_t **p_message)
 {
-    int i_return = 0;
     int i_command = 0;
     char **p_command = NULL;
     char *cmd = command;
     vlm_message_t *message = NULL;
-    int i;
+    int i, j;
 
     /* First, parse the line and cut it */
     while( *cmd != '\0' )
@@ -314,595 +257,447 @@ static int ExecuteCommand(vlm_t *vlm, char *command, vlm_message_t **p_message)
 
             p_temp = FindEndCommand( cmd );
 
-            if( p_temp == NULL )
-            {
-                i_return = 1;
-                goto end_seq;
-            }
+            if( p_temp == NULL ) goto error;
 
             i_temp = p_temp - cmd;
 
-            p_command = realloc( p_command, (i_command + 1) * sizeof( char* ) );
-            p_command[ i_command ] = malloc( (i_temp + 1) * sizeof( char ) ); // don't forget the '\0'
+            p_command = realloc( p_command, (i_command + 1) * sizeof(char*) );
+            p_command[ i_command ] = malloc( (i_temp + 1) * sizeof(char) );
             strncpy( p_command[ i_command ], cmd, i_temp );
-            (p_command[ i_command ])[ i_temp ] = '\0';
+            p_command[ i_command ][ i_temp ] = '\0';
 
             i_command++;
             cmd = p_temp;
         }
     }
 
-    /* And then Interpret it */
+    /*
+     * And then Interpret it
+     */
 
     if( i_command == 0 )
     {
         message = vlm_MessageNew( "", NULL );
-        i_return = 0;
-        goto end_seq;
+        goto success;
     }
 
     if( strcmp(p_command[0], "new") == 0 )
     {
-        if( i_command >= 3 )
-        {
-            int i_type;
-            vlm_media_t *media;
-            vlm_schedule_t *schedule;
-
-            if( strcmp(p_command[2], "schedule") == 0 )
-            {
-                /* new vlm_schedule */
-                if( vlm_ScheduleSearch( vlm, p_command[1] ) != NULL ||
-                    strcmp(p_command[1], "schedule") == 0 )
-                {
-                    char *error_message;
-                    asprintf( &error_message, "%s is already used",
-                              p_command[1] );
-                    message = vlm_MessageNew( "new", error_message );
-                    free( error_message );
-                    i_return = 1;
-                    goto end_seq;
-                }
-
-                schedule = vlm_ScheduleNew( vlm, p_command[1] );
-
-                if( i_command > 3 ) // hey, there are properties
-                {
-                    for( i = 3 ; i < i_command ; i++ )
-                    {
-                        if( strcmp( p_command[i], "enabled" ) == 0 ||
-                            strcmp( p_command[i], "disabled" ) == 0 )
-                        {
-                            vlm_ScheduleSetup( schedule, p_command[i], NULL );
-                        }
-                        /* Beware: evrything behind append is considered as command line */
-                        else if( strcmp( p_command[i], "append" ) == 0 )
-                        {
-                            i++;
-
-                            if( i < i_command )
-                            {
-                                int j;
-                                for( j = (i + 1); j < i_command; j++ )
-                                {
-                                    p_command[i] = realloc( p_command[i], strlen(p_command[i]) + strlen(p_command[j]) + 1 + 1);
-                                    strcat( p_command[i], " " );
-                                    strcat( p_command[i], p_command[j] );
-                                }
-
-                                vlm_ScheduleSetup( schedule, p_command[i - 1], p_command[i] );
-                            }
-                            i = i_command;
-                        }
-                        else
-                        {
-                            if( (i+1) < i_command )
-                            {
-                                vlm_ScheduleSetup( schedule, p_command[i], p_command[i+1] );
-                                i++;
-                            }
-                            else
-                            {
-                                vlm_ScheduleDelete( vlm, schedule, NULL );
-                                message = vlm_MessageNew( p_command[i], "Wrong properties syntax" );
-                                i_return = 1;
-                                goto end_seq;
-                            }
-                        }
-                    }
-                }
+        int i_type;
 
-                message = vlm_MessageNew( "new", NULL );
-                i_return = 0;
-                goto end_seq;
-            }
+        /* Check the number of arguments */
+        if( i_command < 3 ) goto syntax_error;
 
-            if( strcmp(p_command[2], "vod") == 0 )
-            {
-                i_type = VOD_TYPE;
-            }
-            else if( strcmp(p_command[2], "broadcast") == 0 )
-            {
-                i_type = BROADCAST_TYPE;
-            }
-            else
-            {
-                char *error_message;
+        /* Get type */
+        if( strcmp(p_command[2], "vod") == 0 )
+        {
+            i_type = VOD_TYPE;
+        }
+        else if( strcmp(p_command[2], "broadcast") == 0 )
+        {
+            i_type = BROADCAST_TYPE;
+        }
+        else if( strcmp(p_command[2], "schedule") == 0 )
+        {
+            i_type = SCHEDULE_TYPE;
+        }
+        else
+        {
+            message = vlm_MessageNew( "new", "%s: Choose between vod, "
+                                      "broadcast or schedule", p_command[1] );
+            goto error;
+        }
 
-                asprintf( &error_message,
-                          "%s: Choose between vod or broadcast",
-                          p_command[1] );
+        /* Check for forbidden media names */
+        if( strcmp(p_command[1], "all") == 0 ||
+            strcmp(p_command[1], "media") == 0 ||
+            strcmp(p_command[1], "schedule") == 0 )
+        {
+            message = vlm_MessageNew( "new", "\"all\", \"media\" and "
+                                      "\"schedule\" are reserved names" );
+            goto error;
+        }
 
-                message = vlm_MessageNew( "new", error_message );
-                free( error_message );
-                i_return = 1;
-                goto end_seq;
-            }
+        /* Check the name is not already in use */
+        if( vlm_ScheduleSearch( vlm, p_command[1] ) ||
+            vlm_MediaSearch( vlm, p_command[1] ) )
+        {
+            message = vlm_MessageNew( "new", "%s: Name already in use",
+                                      p_command[1] );
+            goto error;
+        }
 
-            /* new vlm_media */
-            if( vlm_MediaSearch( vlm, p_command[1] ) != NULL ||
-                strcmp(p_command[1], "media") == 0 )
+        /* Schedule */
+        if( i_type == SCHEDULE_TYPE )
+        {
+            vlm_schedule_t *schedule;
+            schedule = vlm_ScheduleNew( vlm, p_command[1] );
+            if( !schedule )
             {
-                char *error_message;
-                asprintf( &error_message, "%s is already used",
-                          p_command[1] );
-                message = vlm_MessageNew( "new", error_message );
-                free( error_message );
-                i_return = 1;
-                goto end_seq;
+                message = vlm_MessageNew( "new", "could not create schedule" );
+                goto error;
             }
+        }
 
+        /* Media */
+        else
+        {
+            vlm_media_t *media;
             media = vlm_MediaNew( vlm, p_command[1], i_type );
             if( !media )
             {
                 message = vlm_MessageNew( "new", "could not create media" );
-                i_return = 1;
-                goto end_seq;
-            }
-
-            if( i_command > 3 ) // hey, there are properties
-            {
-                for( i = 3; i < i_command; i++ )
-                {
-                    if( strcmp( p_command[i], "enabled" ) == 0 ||
-                        strcmp( p_command[i], "disabled" ) == 0 )
-                    {
-                        vlm_MediaSetup( vlm, media, p_command[i], NULL );
-                    }
-                    else
-                    {
-                        if( (i+1) < i_command )
-                        {
-                            vlm_MediaSetup( vlm, media, p_command[i], p_command[i+1] );
-                            i++;
-                        }
-                        else
-                        {
-                            vlm_MediaDelete( vlm, media, NULL );
-                            message = vlm_MessageNew( p_command[i], "Wrong properties syntax" );
-                            i_return = 1;
-                            goto end_seq;
-                        }
-                    }
-                }
+                goto error;
             }
-
-            if( media->i_type == VOD_TYPE )
-                message = vlm_MessageNew( "new", "Warning: VOD is not "
-                                          "implemented yet" );
-            else
-                message = vlm_MessageNew( "new", NULL );
-            i_return = 0;
-            goto end_seq;
         }
-        else
+
+        if( i_command <= 3 )
         {
-            message = vlm_MessageNew( "new", "Wrong command syntax" );
-            i_return = 1;
-            goto end_seq;
+            message = vlm_MessageNew( "new", NULL );
+            goto success;
         }
+
+        /* Properties will be dealt with later on */
+    }
+
+    else if( strcmp(p_command[0], "setup") == 0 )
+    {
+        if( i_command < 2 ) goto syntax_error;
+
+        /* Properties will be dealt with later on */
     }
     else if( strcmp(p_command[0], "del") == 0 )
     {
-        if( i_command >= 2 )
-        {
-            vlm_media_t *media;
-            vlm_schedule_t *schedule;
+        vlm_media_t *media;
+        vlm_schedule_t *schedule;
 
-            media = vlm_MediaSearch( vlm, p_command[1] );
-            schedule = vlm_ScheduleSearch( vlm, p_command[1] );
+        if( i_command < 2 ) goto syntax_error;
 
-            if( schedule != NULL )
-            {
-                vlm_ScheduleDelete( vlm, schedule, NULL );
-                message = vlm_MessageNew( "del", NULL );
-                i_return = 0;
-                goto end_seq;
-            }
-            else if( media != NULL )
-            {
-                vlm_MediaDelete( vlm, media, NULL );
-                message = vlm_MessageNew( "del", NULL );
-                i_return = 0;
-                goto end_seq;
-            }
-            else if( strcmp(p_command[1], "media") == 0 )
-            {
-                for( i = 0; i < vlm->i_media; i++ )
-                {
-                    vlm_MediaDelete( vlm, vlm->media[i], NULL );
-                }
-                message = vlm_MessageNew( "del", NULL );
-                goto end_seq;
-            }
-            else if( strcmp(p_command[1], "schedule") == 0 )
-            {
-                for( i = 0; i < vlm->i_schedule; i++ )
-                {
-                    vlm_ScheduleDelete( vlm, vlm->schedule[i], NULL );
-                }
-                message = vlm_MessageNew( "del", NULL );
-                goto end_seq;
-            }
-            else if( strcmp(p_command[1], "all") == 0 )
-            {
-                for( i = 0; i < vlm->i_media; i++ )
-                {
-                    vlm_MediaDelete( vlm, vlm->media[i], NULL );
-                }
+        media = vlm_MediaSearch( vlm, p_command[1] );
+        schedule = vlm_ScheduleSearch( vlm, p_command[1] );
 
-                for( i = 0; i < vlm->i_schedule; i++ )
-                {
-                    vlm_ScheduleDelete( vlm, vlm->schedule[i], NULL );
-                }
-                i_return = 0;
-                message = vlm_MessageNew( "del", NULL );
-                goto end_seq;
-            }
-            else
-            {
-                char *error_message;
-                asprintf( &error_message, "%s: media unknown", p_command[1] );
-                message = vlm_MessageNew( "del", error_message );
-                free( error_message );
-                i_return = 1;
-                goto end_seq;
-            }
+        if( schedule != NULL )
+        {
+            vlm_ScheduleDelete( vlm, schedule, NULL );
+        }
+        else if( media != NULL )
+        {
+            vlm_MediaDelete( vlm, media, NULL );
+        }
+        else if( strcmp(p_command[1], "media") == 0 )
+        {
+            while( vlm->i_media ) vlm_MediaDelete( vlm, vlm->media[0], NULL );
+        }
+        else if( strcmp(p_command[1], "schedule") == 0 )
+        {
+            while( vlm->i_schedule )
+                vlm_ScheduleDelete( vlm, vlm->schedule[0], NULL );
+        }
+        else if( strcmp(p_command[1], "all") == 0 )
+        {
+            while( vlm->i_media ) vlm_MediaDelete( vlm, vlm->media[0], NULL );
+
+            while( vlm->i_schedule )
+                vlm_ScheduleDelete( vlm, vlm->schedule[0], NULL );
         }
         else
         {
-            message = vlm_MessageNew( "setup", "Wrong command syntax" );
-            i_return = 1;
-            goto end_seq;
+            message = vlm_MessageNew( "del", "%s: media unknown",
+                                      p_command[1] );
+            goto error;
         }
+
+        message = vlm_MessageNew( "del", NULL );
+        goto success;
     }
+
     else if( strcmp(p_command[0], "show") == 0 )
     {
+        vlm_media_t *media;
+        vlm_schedule_t *schedule;
+
         if( i_command == 1 )
         {
             message = vlm_Show( vlm, NULL, NULL, NULL );
-            i_return = 0;
-            goto end_seq;
+            goto success;
         }
-        else if( i_command == 2 )
-        {
-            vlm_media_t *media;
-            vlm_schedule_t *schedule;
+        else if( i_command > 2 ) goto syntax_error;
 
-            media = vlm_MediaSearch( vlm, p_command[1] );
-            schedule = vlm_ScheduleSearch( vlm, p_command[1] );
-
-            if( schedule != NULL )
-            {
-                message = vlm_Show( vlm, NULL, schedule, NULL );
-            }
-            else if( media != NULL )
-            {
-                message = vlm_Show( vlm, media, NULL, NULL );
-            }
-            else
-            {
-                message = vlm_Show( vlm, NULL, NULL, p_command[1] );
-            }
+        media = vlm_MediaSearch( vlm, p_command[1] );
+        schedule = vlm_ScheduleSearch( vlm, p_command[1] );
 
-            i_return = 0;
-            goto end_seq;
-        }
-        else
+        if( schedule != NULL )
         {
-            message = vlm_MessageNew( "show", "Wrong command syntax" );
-            i_return = 1;
-            goto end_seq;
+            message = vlm_Show( vlm, NULL, schedule, NULL );
         }
-    }
-    else if( strcmp(p_command[0], "help") == 0 )
-    {
-        if( i_command == 1 )
+        else if( media != NULL )
         {
-            message = vlm_Help( vlm, NULL );
-            i_return = 0;
-            goto end_seq;
+            message = vlm_Show( vlm, media, NULL, NULL );
         }
         else
         {
-            message = vlm_MessageNew( "help", "Wrong command syntax" );
-            i_return = 1;
-            goto end_seq;
+            message = vlm_Show( vlm, NULL, NULL, p_command[1] );
         }
+
+        goto success;
     }
-    else if( strcmp(p_command[0], "setup") == 0 )
-    {
-        if( i_command >= 2 )
-        {
-            vlm_media_t *media;
-            vlm_schedule_t *schedule;
 
-            media = vlm_MediaSearch( vlm, p_command[1] );
-            schedule = vlm_ScheduleSearch( vlm, p_command[1] );
+    else if( strcmp(p_command[0], "help") == 0 )
+    {
+        if( i_command != 1 ) goto syntax_error;
 
-            if( schedule != NULL )
-            {
-                for( i = 2 ; i < i_command ; i++ )
-                {
-                    if( strcmp( p_command[i], "enabled" ) == 0 ||
-                        strcmp( p_command[i], "disabled" ) == 0 )
-                    {
-                        vlm_ScheduleSetup( schedule, p_command[i], NULL );
-                    }
-                    /* Beware: evrything behind append is considered as command line */
-                    else if( strcmp( p_command[i], "append" ) == 0 )
-                    {
-                        i++;
-
-                        if( i < i_command )
-                        {
-                            int j;
-                            for( j = (i + 1); j < i_command; j++ )
-                            {
-                                p_command[i] = realloc( p_command[i], strlen(p_command[i]) + strlen(p_command[j]) + 1 + 1);
-                                strcat( p_command[i], " " );
-                                strcat( p_command[i], p_command[j] );
-                            }
-
-                            vlm_ScheduleSetup( schedule, p_command[i - 1], p_command[i] );
-                        }
-                        i = i_command;
-                    }
-                    else
-                    {
-                        if( (i+1) < i_command )
-                        {
-                            vlm_ScheduleSetup( schedule, p_command[i], p_command[i+1] );
-                            i++;
-                        }
-                        else
-                        {
-                            vlm_ScheduleDelete( vlm, schedule, NULL );
-                            message = vlm_MessageNew( "setup", "Wrong properties syntax" );
-                            i_return = 1;
-                            goto end_seq;
-                        }
-                    }
-                }
+        message = vlm_Help( vlm, NULL );
+        goto success;
+    }
 
-                message = vlm_MessageNew( "setup", NULL );
-                i_return = 0;
-                goto end_seq;
-            }
-            else if( media != NULL )
-            {
-                for( i = 2 ; i < i_command ; i++ )
-                {
-                    if( strcmp( p_command[i], "enabled" ) == 0 ||
-                        strcmp( p_command[i], "disabled" ) == 0 )
-                    {   /* only one argument */
-                        vlm_MediaSetup( vlm, media, p_command[i], NULL );
-                    }
-                    else if( strcmp( p_command[i], "loop" ) == 0 ||
-                             strcmp( p_command[i], "unloop" ) == 0 )
-                    {
-                        if( media->i_type != BROADCAST_TYPE )
-                        {
-                            message = vlm_MessageNew( "setup", "loop only available for broadcast" );
-                            i_return = 1;
-                            goto end_seq;
-                        }
-                        else
-                        {
-                            vlm_MediaSetup( vlm, media, p_command[i], NULL );
-                        }
-                    }
-                    else
-                    {
-                        if( (i+1) < i_command )
-                        {
-                            vlm_MediaSetup( vlm, media, p_command[i], p_command[i+1] );
-                            i++;
-                        }
-                        else
-                        {
-                            vlm_MediaDelete( vlm, media, NULL );
-                            message = vlm_MessageNew( "setup", "Wrong properties syntax" );
-                            i_return = 1;
-                            goto end_seq;
-                        }
-                    }
-                }
+    else if( strcmp(p_command[0], "control") == 0 )
+    {
+        vlm_media_t *media;
 
-                message = vlm_MessageNew( "setup", NULL );
-                i_return = 0;
-                goto end_seq;
-            }
-            else
-            {
-                char *error_message;
-                asprintf( &error_message, "%s unknown", p_command[1] );
-                message = vlm_MessageNew( "setup", error_message );
-                free( error_message );
-                i_return = 1;
-                goto end_seq;
-            }
+        if( i_command < 3 ) goto syntax_error;
 
-        }
-        else
+        if( !(media = vlm_MediaSearch( vlm, p_command[1] ) ) )
         {
-            message = vlm_MessageNew( "setup", "Wrong command syntax" );
-            i_return = 1;
-            goto end_seq;
+            message = vlm_MessageNew( "control", "%s: media unknown",
+                                      p_command[1] );
+            goto error;
         }
-    }
-    else if( strcmp(p_command[0], "control") == 0 )
-    {
-
-        if( i_command >= 3 )
+        else
         {
-            vlm_media_t *media;
+            char *psz_command, *psz_arg = 0, *psz_instance = 0;
+            int i_index = 2;
 
-            media = vlm_MediaSearch( vlm, p_command[1] );
-
-            if( media == NULL )
+            if( strcmp(p_command[2], "play") && strcmp(p_command[2], "stop") &&
+                strcmp(p_command[2], "pause") && strcmp(p_command[2], "seek") )
             {
-                char *error_message;
-                asprintf( &error_message, "%s: media unknown", p_command[1] );
-                message = vlm_MessageNew( "control", error_message );
-                free( error_message );
-                i_return = 1;
-                goto end_seq;
+                i_index++;
+                psz_instance = p_command[2];
+
+                if( i_command < 4 ) goto syntax_error;
             }
-            else
-            {
-                char *psz_args;
 
-                if( i_command >= 4 )
-                {
-                    psz_args = p_command[3];
-                }
-                else
-                {
-                    psz_args = NULL;
-                }
+            psz_command = p_command[i_index];
 
-                /* for now */
-                vlm_MediaControl( vlm, media, p_command[2], psz_args );
-                message = vlm_MessageNew( "control", NULL );
-                i_return = 0;
-                goto end_seq;
-            }
-        }
-        else
-        {
-            message = vlm_MessageNew( "control", "Wrong command syntax" );
-            i_return = 1;
-            goto end_seq;
+            if( i_command >= i_index + 2 ) psz_arg = p_command[i_index + 1];
+
+            vlm_MediaControl( vlm, media, psz_instance, psz_command, psz_arg );
+            message = vlm_MessageNew( "control", NULL );
+            goto success;
         }
     }
+
     else if( strcmp(p_command[0], "save") == 0 )
     {
-        if( i_command == 2 )
-        {
-            FILE *file;
-
-            file = fopen( p_command[1], "w" );
-
-            if( file == NULL )
-            {
-                message = vlm_MessageNew( "save", "Unable to save file" );
-                i_return = 1;
-                goto end_seq;
-            }
-            else
-            {
-                char *save;
+        FILE *file;
 
-                save = vlm_Save( vlm );
+        if( i_command != 2 ) goto syntax_error;
 
-                fwrite( save, strlen( save ), 1, file );
-                fclose( file );
-                free( save );
-                message = vlm_MessageNew( "save", NULL );
-                i_return = 0;
-                goto end_seq;
-            }
+        file = fopen( p_command[1], "w" );
+        if( file == NULL )
+        {
+            message = vlm_MessageNew( "save", "Unable to save file" );
+            goto error;
         }
         else
         {
-            message = vlm_MessageNew( "save", "Wrong command" );
-            i_return = 1;
-            goto end_seq;
+            char *save = vlm_Save( vlm );
+            fwrite( save, strlen( save ), 1, file );
+            fclose( file );
+            free( save );
+            message = vlm_MessageNew( "save", NULL );
+            goto success;
         }
     }
+
     else if( strcmp(p_command[0], "load") == 0 )
     {
+        FILE *file;
 
-        if( i_command == 2 )
-        {
-            FILE *file;
+        if( i_command != 2 ) goto syntax_error;
 
-            file = fopen( p_command[1], "r" );
+        file = fopen( p_command[1], "r" );
 
-            if( file == NULL )
+        if( file == NULL )
+        {
+            message = vlm_MessageNew( "load", "Unable to load file" );
+            goto error;
+        }
+        else
+        {
+            int64_t size;
+            char *buffer;
+
+            if( fseek( file, 0, SEEK_END) == 0 )
             {
-                message = vlm_MessageNew( "load", "Unable to load file" );
-                i_return = 1;
-                goto end_seq;
+                size = ftell( file );
+                fseek( file, 0, SEEK_SET);
+                buffer = malloc( size + 1 );
+                fread( buffer, 1, size, file);
+                buffer[ size ] = '\0';
+                if( vlm_Load( vlm, buffer ) )
+                {
+                    free( buffer );
+                    message = vlm_MessageNew( "load", "error while loading "
+                                              "file" );
+                    goto error;
+                }
+                free( buffer );
             }
             else
             {
-                int64_t size;
-                char *buffer;
+                message = vlm_MessageNew( "load", "read file error" );
+                goto error;
+            }
+
+            fclose( file );
+            message = vlm_MessageNew( "load", NULL );
+            goto success;
+        }
+    }
+
+    else
+    {
+        message = vlm_MessageNew( p_command[0], "Unknown command" );
+        goto error;
+    }
+
+    /* Common code between "new" and "setup" */
+    if( strcmp(p_command[0], "new") == 0 ||
+        strcmp(p_command[0], "setup") == 0 )
+    {
+        int i_command_start = strcmp(p_command[0], "new") ? 2 : 3;
+        vlm_media_t *media;
+        vlm_schedule_t *schedule;
+
+        if( i_command < i_command_start ) goto syntax_error;
+
+        media = vlm_MediaSearch( vlm, p_command[1] );
+        schedule = vlm_ScheduleSearch( vlm, p_command[1] );
+
+        if( !media && !schedule )
+        {
+            message = vlm_MessageNew( p_command[0], "%s unknown",
+                                      p_command[1] );
+            goto error;
+        }
+
+        if( schedule != NULL )
+        {
+            for( i = i_command_start ; i < i_command ; i++ )
+            {
+                if( strcmp( p_command[i], "enabled" ) == 0 ||
+                    strcmp( p_command[i], "disabled" ) == 0 )
+                {
+                    vlm_ScheduleSetup( schedule, p_command[i], NULL );
+                }
 
-                if( fseek( file, 0, SEEK_END) == 0 )
+                /* Beware: everything behind append is considered as 
+                 * command line */
+                else if( strcmp( p_command[i], "append" ) == 0 )
                 {
-                    size = ftell( file );
-                    fseek( file, 0, SEEK_SET);
-                    buffer = malloc( size + 1 );
-                    fread( buffer, 1, size, file);
-                    buffer[ size ] = '\0';
-                    if( vlm_Load( vlm, buffer ) )
+                    if( ++i >= i_command ) break;
+
+                    for( j = i + 1; j < i_command; j++ )
                     {
-                        free( buffer );
-                        message = vlm_MessageNew( "load", "error while loading file" );
-                        i_return = 1;
-                        goto end_seq;
+                        p_command[i] =
+                            realloc( p_command[i], strlen(p_command[i]) +
+                                     strlen(p_command[j]) + 1 + 1 );
+                        strcat( p_command[i], " " );
+                        strcat( p_command[i], p_command[j] );
                     }
-                    free( buffer );
+
+                    vlm_ScheduleSetup( schedule, p_command[i - 1],
+                                       p_command[i] );
+                    break;
                 }
                 else
                 {
-                    message = vlm_MessageNew( "load", "read file error" );
-                    i_return = 1;
-                    goto end_seq;
+                    if( i + 1 >= i_command && !strcmp(p_command[0], "new") )
+                    {
+                        vlm_ScheduleDelete( vlm, schedule, NULL );
+                        message = vlm_MessageNew( p_command[0],
+                                                  "Wrong properties syntax" );
+                        goto error;
+                    }
+                    else if( i + 1 >= i_command )
+                    {
+                        message = vlm_MessageNew( p_command[0],
+                                                  "Wrong properties syntax" );
+                        goto error;
+                    }
+
+                    vlm_ScheduleSetup( schedule, p_command[i],
+                                       p_command[i+1] );
+                    i++;
                 }
-                fclose( file );
-                message = vlm_MessageNew( "load", NULL );
-                i_return = 0;
-                goto end_seq;
             }
         }
-        else
+
+        else if( media != NULL )
         {
-            message = vlm_MessageNew( "load", "Wrong command" );
-            i_return = 1;
-            goto end_seq;
+            for( i = i_command_start ; i < i_command ; i++ )
+            {
+                if( strcmp( p_command[i], "enabled" ) == 0 ||
+                    strcmp( p_command[i], "disabled" ) == 0 )
+                {
+                    vlm_MediaSetup( vlm, media, p_command[i], NULL );
+                }
+                else if( strcmp( p_command[i], "loop" ) == 0 ||
+                         strcmp( p_command[i], "unloop" ) == 0 )
+                {
+                    if( media->i_type != BROADCAST_TYPE )
+                    {
+                        message = vlm_MessageNew( p_command[0],
+                                  "loop only available for broadcast" );
+                    }
+                    else
+                    {
+                        vlm_MediaSetup( vlm, media, p_command[i], NULL );
+                    }
+                }
+                else
+                {
+                    if( i + 1 >= i_command && !strcmp(p_command[0], "new") )
+                    {
+                        vlm_MediaDelete( vlm, media, NULL );
+                        message = vlm_MessageNew( p_command[0],
+                                                  "Wrong properties syntax" );
+                        goto error;
+                    }
+                    else if( i + 1 >= i_command )
+                    {
+                        message = vlm_MessageNew( p_command[0],
+                                                  "Wrong properties syntax" );
+                        goto error;
+                    }
+
+                    vlm_MediaSetup( vlm, media, p_command[i], p_command[i+1] );
+                    i++;
+                }
+            }
         }
-    }
-    else
-    {
-        message = vlm_MessageNew( p_command[0], "Unknown command" );
-        i_return = 1;
-        goto end_seq;
+
+        message = vlm_MessageNew( p_command[0], NULL );
+        goto success;
     }
 
-end_seq:
+success:
+    for( i = 0 ; i < i_command ; i++ ) free( p_command[i] );
+    if( p_command ) free( p_command );
+    *p_message = message;
 
-    for( i = 0 ; i < i_command ; i++ )
-    {
-        free( p_command[i] );
-    }
+    return VLC_SUCCESS;
+
+syntax_error:
+    message = vlm_MessageNew( p_command[0], "Wrong command syntax" );
 
+error:
+    for( i = 0 ; i < i_command ; i++ ) free( p_command[i] );
+    if( p_command ) free( p_command );
     *p_message = message;
 
-    return i_return;
+    return VLC_EGENERIC;
 }
 
 static vlm_media_t *vlm_MediaSearch( vlm_t *vlm, char *psz_name )
@@ -920,6 +715,27 @@ static vlm_media_t *vlm_MediaSearch( vlm_t *vlm, char *psz_name )
     return NULL;
 }
 
+/*****************************************************************************
+ * Media handling
+ *****************************************************************************/
+static vlm_media_instance_t *
+vlm_MediaInstanceSearch( vlm_t *vlm, vlm_media_t *media, char *psz_name )
+{
+    int i;
+
+    for( i = 0; i < media->i_instance; i++ )
+    {
+        if( ( !psz_name && !media->instance[i]->psz_name ) ||
+            ( psz_name && media->instance[i]->psz_name &&
+              !strcmp( psz_name, media->instance[i]->psz_name ) ) )
+        {
+            return media->instance[i];
+        }
+    }
+
+    return NULL;
+}
+
 static vlm_media_t *vlm_MediaNew( vlm_t *vlm, char *psz_name, int i_type )
 {
     vlm_media_t *media = malloc( sizeof( vlm_media_t ) );
@@ -933,6 +749,9 @@ static vlm_media_t *vlm_MediaNew( vlm_t *vlm, char *psz_name, int i_type )
         if( !vlm->vod->p_module )
         {
             msg_Err( vlm, "cannot find vod server" );
+            vlc_object_detach( vlm->vod );
+            vlc_object_destroy( vlm->vod );
+            vlm->vod = 0;
             free( media );
             return NULL;
         }
@@ -945,23 +764,15 @@ static vlm_media_t *vlm_MediaNew( vlm_t *vlm, char *psz_name, int i_type )
     media->vod_media = NULL;
     media->i_input = 0;
     media->input = NULL;
-    media->i_index = 0;
     media->psz_output = NULL;
     media->i_option = 0;
     media->option = NULL;
     media->i_type = i_type;
-    media->p_input = NULL;
+    media->i_instance = 0;
+    media->instance = NULL;
 
     media->item.psz_uri = strdup( psz_name );
-    media->item.psz_name = NULL;
-    media->item.i_duration = -1;
-    media->item.ppsz_options = NULL;
-    media->item.i_options = 0;
-    media->item.i_categories = 0;
-    media->item.pp_categories = NULL;
-    media->item.i_es = 0;
-    media->item.es = 0;
-    vlc_mutex_init( vlm, &media->item.lock );
+    vlc_input_item_Init( VLC_OBJECT(vlm), &media->item );
 
     TAB_APPEND( vlm->i_media, vlm->media, media );
 
@@ -969,19 +780,14 @@ static vlm_media_t *vlm_MediaNew( vlm_t *vlm, char *psz_name, int i_type )
 }
 
 /* for now, simple delete. After, del with options (last arg) */
-static int vlm_MediaDelete( vlm_t *vlm, vlm_media_t *media, char *psz_name )
+static void vlm_MediaDelete( vlm_t *vlm, vlm_media_t *media, char *psz_name )
 {
-    int i;
+    if( media == NULL ) return;
 
-    if( media == NULL ) return 1;
-
-    if( media->p_input )
+    while( media->i_instance )
     {
-        input_StopThread( media->p_input );
-
-        input_DestroyThread( media->p_input );
-        vlc_object_detach( media->p_input );
-        vlc_object_destroy( media->p_input );
+        vlm_media_instance_t *p_instance = media->instance[0];
+        vlm_MediaControl( vlm, media, p_instance->psz_name, "stop", 0 );
     }
 
     TAB_REMOVE( vlm->i_media, vlm->media, media );
@@ -1005,27 +811,17 @@ static int vlm_MediaDelete( vlm_t *vlm, vlm_media_t *media, char *psz_name )
 
     free( media->psz_name );
 
-    for( i = 0; i < media->i_input; i++ ) free( media->input[i] );
+    while( media->i_input-- ) free( media->input[media->i_input] );
     if( media->input ) free( media->input );
 
     if( media->psz_output ) free( media->psz_output );
 
-    for( i = 0; i < media->i_option; i++ ) free( media->option[i] );
-    if(media->option) free( media->option );
+    while( media->i_option-- ) free( media->option[media->i_option] );
+    if( media->option ) free( media->option );
 
-    if( media->item.psz_uri ) free( media->item.psz_uri );
-    if( media->item.psz_name ) free( media->item.psz_name );
-    vlc_mutex_destroy( &media->item.lock );
-    for( i = 0; i < media->item.i_options; i++ )
-    {
-        free( media->item.ppsz_options[i] );
-    }
-    if( media->item.ppsz_options ) free( media->item.ppsz_options );
-    /* FIXME: free the info categories. */
+    vlc_input_item_Clean( &media->item );
 
     free( media );
-
-    return 0;
 }
 
 static int vlm_MediaSetup( vlm_t *vlm, vlm_media_t *media, char *psz_cmd,
@@ -1085,7 +881,7 @@ static int vlm_MediaSetup( vlm_t *vlm, vlm_media_t *media, char *psz_cmd,
     }
     else
     {
-        return 1;
+        return VLC_EGENERIC;
     }
 
     /* Check if we need to create/delete a vod media */
@@ -1093,49 +889,48 @@ static int vlm_MediaSetup( vlm_t *vlm, vlm_media_t *media, char *psz_cmd,
     {
         if( !media->b_enabled && media->vod_media )
         {
-            int i;
-
-            for( i = 0; i < media->item.i_es; i++ )
-            {
-                es_format_Clean( media->item.es[i] );
-                free( media->item.es[i] );
-            }
-            if( media->item.es ) free( media->item.es );
-            media->item.es = 0;
-            media->item.i_es = 0;
-
             vlm->vod->pf_media_del( vlm->vod, media->vod_media );
             media->vod_media = 0;
         }
-        else if( media->b_enabled && !media->vod_media )
+        else if( media->b_enabled && !media->vod_media && media->i_input )
         {
             /* Pre-parse the input */
-            char *psz_output = media->psz_output;
+            input_thread_t *p_input;
+            char *psz_output;
+            int i;
+
+            vlc_input_item_Clean( &media->item );
+            vlc_input_item_Init( VLC_OBJECT(vlm), &media->item );
+
             if( media->psz_output )
-            {
-                asprintf( &media->psz_output, "%s:description",
-                          media->psz_output );
-            }
+                asprintf( &psz_output, "%s:description", media->psz_output );
             else
+                asprintf( &psz_output, "#description" );
+
+            media->item.psz_uri = strdup( media->input[0] );
+            media->item.ppsz_options = malloc( sizeof( char* ) );
+            asprintf( &media->item.ppsz_options[0], "sout=%s", psz_output);
+            media->item.i_options = 1;
+            for( i = 0; i < media->i_option; i++ )
             {
-                asprintf( &media->psz_output, "#description" );
+                media->item.i_options++;
+                media->item.ppsz_options =
+                    realloc( media->item.ppsz_options,
+                             media->item.i_options * sizeof( char* ) );
+                media->item.ppsz_options[ media->item.i_options - 1 ] =
+                    strdup( media->option[i] );
             }
 
-            if( !vlm_MediaControl( vlm, media, "play", 0 ) && media->p_input )
+            if( (p_input = input_CreateThread( vlm, &media->item ) ) )
             {
-                while( !media->p_input->b_eof && !media->p_input->b_error )
-                {
-                    msleep( 100000 );
-                }
+                while( !p_input->b_eof && !p_input->b_error ) msleep( 100000 );
 
-                input_StopThread( media->p_input );
-                input_DestroyThread( media->p_input );
-                vlc_object_detach( media->p_input );
-                vlc_object_destroy( media->p_input );
-                media->p_input = NULL;
+                input_StopThread( p_input );
+                input_DestroyThread( p_input );
+                vlc_object_detach( p_input );
+                vlc_object_destroy( p_input );
             }
-            free( media->psz_output );
-            media->psz_output = psz_output;
+            free( psz_output );
 
             media->vod_media =
                 vlm->vod->pf_media_new( vlm->vod, media->psz_name,
@@ -1143,70 +938,81 @@ static int vlm_MediaSetup( vlm_t *vlm, vlm_media_t *media, char *psz_cmd,
         }
     }
 
-    return 0;
+    return VLC_SUCCESS;
 }
 
-static int vlm_MediaControl( vlm_t *vlm, vlm_media_t *media, char *psz_name,
-                             char *psz_args )
+static int vlm_MediaControl( vlm_t *vlm, vlm_media_t *media, char *psz_id,
+                             char *psz_command, char *psz_args )
 {
-    if( strcmp( psz_name, "play" ) == 0 )
+    vlm_media_instance_t *p_instance;
+    int i;
+
+    p_instance = vlm_MediaInstanceSearch( vlm, media, psz_id );
+
+    if( strcmp( psz_command, "play" ) == 0 && !p_instance )
     {
-        int i;
+        if( !media->b_enabled || media->i_input == 0 ) return 0;
 
-        if( media->b_enabled == VLC_TRUE && media->i_input > 0 )
+        if( !p_instance )
         {
-            if( psz_args != NULL && sscanf( psz_args, "%d", &i ) == 1 &&
-                i < media->i_input )
-            {
-                media->i_index = i;
-            }
-            else
-            {
-                media->i_index = 0;
-            }
+            p_instance = malloc( sizeof(vlm_media_instance_t) );
+            memset( p_instance, 0, sizeof(vlm_media_instance_t) );
+            vlc_input_item_Init( VLC_OBJECT(vlm), &p_instance->item );
+            p_instance->p_input = 0;
 
-            if( media->item.psz_uri )
-            {
-                free( media->item.psz_uri );
-                media->item.psz_uri =NULL;
-            }
-            media->item.psz_uri = strdup( media->input[media->i_index] );
-
-            /* FIXME!!! we need an input_item_t per input spawned */
-            //input_ItemNew( &media->item );
             if( media->psz_output != NULL )
             {
-                media->item.ppsz_options = malloc( sizeof( char* ) );
-                asprintf( &media->item.ppsz_options[0], "sout=%s",
+                p_instance->item.ppsz_options = malloc( sizeof( char* ) );
+                asprintf( &p_instance->item.ppsz_options[0], "sout=%s",
                           media->psz_output );
-                media->item.i_options = 1;
-            }
-            else
-            {
-                media->item.ppsz_options = NULL;
-                media->item.i_options = 0;
+                p_instance->item.i_options = 1;
             }
 
             for( i = 0; i < media->i_option; i++ )
             {
-                media->item.i_options++;
-                media->item.ppsz_options =
-                    realloc( media->item.ppsz_options,
-                             media->item.i_options * sizeof( char* ) );
-                media->item.ppsz_options[ media->item.i_options - 1 ] =
+                p_instance->item.i_options++;
+                p_instance->item.ppsz_options =
+                    realloc( p_instance->item.ppsz_options,
+                             p_instance->item.i_options * sizeof( char* ) );
+                p_instance->item.ppsz_options[p_instance->item.i_options - 1] =
                     strdup( media->option[i] );
             }
 
-            media->p_input = input_CreateThread( vlm, &media->item );
+            p_instance->psz_name = psz_id ? strdup(psz_id) : 0;
+            TAB_APPEND( media->i_instance, media->instance, p_instance );
+        }
 
-            return 0;
+        if( psz_args && sscanf(psz_args, "%d", &i) == 1 && i < media->i_input )
+        {
+            p_instance->i_index = i;
         }
-        else
+
+        if( p_instance->item.psz_uri ) free( p_instance->item.psz_uri );
+        p_instance->item.psz_uri =
+            strdup( media->input[p_instance->i_index] );
+
+        if( p_instance->p_input )
         {
-            return 1;
+            input_StopThread( p_instance->p_input );
+            input_DestroyThread( p_instance->p_input );
+            vlc_object_detach( p_instance->p_input );
+            vlc_object_destroy( p_instance->p_input );
+        }
+
+        p_instance->p_input = input_CreateThread( vlm, &p_instance->item );
+        if( !p_instance->p_input )
+        {
+            TAB_REMOVE( media->i_instance, media->instance, p_instance );
+            vlc_input_item_Clean( &p_instance->item );
+            if( p_instance->psz_name ) free( p_instance->psz_name );
         }
+
+        return VLC_SUCCESS;
     }
-    else if( strcmp( psz_name, "seek" ) == 0 )
+
+    if( !p_instance ) return VLC_EGENERIC;
+
+    if( strcmp( psz_command, "seek" ) == 0 )
     {
         vlc_value_t val;
         float f_percentage;
@@ -1214,167 +1020,429 @@ static int vlm_MediaControl( vlm_t *vlm, vlm_media_t *media, char *psz_name,
         if( psz_args && sscanf( psz_args, "%f", &f_percentage ) == 1 )
         {
             val.f_float = f_percentage / 100.0 ;
-            var_Set( media->p_input, "position", val );
-            return 0;
+            var_Set( p_instance->p_input, "position", val );
+            return VLC_SUCCESS;
         }
     }
-    else if( strcmp( psz_name, "stop" ) == 0 )
+    else if( strcmp( psz_command, "stop" ) == 0 )
     {
-        /* FIXME!!! we need an input_item_t per input spawned */
-        if( media->p_input )
-        {
-            input_StopThread( media->p_input );
-            input_DestroyThread( media->p_input );
-            vlc_object_detach( media->p_input );
-            vlc_object_destroy( media->p_input );
-            media->p_input = NULL;
+        TAB_REMOVE( media->i_instance, media->instance, p_instance );
 
-            //input_ItemDelete( &media->item );
+        if( p_instance->p_input )
+        {
+            input_StopThread( p_instance->p_input );
+            input_DestroyThread( p_instance->p_input );
+            vlc_object_detach( p_instance->p_input );
+            vlc_object_destroy( p_instance->p_input );
         }
 
-        return 0;
+        vlc_input_item_Clean( &p_instance->item );
+        if( p_instance->psz_name ) free( p_instance->psz_name );
+        free( p_instance );
+
+        return VLC_SUCCESS;
     }
-    else if( strcmp( psz_name, "pause" ) == 0 )
+    else if( strcmp( psz_command, "pause" ) == 0 )
     {
         vlc_value_t val;
 
-        val.i_int = 0;
+        if( !p_instance->p_input ) return VLC_SUCCESS;
 
-        if( media->p_input != NULL )
-        {
-            var_Get( media->p_input, "state", &val );
-        }
+        var_Get( p_instance->p_input, "state", &val );
 
-        if( val.i_int == PAUSE_S )
-        {
-            if( media->p_input )
-            {
-                val.i_int = PLAYING_S;
-                var_Set( media->p_input, "state", val );
-            }
-        }
-        else
-        {
-            if( media->p_input )
-            {
-                val.i_int = PAUSE_S;
-                var_Set( media->p_input, "state", val );
-            }
-        }
-        return 0;
+        if( val.i_int == PAUSE_S ) val.i_int = PLAYING_S;
+        else val.i_int = PAUSE_S;
+        var_Set( p_instance->p_input, "state", val );
+
+        return VLC_SUCCESS;
     }
 
-    return 1;
+    return VLC_EGENERIC;
 }
 
-static vlm_message_t *vlm_Show( vlm_t *vlm, vlm_media_t *media,
-                                vlm_schedule_t *schedule, char *psz_filter )
+/*****************************************************************************
+ * Schedule handling
+ *****************************************************************************/
+static vlm_schedule_t *vlm_ScheduleNew( vlm_t *vlm, char *psz_name )
 {
+    vlm_schedule_t *sched = malloc( sizeof( vlm_schedule_t ) );
 
-    if( media != NULL )
-    {
-        int i;
-        vlm_message_t *message;
-        vlm_message_t *message_media;
-        vlm_message_t *message_child;
+    sched->psz_name = strdup( psz_name );
+    sched->b_enabled = VLC_FALSE;
+    sched->i_command = 0;
+    sched->command = NULL;
+    sched->i_date = 0;
+    sched->i_period = 0;
+    sched->i_repeat = -1;
 
-        message = vlm_MessageNew( "show", NULL );
-        message_media =
-            vlm_MessageAdd( message, vlm_MessageNew( media->psz_name, NULL ) );
+    TAB_APPEND( vlm->i_schedule, vlm->schedule, sched );
 
-        if( media->i_type == VOD_TYPE )
-        {
-            vlm_MessageAdd(message_media, vlm_MessageNew("type", "vod"));
-        }
-        else
-        {
-            vlm_MessageAdd(message_media, vlm_MessageNew("type", "broadcast"));
-        }
+    return sched;
+}
 
-        vlm_MessageAdd( message_media,
-                        vlm_MessageNew( "enabled", media->b_enabled ?
-                                        "yes" : "no" ) );
+/* for now, simple delete. After, del with options (last arg) */
+static void vlm_ScheduleDelete( vlm_t *vlm, vlm_schedule_t *sched,
+                                char *psz_name )
+{
+    if( sched == NULL ) return;
 
-        vlm_MessageAdd( message_media,
-                        vlm_MessageNew( "loop", media->b_loop ?
-                                        "yes" : "no" ) );
+    TAB_REMOVE( vlm->i_schedule, vlm->schedule, sched );
+
+    if( vlm->i_schedule == 0 && vlm->schedule ) free( vlm->schedule );
+    free( sched->psz_name );
+    while( sched->i_command-- ) free( sched->command[sched->i_command] );
+    free( sched );
+}
 
-        message_child = vlm_MessageAdd( message_media,
-                                        vlm_MessageNew( "inputs", NULL ) );
+static vlm_schedule_t *vlm_ScheduleSearch( vlm_t *vlm, char *psz_name )
+{
+    int i;
 
-        for( i = 0; i < media->i_input; i++ )
+    for( i = 0; i < vlm->i_schedule; i++ )
+    {
+        if( strcmp( psz_name, vlm->schedule[i]->psz_name ) == 0 )
         {
-            vlm_MessageAdd( message_child,
-                            vlm_MessageNew( media->input[i], NULL ) );
+            return vlm->schedule[i];
         }
+    }
 
-        vlm_MessageAdd( message_media,
-                        vlm_MessageNew( "output", media->psz_output ?
-                                        media->psz_output : "" ) );
+    return NULL;
+}
+
+/* Ok, setup schedule command will be able to support only one (argument value) at a time  */
+static int vlm_ScheduleSetup( vlm_schedule_t *schedule, char *psz_cmd,
+                              char *psz_value )
+{
+    if( strcmp( psz_cmd, "enabled" ) == 0 )
+    {
+        schedule->b_enabled = VLC_TRUE;
+    }
+    else if( strcmp( psz_cmd, "disabled" ) == 0 )
+    {
+        schedule->b_enabled = VLC_FALSE;
+    }
+    else if( strcmp( psz_cmd, "date" ) == 0 )
+    {
+        struct tm time;
+        char *p;
+        time_t date;
+
+        time.tm_sec = 0;         /* seconds */
+        time.tm_min = 0;         /* minutes */
+        time.tm_hour = 0;        /* hours */
+        time.tm_mday = 0;        /* day of the month */
+        time.tm_mon = 0;         /* month */
+        time.tm_year = 0;        /* year */
+        time.tm_wday = 0;        /* day of the week */
+        time.tm_yday = 0;        /* day in the year */
+        time.tm_isdst = 0;       /* daylight saving time */
 
-        message_child = vlm_MessageAdd( message_media,
-                                        vlm_MessageNew( "options", NULL ) );
+        /* date should be year/month/day-hour:minutes:seconds */
+        p = strchr( psz_value, '-' );
 
-        for( i=0 ; i < (media->i_option) ; i++ )
+        if( strcmp( psz_value, "now" ) == 0 )
         {
-            vlm_MessageAdd( message_child,
-                            vlm_MessageNew( media->option[i], NULL ) );
+            schedule->i_date = 0;
         }
-
-        if( media->p_input != NULL )
+        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 */
         {
-            vlc_value_t val;
-
-            var_Get( media->p_input, "state", &val );
+            return 1;
+        }
+        else
+        {
+            int i,j,k;
 
-            if( val.i_int == PLAYING_S )
+            switch( sscanf( p + 1, "%d:%d:%d", &i, &j, &k ) )
             {
-                vlm_MessageAdd( message_media,
-                                vlm_MessageNew( "state", "playing" ) );
+                case 1:
+                    time.tm_sec = i;
+                    break;
+                case 2:
+                    time.tm_min = i;
+                    time.tm_sec = j;
+                    break;
+                case 3:
+                    time.tm_hour = i;
+                    time.tm_min = j;
+                    time.tm_sec = k;
+                    break;
+                default:
+                    return 1;
             }
-            else if( val.i_int == PAUSE_S )
+
+            *p = '\0';
+
+            switch( sscanf( psz_value, "%d/%d/%d", &i, &j, &k ) )
             {
-                vlm_MessageAdd( message_media,
-                                vlm_MessageNew( "state", "paused" ) );
+                case 1:
+                    time.tm_mday = i;
+                    break;
+                case 2:
+                    time.tm_mon = i - 1;
+                    time.tm_mday = j;
+                    break;
+                case 3:
+                    time.tm_year = i - 1900;
+                    time.tm_mon = j - 1;
+                    time.tm_mday = k;
+                    break;
+                default:
+                    return 1;
             }
-            else
+
+            date = mktime( &time );
+            schedule->i_date = ((mtime_t) date) * 1000000;
+        }
+    }
+    else if( strcmp( psz_cmd, "period" ) == 0 )
+    {
+        struct tm time;
+        char *p;
+        char *psz_time = NULL, *psz_date = NULL;
+        time_t date;
+        int i,j,k;
+
+        /* First, if date or period are modified, repeat should be equal to -1 */
+        schedule->i_repeat = -1;
+
+        time.tm_sec = 0;         /* seconds */
+        time.tm_min = 0;         /* minutes */
+        time.tm_hour = 0;        /* hours */
+        time.tm_mday = 0;        /* day of the month */
+        time.tm_mon = 0;         /* month */
+        time.tm_year = 0;        /* year */
+        time.tm_wday = 0;        /* day of the week */
+        time.tm_yday = 0;        /* day in the year */
+        time.tm_isdst = 0;       /* daylight saving time */
+
+        /* date should be year/month/day-hour:minutes:seconds */
+        p = strchr( psz_value, '-' );
+        if( p )
+        {
+            psz_date = psz_value;
+            psz_time = p + 1;
+
+            *p = '\0';
+        }
+        else
+        {
+            psz_time = psz_value;
+        }
+
+
+        switch( sscanf( psz_time, "%d:%d:%d", &i, &j, &k ) )
+        {
+            case 1:
+                time.tm_sec = i;
+                break;
+            case 2:
+                time.tm_min = i;
+                time.tm_sec = j;
+                break;
+            case 3:
+                time.tm_hour = i;
+                time.tm_min = j;
+                time.tm_sec = k;
+                break;
+            default:
+                return 1;
+        }
+        if( psz_date )
+        {
+            switch( sscanf( psz_date, "%d/%d/%d", &i, &j, &k ) )
             {
-                vlm_MessageAdd( message_media,
-                                vlm_MessageNew( "state", "stop" ) );
+                case 1:
+                    time.tm_mday = i;
+                    break;
+                case 2:
+                    time.tm_mon = i;
+                    time.tm_mday = j;
+                    break;
+                case 3:
+                    time.tm_year = i;
+                    time.tm_mon = j;
+                    time.tm_mday = k;
+                    break;
+                default:
+                    return 1;
             }
         }
+
+        /* ok, that's stupid... who is going to schedule streams every 42 years ? */
+        date = (((( time.tm_year * 12 + time.tm_mon ) * 30 + time.tm_mday ) * 24 + time.tm_hour ) * 60 + time.tm_min ) * 60 + time.tm_sec ;
+        schedule->i_period = ((mtime_t) date) * 1000000;
+    }
+    else if( strcmp( psz_cmd, "repeat" ) == 0 )
+    {
+        int i;
+
+        if( sscanf( psz_value, "%d", &i ) == 1 )
+        {
+            schedule->i_repeat = i;
+        }
         else
         {
-            vlm_MessageAdd( message_media,
-                            vlm_MessageNew( "state", "stop" ) );
+            return 1;
         }
+    }
+    else if( strcmp( psz_cmd, "append" ) == 0 )
+    {
+        char *command = strdup( psz_value );
 
-        return message;
+        TAB_APPEND( schedule->i_command, schedule->command, command );
+    }
+    else
+    {
+        return 1;
+    }
+    return 0;
+}
+
+/*****************************************************************************
+ * Message handling functions
+ *****************************************************************************/
+static vlm_message_t *vlm_MessageNew( char *psz_name,
+                                      const char *psz_format, ... )
+{
+    vlm_message_t *p_message;
+    va_list args;
+
+    if( !psz_name ) return 0;
+
+    p_message = malloc( sizeof(vlm_message_t) );
+    p_message->psz_value = 0;
+
+    if( psz_format )
+    {
+        va_start( args, psz_format );
+        if( vasprintf( &p_message->psz_value, psz_format, args ) < 0 )
+        {
+            va_end( args );
+            free( p_message );
+            return 0;
+        }
+        va_end( args );
+    }
+
+    p_message->psz_name = strdup( psz_name );
+    p_message->i_child = 0;
+    p_message->child = NULL;
+
+    return p_message;
+}
+
+void vlm_MessageDelete( vlm_message_t *p_message )
+{
+    if( p_message->psz_name ) free( p_message->psz_name );
+    if( p_message->psz_value ) free( p_message->psz_value );
+    while( p_message->i_child-- )
+        vlm_MessageDelete( p_message->child[p_message->i_child] );
+    if( p_message->child ) free( p_message->child );
+    free( p_message );
+}
+
+/* Add a child */
+static vlm_message_t *vlm_MessageAdd( vlm_message_t *p_message,
+                                      vlm_message_t *p_child )
+{
+    if( p_message == NULL ) return NULL;
 
+    if( p_child )
+    {
+        TAB_APPEND( p_message->i_child, p_message->child, p_child );
     }
-    else if( schedule != NULL )
+
+    return p_child;
+}
+
+/*****************************************************************************
+ * Misc utility functions
+ *****************************************************************************/
+static vlm_message_t *vlm_Show( vlm_t *vlm, vlm_media_t *media,
+                                vlm_schedule_t *schedule, char *psz_filter )
+{
+    if( media != NULL )
     {
         int i;
-        vlm_message_t *message;
-        vlm_message_t *message_schedule;
-        vlm_message_t *message_child;
-        char buffer[100];
+        vlm_message_t *msg;
+        vlm_message_t *msg_media;
+        vlm_message_t *msg_child;
 
-        message = vlm_MessageNew( "show", NULL );
-        message_schedule =
-            vlm_MessageAdd( message, vlm_MessageNew( schedule->psz_name, 0 ) );
+        msg = vlm_MessageNew( "show", NULL );
+        msg_media = vlm_MessageAdd( msg, vlm_MessageNew( media->psz_name, 0 ));
 
-        vlm_MessageAdd( message_schedule, vlm_MessageNew("type", "schedule") );
+        vlm_MessageAdd( msg_media,
+                        vlm_MessageNew( "type", media->i_type == VOD_TYPE ?
+                                        "vod" : "broadcast" ) );
+        vlm_MessageAdd( msg_media,
+                        vlm_MessageNew( "enabled", media->b_enabled ?
+                                        "yes" : "no" ) );
 
-        if( schedule->b_enabled == VLC_TRUE )
+        vlm_MessageAdd( msg_media,
+                        vlm_MessageNew( "loop", media->b_loop ?
+                                        "yes" : "no" ) );
+
+        msg_child = vlm_MessageAdd( msg_media,
+                                    vlm_MessageNew( "inputs", NULL ) );
+
+        for( i = 0; i < media->i_input; i++ )
         {
-            vlm_MessageAdd(message_schedule, vlm_MessageNew("enabled", "yes"));
+            vlm_MessageAdd( msg_child,
+                            vlm_MessageNew( media->input[i], NULL ) );
         }
-        else
+
+        vlm_MessageAdd( msg_media,
+                        vlm_MessageNew( "output", media->psz_output ?
+                                        media->psz_output : "" ) );
+
+        msg_child = vlm_MessageAdd( msg_media, vlm_MessageNew( "options", 0 ));
+
+        for( i = 0; i < media->i_option; i++ )
         {
-            vlm_MessageAdd(message_schedule, vlm_MessageNew("enabled", "no"));
+            vlm_MessageAdd( msg_child, vlm_MessageNew( media->option[i], 0 ) );
         }
 
+        msg_child = vlm_MessageAdd( msg_media,
+                                    vlm_MessageNew( "instances", NULL ) );
+
+        for( i = 0; i < media->i_instance; i++ )
+        {
+            vlm_media_instance_t *p_instance = media->instance[i];
+            vlc_value_t val;
+
+            if( !p_instance->p_input ) val.i_int = END_S;
+            else var_Get( p_instance->p_input, "state", &val );
+
+            vlm_MessageAdd( msg_child,
+                vlm_MessageNew( p_instance->psz_name ?
+                                p_instance->psz_name : "default",
+                                val.i_int == PLAYING_S ? "playing" :
+                                val.i_int == PAUSE_S ? "paused" :
+                                "stopped" ) );
+        }
+
+        return msg;
+
+    }
+
+    else if( schedule != NULL )
+    {
+        int i;
+        vlm_message_t *msg;
+        vlm_message_t *msg_schedule;
+        vlm_message_t *msg_child;
+        char buffer[100];
+
+        msg = vlm_MessageNew( "show", NULL );
+        msg_schedule =
+            vlm_MessageAdd( msg, vlm_MessageNew( schedule->psz_name, 0 ) );
+
+        vlm_MessageAdd( msg_schedule, vlm_MessageNew("type", "schedule") );
+
+        vlm_MessageAdd( msg_schedule,
+                        vlm_MessageNew( "enabled", schedule->b_enabled ?
+                                        "yes" : "no" ) );
+
         if( schedule->i_date != 0 )
         {
             struct tm date;
@@ -1392,13 +1460,13 @@ static vlm_message_t *vlm_Show( vlm_t *vlm, vlm_media_t *media,
                       date.tm_year + 1900, date.tm_mon + 1, date.tm_mday,
                       date.tm_hour, date.tm_min, date.tm_sec );
 
-            vlm_MessageAdd( message_schedule,
+            vlm_MessageAdd( msg_schedule,
                             vlm_MessageNew( "date", psz_date ) );
             free( psz_date );
         }
         else
         {
-            vlm_MessageAdd( message_schedule, vlm_MessageNew("date", "now") );
+            vlm_MessageAdd( msg_schedule, vlm_MessageNew("date", "now") );
         }
 
         if( schedule->i_period != 0 )
@@ -1422,162 +1490,139 @@ static vlm_message_t *vlm_Show( vlm_t *vlm, vlm_media_t *media,
             sprintf( buffer, "%d/%d/%d-%d:%d:%d", date.tm_year, date.tm_mon,
                      date.tm_mday, date.tm_hour, date.tm_min, date.tm_sec);
 
-            vlm_MessageAdd(message_schedule, vlm_MessageNew("period", buffer));
+            vlm_MessageAdd( msg_schedule, vlm_MessageNew("period", buffer) );
         }
         else
         {
-            vlm_MessageAdd(message_schedule, vlm_MessageNew("period", "0"));
+            vlm_MessageAdd( msg_schedule, vlm_MessageNew("period", "0") );
         }
 
         sprintf( buffer, "%d", schedule->i_repeat );
-        vlm_MessageAdd( message_schedule, vlm_MessageNew( "repeat", buffer ) );
+        vlm_MessageAdd( msg_schedule, vlm_MessageNew( "repeat", buffer ) );
 
-        message_child =
-            vlm_MessageAdd( message_schedule, vlm_MessageNew("commands", 0) );
+        msg_child =
+            vlm_MessageAdd( msg_schedule, vlm_MessageNew("commands", 0) );
 
-        for( i = 0 ; i < schedule->i_command ; i++ )
+        for( i = 0; i < schedule->i_command; i++ )
         {
-           vlm_MessageAdd( message_child,
+           vlm_MessageAdd( msg_child,
                            vlm_MessageNew( schedule->command[i], NULL ) );
         }
 
-        return message;
+        return msg;
 
     }
+
     else if( psz_filter && strcmp( psz_filter, "media") == 0 )
     {
-        int i;
-        vlm_message_t *message;
-        vlm_message_t *message_child;
+        int i, j;
+        vlm_message_t *msg;
+        vlm_message_t *msg_child;
 
-        message = vlm_MessageNew( "show", NULL );
-        message_child =
-            vlm_MessageAdd( message, vlm_MessageNew( "media", NULL ) );
+        msg = vlm_MessageNew( "show", NULL );
+        msg_child = vlm_MessageAdd( msg, vlm_MessageNew( "media", NULL ) );
 
         for( i = 0; i < vlm->i_media; i++ )
         {
             vlm_media_t *m = vlm->media[i];
-            vlm_message_t *message_media =
-                vlm_MessageAdd(message_child, vlm_MessageNew(m->psz_name, 0));
+            vlm_message_t *msg_media, *msg_instance;
 
-            if( m->i_type == VOD_TYPE )
-            {
-                vlm_MessageAdd( message_media,
-                                vlm_MessageNew( "type", "vod" ) );
-            }
-            else
-            {
-                vlm_MessageAdd( message_media,
-                                vlm_MessageNew( "type", "broadcast" ) );
-            }
+            msg_media = vlm_MessageAdd( msg_child,
+                                        vlm_MessageNew( m->psz_name, 0 ) );
 
-            if( m->b_enabled == VLC_TRUE )
-            {
-                vlm_MessageAdd( message_media,
-                                vlm_MessageNew( "enabled", "yes" ) );
-            }
-            else
-            {
-                vlm_MessageAdd( message_media,
-                                vlm_MessageNew( "enabled", "no" ) );
-            }
+            vlm_MessageAdd( msg_media,
+                            vlm_MessageNew( "type", m->i_type == VOD_TYPE ?
+                                            "vod" : "broadcast" ) );
 
-            if( m->p_input != NULL )
+            vlm_MessageAdd( msg_media,
+                            vlm_MessageNew( "enabled", m->b_enabled ?
+                                            "yes" : "no" ) );
+
+            msg_instance = vlm_MessageAdd( msg_media,
+                                           vlm_MessageNew( "instances", 0 ) );
+
+            for( j = 0; j < m->i_instance; j++ )
             {
+                vlm_media_instance_t *p_instance = m->instance[j];
                 vlc_value_t val;
 
-                var_Get( m->p_input, "state", &val );
+                if( !p_instance->p_input ) val.i_int = END_S;
+                else var_Get( p_instance->p_input, "state", &val );
 
-                if( val.i_int == PLAYING_S )
-                {
-                    vlm_MessageAdd( message_media,
-                                    vlm_MessageNew( "state", "playing" ) );
-                }
-                else if( val.i_int == PAUSE_S )
-                {
-                    vlm_MessageAdd( message_media,
-                                    vlm_MessageNew( "state", "paused" ) );
-                }
-                else
-                {
-                    vlm_MessageAdd( message_media,
-                                    vlm_MessageNew( "state", "stop" ) );
-                }
-            }
-            else
-            {
-                vlm_MessageAdd( message_media,
-                                vlm_MessageNew( "state", "stop" ) );
+                vlm_MessageAdd( msg_instance,
+                    vlm_MessageNew( p_instance->psz_name ?
+                                    p_instance->psz_name : "default",
+                                    val.i_int == PLAYING_S ? "playing" :
+                                    val.i_int == PAUSE_S ? "paused" :
+                                    "stopped" ) );
             }
         }
 
-        return message;
+        return msg;
     }
+
     else if( psz_filter && strcmp( psz_filter, "schedule") == 0 )
     {
         int i;
-        vlm_message_t *message;
-        vlm_message_t *message_child;
+        vlm_message_t *msg;
+        vlm_message_t *msg_child;
 
-        message = vlm_MessageNew( "show", NULL );
-        message_child =
-            vlm_MessageAdd( message, vlm_MessageNew( "schedule", NULL ) );
+        msg = vlm_MessageNew( "show", NULL );
+        msg_child = vlm_MessageAdd( msg, vlm_MessageNew( "schedule", NULL ) );
 
         for( i = 0; i < vlm->i_schedule; i++ )
         {
             vlm_schedule_t *s = vlm->schedule[i];
-            vlm_message_t *message_schedule =
-                vlm_MessageAdd(message_child, vlm_MessageNew(s->psz_name, 0)); 
+            vlm_message_t *msg_schedule;
+            mtime_t i_time, i_next_date;
 
-            if( s->b_enabled == VLC_TRUE )
-            {
-                mtime_t i_time;
-                mtime_t i_next_date;
+            msg_schedule = vlm_MessageAdd( msg_child,
+                                           vlm_MessageNew( s->psz_name, 0 ) );
+            vlm_MessageAdd( msg_schedule,
+                            vlm_MessageNew( "enabled", s->b_enabled ?
+                                            "yes" : "no" ) );
 
-                vlm_MessageAdd( message_schedule,
-                                vlm_MessageNew( "enabled", "yes" ) );
+            if( !s->b_enabled ) return msg;
 
-                /* calculate next date */
-                i_time = mdate();
 
-                i_next_date = s->i_date;
+            vlm_MessageAdd( msg_schedule,
+                            vlm_MessageNew( "enabled", "yes" ) );
 
-                if( s->i_period != 0 )
-                {
-                    int j = 0;
-                    while( s->i_date + j * s->i_period <= i_time &&
-                           s->i_repeat > j )
-                    {
-                        j++;
-                    }
+            /* calculate next date */
+            i_time = mdate();
+            i_next_date = s->i_date;
 
-                    i_next_date = s->i_date + j * s->i_period;
+            if( s->i_period != 0 )
+            {
+                int j = 0;
+                while( s->i_date + j * s->i_period <= i_time &&
+                       s->i_repeat > j )
+                {
+                    j++;
                 }
 
-                if( i_next_date > i_time )
-                {
-                    time_t i_date = (time_t) (i_next_date / 1000000) ;
+                i_next_date = s->i_date + j * s->i_period;
+            }
+
+            if( i_next_date > i_time )
+            {
+                time_t i_date = (time_t) (i_next_date / 1000000) ;
 
 #ifdef HAVE_CTIME_R
-                    char psz_date[500];
-                    ctime_r( &i_date, psz_date );
+                char psz_date[500];
+                ctime_r( &i_date, psz_date );
 #else
-                    char *psz_date = ctime( &i_date );
+                char *psz_date = ctime( &i_date );
 #endif
 
-                    vlm_MessageAdd( message_schedule,
-                                    vlm_MessageNew("next launch", psz_date) );
-                }
-            }
-            else
-            {
-                vlm_MessageAdd( message_schedule,
-                                vlm_MessageNew( "enabled", "no" ) );
+                vlm_MessageAdd( msg_schedule,
+                                vlm_MessageNew( "next launch", psz_date ) );
             }
         }
 
-        return message;
+        return msg;
     }
+
     else if( psz_filter == NULL && media == NULL && schedule == NULL )
     {
         vlm_message_t *show1 = vlm_Show( vlm, NULL, NULL, "media" );
@@ -1592,6 +1637,7 @@ static vlm_message_t *vlm_Show( vlm_t *vlm, vlm_media_t *media,
 
         return show1;
     }
+
     else
     {
         return vlm_MessageNew( "show", NULL );
@@ -1637,7 +1683,9 @@ static vlm_message_t *vlm_Help( vlm_t *vlm, char *psz_filter )
     return vlm_MessageNew( "help", NULL );
 }
 
-/* file must end by '\0' */
+/*****************************************************************************
+ * Config handling functions
+ *****************************************************************************/
 static int vlm_Load( vlm_t *vlm, char *file )
 {
     char *pf = file;
@@ -1672,6 +1720,7 @@ static int vlm_Load( vlm_t *vlm, char *file )
 
         pf += i_next;
     }
+
     return 0;
 }
 
@@ -1908,261 +1957,13 @@ static char *vlm_Save( vlm_t *vlm )
     return save;
 }
 
-static vlm_schedule_t *vlm_ScheduleNew( vlm_t *vlm, char *psz_name )
-{
-    vlm_schedule_t *sched = malloc( sizeof( vlm_schedule_t ) );
-
-    sched->psz_name = strdup( psz_name );
-    sched->b_enabled = VLC_FALSE;
-    sched->i_command = 0;
-    sched->command = NULL;
-    sched->i_date = 0;
-    sched->i_period = 0;
-    sched->i_repeat = -1;
-
-    TAB_APPEND( vlm->i_schedule, vlm->schedule, sched );
-
-    return sched;
-}
-
-/* for now, simple delete. After, del with options (last arg) */
-static int vlm_ScheduleDelete( vlm_t *vlm, vlm_schedule_t *sched,
-                               char *psz_name )
-{
-    int i;
-
-    if( sched == NULL )
-    {
-        return 1;
-    }
-
-    TAB_REMOVE( vlm->i_schedule, vlm->schedule, sched );
-
-    if( vlm->i_schedule == 0 && vlm->schedule ) free( vlm->schedule );
-
-    free( sched->psz_name );
-
-    for( i = 0; i < sched->i_command; i++ )
-    {
-        free( sched->command[i] );
-    }
-
-    free( sched );
-
-    return 0;
-}
-
-static vlm_schedule_t *vlm_ScheduleSearch( vlm_t *vlm, char *psz_name )
-{
-    int i;
-
-    for( i = 0; i < vlm->i_schedule; i++ )
-    {
-        if( strcmp( psz_name, vlm->schedule[i]->psz_name ) == 0 )
-        {
-            return vlm->schedule[i];
-        }
-    }
-
-    return NULL;
-}
-
-/* Ok, setup schedule command will be able to support only one (argument value) at a time  */
-static int vlm_ScheduleSetup( vlm_schedule_t *schedule, char *psz_cmd,
-                              char *psz_value )
-{
-    if( strcmp( psz_cmd, "enabled" ) == 0 )
-    {
-        schedule->b_enabled = VLC_TRUE;
-    }
-    else if( strcmp( psz_cmd, "disabled" ) == 0 )
-    {
-        schedule->b_enabled = VLC_FALSE;
-    }
-    else if( strcmp( psz_cmd, "date" ) == 0 )
-    {
-        struct tm time;
-        char *p;
-        time_t date;
-
-        time.tm_sec = 0;         /* seconds */
-        time.tm_min = 0;         /* minutes */
-        time.tm_hour = 0;        /* hours */
-        time.tm_mday = 0;        /* day of the month */
-        time.tm_mon = 0;         /* month */
-        time.tm_year = 0;        /* year */
-        time.tm_wday = 0;        /* day of the week */
-        time.tm_yday = 0;        /* day in the year */
-        time.tm_isdst = 0;       /* daylight saving time */
-
-        /* date should be year/month/day-hour:minutes:seconds */
-        p = strchr( psz_value, '-' );
-
-        if( strcmp( psz_value, "now" ) == 0 )
-        {
-            schedule->i_date = 0;
-        }
-        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 */
-        {
-            return 1;
-        }
-        else
-        {
-            int i,j,k;
-
-            switch( sscanf( p + 1, "%d:%d:%d", &i, &j, &k ) )
-            {
-                case 1:
-                    time.tm_sec = i;
-                    break;
-                case 2:
-                    time.tm_min = i;
-                    time.tm_sec = j;
-                    break;
-                case 3:
-                    time.tm_hour = i;
-                    time.tm_min = j;
-                    time.tm_sec = k;
-                    break;
-                default:
-                    return 1;
-            }
-
-            *p = '\0';
-
-            switch( sscanf( psz_value, "%d/%d/%d", &i, &j, &k ) )
-            {
-                case 1:
-                    time.tm_mday = i;
-                    break;
-                case 2:
-                    time.tm_mon = i - 1;
-                    time.tm_mday = j;
-                    break;
-                case 3:
-                    time.tm_year = i - 1900;
-                    time.tm_mon = j - 1;
-                    time.tm_mday = k;
-                    break;
-                default:
-                    return 1;
-            }
-
-            date = mktime( &time );
-            schedule->i_date = ((mtime_t) date) * 1000000;
-        }
-    }
-    else if( strcmp( psz_cmd, "period" ) == 0 )
-    {
-        struct tm time;
-        char *p;
-        char *psz_time = NULL, *psz_date = NULL;
-        time_t date;
-        int i,j,k;
-
-        /* First, if date or period are modified, repeat should be equal to -1 */
-        schedule->i_repeat = -1;
-
-        time.tm_sec = 0;         /* seconds */
-        time.tm_min = 0;         /* minutes */
-        time.tm_hour = 0;        /* hours */
-        time.tm_mday = 0;        /* day of the month */
-        time.tm_mon = 0;         /* month */
-        time.tm_year = 0;        /* year */
-        time.tm_wday = 0;        /* day of the week */
-        time.tm_yday = 0;        /* day in the year */
-        time.tm_isdst = 0;       /* daylight saving time */
-
-        /* date should be year/month/day-hour:minutes:seconds */
-        p = strchr( psz_value, '-' );
-        if( p )
-        {
-            psz_date = psz_value;
-            psz_time = p + 1;
-
-            *p = '\0';
-        }
-        else
-        {
-            psz_time = psz_value;
-        }
-
-
-        switch( sscanf( psz_time, "%d:%d:%d", &i, &j, &k ) )
-        {
-            case 1:
-                time.tm_sec = i;
-                break;
-            case 2:
-                time.tm_min = i;
-                time.tm_sec = j;
-                break;
-            case 3:
-                time.tm_hour = i;
-                time.tm_min = j;
-                time.tm_sec = k;
-                break;
-            default:
-                return 1;
-        }
-        if( psz_date )
-        {
-            switch( sscanf( psz_date, "%d/%d/%d", &i, &j, &k ) )
-            {
-                case 1:
-                    time.tm_mday = i;
-                    break;
-                case 2:
-                    time.tm_mon = i;
-                    time.tm_mday = j;
-                    break;
-                case 3:
-                    time.tm_year = i;
-                    time.tm_mon = j;
-                    time.tm_mday = k;
-                    break;
-                default:
-                    return 1;
-            }
-        }
-
-        /* ok, that's stupid... who is going to schedule streams every 42 years ? */
-        date = (((( time.tm_year * 12 + time.tm_mon ) * 30 + time.tm_mday ) * 24 + time.tm_hour ) * 60 + time.tm_min ) * 60 + time.tm_sec ;
-        schedule->i_period = ((mtime_t) date) * 1000000;
-    }
-    else if( strcmp( psz_cmd, "repeat" ) == 0 )
-    {
-        int i;
-
-        if( sscanf( psz_value, "%d", &i ) == 1 )
-        {
-            schedule->i_repeat = i;
-        }
-        else
-        {
-            return 1;
-        }
-    }
-    else if( strcmp( psz_cmd, "append" ) == 0 )
-    {
-        char *command = strdup( psz_value );
-
-        TAB_APPEND( schedule->i_command, schedule->command, command );
-    }
-    else
-    {
-        return 1;
-    }
-    return 0;
-}
-
 /*****************************************************************************
  * Manage:
  *****************************************************************************/
 static int Manage( vlc_object_t* p_object )
 {
     vlm_t *vlm = (vlm_t*)p_object;
-    int i,j;
+    int i, j;
     mtime_t i_lastcheck;
     mtime_t i_time;
 
@@ -2177,31 +1978,37 @@ static int Manage( vlc_object_t* p_object )
         /* destroy the inputs that wants to die, and launch the next input */
         for( i = 0; i < vlm->i_media; i++ )
         {
-            vlm_media_t *media = vlm->media[i];
+            vlm_media_t *p_media = vlm->media[i];
 
-            if( media->p_input != NULL &&
-                ( media->p_input->b_eof || media->p_input->b_error ) )
+            for( j = 0; j < p_media->i_instance; j++ )
             {
-                input_StopThread( media->p_input );
+                vlm_media_instance_t *p_instance = p_media->instance[j];
 
-                input_DestroyThread( media->p_input );
-                vlc_object_detach( media->p_input );
-                vlc_object_destroy( media->p_input );
-                media->p_input = NULL;
-                media->i_index++;
+                if( !p_instance->p_input ||
+                    ( !p_instance->p_input->b_eof &&
+                      !p_instance->p_input->b_error ) ) continue;
 
-                if( media->i_index == media->i_input &&
-                    media->b_loop == VLC_TRUE )
-                {
-                    media->i_index = 0;
-                }
+                input_StopThread( p_instance->p_input );
+                input_DestroyThread( p_instance->p_input );
+                vlc_object_detach( p_instance->p_input );
+                vlc_object_destroy( p_instance->p_input );
+
+                p_instance->i_index++;
+                if( p_instance->i_index == p_media->i_input &&
+                    p_media->b_loop ) p_instance->i_index = 0;
 
-                if( media->i_index < media->i_input )
+                if( p_instance->i_index < p_media->i_input )
                 {
+                    /* FIXME, find a way to select the right instance */
                     char buffer[12];
-
-                    sprintf( buffer, "%d", media->i_index );
-                    vlm_MediaControl( vlm, media, "play", buffer );
+                    sprintf( buffer, "%d", p_instance->i_index );
+                    vlm_MediaControl( vlm, p_media, p_instance->psz_name,
+                                      "play", buffer );
+                }
+                else
+                {
+                    if( vlm_MediaControl( vlm, p_media, p_instance->psz_name,
+                                          "stop", 0 ) == VLC_SUCCESS ) i--;
                 }
             }
         }
@@ -2260,60 +2067,3 @@ static int Manage( vlc_object_t* p_object )
 
     return VLC_SUCCESS;
 }
-
-static vlm_message_t* vlm_MessageNew( char *psz_name, char *psz_value )
-{
-    vlm_message_t *message = malloc( sizeof(vlm_message_t) );
-
-    if( psz_name )
-    {
-        message->psz_name = strdup( psz_name );
-    }
-    else
-    {
-        return NULL;
-    }
-
-    if( psz_value )
-    {
-        message->psz_value = strdup( psz_value );
-    }
-    else
-    {
-        message->psz_value = NULL;
-    }
-
-    message->i_child = 0;
-    message->child = NULL;
-
-    return message;
-}
-
-void vlm_MessageDelete( vlm_message_t* message )
-{
-    int i;
-
-    if( message->psz_name ) free( message->psz_name );
-    if( message->psz_value ) free( message->psz_value );
-
-    for( i = 0; i < message->i_child; i++)
-    {
-        vlm_MessageDelete( message->child[i] );
-    }
-
-    free( message );
-}
-
-/* Add a child */
-static vlm_message_t *vlm_MessageAdd( vlm_message_t* message,
-                                      vlm_message_t* child )
-{
-    if( message == NULL ) return NULL;
-
-    if( child )
-    {
-        TAB_APPEND( message->i_child, message->child, child );
-    }
-
-    return child;
-}