f7b8a858260bb4fcc03761b4ba0f4a0c7016bba3
[melted] / src / modules / jackrack / jack_rack.c
1 /*
2 * JACK Rack
3 *
4 * Copyright (C) Robert Ham 2002, 2003 (node@users.sourceforge.net)
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <strings.h>
24 #include <string.h>
25 #include <ctype.h>
26
27 #include <ladspa.h>
28 #include <libxml/tree.h>
29
30 #include "jack_rack.h"
31 #include "lock_free_fifo.h"
32 #include "plugin_settings.h"
33
34 #ifndef _
35 #define _(x) x
36 #endif
37
38 jack_rack_t *
39 jack_rack_new (const char * client_name, unsigned long channels)
40 {
41 jack_rack_t *rack;
42
43 rack = g_malloc (sizeof (jack_rack_t));
44 rack->saved_plugins = NULL;
45 rack->channels = channels;
46 rack->procinfo = process_info_new (client_name, channels, FALSE, FALSE);
47 if (!rack->procinfo) {
48 g_free (rack);
49 return NULL;
50 }
51 rack->plugin_mgr = plugin_mgr_new ();
52 plugin_mgr_set_plugins (rack->plugin_mgr, channels);
53
54 return rack;
55 }
56
57
58 void
59 jack_rack_destroy (jack_rack_t * jack_rack)
60 {
61 process_quit (jack_rack->procinfo);
62 plugin_mgr_destroy (jack_rack->plugin_mgr);
63 process_info_destroy (jack_rack->procinfo);
64 g_slist_free (jack_rack->saved_plugins);
65 g_free (jack_rack);
66 }
67
68 plugin_t *
69 jack_rack_instantiate_plugin (jack_rack_t * jack_rack, plugin_desc_t * desc)
70 {
71 plugin_t * plugin;
72
73 /* check whether or not the plugin is RT capable and confirm with the user if it isn't */
74 if (!LADSPA_IS_HARD_RT_CAPABLE(desc->properties)) {
75 fprintf (stderr, "Plugin not RT capable. The plugin '%s' does not describe itself as being capable of real-time operation. You may experience drop outs or jack may even kick us out if you use it.\n",
76 desc->name);
77 }
78
79 /* create the plugin */
80 plugin = plugin_new (desc, jack_rack);
81
82 if (!plugin) {
83 fprintf (stderr, "Error loading file plugin '%s' from file '%s'\n",
84 desc->name, desc->object_file);
85 }
86
87 return plugin;
88 }
89
90
91 void
92 jack_rack_add_saved_plugin (jack_rack_t * jack_rack, saved_plugin_t * saved_plugin)
93 {
94 plugin_t * plugin = jack_rack_instantiate_plugin (jack_rack, saved_plugin->settings->desc);
95 if (!plugin)
96 return;
97 jack_rack->saved_plugins = g_slist_append (jack_rack->saved_plugins, saved_plugin);
98 process_add_plugin (jack_rack->procinfo, plugin);
99 jack_rack_add_plugin (jack_rack, plugin);
100 }
101
102
103 void
104 jack_rack_add_plugin (jack_rack_t * jack_rack, plugin_t * plugin)
105 {
106 saved_plugin_t * saved_plugin = NULL;
107 GSList * list;
108 unsigned long control, channel;
109 LADSPA_Data value;
110 guint copy;
111
112 /* see if there's any saved settings that match the plugin id */
113 for (list = jack_rack->saved_plugins; list; list = g_slist_next (list))
114 {
115 saved_plugin = list->data;
116
117 if (saved_plugin->settings->desc->id == plugin->desc->id)
118 {
119 /* process the settings! */
120 jack_rack->saved_plugins = g_slist_remove (jack_rack->saved_plugins, saved_plugin);
121 break;
122 }
123 saved_plugin = NULL;
124 }
125
126 /* initialize plugin parameters */
127 plugin->enabled = settings_get_enabled (saved_plugin->settings);
128 plugin->wet_dry_enabled = settings_get_wet_dry_enabled (saved_plugin->settings);
129
130 for (control = 0; control < saved_plugin->settings->desc->control_port_count; control++)
131 for (copy = 0; copy < plugin->copies; copy++)
132 {
133 value = settings_get_control_value (saved_plugin->settings, copy, control);
134 plugin->holders[copy].control_memory[control] = value;
135 //printf("setting control value %s (%d) = %f\n", saved_plugin->settings->desc->port_names[control], copy, value);
136 // lff_write (plugin->holders[copy].ui_control_fifos + control, &value);
137 }
138 if (plugin->wet_dry_enabled)
139 for (channel = 0; channel < jack_rack->channels; channel++)
140 {
141 value = settings_get_wet_dry_value (saved_plugin->settings, channel);
142 plugin->wet_dry_values[channel] = value;
143 //printf("setting wet/dry value %d = %f\n", channel, value);
144 // lff_write (plugin->wet_dry_fifos + channel, &value);
145 }
146 }
147
148
149 static void
150 saved_rack_parse_plugin (jack_rack_t * jack_rack, saved_rack_t * saved_rack, saved_plugin_t * saved_plugin,
151 const char * filename, xmlNodePtr plugin)
152 {
153 plugin_desc_t * desc;
154 settings_t * settings = NULL;
155 xmlNodePtr node;
156 xmlNodePtr sub_node;
157 xmlChar *content;
158 unsigned long num;
159 unsigned long control = 0;
160
161 for (node = plugin->children; node; node = node->next)
162 {
163 if (strcmp (node->name, "id") == 0)
164 {
165 content = xmlNodeGetContent (node);
166 num = strtoul (content, NULL, 10);
167 xmlFree (content);
168
169 desc = plugin_mgr_get_any_desc (jack_rack->plugin_mgr, num);
170 if (!desc)
171 {
172 fprintf (stderr, _("The file '%s' contains an unknown plugin with ID '%ld'; skipping\n"), filename, num);
173 return;
174 }
175
176 settings = settings_new (desc, saved_rack->channels, saved_rack->sample_rate);
177 }
178 else if (strcmp (node->name, "enabled") == 0)
179 {
180 content = xmlNodeGetContent (node);
181 settings_set_enabled (settings, strcmp (content, "true") == 0 ? TRUE : FALSE);
182 xmlFree (content);
183 }
184 else if (strcmp (node->name, "wet_dry_enabled") == 0)
185 {
186 content = xmlNodeGetContent (node);
187 settings_set_wet_dry_enabled (settings, strcmp (content, "true") == 0 ? TRUE : FALSE);
188 xmlFree (content);
189 }
190 else if (strcmp (node->name, "wet_dry_locked") == 0)
191 {
192 content = xmlNodeGetContent (node);
193 settings_set_wet_dry_locked (settings, strcmp (content, "true") == 0 ? TRUE : FALSE);
194 xmlFree (content);
195 }
196 else if (strcmp (node->name, "wet_dry_values") == 0)
197 {
198 unsigned long channel = 0;
199
200 for (sub_node = node->children; sub_node; sub_node = sub_node->next)
201 {
202 if (strcmp (sub_node->name, "value") == 0)
203 {
204 content = xmlNodeGetContent (sub_node);
205 settings_set_wet_dry_value (settings, channel, strtod (content, NULL));
206 xmlFree (content);
207
208 channel++;
209 }
210 }
211 }
212 else if (strcmp (node->name, "lockall") == 0)
213 {
214 content = xmlNodeGetContent (node);
215 settings_set_lock_all (settings, strcmp (content, "true") == 0 ? TRUE : FALSE);
216 xmlFree (content);
217 }
218 else if (strcmp (node->name, "controlrow") == 0)
219 {
220 gint copy = 0;
221
222 for (sub_node = node->children; sub_node; sub_node = sub_node->next)
223 {
224 if (strcmp (sub_node->name, "lock") == 0)
225 {
226 content = xmlNodeGetContent (sub_node);
227 settings_set_lock (settings, control, strcmp (content, "true") == 0 ? TRUE : FALSE);
228 xmlFree (content);
229 }
230 else if (strcmp (sub_node->name, "value") == 0)
231 {
232 content = xmlNodeGetContent (sub_node);
233 settings_set_control_value (settings, copy, control, strtod (content, NULL));
234 xmlFree (content);
235 copy++;
236 }
237 }
238
239 control++;
240 }
241 }
242
243 if (settings)
244 saved_plugin->settings = settings;
245 }
246
247 static void
248 saved_rack_parse_jackrack (jack_rack_t * jack_rack, saved_rack_t * saved_rack, const char * filename, xmlNodePtr jackrack)
249 {
250 xmlNodePtr node;
251 xmlChar *content;
252 saved_plugin_t * saved_plugin;
253
254 for (node = jackrack->children; node; node = node->next)
255 {
256 if (strcmp (node->name, "channels") == 0)
257 {
258 content = xmlNodeGetContent (node);
259 saved_rack->channels = strtoul (content, NULL, 10);
260 xmlFree (content);
261 }
262 else if (strcmp (node->name, "samplerate") == 0)
263 {
264 content = xmlNodeGetContent (node);
265 saved_rack->sample_rate = strtoul (content, NULL, 10);
266 xmlFree (content);
267 }
268 else if (strcmp (node->name, "plugin") == 0)
269 {
270 saved_plugin = g_malloc0 (sizeof (saved_plugin_t));
271 saved_rack->plugins = g_slist_append (saved_rack->plugins, saved_plugin);
272 saved_rack_parse_plugin (jack_rack, saved_rack, saved_plugin, filename, node);
273 }
274 }
275 }
276
277 static saved_rack_t *
278 saved_rack_new (jack_rack_t * jack_rack, const char * filename, xmlDocPtr doc)
279 {
280 xmlNodePtr node;
281 saved_rack_t *saved_rack;
282
283 /* create the saved rack */
284 saved_rack = g_malloc (sizeof (saved_rack_t));
285 saved_rack->plugins = NULL;
286 saved_rack->sample_rate = 48000;
287 saved_rack->channels = 2;
288
289 for (node = doc->children; node; node = node->next)
290 {
291 if (strcmp (node->name, "jackrack") == 0)
292 saved_rack_parse_jackrack (jack_rack, saved_rack, filename, node);
293 }
294
295 return saved_rack;
296 }
297
298 static void
299 saved_rack_destroy (saved_rack_t * saved_rack)
300 {
301 GSList * list;
302
303 for (list = saved_rack->plugins; list; list = g_slist_next (list))
304 settings_destroy (((saved_plugin_t *) list->data)->settings);
305 g_slist_free (saved_rack->plugins);
306 g_free (saved_rack);
307 }
308
309
310 int
311 jack_rack_open_file (jack_rack_t * jack_rack, const char * filename)
312 {
313 xmlDocPtr doc;
314 saved_rack_t * saved_rack;
315 GSList * list;
316 saved_plugin_t * saved_plugin;
317
318 doc = xmlParseFile (filename);
319 if (!doc)
320 {
321 fprintf (stderr, _("Could not parse file '%s'\n"), filename);
322 return 1;
323 }
324
325 if (strcmp ( ((xmlDtdPtr)doc->children)->name, "jackrack") != 0)
326 {
327 fprintf (stderr, _("The file '%s' is not a JACK Rack settings file\n"), filename);
328 return 1;
329 }
330
331 saved_rack = saved_rack_new (jack_rack, filename, doc);
332 xmlFreeDoc (doc);
333
334 if (!saved_rack)
335 return 1;
336
337 for (list = saved_rack->plugins; list; list = g_slist_next (list))
338 {
339 saved_plugin = list->data;
340
341 settings_set_sample_rate (saved_plugin->settings, sample_rate);
342
343 jack_rack_add_saved_plugin (jack_rack, saved_plugin);
344 }
345
346 saved_rack_destroy (saved_rack);
347
348 return 0;
349 }
350
351
352 /* EOF */