jackspa: [fix] suppress the needless control_port_buffer
[ng-jackspa.git] / jackspa.c
blobdad62f6a36b1533af753ba0eb9c2be9ef6df6a5a
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"
27 /* Finds the plugin descriptor with the given ID in the given object file,
28 * storing it in state->descriptor. Returns 1 on success. On failure, returns 0
29 * and sets *error to an appropriate error message.
31 int find_plugin(state_t *state, const char *file, const unsigned long id,
32 const char **error)
34 int err = 0;
35 unsigned long i; /* port index */
36 void *library;
37 LADSPA_Descriptor *(*descriptor_fun)(unsigned long index);
38 LADSPA_Descriptor *descriptor;
40 /* Open the library. */
41 library = dlopen(file, RTLD_LAZY);
42 if (!library)
43 err = 1, *error = dlerror();
45 /* Find the ladspa_descriptor() function. */
46 if (!err) {
47 descriptor_fun = (LADSPA_Descriptor *(*)(unsigned long))
48 dlsym(library, "ladspa_descriptor");
49 if (!descriptor_fun)
50 err = 1, *error = dlerror();
53 /* Find the appropriate descriptor. */
54 for (i = 0; !err; i++) {
55 descriptor = descriptor_fun(i);
57 if (!descriptor)
58 err = 1, *error = "no such plugin index in the given file";
59 else if (descriptor->UniqueID == id) {
60 state->descriptor = descriptor;
61 break;
65 return !err;
68 /* The JACK processing callback. */
69 int process(jack_nframes_t nframes, void *arg)
71 state_t *state = (state_t *)arg;
72 unsigned long p; /* loop variable for ports */
73 LADSPA_Data buf; /* buffer for the control outputs */
75 /* Connect audio ports and unused control ports */
76 for (p = 0; p < state->descriptor->PortCount; p++)
77 if (LADSPA_IS_PORT_AUDIO(state->descriptor->PortDescriptors[p]))
78 state->descriptor->connect_port
79 ( state->handle, p,
80 (LADSPA_Data *)jack_port_get_buffer(state->jack_ports[p], nframes) );
81 else if ( LADSPA_IS_PORT_CONTROL(state->descriptor->PortDescriptors[p]) &&
82 LADSPA_IS_PORT_OUTPUT(state->descriptor->PortDescriptors[p]) )
83 state->descriptor->connect_port(state->handle, p, &buf);
84 /* forget the control output ports values */
86 /* Run the plugin. */
87 state->descriptor->run(state->handle, nframes);
89 return 0;
92 /* Initializes JACK, opening the appropriate ports, instantiating the LADSPA
93 * Plugin, and starting the synthesis thread running.. Returns 1 on success. On
94 * failure, returns 0 and sets *error to an appropriate error message.
96 int init_jack(state_t *state, const char **error)
98 static char client_name_prefix[] = "jackspa_";
99 int err = 0;
100 jack_status_t jack_status;
101 unsigned long p; /* loop variable for ports */
102 unsigned long flags;
104 /* Allocate memory for the client name. */
105 state->client_name = (char *)calloc
106 ( sizeof(client_name_prefix) + strlen(state->descriptor->Label),
107 sizeof(char) );
108 if (!state->client_name)
109 err = 1, *error = strerror(errno);
111 /* Set the client name. */
112 if (!err) {
113 /* state->client_name[0] = '\0'; */ /* done by calloc */
114 strcat(state->client_name, client_name_prefix);
115 strcat(state->client_name, state->descriptor->Label);
118 /* Open JACK. */
119 if (!err) {
120 state->jack_client =
121 jack_client_open(state->client_name, JackNullOption, &jack_status);
122 if (jack_status)
123 err = 1, *error = "could not connect to JACK";
126 /* Allocate memory for the list of ports. */
127 if (!err) {
128 state->jack_ports = (jack_port_t **)calloc
129 (state->descriptor->PortCount, sizeof(jack_port_t *));
130 if (!state->jack_ports)
131 err = 1, *error = strerror(errno);
134 /* Allocate memory for the list of control port values. */
135 if (!err) {
136 state->control_port_values = (LADSPA_Data *)calloc
137 ((size_t)state->descriptor->PortCount, sizeof(LADSPA_Data));
138 if (!state->control_port_values)
139 err = 1, *error = strerror(errno);
142 /* Register ports. */
143 state->num_control_ports = 0;
144 for (p = 0; !err && p < state->descriptor->PortCount; p++) {
145 if ( LADSPA_IS_PORT_CONTROL(state->descriptor-> PortDescriptors[p]) &&
146 LADSPA_IS_PORT_INPUT(state->descriptor->PortDescriptors[p]) )
148 state->num_control_ports++;
149 continue;
152 if (LADSPA_IS_PORT_INPUT(state->descriptor->PortDescriptors[p]))
153 flags = JackPortIsInput;
154 else if (LADSPA_IS_PORT_AUDIO(state->descriptor->PortDescriptors[p]))
155 flags = JackPortIsOutput;
156 else
157 continue; /* skip the control outputs (aka meters) */
159 state->jack_ports[p] = jack_port_register
160 ( state->jack_client, state->descriptor->PortNames[p],
161 JACK_DEFAULT_AUDIO_TYPE, flags, 0 );
163 if (!state->jack_ports[p])
164 err = 1, *error = "could not register JACK ports";
167 /* Register our processing callback. */
168 if (!err)
169 if (jack_set_process_callback(state->jack_client, &process, state))
170 err = 1, *error = "could not register the JACK processing callback";
172 /* Instantiate the LADSPA plugin. */
173 if (!err) {
174 state->handle = state->descriptor->instantiate
175 (state->descriptor, jack_get_sample_rate(state->jack_client));
176 if (!state->handle)
177 err = 1, *error = "could not instantiate the plugin.";
180 /* Connect input control ports. */
181 if (!err)
182 for (p = 0; p < state->descriptor->PortCount; p++)
183 if ( LADSPA_IS_PORT_CONTROL(state->descriptor->PortDescriptors[p]) &&
184 LADSPA_IS_PORT_INPUT(state->descriptor->PortDescriptors[p]))
186 state->descriptor->connect_port
187 (state->handle, p, &state->control_port_values[p]);
188 /* state->control_port_values[p] = 0.0; */ /* done by calloc() */
191 /* Activate the LADSPA plugin. */
192 if (!err)
193 if (state->descriptor->activate)
194 state->descriptor->activate(state->handle);
196 /* Get the bits flowing. */
197 if (!err)
198 if (jack_activate(state->jack_client))
199 err = 1, *error = "could not activate audio processing";
201 return !err;
204 typedef enum {
205 st_want_plugin_file,
206 st_want_plugin_id,
207 st_done
208 } arg_parser_state;
210 /* Parses command-line arguments. Returns 1 on success. On failure, returns 0
211 * and sets *error to an appropriate error message.
213 int parse_args(state_t *state, int argc, char **argv, char **plugin_file,
214 unsigned long *plugin_id, const char **error)
216 int err = 0;
217 int i; /* arg index */
218 arg_parser_state st = st_want_plugin_file;
220 argc--, argv++; /* skip the program name */
222 for (i = 0; i < argc; i++)
223 switch (st) {
224 case st_want_plugin_file:
225 *plugin_file = argv[i];
226 st = st_want_plugin_id;
227 break;
229 case st_want_plugin_id:
230 *plugin_id = atol(argv[i]);
231 st = st_done;
232 break;
234 case st_done:
235 default:
236 break;
239 if (st != st_done)
240 err = 1, *error = "must supply a plugin file and a plugin ID";
242 return !err;
245 int jackspa_init(state_t *state, int argc, char **argv)
247 const char *error;
248 int err = 0;
249 char *plugin_file;
250 unsigned long plugin_id;
252 state->jack_client = 0;
254 err = !parse_args(state, argc, argv, &plugin_file, &plugin_id, &error);
256 if (!err)
257 err = !find_plugin(state, plugin_file, plugin_id, &error);
259 if (!err)
260 err = !init_jack(state, &error);
262 if (err)
263 fprintf(stderr, "jackspa error: %s\n", error);
265 return !err;