Expose voice detune parameter of the lv2 plugin
[zyn.git] / zynadd_dynparam.c
blobddd0db505c7c6aa2a28eb0b9778379689b77ba8b
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 <stdio.h>
25 #include <stdbool.h>
26 #include <lv2.h>
28 #include "common.h"
29 #include "addsynth.h"
30 #include "lv2dynparam/lv2dynparam.h"
31 #include "lv2dynparam/plugin.h"
32 #include "list.h"
33 #include "zynadd_internal.h"
34 #include "zynadd_dynparam_value_changed_callbacks.h"
35 #include "zynadd_dynparam_forest_map_top.h"
36 #include "zynadd_dynparam_forest_map_voice.h"
38 #define LOG_LEVEL LOG_LEVEL_ERROR
39 #include "log.h"
41 bool
42 zynadd_appear_parameter(
43 struct zynadd * zynadd_ptr,
44 struct zynadd_parameter * parameter_ptr)
46 lv2dynparam_plugin_group parent_group;
48 LOG_DEBUG(
49 "Appearing parameter \"%s\"/\"%s\" -> %p:%u",
50 parameter_ptr->parent_ptr ? parameter_ptr->parent_ptr->name_ptr : "",
51 parameter_ptr->name_ptr,
52 parameter_ptr->addsynth_component,
53 parameter_ptr->addsynth_parameter);
55 if (parameter_ptr->parent_ptr == NULL)
57 parent_group = NULL;
59 else
61 parent_group = parameter_ptr->parent_ptr->lv2group;
64 switch (parameter_ptr->type)
66 case LV2DYNPARAM_PARAMETER_TYPE_BOOL:
67 if (!lv2dynparam_plugin_param_boolean_add(
68 zynadd_ptr->dynparams,
69 parent_group,
70 parameter_ptr->name_ptr,
71 parameter_ptr->hints_ptr,
72 zyn_addsynth_get_bool_parameter(
73 parameter_ptr->addsynth_component,
74 parameter_ptr->addsynth_parameter),
75 zynadd_bool_parameter_changed,
76 parameter_ptr,
77 &parameter_ptr->lv2parameter))
79 return false;
82 return true;
84 case LV2DYNPARAM_PARAMETER_TYPE_FLOAT:
85 if (!lv2dynparam_plugin_param_float_add(
86 zynadd_ptr->dynparams,
87 parent_group,
88 parameter_ptr->name_ptr,
89 parameter_ptr->hints_ptr,
90 zyn_addsynth_get_float_parameter(
91 parameter_ptr->addsynth_component,
92 parameter_ptr->addsynth_parameter),
93 parameter_ptr->map_element_ptr->min.fpoint,
94 parameter_ptr->map_element_ptr->max.fpoint,
95 zynadd_float_parameter_changed,
96 parameter_ptr,
97 &parameter_ptr->lv2parameter))
99 return false;
102 return true;
104 case LV2DYNPARAM_PARAMETER_TYPE_INT:
105 if (!lv2dynparam_plugin_param_int_add(
106 zynadd_ptr->dynparams,
107 parent_group,
108 parameter_ptr->name_ptr,
109 parameter_ptr->hints_ptr,
110 zyn_addsynth_get_int_parameter(
111 parameter_ptr->addsynth_component,
112 parameter_ptr->addsynth_parameter),
113 parameter_ptr->map_element_ptr->min.integer,
114 parameter_ptr->map_element_ptr->max.integer,
115 zynadd_int_parameter_changed,
116 parameter_ptr,
117 &parameter_ptr->lv2parameter))
119 return false;
122 return true;
124 case LV2DYNPARAM_PARAMETER_TYPE_ENUM:
125 if (!lv2dynparam_plugin_param_enum_add(
126 zynadd_ptr->dynparams,
127 parent_group,
128 parameter_ptr->name_ptr,
129 parameter_ptr->hints_ptr,
130 parameter_ptr->map_element_ptr->min.enum_values,
131 parameter_ptr->map_element_ptr->max.enum_values_count,
132 zyn_addsynth_get_int_parameter(
133 parameter_ptr->addsynth_component,
134 parameter_ptr->addsynth_parameter),
135 zynadd_enum_parameter_changed,
136 parameter_ptr,
137 &parameter_ptr->lv2parameter))
139 LOG_ERROR("lv2dynparam_plugin_param_enum_add() failed.");
140 return false;
143 return true;
146 assert(0);
147 return false;
150 /* create forest groups and parameters without exposing them */
151 bool
152 zynadd_dynparam_forest_initializer_prepare(
153 struct zyn_forest_initializer * forest_ptr,
154 struct zyn_forest_map * map_ptr,
155 struct zynadd_group * root_group_ptr,
156 zyn_addsynth_component * forest_components_array,
157 struct zynadd * zynadd_ptr,
158 struct list_head * groups_list_ptr,
159 struct list_head * parameters_list_ptr)
161 int i;
162 struct zynadd_group * group_ptr;
163 struct zynadd_parameter * parameter_ptr;
165 LOG_DEBUG("Preparing forest with root \"%s\"/", root_group_ptr == NULL ? "" : root_group_ptr->name_ptr);
167 forest_ptr->map_ptr = map_ptr;
169 forest_ptr->groups_count = map_ptr->groups_count;
170 forest_ptr->parameters_count = map_ptr->parameters_count;
172 forest_ptr->groups = malloc(sizeof(struct zynadd_group *) * forest_ptr->groups_count);
173 if (forest_ptr->groups == NULL)
175 goto fail;
178 forest_ptr->parameters = malloc(sizeof(struct zynadd_parameter *) * forest_ptr->parameters_count);
179 if (forest_ptr->parameters == NULL)
181 goto fail_free_groups_array;
184 for (i = 0 ; i < forest_ptr->groups_count ; i++)
186 LOG_DEBUG("Preparing group \"%s\"", forest_ptr->map_ptr->groups[i].name);
188 group_ptr = malloc(sizeof(struct zynadd_group));
189 if (group_ptr == NULL)
191 goto fail_free_parameters_array;
194 group_ptr->name_ptr = forest_ptr->map_ptr->groups[i].name;
195 group_ptr->hints_ptr = &forest_ptr->map_ptr->groups[i].hints;
196 group_ptr->lv2group = NULL;
198 if (forest_ptr->map_ptr->groups[i].parent == LV2DYNPARAM_GROUP_ROOT)
200 group_ptr->parent_ptr = root_group_ptr;
202 else
204 group_ptr->parent_ptr = forest_ptr->groups[forest_ptr->map_ptr->groups[i].parent];
207 forest_ptr->groups[i] = group_ptr;
209 list_add_tail(&group_ptr->siblings, groups_list_ptr);
212 for (i = 0 ; i < forest_ptr->parameters_count ; i++)
214 LOG_DEBUG(
215 "Preparing parameter \"%s\"/\"%s\"",
216 forest_ptr->map_ptr->parameters[i].parent == LV2DYNPARAM_GROUP_ROOT ?
217 (root_group_ptr == NULL ?
218 "" :
219 root_group_ptr->name_ptr) :
220 forest_ptr->groups[forest_ptr->map_ptr->parameters[i].parent]->name_ptr,
221 forest_ptr->map_ptr->parameters[i].name);
223 parameter_ptr = malloc(sizeof(struct zynadd_parameter));
224 if (parameter_ptr == NULL)
226 goto fail_free_parameters_array;
229 if (forest_ptr->map_ptr->parameters[i].parent == LV2DYNPARAM_GROUP_ROOT)
231 parameter_ptr->parent_ptr = root_group_ptr;
233 else
235 parameter_ptr->parent_ptr = forest_ptr->groups[forest_ptr->map_ptr->parameters[i].parent];
238 forest_ptr->parameters[i] = parameter_ptr;
240 parameter_ptr->synth_ptr = zynadd_ptr;
241 parameter_ptr->addsynth_parameter = forest_ptr->map_ptr->parameters[i].addsynth_parameter;
242 parameter_ptr->addsynth_component = forest_components_array[forest_ptr->map_ptr->parameters[i].addsynth_component];
243 parameter_ptr->scope = forest_ptr->map_ptr->parameters[i].scope;
244 parameter_ptr->other_parameter = NULL;
245 parameter_ptr->lv2parameter = NULL;
246 parameter_ptr->name_ptr = forest_ptr->map_ptr->parameters[i].name;
247 parameter_ptr->type = forest_ptr->map_ptr->parameters[i].type;
248 parameter_ptr->hints_ptr = &forest_ptr->map_ptr->parameters[i].hints;
249 parameter_ptr->map_element_ptr = forest_ptr->map_ptr->parameters + i;
251 list_add_tail(&parameter_ptr->siblings, parameters_list_ptr);
254 /* set other_parameter when needed */
255 for (i = 0 ; i < forest_ptr->parameters_count ; i++)
257 if (forest_ptr->map_ptr->parameters[i].scope == LV2DYNPARAM_PARAMETER_SCOPE_TYPE_HIDE_OTHER ||
258 forest_ptr->map_ptr->parameters[i].scope == LV2DYNPARAM_PARAMETER_SCOPE_TYPE_SHOW_OTHER)
260 forest_ptr->parameters[i]->other_parameter = forest_ptr->parameters[forest_ptr->map_ptr->parameters[i].scope_specific];
264 return true;
266 fail_free_parameters_array:
267 free(forest_ptr->parameters);
269 fail_free_groups_array:
270 free(forest_ptr->groups);
272 fail:
273 return false;
276 void
277 zynadd_dynparam_forest_initializer_clear(
278 struct zyn_forest_initializer * forest_ptr)
280 free(forest_ptr->groups);
281 free(forest_ptr->parameters);
284 void
285 zynadd_dynparam_destroy_forests(
286 struct zynadd * zynadd_ptr)
288 struct list_head * node_ptr;
289 struct zynadd_group * group_ptr;
290 struct zynadd_parameter * parameter_ptr;
292 while (!list_empty(&zynadd_ptr->parameters))
294 node_ptr = zynadd_ptr->parameters.next;
295 parameter_ptr = list_entry(node_ptr, struct zynadd_parameter, siblings);
296 list_del(node_ptr);
297 free(parameter_ptr);
300 while (!list_empty(&zynadd_ptr->groups))
302 node_ptr = zynadd_ptr->groups.next;
303 group_ptr = list_entry(node_ptr, struct zynadd_group, siblings);
304 list_del(node_ptr);
305 free(group_ptr);
309 bool
310 zynadd_dynparam_forests_appear(
311 struct zynadd * zynadd_ptr)
313 bool tmp_bool;
314 struct zynadd_group * group_ptr;
315 struct zynadd_parameter * parameter_ptr;
316 struct list_head * node_ptr;
318 list_for_each(node_ptr, &zynadd_ptr->groups)
320 group_ptr = list_entry(node_ptr, struct zynadd_group, siblings);
322 LOG_DEBUG("Adding group \"%s\"", group_ptr->name_ptr);
324 if (!lv2dynparam_plugin_group_add(
325 zynadd_ptr->dynparams,
326 group_ptr->parent_ptr == NULL ? NULL : group_ptr->parent_ptr->lv2group,
327 group_ptr->name_ptr,
328 group_ptr->hints_ptr,
329 &group_ptr->lv2group))
331 return false;
335 list_for_each(node_ptr, &zynadd_ptr->parameters)
337 parameter_ptr = list_entry(node_ptr, struct zynadd_parameter, siblings);
339 LOG_DEBUG("Adding parameter \"%s\"", parameter_ptr->name_ptr);
341 if (parameter_ptr->scope == LV2DYNPARAM_PARAMETER_SCOPE_TYPE_SEMI)
343 continue;
346 if (parameter_ptr->scope == LV2DYNPARAM_PARAMETER_SCOPE_TYPE_HIDE_OTHER ||
347 parameter_ptr->scope == LV2DYNPARAM_PARAMETER_SCOPE_TYPE_SHOW_OTHER)
349 LOG_DEBUG("Apearing show/hide parameter \"%s\"", parameter_ptr->name_ptr);
350 assert(parameter_ptr->type == LV2DYNPARAM_PARAMETER_TYPE_BOOL);
352 tmp_bool = zyn_addsynth_get_bool_parameter(
353 parameter_ptr->addsynth_component,
354 parameter_ptr->addsynth_parameter);
356 if (!zynadd_appear_parameter(zynadd_ptr, parameter_ptr))
358 return false;
361 if ((parameter_ptr->scope == LV2DYNPARAM_PARAMETER_SCOPE_TYPE_HIDE_OTHER && !tmp_bool) ||
362 (parameter_ptr->scope == LV2DYNPARAM_PARAMETER_SCOPE_TYPE_SHOW_OTHER && tmp_bool))
364 LOG_DEBUG("Apearing semi parameter \"%s\"", parameter_ptr->other_parameter->name_ptr);
365 if (!zynadd_appear_parameter(zynadd_ptr, parameter_ptr->other_parameter))
367 return false;
371 continue;
374 assert(parameter_ptr->scope == LV2DYNPARAM_PARAMETER_SCOPE_TYPE_ALWAYS);
376 if (!zynadd_appear_parameter(zynadd_ptr, parameter_ptr))
378 LOG_ERROR("zynadd_appear_parameter() failed.");
379 return false;
383 return true;
386 bool
387 zynadd_dynparam_init(
388 struct zynadd * zynadd_ptr)
390 struct zyn_forest_initializer top_forest_initializer;
391 struct zyn_forest_initializer voice_forest_initializer;
392 unsigned int i;
393 unsigned int j;
394 char voice_group_names[VOICES_COUNT][20];
396 INIT_LIST_HEAD(&zynadd_ptr->groups);
397 INIT_LIST_HEAD(&zynadd_ptr->parameters);
399 for (i = 0 ; i < ZYNADD_GLOBAL_COMPONENTS_COUNT ; i++)
401 zynadd_ptr->synth_global_components[i] = zyn_addsynth_get_global_component(zynadd_ptr->synth, i);
404 for (i = 0 ; i < VOICES_COUNT ; i++)
406 for (j = 0 ; j < ZYNADD_VOICE_COMPONENTS_COUNT ; j++)
408 LOG_DEBUG("Voice %u component %u", i, j);
409 zynadd_ptr->synth_voice_components[i * ZYNADD_VOICE_COMPONENTS_COUNT + j] = zyn_addsynth_get_voice_component(zynadd_ptr->synth, i, j);
410 LOG_DEBUG("Voice component %p", zynadd_ptr->synth_voice_components[i * ZYNADD_VOICE_COMPONENTS_COUNT + j]);
414 LOG_DEBUG("Preparing top forest...");
416 if (!zynadd_dynparam_forest_initializer_prepare(
417 &top_forest_initializer,
418 &g_top_forest_map,
419 NULL,
420 zynadd_ptr->synth_global_components,
421 zynadd_ptr,
422 &zynadd_ptr->groups,
423 &zynadd_ptr->parameters))
425 goto fail_destroy_forests;
428 LOG_DEBUG("Preparing voice forest...");
430 for (i = 0 ; i < VOICES_COUNT ; i++)
432 sprintf(voice_group_names[i], "Voice %u", i + 1);
434 g_voice_forest_map.groups[0].name = voice_group_names[i];
436 if (!zynadd_dynparam_forest_initializer_prepare(
437 &voice_forest_initializer,
438 &g_voice_forest_map,
439 top_forest_initializer.groups[zynadd_top_forest_map_get_voices_group()],
440 zynadd_ptr->synth_voice_components + i * ZYNADD_VOICE_COMPONENTS_COUNT,
441 zynadd_ptr,
442 &zynadd_ptr->groups,
443 &zynadd_ptr->parameters))
445 goto fail_clear_top_forest_initializer;
449 if (!lv2dynparam_plugin_instantiate(
450 (LV2_Handle)zynadd_ptr,
451 zynadd_ptr->host_features,
452 "zynadd",
453 &zynadd_ptr->dynparams))
455 goto fail_clear_voice_forest_initializer;
458 if (!zynadd_dynparam_forests_appear(zynadd_ptr))
460 goto fail_clean_dynparams;
463 zynadd_dynparam_forest_initializer_clear(&voice_forest_initializer);
464 zynadd_dynparam_forest_initializer_clear(&top_forest_initializer);
466 return true;
468 fail_clean_dynparams:
469 zynadd_dynparam_uninit(zynadd_ptr);
471 fail_clear_voice_forest_initializer:
472 zynadd_dynparam_forest_initializer_clear(&voice_forest_initializer);
474 fail_clear_top_forest_initializer:
475 zynadd_dynparam_forest_initializer_clear(&top_forest_initializer);
477 fail_destroy_forests:
478 zynadd_dynparam_destroy_forests(zynadd_ptr);
480 return false;
483 void
484 zynadd_dynparam_uninit(struct zynadd * zynadd_ptr)
486 zynadd_dynparam_destroy_forests(zynadd_ptr);
488 lv2dynparam_plugin_cleanup(zynadd_ptr->dynparams);