Mercurial > mplayer.hg
annotate m_config.c @ 17471:63909962d3fc
Profiles support.
author | albeu |
---|---|
date | Tue, 24 Jan 2006 11:16:13 +0000 |
parents | bad703951cf9 |
children | 526abfe30498 |
rev | line source |
---|---|
8164 | 1 #include "config.h" |
2 | |
3 #include <stdlib.h> | |
4 #include <stdio.h> | |
5 #include <errno.h> | |
6 #include <string.h> | |
7 #ifdef MP_DEBUG | |
8 #include <assert.h> | |
9 #endif | |
10 | |
11 #include "m_config.h" | |
12 #include "m_option.h" | |
13 #include "mp_msg.h" | |
13699
11b249ef87b0
printf --> mp_msg by the Wanderer <inverseparadox at comcast dot net>
diego
parents:
10595
diff
changeset
|
14 #include "help_mp.h" |
8164 | 15 |
17471 | 16 #define MAX_PROFILE_DEPTH 20 |
17 | |
18 static int | |
19 parse_profile(m_option_t* opt,char *name, char *param, void* dst, int src); | |
20 | |
21 static void | |
22 set_profile(m_option_t *opt, void* dst, void* src); | |
23 | |
24 static int | |
25 show_profile(m_option_t *opt, char* name, char *param); | |
26 | |
27 static void | |
28 m_config_add_option(m_config_t *config, m_option_t *arg, char* prefix); | |
29 | |
8164 | 30 m_config_t* |
31 m_config_new(void) { | |
32 m_config_t* config; | |
17471 | 33 static int inited = 0; |
34 static m_option_type_t profile_opt_type; | |
35 static m_option_t ref_opts[] = { | |
36 { "profile", NULL, &profile_opt_type, CONF_NOSAVE, 0, 0, NULL }, | |
37 { "show-profile", show_profile, CONF_TYPE_PRINT_FUNC, CONF_NOCFG, 0, 0, NULL }, | |
38 { NULL, NULL, NULL, 0, 0, 0, NULL } | |
39 }; | |
40 int i; | |
8164 | 41 |
42 config = (m_config_t*)calloc(1,sizeof(m_config_t)); | |
43 config->lvl = 1; // 0 Is the defaults | |
17471 | 44 if(!inited) { |
45 inited = 1; | |
46 profile_opt_type = m_option_type_string_list; | |
47 profile_opt_type.parse = parse_profile; | |
48 profile_opt_type.set = set_profile; | |
49 } | |
50 config->self_opts = malloc(sizeof(ref_opts)); | |
51 memcpy(config->self_opts,ref_opts,sizeof(ref_opts)); | |
52 for(i = 0 ; config->self_opts[i].name ; i++) | |
53 config->self_opts[i].priv = config; | |
54 m_config_register_options(config,config->self_opts); | |
55 | |
8164 | 56 return config; |
57 } | |
58 | |
59 void | |
60 m_config_free(m_config_t* config) { | |
61 m_config_option_t *i = config->opts, *ct; | |
62 m_config_save_slot_t *sl,*st; | |
17471 | 63 m_profile_t *p,*pn; |
64 int j; | |
8164 | 65 |
66 #ifdef MP_DEBUG | |
67 assert(config != NULL); | |
68 #endif | |
69 | |
70 while(i) { | |
13824 | 71 if (i->flags & M_CFG_OPT_ALIAS) |
72 sl = NULL; | |
73 else | |
74 sl = i->slots; | |
8164 | 75 while(sl) { |
76 m_option_free(i->opt,sl->data); | |
77 st = sl->prev; | |
78 free(sl); | |
79 sl = st; | |
80 } | |
81 if(i->name != i->opt->name) | |
82 free(i->name); | |
83 ct = i->next; | |
84 free(i); | |
13824 | 85 i = ct; |
8164 | 86 } |
17471 | 87 for(p = config->profiles ; p ; p = pn) { |
88 pn = p->next; | |
89 free(p->name); | |
90 if(p->desc) free(p->desc); | |
91 for(j = 0 ; j < p->num_opts ; j++) { | |
92 free(p->opts[2*j]); | |
93 if(p->opts[2*j+1]) free(p->opts[2*j+1]); | |
94 } | |
95 free(p->opts); | |
96 free(p); | |
97 } | |
98 free(config->self_opts); | |
8164 | 99 free(config); |
100 } | |
101 | |
102 void | |
103 m_config_push(m_config_t* config) { | |
104 m_config_option_t *co; | |
105 m_config_save_slot_t *slot; | |
106 | |
107 #ifdef MP_DEBUG | |
108 assert(config != NULL); | |
109 assert(config->lvl > 0); | |
110 #endif | |
111 | |
112 config->lvl++; | |
113 | |
114 for(co = config->opts ; co ; co = co->next ) { | |
115 if(co->opt->type->flags & M_OPT_TYPE_HAS_CHILD) | |
116 continue; | |
117 if(co->opt->flags & (M_OPT_GLOBAL|M_OPT_NOSAVE)) | |
118 continue; | |
9912
39444d65c4cb
Don't save restore all options wich point to the same variable.
albeu
parents:
9593
diff
changeset
|
119 if((co->opt->flags & M_OPT_OLD) && !(co->flags && M_CFG_OPT_SET)) |
39444d65c4cb
Don't save restore all options wich point to the same variable.
albeu
parents:
9593
diff
changeset
|
120 continue; |
39444d65c4cb
Don't save restore all options wich point to the same variable.
albeu
parents:
9593
diff
changeset
|
121 if(co->flags & M_CFG_OPT_ALIAS) |
8164 | 122 continue; |
123 | |
124 // Update the current status | |
125 m_option_save(co->opt,co->slots->data,co->opt->p); | |
126 | |
127 // Allocate a new slot | |
128 slot = (m_config_save_slot_t*)calloc(1,sizeof(m_config_save_slot_t) + co->opt->type->size); | |
129 slot->lvl = config->lvl; | |
130 slot->prev = co->slots; | |
131 co->slots = slot; | |
132 m_option_copy(co->opt,co->slots->data,co->slots->prev->data); | |
9912
39444d65c4cb
Don't save restore all options wich point to the same variable.
albeu
parents:
9593
diff
changeset
|
133 // Reset our set flag |
39444d65c4cb
Don't save restore all options wich point to the same variable.
albeu
parents:
9593
diff
changeset
|
134 co->flags &= ~M_CFG_OPT_SET; |
8164 | 135 } |
136 | |
137 mp_msg(MSGT_CFGPARSER, MSGL_DBG2,"Config pushed level is now %d\n",config->lvl); | |
138 } | |
139 | |
140 void | |
141 m_config_pop(m_config_t* config) { | |
142 m_config_option_t *co; | |
143 m_config_save_slot_t *slot; | |
144 | |
145 #ifdef MP_DEBUG | |
146 assert(config != NULL); | |
147 assert(config->lvl > 1); | |
148 #endif | |
149 | |
150 for(co = config->opts ; co ; co = co->next ) { | |
151 int pop = 0; | |
152 if(co->opt->type->flags & M_OPT_TYPE_HAS_CHILD) | |
153 continue; | |
154 if(co->opt->flags & (M_OPT_GLOBAL|M_OPT_NOSAVE)) | |
155 continue; | |
9912
39444d65c4cb
Don't save restore all options wich point to the same variable.
albeu
parents:
9593
diff
changeset
|
156 if(co->flags & M_CFG_OPT_ALIAS) |
39444d65c4cb
Don't save restore all options wich point to the same variable.
albeu
parents:
9593
diff
changeset
|
157 continue; |
8164 | 158 if(co->slots->lvl > config->lvl) |
13699
11b249ef87b0
printf --> mp_msg by the Wanderer <inverseparadox at comcast dot net>
diego
parents:
10595
diff
changeset
|
159 mp_msg(MSGT_CFGPARSER, MSGL_WARN,MSGTR_SaveSlotTooOld,config->lvl,co->slots->lvl); |
8164 | 160 |
161 while(co->slots->lvl >= config->lvl) { | |
162 m_option_free(co->opt,co->slots->data); | |
163 slot = co->slots; | |
164 co->slots = slot->prev; | |
165 free(slot); | |
166 pop++; | |
167 } | |
168 if(pop) // We removed some ctx -> set the previous value | |
169 m_option_set(co->opt,co->opt->p,co->slots->data); | |
170 } | |
171 | |
172 config->lvl--; | |
173 mp_msg(MSGT_CFGPARSER, MSGL_DBG2,"Config poped level=%d\n",config->lvl); | |
174 } | |
175 | |
176 static void | |
177 m_config_add_option(m_config_t *config, m_option_t *arg, char* prefix) { | |
178 m_config_option_t *co; | |
179 m_config_save_slot_t* sl; | |
180 | |
181 #ifdef MP_DEBUG | |
182 assert(config != NULL); | |
183 assert(config->lvl > 0); | |
184 assert(arg != NULL); | |
185 #endif | |
186 | |
187 // Allocate a new entry for this option | |
188 co = (m_config_option_t*)calloc(1,sizeof(m_config_option_t) + arg->type->size); | |
189 co->opt = arg; | |
190 | |
191 // Fill in the full name | |
192 if(prefix && strlen(prefix) > 0) { | |
193 int l = strlen(prefix) + 1 + strlen(arg->name) + 1; | |
194 co->name = (char*) malloc(l); | |
195 sprintf(co->name,"%s:%s",prefix,arg->name); | |
196 } else | |
197 co->name = arg->name; | |
198 | |
199 // Option with childs -> add them | |
200 if(arg->type->flags & M_OPT_TYPE_HAS_CHILD) { | |
201 m_option_t *ol = arg->p; | |
202 int i; | |
13824 | 203 co->slots = NULL; |
8164 | 204 for(i = 0 ; ol[i].name != NULL ; i++) |
205 m_config_add_option(config,&ol[i], co->name); | |
206 } else { | |
9912
39444d65c4cb
Don't save restore all options wich point to the same variable.
albeu
parents:
9593
diff
changeset
|
207 m_config_option_t *i; |
39444d65c4cb
Don't save restore all options wich point to the same variable.
albeu
parents:
9593
diff
changeset
|
208 // Check if there is alredy an option pointing to this address |
39444d65c4cb
Don't save restore all options wich point to the same variable.
albeu
parents:
9593
diff
changeset
|
209 if(arg->p) { |
39444d65c4cb
Don't save restore all options wich point to the same variable.
albeu
parents:
9593
diff
changeset
|
210 for(i = config->opts ; i ; i = i->next ) { |
39444d65c4cb
Don't save restore all options wich point to the same variable.
albeu
parents:
9593
diff
changeset
|
211 if(i->opt->p == arg->p) { // So we don't save the same vars more than 1 time |
39444d65c4cb
Don't save restore all options wich point to the same variable.
albeu
parents:
9593
diff
changeset
|
212 co->slots = i->slots; |
39444d65c4cb
Don't save restore all options wich point to the same variable.
albeu
parents:
9593
diff
changeset
|
213 co->flags |= M_CFG_OPT_ALIAS; |
39444d65c4cb
Don't save restore all options wich point to the same variable.
albeu
parents:
9593
diff
changeset
|
214 break; |
39444d65c4cb
Don't save restore all options wich point to the same variable.
albeu
parents:
9593
diff
changeset
|
215 } |
39444d65c4cb
Don't save restore all options wich point to the same variable.
albeu
parents:
9593
diff
changeset
|
216 } |
39444d65c4cb
Don't save restore all options wich point to the same variable.
albeu
parents:
9593
diff
changeset
|
217 } |
39444d65c4cb
Don't save restore all options wich point to the same variable.
albeu
parents:
9593
diff
changeset
|
218 if(!(co->flags & M_CFG_OPT_ALIAS)) { |
8164 | 219 // Allocate a slot for the defaults |
220 sl = (m_config_save_slot_t*)calloc(1,sizeof(m_config_save_slot_t) + arg->type->size); | |
221 m_option_save(arg,sl->data,(void**)arg->p); | |
222 // Hack to avoid too much trouble with dynamicly allocated data : | |
223 // We always use a dynamic version | |
224 if((arg->type->flags & M_OPT_TYPE_DYNAMIC) && arg->p && (*(void**)arg->p)) { | |
225 *(void**)arg->p = NULL; | |
226 m_option_set(arg,arg->p,sl->data); | |
227 } | |
228 sl->lvl = 0; | |
13824 | 229 sl->prev = NULL; |
8164 | 230 co->slots = (m_config_save_slot_t*)calloc(1,sizeof(m_config_save_slot_t) + arg->type->size); |
231 co->slots->prev = sl; | |
232 co->slots->lvl = config->lvl; | |
233 m_option_copy(co->opt,co->slots->data,sl->data); | |
9912
39444d65c4cb
Don't save restore all options wich point to the same variable.
albeu
parents:
9593
diff
changeset
|
234 } // !M_OPT_ALIAS |
8164 | 235 } |
236 co->next = config->opts; | |
237 config->opts = co; | |
238 } | |
239 | |
240 int | |
241 m_config_register_options(m_config_t *config, m_option_t *args) { | |
242 int i; | |
243 | |
244 #ifdef MP_DEBUG | |
245 assert(config != NULL); | |
246 assert(config->lvl > 0); | |
247 assert(args != NULL); | |
248 #endif | |
249 | |
250 for(i = 0 ; args[i].name != NULL ; i++) | |
251 m_config_add_option(config,&args[i],NULL); | |
252 | |
253 return 1; | |
254 } | |
255 | |
256 static m_config_option_t* | |
257 m_config_get_co(m_config_t *config, char* arg) { | |
258 m_config_option_t *co; | |
259 | |
260 for(co = config->opts ; co ; co = co->next ) { | |
261 int l = strlen(co->name) - 1; | |
262 if((co->opt->type->flags & M_OPT_TYPE_ALLOW_WILDCARD) && | |
263 (co->name[l] == '*')) { | |
264 if(strncasecmp(co->name,arg,l) == 0) | |
265 return co; | |
266 } else if(strcasecmp(co->name,arg) == 0) | |
267 return co; | |
268 } | |
269 return NULL; | |
270 } | |
271 | |
272 static int | |
273 m_config_parse_option(m_config_t *config, char* arg, char* param,int set) { | |
274 m_config_option_t *co; | |
275 int r = 0; | |
276 | |
277 #ifdef MP_DEBUG | |
278 assert(config != NULL); | |
279 assert(config->lvl > 0); | |
280 assert(arg != NULL); | |
281 #endif | |
282 | |
283 co = m_config_get_co(config,arg); | |
8892 | 284 if(!co){ |
8894 | 285 // mp_msg(MSGT_CFGPARSER, MSGL_ERR,"Unknown option: %s\n",arg); |
10595
522afd56703c
100l to albeu for his english grammar, and 10l to me becouse I noticed that lately (my backward compatibilty macro uses M_OPT_UNKNOWN)
alex
parents:
10594
diff
changeset
|
286 return M_OPT_UNKNOWN; |
8892 | 287 } |
8164 | 288 |
289 #ifdef MP_DEBUG | |
290 // This is the only mandatory function | |
291 assert(co->opt->type->parse); | |
292 #endif | |
293 | |
294 // Check if this option isn't forbiden in the current mode | |
295 if((config->mode == M_CONFIG_FILE) && (co->opt->flags & M_OPT_NOCFG)) { | |
13699
11b249ef87b0
printf --> mp_msg by the Wanderer <inverseparadox at comcast dot net>
diego
parents:
10595
diff
changeset
|
296 mp_msg(MSGT_CFGPARSER, MSGL_ERR,MSGTR_InvalidCfgfileOption,arg); |
8164 | 297 return M_OPT_INVALID; |
298 } | |
299 if((config->mode == M_COMMAND_LINE) && (co->opt->flags & M_OPT_NOCMD)) { | |
13699
11b249ef87b0
printf --> mp_msg by the Wanderer <inverseparadox at comcast dot net>
diego
parents:
10595
diff
changeset
|
300 mp_msg(MSGT_CFGPARSER, MSGL_ERR,MSGTR_InvalidCmdlineOption,arg); |
8164 | 301 return M_OPT_INVALID; |
302 } | |
303 | |
304 // Option with childs are a bit different to parse | |
305 if(co->opt->type->flags & M_OPT_TYPE_HAS_CHILD) { | |
306 char** lst = NULL; | |
307 int i,sr; | |
308 // Parse the child options | |
9593
e9a2af584986
Add the new -vf option wich is the same as vop in reverse order.
albeu
parents:
9222
diff
changeset
|
309 r = m_option_parse(co->opt,arg,param,&lst,M_COMMAND_LINE); |
8164 | 310 // Set them now |
8894 | 311 if(r >= 0) |
8164 | 312 for(i = 0 ; lst && lst[2*i] ; i++) { |
313 int l = strlen(co->name) + 1 + strlen(lst[2*i]) + 1; | |
314 if(r >= 0) { | |
315 // Build the full name | |
316 char n[l]; | |
317 sprintf(n,"%s:%s",co->name,lst[2*i]); | |
318 sr = m_config_parse_option(config,n,lst[2*i+1],set); | |
8894 | 319 if(sr < 0){ |
10595
522afd56703c
100l to albeu for his english grammar, and 10l to me becouse I noticed that lately (my backward compatibilty macro uses M_OPT_UNKNOWN)
alex
parents:
10594
diff
changeset
|
320 if(sr == M_OPT_UNKNOWN){ |
13699
11b249ef87b0
printf --> mp_msg by the Wanderer <inverseparadox at comcast dot net>
diego
parents:
10595
diff
changeset
|
321 mp_msg(MSGT_CFGPARSER, MSGL_ERR,MSGTR_InvalidSuboption,co->name,lst[2*i]); |
8894 | 322 r = M_OPT_INVALID; |
323 } else | |
9222 | 324 if(sr == M_OPT_MISSING_PARAM){ |
13699
11b249ef87b0
printf --> mp_msg by the Wanderer <inverseparadox at comcast dot net>
diego
parents:
10595
diff
changeset
|
325 mp_msg(MSGT_CFGPARSER, MSGL_ERR,MSGTR_MissingSuboptionParameter,lst[2*i],co->name); |
9222 | 326 r = M_OPT_INVALID; |
327 } else | |
8894 | 328 r = sr; |
329 } | |
8164 | 330 } |
331 free(lst[2*i]); | |
332 free(lst[2*i+1]); | |
333 } | |
334 if(lst) free(lst); | |
335 } else | |
336 r = m_option_parse(co->opt,arg,param,set ? co->slots->data : NULL,config->mode); | |
337 | |
338 // Parsing failed ? | |
339 if(r < 0) | |
340 return r; | |
341 // Set the option | |
342 if(set) { | |
343 m_option_set(co->opt,co->opt->p,co->slots->data); | |
9912
39444d65c4cb
Don't save restore all options wich point to the same variable.
albeu
parents:
9593
diff
changeset
|
344 co->flags |= M_CFG_OPT_SET; |
8164 | 345 } |
346 | |
347 return r; | |
348 } | |
349 | |
350 int | |
351 m_config_set_option(m_config_t *config, char* arg, char* param) { | |
352 mp_msg(MSGT_CFGPARSER, MSGL_DBG2,"Setting %s=%s\n",arg,param); | |
353 return m_config_parse_option(config,arg,param,1); | |
354 } | |
355 | |
356 int | |
357 m_config_check_option(m_config_t *config, char* arg, char* param) { | |
9222 | 358 int r; |
8164 | 359 mp_msg(MSGT_CFGPARSER, MSGL_DBG2,"Checking %s=%s\n",arg,param); |
9222 | 360 r=m_config_parse_option(config,arg,param,0); |
361 if(r==M_OPT_MISSING_PARAM){ | |
13699
11b249ef87b0
printf --> mp_msg by the Wanderer <inverseparadox at comcast dot net>
diego
parents:
10595
diff
changeset
|
362 mp_msg(MSGT_CFGPARSER, MSGL_ERR,MSGTR_MissingOptionParameter,arg); |
9222 | 363 return M_OPT_INVALID; |
364 } | |
365 return r; | |
8164 | 366 } |
367 | |
368 | |
369 m_option_t* | |
370 m_config_get_option(m_config_t *config, char* arg) { | |
371 m_config_option_t *co; | |
372 | |
373 #ifdef MP_DEBUG | |
374 assert(config != NULL); | |
375 assert(config->lvl > 0); | |
376 assert(arg != NULL); | |
377 #endif | |
378 | |
379 co = m_config_get_co(config,arg); | |
380 if(co) | |
381 return co->opt; | |
382 else | |
383 return NULL; | |
384 } | |
385 | |
386 void* | |
387 m_config_get_option_ptr(m_config_t *config, char* arg) { | |
388 m_option_t* conf; | |
389 | |
390 #ifdef MP_DEBUG | |
391 assert(config != NULL); | |
392 assert(arg != NULL); | |
393 #endif | |
394 | |
395 conf = m_config_get_option(config,arg); | |
396 if(!conf) return NULL; | |
397 return conf->p; | |
398 } | |
399 | |
400 void | |
401 m_config_print_option_list(m_config_t *config) { | |
402 char min[50],max[50]; | |
403 m_config_option_t* co; | |
404 int count = 0; | |
405 | |
406 if(!config->opts) return; | |
407 | |
13699
11b249ef87b0
printf --> mp_msg by the Wanderer <inverseparadox at comcast dot net>
diego
parents:
10595
diff
changeset
|
408 mp_msg(MSGT_FIXME, MSGL_FIXME, MSGTR_OptionListHeader); |
8164 | 409 for(co = config->opts ; co ; co = co->next) { |
410 m_option_t* opt = co->opt; | |
411 if(opt->type->flags & M_OPT_TYPE_HAS_CHILD) continue; | |
412 if(opt->flags & M_OPT_MIN) | |
413 sprintf(min,"%-8.0f",opt->min); | |
414 else | |
415 strcpy(min,"No"); | |
416 if(opt->flags & M_OPT_MAX) | |
417 sprintf(max,"%-8.0f",opt->max); | |
418 else | |
419 strcpy(max,"No"); | |
13699
11b249ef87b0
printf --> mp_msg by the Wanderer <inverseparadox at comcast dot net>
diego
parents:
10595
diff
changeset
|
420 mp_msg(MSGT_FIXME, MSGL_FIXME, " %-20.20s %-15.15s %-10.10s %-10.10s %-3.3s %-3.3s %-3.3s\n", |
8164 | 421 co->name, |
422 co->opt->type->name, | |
423 min, | |
424 max, | |
425 opt->flags & CONF_GLOBAL ? "Yes" : "No", | |
426 opt->flags & CONF_NOCMD ? "No" : "Yes", | |
427 opt->flags & CONF_NOCFG ? "No" : "Yes"); | |
428 count++; | |
429 } | |
13699
11b249ef87b0
printf --> mp_msg by the Wanderer <inverseparadox at comcast dot net>
diego
parents:
10595
diff
changeset
|
430 mp_msg(MSGT_FIXME, MSGL_FIXME, MSGTR_TotalOptions,count); |
8164 | 431 } |
17471 | 432 |
433 m_profile_t* | |
434 m_config_get_profile(m_config_t* config, char* name) { | |
435 m_profile_t* p; | |
436 for(p = config->profiles ; p ; p = p->next) | |
437 if(!strcmp(p->name,name)) return p; | |
438 return NULL; | |
439 } | |
440 | |
441 m_profile_t* | |
442 m_config_add_profile(m_config_t* config, char* name) { | |
443 m_profile_t* p = m_config_get_profile(config,name); | |
444 if(p) return p; | |
445 p = calloc(1,sizeof(m_profile_t)); | |
446 p->name = strdup(name); | |
447 p->next = config->profiles; | |
448 config->profiles = p; | |
449 return p; | |
450 } | |
451 | |
452 void | |
453 m_profile_set_desc(m_profile_t* p, char* desc) { | |
454 if(p->desc) free(p->desc); | |
455 p->desc = desc ? strdup(desc) : NULL; | |
456 } | |
457 | |
458 int | |
459 m_config_set_profile_option(m_config_t* config, m_profile_t* p, | |
460 char* name, char* val) { | |
461 int i = m_config_check_option(config,name,val); | |
462 if(i < 0) return i; | |
463 if(p->opts) p->opts = realloc(p->opts,2*(p->num_opts+2)*sizeof(char*)); | |
464 else p->opts = malloc(2*(p->num_opts+2)*sizeof(char*)); | |
465 p->opts[p->num_opts*2] = strdup(name); | |
466 p->opts[p->num_opts*2+1] = val ? strdup(val) : NULL; | |
467 p->num_opts++; | |
468 p->opts[p->num_opts*2] = p->opts[p->num_opts*2+1] = NULL; | |
469 } | |
470 | |
471 static void | |
472 m_config_set_profile(m_config_t* config, m_profile_t* p) { | |
473 int i; | |
474 if(config->profile_depth > MAX_PROFILE_DEPTH) { | |
475 mp_msg(MSGT_CFGPARSER, MSGL_WARN, "WARNING: Too deep profile inclusion\n"); | |
476 return; | |
477 } | |
478 config->profile_depth++; | |
479 for(i = 0 ; i < p->num_opts ; i++) | |
480 m_config_set_option(config,p->opts[2*i],p->opts[2*i+1]); | |
481 config->profile_depth--; | |
482 } | |
483 | |
484 static int | |
485 parse_profile(m_option_t* opt,char *name, char *param, void* dst, int src) { | |
486 m_config_t* config = opt->priv; | |
487 char** list = NULL; | |
488 int i,r; | |
489 if(param && !strcmp(param,"help")) { | |
490 m_profile_t* p; | |
491 if(!config->profiles) { | |
492 mp_msg(MSGT_FIXME, MSGL_FIXME, "No profile have been defined.\n"); | |
493 return M_OPT_EXIT-1; | |
494 } | |
495 mp_msg(MSGT_FIXME, MSGL_FIXME, "Available profiles:\n"); | |
496 for(p = config->profiles ; p ; p = p->next) | |
497 mp_msg(MSGT_FIXME, MSGL_FIXME, "\t%s\t%s\n",p->name, | |
498 p->desc ? p->desc : ""); | |
499 mp_msg(MSGT_FIXME, MSGL_FIXME, "\n"); | |
500 return M_OPT_EXIT-1; | |
501 } | |
502 | |
503 r = m_option_type_string_list.parse(opt,name,param,&list,src); | |
504 if(r < 0) return r; | |
505 if(!list || !list[0]) return M_OPT_INVALID; | |
506 for(i = 0 ; list[i] ; i++) | |
507 if(!m_config_get_profile(config,list[i])) { | |
508 mp_msg(MSGT_CFGPARSER, MSGL_WARN, "Unknown profile '%s'.\n", | |
509 list[i]); | |
510 r = M_OPT_INVALID; | |
511 } | |
512 if(dst) | |
513 m_option_copy(opt,dst,&list); | |
514 else | |
515 m_option_free(opt,&list); | |
516 return r; | |
517 } | |
518 | |
519 static void | |
520 set_profile(m_option_t *opt, void* dst, void* src) { | |
521 m_config_t* config = opt->priv; | |
522 m_profile_t* p; | |
523 char** list = NULL; | |
524 int i; | |
525 if(!src || !*(char***)src) return; | |
526 m_option_copy(opt,&list,src); | |
527 for(i = 0 ; list[i] ; i++) { | |
528 p = m_config_get_profile(config,list[i]); | |
529 if(!p) continue; | |
530 m_config_set_profile(config,p); | |
531 } | |
532 m_option_free(opt,&list); | |
533 } | |
534 | |
535 static int | |
536 show_profile(m_option_t *opt, char* name, char *param) { | |
537 m_config_t* config = opt->priv; | |
538 m_profile_t* p; | |
539 int i,j; | |
540 if(!param) return M_OPT_MISSING_PARAM; | |
541 if(!(p = m_config_get_profile(config,param))) { | |
542 mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Unknown profile '%s'\n",param); | |
543 return M_OPT_EXIT-1; | |
544 } | |
545 if(!config->profile_depth) | |
546 mp_msg(MSGT_CFGPARSER, MSGL_INFO, "Profile %s: %s\n",param, | |
547 p->desc ? p->desc : ""); | |
548 config->profile_depth++; | |
549 for(i = 0 ; i < p->num_opts ; i++) { | |
550 char spc[config->profile_depth+1]; | |
551 for(j = 0 ; j < config->profile_depth ; j++) | |
552 spc[j] = ' '; | |
553 spc[config->profile_depth] = '\0'; | |
554 | |
555 mp_msg(MSGT_CFGPARSER, MSGL_INFO, "%s%s=%s\n", spc, | |
556 p->opts[2*i], p->opts[2*i+1]); | |
557 | |
558 | |
559 if(config->profile_depth < MAX_PROFILE_DEPTH && | |
560 !strcmp(p->opts[2*i],"profile")) { | |
561 char* e,*list = p->opts[2*i+1]; | |
562 while((e = strchr(list,','))) { | |
563 int l = e-list; | |
564 char tmp[l+1]; | |
565 if(!l) continue; | |
566 memcpy(tmp,list,l); | |
567 tmp[l] = '\0'; | |
568 show_profile(opt,name,tmp); | |
569 list = e+1; | |
570 } | |
571 if(list[0] != '\0') | |
572 show_profile(opt,name,list); | |
573 } | |
574 } | |
575 config->profile_depth--; | |
576 if(!config->profile_depth) mp_msg(MSGT_CFGPARSER, MSGL_INFO, "\n"); | |
577 return M_OPT_EXIT-1; | |
578 } |