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