2 * This file is part of MPlayer.
4 * MPlayer is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * MPlayer is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License along
15 * with MPlayer; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 /// \ingroup Properties
32 #include "m_property.h"
36 static int do_action(const m_option_t
*prop_list
, const char *name
,
37 int action
, void *arg
, void *ctx
)
40 const m_option_t
*prop
;
41 m_property_action_t ka
;
43 if ((sep
= strchr(name
, '/')) && sep
[1]) {
46 memcpy(base
, name
, len
);
48 prop
= m_option_list_find(prop_list
, base
);
52 action
= M_PROPERTY_KEY_ACTION
;
55 prop
= m_option_list_find(prop_list
, name
);
57 return M_PROPERTY_UNKNOWN
;
58 r
= ((m_property_ctrl_f
)prop
->p
)(prop
, action
, arg
, ctx
);
59 if (action
== M_PROPERTY_GET_TYPE
&& r
< 0) {
61 return M_PROPERTY_ERROR
;
62 *(const m_option_t
**)arg
= prop
;
68 int m_property_do(const m_option_t
*prop_list
, const char *name
,
69 int action
, void *arg
, void *ctx
)
71 const m_option_t
*opt
;
76 case M_PROPERTY_PRINT
:
77 if ((r
= do_action(prop_list
, name
, M_PROPERTY_PRINT
, arg
, ctx
)) >= 0)
79 // fallback on the default print for this type
80 case M_PROPERTY_TO_STRING
:
81 if ((r
= do_action(prop_list
, name
, M_PROPERTY_TO_STRING
, arg
, ctx
)) !=
82 M_PROPERTY_NOT_IMPLEMENTED
)
84 // fallback on the options API. Get the type, value and print.
86 do_action(prop_list
, name
, M_PROPERTY_GET_TYPE
, &opt
, ctx
)) <= 0)
88 val
= calloc(1, opt
->type
->size
);
89 if ((r
= do_action(prop_list
, name
, M_PROPERTY_GET
, val
, ctx
)) <= 0) {
94 return M_PROPERTY_ERROR
;
95 char *str
= m_option_print(opt
, val
);
99 case M_PROPERTY_PARSE
:
100 // try the property own parsing func
101 if ((r
= do_action(prop_list
, name
, M_PROPERTY_PARSE
, arg
, ctx
)) !=
102 M_PROPERTY_NOT_IMPLEMENTED
)
104 // fallback on the options API, get the type and parse.
106 do_action(prop_list
, name
, M_PROPERTY_GET_TYPE
, &opt
, ctx
)) <= 0)
109 return M_PROPERTY_ERROR
;
110 val
= calloc(1, opt
->type
->size
);
111 if ((r
= m_option_parse(opt
, bstr(opt
->name
), bstr(arg
), false,
116 r
= do_action(prop_list
, name
, M_PROPERTY_SET
, val
, ctx
);
117 m_option_free(opt
, val
);
121 return do_action(prop_list
, name
, action
, arg
, ctx
);
124 char *m_properties_expand_string(const m_option_t
*prop_list
, char *str
,
127 int l
, fr
= 0, pos
= 0, size
= strlen(str
) + 512;
128 char *p
= NULL
, *e
, *ret
= malloc(size
), num_val
;
129 int skip
= 0, lvl
= 0, skip_lvl
= 0;
132 if (str
[0] == '\\') {
136 p
= "\x1b", l
= 1; break;
138 p
= "\n", l
= 1; break;
140 p
= "\r", l
= 1; break;
142 p
= "\t", l
= 1; break;
145 char num
[3] = { str
[2], str
[3], 0 };
147 num_val
= strtol(num
, &end
, 16);
158 } else if (lvl
> 0 && str
[0] == ')') {
159 if (skip
&& lvl
<= skip_lvl
)
162 } else if (str
[0] == '$' && str
[1] == '{'
163 && (e
= strchr(str
+ 2, '}'))) {
164 int pl
= e
- str
- 2;
166 memcpy(pname
, str
+ 2, pl
);
168 if (m_property_do(prop_list
, pname
,
169 M_PROPERTY_PRINT
, &p
, ctx
) >= 0 && p
)
170 l
= strlen(p
), fr
= 1;
174 } else if (str
[0] == '?' && str
[1] == '('
175 && (e
= strchr(str
+ 2, ':'))) {
178 int is_not
= str
[2] == '!';
179 int pl
= e
- str
- (is_not
? 3 : 2);
181 memcpy(pname
, str
+ (is_not
? 3 : 2), pl
);
183 if (m_property_do(prop_list
, pname
, M_PROPERTY_GET
, NULL
, ctx
) < 0) {
185 skip
= 1, skip_lvl
= lvl
;
187 skip
= 1, skip_lvl
= lvl
;
191 p
= str
, l
= 1, str
++;
196 if (pos
+ l
+ 1 > size
) {
197 size
= pos
+ l
+ 512;
198 ret
= realloc(ret
, size
);
200 memcpy(ret
+ pos
, p
, l
);
203 talloc_free(p
), fr
= 0;
210 void m_properties_print_help_list(const m_option_t
*list
)
212 char min
[50], max
[50];
215 mp_tmsg(MSGT_CFGPARSER
, MSGL_INFO
,
216 "\n Name Type Min Max\n\n");
217 for (i
= 0; list
[i
].name
; i
++) {
218 const m_option_t
*opt
= &list
[i
];
219 if (opt
->flags
& M_OPT_MIN
)
220 sprintf(min
, "%-8.0f", opt
->min
);
223 if (opt
->flags
& M_OPT_MAX
)
224 sprintf(max
, "%-8.0f", opt
->max
);
227 mp_msg(MSGT_CFGPARSER
, MSGL_INFO
,
228 " %-20.20s %-15.15s %-10.10s %-10.10s\n",
235 mp_tmsg(MSGT_CFGPARSER
, MSGL_INFO
, "\nTotal: %d properties\n", count
);
238 // Some generic property implementations
240 int m_property_int_ro(const m_option_t
*prop
, int action
,
250 return M_PROPERTY_NOT_IMPLEMENTED
;
253 int m_property_int_range(const m_option_t
*prop
, int action
,
260 M_PROPERTY_CLAMP(prop
, *(int *)arg
);
263 case M_PROPERTY_STEP_UP
:
264 case M_PROPERTY_STEP_DOWN
:
265 *var
+= (arg
? *(int *)arg
: 1) *
266 (action
== M_PROPERTY_STEP_DOWN
? -1 : 1);
267 M_PROPERTY_CLAMP(prop
, *var
);
270 return m_property_int_ro(prop
, action
, arg
, *var
);
273 int m_property_choice(const m_option_t
*prop
, int action
,
277 case M_PROPERTY_STEP_UP
:
278 case M_PROPERTY_STEP_DOWN
:
279 *var
+= action
== M_PROPERTY_STEP_UP
? 1 : prop
->max
;
280 *var
%= (int)prop
->max
+ 1;
283 return m_property_int_range(prop
, action
, arg
, var
);
286 int m_property_flag_ro(const m_option_t
*prop
, int action
,
290 case M_PROPERTY_PRINT
:
293 *(char **)arg
= talloc_strdup(NULL
, (var
> prop
->min
) ?
294 mp_gtext("enabled") : mp_gtext("disabled"));
297 return m_property_int_ro(prop
, action
, arg
, var
);
300 int m_property_flag(const m_option_t
*prop
, int action
,
304 case M_PROPERTY_STEP_UP
:
305 case M_PROPERTY_STEP_DOWN
:
306 *var
= *var
== prop
->min
? prop
->max
: prop
->min
;
308 case M_PROPERTY_PRINT
:
309 return m_property_flag_ro(prop
, action
, arg
, *var
);
311 return m_property_int_range(prop
, action
, arg
, var
);
314 int m_property_float_ro(const m_option_t
*prop
, int action
,
315 void *arg
, float var
)
323 case M_PROPERTY_PRINT
:
326 *(char **)arg
= talloc_asprintf(NULL
, "%.2f", var
);
329 return M_PROPERTY_NOT_IMPLEMENTED
;
332 int m_property_float_range(const m_option_t
*prop
, int action
,
333 void *arg
, float *var
)
339 M_PROPERTY_CLAMP(prop
, *(float *)arg
);
340 *var
= *(float *)arg
;
342 case M_PROPERTY_STEP_UP
:
343 case M_PROPERTY_STEP_DOWN
:
344 *var
+= (arg
? *(float *)arg
: 0.1) *
345 (action
== M_PROPERTY_STEP_DOWN
? -1 : 1);
346 M_PROPERTY_CLAMP(prop
, *var
);
349 return m_property_float_ro(prop
, action
, arg
, *var
);
352 int m_property_delay(const m_option_t
*prop
, int action
,
353 void *arg
, float *var
)
356 case M_PROPERTY_PRINT
:
359 *(char **)arg
= talloc_asprintf(NULL
, "%d ms", ROUND((*var
) * 1000));
362 return m_property_float_range(prop
, action
, arg
, var
);
366 int m_property_double_ro(const m_option_t
*prop
, int action
,
367 void *arg
, double var
)
373 *(double *)arg
= var
;
375 case M_PROPERTY_PRINT
:
378 *(char **)arg
= talloc_asprintf(NULL
, "%.2f", var
);
381 return M_PROPERTY_NOT_IMPLEMENTED
;
384 static char *format_time(double time
)
391 return talloc_asprintf(NULL
, "%02d:%02d:%02d", h
, m
, s
);
394 int m_property_time_ro(const m_option_t
*prop
, int action
,
395 void *arg
, double var
)
398 case M_PROPERTY_PRINT
:
400 return M_PROPERTY_ERROR
;
402 *(char **)arg
= format_time(var
);
403 return M_PROPERTY_OK
;
406 return m_property_double_ro(prop
, action
, arg
, var
);
409 int m_property_string_ro(const m_option_t
*prop
, int action
, void *arg
,
418 case M_PROPERTY_PRINT
:
421 *(char **)arg
= talloc_strdup(NULL
, str
);
424 return M_PROPERTY_NOT_IMPLEMENTED
;
427 int m_property_bitrate(const m_option_t
*prop
, int action
, void *arg
, int rate
)
430 case M_PROPERTY_PRINT
:
432 return M_PROPERTY_ERROR
;
433 *(char **)arg
= talloc_asprintf(NULL
, "%d kbps", rate
* 8 / 1000);
434 return M_PROPERTY_OK
;
436 return m_property_int_ro(prop
, action
, arg
, rate
);