mirror of
https://github.com/mpv-player/mpv
synced 2025-01-03 05:22:23 +00:00
Rework the property API to allow sub properties such as
metadata/title, etc. git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@23411 b3059339-0415-0410-9bf9-f77b7e298cf2
This commit is contained in:
parent
7c583588b9
commit
1654c2bd80
78
command.c
78
command.c
@ -1410,17 +1410,17 @@ static m_option_t mp_properties[] = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
m_option_t *mp_property_find(const char *name)
|
|
||||||
{
|
|
||||||
return m_option_list_find(mp_properties, name);
|
|
||||||
}
|
|
||||||
|
|
||||||
int mp_property_do(const char *name, int action, void *val, void *ctx)
|
int mp_property_do(const char *name, int action, void *val, void *ctx)
|
||||||
{
|
{
|
||||||
m_option_t *p = mp_property_find(name);
|
return m_property_do(mp_properties, name, action, val, ctx);
|
||||||
if (!p)
|
}
|
||||||
return M_PROPERTY_UNAVAILABLE;
|
|
||||||
return m_property_do(p, action, val, ctx);
|
char* mp_property_print(const char *name, void* ctx)
|
||||||
|
{
|
||||||
|
char* ret = NULL;
|
||||||
|
if(mp_property_do(name,M_PROPERTY_PRINT,&ret,ctx) <= 0)
|
||||||
|
return NULL;
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *property_expand_string(MPContext * mpctx, char *str)
|
char *property_expand_string(MPContext * mpctx, char *str)
|
||||||
@ -1511,43 +1511,42 @@ static struct {
|
|||||||
static int set_property_command(MPContext * mpctx, mp_cmd_t * cmd)
|
static int set_property_command(MPContext * mpctx, mp_cmd_t * cmd)
|
||||||
{
|
{
|
||||||
int i, r;
|
int i, r;
|
||||||
m_option_t *prop;
|
m_option_t* prop;
|
||||||
|
const char *pname;
|
||||||
|
|
||||||
// look for the command
|
// look for the command
|
||||||
for (i = 0; set_prop_cmd[i].name; i++)
|
for (i = 0; set_prop_cmd[i].name; i++)
|
||||||
if (set_prop_cmd[i].cmd == cmd->id)
|
if (set_prop_cmd[i].cmd == cmd->id)
|
||||||
break;
|
break;
|
||||||
if (!set_prop_cmd[i].name)
|
if (!(pname = set_prop_cmd[i].name))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
// get the property
|
if (mp_property_do(pname,M_PROPERTY_GET_TYPE,&prop,mpctx) <= 0 || !prop)
|
||||||
prop = mp_property_find(set_prop_cmd[i].name);
|
|
||||||
if (!prop)
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
// toggle command
|
// toggle command
|
||||||
if (set_prop_cmd[i].toggle) {
|
if (set_prop_cmd[i].toggle) {
|
||||||
// set to value
|
// set to value
|
||||||
if (cmd->nargs > 0 && cmd->args[0].v.i >= prop->min)
|
if (cmd->nargs > 0 && cmd->args[0].v.i >= prop->min)
|
||||||
r = m_property_do(prop, M_PROPERTY_SET, &cmd->args[0].v.i, mpctx);
|
r = mp_property_do(pname, M_PROPERTY_SET, &cmd->args[0].v.i, mpctx);
|
||||||
else
|
else
|
||||||
r = m_property_do(prop, M_PROPERTY_STEP_UP, NULL, mpctx);
|
r = mp_property_do(pname, M_PROPERTY_STEP_UP, NULL, mpctx);
|
||||||
} else if (cmd->args[1].v.i) //set
|
} else if (cmd->args[1].v.i) //set
|
||||||
r = m_property_do(prop, M_PROPERTY_SET, &cmd->args[0].v, mpctx);
|
r = mp_property_do(pname, M_PROPERTY_SET, &cmd->args[0].v, mpctx);
|
||||||
else // adjust
|
else // adjust
|
||||||
r = m_property_do(prop, M_PROPERTY_STEP_UP, &cmd->args[0].v, mpctx);
|
r = mp_property_do(pname, M_PROPERTY_STEP_UP, &cmd->args[0].v, mpctx);
|
||||||
|
|
||||||
if (r <= 0)
|
if (r <= 0)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
if (set_prop_cmd[i].osd_progbar) {
|
if (set_prop_cmd[i].osd_progbar) {
|
||||||
if (prop->type == CONF_TYPE_INT) {
|
if (prop->type == CONF_TYPE_INT) {
|
||||||
if (m_property_do(prop, M_PROPERTY_GET, &r, mpctx) > 0)
|
if (mp_property_do(pname, M_PROPERTY_GET, &r, mpctx) > 0)
|
||||||
set_osd_bar(set_prop_cmd[i].osd_progbar,
|
set_osd_bar(set_prop_cmd[i].osd_progbar,
|
||||||
set_prop_cmd[i].osd_msg, prop->min, prop->max, r);
|
set_prop_cmd[i].osd_msg, prop->min, prop->max, r);
|
||||||
} else if (prop->type == CONF_TYPE_FLOAT) {
|
} else if (prop->type == CONF_TYPE_FLOAT) {
|
||||||
float f;
|
float f;
|
||||||
if (m_property_do(prop, M_PROPERTY_GET, &f, mpctx) > 0)
|
if (mp_property_do(pname, M_PROPERTY_GET, &f, mpctx) > 0)
|
||||||
set_osd_bar(set_prop_cmd[i].osd_progbar,
|
set_osd_bar(set_prop_cmd[i].osd_progbar,
|
||||||
set_prop_cmd[i].osd_msg, prop->min, prop->max, f);
|
set_prop_cmd[i].osd_msg, prop->min, prop->max, f);
|
||||||
} else
|
} else
|
||||||
@ -1557,7 +1556,7 @@ static int set_property_command(MPContext * mpctx, mp_cmd_t * cmd)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (set_prop_cmd[i].osd_msg) {
|
if (set_prop_cmd[i].osd_msg) {
|
||||||
char *val = m_property_print(prop, mpctx);
|
char *val = mp_property_print(pname, mpctx);
|
||||||
if (val) {
|
if (val) {
|
||||||
set_osd_msg(set_prop_cmd[i].osd_id >=
|
set_osd_msg(set_prop_cmd[i].osd_id >=
|
||||||
0 ? set_prop_cmd[i].osd_id : OSD_MSG_PROPERTY + i,
|
0 ? set_prop_cmd[i].osd_id : OSD_MSG_PROPERTY + i,
|
||||||
@ -1603,11 +1602,12 @@ int run_command(MPContext * mpctx, mp_cmd_t * cmd)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case MP_CMD_SET_PROPERTY:{
|
case MP_CMD_SET_PROPERTY:{
|
||||||
m_option_t *prop = mp_property_find(cmd->args[0].v.s);
|
int r = mp_property_do(cmd->args[0].v.s, M_PROPERTY_PARSE,
|
||||||
if (!prop)
|
cmd->args[1].v.s, mpctx);
|
||||||
|
if (r == M_PROPERTY_UNKNOWN)
|
||||||
mp_msg(MSGT_CPLAYER, MSGL_WARN,
|
mp_msg(MSGT_CPLAYER, MSGL_WARN,
|
||||||
"Unknown property: '%s'\n", cmd->args[0].v.s);
|
"Unknown property: '%s'\n", cmd->args[0].v.s);
|
||||||
else if (m_property_parse(prop, cmd->args[1].v.s, mpctx) <= 0)
|
else if (r <= 0)
|
||||||
mp_msg(MSGT_CPLAYER, MSGL_WARN,
|
mp_msg(MSGT_CPLAYER, MSGL_WARN,
|
||||||
"Failed to set property '%s' to '%s'.\n",
|
"Failed to set property '%s' to '%s'.\n",
|
||||||
cmd->args[0].v.s, cmd->args[1].v.s);
|
cmd->args[0].v.s, cmd->args[1].v.s);
|
||||||
@ -1615,14 +1615,14 @@ int run_command(MPContext * mpctx, mp_cmd_t * cmd)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case MP_CMD_STEP_PROPERTY:{
|
case MP_CMD_STEP_PROPERTY:{
|
||||||
m_option_t *prop = mp_property_find(cmd->args[0].v.s);
|
|
||||||
float arg = cmd->args[1].v.f;
|
float arg = cmd->args[1].v.f;
|
||||||
if (!prop)
|
int r = mp_property_do
|
||||||
|
(cmd->args[0].v.s, M_PROPERTY_STEP_UP,
|
||||||
|
arg ? &arg : NULL, mpctx);
|
||||||
|
if (r == M_PROPERTY_UNKNOWN)
|
||||||
mp_msg(MSGT_CPLAYER, MSGL_WARN,
|
mp_msg(MSGT_CPLAYER, MSGL_WARN,
|
||||||
"Unknown property: '%s'\n", cmd->args[0].v.s);
|
"Unknown property: '%s'\n", cmd->args[0].v.s);
|
||||||
else if (m_property_do
|
else if (r <= 0)
|
||||||
(prop, M_PROPERTY_STEP_UP,
|
|
||||||
arg ? &arg : NULL, mpctx) <= 0)
|
|
||||||
mp_msg(MSGT_CPLAYER, MSGL_WARN,
|
mp_msg(MSGT_CPLAYER, MSGL_WARN,
|
||||||
"Failed to increment property '%s' by %f.\n",
|
"Failed to increment property '%s' by %f.\n",
|
||||||
cmd->args[0].v.s, arg);
|
cmd->args[0].v.s, arg);
|
||||||
@ -1630,30 +1630,14 @@ int run_command(MPContext * mpctx, mp_cmd_t * cmd)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case MP_CMD_GET_PROPERTY:{
|
case MP_CMD_GET_PROPERTY:{
|
||||||
m_option_t *prop;
|
|
||||||
void *val;
|
|
||||||
char *tmp;
|
char *tmp;
|
||||||
prop = mp_property_find(cmd->args[0].v.s);
|
if (mp_property_do(cmd->args[0].v.s, M_PROPERTY_TO_STRING,
|
||||||
if (!prop) {
|
&tmp, mpctx) <= 0) {
|
||||||
mp_msg(MSGT_CPLAYER, MSGL_WARN,
|
|
||||||
"Unknown property: '%s'\n", cmd->args[0].v.s);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
/* Use m_option_print directly to get easily parseable values. */
|
|
||||||
val = calloc(1, prop->type->size);
|
|
||||||
if (m_property_do(prop, M_PROPERTY_GET, val, mpctx) <= 0) {
|
|
||||||
mp_msg(MSGT_CPLAYER, MSGL_WARN,
|
mp_msg(MSGT_CPLAYER, MSGL_WARN,
|
||||||
"Failed to get value of property '%s'.\n",
|
"Failed to get value of property '%s'.\n",
|
||||||
cmd->args[0].v.s);
|
cmd->args[0].v.s);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
tmp = m_option_print(prop, val);
|
|
||||||
if (!tmp || tmp == (char *) -1) {
|
|
||||||
mp_msg(MSGT_CPLAYER, MSGL_WARN,
|
|
||||||
"Failed to print value of property '%s'.\n",
|
|
||||||
cmd->args[0].v.s);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
mp_msg(MSGT_GLOBAL, MSGL_INFO, "ANS_%s=%s\n",
|
mp_msg(MSGT_GLOBAL, MSGL_INFO, "ANS_%s=%s\n",
|
||||||
cmd->args[0].v.s, tmp);
|
cmd->args[0].v.s, tmp);
|
||||||
free(tmp);
|
free(tmp);
|
||||||
|
@ -30,6 +30,7 @@
|
|||||||
struct list_entry_s {
|
struct list_entry_s {
|
||||||
struct list_entry p;
|
struct list_entry p;
|
||||||
char* name;
|
char* name;
|
||||||
|
char* prop;
|
||||||
m_option_t* opt;
|
m_option_t* opt;
|
||||||
char* menu;
|
char* menu;
|
||||||
};
|
};
|
||||||
@ -76,10 +77,8 @@ static m_option_t cfg_fields[] = {
|
|||||||
#define OPT_INFO_TRACK "track"
|
#define OPT_INFO_TRACK "track"
|
||||||
#define OPT_INFO_GENRE "genre"
|
#define OPT_INFO_GENRE "genre"
|
||||||
|
|
||||||
m_option_t* mp_property_find(const char* name);
|
|
||||||
|
|
||||||
static void entry_set_text(menu_t* menu, list_entry_t* e) {
|
static void entry_set_text(menu_t* menu, list_entry_t* e) {
|
||||||
char* val = m_property_print(e->opt, menu->ctx);
|
char* val = mp_property_print(e->prop, menu->ctx);
|
||||||
int l,edit = (mpriv->edit && e == mpriv->p.current);
|
int l,edit = (mpriv->edit && e == mpriv->p.current);
|
||||||
if(!val) {
|
if(!val) {
|
||||||
if(mpriv->hide_na) {
|
if(mpriv->hide_na) {
|
||||||
@ -99,7 +98,7 @@ static void entry_set_text(menu_t* menu, list_entry_t* e) {
|
|||||||
static void update_entries(menu_t* menu) {
|
static void update_entries(menu_t* menu) {
|
||||||
list_entry_t* e;
|
list_entry_t* e;
|
||||||
for(e = mpriv->p.menu ; e ; e = e->p.next)
|
for(e = mpriv->p.menu ; e ; e = e->p.next)
|
||||||
if(e->opt) entry_set_text(menu,e);
|
if(e->prop) entry_set_text(menu,e);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int parse_args(menu_t* menu,char* args) {
|
static int parse_args(menu_t* menu,char* args) {
|
||||||
@ -195,13 +194,13 @@ static int parse_args(menu_t* menu,char* args) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
name = asx_get_attrib("property",attribs);
|
name = asx_get_attrib("property",attribs);
|
||||||
opt = name ? mp_property_find(name) : NULL;
|
if(!name || mp_property_do(name,M_PROPERTY_GET_TYPE,&opt,menu->ctx) <= 0) {
|
||||||
if(!opt) {
|
|
||||||
mp_msg(MSGT_OSD_MENU,MSGL_WARN,MSGTR_LIBMENU_PrefMenuEntryDefinitionsNeed,parser->line);
|
mp_msg(MSGT_OSD_MENU,MSGL_WARN,MSGTR_LIBMENU_PrefMenuEntryDefinitionsNeed,parser->line);
|
||||||
goto next_element;
|
goto next_element;
|
||||||
}
|
}
|
||||||
m = calloc(1,sizeof(struct list_entry_s));
|
m = calloc(1,sizeof(struct list_entry_s));
|
||||||
m->opt = opt;
|
m->opt = opt;
|
||||||
|
m->prop = strdup(name);
|
||||||
m->name = asx_get_attrib("name",attribs);
|
m->name = asx_get_attrib("name",attribs);
|
||||||
if(!m->name) m->name = strdup(opt->name);
|
if(!m->name) m->name = strdup(opt->name);
|
||||||
entry_set_text(menu,m);
|
entry_set_text(menu,m);
|
||||||
@ -227,22 +226,22 @@ static void read_cmd(menu_t* menu,int cmd) {
|
|||||||
case MENU_CMD_UP:
|
case MENU_CMD_UP:
|
||||||
if(!mpriv->edit) break;
|
if(!mpriv->edit) break;
|
||||||
case MENU_CMD_RIGHT:
|
case MENU_CMD_RIGHT:
|
||||||
if(m_property_do(e->opt,M_PROPERTY_STEP_UP,NULL,menu->ctx) > 0)
|
if(mp_property_do(e->prop,M_PROPERTY_STEP_UP,NULL,menu->ctx) > 0)
|
||||||
update_entries(menu);
|
update_entries(menu);
|
||||||
return;
|
return;
|
||||||
case MENU_CMD_DOWN:
|
case MENU_CMD_DOWN:
|
||||||
if(!mpriv->edit) break;
|
if(!mpriv->edit) break;
|
||||||
case MENU_CMD_LEFT:
|
case MENU_CMD_LEFT:
|
||||||
if(m_property_do(e->opt,M_PROPERTY_STEP_DOWN,NULL,menu->ctx) > 0)
|
if(mp_property_do(e->prop,M_PROPERTY_STEP_DOWN,NULL,menu->ctx) > 0)
|
||||||
update_entries(menu);
|
update_entries(menu);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case MENU_CMD_OK:
|
case MENU_CMD_OK:
|
||||||
// check that the property is writable
|
// check that the property is writable
|
||||||
if(m_property_do(e->opt,M_PROPERTY_SET,NULL,menu->ctx) < 0) return;
|
if(mp_property_do(e->prop,M_PROPERTY_SET,NULL,menu->ctx) < 0) return;
|
||||||
// shortcut for flags
|
// shortcut for flags
|
||||||
if(e->opt->type == CONF_TYPE_FLAG) {
|
if(e->opt->type == CONF_TYPE_FLAG) {
|
||||||
if(m_property_do(e->opt,M_PROPERTY_STEP_UP,NULL,menu->ctx) > 0)
|
if(mp_property_do(e->prop,M_PROPERTY_STEP_UP,NULL,menu->ctx) > 0)
|
||||||
update_entries(menu);
|
update_entries(menu);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -291,6 +290,7 @@ static void read_cmd(menu_t* menu,int cmd) {
|
|||||||
static void free_entry(list_entry_t* entry) {
|
static void free_entry(list_entry_t* entry) {
|
||||||
free(entry->p.txt);
|
free(entry->p.txt);
|
||||||
if(entry->name) free(entry->name);
|
if(entry->name) free(entry->name);
|
||||||
|
if(entry->prop) free(entry->prop);
|
||||||
if(entry->menu) free(entry->menu);
|
if(entry->menu) free(entry->menu);
|
||||||
free(entry);
|
free(entry);
|
||||||
}
|
}
|
||||||
|
110
m_property.c
110
m_property.c
@ -17,55 +17,84 @@
|
|||||||
|
|
||||||
#define ROUND(x) ((int)((x)<0 ? (x)-0.5 : (x)+0.5))
|
#define ROUND(x) ((int)((x)<0 ? (x)-0.5 : (x)+0.5))
|
||||||
|
|
||||||
int m_property_do(m_option_t* prop, int action, void* arg, void *ctx) {
|
static int do_action(m_option_t* prop_list, const char* name,
|
||||||
|
int action, void* arg, void *ctx) {
|
||||||
|
const char* sep;
|
||||||
|
m_option_t* prop;
|
||||||
|
m_property_action_t ka;
|
||||||
|
int r;
|
||||||
|
if((sep = strchr(name,'/')) && sep[1]) {
|
||||||
|
int len = sep-name;
|
||||||
|
char base[len+1];
|
||||||
|
memcpy(base,name,len);
|
||||||
|
base[len] = 0;
|
||||||
|
prop = m_option_list_find(prop_list, base);
|
||||||
|
ka.key = sep+1;
|
||||||
|
ka.action = action;
|
||||||
|
ka.arg = arg;
|
||||||
|
action = M_PROPERTY_KEY_ACTION;
|
||||||
|
arg = &ka;
|
||||||
|
} else
|
||||||
|
prop = m_option_list_find(prop_list, name);
|
||||||
if(!prop) return M_PROPERTY_UNKNOWN;
|
if(!prop) return M_PROPERTY_UNKNOWN;
|
||||||
return ((m_property_ctrl_f)prop->p)(prop,action,arg,ctx);
|
r = ((m_property_ctrl_f)prop->p)(prop,action,arg,ctx);
|
||||||
}
|
if(action == M_PROPERTY_GET_TYPE && r == M_PROPERTY_NOT_IMPLEMENTED) {
|
||||||
|
if(!arg) return M_PROPERTY_ERROR;
|
||||||
|
*(m_option_t**)arg = prop;
|
||||||
char* m_property_print(m_option_t* prop, void *ctx) {
|
return M_PROPERTY_OK;
|
||||||
m_property_ctrl_f ctrl;
|
|
||||||
void* val;
|
|
||||||
char* ret;
|
|
||||||
|
|
||||||
if(!prop) return NULL;
|
|
||||||
|
|
||||||
ctrl = prop->p;
|
|
||||||
// look if the property have it's own print func
|
|
||||||
if(ctrl(prop,M_PROPERTY_PRINT,&ret, ctx) >= 0)
|
|
||||||
return ret;
|
|
||||||
// fallback on the default print for this type
|
|
||||||
val = calloc(1,prop->type->size);
|
|
||||||
if(ctrl(prop,M_PROPERTY_GET,val,ctx) <= 0) {
|
|
||||||
free(val);
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
ret = m_option_print(prop,val);
|
return r;
|
||||||
free(val);
|
|
||||||
return ret == (char*)-1 ? NULL : ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int m_property_parse(m_option_t* prop, char* txt, void *ctx) {
|
int m_property_do(m_option_t* prop_list, const char* name,
|
||||||
m_property_ctrl_f ctrl;
|
int action, void* arg, void *ctx) {
|
||||||
|
m_option_t* opt;
|
||||||
void* val;
|
void* val;
|
||||||
|
char* str;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
if(!prop) return M_PROPERTY_UNKNOWN;
|
switch(action) {
|
||||||
|
case M_PROPERTY_PRINT:
|
||||||
ctrl = prop->p;
|
if((r = do_action(prop_list,name,M_PROPERTY_PRINT,arg,ctx)) >= 0)
|
||||||
// try the property own parsing func
|
|
||||||
if((r = ctrl(prop,M_PROPERTY_PARSE,txt,ctx)) != M_PROPERTY_NOT_IMPLEMENTED)
|
|
||||||
return r;
|
return r;
|
||||||
// fallback on the default
|
// fallback on the default print for this type
|
||||||
val = calloc(1,prop->type->size);
|
case M_PROPERTY_TO_STRING:
|
||||||
if((r = m_option_parse(prop,prop->name,txt,val,M_CONFIG_FILE)) <= 0) {
|
if((r = do_action(prop_list,name,M_PROPERTY_TO_STRING,arg,ctx)) !=
|
||||||
|
M_PROPERTY_NOT_IMPLEMENTED)
|
||||||
|
return r;
|
||||||
|
// fallback on the options API. Get the type, value and print.
|
||||||
|
if((r = do_action(prop_list,name,M_PROPERTY_GET_TYPE,&opt,ctx)) <= 0)
|
||||||
|
return r;
|
||||||
|
val = calloc(1,opt->type->size);
|
||||||
|
if((r = do_action(prop_list,name,M_PROPERTY_GET,val,ctx)) <= 0) {
|
||||||
free(val);
|
free(val);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
r = ctrl(prop,M_PROPERTY_SET,val,ctx);
|
if(!arg) return M_PROPERTY_ERROR;
|
||||||
m_option_free(prop,val);
|
str = m_option_print(opt,val);
|
||||||
|
free(val);
|
||||||
|
*(char**)arg = str == (char*)-1 ? NULL : str;
|
||||||
|
return str != (char*)-1;
|
||||||
|
case M_PROPERTY_PARSE:
|
||||||
|
// try the property own parsing func
|
||||||
|
if((r = do_action(prop_list,name,M_PROPERTY_PARSE,arg,ctx)) !=
|
||||||
|
M_PROPERTY_NOT_IMPLEMENTED)
|
||||||
|
return r;
|
||||||
|
// fallback on the options API, get the type and parse.
|
||||||
|
if((r = do_action(prop_list,name,M_PROPERTY_GET_TYPE,&opt,ctx)) <= 0)
|
||||||
|
return r;
|
||||||
|
if(!arg) return M_PROPERTY_ERROR;
|
||||||
|
val = calloc(1,opt->type->size);
|
||||||
|
if((r = m_option_parse(opt,opt->name,arg,val,M_CONFIG_FILE)) <= 0) {
|
||||||
free(val);
|
free(val);
|
||||||
return r;
|
return r;
|
||||||
|
}
|
||||||
|
r = do_action(prop_list,name,M_PROPERTY_SET,val,ctx);
|
||||||
|
m_option_free(opt,val);
|
||||||
|
free(val);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
return do_action(prop_list,name,action,arg,ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
char* m_properties_expand_string(m_option_t* prop_list,char* str, void *ctx) {
|
char* m_properties_expand_string(m_option_t* prop_list,char* str, void *ctx) {
|
||||||
@ -106,11 +135,10 @@ char* m_properties_expand_string(m_option_t* prop_list,char* str, void *ctx) {
|
|||||||
} else if(str[0] == '$' && str[1] == '{' && (e = strchr(str+2,'}'))) {
|
} else if(str[0] == '$' && str[1] == '{' && (e = strchr(str+2,'}'))) {
|
||||||
int pl = e-str-2;
|
int pl = e-str-2;
|
||||||
char pname[pl+1];
|
char pname[pl+1];
|
||||||
m_option_t* prop;
|
|
||||||
memcpy(pname,str+2,pl);
|
memcpy(pname,str+2,pl);
|
||||||
pname[pl] = 0;
|
pname[pl] = 0;
|
||||||
if((prop = m_option_list_find(prop_list,pname)) &&
|
if(m_property_do(prop_list, pname,
|
||||||
(p = m_property_print(prop, ctx)))
|
M_PROPERTY_PRINT, &p, ctx) >= 0 && p)
|
||||||
l = strlen(p), fr = 1;
|
l = strlen(p), fr = 1;
|
||||||
else
|
else
|
||||||
l = 0;
|
l = 0;
|
||||||
@ -118,13 +146,11 @@ char* m_properties_expand_string(m_option_t* prop_list,char* str, void *ctx) {
|
|||||||
} else if(str[0] == '?' && str[1] == '(' && (e = strchr(str+2,':'))) {
|
} else if(str[0] == '?' && str[1] == '(' && (e = strchr(str+2,':'))) {
|
||||||
int pl = e-str-2;
|
int pl = e-str-2;
|
||||||
char pname[pl+1];
|
char pname[pl+1];
|
||||||
m_option_t* prop;
|
|
||||||
lvl++;
|
lvl++;
|
||||||
if(!skip) {
|
if(!skip) {
|
||||||
memcpy(pname,str+2,pl);
|
memcpy(pname,str+2,pl);
|
||||||
pname[pl] = 0;
|
pname[pl] = 0;
|
||||||
if(!(prop = m_option_list_find(prop_list,pname)) ||
|
if(m_property_do(prop_list,pname,M_PROPERTY_GET,NULL,ctx) < 0)
|
||||||
m_property_do(prop,M_PROPERTY_GET,NULL, ctx) < 0)
|
|
||||||
skip = 1, skip_lvl = lvl;
|
skip = 1, skip_lvl = lvl;
|
||||||
}
|
}
|
||||||
str = e+1, l = 0;
|
str = e+1, l = 0;
|
||||||
|
51
m_property.h
51
m_property.h
@ -48,6 +48,32 @@
|
|||||||
*/
|
*/
|
||||||
#define M_PROPERTY_STEP_DOWN 5
|
#define M_PROPERTY_STEP_DOWN 5
|
||||||
|
|
||||||
|
/// Get a string containg a parsable representation.
|
||||||
|
/** Set the variable to a newly allocated string or NULL.
|
||||||
|
* \param arg Pointer to a char* variable.
|
||||||
|
*/
|
||||||
|
#define M_PROPERTY_TO_STRING 6
|
||||||
|
|
||||||
|
/// Pass down an action to a sub-property.
|
||||||
|
#define M_PROPERTY_KEY_ACTION 7
|
||||||
|
|
||||||
|
/// Get a m_option describing the property.
|
||||||
|
#define M_PROPERTY_GET_TYPE 8
|
||||||
|
|
||||||
|
///@}
|
||||||
|
|
||||||
|
/// \defgroup PropertyActionsArg Property actions argument type
|
||||||
|
/// \ingroup Properties
|
||||||
|
/// \brief Types used as action argument.
|
||||||
|
///@{
|
||||||
|
|
||||||
|
/// Argument for \ref M_PROPERTY_KEY_ACTION
|
||||||
|
typedef struct {
|
||||||
|
const char* key;
|
||||||
|
int action;
|
||||||
|
void* arg;
|
||||||
|
} m_property_action_t;
|
||||||
|
|
||||||
///@}
|
///@}
|
||||||
|
|
||||||
/// \defgroup PropertyActionsReturn Property actions return code
|
/// \defgroup PropertyActionsReturn Property actions return code
|
||||||
@ -81,25 +107,14 @@
|
|||||||
typedef int(*m_property_ctrl_f)(m_option_t* prop,int action,void* arg,void *ctx);
|
typedef int(*m_property_ctrl_f)(m_option_t* prop,int action,void* arg,void *ctx);
|
||||||
|
|
||||||
/// Do an action on a property.
|
/// Do an action on a property.
|
||||||
/** \param prop The property.
|
/** \param prop_list The list of properties.
|
||||||
|
* \param prop The path of the property.
|
||||||
* \param action See \ref PropertyActions.
|
* \param action See \ref PropertyActions.
|
||||||
* \param arg Argument, usually a pointer to the data type used by the property.
|
* \param arg Argument, usually a pointer to the data type used by the property.
|
||||||
* \return See \ref PropertyActionsReturn.
|
* \return See \ref PropertyActionsReturn.
|
||||||
*/
|
*/
|
||||||
int m_property_do(m_option_t* prop, int action, void* arg, void *ctx);
|
int m_property_do(m_option_t* prop_list, const char* prop,
|
||||||
|
int action, void* arg, void *ctx);
|
||||||
/// Print the current value of a property.
|
|
||||||
/** \param prop The property.
|
|
||||||
* \return A newly allocated string with the current value or NULL on error.
|
|
||||||
*/
|
|
||||||
char* m_property_print(m_option_t* prop, void *ctx);
|
|
||||||
|
|
||||||
/// Set a property.
|
|
||||||
/** \param prop The property.
|
|
||||||
* \param txt The value to set.
|
|
||||||
* \return 1 on success, 0 on error.
|
|
||||||
*/
|
|
||||||
int m_property_parse(m_option_t* prop, char* txt, void *ctx);
|
|
||||||
|
|
||||||
/// Print a list of properties.
|
/// Print a list of properties.
|
||||||
void m_properties_print_help_list(m_option_t* list);
|
void m_properties_print_help_list(m_option_t* list);
|
||||||
@ -119,12 +134,12 @@ char* m_properties_expand_string(m_option_t* prop_list,char* str, void *ctx);
|
|||||||
|
|
||||||
// Helpers to use MPlayer's properties
|
// Helpers to use MPlayer's properties
|
||||||
|
|
||||||
/// Get an MPlayer property.
|
|
||||||
m_option_t* mp_property_find(const char* name);
|
|
||||||
|
|
||||||
/// Do an action with an MPlayer property.
|
/// Do an action with an MPlayer property.
|
||||||
int mp_property_do(const char* name,int action, void* val, void *ctx);
|
int mp_property_do(const char* name,int action, void* val, void *ctx);
|
||||||
|
|
||||||
|
/// Get the value of a property as a string suitable for display in an UI.
|
||||||
|
char* mp_property_print(const char *name, void* ctx);
|
||||||
|
|
||||||
/// \defgroup PropertyImplHelper Property implementation helpers
|
/// \defgroup PropertyImplHelper Property implementation helpers
|
||||||
/// \ingroup Properties
|
/// \ingroup Properties
|
||||||
/// \brief Helper functions for common property types.
|
/// \brief Helper functions for common property types.
|
||||||
|
Loading…
Reference in New Issue
Block a user