jackspa: --jack-nostartserver: new switch
[ng-jackspa.git] / jackspa.c
blob068d20539fae4b8703f3067e1bd1b9385cf2ddbb
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"
28 /* Initial config (command line) */
29 static gboolean jackexactname = FALSE;
30 static gboolean jacknostartserver = FALSE;
31 const GOptionEntry jackspa_entries[] =
33 /* long, short, flags, arg_type, arg_data, description, arg_description */
34 { "jack-exactname", 'N', 0, G_OPTION_ARG_NONE, &jackexactname,
35 "Do not allow JACK to generate an unused client name", NULL },
36 { "jack-nostartserver", 'S', 0, G_OPTION_ARG_NONE, &jacknostartserver,
37 "Do not start a JACK server if none is running", NULL },
38 { 0 }
40 static char *ladspa_library = NULL;
41 static unsigned long ladspa_id = 0;
44 /* Finds the plugin descriptor with the given ID in the given object file,
45 * storing it in state->descriptor. Returns 1 on success. On failure, returns 0
46 * and sets *error to an appropriate error message.
48 int find_plugin(state_t *state, const char *file, const unsigned long id,
49 const char **error)
51 int err = 0;
52 unsigned long i; /* port index */
53 void *library;
54 LADSPA_Descriptor *(*descriptor_fun)(unsigned long index);
55 LADSPA_Descriptor *descriptor;
57 /* Open the library. */
58 library = dlopen(file, RTLD_LAZY);
59 if (!library)
60 err = 1, *error = dlerror();
62 /* Find the ladspa_descriptor() function. */
63 if (!err) {
64 descriptor_fun = (LADSPA_Descriptor *(*)(unsigned long))
65 dlsym(library, "ladspa_descriptor");
66 if (!descriptor_fun)
67 err = 1, *error = dlerror();
70 /* Find the appropriate descriptor. */
71 for (i = 0; !err; i++) {
72 descriptor = descriptor_fun(i);
74 if (!descriptor)
75 err = 1, *error = "no such plugin index in the given file";
76 else if (descriptor->UniqueID == id) {
77 state->descriptor = descriptor;
78 break;
82 return !err;
85 /* The JACK processing callback. */
86 int process(jack_nframes_t nframes, void *arg)
88 state_t *state = (state_t *)arg;
89 unsigned long p; /* loop variable for ports */
90 LADSPA_Data buf; /* buffer for the control outputs */
92 /* Connect audio ports and unused control ports */
93 for (p = 0; p < state->descriptor->PortCount; p++)
94 if (LADSPA_IS_PORT_AUDIO(state->descriptor->PortDescriptors[p]))
95 state->descriptor->connect_port
96 ( state->handle, p,
97 (LADSPA_Data *)jack_port_get_buffer(state->jack_ports[p], nframes) );
98 else if ( LADSPA_IS_PORT_CONTROL(state->descriptor->PortDescriptors[p]) &&
99 LADSPA_IS_PORT_OUTPUT(state->descriptor->PortDescriptors[p]) )
100 state->descriptor->connect_port(state->handle, p, &buf);
101 /* forget the control output ports values */
103 /* Run the plugin. */
104 state->descriptor->run(state->handle, nframes);
106 return 0;
109 /* Initializes JACK, opening the appropriate ports, instantiating the LADSPA
110 * Plugin, and starting the synthesis thread running.. Returns 1 on success. On
111 * failure, returns 0 and sets *error to an appropriate error message.
113 int init_jack(state_t *state, const char **error)
115 static char client_name_prefix[] = "jackspa_";
116 int err = 0;
117 jack_options_t oflags;
118 jack_status_t jack_status;
119 unsigned long p; /* loop variable for ports */
120 enum JackPortFlags pflags;
122 /* Allocate memory for the client name. */
123 state->client_name = (char *)calloc
124 ( sizeof(client_name_prefix) + strlen(state->descriptor->Label),
125 sizeof(char) );
126 if (!state->client_name)
127 err = 1, *error = strerror(errno);
129 /* Set the client name. */
130 if (!err) {
131 /* state->client_name[0] = '\0'; */ /* done by calloc */
132 strcat(state->client_name, client_name_prefix);
133 strcat(state->client_name, state->descriptor->Label);
136 /* Open JACK. */
137 if (!err) {
138 oflags = JackNullOption;
139 if (jackexactname) oflags |= JackUseExactName;
140 if (jacknostartserver) oflags |= JackNoStartServer;
141 state->jack_client =
142 jack_client_open(state->client_name, oflags, &jack_status);
143 if (!state->jack_client)
144 err = 1, *error = "could not connect to JACK";
147 /* Free memory for the client name */
148 free(state->client_name);
149 if (!err) state->client_name = jack_get_client_name(state->jack_client);
151 /* Allocate memory for the list of ports. */
152 if (!err) {
153 state->jack_ports = (jack_port_t **)calloc
154 (state->descriptor->PortCount, sizeof(jack_port_t *));
155 if (!state->jack_ports)
156 err = 1, *error = strerror(errno);
159 /* Allocate memory for the list of control port values. */
160 if (!err) {
161 state->control_port_values = (LADSPA_Data *)calloc
162 ((size_t)state->descriptor->PortCount, sizeof(LADSPA_Data));
163 if (!state->control_port_values)
164 err = 1, *error = strerror(errno);
167 /* Register ports. */
168 state->num_control_ports = 0;
169 for (p = 0; !err && p < state->descriptor->PortCount; p++) {
170 if ( LADSPA_IS_PORT_CONTROL(state->descriptor-> PortDescriptors[p]) &&
171 LADSPA_IS_PORT_INPUT(state->descriptor->PortDescriptors[p]) )
173 state->num_control_ports++;
174 continue;
177 if (LADSPA_IS_PORT_INPUT(state->descriptor->PortDescriptors[p]))
178 pflags = JackPortIsInput;
179 else if (LADSPA_IS_PORT_AUDIO(state->descriptor->PortDescriptors[p]))
180 pflags = JackPortIsOutput;
181 else
182 continue; /* skip the control outputs (aka meters) */
184 state->jack_ports[p] = jack_port_register
185 ( state->jack_client, state->descriptor->PortNames[p],
186 JACK_DEFAULT_AUDIO_TYPE, pflags, 0 );
188 if (!state->jack_ports[p])
189 err = 1, *error = "could not register JACK ports";
192 /* Register our processing callback. */
193 if (!err)
194 if (jack_set_process_callback(state->jack_client, &process, state))
195 err = 1, *error = "could not register the JACK processing callback";
197 /* Instantiate the LADSPA plugin. */
198 if (!err) {
199 state->handle = state->descriptor->instantiate
200 (state->descriptor, jack_get_sample_rate(state->jack_client));
201 if (!state->handle)
202 err = 1, *error = "could not instantiate the plugin.";
205 /* Connect input control ports. */
206 if (!err)
207 for (p = 0; p < state->descriptor->PortCount; p++)
208 if ( LADSPA_IS_PORT_CONTROL(state->descriptor->PortDescriptors[p]) &&
209 LADSPA_IS_PORT_INPUT(state->descriptor->PortDescriptors[p]))
211 state->descriptor->connect_port
212 (state->handle, p, &state->control_port_values[p]);
213 /* state->control_port_values[p] = 0.0; */ /* done by calloc() */
216 /* Activate the LADSPA plugin. */
217 if (!err)
218 if (state->descriptor->activate)
219 state->descriptor->activate(state->handle);
221 /* Get the bits flowing. */
222 if (!err)
223 if (jack_activate(state->jack_client))
224 err = 1, *error = "could not activate audio processing";
226 return !err;
229 typedef enum {
230 st_want_plugin_file,
231 st_want_plugin_id,
232 st_done
233 } arg_parser_state;
235 /* Parses command-line arguments. Returns 1 on success. On failure, returns 0
236 * and sets *error to an appropriate error message.
238 int parse_args(state_t *state, int argc, char **argv, char **plugin_file,
239 unsigned long *plugin_id, const char **error)
241 int err = 0;
242 int i; /* arg index */
243 arg_parser_state st = st_want_plugin_file;
245 argc--, argv++; /* skip the program name */
247 for (i = 0; i < argc; i++)
248 switch (st) {
249 case st_want_plugin_file:
250 *plugin_file = argv[i];
251 st = st_want_plugin_id;
252 break;
254 case st_want_plugin_id:
255 *plugin_id = atol(argv[i]);
256 st = st_done;
257 break;
259 case st_done:
260 default:
261 err = 1, *error = "extra arguments given";
262 break;
265 if (st != st_done)
266 err = 1, *error = "must supply a plugin file and a plugin ID";
268 return !err;
271 int jackspa_init(state_t *state, int argc, char **argv)
273 const char *error;
274 int err = 0;
276 state->jack_client = 0;
278 err = !parse_args(state, argc, argv, &ladspa_library, &ladspa_id, &error);
280 if (!err)
281 err = !find_plugin(state, ladspa_library, ladspa_id, &error);
283 if (!err)
284 err = !init_jack(state, &error);
286 if (err)
287 fprintf(stderr, "jackspa error: %s\n", error);
289 return !err;