1 /*****************************************************************
2  * gmerlin - a general purpose multimedia framework and applications
3  *
4  * Copyright (c) 2001 - 2011 Members of the Gmerlin project
5  * gmerlin-general@lists.sourceforge.net
6  * http://gmerlin.sourceforge.net
7  *
8  * This program is free software: you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation, either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
20  * *****************************************************************/
21 
22 #include <string.h>
23 #include <stdlib.h>
24 
25 #include <gmerlin/utils.h>
26 #include <gmerlin/parameter.h>
27 
bg_parameter_value_copy(bg_parameter_value_t * dst,const bg_parameter_value_t * src,const bg_parameter_info_t * info)28 void bg_parameter_value_copy(bg_parameter_value_t * dst,
29                              const bg_parameter_value_t * src,
30                              const bg_parameter_info_t * info)
31   {
32   switch(info->type)
33     {
34     case BG_PARAMETER_CHECKBUTTON:
35       dst->val_i = src->val_i;
36       break;
37     case BG_PARAMETER_INT:
38     case BG_PARAMETER_SLIDER_INT:
39       dst->val_i = src->val_i;
40       break;
41     case BG_PARAMETER_FLOAT:
42     case BG_PARAMETER_SLIDER_FLOAT:
43       dst->val_f = src->val_f;
44       break;
45     case BG_PARAMETER_STRING:
46     case BG_PARAMETER_STRING_HIDDEN:
47     case BG_PARAMETER_FONT:
48     case BG_PARAMETER_DEVICE:
49     case BG_PARAMETER_FILE:
50     case BG_PARAMETER_DIRECTORY:
51     case BG_PARAMETER_STRINGLIST:
52     case BG_PARAMETER_MULTI_MENU:
53     case BG_PARAMETER_MULTI_LIST:
54     case BG_PARAMETER_MULTI_CHAIN:
55       dst->val_str = bg_strdup(dst->val_str, src->val_str);
56       break;
57     case BG_PARAMETER_COLOR_RGB:
58       memcpy(dst->val_color,
59              src->val_color,
60              3 * sizeof(dst->val_color[0]));
61       dst->val_color[3] = 1.0;
62       break;
63     case BG_PARAMETER_COLOR_RGBA:
64       memcpy(dst->val_color,
65              src->val_color,
66              4 * sizeof(dst->val_color[0]));
67       break;
68     case BG_PARAMETER_POSITION:
69       memcpy(dst->val_pos,
70              src->val_pos,
71              2 * sizeof(dst->val_pos[0]));
72       break;
73     case BG_PARAMETER_TIME:
74       dst->val_time = src->val_time;
75       break;
76     case BG_PARAMETER_SECTION:
77     case BG_PARAMETER_BUTTON:
78       break;
79     }
80   }
81 
bg_parameter_value_free(bg_parameter_value_t * val,bg_parameter_type_t type)82 void bg_parameter_value_free(bg_parameter_value_t * val,
83                              bg_parameter_type_t type)
84   {
85   switch(type)
86     {
87     case BG_PARAMETER_CHECKBUTTON:
88     case BG_PARAMETER_INT:
89     case BG_PARAMETER_SLIDER_INT:
90     case BG_PARAMETER_FLOAT:
91     case BG_PARAMETER_SLIDER_FLOAT:
92     case BG_PARAMETER_TIME:
93     case BG_PARAMETER_SECTION:
94     case BG_PARAMETER_COLOR_RGB:
95     case BG_PARAMETER_COLOR_RGBA:
96     case BG_PARAMETER_POSITION:
97     case BG_PARAMETER_BUTTON:
98       break;
99     case BG_PARAMETER_STRING:
100     case BG_PARAMETER_STRING_HIDDEN:
101     case BG_PARAMETER_FONT:
102     case BG_PARAMETER_DEVICE:
103     case BG_PARAMETER_FILE:
104     case BG_PARAMETER_DIRECTORY:
105     case BG_PARAMETER_STRINGLIST:
106     case BG_PARAMETER_MULTI_MENU:
107     case BG_PARAMETER_MULTI_LIST:
108     case BG_PARAMETER_MULTI_CHAIN:
109       if(val->val_str)
110         free(val->val_str);
111       break;
112     }
113 
114   }
115 
copy_string_array(char const * const * arr)116 static char ** copy_string_array(char const * const * arr)
117   {
118   int i, num;
119   char ** ret;
120   if(!arr)
121     return NULL;
122 
123   num = 0;
124   while(arr[num])
125     num++;
126 
127   ret = calloc(num+1, sizeof(*ret));
128 
129   for(i = 0; i < num; i++)
130     ret[i] = bg_strdup(ret[i], arr[i]);
131   return ret;
132   }
133 
free_string_array(char ** arr)134 static void free_string_array(char ** arr)
135   {
136   int i = 0;
137   if(!arr)
138     return;
139 
140   while(arr[i])
141     {
142     free(arr[i]);
143     i++;
144     }
145   free(arr);
146   }
147 
bg_parameter_info_copy(bg_parameter_info_t * dst,const bg_parameter_info_t * src)148 void bg_parameter_info_copy(bg_parameter_info_t * dst,
149                             const bg_parameter_info_t * src)
150   {
151   int num_options, i;
152 
153   dst->name = bg_strdup(dst->name, src->name);
154 
155   dst->long_name = bg_strdup(dst->long_name, src->long_name);
156   dst->opt = bg_strdup(dst->opt, src->opt);
157   dst->help_string = bg_strdup(dst->help_string, src->help_string);
158   dst->type = src->type;
159   dst->flags = src->flags;
160 
161   dst->gettext_domain    = bg_strdup(dst->gettext_domain,    src->gettext_domain);
162   dst->gettext_directory = bg_strdup(dst->gettext_directory, src->gettext_directory);
163   dst->preset_path       = bg_strdup(dst->preset_path,       src->preset_path);
164 
165   switch(dst->type)
166     {
167     case BG_PARAMETER_CHECKBUTTON:
168       dst->val_default.val_i = src->val_default.val_i;
169       break;
170     case BG_PARAMETER_INT:
171     case BG_PARAMETER_SLIDER_INT:
172       dst->val_default.val_i = src->val_default.val_i;
173       dst->val_min.val_i     = src->val_min.val_i;
174       dst->val_max.val_i     = src->val_max.val_i;
175       break;
176     case BG_PARAMETER_FLOAT:
177     case BG_PARAMETER_SLIDER_FLOAT:
178       dst->val_default.val_f = src->val_default.val_f;
179       dst->val_min.val_f     = src->val_min.val_f;
180       dst->val_max.val_f     = src->val_max.val_f;
181       dst->num_digits        = src->num_digits;
182       break;
183     case BG_PARAMETER_STRING:
184     case BG_PARAMETER_STRING_HIDDEN:
185     case BG_PARAMETER_FONT:
186     case BG_PARAMETER_DEVICE:
187     case BG_PARAMETER_FILE:
188     case BG_PARAMETER_DIRECTORY:
189       dst->val_default.val_str = bg_strdup(dst->val_default.val_str,
190                                            src->val_default.val_str);
191       break;
192     case BG_PARAMETER_MULTI_MENU:
193     case BG_PARAMETER_MULTI_LIST:
194     case BG_PARAMETER_MULTI_CHAIN:
195       dst->val_default.val_str = bg_strdup(dst->val_default.val_str,
196                                            src->val_default.val_str);
197 
198       dst->multi_names_nc        = copy_string_array(src->multi_names);
199       dst->multi_labels_nc       = copy_string_array(src->multi_labels);
200       dst->multi_descriptions_nc = copy_string_array(src->multi_descriptions);
201 
202       i = 0;
203 
204       if(src->multi_names)
205         {
206         num_options = 0;
207 
208         while(src->multi_names[num_options])
209           num_options++;
210 
211         if(src->multi_parameters)
212           {
213           dst->multi_parameters_nc =
214             calloc(num_options, sizeof(*(src->multi_parameters_nc)));
215           i = 0;
216 
217           while(src->multi_names[i])
218             {
219             if(src->multi_parameters[i])
220               dst->multi_parameters_nc[i] =
221                 bg_parameter_info_copy_array(src->multi_parameters[i]);
222             i++;
223             }
224           }
225         }
226       break;
227     case BG_PARAMETER_STRINGLIST:
228       dst->val_default.val_str = bg_strdup(dst->val_default.val_str,
229                                            src->val_default.val_str);
230 
231       /* Copy stringlist options */
232 
233       if(src->multi_names)
234         dst->multi_names_nc = copy_string_array(src->multi_names);
235       if(src->multi_labels)
236         dst->multi_labels_nc = copy_string_array(src->multi_labels);
237       dst->multi_names = (char const **)dst->multi_names_nc;
238       dst->multi_labels = (char const **)dst->multi_labels_nc;
239       break;
240     case BG_PARAMETER_COLOR_RGB:
241       if(src->val_default.val_color)
242         {
243         memcpy(dst->val_default.val_color,
244                src->val_default.val_color,
245                3 * sizeof(dst->val_default.val_color[0]));
246         dst->val_default.val_color[3] = 1.0;
247         }
248       break;
249     case BG_PARAMETER_COLOR_RGBA:
250       if(src->val_default.val_color)
251         {
252         memcpy(dst->val_default.val_color,
253                src->val_default.val_color,
254                4 * sizeof(dst->val_default.val_color[0]));
255         }
256       break;
257     case BG_PARAMETER_POSITION:
258       if(src->val_default.val_color)
259         {
260         memcpy(dst->val_default.val_pos,
261                src->val_default.val_pos,
262                2 * sizeof(dst->val_default.val_pos[0]));
263         }
264       dst->num_digits        = src->num_digits;
265       break;
266     case BG_PARAMETER_TIME:
267       dst->val_default.val_time = src->val_default.val_time;
268       break;
269     case BG_PARAMETER_SECTION:
270     case BG_PARAMETER_BUTTON:
271       break;
272     }
273   bg_parameter_info_set_const_ptrs(dst);
274 
275   }
276 
277 bg_parameter_info_t *
bg_parameter_info_copy_array(const bg_parameter_info_t * src)278 bg_parameter_info_copy_array(const bg_parameter_info_t * src)
279   {
280   int num_parameters, i;
281   bg_parameter_info_t * ret;
282 
283   num_parameters = 0;
284 
285   while(src[num_parameters].name)
286     num_parameters++;
287 
288   ret = calloc(num_parameters + 1, sizeof(bg_parameter_info_t));
289 
290   for(i = 0; i < num_parameters; i++)
291     bg_parameter_info_copy(&ret[i], &src[i]);
292 
293   return ret;
294   }
295 
bg_parameter_info_destroy_array(bg_parameter_info_t * info)296 void bg_parameter_info_destroy_array(bg_parameter_info_t * info)
297   {
298   int index = 0;
299   int i;
300   while(info[index].name)
301     {
302     free(info[index].name);
303     if(info[index].long_name)
304       free(info[index].long_name);
305     if(info[index].opt)
306       free(info[index].opt);
307     if(info[index].help_string)
308       free(info[index].help_string);
309     if(info[index].gettext_domain)
310       free(info[index].gettext_domain);
311     if(info[index].gettext_directory)
312       free(info[index].gettext_directory);
313     if(info[index].preset_path)
314       free(info[index].preset_path);
315     switch(info[index].type)
316       {
317       case BG_PARAMETER_STRINGLIST:
318         free_string_array(info[index].multi_names_nc);
319         free_string_array(info[index].multi_labels_nc);
320 
321         if(info[index].val_default.val_str)
322           free(info[index].val_default.val_str);
323         break;
324       case BG_PARAMETER_STRING:
325       case BG_PARAMETER_STRING_HIDDEN:
326       case BG_PARAMETER_FONT:
327       case BG_PARAMETER_DEVICE:
328       case BG_PARAMETER_FILE:
329       case BG_PARAMETER_DIRECTORY:
330         if(info[index].val_default.val_str)
331           free(info[index].val_default.val_str);
332         break;
333       case BG_PARAMETER_SECTION:
334       case BG_PARAMETER_BUTTON:
335       case BG_PARAMETER_CHECKBUTTON:
336       case BG_PARAMETER_INT:
337       case BG_PARAMETER_FLOAT:
338       case BG_PARAMETER_TIME:
339       case BG_PARAMETER_SLIDER_INT:
340       case BG_PARAMETER_SLIDER_FLOAT:
341       case BG_PARAMETER_COLOR_RGB:
342       case BG_PARAMETER_COLOR_RGBA:
343       case BG_PARAMETER_POSITION:
344         break;
345       case BG_PARAMETER_MULTI_MENU:
346       case BG_PARAMETER_MULTI_LIST:
347       case BG_PARAMETER_MULTI_CHAIN:
348         i = 0;
349 
350         if(info[index].multi_parameters)
351           {
352           while(info[index].multi_names[i])
353             {
354             if(info[index].multi_parameters[i])
355               bg_parameter_info_destroy_array(info[index].multi_parameters_nc[i]);
356             i++;
357             }
358           free(info[index].multi_parameters_nc);
359           }
360 
361         free_string_array(info[index].multi_names_nc);
362         free_string_array(info[index].multi_labels_nc);
363         free_string_array(info[index].multi_descriptions_nc);
364 
365         if(info[index].val_default.val_str)
366           free(info[index].val_default.val_str);
367 
368 
369       }
370     index++;
371     }
372   free(info);
373   }
374 
375 bg_parameter_info_t *
bg_parameter_info_concat_arrays(bg_parameter_info_t const ** srcs)376 bg_parameter_info_concat_arrays(bg_parameter_info_t const ** srcs)
377   {
378   int i, j, dst, num_parameters;
379 
380   bg_parameter_info_t * ret;
381 
382   /* Count the parameters */
383   num_parameters = 0;
384   i = 0;
385 
386   while(srcs[i])
387     {
388     j = 0;
389     while(srcs[i][j].name)
390       {
391       num_parameters++;
392       j++;
393       }
394     i++;
395     }
396 
397   /* Allocate destination */
398 
399   ret = calloc(num_parameters+1, sizeof(*ret));
400 
401   /* Copy stuff */
402 
403   i = 0;
404   dst = 0;
405 
406   while(srcs[i])
407     {
408     j = 0;
409     while(srcs[i][j].name)
410       {
411       bg_parameter_info_copy(&ret[dst], &srcs[i][j]);
412       dst++;
413       j++;
414       }
415     i++;
416     }
417   return ret;
418   }
419 
bg_parameter_get_selected(const bg_parameter_info_t * info,const char * val)420 int bg_parameter_get_selected(const bg_parameter_info_t * info,
421                               const char * val)
422   {
423   int ret = -1, i;
424 
425   if(val)
426     {
427     i = 0;
428     while(info->multi_names[i])
429       {
430       if(!strcmp(val, info->multi_names[i]))
431         {
432         ret = i;
433         break;
434         }
435       i++;
436       }
437     }
438 
439   if((ret < 0) && info->val_default.val_str)
440     {
441     i = 0;
442     /* Try default value */
443     while(info->multi_names[i])
444       {
445       if(!strcmp(info->val_default.val_str, info->multi_names[i]))
446         {
447         ret = i;
448         break;
449         }
450       i++;
451       }
452     }
453 
454   if(ret < 0)
455     return 0;
456   else
457     return ret;
458   }
459 
460 const bg_parameter_info_t *
bg_parameter_find(const bg_parameter_info_t * info,const char * name)461 bg_parameter_find(const bg_parameter_info_t * info,
462                   const char * name)
463   {
464   int i, j;
465   const bg_parameter_info_t * child_ret;
466   i = 0;
467   while(info[i].name)
468     {
469     if(!strcmp(name, info[i].name))
470       return &info[i];
471 
472     if(info[i].multi_parameters && info[i].multi_names)
473       {
474       j = 0;
475       while(info[i].multi_names[j])
476         {
477         if(info[i].multi_parameters[j])
478           {
479           child_ret = bg_parameter_find(info[i].multi_parameters[j], name);
480           if(child_ret)
481             return child_ret;
482           }
483         j++;
484         }
485       }
486     i++;
487     }
488   return NULL;
489   }
490 
bg_parameter_info_set_const_ptrs(bg_parameter_info_t * ret)491 void bg_parameter_info_set_const_ptrs(bg_parameter_info_t * ret)
492   {
493   ret->multi_names = (char const **)ret->multi_names_nc;
494   ret->multi_labels = (char const **)ret->multi_labels_nc;
495   ret->multi_descriptions = (char const **)ret->multi_descriptions_nc;
496   ret->multi_parameters =
497     (bg_parameter_info_t const * const *)ret->multi_parameters_nc;
498   }
499 
500