Start cleaning up VLM + fixed vlm_New() race condition.
authorLaurent Aimar <fenrir@videolan.org>
Thu, 1 Mar 2007 20:36:11 +0000 (20:36 +0000)
committerLaurent Aimar <fenrir@videolan.org>
Thu, 1 Mar 2007 20:36:11 +0000 (20:36 +0000)
include/vlc_vlm.h
src/control/vlm.c
src/input/vlm.c
src/input/vlm_internal.h [new file with mode: 0644]
src/misc/objects.c

index 0a2c3ab..315af5e 100644 (file)
@@ -36,77 +36,6 @@ extern "C" {
 #include <vlc_input.h>
 
 /* VLM specific - structures and functions */
-enum
-{
-    VOD_TYPE = 0,
-    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;
-
-struct vlm_media_t
-{
-    vlc_bool_t b_enabled;
-    int      i_type;
-
-    /* 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;
-    char *psz_vod_output;
-    char *psz_mux;
-
-    /* actual input instances */
-    int                  i_instance;
-    vlm_media_instance_t **instance;
-
-};
-
-struct vlm_schedule_t
-{
-    /* names "schedule" is reserved */
-    char    *psz_name;
-    vlc_bool_t b_enabled;
-    /* list of commands to execute on date */
-    int i_command;
-    char **command;
-
-    /* the date of 1st execution */
-    mtime_t i_date;
-
-    /* if != 0 repeat schedule every (period) */
-    mtime_t i_period;
-    /* number of times you have to repeat
-       i_repeat < 0 : endless repeat     */
-    int i_repeat;
-
-};
 
 /* ok, here is the structure of a vlm_message:
    The parent node is ( name_of_the_command , NULL ), or
@@ -122,42 +51,14 @@ struct vlm_message_t
 };
 
 
-struct vlm_t
-{
-    VLC_COMMON_MEMBERS
-
-    vlc_mutex_t lock;
-
-    int            i_media;
-    vlm_media_t    **media;
-
-    int            i_vod;
-    vod_t          *vod;
-
-    int            i_schedule;
-    vlm_schedule_t **schedule;
-};
-
-
 #define vlm_New( a ) __vlm_New( VLC_OBJECT(a) )
 VLC_EXPORT( vlm_t *, __vlm_New, ( vlc_object_t * ) );
-VLC_EXPORT( void, vlm_Delete, ( vlm_t * ) );
-VLC_EXPORT( int, vlm_ExecuteCommand, ( vlm_t *, const char *, vlm_message_t ** ) );
-VLC_EXPORT( void, vlm_MessageDelete, ( vlm_message_t * ) );
-VLC_EXPORT( vlm_media_t *, vlm_MediaNew, ( vlm_t *, const char *, int ) );
-VLC_EXPORT( void, vlm_MediaDelete, ( vlm_t *, vlm_media_t *, const char * ) );
-VLC_EXPORT( int, vlm_MediaSetup, ( vlm_t *, vlm_media_t *, const char *, const char * ) );
-VLC_EXPORT( int, vlm_MediaControl, ( vlm_t *, vlm_media_t *, const char *, const char *, const char * ) );
-VLC_EXPORT( vlm_media_t* , vlm_MediaSearch,( vlm_t *, const char *) );
-VLC_EXPORT( vlm_schedule_t *, vlm_ScheduleNew, ( vlm_t *, const char * ) );
-VLC_EXPORT( void, vlm_ScheduleDelete, ( vlm_t *, vlm_schedule_t *, const char * ) );
-VLC_EXPORT( int, vlm_ScheduleSetup, ( vlm_schedule_t *, const char *, const char * ) );
-VLC_EXPORT( int, vlm_MediaVodControl, ( void *, vod_media_t *, const char *, int, va_list ) );
-VLC_EXPORT( int, vlm_Save, ( vlm_t *, const char * ) );
-VLC_EXPORT( int, vlm_Load, ( vlm_t *, const char * ) );
+VLC_EXPORT( void,      vlm_Delete, ( vlm_t * ) );
+VLC_EXPORT( int,       vlm_ExecuteCommand, ( vlm_t *, const char *, vlm_message_t ** ) );
 
 VLC_EXPORT( vlm_message_t *, vlm_MessageNew, ( const char *, const char *, ... ) );
 VLC_EXPORT( vlm_message_t *, vlm_MessageAdd, ( vlm_message_t *, vlm_message_t * ) );
+VLC_EXPORT( void,            vlm_MessageDelete, ( vlm_message_t * ) );
 
 #ifdef __cpluplus
 }
index 78dced5..f23b2f2 100644 (file)
@@ -25,7 +25,7 @@
 #include <vlc/libvlc.h>
 #include <vlc_es.h>
 #include <vlc_input.h>
-#include <vlc_vlm.h>
+#include "../input/vlm_internal.h"
 
 static void InitVLM( libvlc_instance_t *p_instance )
 {
index 2129832..9763069 100644 (file)
@@ -45,6 +45,7 @@
 #include "input_internal.h"
 #include <vlc_stream.h>
 #include <vlc_vlm.h>
+#include "vlm_internal.h"
 #include <vlc_vod.h>
 #include <vlc_charset.h>
 
@@ -63,6 +64,18 @@ static int Load( vlm_t *, char * );
 static int ExecuteCommand( vlm_t *, const char *, vlm_message_t ** );
 static int Manage( vlc_object_t * );
 
+static int vlm_Save( vlm_t *p_vlm, const char *psz_file );
+static int vlm_Load( vlm_t *p_vlm, const char *psz_file );
+
+
+static vlm_schedule_t *vlm_ScheduleNew( vlm_t *vlm, const char *psz_name );
+static void vlm_ScheduleDelete( vlm_t *vlm, vlm_schedule_t *sched, const char *psz_name );
+static int vlm_ScheduleSetup( vlm_schedule_t *schedule, const char *psz_cmd,
+                       const char *psz_value );
+
+static int vlm_MediaVodControl( void *, vod_media_t *, const char *, int, va_list );
+
+
 /*****************************************************************************
  * vlm_New:
  *****************************************************************************/
@@ -72,30 +85,37 @@ vlm_t *__vlm_New ( vlc_object_t *p_this )
     vlm_t *p_vlm = NULL;
     char *psz_vlmconf;
 
-    /* to be sure to avoid multiple creation */
-    var_Create( p_this->p_libvlc_global, "vlm_mutex", VLC_VAR_MUTEX );
-    var_Get( p_this->p_libvlc_global, "vlm_mutex", &lockval );
+    /* Avoid multiple creation */
+    if( var_Create( p_this->p_libvlc_global, "vlm_mutex", VLC_VAR_MUTEX ) ||
+        var_Get( p_this->p_libvlc_global, "vlm_mutex", &lockval ) )
+        return NULL;
+
     vlc_mutex_lock( lockval.p_address );
 
-    if( !(p_vlm = vlc_object_find( p_this, VLC_OBJECT_VLM, FIND_ANYWHERE )) )
+    p_vlm = vlc_object_find( p_this, VLC_OBJECT_VLM, FIND_ANYWHERE );
+    if( p_vlm )
     {
-        msg_Info( p_this, "creating VLM" );
-        if( ( p_vlm = vlc_object_create( p_this, VLC_OBJECT_VLM ) ) == NULL )
-        {
-            vlc_mutex_unlock( lockval.p_address );
-            return NULL;
-        }
+        vlc_object_yield( p_vlm );
+        vlc_mutex_unlock( lockval.p_address );
+        return p_vlm;
+    }
 
-        vlc_mutex_init( p_this->p_libvlc, &p_vlm->lock );
-        TAB_INIT( p_vlm->i_media, p_vlm->media );
-        TAB_INIT( p_vlm->i_schedule, p_vlm->schedule );
-        p_vlm->i_vod = 0;
-        p_vlm->vod = NULL;
+    msg_Dbg( p_this, "creating VLM" );
 
-        vlc_object_yield( p_vlm );
-        vlc_object_attach( p_vlm, p_this->p_libvlc );
+    p_vlm = vlc_object_create( p_this, VLC_OBJECT_VLM );
+    if( !p_vlm )
+    {
+        vlc_mutex_unlock( lockval.p_address );
+        return NULL;
     }
-    vlc_mutex_unlock( lockval.p_address );
+
+    vlc_mutex_init( p_this->p_libvlc, &p_vlm->lock );
+    TAB_INIT( p_vlm->i_media, p_vlm->media );
+    TAB_INIT( p_vlm->i_schedule, p_vlm->schedule );
+    p_vlm->i_vod = 0;
+    p_vlm->vod = NULL;
+    vlc_object_yield( p_vlm );
+    vlc_object_attach( p_vlm, p_this->p_libvlc );
 
     if( vlc_thread_create( p_vlm, "vlm thread",
                            Manage, VLC_THREAD_PRIORITY_LOW, VLC_FALSE ) )
@@ -105,9 +125,8 @@ vlm_t *__vlm_New ( vlc_object_t *p_this )
         return NULL;
     }
 
-    /* Try loading the vlm conf file given by --vlm-conf */
-    psz_vlmconf = config_GetPsz( p_vlm, "vlm-conf" );
-
+    /* Load our configuration file */
+    psz_vlmconf = var_CreateGetString( p_vlm, "vlm-conf" );
     if( psz_vlmconf && *psz_vlmconf )
     {
         vlm_message_t *p_message = NULL;
@@ -117,17 +136,19 @@ vlm_t *__vlm_New ( vlc_object_t *p_this )
         asprintf(&psz_buffer, "load %s", psz_vlmconf );
         if( psz_buffer )
         {
-            msg_Dbg( p_this, psz_buffer);
-            if( vlm_ExecuteCommand( p_vlm, psz_buffer, &p_message ) ){
+            msg_Dbg( p_this, psz_buffer );
+            if( vlm_ExecuteCommand( p_vlm, psz_buffer, &p_message ) )
                 msg_Warn( p_this, "error while loading the configuration file" );
-            }
+
             vlm_MessageDelete(p_message);
             free(psz_buffer);
         }
-   }
-   free(psz_vlmconf);
+    }
+    free(psz_vlmconf);
 
-   return p_vlm;
+    vlc_mutex_unlock( lockval.p_address );
+
+    return p_vlm;
 }
 
 /*****************************************************************************
@@ -137,6 +158,7 @@ void vlm_Delete( vlm_t *p_vlm )
 {
     vlc_value_t lockval;
 
+    msg_Err( p_vlm, "vlm_Delete called" );
     var_Get( p_vlm->p_libvlc_global, "vlm_mutex", &lockval );
     vlc_mutex_lock( lockval.p_address );
 
@@ -151,16 +173,18 @@ void vlm_Delete( vlm_t *p_vlm )
     p_vlm->b_die = VLC_TRUE;
     vlc_thread_join( p_vlm );
 
+    vlc_object_detach( p_vlm );
+
     vlc_mutex_destroy( &p_vlm->lock );
 
-    while( p_vlm->i_media ) vlm_MediaDelete( p_vlm, p_vlm->media[0], NULL );
-    FREENULL( p_vlm->media );
+    while( p_vlm->i_media )
+        vlm_MediaDelete( p_vlm, p_vlm->media[0], NULL );
+    TAB_CLEAN( p_vlm->i_media, p_vlm->media );
 
-    while( p_vlm->i_schedule ) vlm_ScheduleDelete( p_vlm,
-                                                   p_vlm->schedule[0], NULL );
-    FREENULL( p_vlm->schedule );
+    while( p_vlm->i_schedule )
+        vlm_ScheduleDelete( p_vlm, p_vlm->schedule[0], NULL );
+    TAB_CLEAN( p_vlm->schedule, p_vlm->schedule );
 
-    vlc_object_detach( p_vlm );
     vlc_object_destroy( p_vlm );
     vlc_mutex_unlock( lockval.p_address );
 }
@@ -180,77 +204,6 @@ int vlm_ExecuteCommand( vlm_t *p_vlm, const char *psz_command,
     return i_result;
 }
 
-/*****************************************************************************
- * vlm_Save:
- *****************************************************************************/
-int vlm_Save( vlm_t *p_vlm, const char *psz_file )
-{
-    FILE *file;
-    char *psz_save;
-
-    if( !p_vlm || !psz_file ) return 1;
-
-    file = utf8_fopen( psz_file, "wt" );
-    if( file == NULL ) return 1;
-
-    psz_save = Save( p_vlm );
-    if( psz_save == NULL )
-    {
-        fclose( file );
-        return 1;
-    }
-    fwrite( psz_save, strlen( psz_save ), 1, file );
-    fclose( file );
-    free( psz_save );
-
-    return 0;
-}
-
-/*****************************************************************************
- * vlm_Load:
- *****************************************************************************/
-int vlm_Load( vlm_t *p_vlm, const char *psz_file )
-{
-    stream_t *p_stream;
-    int64_t i_size;
-    char *psz_buffer;
-
-    if( !p_vlm || !psz_file ) return 1;
-
-    p_stream = stream_UrlNew( p_vlm, psz_file );
-    if( p_stream == NULL ) return 1;
-
-    if( stream_Seek( p_stream, 0 ) != 0 )
-    {
-        stream_Delete( p_stream );
-        return 2;
-    }
-
-    i_size = stream_Size( p_stream );
-
-    psz_buffer = malloc( i_size + 1 );
-    if( !psz_buffer )
-    {
-        stream_Delete( p_stream );
-        return 2;
-    }
-
-    stream_Read( p_stream, psz_buffer, i_size );
-    psz_buffer[ i_size ] = '\0';
-
-    stream_Delete( p_stream );
-
-    if( Load( p_vlm, psz_buffer ) )
-    {
-        free( psz_buffer );
-        return 3;
-    }
-
-    free( psz_buffer );
-
-    return 0;
-}
-
 
 static const char quotes[] = "\"'";
 /**
@@ -891,6 +844,80 @@ vlm_media_t *vlm_MediaSearch( vlm_t *vlm, const char *psz_name )
     return NULL;
 }
 
+/*****************************************************************************
+ * vlm_Save:
+ *****************************************************************************/
+static int vlm_Save( vlm_t *p_vlm, const char *psz_file )
+{
+    FILE *file;
+    char *psz_save;
+
+    if( !p_vlm || !psz_file )
+        return 1;
+
+    file = utf8_fopen( psz_file, "wt" );
+    if( file == NULL ) return 1;
+
+    psz_save = Save( p_vlm );
+    if( psz_save == NULL )
+    {
+        fclose( file );
+        return 1;
+    }
+    fwrite( psz_save, strlen( psz_save ), 1, file );
+    fclose( file );
+    free( psz_save );
+
+    return 0;
+}
+
+/*****************************************************************************
+ * vlm_Load:
+ *****************************************************************************/
+static int vlm_Load( vlm_t *p_vlm, const char *psz_file )
+{
+    stream_t *p_stream;
+    int64_t i_size;
+    char *psz_buffer;
+
+    if( !p_vlm || !psz_file )
+        return 1;
+
+    p_stream = stream_UrlNew( p_vlm, psz_file );
+    if( p_stream == NULL ) return 1;
+
+    if( stream_Seek( p_stream, 0 ) != 0 )
+    {
+        stream_Delete( p_stream );
+        return 2;
+    }
+
+    i_size = stream_Size( p_stream );
+
+    psz_buffer = malloc( i_size + 1 );
+    if( !psz_buffer )
+    {
+        stream_Delete( p_stream );
+        return 2;
+    }
+
+    stream_Read( p_stream, psz_buffer, i_size );
+    psz_buffer[ i_size ] = '\0';
+
+    stream_Delete( p_stream );
+
+    if( Load( p_vlm, psz_buffer ) )
+    {
+        free( psz_buffer );
+        return 3;
+    }
+
+    free( psz_buffer );
+
+    return 0;
+}
+
+
 /*****************************************************************************
  * Media handling
  *****************************************************************************/
@@ -1400,7 +1427,7 @@ static int64_t vlm_Date(void)
 #endif
 }
 
-vlm_schedule_t *vlm_ScheduleNew( vlm_t *vlm, const char *psz_name )
+static vlm_schedule_t *vlm_ScheduleNew( vlm_t *vlm, const char *psz_name )
 {
     vlm_schedule_t *p_sched = malloc( sizeof( vlm_schedule_t ) );
 
@@ -1428,7 +1455,7 @@ vlm_schedule_t *vlm_ScheduleNew( vlm_t *vlm, const char *psz_name )
 }
 
 /* for now, simple delete. After, del with options (last arg) */
-void vlm_ScheduleDelete( vlm_t *vlm, vlm_schedule_t *sched,
+static void vlm_ScheduleDelete( vlm_t *vlm, vlm_schedule_t *sched,
                          const char *psz_name )
 {
     if( sched == NULL ) return;
@@ -1462,7 +1489,7 @@ static vlm_schedule_t *vlm_ScheduleSearch( vlm_t *vlm, const char *psz_name )
 }
 
 /* Ok, setup schedule command will be able to support only one (argument value) at a time  */
-int vlm_ScheduleSetup( vlm_schedule_t *schedule, const char *psz_cmd,
+static int vlm_ScheduleSetup( vlm_schedule_t *schedule, const char *psz_cmd,
                        const char *psz_value )
 {
     if( !strcmp( psz_cmd, "enabled" ) )
@@ -2380,8 +2407,8 @@ static char *Save( vlm_t *vlm )
 /*****************************************************************************
  * Manage:
  *****************************************************************************/
-int vlm_MediaVodControl( void *p_private, vod_media_t *p_vod_media,
-                         const char *psz_id, int i_query, va_list args )
+static int vlm_MediaVodControl( void *p_private, vod_media_t *p_vod_media,
+                                const char *psz_id, int i_query, va_list args )
 {
     vlm_t *vlm = (vlm_t *)p_private;
     int i, i_ret = VLC_EGENERIC;
@@ -2590,23 +2617,39 @@ static int Manage( vlc_object_t* p_object )
 vlm_t *__vlm_New( vlc_object_t *a )
 {
     msg_Err( a, "VideoLAN manager support is disabled" );
-    return 0;
+    return NULL;
+}
+void vlm_Delete( vlm_t *a )
+{
+    ;
+}
+int vlm_ExecuteCommand( vlm_t *a, char *b, vlm_message_t **c )
+{
+    return -1;
+}
+void vlm_MessageDelete( vlm_message_t *a )
+{
+    ;
+}
+vlm_media_t *vlm_MediaNew( vlm_t *a, char *b, int c )
+{
+    return NULL;
+}
+vlm_media_t *vlm_MediaSearch (vlm_t *a, const char *b )
+{
+    return NULL;
+}
+void vlm_MediaDelete( vlm_t *a, vlm_media_t *b, char *c )
+{
+    ;
+}
+int vlm_MediaSetup( vlm_t *a, vlm_media_t *b, char *c, char *d )
+{
+    return -1;
 }
-void vlm_Delete( vlm_t *a ){}
-int vlm_ExecuteCommand( vlm_t *a, char *b, vlm_message_t **c ){ return -1; }
-void vlm_MessageDelete( vlm_message_t *a ){}
-vlm_media_t *vlm_MediaNew( vlm_t *a, char *b, int c ){ return NULL; }
-vlm_media_t *vlm_MediaSearch (vlm_t *a, const char *b ) { return NULL; }
-void vlm_MediaDelete( vlm_t *a, vlm_media_t *b, char *c ){}
-int vlm_MediaSetup( vlm_t *a, vlm_media_t *b, char *c, char *d ){ return -1; }
 int vlm_MediaControl( vlm_t *a, vlm_media_t *b, char *c, char *d, char *e )
-    { return -1; }
-vlm_schedule_t * vlm_ScheduleNew( vlm_t *a, char *b ){ return NULL; }
-void  vlm_ScheduleDelete( vlm_t *a, vlm_schedule_t *b, char *c ){}
-int vlm_ScheduleSetup( vlm_schedule_t *a, char *b, char *c ){ return -1; }
-int vlm_MediaVodControl( void *a, vod_media_t *b, char *c, int d, va_list e )
-    { return -1; }
-int vlm_Save( vlm_t *a, char *b ){ return -1; }
-int vlm_Load( vlm_t *a, char *b ){ return -1; }
+{
+    return -1;
+}
 
 #endif /* ENABLE_VLM */
diff --git a/src/input/vlm_internal.h b/src/input/vlm_internal.h
new file mode 100644 (file)
index 0000000..fdf431d
--- /dev/null
@@ -0,0 +1,123 @@
+/*****************************************************************************
+ * vlm_internal.h: Internal vlm structures
+ *****************************************************************************
+ * Copyright (C) 1998-2006 the VideoLAN team
+ * $Id$
+ *
+ * Authors: Laurent Aimar <fenrir@via.ecp.fr>
+ *
+ * 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+#ifndef _VLM_INTERNAL_H
+#define _VLM_INTERNAL_H 1
+
+#include <vlc_vlm.h>
+
+
+enum
+{
+       VOD_TYPE = 0,
+       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;
+
+struct vlm_media_t
+{
+    vlc_bool_t b_enabled;
+    int      i_type;
+
+    /* 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;
+    char *psz_vod_output;
+    char *psz_mux;
+
+    /* actual input instances */
+    int                  i_instance;
+    vlm_media_instance_t **instance;
+};
+
+struct vlm_schedule_t
+{
+    /* names "schedule" is reserved */
+    char    *psz_name;
+    vlc_bool_t b_enabled;
+    /* list of commands to execute on date */
+    int i_command;
+    char **command;
+
+    /* the date of 1st execution */
+    mtime_t i_date;
+
+    /* if != 0 repeat schedule every (period) */
+    mtime_t i_period;
+    /* number of times you have to repeat
+       i_repeat < 0 : endless repeat     */
+    int i_repeat;
+};
+
+
+struct vlm_t
+{
+    VLC_COMMON_MEMBERS
+
+    vlc_mutex_t lock;
+
+    int            i_media;
+    vlm_media_t    **media;
+
+    int            i_vod;
+    vod_t          *vod;
+
+    int            i_schedule;
+    vlm_schedule_t **schedule;
+};
+
+vlm_media_t *vlm_MediaNew( vlm_t *, const char *, int );
+void            vlm_MediaDelete( vlm_t *, vlm_media_t *, const char * );
+int                     vlm_MediaSetup( vlm_t *, vlm_media_t *, const char *, const char * );
+int                     vlm_MediaControl( vlm_t *, vlm_media_t *, const char *, const char *, const char * );
+vlm_media_t *vlm_MediaSearch( vlm_t *, const char *);
+
+#endif
index 717efb5..04be619 100644 (file)
@@ -55,6 +55,7 @@
 
 #include "vlc_httpd.h"
 #include "vlc_vlm.h"
+#include "input/vlm_internal.h"
 #include "vlc_vod.h"
 #include "vlc_tls.h"
 #include "vlc_xml.h"