af9e4ef97e3525d5b0dd11f2f3000e2f5c5274b5
[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         const char* last_word;
167         char buffer[2048];
168         char buffer2[2048];
169         
170         tX_seqpar_vttfx *sp;
171
172         plugin=p; vtt=v;
173         
174         instance=(LADSPA_Handle *) plugin->getDescriptor()->instantiate(plugin->getDescriptor(), 44100);
175         
176         if (!instance)
177         {
178                 fprintf (stderr, "tX: Fatal Error: failed to instantiate plugin \"%s\".\n", plugin->getDescriptor()->Name);
179                 /* How to handle this ? */
180         }
181         
182         sp = sp_enable = new tX_seqpar_vttfx_bool();
183         sp->set_mapping_parameters(1, 0, 0, 0);
184         sprintf(buffer, "%s: Enable", plugin->getName());
185         sp->set_name(buffer, "Enable");
186         sp->set_vtt(vtt);
187         controls.push_back(sp); 
188
189         
190         /* connecting ports */
191         for (port=0; port < plugin->getPortCount(); port++)
192         {
193                 if (LADSPA_IS_PORT_AUDIO(cpd))
194                 {
195                         if (LADSPA_IS_PORT_INPUT(cpd)) input_port=port;
196                         else if (LADSPA_IS_PORT_OUTPUT(cpd)) output_port=port;
197                 }
198                 else if ((LADSPA_IS_PORT_CONTROL(cpd)) && (LADSPA_IS_PORT_INPUT(cpd)))
199                 {
200                         min=-22100;
201                         max=+22100;
202                         
203                         if (LADSPA_IS_HINT_BOUNDED_BELOW(cph.HintDescriptor)) min=cph.LowerBound;
204                         if (LADSPA_IS_HINT_BOUNDED_ABOVE(cph.HintDescriptor)) max=cph.UpperBound;
205                         
206                         if (LADSPA_IS_HINT_SAMPLE_RATE(cph.HintDescriptor)) 
207                         {
208                                 min*=44100; max*=44100;
209                         }
210                         
211                         if (LADSPA_IS_HINT_TOGGLED(cph.HintDescriptor))
212                         {
213                                 sp=new tX_seqpar_vttfx_bool();
214                                 sp->set_mapping_parameters(max, min, 0, 0);
215                         }
216                         else
217                         if (LADSPA_IS_HINT_INTEGER(cph.HintDescriptor))
218                         {
219                                 sp=new tX_seqpar_vttfx_int();
220                                 sp->set_mapping_parameters(max, min, 0, 0);
221                         }
222                         else
223                         {
224                                 sp=new tX_seqpar_vttfx_float();
225                                 sp->set_mapping_parameters(max, min, (max-min)/100.0, 1);
226                         }
227                         
228                         sprintf(buffer, "%s: %s", plugin->getLabel(), cpn);
229                         strcpy(buffer2, cpn);
230                         
231                         wrapstr(buffer2);
232                         
233                         sp->set_name(buffer, buffer2);
234                         sp->set_vtt(vtt);
235                         plugin->getDescriptor()->connect_port(instance, port, sp->get_value_ptr());
236                         controls.push_back(sp);
237                 }
238                 else if ((LADSPA_IS_PORT_CONTROL(cpd)) && (LADSPA_IS_PORT_OUTPUT(cpd)))
239                 {
240                         plugin->getDescriptor()->connect_port(instance, port, &ladspa_dummy_output_port);
241                 }
242         }
243         reconnect_buffer();
244 }
245
246 void vtt_fx_ladspa :: activate()
247 {
248         if (plugin->getDescriptor()->activate) plugin->getDescriptor()->activate(instance);
249 }
250
251 void vtt_fx_ladspa :: deactivate()
252 {
253         if (plugin->getDescriptor()->deactivate) plugin->getDescriptor()->deactivate(instance);
254 }
255
256 void vtt_fx_ladspa :: run()
257 {
258         plugin->getDescriptor()->run(instance, (vtt_class :: samples_in_mix_buffer)>>1);
259 }
260
261 int vtt_fx_ladspa :: isEnabled()
262 {
263         return (int) sp_enable->get_value();
264 }
265
266 const char *vtt_fx_ladspa :: get_info_string()
267 {
268         return plugin->get_info_string();
269 }
270
271 vtt_fx_ladspa :: ~vtt_fx_ladspa()
272 {
273         list <tX_seqpar_vttfx *> :: iterator sp;
274         
275         while (controls.size())
276         {
277                 sp=controls.begin();
278                 controls.remove((*sp));
279                 
280                 delete (*sp);
281         }               
282         plugin->getDescriptor()->cleanup(instance);
283         delete panel;
284 }
285
286
287 void vtt_fx_ladspa :: save (FILE *output)
288 {
289         long ID=plugin->getUniqueID();
290         list <tX_seqpar_vttfx *> :: iterator sp;
291         guint32 pid;
292         guint32 type=TX_FX_LADSPA;
293         guint32 count;
294         guint8 hidden;
295         float value;
296         
297         fwrite((void *) &type, sizeof(type), 1, output);
298         
299         fwrite((void *) &ID, sizeof(ID), 1, output);
300         
301         count=controls.size();
302         fwrite((void *) &count, sizeof(count), 1, output);
303         
304         for (sp=controls.begin(); sp!=controls.end(); sp++)
305         {
306                 pid=(*sp)->get_persistence_id();
307                 fwrite((void *) &pid, sizeof(pid), 1, output);
308                 value=(*sp)->get_value();
309                 fwrite((void *) &value, sizeof(value), 1, output);
310         }
311         
312         hidden=panel->is_hidden();
313         fwrite((void *) &hidden, sizeof(hidden), 1, output);
314 }
315
316 void vtt_fx_ladspa :: load (FILE *input)
317 {
318         guint32 count;
319         int i;
320         list <tX_seqpar_vttfx *> :: iterator sp;
321         guint32 pid;
322         guint8 hidden;
323         float value;
324         
325         fread((void *) &count, sizeof(count), 1, input);
326         
327         if (count!=controls.size())
328         {
329                 fprintf(stderr, "tX: Ouch! Plugin %i has less/more controls than saved!\n", plugin->getUniqueID());
330         }
331         
332         for (i=0, sp=controls.begin(); i<count, sp!=controls.end(); i++, sp++)
333         {
334                 fread((void *) &pid, sizeof(pid), 1, input);
335                 (*sp)->set_persistence_id(pid);
336                 fread((void *) &value, sizeof(value), 1, input);
337                 (*sp)->do_exec(value);
338                 (*sp)->do_update_graphics();
339         } 
340         
341         fread((void *) &hidden, sizeof(hidden), 1, input);
342         panel->hide(hidden);
343 }