jackspa: --names: new switch to override the plugin port names
[ng-jackspa.git] / control.c
blob228df1e2bc1493fe1e11f6b830b9c489edc91365
1 /* control.c - interface to the controls of a jackspa plugin instance
2 * Copyright © 2013 Géraud Meyer <graud@gmx.com>
4 * This file is part of ng-jackspa.
6 * ng-jackspa is free software; you can redistribute it and/or modify it under
7 * the terms of the GNU General Public License version 2 as published by the
8 * Free Software Foundation.
10 * This program is distributed in the hope that it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13 * more details.
15 * You should have received a copy of the GNU General Public License along
16 * with ng-jackspa. If not, see <http://www.gnu.org/licenses/>.
19 #include <stdlib.h>
20 #include <stdio.h>
21 #include <math.h>
22 #include <string.h>
23 #include <regex.h>
24 #include "control.h"
25 #include "interface.h"
27 LADSPA_Data control_rounding(const control_t *control, LADSPA_Data val)
29 if (control->type == JACKSPA_INT || control->type == JACKSPA_TOGGLE)
30 return nearbyintf(val);
31 return val;
34 void control_exchange(control_t *control)
36 LADSPA_Data buf;
37 buf = *control->val;
38 *control->val = control->sel;
39 control->sel = buf;
42 /* Initial config (command line switches) */
43 gchar **control_inits = NULL;
44 gchar **control_defaults = NULL;
45 gboolean parse_inits(const gchar *opt, const gchar *arg,
46 gpointer data, GError **error)
48 g_strfreev(control_inits); /* discard a possible previous option */
49 control_inits = g_strsplit(arg, ":", -1);
50 return TRUE;
52 gboolean parse_defaults(const gchar *opt, const gchar *arg,
53 gpointer data, GError **error)
55 g_strfreev(control_defaults); /* discard a possible previous option */
56 control_defaults = g_strsplit(arg, ":", -1);
57 return TRUE;
60 const GOptionEntry control_entries[] =
62 /* long, short, flags, arg_type, arg_data, description, arg_description */
63 { "inits", 'i', 0, G_OPTION_ARG_CALLBACK, parse_inits,
64 "Colon separated list of initial values", "init_values" },
65 { "defaults", 'd', 0, G_OPTION_ARG_CALLBACK, parse_defaults,
66 "Colon separated list of default values", "default_values" },
67 { 0 }
71 typedef struct {
72 LADSPA_Data *ini;
73 LADSPA_Data *def;
74 } control_init_t;
76 /* Interpret the given command to obtain a value depending of the control
77 * parameters.
78 * Return 0 if the value was set, 1 if the command was to skip, -1 otherwise
79 * (invalid command or error) */
80 int control_set_value(LADSPA_Data *val, char *cmd, control_t *control)
82 LADSPA_Data buf;
83 regex_t reg;
84 regmatch_t matches[1];
85 const char *percent_r="^%[0-9][0-9]$";
86 char *e;
87 int rc;
88 char err[30];
90 if (cmd == NULL || !strcmp(cmd, "")) /* skip */
91 return 1;
92 else if (!strcmp(cmd, "<")) /* min */
93 *val = control->min;
94 else if (!strcmp(cmd, ">")) /* max */
95 *val = control->max;
96 else if (cmd[0] == '%') { /* percentage */
97 if ((rc = regcomp(&reg, percent_r, 0)) ) {
98 regerror(rc, &reg, err, sizeof(err));
99 return (fprintf(stderr, "regex compilation failed: %s\n", err), -1);
101 if (regexec(&reg, cmd, 1, matches, 0))
102 return (regfree(&reg), -1);
103 *val = (LADSPA_Data)strtof(&cmd[1], NULL) / 100.0;
104 *val = control_rounding
105 (control, (1.0-*val) * control->min + *val * control->max);
106 regfree(&reg);
108 else if (!strcmp(cmd, "d")) { /* default */
109 if (control->def)
110 *val = *control->def;
111 else
112 return -1;
114 else if (!strcmp(cmd, "a")) /* active */
115 *val = *control->val;
116 else if (!strcmp(cmd, "s")) /* selected */
117 *val = control->sel;
118 else { /* float */
119 buf = (LADSPA_Data)strtof(cmd, &e);
120 if (e == cmd || *e != '\0')
121 return -1;
122 *val = buf;
125 return 0;
128 /* Find the initial config of the control at index ctrl */
129 int control_set_init(control_init_t *init,
130 unsigned long ctrl, control_t *control)
132 int ret = 0, rc;
134 if (!(init->ini = malloc(sizeof(LADSPA_Data))) )
135 return -1;
136 rc = control_set_value(init->ini, glib_strv_index(ctrl, control_inits), control);
137 if (rc)
138 free(init->ini), init->ini = NULL;
139 if (rc < 0)
140 ret = rc;
142 if (!(init->def = malloc(sizeof(LADSPA_Data))) )
143 return -1;
144 rc = control_set_value(init->def, glib_strv_index(ctrl, control_defaults), control);
145 if (rc)
146 free(init->def), init->def = NULL;
147 if (rc < 0)
148 ret = rc;
150 return ret;
153 int control_init(control_t *control, state_t *state, unsigned long port,
154 unsigned long ctrl)
156 control->port = port;
157 control->ctrl = ctrl;
158 control->desc = &state->descriptor->PortDescriptors[port];
159 control->hint = &state->descriptor->PortRangeHints[port];
160 LADSPA_PortRangeHintDescriptor descriptor = control->hint->HintDescriptor;
161 LADSPA_Data lower_bound = control->hint->LowerBound;
162 LADSPA_Data upper_bound = control->hint->UpperBound;
163 control_init_t init;
165 control->name = state->port_names[port];
166 control->val = &state->control_port_values[port];
168 /* control->min, control->max */
169 if (LADSPA_IS_HINT_SAMPLE_RATE(descriptor)) {
170 int sample_rate = jack_get_sample_rate(state->jack_client);
171 lower_bound *= sample_rate;
172 upper_bound *= sample_rate;
174 if ( LADSPA_IS_HINT_BOUNDED_BELOW(descriptor) &&
175 LADSPA_IS_HINT_BOUNDED_ABOVE(descriptor) )
177 control->min = lower_bound;
178 control->max = upper_bound;
180 else if (LADSPA_IS_HINT_BOUNDED_BELOW(descriptor)) {
181 control->min = lower_bound;
182 control->max = 1.0;
184 else if (LADSPA_IS_HINT_BOUNDED_ABOVE(descriptor)) {
185 control->min = 0.0;
186 control->max = upper_bound;
188 else {
189 control->min = -1.0;
190 control->max = 1.0;
193 /* control->def */
194 if (LADSPA_IS_HINT_HAS_DEFAULT(descriptor)) {
195 control->def = (LADSPA_Data *)malloc(sizeof(LADSPA_Data));
196 if (!control->def)
197 return (fprintf(stderr, "memory allocation error\n"), 1);
198 switch (descriptor & LADSPA_HINT_DEFAULT_MASK) {
199 case LADSPA_HINT_DEFAULT_MINIMUM:
200 *control->def = lower_bound;
201 break;
202 case LADSPA_HINT_DEFAULT_LOW:
203 *control->def = lower_bound * 0.75 + upper_bound * 0.25;
204 break;
205 case LADSPA_HINT_DEFAULT_MIDDLE:
206 *control->def = lower_bound * 0.5 + upper_bound * 0.5;
207 break;
208 case LADSPA_HINT_DEFAULT_HIGH:
209 *control->def = lower_bound * 0.25 + upper_bound * 0.75;
210 break;
211 case LADSPA_HINT_DEFAULT_MAXIMUM:
212 *control->def = upper_bound;
213 break;
214 case LADSPA_HINT_DEFAULT_0:
215 *control->def = 0.0;
216 break;
217 case LADSPA_HINT_DEFAULT_1:
218 *control->def = 1.0;
219 break;
220 case LADSPA_HINT_DEFAULT_100:
221 *control->def = 100.0;
222 break;
223 case LADSPA_HINT_DEFAULT_440:
224 *control->def = 440.0;
225 break;
226 default:
227 fprintf(stderr, "default not found\n");
228 free(control->def), control->def = NULL;
231 else
232 control->def = NULL;
234 /* Check the default */
235 if (control->def) {
236 if (*control->def < control->min) {
237 fprintf(stderr, "default smaller than the minimum\n");
238 *control->def = control->min;
240 if (*control->def > control->max) {
241 fprintf(stderr, "default greater than the maximum\n");
242 *control->def = control->max;
246 /* control->inc & Overrides */
247 if (LADSPA_IS_HINT_TOGGLED(descriptor)) {
248 control->min = 0.0;
249 control->max = 1.0;
250 control->inc.fine = 1.0;
251 control->inc.coarse = 1.0;
252 control->type = JACKSPA_TOGGLE;
253 if (control->def) *control->def = nearbyintf(*control->def);
255 else if (LADSPA_IS_HINT_INTEGER(descriptor)) {
256 control->min = nearbyintf(control->min);
257 control->max = nearbyintf(control->max);
258 control->inc.fine = 1.0;
259 control->inc.coarse = 1.0;
260 control->type = JACKSPA_INT;
261 if (control->def) *control->def = nearbyintf(*control->def);
263 else {
264 control->inc.fine = (control->max - control->min) / 500;
265 control->inc.coarse = (control->max - control->min) / 50;
266 control->type = JACKSPA_FLOAT;
269 /* Initial config */
270 if (control_set_init(&init, ctrl, control) < 0)
271 return (fprintf(stderr, "invalid initial value given\n"), 1);
272 if (init.def) {
273 if (!control->def) {
274 control->def = (LADSPA_Data *)malloc(sizeof(LADSPA_Data));
275 if (!control->def)
276 return (fprintf(stderr, "memory allocation error\n"), 1);
278 *control->def = *init.def;
281 /* control->sel, control->val */
282 if (control->def)
283 control->sel = *control->def;
284 else
285 control->sel = control->min;
286 if (init.ini)
287 *control->val = *init.ini;
288 else
289 *control->val = control->sel;
291 free(init.def), free(init.ini);
292 return 0;
295 int control_buildall(unsigned long *count, controls_t *controls, state_t *state)
297 int rc = 0;
298 unsigned long p, c; /* loop variables for ports */
300 *count = state->num_control_ports;
301 *controls = (controls_t)calloc(sizeof(control_t *), (size_t)*count);
302 if (!*controls)
303 return (fprintf(stderr, "memory allocation error\n"), 1);
305 for (p = 0, c = 0; p < state->descriptor->PortCount; p++)
306 if ( LADSPA_IS_PORT_INPUT(state->descriptor->PortDescriptors[p]) &&
307 LADSPA_IS_PORT_CONTROL(state->descriptor->PortDescriptors[p]) )
309 (*controls)[c] = (control_t *)malloc(sizeof(control_t));
310 if (!(*controls)[c])
311 return (fprintf(stderr, "memory allocation error\n"), 1);
312 if (control_init((*controls)[c], state, p, c))
313 rc = 1;
314 c++;
317 return rc;
320 void control_cleanupall(unsigned long count, controls_t *controls)
322 while (count) free((*controls)[--count]);
323 free(*controls);