18 #include "m_property.h"
19 #include "asxparser.h"
21 #include "libmpcodecs/img_format.h"
22 #include "libmpcodecs/mp_image.h"
25 #include "menu_list.h"
26 #include "input/input.h"
27 #include "osdep/keycodes.h"
48 static struct menu_priv_s cfg_dflt
= {
56 static m_option_t cfg_fields
[] = {
57 MENU_LIST_PRIV_FIELDS
,
58 { "title", M_ST_OFF(menu_list_priv_t
,title
), CONF_TYPE_STRING
, 0, 0, 0, NULL
},
59 { "na", M_ST_OFF(struct menu_priv_s
,na
), CONF_TYPE_STRING
, 0, 0, 0, NULL
},
60 { "hide-na", M_ST_OFF(struct menu_priv_s
,hide_na
), CONF_TYPE_FLAG
, CONF_RANGE
, 0, 1, NULL
},
61 { NULL
, NULL
, NULL
, 0,0,0,NULL
}
64 #define mpriv (menu->priv)
66 static void entry_set_text(menu_t
* menu
, list_entry_t
* e
) {
67 char* val
= e
->txt
? property_expand_string(menu
->ctx
, e
->txt
) :
68 mp_property_print(e
->prop
, menu
->ctx
);
69 int l
,edit
= (mpriv
->edit
&& e
== mpriv
->p
.current
);
76 val
= strdup(mpriv
->na
);
77 } else if(mpriv
->hide_na
)
79 l
= strlen(e
->name
) + 2 + strlen(val
) + (edit
? 4 : 0) + 1;
80 if(e
->p
.txt
) free(e
->p
.txt
);
82 sprintf(e
->p
.txt
,"%s: %s%s%s",e
->name
,edit
? "> " : "",val
,edit
? " <" : "");
86 static void update_entries(menu_t
* menu
) {
88 for(e
= mpriv
->p
.menu
; e
; e
= e
->p
.next
)
89 if(e
->txt
|| e
->prop
) entry_set_text(menu
,e
);
92 static int parse_args(menu_t
* menu
,char* args
) {
93 char *element
,*body
, **attribs
, *name
, *txt
;
94 list_entry_t
* m
= NULL
;
97 ASX_Parser_t
* parser
= asx_parser_new();
101 r
= asx_get_element(parser
,&args
,&element
,&body
,&attribs
);
103 mp_msg(MSGT_OSD_MENU
,MSGL_ERR
,MSGTR_LIBMENU_SyntaxErrorAtLine
,parser
->line
);
104 asx_parser_free(parser
);
107 asx_parser_free(parser
);
109 mp_msg(MSGT_OSD_MENU
,MSGL_WARN
,MSGTR_LIBMENU_NoEntryFoundInTheMenuDefinition
);
110 m
= calloc(1,sizeof(struct list_entry_s
));
111 m
->p
.txt
= strdup("Back");
112 menu_list_add_entry(menu
,m
);
115 if(!strcmp(element
,"menu")) {
116 name
= asx_get_attrib("menu",attribs
);
118 mp_msg(MSGT_OSD_MENU
,MSGL_WARN
,MSGTR_LIBMENU_SubmenuDefinitionNeedAMenuAttribut
);
121 m
= calloc(1,sizeof(struct list_entry_s
));
123 name
= NULL
; // we want to keep it
124 m
->p
.txt
= asx_get_attrib("name",attribs
);
125 if(!m
->p
.txt
) m
->p
.txt
= strdup(m
->menu
);
126 menu_list_add_entry(menu
,m
);
130 name
= asx_get_attrib("property",attribs
);
132 if(name
&& mp_property_do(name
,M_PROPERTY_GET_TYPE
,&opt
,menu
->ctx
) <= 0) {
133 mp_msg(MSGT_OSD_MENU
,MSGL_WARN
,MSGTR_LIBMENU_InvalidProperty
,
137 txt
= asx_get_attrib("txt",attribs
);
139 mp_msg(MSGT_OSD_MENU
,MSGL_WARN
,MSGTR_LIBMENU_PrefMenuEntryDefinitionsNeed
,parser
->line
);
140 if(txt
) free(txt
), txt
= NULL
;
143 m
= calloc(1,sizeof(struct list_entry_s
));
145 m
->txt
= txt
; txt
= NULL
;
146 m
->prop
= name
; name
= NULL
;
147 m
->name
= asx_get_attrib("name",attribs
);
148 if(!m
->name
) m
->name
= strdup(opt
? opt
->name
: "-");
149 entry_set_text(menu
,m
);
150 menu_list_add_entry(menu
,m
);
156 asx_free_attribs(attribs
);
160 static void read_key(menu_t
* menu
,int c
) {
161 menu_list_read_key(menu
,c
,0);
164 static void read_cmd(menu_t
* menu
,int cmd
) {
165 list_entry_t
* e
= mpriv
->p
.current
;
170 if(!mpriv
->edit
) break;
172 if(mp_property_do(e
->prop
,M_PROPERTY_STEP_UP
,NULL
,menu
->ctx
) > 0)
173 update_entries(menu
);
176 if(!mpriv
->edit
) break;
178 if(mp_property_do(e
->prop
,M_PROPERTY_STEP_DOWN
,NULL
,menu
->ctx
) > 0)
179 update_entries(menu
);
183 // check that the property is writable
184 if(mp_property_do(e
->prop
,M_PROPERTY_SET
,NULL
,menu
->ctx
) < 0) return;
185 // shortcut for flags
186 if(e
->opt
->type
== CONF_TYPE_FLAG
) {
187 if(mp_property_do(e
->prop
,M_PROPERTY_STEP_UP
,NULL
,menu
->ctx
) > 0)
188 update_entries(menu
);
192 mpriv
->edit
= !mpriv
->edit
;
194 update_entries(menu
);
195 // switch the pointer
197 mpriv
->ptr
= mpriv
->p
.ptr
;
200 mpriv
->p
.ptr
= mpriv
->ptr
;
202 case MENU_CMD_CANCEL
:
203 if(!mpriv
->edit
) break;
205 update_entries(menu
);
206 mpriv
->p
.ptr
= mpriv
->ptr
;
214 char* txt
= malloc(10 + strlen(e
->menu
) + 1);
215 sprintf(txt
,"set_menu %s",e
->menu
);
216 c
= mp_input_parse_cmd(txt
);
217 if(c
) mp_input_queue_cmd(c
);
230 menu_list_read_cmd(menu
,cmd
);
233 static void free_entry(list_entry_t
* entry
) {
235 if(entry
->name
) free(entry
->name
);
236 if(entry
->txt
) free(entry
->txt
);
237 if(entry
->prop
) free(entry
->prop
);
238 if(entry
->menu
) free(entry
->menu
);
242 static void closeMenu(menu_t
* menu
) {
243 menu_list_uninit(menu
,free_entry
);
246 static int openMenu(menu_t
* menu
, char* args
) {
248 menu
->draw
= menu_list_draw
;
249 menu
->read_cmd
= read_cmd
;
250 menu
->read_key
= read_key
;
251 menu
->close
= closeMenu
;
255 mp_msg(MSGT_OSD_MENU
,MSGL_ERR
,MSGTR_LIBMENU_PrefMenuNeedsAnArgument
);
259 menu_list_init(menu
);
260 return parse_args(menu
,args
);
263 const menu_info_t menu_info_pref
= {
270 sizeof(struct menu_priv_s
),