[vlc-devel] [PATCH 3/3] core: add a new type of callback for list variables
Felix Abecassis
felix.abecassis at gmail.com
Fri Jul 25 16:38:59 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 | 118 ++++++++++++++++++++++++++++++++++++++++++------
src/misc/variables.h | 2 +
5 files changed, 130 insertions(+), 15 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 d40469f..70653c3 100644
--- a/src/misc/variables.c
+++ b/src/misc/variables.c
@@ -49,7 +49,12 @@
*****************************************************************************/
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_var->p_entries[i_entry].pf_callback == pf_callback )
+ else if( 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 );
diff --git a/src/misc/variables.h b/src/misc/variables.h
index d09ba66..35b8203 100644
--- a/src/misc/variables.h
+++ b/src/misc/variables.h
@@ -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 * );
--
1.9.1
More information about the vlc-devel
mailing list