njackspa: [bug] fix the fields' widths
[ng-jackspa.git] / jackspa.c
bloba0ef2050e89345fea4542acaaceee29acec69ac6
1 /* jackspa.c - LADSPA plugin instance with JACK audio ports
2 * Copyright © 2007 Nick Thomas
3 * Copyright © 2013 Géraud Meyer <graud@gmx.com>
5 * jackspa.c is part of ng-jackspa.
7 * ng-jackpsa is free software; you can redistribute it and/or modify it under
8 * the terms of the GNU General Public License version 2 as published by the
9 * Free Software Foundation.
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * for more details.
16 * You should have received a copy of the GNU General Public License along
17 * with this program. If not, see <http://www.gnu.org/licenses/>.
20 #include <dlfcn.h>
21 #include <errno.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include "jackspa.h"
26 #include "interface.h"
28 #include "ladspa.c"
31 /* Initial config (command line) */
32 static gboolean jackexactname = FALSE;
33 static gboolean jacknostartserver = FALSE;
34 static gchar *jackclientname = NULL;
35 static gchar **portnames = NULL;
36 gboolean parse_names(const gchar *opt, const gchar *arg,
37 gpointer data, GError **error)
39 g_strfreev(portnames); /* discard a possible previous option */
40 portnames = g_strsplit(arg, ":", -1);
41 return TRUE;
43 static gboolean controlvout = FALSE;
44 static gint controlvin = 0;
45 gboolean parse_cvio(const gchar *opt, const gchar *arg,
46 gpointer data, GError **error)
48 controlvin = 2;
49 return TRUE;
51 const GOptionEntry jackspa_entries[] =
53 /* long, short, flags, arg_type, arg_data, description, arg_description */
54 { "jack-exactname", 'N', 0, G_OPTION_ARG_NONE, &jackexactname,
55 "Do not allow JACK to generate an unused client name", NULL },
56 { "jack-nostartserver", 'S', 0, G_OPTION_ARG_NONE, &jacknostartserver,
57 "Do not start a JACK server if none is running", NULL },
58 { "jack-client", 'j', 0, G_OPTION_ARG_STRING, &jackclientname,
59 "Use the given name instead of the concatenation of a fixed prefix and the plugin label", "client_name" },
60 { "names", 'n', 0, G_OPTION_ARG_CALLBACK, parse_names,
61 "Colon separated list of overriding names for the LADPSA audio and control ports", "port_names" },
62 { "controlv-out", 'O', 0, G_OPTION_ARG_NONE, &controlvout,
63 "Export the control outputs as control voltages on JACK audio ports", NULL },
64 { "controlv-in", 'I', 0, G_OPTION_ARG_NONE, &controlvin,
65 "Export the control inputs as control voltages on JACK input audio ports", NULL },
66 { "controlv-inasout", 'T', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, parse_cvio,
67 "Export the control inputs as control voltages on JACK output audio ports not on input ones", NULL },
68 { 0 }
70 static char *ladspa_library = NULL;
71 typedef struct {
72 char is_label;
73 union { unsigned long uid; char *label; } id;
74 } plugin_id_t;
75 static plugin_id_t ladspa_id = { 0 };
78 /* Finds the plugin descriptor with the given ID in the given object file,
79 * storing it in state->descriptor. Returns 1 on success. On failure, returns 0
80 * and sets *error to an appropriate error message.
82 int find_plugin(state_t *state, const char *file, const plugin_id_t plugin_id,
83 const char **error)
85 int err = 0;
86 unsigned long i; /* port index */
87 void *library;
88 LADSPA_Descriptor *(*descriptor_fun)(unsigned long index);
89 LADSPA_Descriptor *descriptor;
91 /* Open the library. */
92 library = ladspa_dlopen(file, RTLD_LAZY);
93 if (!library)
94 err = 1, *error = dlerror();
96 /* Find the ladspa_descriptor() function. */
97 if (!err) {
98 descriptor_fun = (LADSPA_Descriptor *(*)(unsigned long))
99 dlsym(library, "ladspa_descriptor");
100 if (!descriptor_fun)
101 err = 1, *error = dlerror();
104 /* Find the appropriate descriptor. */
105 for (i = 0; !err; i++) {
106 descriptor = descriptor_fun(i);
108 if (!descriptor)
109 err = 1, *error = plugin_id.is_label ?
110 "no such plugin label in the given library" :
111 "no such plugin UID in the given library";
112 else if ( (!plugin_id.is_label && descriptor->UniqueID == plugin_id.id.uid) ||
113 (plugin_id.is_label && !strcmp(descriptor->Label, plugin_id.id.label)) )
115 state->descriptor = descriptor;
116 break;
120 return !err;
123 /* The JACK processing callback. */
124 int process(jack_nframes_t nframes, void *arg)
126 state_t *state = (state_t *)arg;
127 unsigned long p; /* loop variable for ports */
128 const LADSPA_PortDescriptor *port; /* loop variable for port descriptors */
129 void *buffer; /* JACK buffer */
130 LADSPA_Data buf; /* buffer for the control outputs */
132 /* Connect audio ports and unused control ports */
133 for ( p = 0, port = state->descriptor->PortDescriptors;
134 p < state->descriptor->PortCount; p++, port++ )
136 if (LADSPA_IS_PORT_CONTROL(*port)) {
137 if (LADSPA_IS_PORT_INPUT(*port) && !controlvin)
138 continue;
139 if (LADSPA_IS_PORT_OUTPUT(*port) && !controlvout) {
140 state->descriptor->connect_port(state->handle, p, &buf);
141 /* forget the control output ports values */
142 continue;
146 buffer = jack_port_get_buffer(state->jack_ports[p], nframes);
147 if (LADSPA_IS_PORT_CONTROL(*port)) {
148 if (LADSPA_IS_PORT_OUTPUT(*port))
149 memset(buffer, 0, (size_t)nframes); /* might be needless */
150 /* only the first sample will be set */
151 else if (controlvin == 1 && !jack_port_connected(state->jack_ports[p]))
152 *(LADSPA_Data *)buffer = state->control_port_values[p];
153 /* use the previous value (or the value set in the UI) */
154 else if (controlvin == 1)
155 state->control_port_values[p] = *(LADSPA_Data *)buffer;
156 /* record the new control value */
157 else {
158 memset(buffer, 0, (size_t)nframes); /* might be needless */
159 *(LADSPA_Data *)buffer = state->control_port_values[p];
162 state->descriptor->connect_port
163 (state->handle, p, (LADSPA_Data *)buffer);
166 /* Run the plugin. */
167 state->descriptor->run(state->handle, nframes);
169 return 0;
172 /* Initializes JACK, opening the appropriate ports, instantiating the LADSPA
173 * Plugin, and starting the synthesis thread running.. Returns 1 on success. On
174 * failure, returns 0 and sets *error to an appropriate error message.
176 int init_jack(state_t *state, const char **error)
178 static char client_name_prefix[] = "jackspa_";
179 int err = 0;
180 jack_options_t oflags;
181 jack_status_t jack_status;
182 unsigned long p; /* loop variable for ports */
183 const LADSPA_PortDescriptor *port; /* loop variable for port descriptors */
184 enum JackPortFlags pflags;
186 /* Allocate memory for the client name. */
187 if (!jackclientname) {
188 state->client_name = (char *)calloc
189 ( sizeof(client_name_prefix) + strlen(state->descriptor->Label),
190 sizeof(char) );
191 if (!state->client_name)
192 err = 1, *error = strerror(errno);
195 /* Set the client name. */
196 if (!err) {
197 if (jackclientname)
198 state->client_name = jackclientname;
199 else {
200 /* state->client_name[0] = '\0'; */ /* done by calloc */
201 strcat(state->client_name, client_name_prefix);
202 strcat(state->client_name, state->descriptor->Label);
206 /* Open JACK. */
207 if (!err) {
208 oflags = JackNullOption;
209 if (jackexactname) oflags |= JackUseExactName;
210 if (jacknostartserver) oflags |= JackNoStartServer;
211 state->jack_client =
212 jack_client_open(state->client_name, oflags, &jack_status);
213 if (!state->jack_client)
214 err = 1, *error = "could not connect to JACK";
217 /* Free memory for the client name */
218 if (!jackclientname) free(state->client_name);
219 if (!err) state->client_name = jack_get_client_name(state->jack_client);
221 /* Allocate memory for the list of ports. */
222 if (!err) {
223 state->jack_ports = (jack_port_t **)calloc
224 (state->descriptor->PortCount, sizeof(jack_port_t *));
225 if (!state->jack_ports)
226 err = 1, *error = strerror(errno);
229 /* Allocate memory for the list of control port values. */
230 if (!err) {
231 state->control_port_values = (LADSPA_Data *)calloc
232 ((size_t)state->descriptor->PortCount, sizeof(LADSPA_Data));
233 if (!state->control_port_values)
234 err = 1, *error = strerror(errno);
237 /* Register ports. */
238 state->num_control_ports = 0; state->num_meter_ports = 0;
239 for ( p = 0, port = state->descriptor->PortDescriptors;
240 !err && p < state->descriptor->PortCount; p++, port++ )
242 /* Get the actual port name */
243 state->port_names[p] = glib_strv_index(p, portnames);
244 if (!state->port_names[p] || *state->port_names[p] == '\0')
245 state->port_names[p] = state->descriptor->PortNames[p];
247 /* Count control ports and skip non exported ports */
248 if (LADSPA_IS_PORT_CONTROL(*port)) {
249 if (LADSPA_IS_PORT_INPUT(*port)) {
250 state->num_control_ports++;
251 if (!controlvin) continue;
253 else {
254 state->num_meter_ports++;
255 if (!controlvout) continue;
259 if (LADSPA_IS_PORT_INPUT(*port)) {
260 if (controlvin != 1 && LADSPA_IS_PORT_CONTROL(*port))
261 pflags = JackPortIsOutput;
262 else
263 pflags = JackPortIsInput;
265 else
266 pflags = JackPortIsOutput;
268 state->jack_ports[p] = jack_port_register
269 ( state->jack_client, state->port_names[p],
270 JACK_DEFAULT_AUDIO_TYPE, pflags, 0 );
272 if (!state->jack_ports[p])
273 err = 1, *error = "could not register JACK ports";
276 /* Register our processing callback. */
277 if (!err)
278 if (jack_set_process_callback(state->jack_client, &process, state))
279 err = 1, *error = "could not register the JACK processing callback";
281 /* Instantiate the LADSPA plugin. */
282 if (!err) {
283 state->handle = state->descriptor->instantiate
284 (state->descriptor, jack_get_sample_rate(state->jack_client));
285 if (!state->handle)
286 err = 1, *error = "could not instantiate the plugin.";
289 /* Connect input control ports. */
290 if (!err)
291 for (p = 0; p < state->descriptor->PortCount; p++)
292 if ( LADSPA_IS_PORT_CONTROL(state->descriptor->PortDescriptors[p]) &&
293 LADSPA_IS_PORT_INPUT(state->descriptor->PortDescriptors[p]))
295 state->descriptor->connect_port
296 (state->handle, p, &state->control_port_values[p]);
297 /* state->control_port_values[p] = 0.0; */ /* done by calloc() */
300 /* Activate the LADSPA plugin. */
301 if (!err)
302 if (state->descriptor->activate)
303 state->descriptor->activate(state->handle);
305 /* Get the bits flowing. */
306 if (!err)
307 if (jack_activate(state->jack_client))
308 err = 1, *error = "could not activate audio processing";
310 return !err;
313 typedef enum {
314 st_want_plugin_file,
315 st_want_plugin_id,
316 st_done
317 } arg_parser_state;
319 /* Parses command-line arguments. Returns 1 on success. On failure, returns 0
320 * and sets *error to an appropriate error message.
322 int parse_args(state_t *state, int argc, char **argv, char **plugin_file,
323 plugin_id_t *plugin_id, const char **error)
325 int err = 0;
326 int i; /* arg index */
327 arg_parser_state st = st_want_plugin_file;
328 char *e;
330 argc--, argv++; /* skip the program name */
332 for (i = 0; i < argc; i++)
333 switch (st) {
334 case st_want_plugin_file:
335 *plugin_file = argv[i];
336 st = st_want_plugin_id;
337 break;
339 case st_want_plugin_id:
340 plugin_id->is_label = 0, plugin_id->id.uid = strtol(argv[i], &e, 0);
341 if (e == argv[i] || *e != '\0')
342 plugin_id->is_label = 1, plugin_id->id.label = argv[i];
343 st = st_done;
344 break;
346 case st_done:
347 default:
348 err = 1, *error = "extra arguments given";
349 break;
352 if (st != st_done)
353 err = 1, *error = "must supply a plugin file and a plugin ID";
355 return !err;
358 int jackspa_init(state_t *state, int argc, char **argv)
360 const char *error;
361 int err = 0;
363 state->jack_client = 0;
365 err = !parse_args(state, argc, argv, &ladspa_library, &ladspa_id, &error);
367 if (!err)
368 err = !find_plugin(state, ladspa_library, ladspa_id, &error);
370 if (!err) {
371 state->port_names =
372 (const char **)calloc(state->descriptor->PortCount, sizeof(char *));
373 if (!state->port_names)
374 err = 1, error = "memory allocation error";
377 if (!err)
378 err = !init_jack(state, &error);
380 if (err)
381 fprintf(stderr, "jackspa error: %s\n", error);
383 return !err;