[vlc-devel] [PATCH 2/3] core: add a new type of callback for list variables
Rémi Denis-Courmont
remi at remlab.net
Wed Jul 23 18:02:30 CEST 2014
Le mercredi 23 juillet 2014, 14:43:08 Felix Abecassis a écrit :
> 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;
I'd rather add a new table. Is there any particular reason for multiplexing
the different callback types?
> + 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 );
--
Rémi Denis-Courmont
http://www.remlab.net/
More information about the vlc-devel
mailing list