[vlc-devel] [PATCH 2/3] core: add a new type of callback for list variables

Felix Abecassis felix.abecassis at gmail.com
Wed Jul 23 14:43:08 CEST 2014


This new callback is triggered when an element is added/removed from
the list, or when the list is cleared.
---
 include/vlc_common.h    |  17 +++++++-
 include/vlc_variables.h |   6 +++
 src/libvlccore.sym      |   2 +
 src/misc/variables.c    | 102 ++++++++++++++++++++++++++++++++++++++++++++----
 4 files changed, 118 insertions(+), 9 deletions(-)

diff --git a/include/vlc_common.h b/include/vlc_common.h
index 8b4b923..128177e 100644
--- a/include/vlc_common.h
+++ b/include/vlc_common.h
@@ -382,7 +382,7 @@ struct vlc_list_t
 #define VLC_ENOITEM        (-8) /**< Item not found */
 
 /*****************************************************************************
- * Variable callbacks
+ * Variable callbacks: called when the value is modified
  *****************************************************************************/
 typedef int ( * vlc_callback_t ) ( vlc_object_t *,      /* variable's object */
                                    char const *,            /* variable name */
@@ -391,6 +391,21 @@ typedef int ( * vlc_callback_t ) ( vlc_object_t *,      /* variable's object */
                                    void * );                /* callback data */
 
 /*****************************************************************************
+ * List callbacks: called when elements are added/removed from the list
+ *****************************************************************************/
+typedef int ( * vlc_list_callback_t ) ( vlc_object_t *,      /* variable's object */
+                                        char const *,            /* variable name */
+                                        int,                  /* VLC_VAR_* action */
+                                        vlc_value_t *,      /* new/deleted value  */
+                                        void *);                 /* callback data */
+
+typedef enum
+{
+    vlc_value_callback,
+    vlc_list_callback
+} vlc_callback_type_t;
+
+/*****************************************************************************
  * OS-specific headers and thread types
  *****************************************************************************/
 #if defined( _WIN32 )
diff --git a/include/vlc_variables.h b/include/vlc_variables.h
index 420f0b4..6f48aa1 100644
--- a/include/vlc_variables.h
+++ b/include/vlc_variables.h
@@ -183,10 +183,16 @@ VLC_API int var_AddCallback( vlc_object_t *, const char *, vlc_callback_t, void
 VLC_API int var_DelCallback( vlc_object_t *, const char *, vlc_callback_t, void * );
 VLC_API int var_TriggerCallback( vlc_object_t *, const char * );
 
+VLC_API int var_AddListCallback( vlc_object_t *, const char *, vlc_list_callback_t, void * );
+VLC_API int var_DelListCallback( vlc_object_t *, const char *, vlc_list_callback_t, void * );
+
 #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 )
 #define var_TriggerCallback(a,b) var_TriggerCallback( VLC_OBJECT(a), b )
 
+#define var_AddListCallback(a,b,c,d) var_AddListCallback( VLC_OBJECT(a), b, c, d )
+#define var_DelListCallback(a,b,c,d) var_DelListCallback( VLC_OBJECT(a), b, c, d )
+
 /*****************************************************************************
  * helpers functions
  *****************************************************************************/
diff --git a/src/libvlccore.sym b/src/libvlccore.sym
index 325c8f6..679958d 100644
--- a/src/libvlccore.sym
+++ b/src/libvlccore.sym
@@ -452,9 +452,11 @@ vlc_socket
 vlc_accept
 utf8_vfprintf
 var_AddCallback
+var_AddListCallback
 var_Change
 var_Create
 var_DelCallback
+var_DelListCallback
 var_Destroy
 var_FreeList
 var_Get
diff --git a/src/misc/variables.c b/src/misc/variables.c
index 369d2e5..659ab72 100644
--- a/src/misc/variables.c
+++ b/src/misc/variables.c
@@ -49,7 +49,13 @@
  *****************************************************************************/
 struct callback_entry_t
 {
-    vlc_callback_t pf_callback;
+    vlc_callback_type_t i_type;
+    union
+    {
+        vlc_callback_t       pf_value_callback;
+        vlc_list_callback_t  pf_list_callback;
+        void *               p_callback;
+    } u;
     void *         p_data;
 };
 
@@ -136,6 +142,10 @@ static void     CheckValue  ( variable_t *, vlc_value_t * );
 static int      TriggerCallback( vlc_object_t *, variable_t *, const char *,
                                  vlc_value_t );
 
+static int      TriggerListCallback( vlc_object_t *, variable_t *,
+                                     const char *, int,
+                                     vlc_value_t * );
+
 static int varcmp( const void *a, const void *b )
 {
     const variable_t *va = a, *vb = b;
@@ -461,6 +471,8 @@ int var_Change( vlc_object_t *p_this, const char *psz_name,
                 strdup( p_val2->psz_string ) : NULL;
 
             CheckValue( p_var, &p_var->val );
+
+            TriggerListCallback(p_this, p_var, psz_name, VLC_VAR_ADDCHOICE, p_val);
             break;
         }
         case VLC_VAR_DELCHOICE:
@@ -490,6 +502,8 @@ int var_Change( vlc_object_t *p_this, const char *psz_name,
                          p_var->choices_text.i_count, i );
 
             CheckValue( p_var, &p_var->val );
+
+            TriggerListCallback(p_this, p_var, psz_name, VLC_VAR_DELCHOICE, p_val);
             break;
         }
         case VLC_VAR_CHOICESCOUNT:
@@ -509,6 +523,7 @@ int var_Change( vlc_object_t *p_this, const char *psz_name,
             p_var->choices_text.i_count = 0;
             p_var->choices_text.p_values = NULL;
             p_var->i_default = -1;
+            TriggerListCallback(p_this, p_var, psz_name, VLC_VAR_CLEARCHOICES, NULL);
             break;
         case VLC_VAR_SETDEFAULT:
         {
@@ -820,7 +835,7 @@ static int AddCallback( vlc_object_t *p_this, const char *psz_name,
     {
         vlc_mutex_unlock( &p_priv->var_lock );
         msg_Err( p_this, "cannot add callback %p to nonexistent "
-                         "variable '%s'", entry.pf_callback, psz_name );
+                         "variable '%s'", entry.u.p_callback, psz_name );
         return VLC_ENOVAR;
     }
 
@@ -856,7 +871,8 @@ int var_AddCallback( vlc_object_t *p_this, const char *psz_name,
                      vlc_callback_t pf_callback, void *p_data )
 {
     callback_entry_t entry;
-    entry.pf_callback = pf_callback;
+    entry.i_type = vlc_value_callback;
+    entry.u.pf_value_callback = pf_callback;
     entry.p_data = p_data;
 
     return AddCallback(p_this, psz_name, entry);
@@ -888,13 +904,13 @@ static int DelCallback( vlc_object_t *p_this, const char *psz_name,
 
     for( i_entry = p_var->i_entries ; i_entry-- ; )
     {
-        if( p_var->p_entries[i_entry].pf_callback == entry.pf_callback
+        if( p_var->p_entries[i_entry].u.p_callback == entry.u.p_callback
             && p_var->p_entries[i_entry].p_data == entry.p_data )
         {
             break;
         }
 #ifndef NDEBUG
-        else if( p_var->p_entries[i_entry].pf_callback == pf_callback )
+        else if( p_var->p_entries[i_entry].u.p_callback == entry.u.p_callback )
             b_found_similar = true;
 #endif
     }
@@ -929,7 +945,8 @@ int var_DelCallback( vlc_object_t *p_this, const char *psz_name,
                      vlc_callback_t pf_callback, void *p_data )
 {
     callback_entry_t entry;
-    entry.pf_callback = pf_callback;
+    entry.i_type = vlc_value_callback;
+    entry.u.pf_value_callback = pf_callback;
     entry.p_data = p_data;
 
     return DelCallback(p_this, psz_name, entry);
@@ -970,6 +987,43 @@ int var_TriggerCallback( vlc_object_t *p_this, const char *psz_name )
     return i_ret;
 }
 
+#undef var_AddListCallback
+/**
+ * Register a callback for a list variable
+ *
+ * The callback is triggered when an element is added/removed from the
+ * list or when the list is cleared.
+ *
+ * See var_AddCallback().
+ */
+int var_AddListCallback( vlc_object_t *p_this, const char *psz_name,
+                         vlc_list_callback_t pf_callback, void *p_data )
+{
+    callback_entry_t entry;
+    entry.i_type = vlc_list_callback;
+    entry.u.pf_list_callback = pf_callback;
+    entry.p_data = p_data;
+
+    return AddCallback(p_this, psz_name, entry);
+}
+
+#undef var_DelListCallback
+/**
+ * Remove a callback from a list variable
+ *
+ * See var_DelCallback().
+ */
+int var_DelListCallback( vlc_object_t *p_this, const char *psz_name,
+                         vlc_list_callback_t pf_callback, void *p_data )
+{
+    callback_entry_t entry;
+    entry.i_type = vlc_list_callback;
+    entry.u.pf_list_callback = pf_callback;
+    entry.p_data = p_data;
+
+    return DelCallback(p_this, psz_name, entry);
+}
+
 /** Parse a stringified option
  * This function parse a string option and create the associated object
  * variable
@@ -1331,8 +1385,40 @@ static int TriggerCallback( vlc_object_t *p_this, variable_t *p_var,
     /* The real calls */
     for( ; i_entries-- ; )
     {
-        p_entries[i_entries].pf_callback( p_this, psz_name, oldval, p_var->val,
-                                          p_entries[i_entries].p_data );
+        if (p_entries[i_entries].i_type == vlc_value_callback)
+            p_entries[i_entries].u.pf_value_callback( p_this, psz_name, oldval, p_var->val,
+                                                      p_entries[i_entries].p_data );
+    }
+
+    vlc_mutex_lock( &p_priv->var_lock );
+    p_var->b_incallback = false;
+    vlc_cond_broadcast( &p_priv->var_wait );
+
+    return VLC_SUCCESS;
+}
+
+static int TriggerListCallback( vlc_object_t *p_this, variable_t *p_var,
+                                const char *psz_name, int i_action,
+                                vlc_value_t *val )
+{
+    assert( p_this );
+
+    int i_entries = p_var->i_entries;
+    if( i_entries == 0 )
+        return VLC_SUCCESS;
+
+    callback_entry_t *p_entries = p_var->p_entries;
+    vlc_object_internals_t *p_priv = vlc_internals( p_this );
+
+    assert( !p_var->b_incallback );
+    p_var->b_incallback = true;
+    vlc_mutex_unlock( &p_priv->var_lock );
+
+    for( ; i_entries-- ; )
+    {
+        if (p_entries[i_entries].i_type == vlc_list_callback)
+            p_entries[i_entries].u.pf_list_callback( p_this, psz_name, i_action, val,
+                                                     p_entries[i_entries].p_data );
     }
 
     vlc_mutex_lock( &p_priv->var_lock );
-- 
1.9.1




More information about the vlc-devel mailing list