]> git.sesse.net Git - vlc/commitdiff
core: add a new type of callback for list variables
authorFelix Abecassis <felix.abecassis@gmail.com>
Mon, 4 Aug 2014 10:06:29 +0000 (12:06 +0200)
committerFelix Abecassis <felix.abecassis@gmail.com>
Mon, 4 Aug 2014 10:09:36 +0000 (12:09 +0200)
This new callback is triggered when an element is added/removed from
the list, or when the list is cleared.

include/vlc_common.h
include/vlc_variables.h
src/libvlccore.sym
src/misc/variables.c
src/misc/variables.h

index 8b4b923d9e89cc218bdafe4c4d18d5893e4ea947..128177e022dada16d220568c71b81b665c80679e 100644 (file)
@@ -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 */
@@ -390,6 +390,21 @@ typedef int ( * vlc_callback_t ) ( vlc_object_t *,      /* variable's object */
                                    vlc_value_t,                 /* new value */
                                    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
  *****************************************************************************/
index 420f0b4d026725d423f32ed510276bd53ffcf207..6f48aa1760fc644eede289b7b6c9059b60a2fe78 100644 (file)
@@ -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
  *****************************************************************************/
index 1b9973e47bf64981ef4ca7adb4565582f073f9bd..bdd7b065f15b972b747e1ca7739feabf925e7ebb 100644 (file)
@@ -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
index 46d5194b9c3e0a0186759ba3964c5886d9a0c4ab..05a11d409a2987d2772bc2afbe1e5fc2bf70853c 100644 (file)
  *****************************************************************************/
 struct callback_entry_t
 {
-    vlc_callback_t pf_callback;
+    union
+    {
+        vlc_callback_t       pf_value_callback;
+        vlc_list_callback_t  pf_list_callback;
+        void *               p_callback;
+    } u;
     void *         p_data;
 };
 
@@ -136,6 +141,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 +470,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 +501,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 +522,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:
         {
@@ -805,7 +819,7 @@ int var_Get( vlc_object_t *p_this, const char *psz_name, vlc_value_t *p_val )
 }
 
 static int AddCallback( vlc_object_t *p_this, const char *psz_name,
-                        callback_entry_t entry )
+                        callback_entry_t entry, vlc_callback_type_t i_type )
 {
     variable_t *p_var;
 
@@ -820,12 +834,17 @@ 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;
     }
 
     WaitUnused( p_this, p_var );
-    callback_table_t *p_table = &p_var->value_callbacks;
+
+    callback_table_t *p_table;
+    if (i_type == vlc_value_callback)
+        p_table = &p_var->value_callbacks;
+    else
+        p_table = &p_var->list_callbacks;
     INSERT_ELEM( p_table->p_entries,
                  p_table->i_entries,
                  p_table->i_entries,
@@ -857,14 +876,14 @@ 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.u.pf_value_callback = pf_callback;
     entry.p_data = p_data;
 
-    return AddCallback(p_this, psz_name, entry);
+    return AddCallback(p_this, psz_name, entry, vlc_value_callback);
 }
 
 static int DelCallback( vlc_object_t *p_this, const char *psz_name,
-                        callback_entry_t entry )
+                        callback_entry_t entry, vlc_callback_type_t i_type )
 {
     int i_entry;
     variable_t *p_var;
@@ -887,16 +906,21 @@ static int DelCallback( vlc_object_t *p_this, const char *psz_name,
 
     WaitUnused( p_this, p_var );
 
-    callback_table_t *p_table = &p_var->value_callbacks;
+    callback_table_t *p_table;
+    if (i_type == vlc_value_callback)
+        p_table = &p_var->value_callbacks;
+    else
+        p_table = &p_var->list_callbacks;
+
     for( i_entry = p_table->i_entries ; i_entry-- ; )
     {
-        if( p_table->p_entries[i_entry].pf_callback == entry.pf_callback
+        if( p_table->p_entries[i_entry].u.p_callback == entry.u.p_callback
             && p_table->p_entries[i_entry].p_data == entry.p_data )
         {
             break;
         }
 #ifndef NDEBUG
-        else if( p_table->p_entries[i_entry].pf_callback == entry.pf_callback )
+        else if( p_table->p_entries[i_entry].u.p_callback == entry.u.p_callback )
             b_found_similar = true;
 #endif
     }
@@ -931,10 +955,10 @@ 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.u.pf_value_callback = pf_callback;
     entry.p_data = p_data;
 
-    return DelCallback(p_this, psz_name, entry);
+    return DelCallback(p_this, psz_name, entry, vlc_value_callback);
 }
 
 #undef var_TriggerCallback
@@ -972,6 +996,41 @@ 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.u.pf_list_callback = pf_callback;
+    entry.p_data = p_data;
+
+    return AddCallback(p_this, psz_name, entry, vlc_list_callback);
+}
+
+#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.u.pf_list_callback = pf_callback;
+    entry.p_data = p_data;
+
+    return DelCallback(p_this, psz_name, entry, vlc_list_callback);
+}
+
 /** Parse a stringified option
  * This function parse a string option and create the associated object
  * variable
@@ -1334,8 +1393,39 @@ 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 );
+        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 );
+
+    callback_table_t *p_table = &p_var->list_callbacks;
+    int i_entries = p_table->i_entries;
+    if( i_entries == 0 )
+        return VLC_SUCCESS;
+
+    callback_entry_t *p_entries = p_table->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-- ; )
+    {
+        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 );
index d09ba6618fbae7e512e60b3fcdb327f6cf4dfdf9..35b82030e29517aa91bec096919abca3b7232450 100644 (file)
@@ -107,6 +107,8 @@ struct variable_t
 
     /** Registered value callbacks */
     callback_table_t    value_callbacks;
+    /** Registered list callbacks */
+    callback_table_t    list_callbacks;
 };
 
 extern void var_DestroyAll( vlc_object_t * );