ALSA fix + deactivating run_adding - Alex
[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 :: reconnect_buffer()
35 {
36         /* NOP */
37 }
38
39 vtt_fx :: ~vtt_fx() {}
40
41 /******************* builtin fx ***/
42
43 /* lowpass */ 
44 void vtt_fx_lp :: activate() { myvtt->lp_reset(); }
45 void vtt_fx_lp :: deactivate() { /* NOP */ }
46 void vtt_fx_lp :: run() { myvtt->render_lp(); }
47 int vtt_fx_lp :: isEnabled() { return myvtt->lp_enable; }
48
49 void vtt_fx_lp :: save (FILE *rc, gzFile rz, char *indent) { 
50         tX_store("%s<cutoff/>\n", indent);
51 }
52
53 const char *vtt_fx_lp :: get_info_string()
54 {
55         return "TerminatorX built-in resonant lowpass filter.";
56 }
57
58
59 /* echo */
60 void vtt_fx_ec :: activate() { /* NOP */ }
61 void vtt_fx_ec :: deactivate() { myvtt->ec_clear_buffer(); }
62 void vtt_fx_ec :: run() { myvtt->render_ec(); }
63 int vtt_fx_ec :: isEnabled() { return myvtt->ec_enable; }
64
65 void vtt_fx_ec :: save (FILE *rc, gzFile rz, char *indent) { 
66         tX_store("%s<lowpass/>\n", indent);     
67 }
68
69 const char *vtt_fx_ec :: get_info_string()
70 {
71         return "TerminatorX built-in echo effect.";
72 }
73
74
75 /******************** LADSPA fx ***/
76 /* short cut "cpd" macro to current port descriptor */
77
78 #define cpd plugin->getDescriptor()->PortDescriptors[port]
79 #define cpn plugin->getDescriptor()->PortNames[port]
80 #define cph plugin->getDescriptor()->PortRangeHints[port]
81
82 void vtt_fx_ladspa :: reconnect_buffer()
83 {
84         plugin->getDescriptor()->connect_port(instance, input_port, myvtt->output_buffer);      
85         plugin->getDescriptor()->connect_port(instance, output_port, myvtt->output_buffer);             
86 }
87
88 static void wrapstr(char *str)
89 {
90         char temp[256]="";
91         char target[2048]="";
92         char *token;
93
94         token=strtok(str, " "); 
95         
96         while(token)
97         {
98                 if (strlen(token)+strlen(temp)<10)
99                 {
100                         if (strlen(temp)) strcat(temp, " ");
101                         strcat(temp, token);
102                 }
103                 else
104                 {
105                         if (strlen(temp))
106                         {
107                                 if(strlen(target)) strcat(target, "\n");
108                                 if(strlen(temp)>10)
109                                 {
110                                         temp[8]='.';
111                                         temp[9]='.';
112                                         temp[10]='.';
113                                         temp[11]=0;
114                                 }
115                                 strcat(target, temp);
116                                 strcpy(temp,token);
117                         }
118                 }
119                 token=strtok(NULL, " ");
120         }
121
122        if (strlen(temp))
123        {
124                if(strlen(target)) strcat(target, "\n");
125                strcat(target, temp);
126        }
127
128         strcpy(str, target);
129  }
130
131 vtt_fx_ladspa :: vtt_fx_ladspa(LADSPA_Plugin *p, void *v)
132 {
133         int port;
134         float min, max;
135         char buffer[2048];
136         char buffer2[2048];
137         
138         tX_seqpar_vttfx *sp;
139
140         plugin=p; vtt=v;
141         
142         instance=(LADSPA_Handle *) plugin->getDescriptor()->instantiate(plugin->getDescriptor(), 44100);
143         
144         if (!instance)
145         {
146                 fprintf (stderr, "tX: Fatal Error: failed to instantiate plugin \"%s\".\n", plugin->getDescriptor()->Name);
147                 /* How to handle this ? */
148         }
149         
150         sp = sp_enable = new tX_seqpar_vttfx_bool();
151         sp->set_mapping_parameters(1, 0, 0, 0);
152         sprintf(buffer, "%s: Enable", plugin->getName());
153         sp->set_name(buffer, "Enable");
154         sp->set_vtt(vtt);
155         controls.push_back(sp); 
156
157         /* if (plugin->getDescriptor()->run_adding && plugin->getDescriptor()->set_run_adding_gain) {   
158                 sp = sp_outgain = new tX_seqpar_vttfx_float();
159                 sp->set_mapping_parameters(3, 0, 0.01, 1);
160                 sprintf(buffer, "%s: Out Gain", plugin->getName());
161                 sp->set_name(buffer, "Out Gain");
162                 sp->set_vtt(vtt);
163                 controls.push_back(sp);
164         } else {
165                 sp_outgain = NULL;
166         } */
167         
168         sp_outgain=NULL;
169         
170         /* connecting ports */
171         for (port=0; port < plugin->getPortCount(); port++)
172         {
173                 if (LADSPA_IS_PORT_AUDIO(cpd))
174                 {
175                         if (LADSPA_IS_PORT_INPUT(cpd)) input_port=port;
176                         else if (LADSPA_IS_PORT_OUTPUT(cpd)) output_port=port;
177                 }
178                 else if ((LADSPA_IS_PORT_CONTROL(cpd)) && (LADSPA_IS_PORT_INPUT(cpd)))
179                 {
180                         min=-22100;
181                         max=+22100;
182                         
183                         if (LADSPA_IS_HINT_BOUNDED_BELOW(cph.HintDescriptor)) min=cph.LowerBound;
184                         if (LADSPA_IS_HINT_BOUNDED_ABOVE(cph.HintDescriptor)) max=cph.UpperBound;
185                         
186                         if (LADSPA_IS_HINT_SAMPLE_RATE(cph.HintDescriptor)) 
187                         {
188                                 min*=44100; max*=44100;
189                         }
190                         
191                         if (LADSPA_IS_HINT_TOGGLED(cph.HintDescriptor))
192                         {
193                                 sp=new tX_seqpar_vttfx_bool();
194                                 sp->set_mapping_parameters(max, min, 0, 0);
195                         }
196                         else
197                         if (LADSPA_IS_HINT_INTEGER(cph.HintDescriptor))
198                         {
199                                 sp=new tX_seqpar_vttfx_int();
200                                 sp->set_mapping_parameters(max, min, 0, 0);
201                         }
202                         else
203                         {
204                                 sp=new tX_seqpar_vttfx_float();
205                                 sp->set_mapping_parameters(max, min, (max-min)/100.0, 1);
206                         }
207                         
208                         sprintf(buffer, "%s: %s", plugin->getLabel(), cpn);
209                         strcpy(buffer2, cpn);
210                         
211                         wrapstr(buffer2);
212                         
213                         sp->set_name(buffer, buffer2);
214                         sp->set_vtt(vtt);
215                         plugin->getDescriptor()->connect_port(instance, port, sp->get_value_ptr());
216                         controls.push_back(sp);
217                 }
218                 else if ((LADSPA_IS_PORT_CONTROL(cpd)) && (LADSPA_IS_PORT_OUTPUT(cpd)))
219                 {
220                         plugin->getDescriptor()->connect_port(instance, port, &ladspa_dummy_output_port);
221                 }
222         }
223         reconnect_buffer();
224 }
225
226 void vtt_fx_ladspa :: activate()
227 {
228         if (plugin->getDescriptor()->activate) plugin->getDescriptor()->activate(instance);
229 }
230
231 void vtt_fx_ladspa :: deactivate()
232 {
233         if (plugin->getDescriptor()->deactivate) plugin->getDescriptor()->deactivate(instance);
234 }
235
236 void vtt_fx_ladspa :: run()
237 {
238         if (sp_outgain) {
239                 plugin->getDescriptor()->set_run_adding_gain(instance, sp_outgain->get_value());
240                 plugin->getDescriptor()->run_adding(instance, (vtt_class :: samples_in_mix_buffer)>>1);
241         } else {
242                 plugin->getDescriptor()->run(instance, (vtt_class :: samples_in_mix_buffer)>>1);
243         }
244 }
245
246 int vtt_fx_ladspa :: isEnabled()
247 {
248         return (int) sp_enable->get_value();
249 }
250
251 const char *vtt_fx_ladspa :: get_info_string()
252 {
253         return plugin->get_info_string();
254 }
255
256 vtt_fx_ladspa :: ~vtt_fx_ladspa()
257 {
258         list <tX_seqpar_vttfx *> :: iterator sp;
259         
260         while (controls.size())
261         {
262                 sp=controls.begin();
263                 controls.remove((*sp));
264                 
265                 delete (*sp);
266         }               
267         plugin->getDescriptor()->cleanup(instance);
268         delete panel;
269 }
270
271
272 void vtt_fx_ladspa :: save (FILE *rc, gzFile rz, char *indent) {
273         long ID=plugin->getUniqueID();
274         list <tX_seqpar_vttfx *> :: iterator sp;
275         
276         tX_store("%s<ladspa_plugin>\n", indent);
277         strcat (indent, "\t");
278         
279         store_int("ladspa_id", ID);
280         
281         for (sp=controls.begin(); sp!=controls.end(); sp++) {
282                 store_float_id("param", (*sp)->get_value(), (*sp)->get_persistence_id());
283         }
284         
285         store_bool("panel_hidden", panel->is_hidden());
286         
287         indent[strlen(indent)-1]=0;
288         tX_store("%s</ladspa_plugin>\n", indent);
289 }
290
291 void vtt_fx_ladspa :: load(xmlDocPtr doc, xmlNodePtr node) {
292         int dummy;
293         bool hidden=false;
294         list <tX_seqpar_vttfx *> :: iterator sp=controls.begin();
295         int elementFound;
296         guint32 pid=0;
297         double val;
298         
299         for (xmlNodePtr cur=node->xmlChildrenNode; cur!=NULL; cur=cur->next) {
300                 if (cur->type == XML_ELEMENT_NODE) {
301                         elementFound=0;
302                         
303                         restore_int("ladspa_id", dummy);
304                         restore_bool("panel_hidden", hidden);
305                         if ((!elementFound) && (xmlStrcmp(cur->name, (xmlChar *) "param")==0)) {
306                                 val=0;
307                                 elementFound=1;
308                         
309                                 if (sp==controls.end()) {
310                                         tX_warning("found unexpected parameters for ladspa plugin [%i].", dummy);
311                                 } else {                        
312                                         char *buff=(char *) xmlGetProp(cur, (xmlChar *) "id");
313                                         sscanf(buff, "%i", &pid);
314                         
315                                         if  (xmlNodeListGetString(doc, cur->xmlChildrenNode, 1)) {
316                                                 sscanf((char *) xmlNodeListGetString(doc, cur->xmlChildrenNode, 1), "%lf", &val); 
317                                         }
318                                         (*sp)->set_persistence_id(pid);
319                                         (*sp)->do_exec(val);
320                                         (*sp)->do_update_graphics();
321                                         sp++;
322                                 }
323                         }
324                         
325                         if (!elementFound) {
326                                 tX_warning("unhandled ladspa_plugin element %s.", cur->name);
327                         }
328                 }
329         }
330         
331         panel->hide(hidden);
332 }