]> git.sesse.net Git - vlc/commitdiff
* ./include/variables.h, ./src/misc/variables.c: implemented variable
authorSam Hocevar <sam@videolan.org>
Wed, 16 Oct 2002 19:39:42 +0000 (19:39 +0000)
committerSam Hocevar <sam@videolan.org>
Wed, 16 Oct 2002 19:39:42 +0000 (19:39 +0000)
    callbacks.

include/variables.h
include/vlc_common.h
src/misc/variables.c

index 52b398389c58d76b27e930d3771d719c498fa1c4..7f5cb5ff1775445db210c9c303d0357da3e2f29b 100644 (file)
@@ -2,7 +2,7 @@
  * variables.h: variables handling
  *****************************************************************************
  * Copyright (C) 2002 VideoLAN
- * $Id: variables.h,v 1.3 2002/10/14 19:04:51 sam Exp $
+ * $Id: variables.h,v 1.4 2002/10/16 19:39:42 sam Exp $
  *
  * Authors: Samuel Hocevar <sam@zoy.org>
  *
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
  *****************************************************************************/
 
-/* Variable types - probably very incomplete */
-#define VLC_VAR_BOOL      0x0100
-#define VLC_VAR_INTEGER   0x0200
-#define VLC_VAR_STRING    0x0300
-#define VLC_VAR_MODULE    0x0301
-#define VLC_VAR_FILE      0x0302
-#define VLC_VAR_FLOAT     0x0400
-#define VLC_VAR_TIME      0x0500
-#define VLC_VAR_ADDRESS   0x0600
-#define VLC_VAR_COMMAND   0x0700
-#define VLC_VAR_MUTEX     0x0800
+typedef struct callback_entry_t callback_entry_t;
 
 /*****************************************************************************
  * vlc_value_t is the common union for variable values; variable_t is the
  *****************************************************************************/
 struct variable_t
 {
-    u32          i_hash;
-    char *       psz_name;
+    /* The variable's exported value */
+    vlc_value_t  val;
 
+    /* The variable unique name, (almost) unique hashed value, and type */
+    char *       psz_name;
+    u32          i_hash;
     int          i_type;
-    vlc_value_t  val;
 
     /* Lots of other things that can be added */
     int          i_usage;
-    vlc_bool_t   b_set;
-    vlc_bool_t   b_active;
+
+    int                i_entries;
+    callback_entry_t * p_entries;
 };
 
+/*****************************************************************************
+ * Variable types - probably very incomplete
+ *****************************************************************************/
+#define VLC_VAR_BOOL      0x0100
+#define VLC_VAR_INTEGER   0x0200
+#define VLC_VAR_STRING    0x0300
+#define VLC_VAR_MODULE    0x0301
+#define VLC_VAR_FILE      0x0302
+#define VLC_VAR_FLOAT     0x0400
+#define VLC_VAR_TIME      0x0500
+#define VLC_VAR_ADDRESS   0x0600
+#define VLC_VAR_COMMAND   0x0700
+#define VLC_VAR_MUTEX     0x0800
+
 /*****************************************************************************
  * Prototypes
  *****************************************************************************/
@@ -61,18 +68,25 @@ VLC_EXPORT( int, __var_Type, ( vlc_object_t *, const char * ) );
 VLC_EXPORT( int, __var_Set, ( vlc_object_t *, const char *, vlc_value_t ) );
 VLC_EXPORT( int, __var_Get, ( vlc_object_t *, const char *, vlc_value_t * ) );
 
-#define var_Create(a,b,c) \
-    __var_Create( VLC_OBJECT(a), b, c )
+#define var_Create(a,b,c) __var_Create( VLC_OBJECT(a), b, c )
+#define var_Destroy(a,b) __var_Destroy( VLC_OBJECT(a), b )
 
-#define var_Destroy(a,b) \
-    __var_Destroy( VLC_OBJECT(a), b )
+#define var_Type(a,b) __var_Type( VLC_OBJECT(a), b )
+#define var_Set(a,b,c) __var_Set( VLC_OBJECT(a), b, c )
+#define var_Get(a,b,c) __var_Get( VLC_OBJECT(a), b, c )
 
-#define var_Type(a,b) \
-    __var_Type( VLC_OBJECT(a), b )
-
-#define var_Set(a,b,c) \
-    __var_Set( VLC_OBJECT(a), b, c )
+/*****************************************************************************
+ * Variable callbacks
+ *****************************************************************************
+ * int MyCallback( vlc_object_t *p_this,
+ *                 char const *psz_variable,
+ *                 vlc_value_t oldvalue,
+ *                 vlc_value_t newvalue,
+ *                 void *p_data);
+ *****************************************************************************/
+VLC_EXPORT( int, __var_AddCallback, ( vlc_object_t *, const char *, vlc_callback_t, void * ) );
+VLC_EXPORT( int, __var_DelCallback, ( vlc_object_t *, const char *, vlc_callback_t, void * ) );
 
-#define var_Get(a,b,c) \
-    __var_Get( VLC_OBJECT(a), b, c )
+#define var_AddCallback(a,b,c,d) __var_AddCallback( VLC_OBJECT(a), b, c, d )
+#define var_DelCallback(a,b,c,d) __var_DelCallback( VLC_OBJECT(a), b, c, d )
 
index 3796830d76a9cf731df361e62c54e4b16fcbd92e..a17400391891a19a723db55437072c1b5914143c 100644 (file)
@@ -3,7 +3,7 @@
  * Collection of useful common types and macros definitions
  *****************************************************************************
  * Copyright (C) 1998, 1999, 2000 VideoLAN
- * $Id: vlc_common.h,v 1.30 2002/10/16 15:10:39 sam Exp $
+ * $Id: vlc_common.h,v 1.31 2002/10/16 19:39:42 sam Exp $
  *
  * Authors: Samuel Hocevar <sam@via.ecp.fr>
  *          Vincent Seguin <seguin@via.ecp.fr>
@@ -236,6 +236,15 @@ typedef struct bit_stream_t bit_stream_t;
 typedef struct network_socket_t network_socket_t;
 typedef struct iso639_lang_t iso639_lang_t;
 
+/*****************************************************************************
+ * Variable callbacks
+ *****************************************************************************/
+typedef int ( * vlc_callback_t ) ( vlc_object_t *,      /* variable's object */
+                                   char const *,            /* variable name */
+                                   vlc_value_t,                 /* old value */
+                                   vlc_value_t,                 /* new value */
+                                   void * );                /* callback data */
+
 /*****************************************************************************
  * Plug-in stuff
  *****************************************************************************/
index 3db0d7e5fc541b8f7b505869402d0abace7bb9aa..3c73184ffbeeefa009ca115a7f35af41efbbb1a8 100644 (file)
@@ -2,7 +2,7 @@
  * variables.c: routines for object variables handling
  *****************************************************************************
  * Copyright (C) 2002 VideoLAN
- * $Id: variables.c,v 1.6 2002/10/16 10:31:58 sam Exp $
+ * $Id: variables.c,v 1.7 2002/10/16 19:39:42 sam Exp $
  *
  * Authors: Samuel Hocevar <sam@zoy.org>
  *
 #   include <stdlib.h>                                          /* realloc() */
 #endif
 
+/*****************************************************************************
+ * Private types
+ *****************************************************************************/
+struct callback_entry_t
+{
+    vlc_callback_t pf_callback;
+    void *         p_data;
+};
+
 /*****************************************************************************
  * Local prototypes
  *****************************************************************************/
@@ -96,15 +105,37 @@ int __var_Create( vlc_object_t *p_this, const char *psz_name, int i_type )
     memset( &p_var->val, 0, sizeof(vlc_value_t) );
 
     p_var->i_usage = 1;
-    p_var->b_set = VLC_FALSE;
-    p_var->b_active = VLC_TRUE;
 
+    p_var->i_entries = 0;
+    p_var->p_entries = NULL;
+
+    /* Always initialize the variable */
     switch( i_type )
     {
+        case VLC_VAR_BOOL:
+            p_var->val.b_bool = VLC_FALSE;
+            break;
+        case VLC_VAR_INTEGER:
+            p_var->val.i_int = 0;
+            break;
+        case VLC_VAR_STRING:
+        case VLC_VAR_MODULE:
+        case VLC_VAR_FILE:
+            p_var->val.psz_string = strdup( "" );
+            break;
+        case VLC_VAR_FLOAT:
+            p_var->val.f_float = 0.0;
+            break;
+        case VLC_VAR_TIME:
+            /* TODO */
+            break;
+        case VLC_VAR_ADDRESS:
+        case VLC_VAR_COMMAND:
+            p_var->val.p_address = NULL;
+            break;
         case VLC_VAR_MUTEX:
             p_var->val.p_address = malloc( sizeof(vlc_mutex_t) );
             vlc_mutex_init( p_this, (vlc_mutex_t*)p_var->val.p_address );
-            p_var->b_set = VLC_TRUE;
             break;
     }
 
@@ -149,10 +180,7 @@ int __var_Destroy( vlc_object_t *p_this, const char *psz_name )
         case VLC_VAR_STRING:
         case VLC_VAR_MODULE:
         case VLC_VAR_FILE:
-            if( p_var->b_set && p_var->val.psz_string )
-            {
-                free( p_var->val.psz_string );
-            }
+            free( p_var->val.psz_string );
             break;
 
         case VLC_VAR_MUTEX:
@@ -161,6 +189,12 @@ int __var_Destroy( vlc_object_t *p_this, const char *psz_name )
             break;
     }
 
+    /* Free callbacks if needed */
+    if( p_var->p_entries )
+    {
+        free( p_var->p_entries );
+    }
+
     free( p_var->psz_name );
 
     memmove( p_this->p_vars + i_del,
@@ -214,6 +248,8 @@ int __var_Type( vlc_object_t *p_this, const char *psz_name )
 int __var_Set( vlc_object_t *p_this, const char *psz_name, vlc_value_t val )
 {
     int i_var;
+    variable_t *p_var;
+    vlc_value_t oldval;
 
     vlc_mutex_lock( &p_this->var_lock );
 
@@ -225,28 +261,47 @@ int __var_Set( vlc_object_t *p_this, const char *psz_name, vlc_value_t val )
         return VLC_ENOVAR;
     }
 
-    /* Duplicate value if needed */
-    switch( p_this->p_vars[i_var].i_type )
+    p_var = &p_this->p_vars[i_var];
+
+    /* Duplicate data if needed */
+    switch( p_var->i_type )
     {
         case VLC_VAR_STRING:
         case VLC_VAR_MODULE:
         case VLC_VAR_FILE:
-            if( p_this->p_vars[i_var].b_set
-                 && p_this->p_vars[i_var].val.psz_string )
-            {
-                free( p_this->p_vars[i_var].val.psz_string );
-            }
-            if( val.psz_string )
-            {
-                val.psz_string = strdup( val.psz_string );
-            }
+            val.psz_string = strdup( val.psz_string );
             break;
     }
 
-    p_this->p_vars[i_var].val = val;
-    p_this->p_vars[i_var].b_set = VLC_TRUE;
+    /* Backup needed stuff */
+    oldval = p_var->val;
 
-    /* XXX: callback stuff will go here */
+    /* Set the variable */
+    p_var->val = val;
+
+    /* Deal with callbacks */
+    if( p_var->i_entries )
+    {
+        int i;
+
+        for( i = p_var->i_entries ; i-- ; )
+        {
+            /* FIXME: oooh, see the deadlocks! see the race conditions! */
+            p_var->p_entries[i].pf_callback( p_this, p_var->psz_name,
+                                             oldval, val,
+                                             p_var->p_entries[i].p_data );
+        }
+    }
+
+    /* Free data if needed */
+    switch( p_var->i_type )
+    {
+        case VLC_VAR_STRING:
+        case VLC_VAR_MODULE:
+        case VLC_VAR_FILE:
+            free( oldval.psz_string );
+            break;
+    }
 
     vlc_mutex_unlock( &p_this->var_lock );
 
@@ -261,6 +316,7 @@ int __var_Set( vlc_object_t *p_this, const char *psz_name, vlc_value_t val )
 int __var_Get( vlc_object_t *p_this, const char *psz_name, vlc_value_t *p_val )
 {
     int i_var;
+    variable_t *p_var;
 
     vlc_mutex_lock( &p_this->var_lock );
 
@@ -272,26 +328,23 @@ int __var_Get( vlc_object_t *p_this, const char *psz_name, vlc_value_t *p_val )
         return VLC_ENOVAR;
     }
 
-    if( !p_this->p_vars[i_var].b_set )
-    {
-        vlc_mutex_unlock( &p_this->var_lock );
-        return VLC_EBADVAR;
-    }
+    p_var = &p_this->p_vars[i_var];
 
     /* Some variables trigger special behaviour. */
-    switch( p_this->p_vars[i_var].i_type )
+    switch( p_var->i_type )
     {
         case VLC_VAR_COMMAND:
-            if( p_this->p_vars[i_var].b_set )
+            if( p_var->val.p_address )
             {
-                /* We need this to avoid deadlocks */
+                /* We need to save data before releasing the lock */
                 int i_ret;
                 int (*pf_command) (vlc_object_t *, char *, char *) =
-                                          p_this->p_vars[i_var].val.p_address;
-                char *psz_cmd = strdup( p_this->p_vars[i_var].psz_name );
+                                          p_var->val.p_address;
+                char *psz_cmd = strdup( p_var->psz_name );
                 char *psz_arg = strdup( p_val->psz_string );
 
                 vlc_mutex_unlock( &p_this->var_lock );
+
                 i_ret = pf_command( p_this, psz_cmd, psz_arg );
                 free( psz_cmd );
                 free( psz_arg );
@@ -302,10 +355,10 @@ int __var_Get( vlc_object_t *p_this, const char *psz_name, vlc_value_t *p_val )
     }
 
     /* Really set the variable */
-    *p_val = p_this->p_vars[i_var].val;
+    *p_val = p_var->val;
 
     /* Duplicate value if needed */
-    switch( p_this->p_vars[i_var].i_type )
+    switch( p_var->i_type )
     {
         case VLC_VAR_STRING:
         case VLC_VAR_MODULE:
@@ -322,6 +375,110 @@ int __var_Get( vlc_object_t *p_this, const char *psz_name, vlc_value_t *p_val )
     return VLC_SUCCESS;
 }
 
+/*****************************************************************************
+ * var_AddCallback: register a callback in a variable
+ *****************************************************************************
+ * We store a function pointer pf_callback that will be called upon variable
+ * modification. p_data is a generic pointer that will be passed as additional
+ * argument to the callback function.
+ *****************************************************************************/
+int __var_AddCallback( vlc_object_t *p_this, const char *psz_name,
+                       vlc_callback_t pf_callback, void *p_data )
+{
+    int i_var, i_entry;
+    variable_t *p_var;
+
+    vlc_mutex_lock( &p_this->var_lock );
+
+    i_var = Lookup( p_this->p_vars, p_this->i_vars, psz_name );
+    if( i_var < 0 )
+    {
+        vlc_mutex_unlock( &p_this->var_lock );
+        return VLC_ENOVAR;
+    }
+
+    p_var = &p_this->p_vars[i_var];
+
+    i_entry = p_var->i_entries++;
+
+    if( i_entry )
+    {
+        p_var->p_entries = realloc( p_var->p_entries,
+                               sizeof( callback_entry_t ) * p_var->i_entries );
+    }
+    else
+    {
+        p_var->p_entries = malloc( sizeof( callback_entry_t ) );
+    }
+
+    p_var->p_entries[ i_entry ].pf_callback = pf_callback;
+    p_var->p_entries[ i_entry ].p_data = p_data;
+        
+    vlc_mutex_unlock( &p_this->var_lock );
+
+    return VLC_SUCCESS;
+}
+
+/*****************************************************************************
+ * var_DelCallback: remove a callback from a variable
+ *****************************************************************************
+ * pf_callback and p_data have to be given again, because different objects
+ * might have registered the same callback function.
+ *****************************************************************************/
+int __var_DelCallback( vlc_object_t *p_this, const char *psz_name,
+                       vlc_callback_t pf_callback, void *p_data )
+{
+    int i_var, i_entry;
+    variable_t *p_var;
+
+    vlc_mutex_lock( &p_this->var_lock );
+
+    i_var = Lookup( p_this->p_vars, p_this->i_vars, psz_name );
+    if( i_var < 0 )
+    {
+        vlc_mutex_unlock( &p_this->var_lock );
+        return VLC_ENOVAR;
+    }
+
+    p_var = &p_this->p_vars[i_var];
+
+    for( i_entry = p_var->i_entries ; i_entry-- ; )
+    {
+        if( p_var->p_entries[i_entry].pf_callback == pf_callback
+            || p_var->p_entries[i_entry].p_data == p_data )
+        {
+            break;
+        }
+    }
+
+    if( i_entry < 0 )
+    {
+        vlc_mutex_unlock( &p_this->var_lock );
+        return VLC_EGENERIC;
+    }
+
+    p_var->i_entries--;
+
+    memmove( p_var->p_entries + i_entry,
+             p_var->p_entries + i_entry + 1,
+             sizeof( callback_entry_t ) * ( p_var->i_entries - i_entry ) );
+
+    if( p_var->i_entries )
+    {
+        p_var->p_entries = realloc( p_var->p_entries,
+                       sizeof( callback_entry_t ) * ( p_var->i_entries ) );
+    }
+    else
+    {
+        free( p_var->p_entries );
+        p_var->p_entries = NULL;
+    }
+
+    vlc_mutex_unlock( &p_this->var_lock );
+
+    return VLC_SUCCESS;
+}
+
 /* Following functions are local */
 
 /*****************************************************************************