GUI tweaks.
[ng-jackspa.git] / jackspa.cpp
blobcabe67b1385e278d950f17d82edf79e382a63878
1 // jackspa, a dirt-simple LADSPA host for JACK
2 // Copyright (C) 2007 Nick Thomas
3 //
4 // This program is free software; you can redistribute it and/or
5 // modify it under the terms of version 2 of the GNU General Public
6 // License as published by the Free Software Foundation; the terms of
7 // any later version are NOT APPLICABLE.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
14 // You should have received a copy of the GNU General Public License along
15 // with this program; if not, write to the Free Software Foundation, Inc.,
16 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 #include <dlfcn.h>
19 #include <errno.h>
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include "jackspa.hpp"
25 // Finds the plugin descriptor with the given ID in the given
26 // object file, storing it in state->descriptor. Returns 1 on
27 // success. On failure, returns 0 and sets *error to an appropriate
28 // error message.
29 int find_plugin(state_t *state, char *file, int id, char **error)
31 int err = 0;
32 int i;
33 void *library;
34 LADSPA_Descriptor *(*descriptor_fun)(unsigned long index);
35 LADSPA_Descriptor *descriptor;
37 // Open the library.
38 library = dlopen(file, RTLD_LAZY);
39 if (!library) {
40 *error = dlerror();
41 err = 1;
44 // Find the ladspa_descriptor() function.
45 if (!err) {
46 descriptor_fun = (LADSPA_Descriptor *(*)(unsigned long))
47 dlsym(library, "ladspa_descriptor");
48 if (!descriptor_fun) {
49 *error = dlerror();
50 err = 1;
54 // Find the appropriate descriptor.
55 for (i = 0; !err; i++) {
56 descriptor = descriptor_fun(i);
58 if (!descriptor) {
59 *error = "no such plugin index in the given file";
60 err = 1;
61 } else if ((int)descriptor->UniqueID == id) {
62 state->descriptor = descriptor;
63 break;
67 return !err;
70 // The JACK processing callback.
71 int process(jack_nframes_t nframes, void *arg)
73 state_t *state = (state_t *)arg;
74 int i, j;
75 float *buffer = state->control_port_buffer;
77 // Connect audio ports and copy control port values.
78 for (i = 0; i < (int)state->descriptor->PortCount; i++) {
79 if (LADSPA_IS_PORT_CONTROL(state->descriptor->PortDescriptors[i]) &&
80 LADSPA_IS_PORT_INPUT(state->descriptor->PortDescriptors[i])) {
81 for (j = 0; j < (int)nframes; j++, buffer++) {
82 *buffer = state->control_port_values[i];
84 } else {
85 state->descriptor->connect_port
86 (state->handle, i,
87 (float *)jack_port_get_buffer(state->ports[i], nframes));
91 // Run the plugin.
92 state->descriptor->run(state->handle, nframes);
94 return 0;
97 // The JACK buffer size callback.
98 int buffer_size(jack_nframes_t nframes, void *arg)
100 state_t *state = (state_t *)arg;
101 float *buffer;
102 int i;
104 state->control_port_buffer = (float *)realloc
105 (state->control_port_buffer, state->num_control_ports *
106 nframes * sizeof(float));
108 buffer = state->control_port_buffer;
110 for (i = 0; i < (int)state->descriptor->PortCount; i++) {
111 if (LADSPA_IS_PORT_CONTROL(state->descriptor->
112 PortDescriptors[i]) &&
113 LADSPA_IS_PORT_INPUT(state->descriptor->PortDescriptors[i])) {
114 state->descriptor->connect_port(state->handle, i, buffer);
115 buffer += jack_get_buffer_size(state->jack_client);
119 return 0;
122 // Initializes JACK, opening the appropriate ports, instantiating the
123 // LADSPA Plugin, and starting the synthesis thread running.. Returns
124 // 1 on success. On failure, returns 0 and sets *error to an
125 // appropriate error message.
126 int init_jack(state_t *state, char **error)
128 static char client_name_prefix[] = "jackspa_";
129 int err = 0;
130 jack_status_t jack_status;
131 int i;
132 unsigned long flags;
133 float *buffer;
135 // Allocate memory for the client name.
136 state->client_name = (char *)calloc(1, sizeof(client_name_prefix) +
137 strlen(state->descriptor->Label));
138 if (!state->client_name) {
139 err = 1;
140 *error = strerror(errno);
143 // Set the client name.
144 if (!err) {
145 strcat(state->client_name, client_name_prefix);
146 strcat(state->client_name, state->descriptor->Label);
149 // Open JACK.
150 if (!err) {
151 state->jack_client = jack_client_open(state->client_name,
152 JackNullOption, &jack_status);
153 if (jack_status) {
154 *error = "could not connect to JACK";
155 err = 1;
159 // Allocate memory for the list of ports.
160 if (!err) {
161 state->ports = (jack_port_t **)calloc(state->descriptor->PortCount,
162 sizeof(jack_port_t *));
163 if (!state->ports) {
164 *error = strerror(errno);
165 err = 1;
169 // Allocate memory for the list of control port values.
170 if (!err) {
171 state->control_port_values =
172 (float *)malloc(state->descriptor->PortCount * sizeof(float));
173 if (!state->control_port_values) {
174 *error = strerror(errno);
175 err = 1;
179 // Register ports.
180 state->num_control_ports = 0;
181 for (i = 0; !err && i < (int)state->descriptor->PortCount; i++) {
182 if (LADSPA_IS_PORT_CONTROL(state->descriptor->
183 PortDescriptors[i]) &&
184 LADSPA_IS_PORT_INPUT(state->descriptor->PortDescriptors[i])) {
185 state->num_control_ports++;
186 continue;
189 if (LADSPA_IS_PORT_INPUT(state->descriptor->PortDescriptors[i])) {
190 flags = JackPortIsInput;
191 } else {
192 flags = JackPortIsOutput;
195 state->ports[i] =
196 jack_port_register(state->jack_client,
197 state->descriptor->PortNames[i],
198 JACK_DEFAULT_AUDIO_TYPE,
199 flags, 0);
201 if (!state->ports[i]) {
202 err = 1;
203 *error = "could not register JACK ports";
207 // Register our processing callback.
208 if (!err) {
209 if (jack_set_process_callback(state->jack_client, &process, state)) {
210 err = 1;
211 *error = "could not register the JACK processing callback";
215 // Register our buffer size callback.
216 if (!err) {
217 if (jack_set_buffer_size_callback(state->jack_client, &buffer_size,
218 state)) {
219 err = 1;
220 *error = "could not register the JACK processing callback";
224 // Instantiate the LADSPA plugin.
225 if (!err) {
226 state->handle = state->descriptor->instantiate
227 (state->descriptor, jack_get_sample_rate(state->jack_client));
228 if (!state->handle) {
229 err = 1;
230 *error = "could not instantiate the plugin.";
234 // Allocate control port buffers.
235 if (!err) {
236 state->control_port_buffer = (float *)malloc
237 (state->num_control_ports *
238 jack_get_buffer_size(state->jack_client) *
239 sizeof(float));
240 if (!state->control_port_buffer) {
241 err = 1;
242 *error = strerror(errno);
246 // Connect control ports.
247 if (!err) {
248 buffer = state->control_port_buffer;
250 for (i = 0; i < (int)state->descriptor->PortCount; i++) {
251 if (LADSPA_IS_PORT_CONTROL(state->descriptor->
252 PortDescriptors[i]) &&
253 LADSPA_IS_PORT_INPUT(state->descriptor->PortDescriptors[i])) {
254 state->descriptor->connect_port(state->handle, i, buffer);
255 buffer += jack_get_buffer_size(state->jack_client);
256 state->control_port_values[i] = 0.0;
261 // Activate the LADSPA plugin.
262 if (!err) {
263 if (state->descriptor->activate) {
264 state->descriptor->activate(state->handle);
268 // Get the bits flowing.
269 if (!err) {
270 if (jack_activate(state->jack_client)) {
271 err = 1;
272 *error = "could not activate audio processing";
276 return !err;
279 typedef enum {
280 st_want_plugin_file,
281 st_want_plugin_id,
282 st_done
283 } arg_parser_state;
285 // Parses command-line arguments. Returns 1 on success. On failure,
286 // returns 0 and sets *error to an appropriate error message.
287 int parse_args(state_t *state, int argc, char **argv, char **plugin_file,
288 int *plugin_id, char **error)
290 int err = 0;
291 int i;
292 arg_parser_state st = st_want_plugin_file;
294 argc--;
295 argv++;
297 for (i = 0; i < argc; i++) {
298 switch (st) {
299 case st_want_plugin_file:
300 *plugin_file = argv[i];
301 st = st_want_plugin_id;
302 break;
304 case st_want_plugin_id:
305 *plugin_id = atoi(argv[i]);
306 st = st_done;
307 break;
309 case st_done:
310 break;
312 default:
313 break;
317 if (st != st_done) {
318 err = 1;
319 *error = "must supply a plugin file and a plugin ID";
322 return !err;
325 void jackspa_init(state_t *state, int argc, char **argv)
327 char *error;
328 int err = 0;
329 char *plugin_file;
330 int plugin_id;
332 state->jack_client = 0;
334 err = !parse_args(state, argc, argv, &plugin_file, &plugin_id, &error);
336 if (!err) {
337 err = !find_plugin(state, plugin_file, plugin_id, &error);
340 if (!err) {
341 err = !init_jack(state, &error);
344 if (err) {
345 fprintf(stderr, "Error: %s.\n", error);