audiofile support + improved sample rate support + results of a -Wall -Werr
[terminatorX.git] / src / tX_vttfx.cc
1 /*
2     terminatorX - realtime audio scratching software
3     Copyright (C) 1999-2002  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
31 float ladspa_dummy_output_port;
32
33 void vtt_fx :: activate ()
34 {
35         fprintf(stderr, "tX: Oops: activate() abstract vtt_fx?");
36 }
37
38 void vtt_fx :: deactivate ()
39 {
40         fprintf(stderr, "tX: Oops: deactivate() abstract vtt_fx?");
41 }
42
43 void vtt_fx :: run ()
44 {
45         fprintf(stderr, "tX: Oops: run() abstract vtt_fx?");
46 }
47
48 void vtt_fx :: save (FILE *output)
49 {
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 void vtt_fx_lp :: save (FILE *output)
78
79         guint32 type=TX_FX_BUILTINCUTOFF;
80         fwrite((void *) &type, sizeof(type), 1, output);
81 }
82
83 const char *vtt_fx_lp :: get_info_string()
84 {
85         return "TerminatorX built-in resonant lowpass filter.";
86 }
87
88
89 /* echo */
90 void vtt_fx_ec :: activate() { /* NOP */ }
91 void vtt_fx_ec :: deactivate() { myvtt->ec_clear_buffer(); }
92 void vtt_fx_ec :: run() { myvtt->render_ec(); }
93 int vtt_fx_ec :: isEnabled() { return myvtt->ec_enable; }
94 void vtt_fx_ec :: save (FILE *output)
95
96         guint32 type=TX_FX_BUILTINECHO;
97         fwrite((void *) &type, sizeof(type), 1, output);
98 }
99
100 const char *vtt_fx_ec :: get_info_string()
101 {
102         return "TerminatorX built-in echo effect.";
103 }
104
105
106 /******************** LADSPA fx ***/
107 /* short cut "cpd" macro to current port descriptor */
108
109 #define cpd plugin->getDescriptor()->PortDescriptors[port]
110 #define cpn plugin->getDescriptor()->PortNames[port]
111 #define cph plugin->getDescriptor()->PortRangeHints[port]
112
113 void vtt_fx_ladspa :: reconnect_buffer()
114 {
115         plugin->getDescriptor()->connect_port(instance, input_port, myvtt->output_buffer);      
116         plugin->getDescriptor()->connect_port(instance, output_port, myvtt->output_buffer);             
117 }
118
119 static void wrapstr(char *str)
120 {
121         char temp[256]="";
122         char target[2048]="";
123         char *token;
124
125         token=strtok(str, " "); 
126         
127         while(token)
128         {
129                 if (strlen(token)+strlen(temp)<10)
130                 {
131                         if (strlen(temp)) strcat(temp, " ");
132                         strcat(temp, token);
133                 }
134                 else
135                 {
136                         if (strlen(temp))
137                         {
138                                 if(strlen(target)) strcat(target, "\n");
139                                 if(strlen(temp)>10)
140                                 {
141                                         temp[8]='.';
142                                         temp[9]='.';
143                                         temp[10]='.';
144                                         temp[11]=0;
145                                 }
146                                 strcat(target, temp);
147                                 strcpy(temp,token);
148                         }
149                 }
150                 token=strtok(NULL, " ");
151         }
152
153        if (strlen(temp))
154        {
155                if(strlen(target)) strcat(target, "\n");
156                strcat(target, temp);
157        }
158
159         strcpy(str, target);
160  }
161
162 vtt_fx_ladspa :: vtt_fx_ladspa(LADSPA_Plugin *p, void *v)
163 {
164         int port;
165         float min, max;
166         char buffer[2048];
167         char buffer2[2048];
168         
169         tX_seqpar_vttfx *sp;
170
171         plugin=p; vtt=v;
172         
173         instance=(LADSPA_Handle *) plugin->getDescriptor()->instantiate(plugin->getDescriptor(), 44100);
174         
175         if (!instance)
176         {
177                 fprintf (stderr, "tX: Fatal Error: failed to instantiate plugin \"%s\".\n", plugin->getDescriptor()->Name);
178                 /* How to handle this ? */
179         }
180         
181         sp = sp_enable = new tX_seqpar_vttfx_bool();
182         sp->set_mapping_parameters(1, 0, 0, 0);
183         sprintf(buffer, "%s: Enable", plugin->getName());
184         sp->set_name(buffer, "Enable");
185         sp->set_vtt(vtt);
186         controls.push_back(sp); 
187
188         
189         /* connecting ports */
190         for (port=0; port < plugin->getPortCount(); port++)
191         {
192                 if (LADSPA_IS_PORT_AUDIO(cpd))
193                 {
194                         if (LADSPA_IS_PORT_INPUT(cpd)) input_port=port;
195                         else if (LADSPA_IS_PORT_OUTPUT(cpd)) output_port=port;
196                 }
197                 else if ((LADSPA_IS_PORT_CONTROL(cpd)) && (LADSPA_IS_PORT_INPUT(cpd)))
198                 {
199                         min=-22100;
200                         max=+22100;
201                         
202                         if (LADSPA_IS_HINT_BOUNDED_BELOW(cph.HintDescriptor)) min=cph.LowerBound;
203                         if (LADSPA_IS_HINT_BOUNDED_ABOVE(cph.HintDescriptor)) max=cph.UpperBound;
204                         
205                         if (LADSPA_IS_HINT_SAMPLE_RATE(cph.HintDescriptor)) 
206                         {
207                                 min*=44100; max*=44100;
208                         }
209                         
210                         if (LADSPA_IS_HINT_TOGGLED(cph.HintDescriptor))
211                         {
212                                 sp=new tX_seqpar_vttfx_bool();
213                                 sp->set_mapping_parameters(max, min, 0, 0);
214                         }
215                         else
216                         if (LADSPA_IS_HINT_INTEGER(cph.HintDescriptor))
217                         {
218                                 sp=new tX_seqpar_vttfx_int();
219                                 sp->set_mapping_parameters(max, min, 0, 0);
220                         }
221                         else
222                         {
223                                 sp=new tX_seqpar_vttfx_float();
224                                 sp->set_mapping_parameters(max, min, (max-min)/100.0, 1);
225                         }
226                         
227                         sprintf(buffer, "%s: %s", plugin->getLabel(), cpn);
228                         strcpy(buffer2, cpn);
229                         
230                         wrapstr(buffer2);
231                         
232                         sp->set_name(buffer, buffer2);
233                         sp->set_vtt(vtt);
234                         plugin->getDescriptor()->connect_port(instance, port, sp->get_value_ptr());
235                         controls.push_back(sp);
236                 }
237                 else if ((LADSPA_IS_PORT_CONTROL(cpd)) && (LADSPA_IS_PORT_OUTPUT(cpd)))
238                 {
239                         plugin->getDescriptor()->connect_port(instance, port, &ladspa_dummy_output_port);
240                 }
241         }
242         reconnect_buffer();
243 }
244
245 void vtt_fx_ladspa :: activate()
246 {
247         if (plugin->getDescriptor()->activate) plugin->getDescriptor()->activate(instance);
248 }
249
250 void vtt_fx_ladspa :: deactivate()
251 {
252         if (plugin->getDescriptor()->deactivate) plugin->getDescriptor()->deactivate(instance);
253 }
254
255 void vtt_fx_ladspa :: run()
256 {
257         plugin->getDescriptor()->run(instance, (vtt_class :: samples_in_mix_buffer)>>1);
258 }
259
260 int vtt_fx_ladspa :: isEnabled()
261 {
262         return (int) sp_enable->get_value();
263 }
264
265 const char *vtt_fx_ladspa :: get_info_string()
266 {
267         return plugin->get_info_string();
268 }
269
270 vtt_fx_ladspa :: ~vtt_fx_ladspa()
271 {
272         list <tX_seqpar_vttfx *> :: iterator sp;
273         
274         while (controls.size())
275         {
276                 sp=controls.begin();
277                 controls.remove((*sp));
278                 
279                 delete (*sp);
280         }               
281         plugin->getDescriptor()->cleanup(instance);
282         delete panel;
283 }
284
285
286 void vtt_fx_ladspa :: save (FILE *output)
287 {
288         long ID=plugin->getUniqueID();
289         list <tX_seqpar_vttfx *> :: iterator sp;
290         guint32 pid;
291         guint32 type=TX_FX_LADSPA;
292         guint32 count;
293         guint8 hidden;
294         float value;
295         
296         fwrite((void *) &type, sizeof(type), 1, output);
297         
298         fwrite((void *) &ID, sizeof(ID), 1, output);
299         
300         count=controls.size();
301         fwrite((void *) &count, sizeof(count), 1, output);
302         
303         for (sp=controls.begin(); sp!=controls.end(); sp++)
304         {
305                 pid=(*sp)->get_persistence_id();
306                 fwrite((void *) &pid, sizeof(pid), 1, output);
307                 value=(*sp)->get_value();
308                 fwrite((void *) &value, sizeof(value), 1, output);
309         }
310         
311         hidden=panel->is_hidden();
312         fwrite((void *) &hidden, sizeof(hidden), 1, output);
313 }
314
315 void vtt_fx_ladspa :: load (FILE *input)
316 {
317         guint32 count;
318         unsigned int i;
319         list <tX_seqpar_vttfx *> :: iterator sp;
320         guint32 pid;
321         guint8 hidden;
322         float value;
323         
324         fread((void *) &count, sizeof(count), 1, input);
325         
326         if (count!=controls.size())
327         {
328                 fprintf(stderr, "tX: Ouch! Plugin %li has less/more controls than saved!\n", plugin->getUniqueID());
329         }
330         
331         for (i=0, sp=controls.begin(); (i<count) && (sp!=controls.end()); i++, sp++) {
332                 fread((void *) &pid, sizeof(pid), 1, input);
333                 (*sp)->set_persistence_id(pid);
334                 fread((void *) &value, sizeof(value), 1, input);
335                 (*sp)->do_exec(value);
336                 (*sp)->do_update_graphics();
337         } 
338         
339         fread((void *) &hidden, sizeof(hidden), 1, input);
340         panel->hide(hidden);
341 }