Misc stuff, adding new glade stuff - Alex
[terminatorX.git] / src / tX_vtt.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_vtt.cc
20  
21     Description: This implements the new virtual turntable class. It replaces
22                  the old turntable.c from terminatorX 3.2 and earlier. The lowpass
23                  filter is based on some sample code by Paul Kellett
24                  <paul.kellett@maxim.abel.co.uk>
25                  
26     08 Dec 1999 - Switched to the new audiofile class            
27 */    
28
29 #include "tX_vtt.h"
30 #include "tX_global.h"
31 #include <stdio.h>
32 #include "malloc.h"
33 #include <math.h>
34 #include "tX_mastergui.h"
35 #include "tX_sequencer.h"
36 #include <glib.h>
37
38 #ifdef HAVE_CONFIG_H
39 #include <config.h>
40 #endif
41
42 #ifdef USE_3DNOW
43 #include "3dnow.h"
44 #endif
45
46 #ifdef DEBUG
47 #define tX_freemem(ptr, varname, comment); fprintf(stderr, "** free() [%s] at %08x. %s.\n", varname, ptr, comment); free(ptr);
48 #define tX_malloc(ptr, varname, comment, size, type); fprintf(stderr, "**[1/2] malloc() [%s]. Size: %i. %s.\n", varname, size, comment); ptr=type malloc(size); fprintf(stderr, "**[2/2] malloc() [%s]. ptr: %08x.\n", varname, ptr);
49 #else
50 #define tX_freemem(ptr, varname, comment); free(ptr);
51 #define tX_malloc(ptr, varname, comment, size, type); ptr=type malloc(size);
52 #endif
53
54 #include "tX_loaddlg.h"
55
56 #define USE_PREFETCH 1
57
58 #ifdef USE_PREFETCH
59 #define my_prefetch(base, index); __asm__  __volatile__ ("prefetch index(%0)\n" : : "r" (base));
60 #define my_prefetchw(base, index); __asm__  __volatile__ ("prefetchw index(%0)\n" : : "r" (base));
61 #else
62 #define my_prefetch(base, index);  /* NOP */;
63 #define my_prefetchw(base, index); /* NOP */;
64 #endif
65
66 extern void build_vtt_gui(vtt_class *);
67 extern void gui_set_name(vtt_class *vtt, char *newname);
68 extern void gui_set_filename(vtt_class *vtt, char *newname);
69 extern void delete_gui(vtt_class *vtt);
70 extern void gui_update_display(vtt_class *vtt);
71 extern void gui_clear_master_button(vtt_class *vtt);
72 extern void cleanup_vtt(vtt_class *vtt);
73 extern int vg_get_current_page(vtt_class *vtt);
74 extern f_prec gui_get_audio_x_zoom(vtt_class *vtt);
75 extern void gui_set_audio_x_zoom(vtt_class *vtt, f_prec);
76
77
78 int vtt_class::vtt_amount=0;
79 list <vtt_class *> vtt_class::main_list;
80 list <vtt_class *> vtt_class::render_list;
81 int16_t* vtt_class::mix_out_buffer=NULL;
82 f_prec * vtt_class::mix_buffer=NULL;
83 f_prec * vtt_class::mix_buffer_end=NULL;
84 int vtt_class::solo_ctr=0;
85
86 int vtt_class::samples_in_mix_buffer=0;
87 pthread_mutex_t vtt_class::render_lock=PTHREAD_MUTEX_INITIALIZER;
88 f_prec vtt_class::master_volume=1.0;
89 f_prec vtt_class::res_master_volume=1.0;
90 f_prec vtt_class::saturate_fac=0.1;
91 int vtt_class::do_saturate=0;
92 vtt_class * vtt_class::sync_master=NULL;
93 int vtt_class::master_triggered=0;
94 int vtt_class::master_triggered_at=0;
95 vtt_class * vtt_class::focused_vtt=NULL;
96 f_prec vtt_class::mix_max_l=0;
97 f_prec vtt_class::mix_max_r=0;
98 f_prec vtt_class::vol_channel_adjust=1.0;
99
100 #define GAIN_AUTO_ADJUST 0.8
101
102 vtt_class :: vtt_class (int do_create_gui)
103 {       
104         vtt_amount++;
105         sprintf (name, "Turntable %i", vtt_amount);
106         strcpy(filename, "NONE");
107         buffer=NULL;
108         samples_in_buffer=0;
109         
110         set_volume(1);
111         set_pitch(1);
112         
113         autotrigger=1;
114         loop=1;
115         
116         is_playing=0;
117         is_sync_master=0;
118         is_sync_client=0;
119         sync_cycles=0,
120         sync_countdown=0;
121         
122         lp_enable=0;
123         lp_reso=0.8;
124         lp_freq=0.3;
125         lp_gain=1;
126         lp_setup(lp_gain, lp_reso, lp_freq);
127         lp_reset();
128         
129         ec_enable=0;
130         ec_length=0.5;
131         ec_feedback=0.3;
132         ec_clear_buffer();
133         ec_set_length(0.5);
134         ec_set_pan(0);
135         ec_set_volume(1);
136         
137         main_list.push_back(this);
138
139         /* "connecting" the seq-parameters */
140         
141         sp_speed.set_vtt((void *) this);
142         sp_volume.set_vtt((void *) this);       
143         sp_pitch.set_vtt((void *) this);        
144         sp_pan.set_vtt((void *) this);
145         sp_trigger.set_vtt((void *) this);      
146         sp_loop.set_vtt((void *) this); 
147         sp_sync_client.set_vtt((void *) this);  
148         sp_sync_cycles.set_vtt((void *) this);  
149         sp_lp_enable.set_vtt((void *) this);    
150         sp_lp_gain.set_vtt((void *) this);      
151         sp_lp_reso.set_vtt((void *) this);      
152         sp_lp_freq.set_vtt((void *) this);      
153         sp_ec_enable.set_vtt((void *) this);    
154         sp_ec_length.set_vtt((void *) this);
155         sp_ec_pan.set_vtt((void *) this);
156         sp_ec_volume.set_vtt((void *) this);
157         sp_ec_feedback.set_vtt((void *) this);          
158         sp_mute.set_vtt((void *) this);
159         sp_spin.set_vtt((void *) this);
160
161         x_par = &sp_speed;
162         y_par = &sp_lp_freq;
163         
164         lp_fx=new vtt_fx_lp();
165         lp_fx->set_vtt((void *) this);
166         fx_list.push_back(lp_fx);
167
168         ec_fx=new vtt_fx_ec();
169         ec_fx->set_vtt((void *) this);
170         fx_list.push_back(ec_fx);
171         
172         if (do_create_gui)
173         {       
174                 build_vtt_gui(this);
175                 lp_fx->set_panel_widget(gui.lp_panel->get_widget());    
176                 ec_fx->set_panel_widget(gui.ec_panel->get_widget());
177         }
178         else have_gui=0;
179                 
180         set_pan(0);     
181         set_master_volume(globals.volume);
182         set_output_buffer_size(samples_in_mix_buffer/2);
183         
184         audiofile = NULL;
185         audiofile_pitch_correction=0;
186         mix_solo=0;
187         mix_mute=0;
188         res_mute=mute;
189         res_mute_old=0;
190         
191         audio_hidden=false;
192         control_hidden=false;\r
193 }
194
195 vtt_class :: ~vtt_class()
196 {
197         vtt_fx *effect;
198         stop();
199
200         main_list.remove(this);
201         if (audiofile) delete audiofile;
202         //if (buffer) free(buffer);
203         if (output_buffer) tX_freemem(output_buffer, "output_buffer", "vtt Destructor");
204         vtt_amount--;
205         
206         while (fx_list.size())
207         { 
208                 effect=(*fx_list.begin());
209                 fx_list.remove(effect);
210                 delete effect;
211         }
212         
213         delete_gui(this);
214 }
215
216 void vtt_class :: set_name(char *newname)
217 {
218         strcpy(name, newname);
219         gui_set_name(this, name);       
220 }
221
222 tX_audio_error vtt_class :: load_file(char *fname)
223 {
224         tX_audio_error res;
225         int was_playing=is_playing;
226         
227         if (is_playing) stop();
228
229         if (audiofile) delete(audiofile);
230         
231         buffer=NULL;
232         samples_in_buffer=0;
233         maxpos=0;
234         strcpy(filename,"");
235
236         audiofile=new tx_audiofile();
237         res=audiofile->load(fname);     
238         
239         if (res==TX_AUDIO_SUCCESS) {
240                 buffer=audiofile->get_buffer();
241                 double file_rate=audiofile->get_sample_rate();
242                 audiofile_pitch_correction=file_rate/44100.0;
243                 recalc_pitch();
244                 samples_in_buffer=audiofile->get_no_samples();
245                 maxpos=audiofile->get_no_samples();
246                 strcpy(filename, fname);
247                 if (was_playing) trigger();
248 //              printf("Successfully loaded %s, %08x, %i\n", fname, buffer, samples_in_buffer);
249         }
250         
251         if (have_gui)
252         {
253                 gui_update_display(this);
254         }
255         ec_set_length(ec_length);
256         
257         return(res);
258 }
259
260 int vtt_class :: set_output_buffer_size(int newsize)
261 {
262         list <vtt_fx *> :: iterator effect;
263
264         if (ec_output_buffer) tX_freemem(ec_output_buffer, "ec_output_buffer", "vtt set_output_buffer_size()");
265         tX_malloc(ec_output_buffer, "ec_output_buffer", "vtt set_output_buffer_size()", sizeof(float)*newsize, (float *));
266
267         if (output_buffer) tX_freemem(output_buffer, "output_buffer", "vtt set_output_buffer_size()");
268         tX_malloc(output_buffer, "output_buffer", "vtt set_output_buffer_size()", sizeof(float)*newsize, (float *));
269
270         end_of_outputbuffer = output_buffer + newsize; //size_t(sizeof(float)*(newsize));
271         
272         samples_in_outputbuffer=newsize;
273         inv_samples_in_outputbuffer=1.0/samples_in_outputbuffer;
274
275         for (effect=fx_list.begin(); effect != fx_list.end(); effect++)
276         {
277                 (*effect)->reconnect_buffer();
278         }
279         
280         if (output_buffer) return(0);   
281         else return(0);
282 }
283
284 void vtt_class :: set_volume(f_prec newvol)
285 {
286         rel_volume=newvol;
287         recalc_volume();
288 }
289
290 void vtt_class :: recalc_volume()
291 {
292         res_volume=rel_volume*res_master_volume;
293         f_prec ec_res_volume=res_volume*ec_volume;
294         
295         if (pan>0.0)
296         {
297                 res_volume_left=(1.0-pan)*res_volume;
298                 res_volume_right=res_volume;
299         }
300         else if (pan<0.0)
301         {
302                 res_volume_left=res_volume;
303                 res_volume_right=(1.0+pan)*res_volume;
304         }
305         else
306         {
307                 res_volume_left=res_volume_right=res_volume;
308         }
309         
310         if (ec_pan>0.0)
311         {
312                 ec_volume_left=(1.0-ec_pan)*ec_res_volume;
313                 ec_volume_right=ec_res_volume;
314         }
315         else if (ec_pan<0.0)
316         {
317                 ec_volume_left=ec_res_volume;
318                 ec_volume_right=(1.0+ec_pan)*ec_res_volume;
319         }
320         else
321         {
322                 ec_volume_left=ec_volume_right=ec_res_volume;
323         }       
324 //      printf("vtt_volume: %f, %f, l: %f, r: %f\n", rel_volume, res_volume, res_volume_left, res_volume_right);
325         
326 #ifdef USE_3DNOW
327         mm_res_volume.s[0]=mm_res_volume.s[1]=res_volume;
328 #endif  
329 }
330
331 void vtt_class :: set_pan(f_prec newpan)
332 {
333         pan=newpan;
334         recalc_volume();
335 }
336
337 void vtt_class :: set_pitch(f_prec newpitch)
338 {
339         rel_pitch=newpitch;
340         res_pitch=globals.pitch*rel_pitch;
341         speed=res_pitch;
342         ec_set_length(ec_length);
343 }
344
345 void vtt_class :: recalc_pitch()
346 {
347         res_pitch=globals.pitch*rel_pitch;
348         res_pitch*=audiofile_pitch_correction;
349         speed=res_pitch;
350         ec_set_length(ec_length);
351 }
352
353 void vtt_class :: set_autotrigger(int newstate)
354 {
355         autotrigger=newstate;
356 }
357
358 void vtt_class :: set_loop(int newstate)
359 {
360         loop=newstate;
361 }
362
363 void vtt_class :: set_mute(int newstate)
364 {
365         mute=newstate;
366         calc_mute();
367 }
368
369 void vtt_class :: set_mix_mute(int newstate)
370 {
371         mix_mute=newstate;
372         calc_mute();
373 }
374
375 void vtt_class :: set_mix_solo(int newstate)
376 {
377         if (mix_solo && !newstate)
378         {
379                 /* turning it off */
380                 mix_solo=0;
381                 solo_ctr--;
382         }
383         else if (!mix_solo && newstate)
384         {
385                 /* turning it on */
386                 mix_solo=1;
387                 solo_ctr++;
388         }
389         calc_mute();
390
391         /* locking ? */
392         list <vtt_class *> :: iterator vtt;
393         
394         for (vtt=main_list.begin(); vtt!=main_list.end() ; vtt++)
395         {
396                 (*vtt)->calc_mute();
397         }
398 }
399
400 void vtt_class :: lp_set_enable (int newstate)
401 {
402         lp_enable=newstate;
403         lp_reset();
404 }
405
406 void vtt_class :: lp_reset()
407 {
408         lp_buf0=lp_buf1=0;
409 }
410
411 void vtt_class :: lp_set_gain (f_prec gain)
412 {
413         lp_gain=gain;
414         lp_resgain=lp_gain*lp_autogain;
415 }
416
417 void vtt_class :: lp_set_reso(f_prec reso)
418 {
419         lp_reso=reso;
420         
421         lp_b=reso*(1.0+(1.0/lp_a));
422         lp_autogain=1.0-reso*GAIN_AUTO_ADJUST;
423         lp_resgain=lp_gain*lp_autogain;
424 }
425
426 void vtt_class :: lp_set_freq(f_prec freq)
427 {
428         lp_freq=freq;
429         
430         lp_a=0.9999-freq;
431         lp_b=lp_reso*(1.0+(1.0/lp_a));
432 }
433
434 void vtt_class :: lp_setup(f_prec gain, f_prec reso, f_prec freq)
435 {
436         lp_freq=freq;
437         lp_reso=reso;
438         
439         lp_a=1.0-freq;
440         lp_b=reso*(1.0+(1.0/lp_a));
441         
442         lp_autogain=1.0-reso*GAIN_AUTO_ADJUST;
443         lp_resgain=lp_gain*lp_autogain;
444 }
445
446 void vtt_class :: ec_set_enable(int newstate)
447 {
448         ec_enable=newstate;
449         ec_clear_buffer();
450 }
451
452
453 void vtt_class :: ec_set_pan(f_prec pan)
454 {
455         ec_pan=pan;
456
457         recalc_volume();
458 }
459
460 /* Max length is 1.0 */
461
462 void vtt_class :: ec_set_length(f_prec length)
463 {
464         int delay;
465
466         ec_length=length;
467         if (res_pitch==0) 
468         {
469                 ec_res_length=length*samples_in_buffer;
470         }
471         else
472         {
473                 ec_res_length=length*samples_in_buffer/res_pitch;       
474         }
475         
476         if (ec_res_length<0) ec_res_length*=-1;
477         
478         if (ec_res_length>=EC_MAX_BUFFER)
479         {
480                 ec_res_length=EC_MAX_BUFFER*length;
481         }
482         
483         delay=(int )floor(ec_res_length);
484         delay-=2;
485         ec_delay=&ec_buffer[delay];
486 }
487
488 void vtt_class :: ec_set_feedback(f_prec feedback)
489 {
490         ec_feedback=feedback;
491 }
492
493
494 void vtt_class :: ec_set_volume(f_prec volume)
495 {
496         ec_volume=volume;
497         recalc_volume();
498 }
499
500 void vtt_class :: ec_clear_buffer()
501 {
502         f_prec *ptr;
503         
504         for (ptr=ec_buffer; ptr<=ec_delay; ptr++)
505         {
506                 *ptr=0.0;
507         }
508         ec_ptr=ec_buffer;
509 }
510
511 void vtt_class :: render()
512 {
513         list <vtt_fx *> :: iterator effect;
514
515         if (do_scratch)
516         {
517                 if (sense_cycles>0)
518                 {
519                         sense_cycles--;
520                         if (sense_cycles==0) sp_speed.receive_input_value(0);
521                 }
522         }
523         render_scratch();
524         
525         for (effect=fx_list.begin(); effect != fx_list.end(); effect++)
526         {
527                 if ((*effect)->isEnabled()) (*effect)->run();
528         }
529 }
530
531 extern void vg_create_fx_gui(vtt_class *vtt, vtt_fx_ladspa *effect, LADSPA_Plugin *plugin);
532
533 vtt_fx_ladspa * vtt_class :: add_effect (LADSPA_Plugin *plugin)
534 {
535         vtt_fx_ladspa *new_effect;
536         
537         new_effect = new vtt_fx_ladspa (plugin, this);
538         pthread_mutex_lock(&render_lock);
539         fx_list.push_back(new_effect);
540         if (is_playing) new_effect->activate();
541         pthread_mutex_unlock(&render_lock);
542         vg_create_fx_gui(this, new_effect, plugin);
543         
544         return new_effect;
545 }
546
547 void vtt_class :: calc_speed()
548 {
549         do_mute=0;
550         fade_out=0;
551         fade_in=0;
552
553         if (speed != speed_target)
554         {
555                 speed_target=speed;
556                 speed_step=speed_target-speed_real;
557                 speed_step/=10.0;
558         }
559                         
560         if (speed_target != speed_real)
561         {
562                 speed_real+=speed_step;
563                 if ((speed_step<0) && (speed_real<speed_target)) speed_real=speed_target;
564                 else
565                 if ((speed_step>0) && (speed_real>speed_target)) speed_real=speed_target;                       
566         }
567         
568         if (fade)
569         {
570                 if ((speed_last==0) && (speed_real !=0))
571                 {
572                         fade_in=1;
573                         fade=NEED_FADE_OUT;
574                 }
575         }
576         else
577         {
578                 if ((speed_last!=0) && (speed_real==0))
579                 {
580                         fade_out=1;
581                         fade=NEED_FADE_IN;
582                 }
583         }
584
585         speed_last = speed_real;
586
587         if (res_mute != res_mute_old)
588         {
589                 if (res_mute)
590                 {
591                         fade_out=1; fade_in=0;
592                         fade=NEED_FADE_IN;
593                 }
594                 else
595                 {
596                         fade_in=1; fade_out=0;
597                         fade=NEED_FADE_OUT;
598                 }
599                 res_mute_old=res_mute;
600         }
601         else
602         {
603                 if (res_mute) do_mute=1;
604         }       
605 }
606
607 void vtt_class :: render_scratch()
608 {
609         int16_t *ptr;
610         
611         int sample;
612         
613         f_prec pos_a_f;
614         
615         f_prec amount_a;
616         f_prec amount_b;
617
618         f_prec sample_a;
619         f_prec sample_b;
620         
621         f_prec sample_res;
622         
623         f_prec *out;
624         f_prec fade_vol;        
625
626         calc_speed();
627                                         
628         for (sample =0,out=output_buffer, fade_vol=0.0; sample < samples_in_outputbuffer;sample++, out++, fade_vol+=inv_samples_in_outputbuffer)
629         {
630                 if ((speed_real!=0) || (fade_out))
631                 {
632
633                         pos_f+=speed_real;
634
635                         if (pos_f>maxpos)
636                         {
637                                 pos_f-=maxpos;
638                                 if (res_pitch>0)
639                                 {
640                                         if (loop)
641                                         {
642                                         if (is_sync_master)
643                                         {
644                                                 master_triggered=1;
645                                                 master_triggered_at=sample;
646                                         }
647                                         }
648                                         else
649                                         {
650                                                 want_stop=1;
651                                         }
652                                         
653                                 }
654                         }
655                         else if (pos_f<0)
656                         {
657                                 pos_f+=maxpos;
658                                 if (res_pitch<0)
659                                 {
660                                         if (loop)
661                                         {
662                                         if (is_sync_master)
663                                         {
664                                                 master_triggered=1;
665                                                 master_triggered_at=sample;
666                                         }
667                                         }
668                                         else
669                                         {
670                                                 want_stop=1;
671                                         }
672                                 }
673                         }
674                                 
675                         pos_a_f=floor(pos_f);
676                         pos_i=(unsigned int) pos_a_f;
677                                                                 
678                         amount_b=pos_f-pos_a_f;                         
679                         amount_a=1.0-amount_b;                          
680                                 
681                         if (do_mute)
682                         {
683                                 *out=0.0;
684                         }
685                         else
686                         {
687                                 ptr=&buffer[pos_i];
688                                 sample_a=(f_prec) *ptr;
689                         
690                                 if (pos_i == samples_in_buffer) 
691                                 {
692                                         sample_b=*buffer;
693                                 }
694                                 else
695                                 {
696                                         ptr++;
697                                         sample_b=(f_prec) *ptr;
698                                 }
699                                 
700                                 sample_res=(sample_a*amount_a)+(sample_b*amount_b);
701                                                                 
702                                 if (fade_in)
703                                 {
704                                         sample_res*=fade_vol;
705                                 }
706                                 else
707                                 if (fade_out)
708                                 {
709                                         sample_res*=1.0-fade_vol;
710                                 }
711  
712                                 *out=sample_res;
713                         }
714                 }
715                 else
716                 {
717                                 *out=0;
718                 }
719         }
720 }       
721
722 void vtt_class :: forward_turntable()
723 {
724         int sample;
725         double pos_f_tmp;
726 #ifdef pos_f_test
727         int show=0;
728         double diff;
729 #endif
730
731         calc_speed();
732
733         if ((speed_real==0) && (!fade_out)) return;
734         
735         
736         /* following code is problematic as adding speed_real*n is
737           different from adding speed_real n times to pos_f.
738           
739           well it speeds things up quite a bit and double precision
740           seems to do a satisfying job.
741           
742           #define pos_f_test to prove that.
743         */
744         
745         pos_f_tmp=pos_f+speed_real*samples_in_outputbuffer;
746         
747         if ((pos_f_tmp > 0) && (pos_f_tmp < maxpos))
748         {
749 #ifdef pos_f_test
750                 show=1;
751 #else   
752                 pos_f=pos_f_tmp;
753                 return;
754 #endif          
755         }
756                                 
757         /* now the slow way ;) */
758         
759         for (sample =0; sample < samples_in_outputbuffer; sample++)
760         {
761                         pos_f+=speed_real;
762
763                         if (pos_f>maxpos)
764                         {
765                                 pos_f-=maxpos;
766                                 if (res_pitch>0)
767                                 {
768                                         if (loop)
769                                         {
770                                         if (is_sync_master)
771                                         {
772                                                 master_triggered=1;
773                                                 master_triggered_at=sample;
774                                         }
775                                         }
776                                         else
777                                         {
778                                                 want_stop=1;
779                                         }
780                                         
781                                 }
782                         }
783                         else if (pos_f<0)
784                         {
785                                 pos_f+=maxpos;
786                                 if (res_pitch<0)
787                                 {
788                                         if (loop)
789                                         {
790                                         if (is_sync_master)
791                                         {
792                                                 master_triggered=1;
793                                                 master_triggered_at=sample;
794                                         }
795                                         }
796                                         else
797                                         {
798                                                 want_stop=1;
799                                         }
800                                 }
801                         }
802                 
803         }
804 #ifdef pos_f_test
805         if (show)
806         {
807                 diff=pos_f_tmp-pos_f;
808                 if (diff!=0) printf("fast: %f, slow: %f, diff: %f, tt: %s\n", pos_f_tmp, pos_f, diff, name);
809         }
810 #endif  
811 }       
812
813 /*
814         The following lowpass filter is based on some sample code by
815         Paul Kellett <paul.kellett@maxim.abel.co.uk>
816 */
817
818 void vtt_class :: render_lp()
819 {
820         f_prec *sample;
821                 
822         for (sample = output_buffer; sample<end_of_outputbuffer; sample++)
823         {
824                 lp_buf0 = lp_a * lp_buf0 + lp_freq * ((*sample)*lp_resgain + lp_b * (lp_buf0 - lp_buf1));
825                 lp_buf1 = lp_a * lp_buf1 + lp_freq * lp_buf0;
826                 
827                 *sample=lp_buf1;
828         }
829 }
830
831 void vtt_class :: render_ec()
832 {
833         f_prec *sample;
834         f_prec *ec_sample;
835         int i;
836
837         for (i=0, sample = output_buffer, ec_sample=ec_output_buffer; i<samples_in_outputbuffer; i++, ec_sample++,sample++, ec_ptr++)
838         {
839                 if (ec_ptr>ec_delay) ec_ptr=ec_buffer;
840                 *ec_sample=(*ec_ptr) *ec_feedback;
841                 *ec_ptr=*sample+*ec_sample;
842         }       
843 }
844
845 int vtt_class :: set_mix_buffer_size(int no_samples)
846 {
847         list <vtt_class *> :: iterator vtt;
848         int res=0;
849         
850 //      printf("vtt_class::set_mix_buffer_size(), mix_buffer: %12x, mix_out: %12x, samples: %i\n", mix_buffer, mix_out_buffer, no_samples);
851         
852         if (mix_buffer) tX_freemem(mix_buffer, "mix_buffer", "vtt set_mix_buffer_size()");
853         samples_in_mix_buffer=no_samples*2;
854
855         tX_malloc(mix_buffer, "mix_buffer", "vtt set_mix_buffer_size()", sizeof(float)*samples_in_mix_buffer, (float *));
856         mix_buffer_end=mix_buffer+samples_in_mix_buffer;
857
858 //      printf("mix_buffer: %12x\n", mix_buffer);
859 //      printf("mix_samples: %i, out_samples: %i", samples_in_mix_buffer, no_samples);
860         
861         if (mix_out_buffer) tX_freemem(mix_out_buffer, "mix_out_buffer", "vtt set_mix_buffer_size()");
862         tX_malloc(mix_out_buffer, "mix_out_buffer", "vtt set_mix_buffer_size()", sizeof(int16_t)*samples_in_mix_buffer + 4, (int16_t *));
863
864 //      printf("mix_out_buffer: %12x\n", mix_out_buffer);
865         
866         for (vtt=main_list.begin(); vtt!=main_list.end(); vtt++)
867         {
868                 res|=(*vtt)->set_output_buffer_size(no_samples);
869         }
870         
871         if ((!mix_buffer) || (!mix_out_buffer) || res) return(1);
872         return(0);
873 }
874
875 int16_t * vtt_class :: render_all_turntables()
876 {
877         list <vtt_class *> :: iterator vtt, next;
878         int sample;
879         int mix_sample;
880         f_prec temp;
881
882 #ifdef USE_3DNOW
883         mmx_t *mix;
884         mmx_t *vtt_buffer;
885         int32_t *mix_int;
886 #endif
887
888 #ifdef USE_FLASH
889         f_prec max;
890         f_prec min;
891 #ifdef USE_3DNOW
892         mmx_t mm_max;
893         mmx_t mm_min;
894         mmx_t mm_volume;
895         mmx_t mm_src1;
896         mmx_t mm_src2;
897
898 #ifndef OVERRIDE_MOVQ_AUTODETECT
899 #ifndef GCC_VERSION
900 #define GCC_VERSION (__GNUC__ * 1000 + __GNUC_MINOR__)
901 #endif /* GCC_VERSION */
902
903 #if (GCC_VERSION < 2096)
904 #warning "*************************"
905 #warning "* gcc < 2.96            *"
906 #warning "* assuming working movq *"
907 #warning "*************************"
908 #undef GCC_MOVQ_BUG_WORKAROUND
909 #else
910 #warning "*************************"
911 #warning "* gcc >= 2.96           *"
912 #warning "* using movq-workaround *"
913 #warning "*************************"
914 #define GCC_MOVQ_BUG_WORKAROUND 1
915 #endif /* GCC < 2.96 */
916 #endif /* OVERRIDE MOVQ AUTODETECVT */
917         
918 #ifdef GCC_MOVQ_BUG_WORKAROUND
919         /* REQUIRED DUE TO GCC BUG (2.96-3.0.2) */
920         mmx_t *mm_src1_ptr=&mm_src1;
921         mmx_t *mm_src2_ptr=&mm_src2;
922         mmx_t *mm_volume_ptr=&mm_volume;
923         mmx_t *mm_max_ptr=&mm_max;
924         mmx_t *mm_min_ptr=&mm_min;
925         
926 #define MM_VAR_ACC(var) (* var ## _ptr)
927 #define MM_VAR_MOVQ(var) * var ## _ptr
928 #else
929 #define MM_VAR_ACC(var) var
930 #define MM_VAR_MOVQ(var) var
931 #endif  
932         int32_t *temp_int=&mm_max.d[1];
933 #endif  
934 #endif  
935         
936         pthread_mutex_lock(&render_lock);
937         
938         if (render_list.size()==0)
939         {
940                 for (sample=0; sample<samples_in_mix_buffer; sample++)
941                 {
942                         mix_out_buffer[sample]=0;
943                 }
944         }
945         else
946         {
947                         vtt=render_list.begin();
948                         (*vtt)->render();                       
949                         max=(*vtt)->max_value;
950                         min=max;
951
952 #ifndef USE_3DNOW
953                         for (sample=0, mix_sample=0; sample<(*vtt)->samples_in_outputbuffer; sample++)
954                         {                               
955                                 temp=(*vtt)->output_buffer[sample];
956                                 mix_buffer[mix_sample]=temp*(*vtt)->res_volume_left;
957                                 mix_sample++;
958                                 mix_buffer[mix_sample]=temp*(*vtt)->res_volume_right;
959                                 mix_sample++;
960                                 
961                                 if (temp>max) max=temp;
962                                 else if (temp<min) min=temp;
963                         }
964 #else
965                         MM_VAR_ACC(mm_volume).s[0]=(*vtt)->res_volume_left;
966                         MM_VAR_ACC(mm_volume).s[1]=(*vtt)->res_volume_right;
967
968                         MM_VAR_ACC(mm_max).s[1]=MM_VAR_ACC(mm_max).s[0]=max;
969                         MM_VAR_ACC(mm_min).s[1]=MM_VAR_ACC(mm_min).s[0]=min;
970                         
971                         movq_m2r(MM_VAR_MOVQ(mm_max), mm1);
972                         movq_m2r(MM_VAR_MOVQ(mm_min), mm2);
973                                                         
974                         movq_m2r(MM_VAR_MOVQ(mm_volume), mm0);
975                         
976                         mix=(mmx_t*)mix_buffer;
977                         
978                         for (f_prec* src=(*vtt)->output_buffer; mix < (mmx_t*) mix_buffer_end;)
979                         {
980                                 /* first sample */
981                                 MM_VAR_ACC(mm_src1).s[0]=*src;
982                                 MM_VAR_ACC(mm_src1).s[1]=*src;
983                                         
984                                 /* sample * l/r volume */
985                                 movq_m2r(MM_VAR_MOVQ(mm_src1), mm3);
986                                 pfmul_r2r(mm0, mm3);
987                                 movq_r2m(mm3, *mix);
988                                         
989                                 /* next sample */
990                                 src++, mix++;
991                                 MM_VAR_ACC(mm_src2).s[0]=*src;
992                                 MM_VAR_ACC(mm_src2).s[1]=*src;
993                                         
994                                 /* sample * l/r volume */
995                                 movq_m2r(MM_VAR_MOVQ(mm_src2), mm3);
996                                 pfmul_r2r(mm0, mm3);
997                                 movq_r2m(mm3, *mix);
998                                         
999                                 /* calculating min/max */
1000                                 MM_VAR_ACC(mm_src1).s[1]=MM_VAR_ACC(mm_src2).s[0];
1001                                 movq_m2r(mm_src1, mm3);
1002                                 pfmax_r2r(mm3, mm1);
1003                                 pfmin_r2r(mm3, mm2);
1004                                 
1005                                 src++, mix++;
1006                         }
1007
1008                         movq_r2m(mm1, MM_VAR_MOVQ(mm_max));
1009                         movq_r2m(mm2, MM_VAR_MOVQ(mm_min));
1010                         
1011                         femms();
1012                         
1013                         if (MM_VAR_ACC(mm_max).s[0]>MM_VAR_ACC(mm_max).s[1]) max=MM_VAR_ACC(mm_max).s[0]; else max=MM_VAR_ACC(mm_max).s[1];
1014                         if (MM_VAR_ACC(mm_min).s[0]<MM_VAR_ACC(mm_min).s[0]) min=MM_VAR_ACC(mm_min).s[0]; else min=MM_VAR_ACC(mm_min).s[1];
1015 #endif                  
1016                         
1017                         min*=-1.0;
1018                         if (min>max) (*vtt)->max_value=min; else (*vtt)->max_value=max;
1019
1020                         if ((*vtt)->ec_enable)
1021                         {
1022 #ifndef USE_3DNOW                       
1023                                 for (sample=0, mix_sample=0; sample<(*vtt)->samples_in_outputbuffer; sample++)
1024                                 {                               
1025                                         temp=(*vtt)->ec_output_buffer[sample];
1026                                         
1027                                         mix_buffer[mix_sample]+=temp*(*vtt)->ec_volume_left;
1028                                         mix_sample++;
1029                                         mix_buffer[mix_sample]+=temp*(*vtt)->ec_volume_right;
1030                                         mix_sample++;
1031                                 }
1032 #else
1033                                 MM_VAR_ACC(mm_volume).s[0]=(*vtt)->ec_volume_left;
1034                                 MM_VAR_ACC(mm_volume).s[1]=(*vtt)->ec_volume_right;
1035                                                 
1036                                 movq_m2r(MM_VAR_MOVQ(mm_volume), mm0);
1037                                 mix =(mmx_t*)mix_buffer;
1038
1039                                 for (f_prec* src=(*vtt)->ec_output_buffer; mix < (mmx_t*) mix_buffer_end; src++, mix++)
1040                                 {
1041                                         /* first sample */
1042                                         MM_VAR_ACC(mm_src1).s[0]=*src;
1043                                         MM_VAR_ACC(mm_src1).s[1]=*src;
1044                                 
1045                                         /* sample * l/r volume */
1046                                         movq_m2r(MM_VAR_MOVQ(mm_src1), mm3);
1047                                         pfmul_r2r(mm0, mm3);
1048                                 
1049                                         /* accumulating complete mix */
1050                                         movq_m2r(*mix, mm4);
1051                                         pfadd_r2r(mm4, mm3);
1052                                         movq_r2m(mm3, *mix);
1053                                 }
1054                                 femms();
1055 #endif                          
1056                         }
1057                         
1058                         if (master_triggered)
1059                         {
1060                                 pthread_mutex_unlock(&render_lock);
1061                                 for (vtt=main_list.begin(); vtt!=main_list.end(); vtt++)
1062                                 {
1063                                         if ((*vtt)->is_sync_client)
1064                                         {
1065                                                 if ((*vtt)->sync_countdown)
1066                                                 {
1067                                                         (*vtt)->sync_countdown--;
1068                                                 }
1069                                                 else
1070                                                 {
1071                                                         (*vtt)->sync_countdown=(*vtt)->sync_cycles;
1072                                                         (*vtt)->trigger();
1073                                                 }
1074                                         }
1075                                 }
1076                                 pthread_mutex_lock(&render_lock);
1077                         }
1078                         
1079                         vtt=render_list.begin();
1080                         for (vtt++; vtt!=render_list.end(); vtt++)
1081                         {
1082                                 (*vtt)->render();                                       
1083                                 max=(*vtt)->max_value;
1084                                 min=max;
1085
1086 #ifndef USE_3DNOW
1087                                 for (sample=0, mix_sample=0; sample<(*vtt)->samples_in_outputbuffer; sample++)
1088                                 {                               
1089                                         temp=(*vtt)->output_buffer[sample];
1090                                         mix_buffer[mix_sample]+=temp*(*vtt)->res_volume_left;
1091                                         mix_sample++;                                   
1092                                         mix_buffer[mix_sample]+=temp*(*vtt)->res_volume_right;
1093                                         mix_sample++;
1094                                 
1095                                         if (temp>max) max=temp;
1096                                         else if (temp<min) min=temp;
1097                                 }
1098 #else
1099                                 MM_VAR_ACC(mm_volume).s[0]=(*vtt)->res_volume_left;
1100                                 MM_VAR_ACC(mm_volume).s[1]=(*vtt)->res_volume_right;
1101
1102                                 MM_VAR_ACC(mm_max).s[1]=MM_VAR_ACC(mm_max).s[0]=max;
1103                                 MM_VAR_ACC(mm_min).s[1]=MM_VAR_ACC(mm_min).s[0]=min;
1104                         
1105                                 movq_m2r(MM_VAR_MOVQ(mm_max), mm1);
1106                                 movq_m2r(MM_VAR_MOVQ(mm_min), mm2);
1107                                                         
1108                                 movq_m2r(MM_VAR_MOVQ(mm_volume), mm0);
1109                                 mix=(mmx_t*)mix_buffer;
1110
1111                                 for (f_prec* src=(*vtt)->output_buffer; mix < (mmx_t*) mix_buffer_end;)
1112                                 {
1113                                         /* first sample */
1114                                         MM_VAR_ACC(mm_src1).s[0]=*src;
1115                                         MM_VAR_ACC(mm_src1).s[1]=*src;
1116                                         
1117                                         /* sample * l/r volume */
1118                                         movq_m2r(MM_VAR_MOVQ(mm_src1), mm3);
1119                                         pfmul_r2r(mm0, mm3);
1120                                         
1121                                         /* accumulating complete mix */
1122                                         movq_m2r(*mix, mm4);
1123                                         pfadd_r2r(mm4, mm3);
1124                                         movq_r2m(mm3, *mix);
1125                                         
1126                                         /* next sample */
1127                                         src++, mix++;
1128                                         MM_VAR_ACC(mm_src2).s[0]=*src;
1129                                         MM_VAR_ACC(mm_src2).s[1]=*src;
1130                                         
1131                                         /* sample * l/r volume */
1132                                         movq_m2r(MM_VAR_MOVQ(mm_src2), mm3);
1133                                         pfmul_r2r(mm0, mm3);
1134
1135                                         /* accumulating complete mix */
1136                                         movq_m2r(*mix, mm4);
1137                                         pfadd_r2r(mm4, mm3);
1138                                         movq_r2m(mm3, *mix);
1139                                         
1140                                         /* calculating min/max */
1141                                         MM_VAR_ACC(mm_src1).s[1]=MM_VAR_ACC(mm_src2).s[0];
1142                                         movq_m2r(MM_VAR_MOVQ(mm_src1), mm3);
1143                                         pfmax_r2r(mm3, mm1);
1144                                         pfmin_r2r(mm3, mm2);
1145                                         
1146                                         src++, mix++;
1147                                 }
1148
1149                                 movq_r2m(mm1, MM_VAR_MOVQ(mm_max));
1150                                 movq_r2m(mm2, MM_VAR_MOVQ(mm_min));
1151                                 
1152                                 femms();
1153         
1154                                 if (MM_VAR_ACC(mm_max).s[0]>MM_VAR_ACC(mm_max).s[1]) max=MM_VAR_ACC(mm_max).s[0]; else max=MM_VAR_ACC(mm_max).s[1];
1155                                 if (MM_VAR_ACC(mm_min).s[0]<MM_VAR_ACC(mm_min).s[0]) min=MM_VAR_ACC(mm_min).s[0]; else min=MM_VAR_ACC(mm_min).s[1];
1156 #endif
1157                                 
1158                                 min*=-1.0;
1159                                 if (min>max) (*vtt)->max_value=min; else (*vtt)->max_value=max;
1160                                 
1161                                 if ((*vtt)->ec_enable)
1162                                 {
1163 #ifndef USE_3DNOW
1164                                         for (sample=0, mix_sample=0; sample<(*vtt)->samples_in_outputbuffer; sample++)
1165                                         {                               
1166                                                 temp=(*vtt)->ec_output_buffer[sample];
1167                                                 
1168                                                 mix_buffer[mix_sample]+=temp*(*vtt)->ec_volume_left;
1169                                                 mix_sample++;
1170                                                 mix_buffer[mix_sample]+=temp*(*vtt)->ec_volume_right;
1171                                                 mix_sample++;
1172                                         }
1173 #else
1174                                         MM_VAR_ACC(mm_volume).s[0]=(*vtt)->ec_volume_left;
1175                                         MM_VAR_ACC(mm_volume).s[1]=(*vtt)->ec_volume_right;
1176                                                 
1177                                         movq_m2r(MM_VAR_MOVQ(mm_volume), mm0);
1178                                         mix =(mmx_t*)mix_buffer;
1179
1180                                         for (f_prec* src=(*vtt)->ec_output_buffer; mix < (mmx_t*) mix_buffer_end; src++, mix++)
1181                                         {
1182                                                 /* first sample */
1183                                                 MM_VAR_ACC(mm_src1).s[0]=*src;
1184                                                 MM_VAR_ACC(mm_src1).s[1]=*src;
1185                                 
1186                                                 /* sample * l/r volume */
1187                                                 movq_m2r(MM_VAR_MOVQ(mm_src1), mm3);
1188                                                 pfmul_r2r(mm0, mm3);
1189                                 
1190                                                 /* accumulating complete mix */
1191                                                 movq_m2r(*mix, mm4);
1192                                                 pfadd_r2r(mm4, mm3);
1193                                                 movq_r2m(mm3, *mix);
1194                                         }
1195
1196                                         femms();
1197 #endif                                  
1198                                 }
1199                         }
1200                         
1201                         /* left */
1202                         
1203                         max=mix_max_l;
1204                         min=max;
1205
1206                         for (sample=0; sample<samples_in_mix_buffer; sample+=2)
1207                         {                               
1208                                 temp=mix_buffer[sample];
1209
1210 #ifndef TX_DO_CLIP
1211 #define FL_SHRT_MAX 32767.0
1212 #define FL_SHRT_MIN -32768.0
1213                                 if(temp < FL_SHRT_MIN) temp = FL_SHRT_MIN;
1214                                 else if (temp > FL_SHRT_MAX) temp = FL_SHRT_MAX;
1215 #endif                                  
1216
1217                                 mix_out_buffer[sample]=(int16_t) temp;
1218                         
1219                                 if (temp>max) max=temp;
1220                                 else if (temp<min) min=temp;
1221                         }
1222                         
1223                         min*=-1.0;
1224                         if (min>max) mix_max_l=min; else mix_max_l=max;         
1225                         
1226                         /* right */
1227                         
1228                         max=mix_max_r;
1229                         min=max;
1230
1231                         for (sample=1; sample<samples_in_mix_buffer; sample+=2)
1232                         {                               
1233                                 temp=mix_buffer[sample];
1234
1235 #ifndef TX_DO_CLIP
1236                                 if(temp < FL_SHRT_MIN) temp = FL_SHRT_MIN;
1237                                 else if (temp > FL_SHRT_MAX) temp = FL_SHRT_MAX;
1238 #endif
1239                                 
1240                                 mix_out_buffer[sample]=(int16_t) temp;
1241                         
1242                                 if (temp>max) max=temp;
1243                                 else if (temp<min) min=temp;
1244                         }
1245                         
1246                         min*=-1.0;
1247                         if (min>max) mix_max_r=min; else mix_max_r=max;         
1248                         
1249         }
1250         master_triggered=0;
1251                 
1252         vtt=render_list.begin();
1253         while (vtt!=render_list.end())
1254         {
1255                 next=vtt;
1256                 next++;
1257                 
1258                 if ((*vtt)->want_stop) (*vtt)->stop_nolock();
1259                 vtt=next;
1260         }
1261         pthread_mutex_unlock(&render_lock);
1262         
1263         return(mix_out_buffer);
1264 }
1265
1266 void vtt_class :: forward_all_turntables()
1267 {
1268         list <vtt_class *> :: iterator vtt, next;
1269
1270         if (render_list.size()>0)
1271         {
1272                  vtt=render_list.begin();
1273                  (*vtt)->forward_turntable();                    
1274
1275                  if (master_triggered)
1276                  {
1277                          for (vtt=main_list.begin(); vtt!=main_list.end(); vtt++)
1278                          {
1279                                  if ((*vtt)->is_sync_client)
1280                                  {
1281                                          if ((*vtt)->sync_countdown)
1282                                          {
1283                                                  (*vtt)->sync_countdown--;
1284                                          }
1285                                          else
1286                                          {
1287                                                  (*vtt)->sync_countdown=(*vtt)->sync_cycles;
1288                                                  (*vtt)->trigger();
1289                                          }
1290                                  }
1291                          }
1292                  }
1293
1294                  vtt=render_list.begin();
1295                  for (vtt++; vtt!=render_list.end(); vtt++)
1296                  {
1297                          (*vtt)->forward_turntable();
1298                  }
1299                  
1300         }
1301         master_triggered=0;
1302         vtt=render_list.begin();
1303         while (vtt!=render_list.end())
1304         {
1305                 next=vtt;
1306                 next++;
1307                 
1308                 if ((*vtt)->want_stop) (*vtt)->stop_nolock();
1309                 vtt=next;
1310         }
1311 }
1312
1313
1314 int vtt_class :: trigger()
1315 {
1316         list <vtt_fx *> :: iterator effect;
1317
1318         if (!buffer) return (1);
1319         
1320         if (!is_playing) pthread_mutex_lock(&render_lock);
1321         
1322         if (res_pitch>=0) pos_f=0;
1323         else pos_f=maxpos;
1324         fade=NEED_FADE_OUT;
1325         speed=res_pitch;
1326         speed_real=res_pitch;
1327         speed_target=res_pitch;
1328         want_stop=0;
1329
1330         /* activating plugins */
1331         for (effect=fx_list.begin(); effect != fx_list.end(); effect++)
1332         {
1333                 (*effect)->activate();
1334         }
1335
1336
1337 #ifdef USE_FLASH
1338         max_value=0;
1339 #endif
1340         
1341         if (is_sync_master)
1342         {
1343                 master_triggered=1;
1344                 master_triggered_at=0;
1345         }
1346         
1347         if (!is_playing)
1348         {
1349                 is_playing=1;
1350         
1351                 if (is_sync_master) 
1352                 {
1353                         render_list.push_front(this);           
1354                 }               
1355                 else
1356                 {
1357                         render_list.push_back(this);
1358                 }
1359                 pthread_mutex_unlock(&render_lock);
1360         }
1361         return(0);
1362 }
1363
1364 int vtt_class :: stop_nolock()
1365 {
1366         list <vtt_fx *> :: iterator effect;
1367
1368         if (!is_playing) 
1369         {
1370                 pthread_mutex_unlock(&render_lock);
1371                 return(1);
1372         }
1373         render_list.remove(this);
1374         want_stop=0;
1375
1376         is_playing=0;
1377
1378 #ifdef USE_FLASH
1379         max_value=0;
1380 #endif
1381         cleanup_vtt(this);
1382         sync_countdown=0;
1383         
1384         /* deactivating plugins */
1385         for (effect=fx_list.begin(); effect != fx_list.end(); effect++)
1386         {
1387                 (*effect)->deactivate();
1388         }
1389         
1390         return(0);
1391 }
1392
1393 int vtt_class :: stop()
1394 {
1395         int res;
1396         
1397         pthread_mutex_lock(&render_lock);
1398
1399         res=stop_nolock();
1400
1401         pthread_mutex_unlock(&render_lock);
1402
1403         return(res);
1404 }
1405
1406 void vtt_class :: set_sync_master(int master)
1407 {
1408         if (master)
1409         {
1410                 if (sync_master) sync_master->set_sync_master(0);
1411                 sync_master=this;
1412                 is_sync_master=1;
1413         }
1414         else
1415         {
1416                 if (sync_master==this) sync_master=0;
1417                 is_sync_master=0;
1418                 gui_clear_master_button(this);
1419         }
1420 }
1421
1422 void vtt_class :: set_sync_client(int slave, int cycles)
1423 {
1424         is_sync_client=slave;
1425         sync_cycles=cycles;
1426 //      sync_countdown=cycles; 
1427         sync_countdown=0;
1428 }
1429
1430 void vtt_class :: set_sync_client_ug(int slave, int cycles)
1431 {
1432         set_sync_client(slave, cycles);
1433 }
1434
1435 void vtt_class :: set_master_volume(f_prec new_volume)
1436 {
1437         list <vtt_class *> :: iterator vtt;
1438
1439         master_volume=new_volume;
1440         globals.volume=new_volume;
1441         
1442         if (main_list.size()>0)
1443         {
1444                 vol_channel_adjust=sqrt((f_prec) main_list.size());
1445                 res_master_volume=master_volume/vol_channel_adjust;             
1446         }
1447                 
1448         for (vtt=main_list.begin(); vtt!=main_list.end(); vtt++)
1449         {
1450                 (*vtt)->recalc_volume();
1451         }
1452 }
1453
1454 void vtt_class :: set_master_pitch(f_prec new_pitch)
1455 {
1456         list <vtt_class *> :: iterator vtt;
1457         
1458         globals.pitch=new_pitch;
1459         for (vtt=main_list.begin(); vtt!=main_list.end(); vtt++)
1460         {
1461                 (*vtt)->recalc_pitch();
1462         }
1463 }
1464
1465 void vtt_class :: enable_saturate (int newstate)
1466 {
1467         do_saturate=newstate;
1468 }
1469
1470 void vtt_class :: focus_no(int no)
1471 {
1472         list <vtt_class *> :: iterator vtt;
1473         int i;
1474
1475         for (i=0, vtt=main_list.begin(); vtt!=main_list.end(); vtt++, i++)
1476         {
1477                 if (i==no)
1478                 {
1479                         focused_vtt=(*vtt);
1480                 }
1481         }
1482 }
1483
1484 void vtt_class :: focus_next()
1485 {
1486         list <vtt_class *> :: iterator vtt;
1487         
1488         if (!focused_vtt)
1489         {
1490                 if (main_list.size())
1491                 {
1492                         focused_vtt=(*main_list.begin());
1493                 }
1494                 return;
1495         }
1496         
1497         for (vtt=main_list.begin(); vtt!=main_list.end() ; vtt++) {
1498                 if ((*vtt)==focused_vtt) {
1499                         /* Ok, we found ourselves.. */
1500                         
1501                         vtt++;
1502                         while ((vtt!=main_list.end()) && ((*vtt)->audio_hidden) ) {
1503                                 vtt++;
1504                         }
1505                         
1506                         if (vtt==main_list.end()) {
1507                                 /* No other "focusable" after this vtt so we're looking for the next */
1508                                 
1509                                 for (vtt=main_list.begin(); vtt!=main_list.end() ; vtt++) {
1510                                         if (! (*vtt)->audio_hidden) {
1511                                                 focused_vtt=(*vtt);
1512                                                 return;
1513                                         }
1514                                 }
1515                                 /* When we get here there's no "focusable" vtt at all... damn */
1516                                 focused_vtt=NULL;
1517                                 return;
1518                         } else {
1519                                 focused_vtt=(*vtt);
1520                                 return;
1521                         }
1522                 }
1523         }
1524         
1525         focused_vtt=(*main_list.begin());
1526 }
1527
1528 void vtt_class :: set_scratch(int newstate)
1529 {
1530         if (newstate)
1531         {
1532                 sp_spin.receive_input_value(0);
1533                 do_scratch=1;
1534                 sense_cycles=globals.sense_cycles;
1535         }
1536         else
1537         {
1538                 sp_spin.receive_input_value(1);
1539                 do_scratch=0;
1540         }
1541 }
1542
1543
1544 void vtt_class :: unfocus()
1545 {
1546         focused_vtt=NULL;
1547 }
1548
1549 void vtt_class :: set_x_input_parameter(tX_seqpar *sp)
1550 {
1551         x_par = sp;
1552 }
1553
1554 void vtt_class :: set_y_input_parameter(tX_seqpar *sp)
1555 {
1556         y_par = sp;
1557 }
1558
1559 void vtt_class :: xy_input(f_prec x_value, f_prec y_value)
1560 {
1561         if (x_par) x_par->handle_mouse_input(x_value*globals.mouse_speed);
1562         if (y_par) y_par->handle_mouse_input(y_value*globals.mouse_speed);
1563 }
1564
1565 #define store(data); if (fwrite((void *) &data, sizeof(data), 1, output)!=1) res+=1;
1566
1567 int  vtt_class :: save(FILE *rc, char *indent) {
1568         list <vtt_fx *> :: iterator effect;
1569         char tmp_xml_buffer[4096];
1570         
1571         int res=0;
1572
1573         fprintf(rc, "%s<turntable>\n", indent);
1574         strcat(indent, "\t");
1575         
1576         store_string("name", name);
1577         if (buffer) {
1578                 store_string("audiofile", filename);
1579         } else {
1580                 store_string("audiofile", "");
1581         }
1582         store_bool("sync_master", is_sync_master);
1583         store_bool("autotrigger", autotrigger);
1584         store_bool_sp("loop", loop, sp_loop);
1585
1586         store_bool_sp("sync_client", is_sync_client, sp_sync_client);
1587         store_int_sp("sync_cycles", sync_cycles, sp_sync_cycles);
1588
1589         store_float_sp("volume", rel_volume, sp_volume);
1590         store_float_sp("pitch", rel_pitch, sp_pitch);   
1591         store_bool_sp("mute", mute, sp_mute);
1592         store_float_sp("pan", pan, sp_pan);
1593         
1594         store_bool_sp("lowpass_enable", lp_enable, sp_lp_enable);
1595         store_float_sp("lowpass_gain", lp_gain, sp_lp_gain);
1596         store_float_sp("lowpass_reso", lp_reso, sp_lp_reso);
1597         store_float_sp("lowpass_freq", lp_freq, sp_lp_freq);
1598
1599         store_bool_sp("echo_enable", ec_enable, sp_ec_enable);
1600         store_float_sp("echo_length", ec_length, sp_ec_length);
1601         store_float_sp("echo_feedback", ec_feedback, sp_ec_feedback);
1602         store_float_sp("echo_pan", ec_pan, sp_ec_pan);
1603         store_float_sp("echo_volume", ec_volume, sp_ec_volume);
1604         
1605         store_id("speed", sp_speed.get_persistence_id());
1606         store_id("trigger", sp_trigger.get_persistence_id());
1607         store_id("spin", sp_spin.get_persistence_id());
1608
1609         
1610         if (x_par) {
1611                 store_int("x_axis_mapping", x_par->get_persistence_id());
1612         }
1613         
1614         if (y_par) {
1615                 store_int("y_axis_mapping", y_par->get_persistence_id());
1616         }
1617
1618         store_bool("audio_panel_hidden", audio_hidden);
1619         store_bool("control_panel_hidden", control_hidden);
1620         store_bool("main_panel_hidden", gui.main_panel->is_hidden());
1621         store_bool("trigger_panel_hidden", gui.trigger_panel->is_hidden());
1622         store_bool("lowpass_panel_hidden", gui.lp_panel->is_hidden());
1623         store_bool("echo_panel_hidden", gui.ec_panel->is_hidden());
1624
1625         store_float("audio_x_zoom", gui_get_audio_x_zoom(this));
1626         
1627         fprintf(rc, "%s<fx>\n", indent);
1628         strcat(indent, "\t");
1629         
1630         for (effect=fx_list.begin(); effect!=fx_list.end(); effect++) {
1631                 (*effect)->save(rc, indent);
1632         }
1633         indent[strlen(indent)-1]=0;
1634         fprintf(rc, "%s</fx>\n", indent);
1635         
1636         indent[strlen(indent)-1]=0;
1637         fprintf(rc, "%s</turntable>\n", indent);
1638         
1639         return(res);
1640 }
1641
1642 #define TX_XML_SETFILE_VERSION "1.0"
1643
1644 int  vtt_class :: save_all(FILE* rc) {
1645         int res=0;
1646         list <vtt_class *> :: iterator vtt;
1647         char indent[256];
1648         
1649         tX_seqpar :: create_persistence_ids();
1650
1651         fprintf(rc, "<?xml version=\"1.0\" encoding=\"US-ASCII\"?>\n\n");
1652         fprintf(rc, "<terminatorXset version=\"%s\">\n", TX_XML_SETFILE_VERSION);
1653         
1654         strcpy(indent, "\t");
1655
1656         //store_int(vtt_amount); obsolete
1657
1658         store_float_sp("master_volume", master_volume, sp_master_volume);
1659         store_float_sp("master_pitch", globals.pitch, sp_master_pitch);
1660
1661         for (vtt=main_list.begin(); vtt!=main_list.end(); vtt++) {
1662                 res+=(*vtt)->save(rc, indent);
1663         }
1664         
1665         sequencer.save(rc, indent);
1666         
1667         fprintf(rc, "</terminatorXset>\n");
1668         
1669         return(res);
1670 }
1671
1672 int vtt_class :: load(xmlDocPtr doc, xmlNodePtr node) {
1673         char buffer[1024];
1674         bool hidden;
1675         int xpar_id=-1;
1676         int ypar_id=-1;
1677         int elementFound;
1678         char *pid_attr;
1679         int pid;
1680         double dvalue;
1681         double tmp;
1682         
1683         for (xmlNodePtr cur=node->xmlChildrenNode; cur != NULL; cur = cur->next) {
1684                 if (cur->type == XML_ELEMENT_NODE) {
1685                         elementFound=0;
1686                         
1687                         restore_string_ac("name", buffer, set_name(buffer));
1688                         restore_string("audiofile", filename);
1689                         restore_bool("sync_master", is_sync_master);
1690                         restore_bool("autotrigger", autotrigger);
1691                         restore_bool_id("loop", loop, sp_loop, nop);
1692                         restore_bool_id("sync_client", is_sync_client, sp_sync_client, set_sync_client(is_sync_client, sync_cycles));
1693                         restore_int_id("sync_cycles", sync_cycles, sp_sync_cycles, set_sync_client(is_sync_client, sync_cycles));
1694                         restore_float_id("volume", rel_volume, sp_volume, recalc_volume());
1695                         restore_float_id("pitch", rel_pitch, sp_pitch, recalc_pitch());
1696                         restore_bool_id("mute", mute, sp_mute, set_mute(mute));
1697                         restore_float_id("pan", pan, sp_pan, set_pan(pan));
1698         
1699                         restore_bool_id("lowpass_enable", lp_enable, sp_lp_enable, lp_set_enable(lp_enable));
1700                         restore_float_id("lowpass_gain", lp_gain, sp_lp_gain, lp_set_gain(lp_gain)); 
1701                         restore_float_id("lowpass_reso", lp_reso, sp_lp_reso, lp_set_reso(lp_reso));
1702                         restore_float_id("lowpass_freq", lp_freq, sp_lp_freq, lp_set_freq(lp_freq));
1703         
1704                         restore_bool_id("echo_enable", ec_enable, sp_ec_enable, ec_set_enable(ec_enable));      
1705                         restore_float_id("echo_length", ec_length, sp_ec_length, ec_set_length(ec_length));
1706                         restore_float_id("echo_feedback", ec_feedback, sp_ec_feedback, ec_set_feedback(ec_feedback));
1707                         restore_float_id("echo_pan", ec_pan, sp_ec_pan, ec_set_pan(ec_pan));
1708                         restore_float_id("echo_volume", ec_volume, sp_ec_volume, ec_set_volume(ec_volume));             
1709                 
1710                         restore_id("speed", sp_speed);  
1711                         restore_id("trigger", sp_trigger);
1712                         restore_id("spin", sp_spin);
1713         
1714                         restore_int("x_axis_mapping", xpar_id);
1715                         restore_int("y_axis_mapping", ypar_id);
1716         
1717                         restore_bool("audio_panel_hidden", audio_hidden);
1718                         restore_bool("control_panel_hidden", control_hidden);
1719                         restore_bool_ac("main_panel_hidden", hidden, gui.main_panel->hide(hidden));
1720                         restore_bool_ac("trigger_panel_hidden", hidden, gui.trigger_panel->hide(hidden));
1721                         restore_bool_ac("lowpass_panel_hidden", hidden, gui.lp_panel->hide(hidden));                    
1722                         restore_bool_ac("echo_panel_hidden", hidden, gui.ec_panel->hide(hidden));
1723                         restore_float_ac("audio_x_zoom", tmp, gui_set_audio_x_zoom(this,tmp));
1724                         vg_adjust_zoom(gui.zoom, this);
1725                         
1726                         if (xmlStrcmp(cur->name, (xmlChar *) "fx")==0) {
1727                                 xmlNodePtr fx=cur;
1728                                 elementFound=1;
1729                                 
1730                                 for (xmlNodePtr cur=fx->xmlChildrenNode; cur != NULL; cur = cur->next) {
1731                                         if (cur->type == XML_ELEMENT_NODE) {
1732                                                 int elementFound=0;
1733                                                 
1734                                                 if (xmlStrcmp(cur->name, (xmlChar *) "cutoff")==0) {
1735                                                         for (unsigned int t=0; t<fx_list.size(); t++) effect_down(lp_fx);
1736                                                         elementFound=1;
1737                                                 } else if (xmlStrcmp(cur->name, (xmlChar *) "lowpass")==0) {
1738                                                         for (unsigned int t=0; t<fx_list.size(); t++) effect_down(ec_fx);
1739                                                         elementFound=1;                                                         
1740                                                 } else if (xmlStrcmp(cur->name, (xmlChar *) "ladspa_plugin")==0) {
1741                                                         xmlNodePtr pluginNode=cur;
1742                                                         int ladspa_id=-1;
1743                                                         elementFound=1;
1744                                                         
1745                                                         for (xmlNodePtr cur=pluginNode->xmlChildrenNode; cur!=NULL; cur = cur->next) {
1746                                                                 int elementFound;
1747                                                                 if (cur->type == XML_ELEMENT_NODE) {
1748                                                                         elementFound=0;
1749
1750                                                                         restore_int("ladspa_id", ladspa_id);
1751                                                                         if (elementFound) break;
1752                                                                 }
1753                                                         }
1754                                                         
1755                                                         if (ladspa_id!=-1) {
1756                                                                 LADSPA_Plugin *plugin=LADSPA_Plugin::getPluginByUniqueID(ladspa_id);
1757                                                                 if (plugin) {
1758                                                                         vtt_fx_ladspa *ladspa_effect=add_effect(plugin);
1759                                                                         ladspa_effect->load(doc, pluginNode);
1760                                                                 } else {
1761                                                                         sprintf(buffer,"The terminatorX set file you are loading makes use of a LADSPA plugin that is not installed on this machine. The plugin's ID is [%i].", ladspa_id);
1762                                                                         tx_note(buffer, true);                                                  
1763                                                                 }
1764                                                         } else {
1765                                                                 tX_warning("ladspa_plugin section without a ladspa_id element.");
1766                                                         }
1767                                                         
1768                                                 } else {
1769                                                         tX_warning("unhandled element %s in fx section.", cur->name);
1770                                                 }
1771                                         }
1772                                 }
1773                         }
1774                         
1775                         if(!elementFound) {
1776                                 tX_warning("unhandled element %s in turntable secion.", cur->name);
1777                         }
1778                 }
1779         }
1780
1781         recalc_volume();
1782
1783         if (xpar_id>=0) {
1784                 set_x_input_parameter(tX_seqpar :: get_sp_by_persistence_id(xpar_id));
1785         }
1786         else set_x_input_parameter(NULL);
1787         
1788         if (ypar_id) {
1789                 set_y_input_parameter(tX_seqpar :: get_sp_by_persistence_id(ypar_id));
1790         }
1791         else set_y_input_parameter(NULL);
1792                 
1793         return 0;
1794 }
1795
1796
1797 int vtt_class :: load_all(xmlDocPtr doc, char *fname) {
1798         xmlNodePtr root=xmlDocGetRootElement(doc);
1799         int elementFound=0;
1800         char fn_buff[4096];
1801         double dvalue;
1802         int res=0;
1803         int restmp=0;
1804         char *pid_attr;
1805         int pid;
1806
1807         
1808         if (!root) {
1809                 tX_error("no root element? What kind of XML document is this?");
1810                 return 1;
1811         }
1812         
1813         if (xmlStrcmp(root->name, (const xmlChar *) "terminatorXset")) {
1814                 tX_error("this is not a terminatorXset file.")
1815                 return 2;
1816         }
1817         
1818         if (xmlGetProp(root,(xmlChar *) "version")==NULL) {
1819                 tX_error("the set file lacks a version attribute.");
1820                 return 3;
1821         }
1822         
1823         if (xmlStrcmp(xmlGetProp(root, (xmlChar *) "version"), (xmlChar *) TX_XML_SETFILE_VERSION)) {
1824                 tX_warning("this set file is version %s - while this releases uses version %s - trying to load anyway.", xmlGetProp(root, (xmlChar *) "version"), TX_XML_SETFILE_VERSION);
1825         }
1826         
1827         /* delete current tables... */
1828         while (main_list.size()) {
1829                 delete((*main_list.begin()));
1830         }
1831
1832         int table_ctr=0;
1833         
1834         /* counting turntables.. */
1835         for (xmlNodePtr cur=root->xmlChildrenNode; cur != NULL; cur = cur->next) {
1836                 if (cur->type == XML_ELEMENT_NODE) {    
1837                         if (xmlStrcmp(cur->name, (xmlChar *) "turntable")==0) {
1838                                 table_ctr++;
1839                         }
1840                 }
1841         }
1842
1843         tX_debug("Found %i turntables in set.",  table_ctr);
1844
1845         ld_create_loaddlg(TX_LOADDLG_MODE_MULTI, table_ctr);
1846         ld_set_setname(fname);
1847
1848         /* parsing all */
1849         for (xmlNodePtr cur=root->xmlChildrenNode; cur != NULL; cur = cur->next) {
1850                 if (cur->type == XML_ELEMENT_NODE) {                    
1851                         elementFound=0;
1852                 
1853                         restore_float_id("master_volume", master_volume, sp_master_volume, set_master_volume(master_volume));
1854                         restore_float_id("master_pitch", globals.pitch, sp_master_pitch, set_master_pitch(globals.pitch));
1855                         
1856                         if ((!elementFound) && (xmlStrcmp(cur->name, (xmlChar *) "turntable")==0)) {
1857                                 elementFound=1;
1858                                 vtt_class *vtt=new vtt_class(1);
1859                                 vtt->load(doc, cur);
1860                                 
1861                                 tX_debug("loading a turntable..");
1862
1863                                 if (strlen(vtt->filename)) {
1864                                         strcpy(fn_buff, vtt->filename);
1865                                         ld_set_filename(fn_buff);
1866                                 
1867                                         restmp=(int) vtt->load_file(fn_buff);
1868                                         res+=restmp;
1869                                 }
1870         
1871                                 gtk_box_pack_start(GTK_BOX(control_parent), vtt->gui.control_box, TRUE, TRUE, 0);
1872                                 gtk_box_pack_start(GTK_BOX(audio_parent), vtt->gui.audio_box, TRUE, TRUE, 0);
1873                                 if (vtt->audio_hidden) vtt->hide_audio(vtt->audio_hidden);
1874                                 if (vtt->control_hidden) vtt->hide_control(vtt->control_hidden);\r
1875                         }
1876                         if ((!elementFound) && (xmlStrcmp(cur->name, (xmlChar *) "sequencer")==0)) {
1877                                 elementFound=1;
1878                                 sequencer.load(doc, cur);
1879                         }
1880                         if (!elementFound) {
1881                                 tX_warning("unhandled element %s in setfile %s", cur->name, fname);
1882                         }
1883                 }
1884         }
1885         
1886         ld_destroy();
1887         
1888         return(res);
1889 }
1890
1891 void add_vtt(GtkWidget *ctrl, GtkWidget *audio, char *fn)
1892 {
1893         vtt_class *hmmpg;
1894         hmmpg = new vtt_class(1);
1895         gtk_box_pack_start(GTK_BOX(ctrl), hmmpg->gui.control_box, TRUE, TRUE, 0);
1896         gtk_box_pack_start(GTK_BOX(audio), hmmpg->gui.audio_box, TRUE, TRUE, 0);
1897         if (fn) hmmpg->load_file(fn);
1898 }
1899
1900 extern void vg_move_fx_panel_up(GtkWidget *wid, vtt_class *vtt);
1901 extern void vg_move_fx_panel_down(GtkWidget *wid, vtt_class *vtt);
1902
1903 //#define debug_fx_stack(); for (i=fx_list.begin(); i != fx_list.end(); i++) puts((*i)->get_info_string());
1904 #define debug_fx_stack();
1905
1906 void vtt_class :: effect_up(vtt_fx *effect)
1907 {
1908         list <vtt_fx *> :: iterator i;
1909         list <vtt_fx *> :: iterator previous;
1910         int ok=0;
1911         
1912         debug_fx_stack();
1913         
1914         if ((*fx_list.begin())==effect) return;
1915         
1916         for (previous=i=fx_list.begin(); i != fx_list.end(); i++)
1917         {
1918                 if ((*i) == effect)
1919                 {
1920                         ok=1;
1921                         break;
1922                 }
1923                 previous=i;
1924         }
1925         
1926         if (ok)
1927         {       
1928                 pthread_mutex_lock(&render_lock);
1929                 fx_list.remove(effect);
1930                 fx_list.insert(previous, effect);
1931                 pthread_mutex_unlock(&render_lock);
1932
1933                 vg_move_fx_panel_up(effect->get_panel_widget(), this);
1934         }
1935         
1936         debug_fx_stack();
1937 }
1938
1939 void vtt_class :: effect_down(vtt_fx *effect)
1940 {
1941         list <vtt_fx *> :: iterator i;
1942         int ok=0;
1943
1944         debug_fx_stack();
1945                 
1946         for (i=fx_list.begin(); i != fx_list.end(); i++)
1947         {
1948                 if ((*i) == effect)
1949                 {
1950                         ok=1;
1951                         break;
1952                 }
1953         }
1954         
1955         if ((ok) && (i!=fx_list.end()))
1956         {
1957                 i++;
1958                 if (i==fx_list.end()) return;
1959                 i++;
1960
1961                 pthread_mutex_lock(&render_lock);
1962                 fx_list.remove(effect);
1963                 
1964                 fx_list.insert(i, effect);
1965                 vg_move_fx_panel_down(effect->get_panel_widget(), this);
1966                 pthread_mutex_unlock(&render_lock);
1967         }
1968         
1969 debug_fx_stack();       
1970 }
1971
1972 void vtt_class ::  effect_remove(vtt_fx_ladspa *effect)
1973 {
1974         pthread_mutex_lock(&render_lock);
1975         fx_list.remove(effect);
1976         pthread_mutex_unlock(&render_lock);
1977         
1978         delete effect;
1979 }
1980
1981 extern void gui_hide_control_panel(vtt_class *vtt, bool hide);
1982 extern void gui_hide_audio_panel(vtt_class *vtt, bool hide);
1983
1984 void vtt_class :: hide_audio(bool hide) {
1985         audio_hidden=hide;
1986         gui_hide_audio_panel(this, hide);
1987 }
1988
1989 void vtt_class :: hide_control(bool hide) {
1990         control_hidden=hide;
1991         gui_hide_control_panel(this, hide);     
1992 }