/** * Perform an action on a variable * * \param p_this The object that holds the variable * \param psz_name The name of the variable * \param i_action The action to perform. Must be one of \ref var_action * \param p_val First action parameter * \param p_val2 Second action parameter */ int var_Change( vlc_object_t *p_this, const char *psz_name, int i_action, vlc_value_t *p_val, vlc_value_t *p_val2 ) { int ret = VLC_SUCCESS; variable_t *p_var; vlc_value_t oldval; vlc_value_t newval; 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; } switch( i_action ) { case VLC_VAR_GETMIN: *p_val = p_var->min; break; case VLC_VAR_GETMAX: *p_val = p_var->max; break; case VLC_VAR_SETMINMAX: assert(p_var->ops->pf_free == FreeDummy); p_var->min = *p_val; p_var->max = *p_val2; break; case VLC_VAR_SETSTEP: assert(p_var->ops->pf_free == FreeDummy); p_var->step = *p_val; CheckValue( p_var, &p_var->val ); break; case VLC_VAR_GETSTEP: switch (p_var->i_type & VLC_VAR_TYPE) { case VLC_VAR_INTEGER: if (p_var->step.i_int == 0) ret = VLC_EGENERIC; break; case VLC_VAR_FLOAT: if (p_var->step.f_float == 0.f) ret = VLC_EGENERIC; break; default: ret = VLC_EGENERIC; } if (ret == VLC_SUCCESS) *p_val = p_var->step; break; case VLC_VAR_ADDCHOICE: { int i = p_var->choices.i_count; TAB_APPEND(p_var->choices.i_count, p_var->choices.p_values, *p_val); assert(i == p_var->choices_text.i_count); TAB_APPEND(p_var->choices_text.i_count, p_var->choices_text.p_values, *p_val); p_var->ops->pf_dup( &p_var->choices.p_values[i] ); p_var->choices_text.p_values[i].psz_string = ( p_val2 && p_val2->psz_string ) ? strdup( p_val2->psz_string ) : NULL; TriggerListCallback(p_this, p_var, psz_name, VLC_VAR_ADDCHOICE, p_val); break; } case VLC_VAR_DELCHOICE: { int i; for( i = 0 ; i < p_var->choices.i_count ; i++ ) if( p_var->ops->pf_cmp( p_var->choices.p_values[i], *p_val ) == 0 ) break; if( i == p_var->choices.i_count ) { /* Not found */ vlc_mutex_unlock( &p_priv->var_lock ); return VLC_EGENERIC; } p_var->ops->pf_free( &p_var->choices.p_values[i] ); free( p_var->choices_text.p_values[i].psz_string ); TAB_ERASE(p_var->choices.i_count, p_var->choices.p_values, i); TAB_ERASE(p_var->choices_text.i_count, p_var->choices_text.p_values, i); TriggerListCallback(p_this, p_var, psz_name, VLC_VAR_DELCHOICE, p_val); break; } case VLC_VAR_CHOICESCOUNT: p_val->i_int = p_var->choices.i_count; break; case VLC_VAR_CLEARCHOICES: for( int i = 0 ; i < p_var->choices.i_count ; i++ ) p_var->ops->pf_free( &p_var->choices.p_values[i] ); for( int i = 0 ; i < p_var->choices_text.i_count ; i++ ) free( p_var->choices_text.p_values[i].psz_string ); if( p_var->choices.i_count ) free( p_var->choices.p_values ); if( p_var->choices_text.i_count ) free( p_var->choices_text.p_values ); p_var->choices.i_count = 0; p_var->choices.p_values = NULL; p_var->choices_text.i_count = 0; p_var->choices_text.p_values = NULL; TriggerListCallback(p_this, p_var, psz_name, VLC_VAR_CLEARCHOICES, NULL); break; case VLC_VAR_SETVALUE: /* Duplicate data if needed */ newval = *p_val; p_var->ops->pf_dup( &newval ); /* Backup needed stuff */ oldval = p_var->val; /* Check boundaries and list */ CheckValue( p_var, &newval ); /* Set the variable */ p_var->val = newval; /* Free data if needed */ p_var->ops->pf_free( &oldval ); break; case VLC_VAR_GETCHOICES: p_val->p_list = xmalloc( sizeof(vlc_list_t) ); p_val->p_list->p_values = xmalloc( p_var->choices.i_count * sizeof(vlc_value_t) ); p_val->p_list->i_type = p_var->i_type; p_val->p_list->i_count = p_var->choices.i_count; if( p_val2 ) { p_val2->p_list = xmalloc( sizeof(vlc_list_t) ); p_val2->p_list->p_values = xmalloc( p_var->choices.i_count * sizeof(vlc_value_t) ); p_val2->p_list->i_type = VLC_VAR_STRING; p_val2->p_list->i_count = p_var->choices.i_count; } for( int i = 0 ; i < p_var->choices.i_count ; i++ ) { p_val->p_list->p_values[i] = p_var->choices.p_values[i]; p_var->ops->pf_dup( &p_val->p_list->p_values[i] ); if( p_val2 ) { p_val2->p_list->p_values[i].psz_string = p_var->choices_text.p_values[i].psz_string ? strdup(p_var->choices_text.p_values[i].psz_string) : NULL; } } break; case VLC_VAR_SETTEXT: free( p_var->psz_text ); if( p_val && p_val->psz_string ) p_var->psz_text = strdup( p_val->psz_string ); else p_var->psz_text = NULL; break; case VLC_VAR_GETTEXT: p_val->psz_string = p_var->psz_text ? strdup( p_var->psz_text ) : NULL; break; default: break; } vlc_mutex_unlock( &p_priv->var_lock ); return ret; }
/** * Perform an action on a variable * * \param p_this The object that holds the variable * \param psz_name The name of the variable * \param i_action The action to perform. Must be one of \ref var_action * \param p_val First action parameter * \param p_val2 Second action parameter */ int var_Change( vlc_object_t *p_this, const char *psz_name, int i_action, vlc_value_t *p_val, vlc_value_t *p_val2 ) { int ret = VLC_SUCCESS; variable_t *p_var; vlc_value_t oldval; vlc_value_t newval; 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; } switch( i_action ) { case VLC_VAR_SETMIN: if( p_var->i_type & VLC_VAR_HASMIN ) { p_var->ops->pf_free( &p_var->min ); } p_var->i_type |= VLC_VAR_HASMIN; p_var->min = *p_val; p_var->ops->pf_dup( &p_var->min ); CheckValue( p_var, &p_var->val ); break; case VLC_VAR_GETMIN: if( p_var->i_type & VLC_VAR_HASMIN ) *p_val = p_var->min; else ret = VLC_EGENERIC; break; case VLC_VAR_SETMAX: if( p_var->i_type & VLC_VAR_HASMAX ) { p_var->ops->pf_free( &p_var->max ); } p_var->i_type |= VLC_VAR_HASMAX; p_var->max = *p_val; p_var->ops->pf_dup( &p_var->max ); CheckValue( p_var, &p_var->val ); break; case VLC_VAR_GETMAX: if( p_var->i_type & VLC_VAR_HASMAX ) *p_val = p_var->max; else ret = VLC_EGENERIC; break; case VLC_VAR_SETSTEP: if( p_var->i_type & VLC_VAR_HASSTEP ) { p_var->ops->pf_free( &p_var->step ); } p_var->i_type |= VLC_VAR_HASSTEP; p_var->step = *p_val; p_var->ops->pf_dup( &p_var->step ); CheckValue( p_var, &p_var->val ); break; case VLC_VAR_GETSTEP: if( p_var->i_type & VLC_VAR_HASSTEP ) *p_val = p_var->step; else ret = VLC_EGENERIC; break; case VLC_VAR_ADDCHOICE: { int i = p_var->choices.i_count; INSERT_ELEM( p_var->choices.p_values, p_var->choices.i_count, i, *p_val ); INSERT_ELEM( p_var->choices_text.p_values, p_var->choices_text.i_count, i, *p_val ); p_var->ops->pf_dup( &p_var->choices.p_values[i] ); p_var->choices_text.p_values[i].psz_string = ( p_val2 && p_val2->psz_string ) ? 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: { int i; for( i = 0 ; i < p_var->choices.i_count ; i++ ) if( p_var->ops->pf_cmp( p_var->choices.p_values[i], *p_val ) == 0 ) break; if( i == p_var->choices.i_count ) { /* Not found */ vlc_mutex_unlock( &p_priv->var_lock ); return VLC_EGENERIC; } if( p_var->i_default > i ) p_var->i_default--; else if( p_var->i_default == i ) p_var->i_default = -1; p_var->ops->pf_free( &p_var->choices.p_values[i] ); free( p_var->choices_text.p_values[i].psz_string ); REMOVE_ELEM( p_var->choices.p_values, p_var->choices.i_count, i ); REMOVE_ELEM( p_var->choices_text.p_values, 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: p_val->i_int = p_var->choices.i_count; break; case VLC_VAR_CLEARCHOICES: for( int i = 0 ; i < p_var->choices.i_count ; i++ ) p_var->ops->pf_free( &p_var->choices.p_values[i] ); for( int i = 0 ; i < p_var->choices_text.i_count ; i++ ) free( p_var->choices_text.p_values[i].psz_string ); if( p_var->choices.i_count ) free( p_var->choices.p_values ); if( p_var->choices_text.i_count ) free( p_var->choices_text.p_values ); p_var->choices.i_count = 0; p_var->choices.p_values = NULL; 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: { int i; /* FIXME: the list is sorted, dude. Use something cleverer. */ for( i = 0 ; i < p_var->choices.i_count ; i++ ) if( p_var->ops->pf_cmp( p_var->choices.p_values[i], *p_val ) == 0 ) break; if( i == p_var->choices.i_count ) /* Not found */ break; p_var->i_default = i; CheckValue( p_var, &p_var->val ); break; } case VLC_VAR_SETVALUE: /* Duplicate data if needed */ newval = *p_val; p_var->ops->pf_dup( &newval ); /* Backup needed stuff */ oldval = p_var->val; /* Check boundaries and list */ CheckValue( p_var, &newval ); /* Set the variable */ p_var->val = newval; /* Free data if needed */ p_var->ops->pf_free( &oldval ); break; case VLC_VAR_GETCHOICES: p_val->p_list = xmalloc( sizeof(vlc_list_t) ); p_val->p_list->p_values = xmalloc( p_var->choices.i_count * sizeof(vlc_value_t) ); p_val->p_list->i_type = p_var->i_type; p_val->p_list->i_count = p_var->choices.i_count; if( p_val2 ) { p_val2->p_list = xmalloc( sizeof(vlc_list_t) ); p_val2->p_list->p_values = xmalloc( p_var->choices.i_count * sizeof(vlc_value_t) ); p_val2->p_list->i_type = VLC_VAR_STRING; p_val2->p_list->i_count = p_var->choices.i_count; } for( int i = 0 ; i < p_var->choices.i_count ; i++ ) { p_val->p_list->p_values[i] = p_var->choices.p_values[i]; p_var->ops->pf_dup( &p_val->p_list->p_values[i] ); if( p_val2 ) { p_val2->p_list->p_values[i].psz_string = p_var->choices_text.p_values[i].psz_string ? strdup(p_var->choices_text.p_values[i].psz_string) : NULL; } } break; case VLC_VAR_SETTEXT: free( p_var->psz_text ); if( p_val && p_val->psz_string ) p_var->psz_text = strdup( p_val->psz_string ); else p_var->psz_text = NULL; break; case VLC_VAR_GETTEXT: p_val->psz_string = p_var->psz_text ? strdup( p_var->psz_text ) : NULL; break; default: break; } vlc_mutex_unlock( &p_priv->var_lock ); return ret; }