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