Commit d53bf1b3 authored by Rémi Denis-Courmont's avatar Rémi Denis-Courmont

Repack module_config_t

Also do not save garbage, especially pointers, in the plugin cache.
parent acc457d1
......@@ -55,32 +55,39 @@ typedef int (*vlc_string_list_cb)(vlc_object_t *, const char *,
struct module_config_t
{
union
{
struct
{
uint8_t i_type; /* Configuration type */
char i_short; /* Optional short option name */
unsigned b_advanced:1; /* Advanced option */
unsigned b_internal:1; /* Hidden from prefs and help */
unsigned b_unsaveable:1; /* Not stored in configuration */
unsigned b_safe:1; /* Safe in web plugins and playlists */
unsigned b_removed:1; /* Deprecated */
};
uint32_t flags;
};
char *psz_type; /* Configuration subtype */
char *psz_name; /* Option name */
char *psz_text; /* Short comment on the configuration option */
char *psz_longtext; /* Long comment on the configuration option */
module_value_t value; /* Option value */
module_value_t orig;
module_value_t min;
module_value_t max;
/* Values list */
char ** ppsz_list; /* List of possible values for the option */
int *pi_list; /* Idem for integers */
char **ppsz_list_text; /* Friendly names for list values */
int i_list; /* Options list size */
vlc_string_list_cb pf_update_list;
uint8_t i_type; /* Configuration type */
char i_short; /* Optional short option name */
/* Misc */
unsigned b_advanced:1; /* Flag to indicate an advanced option */
unsigned b_internal:1; /* Flag to indicate option is not to be shown */
unsigned b_unsaveable:1; /* Config should not be saved */
unsigned b_safe:1; /* Safe to use in web plugins and playlists */
/* Deprecated */
bool b_removed;
uint16_t list_count; /* Options list size */
union
{
char **psz; /* List of possible values for the option */
int *i;
vlc_string_list_cb psz_cb;
} list;
char **list_text; /* Friendly names for list values */
};
/*****************************************************************************
......
......@@ -93,10 +93,10 @@ ConfigControl *ConfigControl::createControl( vlc_object_t *p_this,
p_control = new ModuleListConfigControl( p_this, p_item, parent, true );
break;
case CONFIG_ITEM_STRING:
if( !p_item->i_list )
p_control = new StringConfigControl( p_this, p_item, parent, false );
else
if( p_item->list_count )
p_control = new StringListConfigControl( p_this, p_item, parent );
else
p_control = new StringConfigControl( p_this, p_item, parent, false );
break;
case CONFIG_ITEM_PASSWORD:
p_control = new StringConfigControl( p_this, p_item, parent, true );
......@@ -105,7 +105,7 @@ ConfigControl *ConfigControl::createControl( vlc_object_t *p_this,
p_control = new ColorConfigControl( p_this, p_item, parent );
break;
case CONFIG_ITEM_INTEGER:
if( p_item->i_list )
if( p_item->list_count )
p_control = new IntegerListConfigControl( p_this, p_item, parent, false );
else if( p_item->min.i || p_item->max.i )
p_control = new IntegerRangeConfigControl( p_this, p_item, parent );
......
......@@ -81,6 +81,7 @@ audio_output_t *aout_New( vlc_object_t * p_parent )
* Persistent audio output variables
*/
vlc_value_t val, text;
module_config_t *cfg;
char *str;
var_Create (aout, "volume", VLC_VAR_FLOAT);
......@@ -142,18 +143,14 @@ audio_output_t *aout_New( vlc_object_t * p_parent )
val.psz_string = (char*)"";
text.psz_string = _("Disable");
var_Change (aout, "equalizer", VLC_VAR_ADDCHOICE, &val, &text);
cfg = config_FindConfig (VLC_OBJECT(aout), "equalizer-preset");
if (likely(cfg != NULL))
for (unsigned i = 0; i < cfg->list_count; i++)
{
module_config_t *cfg = config_FindConfig (VLC_OBJECT(aout),
"equalizer-preset");
if (cfg != NULL)
for (int i = 0; i < cfg->i_list; i++)
{
val.psz_string = (char *)cfg->ppsz_list[i];
text.psz_string = (char *)cfg->ppsz_list_text[i];
val.psz_string = cfg->list.psz[i];
text.psz_string = vlc_gettext(cfg->list_text[i]);
var_Change (aout, "equalizer", VLC_VAR_ADDCHOICE, &val, &text);
}
}
var_Create (aout, "audio-filter", VLC_VAR_STRING | VLC_VAR_DOINHERIT);
text.psz_string = _("Audio filters");
......@@ -170,19 +167,15 @@ audio_output_t *aout_New( vlc_object_t * p_parent )
VLC_VAR_STRING | VLC_VAR_DOINHERIT );
text.psz_string = _("Replay gain");
var_Change (aout, "audio-replay-gain-mode", VLC_VAR_SETTEXT, &text, NULL);
cfg = config_FindConfig (VLC_OBJECT(aout), "audio-replay-gain-mode");
if (likely(cfg != NULL))
for (unsigned i = 0; i < cfg->list_count; i++)
{
module_config_t *cfg = config_FindConfig (VLC_OBJECT(aout),
"audio-replay-gain-mode");
if( cfg != NULL )
for (int i = 0; i < cfg->i_list; i++)
{
val.psz_string = (char *)cfg->ppsz_list[i];
text.psz_string = (char *)cfg->ppsz_list_text[i];
val.psz_string = cfg->list.psz[i];
text.psz_string = vlc_gettext(cfg->list_text[i]);
var_Change (aout, "audio-replay-gain-mode", VLC_VAR_ADDCHOICE,
&val, &text);
}
}
return aout;
}
......
......@@ -352,7 +352,7 @@ ssize_t config_GetIntChoices (vlc_object_t *obj, const char *name,
return -1;
}
size_t count = cfg->i_list;
size_t count = cfg->list_count;
if (count == 0)
return 0;
......@@ -363,8 +363,9 @@ ssize_t config_GetIntChoices (vlc_object_t *obj, const char *name,
for (size_t i = 0; i < count; i++)
{
vals[i] = cfg->pi_list[i];
txts[i] = strdup (cfg->ppsz_list_text[i]);
vals[i] = cfg->list.i[i];
/* FIXME: use module_gettext() instead */
txts[i] = strdup (vlc_gettext (cfg->list_text[i]));
if (unlikely(txts[i] == NULL))
abort ();
}
......@@ -397,12 +398,13 @@ ssize_t config_GetPszChoices (vlc_object_t *obj, const char *name,
return -1;
}
if (cfg->pf_update_list != NULL)
return cfg->pf_update_list (obj, name, values, texts);
size_t count = cfg->i_list;
size_t count = cfg->list_count;
if (count == 0)
{
if (cfg->list.psz_cb == NULL)
return 0;
return cfg->list.psz_cb(obj, name, values, texts);
}
char **vals = malloc (sizeof (*vals) * count);
char **txts = malloc (sizeof (*txts) * count);
......@@ -411,8 +413,9 @@ ssize_t config_GetPszChoices (vlc_object_t *obj, const char *name,
for (size_t i = 0; i < count; i++)
{
vals[i] = strdup (cfg->ppsz_list[i]);
txts[i] = strdup (cfg->ppsz_list_text[i]);
vals[i] = strdup (cfg->list.psz[i]);
/* FIXME: use module_gettext() instead */
txts[i] = strdup (vlc_gettext(cfg->list_text[i]));
if (unlikely(vals[i] == NULL || txts[i] == NULL))
abort ();
}
......@@ -535,17 +538,19 @@ void config_Free (module_config_t *config, size_t confsize)
{
free (p_item->value.psz);
free (p_item->orig.psz);
if (p_item->list_count)
{
for (size_t i = 0; i < p_item->list_count; i++)
free (p_item->list.psz[i]);
free (p_item->list.psz);
}
}
else
free (p_item->list.i);
if( p_item->ppsz_list )
for (int i = 0; i < p_item->i_list; i++)
free( p_item->ppsz_list[i] );
if( p_item->ppsz_list_text )
for (int i = 0; i < p_item->i_list; i++)
free( p_item->ppsz_list_text[i] );
free( p_item->ppsz_list );
free( p_item->ppsz_list_text );
free( p_item->pi_list );
for (size_t i = 0; i < p_item->list_count; i++)
free (p_item->list_text[i]);
free (p_item->list_text);
}
free (config);
......
......@@ -448,15 +448,15 @@ static void Usage (vlc_object_t *p_this, char const *psz_search)
psz_type = _("string");
psz_ket = ">";
if( p_item->ppsz_list )
if( p_item->list_count )
{
psz_bra = OPTION_VALUE_SEP "{";
psz_type = psz_buffer;
psz_buffer[0] = '\0';
for( i = 0; i < p_item->i_list; i++ )
for( i = 0; i < p_item->list_count; i++ )
{
if( i ) strcat( psz_buffer, "," );
strcat( psz_buffer, p_item->ppsz_list[i] );
strcat( psz_buffer, p_item->list.psz[i] );
}
psz_ket = "}";
}
......@@ -476,17 +476,17 @@ static void Usage (vlc_object_t *p_this, char const *psz_search)
psz_type = psz_buffer;
}
if( p_item->i_list )
if( p_item->list_count )
{
psz_bra = OPTION_VALUE_SEP "{";
psz_type = psz_buffer;
psz_buffer[0] = '\0';
for( i = 0; i < p_item->i_list; i++ )
for( i = 0; i < p_item->list_count; i++ )
{
if( i ) strcat( psz_buffer, ", " );
sprintf( psz_buffer + strlen(psz_buffer), "%i (%s)",
p_item->pi_list[i],
module_gettext( p_parser, p_item->ppsz_list_text[i] ) );
p_item->list.i[i],
module_gettext( p_parser, p_item->list_text[i] ) );
}
psz_ket = "}";
}
......
......@@ -489,7 +489,8 @@ static int AllocatePluginFile (module_bank_t *bank, const char *abspath,
/* For now we force loading if the module's config contains callbacks.
* Could be optimized by adding an API call.*/
for (size_t n = module->confsize, i = 0; i < n; i++)
if (module->p_config[i].pf_update_list != NULL)
if (module->p_config[i].list_count == 0
&& module->p_config[i].list.psz_cb != NULL)
{
/* !unloadable not allowed for plugins with callbacks */
vlc_module_destroy (module);
......
......@@ -55,11 +55,9 @@
* Local prototypes
*****************************************************************************/
#ifdef HAVE_DYNAMIC_PLUGINS
static int CacheLoadConfig ( module_t *, FILE * );
/* Sub-version number
* (only used to avoid breakage in dev version when cache structure changes) */
#define CACHE_SUBVERSION_NUM 19
#define CACHE_SUBVERSION_NUM 20
/* Cache filename */
#define CACHE_NAME "plugins.dat"
......@@ -80,6 +78,118 @@ void CacheDelete( vlc_object_t *obj, const char *dir )
free( path );
}
#define LOAD_IMMEDIATE(a) \
if (fread (&(a), sizeof (char), sizeof (a), file) != sizeof (a)) \
goto error
static int CacheLoadString (char **p, FILE *file)
{
char *psz = NULL;
uint16_t size;
LOAD_IMMEDIATE (size);
if (size > 16384)
{
error:
return -1;
}
if (size > 0)
{
psz = malloc (size);
if (unlikely(psz == NULL))
goto error;
if (fread (psz, 1, size, file) != size)
{
free (psz);
goto error;
}
psz[size - 1] = '\0';
}
*p = psz;
return 0;
}
#define LOAD_STRING(a) \
if (CacheLoadString (&(a), file)) goto error
static int CacheLoadConfig (module_config_t *cfg, FILE *file)
{
LOAD_IMMEDIATE (cfg->flags);
LOAD_STRING (cfg->psz_type);
LOAD_STRING (cfg->psz_name);
LOAD_STRING (cfg->psz_text);
LOAD_STRING (cfg->psz_longtext);
LOAD_IMMEDIATE (cfg->list_count);
if (IsConfigStringType (cfg->i_type))
{
LOAD_STRING (cfg->orig.psz);
if (cfg->orig.psz != NULL)
cfg->value.psz = strdup (cfg->orig.psz);
else
cfg->value.psz = NULL;
if (cfg->list_count)
cfg->list.psz = xmalloc (cfg->list_count * sizeof (char *));
else
cfg->list.psz_cb = NULL;
for (unsigned i = 0; i < cfg->list_count; i++)
LOAD_STRING (cfg->list.psz[i]);
}
else
{
LOAD_IMMEDIATE (cfg->orig);
LOAD_IMMEDIATE (cfg->min);
LOAD_IMMEDIATE (cfg->max);
cfg->value = cfg->orig;
cfg->list.i = xmalloc (cfg->list_count * sizeof (int));
for (unsigned i = 0; i < cfg->list_count; i++)
LOAD_IMMEDIATE (cfg->list.i[i]);
}
cfg->list_text = xmalloc (cfg->list_count * sizeof (char *));
for (unsigned i = 0; i < cfg->list_count; i++)
LOAD_STRING (cfg->list_text[i]);
return 0;
error:
return -1; /* FIXME: leaks */
}
static int CacheLoadModuleConfig (module_t *module, FILE *file)
{
uint16_t lines;
/* Calculate the structure length */
LOAD_IMMEDIATE (module->i_config_items);
LOAD_IMMEDIATE (module->i_bool_items);
LOAD_IMMEDIATE (lines);
/* Allocate memory */
if (lines)
{
module->p_config = malloc (lines * sizeof (module_config_t));
if (unlikely(module->p_config == NULL))
{
module->confsize = 0;
return -1;
}
}
else
module->p_config = NULL;
module->confsize = lines;
/* Do the duplication job */
for (size_t i = 0; i < lines; i++)
if (CacheLoadConfig (module->p_config + i, file))
return -1;
return 0;
error:
return -1; /* FIXME: leaks */
}
/**
* Loads a plugins cache file.
*
......@@ -171,32 +281,9 @@ size_t CacheLoad( vlc_object_t *p_this, const char *dir, module_cache_t **r )
module_cache_t *cache = NULL;
#define LOAD_IMMEDIATE(a) \
if( fread( (void *)&a, sizeof(char), sizeof(a), file ) != sizeof(a) ) goto error
#define LOAD_STRING(a) \
{ \
a = NULL; \
if( ( fread( &i_size, sizeof(i_size), 1, file ) != 1 ) \
|| ( i_size > 16384 ) ) \
goto error; \
if( i_size ) { \
char *psz = xmalloc( i_size ); \
if( fread( psz, i_size, 1, file ) != 1 ) { \
free( psz ); \
goto error; \
} \
if( psz[i_size-1] ) { \
free( psz ); \
goto error; \
} \
a = psz; \
} \
}
for (size_t count = 0; count < i_cache;)
{
module_t *module;
uint16_t i_size;
int i_submodules;
module = vlc_module_create (NULL);
......@@ -222,7 +309,7 @@ size_t CacheLoad( vlc_object_t *p_this, const char *dir, module_cache_t **r )
LOAD_IMMEDIATE(module->b_unloadable);
/* Config stuff */
if (CacheLoadConfig (module, file) != VLC_SUCCESS)
if (CacheLoadModuleConfig (module, file) != VLC_SUCCESS)
goto error;
LOAD_STRING(module->domain);
......@@ -280,74 +367,73 @@ error:
return 0;
}
#define SAVE_IMMEDIATE( a ) \
if (fwrite (&(a), sizeof(a), 1, file) != 1) \
goto error
static int CacheLoadConfig( module_t *p_module, FILE *file )
static int CacheSaveString (FILE *file, const char *str)
{
uint32_t i_lines;
uint16_t i_size;
/* Calculate the structure length */
LOAD_IMMEDIATE( p_module->i_config_items );
LOAD_IMMEDIATE( p_module->i_bool_items );
LOAD_IMMEDIATE( i_lines );
uint16_t size = (str != NULL) ? strlen (str) : 0;
/* Allocate memory */
if (i_lines)
{
p_module->p_config =
(module_config_t *)calloc( i_lines, sizeof(module_config_t) );
if( p_module->p_config == NULL )
SAVE_IMMEDIATE (size);
if (size != 0 && fwrite (str, 1, size, file) != size)
{
p_module->confsize = 0;
return VLC_ENOMEM;
}
error:
return -1;
}
p_module->confsize = i_lines;
/* Do the duplication job */
for (size_t i = 0; i < i_lines; i++ )
{
LOAD_IMMEDIATE( p_module->p_config[i] );
return 0;
}
LOAD_STRING( p_module->p_config[i].psz_type );
LOAD_STRING( p_module->p_config[i].psz_name );
LOAD_STRING( p_module->p_config[i].psz_text );
LOAD_STRING( p_module->p_config[i].psz_longtext );
#define SAVE_STRING( a ) \
if (CacheSaveString (file, (a))) \
goto error
if (IsConfigStringType (p_module->p_config[i].i_type))
static int CacheSaveConfig (FILE *file, const module_config_t *cfg)
{
SAVE_IMMEDIATE (cfg->flags);
SAVE_STRING (cfg->psz_type);
SAVE_STRING (cfg->psz_name);
SAVE_STRING (cfg->psz_text);
SAVE_STRING (cfg->psz_longtext);
SAVE_IMMEDIATE (cfg->list_count);
if (IsConfigStringType (cfg->i_type))
{
LOAD_STRING (p_module->p_config[i].orig.psz);
p_module->p_config[i].value.psz =
(p_module->p_config[i].orig.psz != NULL)
? strdup (p_module->p_config[i].orig.psz) : NULL;
p_module->p_config[i].ppsz_list =
xmalloc( p_module->p_config[i].i_list * sizeof(char *) );
for( int j = 0; j < p_module->p_config[i].i_list; j++ )
LOAD_STRING( p_module->p_config[i].ppsz_list[j] );
SAVE_STRING (cfg->orig.psz);
for (unsigned i = 0; i < cfg->list_count; i++)
SAVE_STRING (cfg->list.psz[i]);
}
else
{
memcpy (&p_module->p_config[i].value, &p_module->p_config[i].orig,
sizeof (p_module->p_config[i].value));
p_module->p_config[i].pi_list =
xmalloc( p_module->p_config[i].i_list * sizeof(int) );
for( int j = 0; j < p_module->p_config[i].i_list; j++ )
LOAD_IMMEDIATE( p_module->p_config[i].pi_list[j] );
SAVE_IMMEDIATE (cfg->orig);
SAVE_IMMEDIATE (cfg->min);
SAVE_IMMEDIATE (cfg->max);
for (unsigned i = 0; i < cfg->list_count; i++)
SAVE_IMMEDIATE (cfg->list.i[i]);
}
for (unsigned i = 0; i < cfg->list_count; i++)
SAVE_STRING (cfg->list_text[i]);
p_module->p_config[i].ppsz_list_text =
xmalloc( p_module->p_config[i].i_list * sizeof(char *) );
for( int j = 0; j < p_module->p_config[i].i_list; j++ )
LOAD_STRING( p_module->p_config[i].ppsz_list_text[j] );
}
return 0;
error:
return -1;
}
return VLC_SUCCESS;
static int CacheSaveModuleConfig (FILE *file, const module_t *module)
{
uint16_t lines = module->confsize;
SAVE_IMMEDIATE (module->i_config_items);
SAVE_IMMEDIATE (module->i_bool_items);
SAVE_IMMEDIATE (lines);
error:
for (size_t i = 0; i < lines; i++)
if (CacheSaveConfig (file, module->p_config + i))
goto error;
return VLC_EGENERIC;
return 0;
error:
return -1;
}
static int CacheSaveBank( FILE *file, const module_cache_t *, size_t );
......@@ -401,7 +487,6 @@ out:
free (entries);
}
static int CacheSaveConfig (FILE *, const module_t *);
static int CacheSaveSubmodule (FILE *, const module_t *);
static int CacheSaveBank (FILE *file, const module_cache_t *cache,
......@@ -431,17 +516,6 @@ static int CacheSaveBank (FILE *file, const module_cache_t *cache,
if (fwrite( &i_cache, sizeof (i_cache), 1, file) != 1)
goto error;
#define SAVE_IMMEDIATE( a ) \
if (fwrite (&(a), sizeof(a), 1, file) != 1) \
goto error
#define SAVE_STRING( a ) \
{ \
uint16_t i_size = (a != NULL) ? (strlen (a) + 1) : 0; \
if ((fwrite (&i_size, sizeof (i_size), 1, file) != 1) \
|| (a && (fwrite (a, 1, i_size, file) != i_size))) \
goto error; \
} while(0)
for (unsigned i = 0; i < i_cache; i++)
{
module_t *module = cache[i].p_module;
......@@ -460,7 +534,7 @@ static int CacheSaveBank (FILE *file, const module_cache_t *cache,
SAVE_IMMEDIATE(module->b_unloadable);
/* Config stuff */
if (CacheSaveConfig (file, module))
if (CacheSaveModuleConfig (file, module))
goto error;
SAVE_STRING(module->domain);
......@@ -505,45 +579,6 @@ error:
return -1;
}
static int CacheSaveConfig (FILE *file, const module_t *p_module)
{
uint32_t i_lines = p_module->confsize;
SAVE_IMMEDIATE( p_module->i_config_items );
SAVE_IMMEDIATE( p_module->i_bool_items );
SAVE_IMMEDIATE( i_lines );
for (size_t i = 0; i < i_lines ; i++)
{
SAVE_IMMEDIATE( p_module->p_config[i] );
SAVE_STRING( p_module->p_config[i].psz_type );
SAVE_STRING( p_module->p_config[i].psz_name );
SAVE_STRING( p_module->p_config[i].psz_text );
SAVE_STRING( p_module->p_config[i].psz_longtext );
if (IsConfigStringType (p_module->p_config[i].i_type))
{
SAVE_STRING( p_module->p_config[i].orig.psz );
for (int j = 0; j < p_module->p_config[i].i_list; j++)
SAVE_STRING( p_module->p_config[i].ppsz_list[j] );
}
else
{
for (int j = 0; j < p_module->p_config[i].i_list; j++)
SAVE_IMMEDIATE( p_module->p_config[i].pi_list[j] );
}
for (int j = 0; j < p_module->p_config[i].i_list; j++)
SAVE_STRING( p_module->p_config[i].ppsz_list_text[j] );
}
return 0;
error:
return -1;
}
/*****************************************************************************
* CacheMerge: Merge a cache module descriptor with a full module descriptor.
*****************************************************************************/
......
......@@ -377,6 +377,8 @@ static int vlc_plugin_setter (void *plugin, void *tgt, int propid, ...)
{
size_t len = va_arg (ap, size_t);
assert (item->list_count == 0); /* cannot replace choices */
assert (item->list.psz_cb == NULL);
/* Copy values */
if (IsConfigIntegerType (item->i_type))
{
......@@ -388,7 +390,7 @@ static int vlc_plugin_setter (void *plugin, void *tgt, int propid, ...)
memcpy (dst, src, sizeof (int) * len);
dst[len] = 0;
}
item->pi_list = dst;
item->list.i = dst;
}
else
if (IsConfigStringType (item->i_type))
......@@ -402,7 +404,7 @@ static int vlc_plugin_setter (void *plugin, void *tgt, int propid, ...)
dst[i] = src[i] ? strdup (src[i]) : NULL;
dst[len] = NULL;
}
item->ppsz_list = dst;
item->list.psz = dst;
}
else
break;
......@@ -416,13 +418,13 @@ static int vlc_plugin_setter (void *plugin, void *tgt, int propid, ...)
dtext[i] = text[i] ? strdup (text[i]) : NULL;
dtext[len] = NULL;
}
item->ppsz_list_text = dtext;
item->i_list = len;
item->list_text = dtext;
item->list_count = len;
break;
}
case VLC_CONFIG_LIST_CB:
item->pf_update_list = va_arg (ap, vlc_string_list_cb);
item->list.psz_cb = va_arg (ap, vlc_string_list_cb);
break;
default:
......
......@@ -182,9 +182,10 @@ void vout_InitInterlacingSupport(vout_thread_t *vout, bool is_interlaced)
const module_config_t *optd = config_FindConfig(VLC_OBJECT(vout), "deinterlace");
var_Change(vout, "deinterlace", VLC_VAR_CLEARCHOICES, NULL, NULL);
for (int i = 0; optd && i < optd->i_list; i++) {
val.i_int = optd->pi_list[i];
text.psz_string = (char*)vlc_gettext(optd->ppsz_list_text[i]);
if (likely(optd != NULL))
for (unsigned i = 0; i < optd->list_count; i++) {
val.i_int = optd->list.i[i];
text.psz_string = vlc_gettext(optd->list_text[i]);
var_Change(vout, "deinterlace", VLC_VAR_ADDCHOICE, &val, &text);
}
var_AddCallback(vout, "deinterlace", DeinterlaceCallback, NULL);
......@@ -197,13 +198,15 @@ void vout_InitInterlacingSupport(vout_thread_t *vout, bool is_interlaced)
const module_config_t *optm = config_FindConfig(VLC_OBJECT(vout), "deinterlace-mode");
var_Change(vout, "deinterlace-mode", VLC_VAR_CLEARCHOICES, NULL, NULL);
for (int i = 0; optm && i < optm->i_list; i++) {
if (!DeinterlaceIsModeValid(optm->ppsz_list[i]))
if (likely(optm != NULL))
for (unsigned i = 0; i < optm->list_count; i++) {
if (!DeinterlaceIsModeValid(optm->list.psz[i]))
continue;
val.psz_string = optm->ppsz_list[i];
text.psz_string = (char*)vlc_gettext(optm->ppsz_list_text[i]);
var_Change(vout, "deinterlace-mode", VLC_VAR_ADDCHOICE, &val, &text);
val.psz_string = optm->list.psz[i];
text.psz_string = vlc_gettext(optm->list_text[i]);
var_Change(vout, "deinterlace-mode", VLC_VAR_ADDCHOICE,
&val, &text);
}
var_AddCallback(vout, "deinterlace-mode", DeinterlaceCallback, NULL);
/* */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment