Add voice index parameter to zyn_addsynth_get_global_component()
[zyn.git] / zynadd_dynparam.c
blob7c94e2321815e8252b70c484f0b2e08ab7290c2e
1 /* -*- Mode: C ; c-basic-offset: 2 -*- */
2 /*****************************************************************************
4 * Copyright (C) 2006,2007,2008,2009 Nedko Arnaudov <nedko@arnaudov.name>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
19 *****************************************************************************/
21 #include <assert.h>
22 #include <stdarg.h>
23 #include <stdlib.h>
24 #include <stdbool.h>
25 #include <lv2.h>
27 #include "common.h"
28 #include "addsynth.h"
29 #include "lv2dynparam/lv2dynparam.h"
30 #include "lv2dynparam/plugin.h"
31 #include "list.h"
32 #include "zynadd_internal.h"
33 #include "zynadd_dynparam_value_changed_callbacks.h"
34 #include "zynadd_dynparam_forest_map_top.h"
35 #include "zynadd_dynparam_forest_map_voice.h"
37 #define LOG_LEVEL LOG_LEVEL_ERROR
38 #include "log.h"
40 bool
41 zynadd_appear_parameter(
42 struct zynadd * zynadd_ptr,
43 struct zynadd_parameter * parameter_ptr)
45 lv2dynparam_plugin_group parent_group;
47 LOG_DEBUG(
48 "Appearing parameter \"%s\"/\"%s\" -> %u",
49 parameter_ptr->parent_ptr ? parameter_ptr->parent_ptr->name_ptr : "",
50 parameter_ptr->name_ptr,
51 parameter_ptr->addsynth_parameter);
53 if (parameter_ptr->parent_ptr == NULL)
55 parent_group = NULL;
57 else
59 parent_group = parameter_ptr->parent_ptr->lv2group;
62 switch (parameter_ptr->type)
64 case LV2DYNPARAM_PARAMETER_TYPE_BOOL:
65 if (!lv2dynparam_plugin_param_boolean_add(
66 zynadd_ptr->dynparams,
67 parent_group,
68 parameter_ptr->name_ptr,
69 parameter_ptr->hints_ptr,
70 zyn_addsynth_get_bool_parameter(
71 parameter_ptr->addsynth_component,
72 parameter_ptr->addsynth_parameter),
73 zynadd_bool_parameter_changed,
74 parameter_ptr,
75 &parameter_ptr->lv2parameter))
77 return false;
80 return true;
82 case LV2DYNPARAM_PARAMETER_TYPE_FLOAT:
83 if (!lv2dynparam_plugin_param_float_add(
84 zynadd_ptr->dynparams,
85 parent_group,
86 parameter_ptr->name_ptr,
87 parameter_ptr->hints_ptr,
88 zyn_addsynth_get_float_parameter(
89 parameter_ptr->addsynth_component,
90 parameter_ptr->addsynth_parameter),
91 parameter_ptr->map_element_ptr->min.fpoint,
92 parameter_ptr->map_element_ptr->max.fpoint,
93 zynadd_float_parameter_changed,
94 parameter_ptr,
95 &parameter_ptr->lv2parameter))
97 return false;
100 return true;
102 case LV2DYNPARAM_PARAMETER_TYPE_INT:
103 if (!lv2dynparam_plugin_param_int_add(
104 zynadd_ptr->dynparams,
105 parent_group,
106 parameter_ptr->name_ptr,
107 parameter_ptr->hints_ptr,
108 zyn_addsynth_get_int_parameter(
109 parameter_ptr->addsynth_component,
110 parameter_ptr->addsynth_parameter),
111 parameter_ptr->map_element_ptr->min.integer,
112 parameter_ptr->map_element_ptr->max.integer,
113 zynadd_int_parameter_changed,
114 parameter_ptr,
115 &parameter_ptr->lv2parameter))
117 return false;
120 return true;
122 case LV2DYNPARAM_PARAMETER_TYPE_ENUM:
123 if (!lv2dynparam_plugin_param_enum_add(
124 zynadd_ptr->dynparams,
125 parent_group,
126 parameter_ptr->name_ptr,
127 parameter_ptr->hints_ptr,
128 parameter_ptr->map_element_ptr->min.enum_values,
129 parameter_ptr->map_element_ptr->max.enum_values_count,
130 zyn_addsynth_get_int_parameter(
131 parameter_ptr->addsynth_component,
132 parameter_ptr->addsynth_parameter),
133 zynadd_enum_parameter_changed,
134 parameter_ptr,
135 &parameter_ptr->lv2parameter))
137 LOG_ERROR("lv2dynparam_plugin_param_enum_add() failed.");
138 return false;
141 return true;
144 assert(0);
145 return false;
148 /* create forest groups and parameters without exposing them */
149 bool
150 zynadd_dynparam_forest_initializer_prepare(
151 struct zyn_forest_initializer * forest_ptr,
152 struct zyn_forest_map * map_ptr,
153 struct zynadd_group * root_group_ptr,
154 zyn_addsynth_component * forest_components_array,
155 struct zynadd * zynadd_ptr,
156 struct list_head * groups_list_ptr,
157 struct list_head * parameters_list_ptr)
159 int i;
160 struct zynadd_group * group_ptr;
161 struct zynadd_parameter * parameter_ptr;
163 LOG_DEBUG("Preparing forest with root \"%s\"/", root_group_ptr == NULL ? "" : root_group_ptr->name_ptr);
165 forest_ptr->map_ptr = map_ptr;
167 forest_ptr->groups_count = map_ptr->groups_count;
168 forest_ptr->parameters_count = map_ptr->parameters_count;
170 forest_ptr->groups = malloc(sizeof(struct zynadd_group *) * forest_ptr->groups_count);
171 if (forest_ptr->groups == NULL)
173 goto fail;
176 forest_ptr->parameters = malloc(sizeof(struct zynadd_parameter *) * forest_ptr->parameters_count);
177 if (forest_ptr->parameters == NULL)
179 goto fail_free_groups_array;
182 for (i = 0 ; i < forest_ptr->groups_count ; i++)
184 LOG_DEBUG("Preparing group \"%s\"", forest_ptr->map_ptr->groups[i].name);
186 group_ptr = malloc(sizeof(struct zynadd_group));
187 if (group_ptr == NULL)
189 goto fail_free_parameters_array;
192 group_ptr->name_ptr = forest_ptr->map_ptr->groups[i].name;
193 group_ptr->hints_ptr = &forest_ptr->map_ptr->groups[i].hints;
194 group_ptr->lv2group = NULL;
196 if (forest_ptr->map_ptr->groups[i].parent == LV2DYNPARAM_GROUP_ROOT)
198 group_ptr->parent_ptr = root_group_ptr;
200 else
202 group_ptr->parent_ptr = forest_ptr->groups[forest_ptr->map_ptr->groups[i].parent];
205 forest_ptr->groups[i] = group_ptr;
207 list_add_tail(&group_ptr->siblings, groups_list_ptr);
210 for (i = 0 ; i < forest_ptr->parameters_count ; i++)
212 LOG_DEBUG(
213 "Preparing parameter \"%s\"/\"%s\"",
214 forest_ptr->map_ptr->parameters[i].parent == LV2DYNPARAM_GROUP_ROOT ?
215 (root_group_ptr == NULL ?
216 "" :
217 root_group_ptr->name_ptr) :
218 forest_ptr->groups[forest_ptr->map_ptr->parameters[i].parent]->name_ptr,
219 forest_ptr->map_ptr->parameters[i].name);
221 parameter_ptr = malloc(sizeof(struct zynadd_parameter));
222 if (parameter_ptr == NULL)
224 goto fail_free_parameters_array;
227 if (forest_ptr->map_ptr->parameters[i].parent == LV2DYNPARAM_GROUP_ROOT)
229 parameter_ptr->parent_ptr = root_group_ptr;
231 else
233 parameter_ptr->parent_ptr = forest_ptr->groups[forest_ptr->map_ptr->parameters[i].parent];
236 forest_ptr->parameters[i] = parameter_ptr;
238 parameter_ptr->synth_ptr = zynadd_ptr;
239 parameter_ptr->addsynth_parameter = forest_ptr->map_ptr->parameters[i].addsynth_parameter;
240 parameter_ptr->addsynth_component = forest_components_array[forest_ptr->map_ptr->parameters[i].addsynth_component];
241 parameter_ptr->scope = forest_ptr->map_ptr->parameters[i].scope;
242 parameter_ptr->other_parameter = NULL;
243 parameter_ptr->lv2parameter = NULL;
244 parameter_ptr->name_ptr = forest_ptr->map_ptr->parameters[i].name;
245 parameter_ptr->type = forest_ptr->map_ptr->parameters[i].type;
246 parameter_ptr->hints_ptr = &forest_ptr->map_ptr->parameters[i].hints;
247 parameter_ptr->map_element_ptr = forest_ptr->map_ptr->parameters + i;
249 list_add_tail(&parameter_ptr->siblings, parameters_list_ptr);
252 /* set other_parameter when needed */
253 for (i = 0 ; i < forest_ptr->parameters_count ; i++)
255 if (forest_ptr->map_ptr->parameters[i].scope == LV2DYNPARAM_PARAMETER_SCOPE_TYPE_HIDE_OTHER ||
256 forest_ptr->map_ptr->parameters[i].scope == LV2DYNPARAM_PARAMETER_SCOPE_TYPE_SHOW_OTHER)
258 forest_ptr->parameters[i]->other_parameter = forest_ptr->parameters[forest_ptr->map_ptr->parameters[i].scope_specific];
262 return true;
264 fail_free_parameters_array:
265 free(forest_ptr->parameters);
267 fail_free_groups_array:
268 free(forest_ptr->groups);
270 fail:
271 return false;
274 void
275 zynadd_dynparam_forest_initializer_clear(
276 struct zyn_forest_initializer * forest_ptr)
278 free(forest_ptr->groups);
279 free(forest_ptr->parameters);
282 void
283 zynadd_dynparam_destroy_forests(
284 struct zynadd * zynadd_ptr)
286 struct list_head * node_ptr;
287 struct zynadd_group * group_ptr;
288 struct zynadd_parameter * parameter_ptr;
290 while (!list_empty(&zynadd_ptr->parameters))
292 node_ptr = zynadd_ptr->parameters.next;
293 parameter_ptr = list_entry(node_ptr, struct zynadd_parameter, siblings);
294 list_del(node_ptr);
295 free(parameter_ptr);
298 while (!list_empty(&zynadd_ptr->groups))
300 node_ptr = zynadd_ptr->groups.next;
301 group_ptr = list_entry(node_ptr, struct zynadd_group, siblings);
302 list_del(node_ptr);
303 free(group_ptr);
307 bool
308 zynadd_dynparam_forests_appear(
309 struct zynadd * zynadd_ptr)
311 bool tmp_bool;
312 struct zynadd_group * group_ptr;
313 struct zynadd_parameter * parameter_ptr;
314 struct list_head * node_ptr;
316 list_for_each(node_ptr, &zynadd_ptr->groups)
318 group_ptr = list_entry(node_ptr, struct zynadd_group, siblings);
320 LOG_DEBUG("Adding group \"%s\"", group_ptr->name_ptr);
322 if (!lv2dynparam_plugin_group_add(
323 zynadd_ptr->dynparams,
324 group_ptr->parent_ptr == NULL ? NULL : group_ptr->parent_ptr->lv2group,
325 group_ptr->name_ptr,
326 group_ptr->hints_ptr,
327 &group_ptr->lv2group))
329 return false;
333 list_for_each(node_ptr, &zynadd_ptr->parameters)
335 parameter_ptr = list_entry(node_ptr, struct zynadd_parameter, siblings);
337 LOG_DEBUG("Adding parameter \"%s\"", parameter_ptr->name_ptr);
339 if (parameter_ptr->scope == LV2DYNPARAM_PARAMETER_SCOPE_TYPE_SEMI)
341 continue;
344 if (parameter_ptr->scope == LV2DYNPARAM_PARAMETER_SCOPE_TYPE_HIDE_OTHER ||
345 parameter_ptr->scope == LV2DYNPARAM_PARAMETER_SCOPE_TYPE_SHOW_OTHER)
347 LOG_DEBUG("Apearing show/hide parameter \"%s\"", parameter_ptr->name_ptr);
348 assert(parameter_ptr->type == LV2DYNPARAM_PARAMETER_TYPE_BOOL);
350 tmp_bool = zyn_addsynth_get_bool_parameter(
351 parameter_ptr->addsynth_component,
352 parameter_ptr->addsynth_parameter);
354 if (!zynadd_appear_parameter(zynadd_ptr, parameter_ptr))
356 return false;
359 if ((parameter_ptr->scope == LV2DYNPARAM_PARAMETER_SCOPE_TYPE_HIDE_OTHER && !tmp_bool) ||
360 (parameter_ptr->scope == LV2DYNPARAM_PARAMETER_SCOPE_TYPE_SHOW_OTHER && tmp_bool))
362 LOG_DEBUG("Apearing semi parameter \"%s\"", parameter_ptr->other_parameter->name_ptr);
363 if (!zynadd_appear_parameter(zynadd_ptr, parameter_ptr->other_parameter))
365 return false;
369 continue;
372 assert(parameter_ptr->scope == LV2DYNPARAM_PARAMETER_SCOPE_TYPE_ALWAYS);
374 if (!zynadd_appear_parameter(zynadd_ptr, parameter_ptr))
376 LOG_ERROR("zynadd_appear_parameter() failed.");
377 return false;
381 return true;
384 bool
385 zynadd_dynparam_init(
386 struct zynadd * zynadd_ptr)
388 struct zyn_forest_initializer top_forest_initializer;
389 struct zyn_forest_initializer voice_forest_initializer;
390 unsigned int i;
392 INIT_LIST_HEAD(&zynadd_ptr->groups);
393 INIT_LIST_HEAD(&zynadd_ptr->parameters);
395 for (i = 0 ; i < ZYNADD_GLOBAL_COMPONENTS_COUNT ; i++)
397 zynadd_ptr->synth_global_components[i] = zyn_addsynth_get_global_component(zynadd_ptr->synth, i);
400 for (i = 0 ; i < ZYNADD_VOICE_COMPONENTS_COUNT ; i++)
402 zynadd_ptr->synth_voice0_components[i] = zyn_addsynth_get_voice_component(zynadd_ptr->synth, 0, i);
403 //LOG_DEBUG("Voice component %p", zynadd_ptr->synth_voice0_components[i]);
406 LOG_DEBUG("Preparing top forest...");
408 if (!zynadd_dynparam_forest_initializer_prepare(
409 &top_forest_initializer,
410 &g_top_forest_map,
411 NULL,
412 zynadd_ptr->synth_global_components,
413 zynadd_ptr,
414 &zynadd_ptr->groups,
415 &zynadd_ptr->parameters))
417 goto fail_destroy_forests;
420 LOG_DEBUG("Preparing voice forest...");
422 if (!zynadd_dynparam_forest_initializer_prepare(
423 &voice_forest_initializer,
424 &g_voice_forest_map,
425 top_forest_initializer.groups[zynadd_top_forest_map_get_voices_group()],
426 zynadd_ptr->synth_voice0_components,
427 zynadd_ptr,
428 &zynadd_ptr->groups,
429 &zynadd_ptr->parameters))
431 goto fail_clear_top_forest_initializer;
434 if (!lv2dynparam_plugin_instantiate(
435 (LV2_Handle)zynadd_ptr,
436 zynadd_ptr->host_features,
437 "zynadd",
438 &zynadd_ptr->dynparams))
440 goto fail_clear_voice_forest_initializer;
443 if (!zynadd_dynparam_forests_appear(zynadd_ptr))
445 goto fail_clean_dynparams;
448 zynadd_dynparam_forest_initializer_clear(&voice_forest_initializer);
449 zynadd_dynparam_forest_initializer_clear(&top_forest_initializer);
451 return true;
453 fail_clean_dynparams:
454 zynadd_dynparam_uninit(zynadd_ptr);
456 fail_clear_voice_forest_initializer:
457 zynadd_dynparam_forest_initializer_clear(&voice_forest_initializer);
459 fail_clear_top_forest_initializer:
460 zynadd_dynparam_forest_initializer_clear(&top_forest_initializer);
462 fail_destroy_forests:
463 zynadd_dynparam_destroy_forests(zynadd_ptr);
465 return false;
468 void
469 zynadd_dynparam_uninit(struct zynadd * zynadd_ptr)
471 zynadd_dynparam_destroy_forests(zynadd_ptr);
473 lv2dynparam_plugin_cleanup(zynadd_ptr->dynparams);