Merged Arthur's MIDI patch, starting on the menubar, gui fixes and
[terminatorX.git] / src / tX_vtt.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_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                                 mix_out_buffer[sample]=(int16_t) temp;
1210                         
1211                                 if (temp>max) max=temp;
1212                                 else if (temp<min) min=temp;
1213                         }
1214                         
1215                         min*=-1.0;
1216                         if (min>max) mix_max_l=min; else mix_max_l=max;         
1217                         
1218                         /* right */
1219                         
1220                         max=mix_max_r;
1221                         min=max;
1222
1223                         for (sample=1; sample<samples_in_mix_buffer; sample+=2)
1224                         {                               
1225                                 temp=mix_buffer[sample];
1226                                 mix_out_buffer[sample]=(int16_t) temp;
1227                         
1228                                 if (temp>max) max=temp;
1229                                 else if (temp<min) min=temp;
1230                         }
1231                         
1232                         min*=-1.0;
1233                         if (min>max) mix_max_r=min; else mix_max_r=max;         
1234                         
1235         }
1236         master_triggered=0;
1237                 
1238         vtt=render_list.begin();
1239         while (vtt!=render_list.end())
1240         {
1241                 next=vtt;
1242                 next++;
1243                 
1244                 if ((*vtt)->want_stop) (*vtt)->stop_nolock();
1245                 vtt=next;
1246         }
1247         pthread_mutex_unlock(&render_lock);
1248         
1249         return(mix_out_buffer);
1250 }
1251
1252 void vtt_class :: forward_all_turntables()
1253 {
1254         list <vtt_class *> :: iterator vtt, next;
1255
1256         if (render_list.size()>0)
1257         {
1258                  vtt=render_list.begin();
1259                  (*vtt)->forward_turntable();                    
1260
1261                  if (master_triggered)
1262                  {
1263                          for (vtt=main_list.begin(); vtt!=main_list.end(); vtt++)
1264                          {
1265                                  if ((*vtt)->is_sync_client)
1266                                  {
1267                                          if ((*vtt)->sync_countdown)
1268                                          {
1269                                                  (*vtt)->sync_countdown--;
1270                                          }
1271                                          else
1272                                          {
1273                                                  (*vtt)->sync_countdown=(*vtt)->sync_cycles;
1274                                                  (*vtt)->trigger();
1275                                          }
1276                                  }
1277                          }
1278                  }
1279
1280                  vtt=render_list.begin();
1281                  for (vtt++; vtt!=render_list.end(); vtt++)
1282                  {
1283                          (*vtt)->forward_turntable();
1284                  }
1285                  
1286         }
1287         master_triggered=0;
1288         vtt=render_list.begin();
1289         while (vtt!=render_list.end())
1290         {
1291                 next=vtt;
1292                 next++;
1293                 
1294                 if ((*vtt)->want_stop) (*vtt)->stop_nolock();
1295                 vtt=next;
1296         }
1297 }
1298
1299
1300 int vtt_class :: trigger()
1301 {
1302         list <vtt_fx *> :: iterator effect;
1303
1304         if (!buffer) return (1);
1305         
1306         if (!is_playing) pthread_mutex_lock(&render_lock);
1307         
1308         if (res_pitch>=0) pos_f=0;
1309         else pos_f=maxpos;
1310         fade=NEED_FADE_OUT;
1311         speed=res_pitch;
1312         speed_real=res_pitch;
1313         speed_target=res_pitch;
1314         want_stop=0;
1315
1316         /* activating plugins */
1317         for (effect=fx_list.begin(); effect != fx_list.end(); effect++)
1318         {
1319                 (*effect)->activate();
1320         }
1321
1322
1323 #ifdef USE_FLASH
1324         max_value=0;
1325 #endif
1326         
1327         if (is_sync_master)
1328         {
1329                 master_triggered=1;
1330                 master_triggered_at=0;
1331         }
1332         
1333         if (!is_playing)
1334         {
1335                 is_playing=1;
1336         
1337                 if (is_sync_master) 
1338                 {
1339                         render_list.push_front(this);           
1340                 }               
1341                 else
1342                 {
1343                         render_list.push_back(this);
1344                 }
1345                 pthread_mutex_unlock(&render_lock);
1346         }
1347         return(0);
1348 }
1349
1350 int vtt_class :: stop_nolock()
1351 {
1352         list <vtt_fx *> :: iterator effect;
1353
1354         if (!is_playing) 
1355         {
1356                 pthread_mutex_unlock(&render_lock);
1357                 return(1);
1358         }
1359         render_list.remove(this);
1360         want_stop=0;
1361
1362         is_playing=0;
1363
1364 #ifdef USE_FLASH
1365         max_value=0;
1366 #endif
1367         cleanup_vtt(this);
1368         sync_countdown=0;
1369         
1370         /* deactivating plugins */
1371         for (effect=fx_list.begin(); effect != fx_list.end(); effect++)
1372         {
1373                 (*effect)->deactivate();
1374         }
1375         
1376         return(0);
1377 }
1378
1379 int vtt_class :: stop()
1380 {
1381         int res;
1382         
1383         pthread_mutex_lock(&render_lock);
1384
1385         res=stop_nolock();
1386
1387         pthread_mutex_unlock(&render_lock);
1388
1389         return(res);
1390 }
1391
1392 void vtt_class :: set_sync_master(int master)
1393 {
1394         if (master)
1395         {
1396                 if (sync_master) sync_master->set_sync_master(0);
1397                 sync_master=this;
1398                 is_sync_master=1;
1399         }
1400         else
1401         {
1402                 if (sync_master==this) sync_master=0;
1403                 is_sync_master=0;
1404                 gui_clear_master_button(this);
1405         }
1406 }
1407
1408 void vtt_class :: set_sync_client(int slave, int cycles)
1409 {
1410         is_sync_client=slave;
1411         sync_cycles=cycles;
1412 //      sync_countdown=cycles; 
1413         sync_countdown=0;
1414 }
1415
1416 void vtt_class :: set_sync_client_ug(int slave, int cycles)
1417 {
1418         set_sync_client(slave, cycles);
1419 }
1420
1421 void vtt_class :: set_master_volume(f_prec new_volume)
1422 {
1423         list <vtt_class *> :: iterator vtt;
1424
1425         master_volume=new_volume;
1426         globals.volume=new_volume;
1427         
1428         if (main_list.size()>0)
1429         {
1430                 vol_channel_adjust=sqrt((f_prec) main_list.size());
1431                 res_master_volume=master_volume/vol_channel_adjust;             
1432         }
1433                 
1434         for (vtt=main_list.begin(); vtt!=main_list.end(); vtt++)
1435         {
1436                 (*vtt)->recalc_volume();
1437         }
1438 }
1439
1440 void vtt_class :: set_master_pitch(f_prec new_pitch)
1441 {
1442         list <vtt_class *> :: iterator vtt;
1443         
1444         globals.pitch=new_pitch;
1445         for (vtt=main_list.begin(); vtt!=main_list.end(); vtt++)
1446         {
1447                 (*vtt)->recalc_pitch();
1448         }
1449 }
1450
1451 void vtt_class :: enable_saturate (int newstate)
1452 {
1453         do_saturate=newstate;
1454 }
1455
1456 void vtt_class :: focus_no(int no)
1457 {
1458         list <vtt_class *> :: iterator vtt;
1459         int i;
1460
1461         for (i=0, vtt=main_list.begin(); vtt!=main_list.end(); vtt++, i++)
1462         {
1463                 if (i==no)
1464                 {
1465                         focused_vtt=(*vtt);
1466                 }
1467         }
1468 }
1469
1470 void vtt_class :: focus_next()
1471 {
1472         list <vtt_class *> :: iterator vtt;
1473         
1474         if (!focused_vtt)
1475         {
1476                 if (main_list.size())
1477                 {
1478                         focused_vtt=(*main_list.begin());
1479                 }
1480                 return;
1481         }
1482         
1483         for (vtt=main_list.begin(); vtt!=main_list.end() ; vtt++) {
1484                 if ((*vtt)==focused_vtt) {
1485                         /* Ok, we found ourselves.. */
1486                         
1487                         vtt++;
1488                         while ((vtt!=main_list.end()) && ((*vtt)->audio_hidden) ) {
1489                                 vtt++;
1490                         }
1491                         
1492                         if (vtt==main_list.end()) {
1493                                 /* No other "focusable" after this vtt so we're looking for the next */
1494                                 
1495                                 for (vtt=main_list.begin(); vtt!=main_list.end() ; vtt++) {
1496                                         if (! (*vtt)->audio_hidden) {
1497                                                 focused_vtt=(*vtt);
1498                                                 return;
1499                                         }
1500                                 }
1501                                 /* When we get here there's no "focusable" vtt at all... damn */
1502                                 focused_vtt=NULL;
1503                                 return;
1504                         } else {
1505                                 focused_vtt=(*vtt);
1506                                 return;
1507                         }
1508                 }
1509         }
1510         
1511         focused_vtt=(*main_list.begin());
1512 }
1513
1514 void vtt_class :: set_scratch(int newstate)
1515 {
1516         if (newstate)
1517         {
1518                 sp_spin.receive_input_value(0);
1519                 do_scratch=1;
1520                 sense_cycles=globals.sense_cycles;
1521         }
1522         else
1523         {
1524                 sp_spin.receive_input_value(1);
1525                 do_scratch=0;
1526         }
1527 }
1528
1529
1530 void vtt_class :: unfocus()
1531 {
1532         focused_vtt=NULL;
1533 }
1534
1535 void vtt_class :: set_x_input_parameter(tX_seqpar *sp)
1536 {
1537         x_par = sp;
1538 }
1539
1540 void vtt_class :: set_y_input_parameter(tX_seqpar *sp)
1541 {
1542         y_par = sp;
1543 }
1544
1545 void vtt_class :: xy_input(f_prec x_value, f_prec y_value)
1546 {
1547         if (x_par) x_par->handle_mouse_input(x_value*globals.mouse_speed);
1548         if (y_par) y_par->handle_mouse_input(y_value*globals.mouse_speed);
1549 }
1550
1551 #define store(data); if (fwrite((void *) &data, sizeof(data), 1, output)!=1) res+=1;
1552
1553 int  vtt_class :: save(FILE *rc, char *indent) {
1554         list <vtt_fx *> :: iterator effect;
1555         char tmp_xml_buffer[4096];
1556         
1557         int res=0;
1558
1559         fprintf(rc, "%s<turntable>\n", indent);
1560         strcat(indent, "\t");
1561         
1562         store_string("name", name);
1563         if (buffer) {
1564                 store_string("audiofile", filename);
1565         } else {
1566                 store_string("audiofile", "");
1567         }
1568         store_bool("sync_master", is_sync_master);
1569         store_bool("autotrigger", autotrigger);
1570         store_bool_id("loop", loop, sp_loop.get_persistence_id());
1571
1572         store_bool_id("sync_client", is_sync_client, sp_sync_client.get_persistence_id());
1573         store_int_id("sync_cycles", sync_cycles, sp_sync_cycles.get_persistence_id());
1574
1575         store_float_id("volume", rel_volume, sp_volume.get_persistence_id());
1576         store_float_id("pitch", rel_pitch, sp_pitch.get_persistence_id());      
1577         store_bool_id("mute", mute, sp_mute.get_persistence_id());
1578         store_float_id("pan", pan, sp_pan.get_persistence_id());
1579         
1580         store_bool_id("lowpass_enable", lp_enable, sp_lp_enable.get_persistence_id());
1581         store_float_id("lowpass_gain", lp_gain, sp_lp_gain.get_persistence_id());
1582         store_float_id("lowpass_reso", lp_reso, sp_lp_reso.get_persistence_id());
1583         store_float_id("lowpass_freq", lp_freq, sp_lp_freq.get_persistence_id());
1584
1585         store_bool_id("echo_enable", ec_enable, sp_ec_enable.get_persistence_id());
1586         store_float_id("echo_length", ec_length, sp_ec_length.get_persistence_id());
1587         store_float_id("echo_feedback", ec_feedback, sp_ec_feedback.get_persistence_id());
1588         store_float_id("echo_pan", ec_pan, sp_ec_pan.get_persistence_id());
1589         store_float_id("echo_volume", ec_volume, sp_ec_volume.get_persistence_id());
1590         
1591         store_id("speed", sp_speed.get_persistence_id());
1592         store_id("trigger", sp_trigger.get_persistence_id());
1593         store_id("spin", sp_spin.get_persistence_id());
1594
1595         
1596         if (x_par) {
1597                 store_int("x_axis_mapping", x_par->get_persistence_id());
1598         }
1599         
1600         if (y_par) {
1601                 store_int("y_axis_mapping", y_par->get_persistence_id());
1602         }
1603
1604         store_bool("audio_panel_hidden", audio_hidden);
1605         store_bool("control_panel_hidden", control_hidden);
1606         store_bool("main_panel_hidden", gui.main_panel->is_hidden());
1607         store_bool("trigger_panel_hidden", gui.trigger_panel->is_hidden());
1608         store_bool("lowpass_panel_hidden", gui.lp_panel->is_hidden());
1609         store_bool("echo_panel_hidden", gui.ec_panel->is_hidden());
1610
1611         store_float("audio_x_zoom", gui_get_audio_x_zoom(this));
1612         
1613         fprintf(rc, "%s<fx>\n", indent);
1614         strcat(indent, "\t");
1615         
1616         for (effect=fx_list.begin(); effect!=fx_list.end(); effect++) {
1617                 (*effect)->save(rc, indent);
1618         }
1619         indent[strlen(indent)-1]=0;
1620         fprintf(rc, "%s</fx>\n", indent);
1621         
1622         indent[strlen(indent)-1]=0;
1623         fprintf(rc, "%s</turntable>\n", indent);
1624         
1625         return(res);
1626 }
1627
1628 #define TX_XML_SETFILE_VERSION "1.0"
1629
1630 int  vtt_class :: save_all(FILE* rc) {
1631         int res=0;
1632         list <vtt_class *> :: iterator vtt;
1633         char indent[256];
1634         
1635         tX_seqpar :: create_persistence_ids();
1636
1637         fprintf(rc, "<?xml version=\"1.0\" encoding=\"US-ASCII\"?>\n\n");
1638         fprintf(rc, "<terminatorXset version=\"%s\">\n", TX_XML_SETFILE_VERSION);
1639         
1640         strcpy(indent, "\t");
1641
1642         //store_int(vtt_amount); obsolete
1643
1644         store_float_id("master_volume", master_volume, sp_master_volume.get_persistence_id());
1645         store_float_id("master_pitch", globals.pitch, sp_master_pitch.get_persistence_id());
1646
1647         for (vtt=main_list.begin(); vtt!=main_list.end(); vtt++) {
1648                 res+=(*vtt)->save(rc, indent);
1649         }
1650         
1651         sequencer.save(rc, indent);
1652         
1653         fprintf(rc, "</terminatorXset>\n");
1654         
1655         return(res);
1656 }
1657
1658 int vtt_class :: load(xmlDocPtr doc, xmlNodePtr node) {
1659         char buffer[1024];
1660         bool hidden;
1661         int xpar_id=-1;
1662         int ypar_id=-1;
1663         int elementFound;
1664         char *pid_attr;
1665         int pid;
1666         double dvalue;
1667         double tmp;
1668         
1669         for (xmlNodePtr cur=node->xmlChildrenNode; cur != NULL; cur = cur->next) {
1670                 if (cur->type == XML_ELEMENT_NODE) {
1671                         elementFound=0;
1672                         
1673                         restore_string_ac("name", buffer, set_name(buffer));
1674                         restore_string("audiofile", filename);
1675                         restore_bool("sync_master", is_sync_master);
1676                         restore_bool("autotrigger", autotrigger);
1677                         restore_bool_id("loop", loop, sp_loop, nop);
1678                         restore_bool_id("sync_client", is_sync_client, sp_sync_client, set_sync_client(is_sync_client, sync_cycles));
1679                         restore_int_id("sync_cycles", sync_cycles, sp_sync_cycles, set_sync_client(is_sync_client, sync_cycles));
1680                         restore_float_id("volume", rel_volume, sp_volume, recalc_volume());
1681                         restore_float_id("pitch", rel_pitch, sp_pitch, recalc_pitch());
1682                         restore_bool_id("mute", mute, sp_mute, set_mute(mute));
1683                         restore_float_id("pan", pan, sp_pan, set_pan(pan));
1684         
1685                         restore_bool_id("lowpass_enable", lp_enable, sp_lp_enable, lp_set_enable(lp_enable));
1686                         restore_float_id("lowpass_gain", lp_gain, sp_lp_gain, lp_set_gain(lp_gain)); 
1687                         restore_float_id("lowpass_reso", lp_reso, sp_lp_reso, lp_set_reso(lp_reso));
1688                         restore_float_id("lowpass_freq", lp_freq, sp_lp_freq, lp_set_freq(lp_freq));
1689         
1690                         restore_bool_id("echo_enable", ec_enable, sp_ec_enable, ec_set_enable(ec_enable));      
1691                         restore_float_id("echo_length", ec_length, sp_ec_length, ec_set_length(ec_length));
1692                         restore_float_id("echo_feedback", ec_feedback, sp_ec_feedback, ec_set_feedback(ec_feedback));
1693                         restore_float_id("echo_pan", ec_pan, sp_ec_pan, ec_set_pan(ec_pan));
1694                         restore_float_id("echo_volume", ec_volume, sp_ec_volume, ec_set_volume(ec_volume));             
1695                 
1696                         restore_id("speed", sp_speed);  
1697                         restore_id("trigger", sp_trigger);
1698                         restore_id("spin", sp_spin);
1699         
1700                         restore_int("x_axis_mapping", xpar_id);
1701                         restore_int("y_axis_mapping", ypar_id);
1702         
1703                         restore_bool("audio_panel_hidden", audio_hidden);
1704                         restore_bool("control_panel_hidden", control_hidden);
1705                         restore_bool_ac("main_panel_hidden", hidden, gui.main_panel->hide(hidden));
1706                         restore_bool_ac("trigger_panel_hidden", hidden, gui.trigger_panel->hide(hidden));
1707                         restore_bool_ac("lowpass_panel_hidden", hidden, gui.lp_panel->hide(hidden));                    
1708                         restore_bool_ac("echo_panel_hidden", hidden, gui.ec_panel->hide(hidden));
1709                         restore_float_ac("audio_x_zoom", tmp, gui_set_audio_x_zoom(this,tmp));
1710                         
1711                         if (xmlStrcmp(cur->name, (xmlChar *) "fx")==0) {
1712                                 xmlNodePtr fx=cur;
1713                                 elementFound=1;
1714                                 
1715                                 for (xmlNodePtr cur=fx->xmlChildrenNode; cur != NULL; cur = cur->next) {
1716                                         if (cur->type == XML_ELEMENT_NODE) {
1717                                                 int elementFound=0;
1718                                                 
1719                                                 if (xmlStrcmp(cur->name, (xmlChar *) "cutoff")==0) {
1720                                                         for (unsigned int t=0; t<fx_list.size(); t++) effect_down(lp_fx);
1721                                                         elementFound=1;
1722                                                 } else if (xmlStrcmp(cur->name, (xmlChar *) "lowpass")==0) {
1723                                                         for (unsigned int t=0; t<fx_list.size(); t++) effect_down(ec_fx);
1724                                                         elementFound=1;                                                         
1725                                                 } else if (xmlStrcmp(cur->name, (xmlChar *) "ladspa_plugin")==0) {
1726                                                         xmlNodePtr pluginNode=cur;
1727                                                         int ladspa_id=-1;
1728                                                         elementFound=1;
1729                                                         
1730                                                         for (xmlNodePtr cur=pluginNode->xmlChildrenNode; cur!=NULL; cur = cur->next) {
1731                                                                 int elementFound;
1732                                                                 if (cur->type == XML_ELEMENT_NODE) {
1733                                                                         elementFound=0;
1734
1735                                                                         restore_int("ladspa_id", ladspa_id);
1736                                                                         if (elementFound) break;
1737                                                                 }
1738                                                         }
1739                                                         
1740                                                         if (ladspa_id!=-1) {
1741                                                                 LADSPA_Plugin *plugin=LADSPA_Plugin::getPluginByUniqueID(ladspa_id);
1742                                                                 if (plugin) {
1743                                                                         vtt_fx_ladspa *ladspa_effect=add_effect(plugin);
1744                                                                         ladspa_effect->load(doc, pluginNode);
1745                                                                 } else {
1746                                                                         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);
1747                                                                         tx_note(buffer, true);                                                  
1748                                                                 }
1749                                                         } else {
1750                                                                 tX_warning("ladspa_plugin section without a ladspa_id element.");
1751                                                         }
1752                                                         
1753                                                 } else {
1754                                                         tX_warning("unhandled element %s in fx section.", cur->name);
1755                                                 }
1756                                         }
1757                                 }
1758                         }
1759                         
1760                         if(!elementFound) {
1761                                 tX_warning("unhandled element %s in turntable secion.", cur->name);
1762                         }
1763                 }
1764         }
1765
1766         recalc_volume();
1767
1768         if (xpar_id>=0) {
1769                 set_x_input_parameter(tX_seqpar :: get_sp_by_persistence_id(xpar_id));
1770         }
1771         else set_x_input_parameter(NULL);
1772         
1773         if (ypar_id) {
1774                 set_y_input_parameter(tX_seqpar :: get_sp_by_persistence_id(ypar_id));
1775         }
1776         else set_y_input_parameter(NULL);
1777                 
1778         return 0;
1779 }
1780
1781
1782 int vtt_class :: load_all(xmlDocPtr doc, char *fname) {
1783         xmlNodePtr root=xmlDocGetRootElement(doc);
1784         int elementFound=0;
1785         char fn_buff[4096];
1786         double dvalue;
1787         int res=0;
1788         int restmp=0;
1789         char *pid_attr;
1790         int pid;
1791
1792         
1793         if (!root) {
1794                 tX_error("no root element? What kind of XML document is this?");
1795                 return 1;
1796         }
1797         
1798         if (xmlStrcmp(root->name, (const xmlChar *) "terminatorXset")) {
1799                 tX_error("this is not a terminatorXset file.")
1800                 return 2;
1801         }
1802         
1803         if (xmlGetProp(root,(xmlChar *) "version")==NULL) {
1804                 tX_error("the set file lacks a version attribute.");
1805                 return 3;
1806         }
1807         
1808         if (xmlStrcmp(xmlGetProp(root, (xmlChar *) "version"), (xmlChar *) TX_XML_SETFILE_VERSION)) {
1809                 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);
1810         }
1811         
1812         /* delete current tables... */
1813         while (main_list.size()) {
1814                 delete((*main_list.begin()));
1815         }
1816
1817         int table_ctr=0;
1818         
1819         /* counting turntables.. */
1820         for (xmlNodePtr cur=root->xmlChildrenNode; cur != NULL; cur = cur->next) {
1821                 if (cur->type == XML_ELEMENT_NODE) {    
1822                         if (xmlStrcmp(cur->name, (xmlChar *) "turntable")==0) {
1823                                 table_ctr++;
1824                         }
1825                 }
1826         }
1827
1828         tX_debug("Found %i turntables in set.",  table_ctr);
1829
1830         ld_create_loaddlg(TX_LOADDLG_MODE_MULTI, table_ctr);
1831         ld_set_setname(fname);
1832
1833         /* parsing all */
1834         for (xmlNodePtr cur=root->xmlChildrenNode; cur != NULL; cur = cur->next) {
1835                 if (cur->type == XML_ELEMENT_NODE) {                    
1836                         elementFound=0;
1837                 
1838                         restore_float_id("master_volume", master_volume, sp_master_volume, set_master_volume(master_volume));
1839                         restore_float_id("master_pitch", globals.pitch, sp_master_pitch, set_master_pitch(globals.pitch));
1840                         
1841                         if ((!elementFound) && (xmlStrcmp(cur->name, (xmlChar *) "turntable")==0)) {
1842                                 elementFound=1;
1843                                 vtt_class *vtt=new vtt_class(1);
1844                                 vtt->load(doc, cur);
1845                                 
1846                                 tX_debug("loading a turntable..");
1847
1848                                 if (strlen(vtt->filename)) {
1849                                         strcpy(fn_buff, vtt->filename);
1850                                         ld_set_filename(fn_buff);
1851                                 
1852                                         restmp=(int) vtt->load_file(fn_buff);
1853                                         res+=restmp;
1854                                 }
1855         
1856                                 gtk_box_pack_start(GTK_BOX(control_parent), vtt->gui.control_box, TRUE, TRUE, 0);
1857                                 gtk_box_pack_start(GTK_BOX(audio_parent), vtt->gui.audio_box, TRUE, TRUE, 0);
1858                                 if (vtt->audio_hidden) vtt->hide_audio(vtt->audio_hidden);
1859                                 if (vtt->control_hidden) vtt->hide_control(vtt->control_hidden);\r
1860                         }
1861                         if ((!elementFound) && (xmlStrcmp(cur->name, (xmlChar *) "sequencer")==0)) {
1862                                 elementFound=1;
1863                                 sequencer.load(doc, cur);
1864                         }
1865                         if (!elementFound) {
1866                                 tX_warning("unhandled element %s in setfile %s", cur->name, fname);
1867                         }
1868                 }
1869         }
1870         
1871         ld_destroy();
1872         
1873         return(res);
1874 }
1875
1876 void add_vtt(GtkWidget *ctrl, GtkWidget *audio, char *fn)
1877 {
1878         vtt_class *hmmpg;
1879         hmmpg = new vtt_class(1);
1880         gtk_box_pack_start(GTK_BOX(ctrl), hmmpg->gui.control_box, TRUE, TRUE, 0);
1881         gtk_box_pack_start(GTK_BOX(audio), hmmpg->gui.audio_box, TRUE, TRUE, 0);
1882         if (fn) hmmpg->load_file(fn);
1883 }
1884
1885 extern void vg_move_fx_panel_up(GtkWidget *wid, vtt_class *vtt);
1886 extern void vg_move_fx_panel_down(GtkWidget *wid, vtt_class *vtt);
1887
1888 //#define debug_fx_stack(); for (i=fx_list.begin(); i != fx_list.end(); i++) puts((*i)->get_info_string());
1889 #define debug_fx_stack();
1890
1891 void vtt_class :: effect_up(vtt_fx *effect)
1892 {
1893         list <vtt_fx *> :: iterator i;
1894         list <vtt_fx *> :: iterator previous;
1895         int ok=0;
1896         
1897         debug_fx_stack();
1898         
1899         if ((*fx_list.begin())==effect) return;
1900         
1901         for (previous=i=fx_list.begin(); i != fx_list.end(); i++)
1902         {
1903                 if ((*i) == effect)
1904                 {
1905                         ok=1;
1906                         break;
1907                 }
1908                 previous=i;
1909         }
1910         
1911         if (ok)
1912         {       
1913                 pthread_mutex_lock(&render_lock);
1914                 fx_list.remove(effect);
1915                 fx_list.insert(previous, effect);
1916                 pthread_mutex_unlock(&render_lock);
1917
1918                 vg_move_fx_panel_up(effect->get_panel_widget(), this);
1919         }
1920         
1921         debug_fx_stack();
1922 }
1923
1924 void vtt_class :: effect_down(vtt_fx *effect)
1925 {
1926         list <vtt_fx *> :: iterator i;
1927         int ok=0;
1928
1929         debug_fx_stack();
1930                 
1931         for (i=fx_list.begin(); i != fx_list.end(); i++)
1932         {
1933                 if ((*i) == effect)
1934                 {
1935                         ok=1;
1936                         break;
1937                 }
1938         }
1939         
1940         if ((ok) && (i!=fx_list.end()))
1941         {
1942                 i++;
1943                 if (i==fx_list.end()) return;
1944                 i++;
1945
1946                 pthread_mutex_lock(&render_lock);
1947                 fx_list.remove(effect);
1948                 
1949                 fx_list.insert(i, effect);
1950                 vg_move_fx_panel_down(effect->get_panel_widget(), this);
1951                 pthread_mutex_unlock(&render_lock);
1952         }
1953         
1954 debug_fx_stack();       
1955 }
1956
1957 void vtt_class ::  effect_remove(vtt_fx_ladspa *effect)
1958 {
1959         pthread_mutex_lock(&render_lock);
1960         fx_list.remove(effect);
1961         pthread_mutex_unlock(&render_lock);
1962         
1963         delete effect;
1964 }
1965
1966 extern void gui_hide_control_panel(vtt_class *vtt, bool hide);
1967 extern void gui_hide_audio_panel(vtt_class *vtt, bool hide);
1968
1969 void vtt_class :: hide_audio(bool hide) {
1970         audio_hidden=hide;
1971         gui_hide_audio_panel(this, hide);
1972 }
1973
1974 void vtt_class :: hide_control(bool hide) {
1975         control_hidden=hide;
1976         gui_hide_control_panel(this, hide);     
1977 }