]> git.sesse.net Git - mlt/blob - src/modules/jackrack/jack_rack.c
Convert jackrack printfs to mlt_log (3301094).
[mlt] / 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 #include "framework/mlt_log.h"
39
40 #ifndef _
41 #define _(x) x
42 #endif
43 #define _x (const xmlChar*)
44 #define _s (const char*)
45
46 jack_rack_t *
47 jack_rack_new (const char * client_name, unsigned long channels)
48 {
49   jack_rack_t *rack;
50
51   rack = g_malloc (sizeof (jack_rack_t));
52   rack->saved_plugins  = NULL;
53   rack->channels       = channels;
54   rack->procinfo = process_info_new (client_name, channels, FALSE, FALSE);
55   if (!rack->procinfo) {
56     g_free (rack);
57     return NULL;
58   }
59   rack->plugin_mgr = plugin_mgr_new ();
60   plugin_mgr_set_plugins (rack->plugin_mgr, channels);
61
62   return rack;
63 }
64
65
66 void
67 jack_rack_destroy (jack_rack_t * jack_rack)
68 {
69   process_quit (jack_rack->procinfo);
70   plugin_mgr_destroy (jack_rack->plugin_mgr);
71   process_info_destroy (jack_rack->procinfo);
72   g_slist_free (jack_rack->saved_plugins);
73   g_free (jack_rack);
74 }
75
76 plugin_t *
77 jack_rack_instantiate_plugin (jack_rack_t * jack_rack, plugin_desc_t * desc)
78 {
79   plugin_t * plugin;
80   
81   /* check whether or not the plugin is RT capable and confirm with the user if it isn't */
82   if (!LADSPA_IS_HARD_RT_CAPABLE(desc->properties)) {
83     mlt_log_info( NULL, "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",
84                desc->name);
85   }
86
87   /* create the plugin */
88   plugin = plugin_new (desc, jack_rack);
89
90   if (!plugin) {
91    mlt_log_error( NULL, "Error loading file plugin '%s' from file '%s'\n",
92                desc->name, desc->object_file);
93   }
94   
95   return plugin;
96 }
97
98
99 void
100 jack_rack_add_saved_plugin (jack_rack_t * jack_rack, saved_plugin_t * saved_plugin)
101 {
102   plugin_t * plugin = jack_rack_instantiate_plugin (jack_rack, saved_plugin->settings->desc);
103   if (!plugin)
104     return;
105   jack_rack->saved_plugins = g_slist_append (jack_rack->saved_plugins, saved_plugin);
106   process_add_plugin (jack_rack->procinfo, plugin);
107   jack_rack_add_plugin (jack_rack, plugin);
108 }
109
110
111 void
112 jack_rack_add_plugin (jack_rack_t * jack_rack, plugin_t * plugin)
113 {
114   saved_plugin_t * saved_plugin = NULL;
115   GSList * list;
116   unsigned long control, channel;
117   LADSPA_Data value;
118   guint copy;
119   
120   /* see if there's any saved settings that match the plugin id */
121   for (list = jack_rack->saved_plugins; list; list = g_slist_next (list))
122     {
123       saved_plugin = list->data;
124       
125       if (saved_plugin->settings->desc->id == plugin->desc->id)
126         {
127           /* process the settings! */
128           jack_rack->saved_plugins = g_slist_remove (jack_rack->saved_plugins, saved_plugin);
129           break;
130         }
131       saved_plugin = NULL;
132     }
133         
134   /* initialize plugin parameters */
135   plugin->enabled = settings_get_enabled (saved_plugin->settings);
136   plugin->wet_dry_enabled = settings_get_wet_dry_enabled (saved_plugin->settings);
137         
138   for (control = 0; control < saved_plugin->settings->desc->control_port_count; control++)
139     for (copy = 0; copy < plugin->copies; copy++)
140       {
141         value = settings_get_control_value (saved_plugin->settings, copy, control);
142         plugin->holders[copy].control_memory[control] = value;
143 //mlt_log_debug( NULL, "setting control value %s (%d) = %f\n", saved_plugin->settings->desc->port_names[control], copy, value);
144 //        lff_write (plugin->holders[copy].ui_control_fifos + control, &value);
145       }
146   if (plugin->wet_dry_enabled)
147     for (channel = 0; channel < jack_rack->channels; channel++)
148       {
149         value = settings_get_wet_dry_value (saved_plugin->settings, channel);
150         plugin->wet_dry_values[channel] = value;
151 //mlt_log_debug( NULL, "setting wet/dry value %d = %f\n", channel, value);
152 //        lff_write (plugin->wet_dry_fifos + channel, &value);
153       }
154 }
155
156
157 static void
158 saved_rack_parse_plugin (jack_rack_t * jack_rack, saved_rack_t * saved_rack, saved_plugin_t * saved_plugin,
159                          const char * filename, xmlNodePtr plugin)
160 {
161   plugin_desc_t * desc;
162   settings_t * settings = NULL;
163   xmlNodePtr node;
164   xmlNodePtr sub_node;
165   xmlChar *content;
166   unsigned long num;
167   unsigned long control = 0;
168 #ifdef WIN32
169   xmlFreeFunc xmlFree = NULL;
170   xmlMemGet( &xmlFree, NULL, NULL, NULL);
171 #endif
172
173   for (node = plugin->children; node; node = node->next)
174     {
175       if (xmlStrcmp (node->name, _x("id")) == 0)
176         {
177           content = xmlNodeGetContent (node);
178           num = strtoul (_s(content), NULL, 10);
179           xmlFree (content);
180
181           desc = plugin_mgr_get_any_desc (jack_rack->plugin_mgr, num);
182           if (!desc)
183             {
184               mlt_log_verbose( NULL, _("The file '%s' contains an unknown plugin with ID '%ld'; skipping\n"), filename, num);
185               return;
186             }
187           
188           settings = settings_new (desc, saved_rack->channels, saved_rack->sample_rate);
189         }
190       else if (xmlStrcmp (node->name, _x("enabled")) == 0)
191         {
192           content = xmlNodeGetContent (node);
193           settings_set_enabled (settings, xmlStrcmp (content, _x("true")) == 0 ? TRUE : FALSE);
194           xmlFree (content);
195         }
196       else if (xmlStrcmp (node->name, _x("wet_dry_enabled")) == 0)
197         {
198           content = xmlNodeGetContent (node);
199           settings_set_wet_dry_enabled (settings, xmlStrcmp (content, _x("true")) == 0 ? TRUE : FALSE);
200           xmlFree (content);
201         }
202       else if (xmlStrcmp (node->name, _x("wet_dry_locked")) == 0)
203         {
204           content = xmlNodeGetContent (node);
205           settings_set_wet_dry_locked (settings, xmlStrcmp (content, _x("true")) == 0 ? TRUE : FALSE);
206           xmlFree (content);
207         }
208       else if (xmlStrcmp (node->name, _x("wet_dry_values")) == 0)
209         {
210           unsigned long channel = 0;
211           
212           for (sub_node = node->children; sub_node; sub_node = sub_node->next)
213             {
214               if (xmlStrcmp (sub_node->name, _x("value")) == 0)
215                 {
216                   content = xmlNodeGetContent (sub_node);
217                   settings_set_wet_dry_value (settings, channel, strtod (_s(content), NULL));
218                   xmlFree (content);
219                   
220                   channel++;
221                 }
222             }
223         }
224       else if (xmlStrcmp (node->name, _x("lockall")) == 0)
225         {
226           content = xmlNodeGetContent (node);
227           settings_set_lock_all (settings, xmlStrcmp (content, _x("true")) == 0 ? TRUE : FALSE);
228           xmlFree (content);
229         }
230       else if (xmlStrcmp (node->name, _x("controlrow")) == 0)
231         {
232           gint copy = 0;
233
234           for (sub_node = node->children; sub_node; sub_node = sub_node->next)
235             {
236               if (xmlStrcmp (sub_node->name, _x("lock")) == 0)
237                 {
238                   content = xmlNodeGetContent (sub_node);
239                   settings_set_lock (settings, control, xmlStrcmp (content, _x("true")) == 0 ? TRUE : FALSE);
240                   xmlFree (content);
241                 }
242               else if (xmlStrcmp (sub_node->name, _x("value")) == 0)
243                 {
244                   content = xmlNodeGetContent (sub_node);
245                   settings_set_control_value (settings, copy, control, strtod (_s(content), NULL));
246                   xmlFree (content);
247                   copy++;
248                 }
249             }
250           
251           control++;
252         }
253     }
254   
255   if (settings)
256     saved_plugin->settings = settings;
257 }
258
259 static void
260 saved_rack_parse_jackrack (jack_rack_t * jack_rack, saved_rack_t * saved_rack, const char * filename, xmlNodePtr jackrack)
261 {
262   xmlNodePtr node;
263   xmlChar *content;
264   saved_plugin_t * saved_plugin;
265 #ifdef WIN32
266   xmlFreeFunc xmlFree = NULL;
267   xmlMemGet( &xmlFree, NULL, NULL, NULL);
268 #endif
269
270   for (node = jackrack->children; node; node = node->next)
271     {
272       if (xmlStrcmp (node->name, _x("channels")) == 0)
273         {
274           content = xmlNodeGetContent (node);
275           saved_rack->channels = strtoul (_s(content), NULL, 10);
276           xmlFree (content);
277         }
278       else if (xmlStrcmp (node->name, _x("samplerate")) == 0)
279         {
280           content = xmlNodeGetContent (node);
281           saved_rack->sample_rate = strtoul (_s(content), NULL, 10);
282           xmlFree (content);
283         }
284       else if (xmlStrcmp (node->name, _x("plugin")) == 0)
285         {
286           saved_plugin = g_malloc0 (sizeof (saved_plugin_t));
287           saved_rack->plugins = g_slist_append (saved_rack->plugins, saved_plugin);
288           saved_rack_parse_plugin (jack_rack, saved_rack, saved_plugin, filename, node);
289         }
290     }
291 }
292
293 static saved_rack_t *
294 saved_rack_new (jack_rack_t * jack_rack, const char * filename, xmlDocPtr doc)
295 {
296   xmlNodePtr node;
297   saved_rack_t *saved_rack;
298   
299   /* create the saved rack */
300   saved_rack = g_malloc (sizeof (saved_rack_t));
301   saved_rack->plugins = NULL;
302   saved_rack->sample_rate = 48000;
303   saved_rack->channels = 2;
304   
305   for (node = doc->children; node; node = node->next)
306     {
307       if (xmlStrcmp (node->name, _x("jackrack")) == 0)
308         saved_rack_parse_jackrack (jack_rack, saved_rack, filename, node);
309     }
310   
311   return saved_rack;
312 }
313
314 static void
315 saved_rack_destroy (saved_rack_t * saved_rack)
316 {
317   GSList * list;
318   
319   for (list = saved_rack->plugins; list; list = g_slist_next (list))
320     settings_destroy (((saved_plugin_t *) list->data)->settings);
321   g_slist_free (saved_rack->plugins);
322   g_free (saved_rack);
323 }
324
325
326 int
327 jack_rack_open_file (jack_rack_t * jack_rack, const char * filename)
328 {
329   xmlDocPtr doc;
330   saved_rack_t * saved_rack;
331   GSList * list;
332   saved_plugin_t * saved_plugin;
333
334   doc = xmlParseFile (filename);
335   if (!doc)
336     {
337       mlt_log_error( NULL, _("Could not parse file '%s'\n"), filename);
338       return 1;
339     }
340   
341   if (xmlStrcmp ( ((xmlDtdPtr)doc->children)->name, _x("jackrack")) != 0)
342     {
343       mlt_log_error( NULL, _("The file '%s' is not a JACK Rack settings file\n"), filename);
344       return 1;
345     }
346   
347   saved_rack = saved_rack_new (jack_rack, filename, doc);
348   xmlFreeDoc (doc);
349   
350   if (!saved_rack)
351     return 1;
352
353   for (list = saved_rack->plugins; list; list = g_slist_next (list))
354     {
355       saved_plugin = list->data;
356       
357       settings_set_sample_rate (saved_plugin->settings, sample_rate);
358       
359       jack_rack_add_saved_plugin (jack_rack, saved_plugin);
360     }
361   
362   saved_rack_destroy (saved_rack);
363   
364   return 0;
365 }
366
367
368 /* EOF */