[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