/** * Destroy a vlc variable * * Look for the variable and destroy it if it is found. As in var_Create we * do a call to memmove() but we have performance counterparts elsewhere. * * \param p_this The object that holds the variable * \param psz_name The name of the variable */ void (var_Destroy)(vlc_object_t *p_this, const char *psz_name) { variable_t *p_var; assert( p_this ); vlc_object_internals_t *p_priv = vlc_internals( p_this ); p_var = Lookup( p_this, psz_name ); if( p_var == NULL ) { vlc_mutex_unlock( &p_priv->var_lock ); return; } WaitUnused( p_this, p_var ); if( --p_var->i_usage == 0 ) tdelete( p_var, &p_priv->var_root, varcmp ); else p_var = NULL; vlc_mutex_unlock( &p_priv->var_lock ); if( p_var != NULL ) Destroy( p_var ); }
static void AddCallback( vlc_object_t *p_this, const char *psz_name, callback_entry_t entry, vlc_callback_type_t i_type ) { variable_t *p_var; assert( p_this ); vlc_object_internals_t *p_priv = vlc_internals( p_this ); p_var = Lookup( p_this, psz_name ); if( p_var == NULL ) { vlc_mutex_unlock( &p_priv->var_lock ); msg_Err( p_this, "cannot add callback %p to nonexistent variable '%s'", entry.p_callback, psz_name ); return; } WaitUnused( p_this, p_var ); callback_table_t *p_table; if (i_type == vlc_value_callback) p_table = &p_var->value_callbacks; else p_table = &p_var->list_callbacks; TAB_APPEND(p_table->i_entries, p_table->p_entries, entry); vlc_mutex_unlock( &p_priv->var_lock ); }
/** * Perform a Get and Set on a variable * * \param p_this: The object that hold the variable * \param psz_name: the name of the variable * \param i_action: the action to perform * \param p_val: The action parameter * \return vlc error codes */ int var_GetAndSet( vlc_object_t *p_this, const char *psz_name, int i_action, vlc_value_t *p_val ) { variable_t *p_var; vlc_value_t oldval; assert( p_this ); assert( p_val ); vlc_object_internals_t *p_priv = vlc_internals( p_this ); p_var = Lookup( p_this, psz_name ); if( p_var == NULL ) { vlc_mutex_unlock( &p_priv->var_lock ); return VLC_ENOVAR; } WaitUnused( p_this, p_var ); /* Duplicated data if needed */ //p_var->ops->pf_dup( &val ); /* Backup needed stuff */ oldval = p_var->val; /* depending of the action requiered */ switch( i_action ) { case VLC_VAR_BOOL_TOGGLE: assert( ( p_var->i_type & VLC_VAR_BOOL ) == VLC_VAR_BOOL ); p_var->val.b_bool = !p_var->val.b_bool; break; case VLC_VAR_INTEGER_ADD: assert( ( p_var->i_type & VLC_VAR_INTEGER ) == VLC_VAR_INTEGER ); p_var->val.i_int += p_val->i_int; break; case VLC_VAR_INTEGER_OR: assert( ( p_var->i_type & VLC_VAR_INTEGER ) == VLC_VAR_INTEGER ); p_var->val.i_int |= p_val->i_int; break; case VLC_VAR_INTEGER_NAND: assert( ( p_var->i_type & VLC_VAR_INTEGER ) == VLC_VAR_INTEGER ); p_var->val.i_int &= ~p_val->i_int; break; default: vlc_mutex_unlock( &p_priv->var_lock ); return VLC_EGENERIC; } /* Check boundaries */ CheckValue( p_var, &p_var->val ); *p_val = p_var->val; /* Deal with callbacks.*/ TriggerCallback( p_this, p_var, psz_name, oldval ); vlc_mutex_unlock( &p_priv->var_lock ); return VLC_SUCCESS; }
/** * Trigger callback on a variable * * \param p_this The object that hold the variable * \param psz_name The name of the variable */ int var_TriggerCallback( vlc_object_t *p_this, const char *psz_name ) { int i_ret; variable_t *p_var; assert( p_this ); vlc_object_internals_t *p_priv = vlc_internals( p_this ); vlc_mutex_lock( &p_priv->var_lock ); p_var = Lookup( p_this, psz_name ); if( p_var == NULL ) { vlc_mutex_unlock( &p_priv->var_lock ); return VLC_ENOVAR; } WaitUnused( p_this, p_var ); /* Deal with callbacks. Tell we're in a callback, release the lock, * call stored functions, retake the lock. */ i_ret = TriggerCallback( p_this, p_var, psz_name, p_var->val ); vlc_mutex_unlock( &p_priv->var_lock ); return i_ret; }
/** * Register a callback in a variable * * We store a function pointer that will be called upon variable * modification. * * \param p_this The object that holds the variable * \param psz_name The name of the variable * \param pf_callback The function pointer * \param p_data A generic pointer that will be passed as the last * argument to the callback function. * * \warning The callback function is run in the thread that calls var_Set on * the variable. Use proper locking. This thread may not have much * time to spare, so keep callback functions short. */ int var_AddCallback( vlc_object_t *p_this, const char *psz_name, vlc_callback_t pf_callback, void *p_data ) { variable_t *p_var; callback_entry_t entry; assert( p_this ); vlc_object_internals_t *p_priv = vlc_internals( p_this ); entry.pf_callback = pf_callback; entry.p_data = p_data; vlc_mutex_lock( &p_priv->var_lock ); p_var = Lookup( p_this, psz_name ); if( p_var == NULL ) { vlc_mutex_unlock( &p_priv->var_lock ); msg_Err( p_this, "cannot add callback %p to nonexistent " "variable '%s'", pf_callback, psz_name ); return VLC_ENOVAR; } WaitUnused( p_this, p_var ); INSERT_ELEM( p_var->p_entries, p_var->i_entries, p_var->i_entries, entry ); vlc_mutex_unlock( &p_priv->var_lock ); return VLC_SUCCESS; }
static void DelCallback( vlc_object_t *p_this, const char *psz_name, callback_entry_t entry, vlc_callback_type_t i_type ) { int i_entry; variable_t *p_var; #ifndef NDEBUG bool b_found_similar = false; #endif assert( p_this ); vlc_object_internals_t *p_priv = vlc_internals( p_this ); p_var = Lookup( p_this, psz_name ); if( p_var == NULL ) { vlc_mutex_unlock( &p_priv->var_lock ); msg_Err( p_this, "cannot delete callback %p from nonexistent " "variable '%s'", entry.p_callback, psz_name ); return; } WaitUnused( p_this, p_var ); 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].p_callback == entry.p_callback && p_table->p_entries[i_entry].p_data == entry.p_data ) { break; } #ifndef NDEBUG else if( p_table->p_entries[i_entry].p_callback == entry.p_callback ) b_found_similar = true; #endif } if( i_entry < 0 ) { #ifndef NDEBUG if( b_found_similar ) fprintf( stderr, "Calling var_DelCallback for '%s' with the same " "function but not the same data.", psz_name ); vlc_assert_unreachable(); #endif vlc_mutex_unlock( &p_priv->var_lock ); return; } TAB_ERASE(p_table->i_entries, p_table->p_entries, i_entry); vlc_mutex_unlock( &p_priv->var_lock ); }
/** * Remove a callback from a variable * * pf_callback and p_data have to be given again, because different objects * might have registered the same callback function. */ int var_DelCallback( vlc_object_t *p_this, const char *psz_name, vlc_callback_t pf_callback, void *p_data ) { int i_entry; variable_t *p_var; #ifndef NDEBUG bool b_found_similar = false; #endif assert( p_this ); vlc_object_internals_t *p_priv = vlc_internals( p_this ); vlc_mutex_lock( &p_priv->var_lock ); p_var = Lookup( p_this, psz_name ); if( p_var == NULL ) { vlc_mutex_unlock( &p_priv->var_lock ); return VLC_ENOVAR; } WaitUnused( p_this, p_var ); for( i_entry = p_var->i_entries ; i_entry-- ; ) { if( p_var->p_entries[i_entry].pf_callback == pf_callback && p_var->p_entries[i_entry].p_data == p_data ) { break; } #ifndef NDEBUG else if( p_var->p_entries[i_entry].pf_callback == pf_callback ) b_found_similar = true; #endif } if( i_entry < 0 ) { #ifndef NDEBUG if( b_found_similar ) fprintf( stderr, "Calling var_DelCallback for '%s' with the same " "function but not the same data.", psz_name ); assert( 0 ); #endif vlc_mutex_unlock( &p_priv->var_lock ); return VLC_EGENERIC; } REMOVE_ELEM( p_var->p_entries, p_var->i_entries, i_entry ); vlc_mutex_unlock( &p_priv->var_lock ); return VLC_SUCCESS; }
int var_SetChecked( vlc_object_t *p_this, const char *psz_name, int expected_type, vlc_value_t val ) { int i_ret = VLC_SUCCESS; variable_t *p_var; vlc_value_t oldval; assert( p_this ); vlc_object_internals_t *p_priv = vlc_internals( p_this ); vlc_mutex_lock( &p_priv->var_lock ); p_var = Lookup( p_this, psz_name ); if( p_var == NULL ) { vlc_mutex_unlock( &p_priv->var_lock ); return VLC_ENOVAR; } assert( expected_type == 0 || (p_var->i_type & VLC_VAR_CLASS) == expected_type ); #ifndef NDEBUG /* Alert if the type is VLC_VAR_VOID */ if( ( p_var->i_type & VLC_VAR_TYPE ) == VLC_VAR_VOID ) msg_Warn( p_this, "Calling var_Set on the void variable '%s' (0x%04x)", psz_name, p_var->i_type ); #endif WaitUnused( p_this, p_var ); /* Duplicate data if needed */ p_var->ops->pf_dup( &val ); /* Backup needed stuff */ oldval = p_var->val; /* Check boundaries and list */ CheckValue( p_var, &val ); /* Set the variable */ p_var->val = val; /* Deal with callbacks */ i_ret = TriggerCallback( p_this, p_var, psz_name, oldval ); /* Free data if needed */ p_var->ops->pf_free( &oldval ); vlc_mutex_unlock( &p_priv->var_lock ); return i_ret; }
/** * Trigger callback on a variable * * \param p_this The object that hold the variable * \param psz_name The name of the variable */ void var_TriggerCallback( vlc_object_t *p_this, const char *psz_name ) { vlc_object_internals_t *p_priv = vlc_internals( p_this ); variable_t *p_var = Lookup( p_this, psz_name ); if( p_var != NULL ) { WaitUnused( p_this, p_var ); /* Deal with callbacks. Tell we're in a callback, release the lock, * call stored functions, retake the lock. */ TriggerCallback( p_this, p_var, psz_name, p_var->val ); } vlc_mutex_unlock( &p_priv->var_lock ); }
int var_SetChecked( vlc_object_t *p_this, const char *psz_name, int expected_type, vlc_value_t val ) { variable_t *p_var; vlc_value_t oldval; assert( p_this ); vlc_object_internals_t *p_priv = vlc_internals( p_this ); p_var = Lookup( p_this, psz_name ); if( p_var == NULL ) { vlc_mutex_unlock( &p_priv->var_lock ); return VLC_ENOVAR; } assert( expected_type == 0 || (p_var->i_type & VLC_VAR_CLASS) == expected_type ); assert ((p_var->i_type & VLC_VAR_CLASS) != VLC_VAR_VOID); WaitUnused( p_this, p_var ); /* Duplicate data if needed */ p_var->ops->pf_dup( &val ); /* Backup needed stuff */ oldval = p_var->val; /* Check boundaries and list */ CheckValue( p_var, &val ); /* Set the variable */ p_var->val = val; /* Deal with callbacks */ TriggerCallback( p_this, p_var, psz_name, oldval ); /* Free data if needed */ p_var->ops->pf_free( &oldval ); vlc_mutex_unlock( &p_priv->var_lock ); return VLC_SUCCESS; }
/** * Register a callback in a variable * * We store a function pointer that will be called upon variable * modification. * * \param p_this The object that holds the variable * \param psz_name The name of the variable * \param pf_callback The function pointer * \param p_data A generic pointer that will be passed as the last * argument to the callback function. * * \warning The callback function is run in the thread that calls var_Set on * the variable. Use proper locking. This thread may not have much * time to spare, so keep callback functions short. */ int var_AddCallback( vlc_object_t *p_this, const char *psz_name, vlc_callback_t pf_callback, void *p_data ) { variable_t *p_var; callback_entry_t entry; assert( p_this ); vlc_object_internals_t *p_priv = vlc_internals( p_this ); entry.pf_callback = pf_callback; entry.p_data = p_data; vlc_mutex_lock( &p_priv->var_lock ); p_var = Lookup( p_this, psz_name ); if( p_var == NULL ) { #ifndef NDEBUG msg_Warn( p_this, "Failed to add a callback to the non-existing " "variable '%s'", psz_name ); #endif vlc_mutex_unlock( &p_priv->var_lock ); return VLC_ENOVAR; } WaitUnused( p_this, p_var ); INSERT_ELEM( p_var->p_entries, p_var->i_entries, p_var->i_entries, entry ); vlc_mutex_unlock( &p_priv->var_lock ); return VLC_SUCCESS; }