b2c008abd5d2ccd1c79a14bcaa1784a47c7504a2
[terminatorX.git] / src / tX_vttfx.cc
1 /*
2     terminatorX - realtime audio scratching software
3     Copyright (C) 1999-2003  Alexander K├Ânig
4  
5     This program is free software; you can redistribute it and/or modify
6     it under the terms of the GNU General Public License as published by
7     the Free Software Foundation; either version 2 of the License, or
8     (at your option) any later version.
9  
10     This program is distributed in the hope that it will be useful,
11     but WITHOUT ANY WARRANTY; without even the implied warranty of
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13     GNU General Public License for more details.
14  
15     You should have received a copy of the GNU General Public License
16     along with this program; if not, write to the Free Software
17     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18  
19     File: tX_vttfx.cc
20  
21     Description: This handles the effects in the per vtt fx chain. Supports the
22                  buitlin echo/lowpass effects and ladspa plugins.
23 */
24
25 #include "tX_vttfx.h"
26 #include <stdio.h>
27 #include <glib.h>
28 #include "tX_vtt.h"
29 #define myvtt ((vtt_class *) vtt)
30 #include "tX_global.h"
31
32 float ladspa_dummy_output_port;
33
34 void vtt_fx :: activate ()
35 {
36         fprintf(stderr, "tX: Oops: activate() abstract vtt_fx?");
37 }
38
39 void vtt_fx :: deactivate ()
40 {
41         fprintf(stderr, "tX: Oops: deactivate() abstract vtt_fx?");
42 }
43
44 void vtt_fx :: run ()
45 {
46         fprintf(stderr, "tX: Oops: run() abstract vtt_fx?");
47 }
48
49 void vtt_fx :: save(FILE *rc, gzFile rz, char *indent) {
50         fprintf(stderr, "tX: Oops: run() abstract vtt_fx?");
51 }
52
53 void vtt_fx :: reconnect_buffer()
54 {
55 }
56
57 int vtt_fx :: isEnabled ()
58 {
59         fprintf(stderr, "tX: Oops: isEnabled() abstract vtt_fx?");
60         return 0;
61 }
62
63 const char * vtt_fx :: get_info_string()
64 {
65         return "tX: Oops: Why do you see this info string?";
66 }
67
68 vtt_fx :: ~vtt_fx() {}
69
70 /******************* builtin fx ***/
71
72 /* lowpass */ 
73 void vtt_fx_lp :: activate() { myvtt->lp_reset(); }
74 void vtt_fx_lp :: deactivate() { /* NOP */ }
75 void vtt_fx_lp :: run() { myvtt->render_lp(); }
76 int vtt_fx_lp :: isEnabled() { return myvtt->lp_enable; }
77
78 void vtt_fx_lp :: save (FILE *rc, gzFile rz, char *indent) { 
79         tX_store("%s<cutoff/>\n", indent);
80 }
81
82 const char *vtt_fx_lp :: get_info_string()
83 {
84         return "TerminatorX built-in resonant lowpass filter.";
85 }
86
87
88 /* echo */
89 void vtt_fx_ec :: activate() { /* NOP */ }
90 void vtt_fx_ec :: deactivate() { myvtt->ec_clear_buffer(); }
91 void vtt_fx_ec :: run() { myvtt->render_ec(); }
92 int vtt_fx_ec :: isEnabled() { return myvtt->ec_enable; }
93
94 void vtt_fx_ec :: save (FILE *rc, gzFile rz, char *indent) { 
95         tX_store("%s<lowpass/>\n", indent);     
96 }
97
98 const char *vtt_fx_ec :: get_info_string()
99 {
100         return "TerminatorX built-in echo effect.";
101 }
102
103
104 /******************** LADSPA fx ***/
105 /* short cut "cpd" macro to current port descriptor */
106
107 #define cpd plugin->getDescriptor()->PortDescriptors[port]
108 #define cpn plugin->getDescriptor()->PortNames[port]
109 #define cph plugin->getDescriptor()->PortRangeHints[port]
110
111 void vtt_fx_ladspa :: reconnect_buffer()
112 {
113         plugin->getDescriptor()->connect_port(instance, input_port, myvtt->output_buffer);      
114         plugin->getDescriptor()->connect_port(instance, output_port, myvtt->output_buffer);             
115 }
116
117 static void wrapstr(char *str)
118 {
119         char temp[256]="";
120         char target[2048]="";
121         char *token;
122
123         token=strtok(str, " "); 
124         
125         while(token)
126         {
127                 if (strlen(token)+strlen(temp)<10)
128                 {
129                         if (strlen(temp)) strcat(temp, " ");
130                         strcat(temp, token);
131                 }
132                 else
133                 {
134                         if (strlen(temp))
135                         {
136                                 if(strlen(target)) strcat(target, "\n");
137                                 if(strlen(temp)>10)
138                                 {
139                                         temp[8]='.';
140                                         temp[9]='.';
141                                         temp[10]='.';
142                                         temp[11]=0;
143                                 }
144                                 strcat(target, temp);
145                                 strcpy(temp,token);
146                         }
147                 }
148                 token=strtok(NULL, " ");
149         }
150
151        if (strlen(temp))
152        {
153                if(strlen(target)) strcat(target, "\n");
154                strcat(target, temp);
155        }
156
157         strcpy(str, target);
158  }
159
160 vtt_fx_ladspa :: vtt_fx_ladspa(LADSPA_Plugin *p, void *v)
161 {
162         int port;
163         float min, max;
164         char buffer[2048];
165         char buffer2[2048];
166         
167         tX_seqpar_vttfx *sp;
168
169         plugin=p; vtt=v;
170         
171         instance=(LADSPA_Handle *) plugin->getDescriptor()->instantiate(plugin->getDescriptor(), 44100);
172         
173         if (!instance)
174         {
175                 fprintf (stderr, "tX: Fatal Error: failed to instantiate plugin \"%s\".\n", plugin->getDescriptor()->Name);
176                 /* How to handle this ? */
177         }
178         
179         sp = sp_enable = new tX_seqpar_vttfx_bool();
180         sp->set_mapping_parameters(1, 0, 0, 0);
181         sprintf(buffer, "%s: Enable", plugin->getName());
182         sp->set_name(buffer, "Enable");
183         sp->set_vtt(vtt);
184         controls.push_back(sp); 
185
186         
187         /* connecting ports */
188         for (port=0; port < plugin->getPortCount(); port++)
189         {
190                 if (LADSPA_IS_PORT_AUDIO(cpd))
191                 {
192                         if (LADSPA_IS_PORT_INPUT(cpd)) input_port=port;
193                         else if (LADSPA_IS_PORT_OUTPUT(cpd)) output_port=port;
194                 }
195                 else if ((LADSPA_IS_PORT_CONTROL(cpd)) && (LADSPA_IS_PORT_INPUT(cpd)))
196                 {
197                         min=-22100;
198                         max=+22100;
199                         
200                         if (LADSPA_IS_HINT_BOUNDED_BELOW(cph.HintDescriptor)) min=cph.LowerBound;
201                         if (LADSPA_IS_HINT_BOUNDED_ABOVE(cph.HintDescriptor)) max=cph.UpperBound;
202                         
203                         if (LADSPA_IS_HINT_SAMPLE_RATE(cph.HintDescriptor)) 
204                         {
205                                 min*=44100; max*=44100;
206                         }
207                         
208                         if (LADSPA_IS_HINT_TOGGLED(cph.HintDescriptor))
209                         {
210                                 sp=new tX_seqpar_vttfx_bool();
211                                 sp->set_mapping_parameters(max, min, 0, 0);
212                         }
213                         else
214                         if (LADSPA_IS_HINT_INTEGER(cph.HintDescriptor))
215                         {
216                                 sp=new tX_seqpar_vttfx_int();
217                                 sp->set_mapping_parameters(max, min, 0, 0);
218                         }
219                         else
220                         {
221                                 sp=new tX_seqpar_vttfx_float();
222                                 sp->set_mapping_parameters(max, min, (max-min)/100.0, 1);
223                         }
224                         
225                         sprintf(buffer, "%s: %s", plugin->getLabel(), cpn);
226                         strcpy(buffer2, cpn);
227                         
228                         wrapstr(buffer2);
229                         
230                         sp->set_name(buffer, buffer2);
231                         sp->set_vtt(vtt);
232                         plugin->getDescriptor()->connect_port(instance, port, sp->get_value_ptr());
233                         controls.push_back(sp);
234                 }
235                 else if ((LADSPA_IS_PORT_CONTROL(cpd)) && (LADSPA_IS_PORT_OUTPUT(cpd)))
236                 {
237                         plugin->getDescriptor()->connect_port(instance, port, &ladspa_dummy_output_port);
238                 }
239         }
240         reconnect_buffer();
241 }
242
243 void vtt_fx_ladspa :: activate()
244 {
245         if (plugin->getDescriptor()->activate) plugin->getDescriptor()->activate(instance);
246 }
247
248 void vtt_fx_ladspa :: deactivate()
249 {
250         if (plugin->getDescriptor()->deactivate) plugin->getDescriptor()->deactivate(instance);
251 }
252
253 void vtt_fx_ladspa :: run()
254 {
255         plugin->getDescriptor()->run(instance, (vtt_class :: samples_in_mix_buffer)>>1);
256 }
257
258 int vtt_fx_ladspa :: isEnabled()
259 {
260         return (int) sp_enable->get_value();
261 }
262
263 const char *vtt_fx_ladspa :: get_info_string()
264 {
265         return plugin->get_info_string();
266 }
267
268 vtt_fx_ladspa :: ~vtt_fx_ladspa()
269 {
270         list <tX_seqpar_vttfx *> :: iterator sp;
271         
272         while (controls.size())
273         {
274                 sp=controls.begin();
275                 controls.remove((*sp));
276                 
277                 delete (*sp);
278         }               
279         plugin->getDescriptor()->cleanup(instance);
280         delete panel;
281 }
282
283
284 void vtt_fx_ladspa :: save (FILE *rc, gzFile rz, char *indent) {
285         long ID=plugin->getUniqueID();
286         list <tX_seqpar_vttfx *> :: iterator sp;
287         
288         tX_store("%s<ladspa_plugin>\n", indent);
289         strcat (indent, "\t");
290         
291         store_int("ladspa_id", ID);
292         
293         for (sp=controls.begin(); sp!=controls.end(); sp++) {
294                 store_float_id("param", (*sp)->get_value(), (*sp)->get_persistence_id());
295         }
296         
297         store_bool("panel_hidden", panel->is_hidden());
298         
299         indent[strlen(indent)-1]=0;
300         tX_store("%s</ladspa_plugin>\n", indent);
301 }
302
303 void vtt_fx_ladspa :: load(xmlDocPtr doc, xmlNodePtr node) {
304         int dummy;
305         bool hidden;
306         list <tX_seqpar_vttfx *> :: iterator sp=controls.begin();
307         int elementFound;
308         guint32 pid=0;
309         double val;
310         
311         for (xmlNodePtr cur=node->xmlChildrenNode; cur!=NULL; cur=cur->next) {
312                 if (cur->type == XML_ELEMENT_NODE) {
313                         elementFound=0;
314                         
315                         restore_int("ladspa_id", dummy);
316                         restore_bool("panel_hidden", hidden);
317                         if ((!elementFound) && (xmlStrcmp(cur->name, (xmlChar *) "param")==0)) {
318                                 val=0;
319                                 elementFound=1;
320                         
321                                 if (sp==controls.end()) {
322                                         tX_warning("found unexpected parameters for ladspa plugin [%i].", dummy);
323                                 } else {                        
324                                         char *buff=(char *) xmlGetProp(cur, (xmlChar *) "id");
325                                         sscanf(buff, "%i", &pid);
326                         
327                                         if  (xmlNodeListGetString(doc, cur->xmlChildrenNode, 1)) {
328                                                 sscanf((char *) xmlNodeListGetString(doc, cur->xmlChildrenNode, 1), "%lf", &val); 
329                                         }
330                                         (*sp)->set_persistence_id(pid);
331                                         (*sp)->do_exec(val);
332                                         (*sp)->do_update_graphics();
333                                         sp++;
334                                 }
335                         }
336                         
337                         if (!elementFound) {
338                                 tX_warning("unhandled ladspa_plugin element %s.", cur->name);
339                         }
340                 }
341         }
342         
343         panel->hide(hidden);
344 }