XML serialization for set files, bug fixes and a new full screen mode
[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=fade_out=fade_in=0;
550
551         if (speed != speed_target)
552         {
553                 speed_target=speed;
554                 speed_step=speed_target-speed_real;
555                 speed_step/=10.0;
556         }
557                         
558         if (speed_target != speed_real)
559         {
560                 speed_real+=speed_step;
561                 if ((speed_step<0) && (speed_real<speed_target)) speed_real=speed_target;
562                 else
563                 if ((speed_step>0) && (speed_real>speed_target)) speed_real=speed_target;                       
564         }
565         
566         if (fade)
567         {
568                 if ((speed_last==0) && (speed_real !=0))
569                 {
570                         fade_in=1;
571                         fade=NEED_FADE_OUT;
572                 }
573         }
574         else
575         {
576                 if ((speed_last!=0) && (speed_real==0))
577                 {
578                         fade_out=1;
579                         fade=NEED_FADE_IN;
580                 }
581         }
582
583         speed_last = speed_real;
584
585         if (res_mute != res_mute_old)
586         {
587                 if (res_mute)
588                 {
589                         fade_out=1; fade_in=0;
590                         fade=NEED_FADE_IN;
591                 }
592                 else
593                 {
594                         fade_in=1; fade_out=0;
595                         fade=NEED_FADE_OUT;
596                 }
597                 res_mute_old=res_mute;
598         }
599         else
600         {
601                 if (res_mute) do_mute=1;
602         }       
603 }
604
605 void vtt_class :: render_scratch()
606 {
607         int16_t *ptr;
608         
609         int sample;
610         
611         f_prec pos_a_f;
612         
613         f_prec amount_a;
614         f_prec amount_b;
615
616         f_prec sample_a;
617         f_prec sample_b;
618         
619         f_prec sample_res;
620         
621         f_prec *out;
622         f_prec fade_vol;        
623
624         calc_speed();
625                                         
626         for (sample =0,out=output_buffer, fade_vol=0.0; sample < samples_in_outputbuffer;sample++, out++, fade_vol+=inv_samples_in_outputbuffer)
627         {
628                 if ((speed_real!=0) || (fade_out))
629                 {
630
631                         pos_f+=speed_real;
632
633                         if (pos_f>maxpos)
634                         {
635                                 pos_f-=maxpos;
636                                 if (res_pitch>0)
637                                 {
638                                         if (loop)
639                                         {
640                                         if (is_sync_master)
641                                         {
642                                                 master_triggered=1;
643                                                 master_triggered_at=sample;
644                                         }
645                                         }
646                                         else
647                                         {
648                                                 want_stop=1;
649                                         }
650                                         
651                                 }
652                         }
653                         else if (pos_f<0)
654                         {
655                                 pos_f+=maxpos;
656                                 if (res_pitch<0)
657                                 {
658                                         if (loop)
659                                         {
660                                         if (is_sync_master)
661                                         {
662                                                 master_triggered=1;
663                                                 master_triggered_at=sample;
664                                         }
665                                         }
666                                         else
667                                         {
668                                                 want_stop=1;
669                                         }
670                                 }
671                         }
672                                 
673                         pos_a_f=floor(pos_f);
674                         pos_i=(unsigned int) pos_a_f;
675                                                                 
676                         amount_b=pos_f-pos_a_f;                         
677                         amount_a=1.0-amount_b;                          
678                                 
679                         if (do_mute)
680                         {
681                                 *out=0.0;
682                         }
683                         else
684                         {
685                                 ptr=&buffer[pos_i];
686                                 sample_a=(f_prec) *ptr;
687                         
688                                 if (pos_i == samples_in_buffer) 
689                                 {
690                                         sample_b=*buffer;
691                                 }
692                                 else
693                                 {
694                                         ptr++;
695                                         sample_b=(f_prec) *ptr;
696                                 }
697                                 
698                                 sample_res=(sample_a*amount_a)+(sample_b*amount_b);
699                                                                 
700                                 if (fade_in)
701                                 {
702                                         sample_res*=fade_vol;
703                                 }
704                                 else
705                                 if (fade_out)
706                                 {
707                                         sample_res*=1.0-fade_vol;
708                                 }
709  
710                                 *out=sample_res;
711                         }
712                 }
713                 else
714                 {
715                                 *out=0;
716                 }
717         }
718 }       
719
720 void vtt_class :: forward_turntable()
721 {
722         int sample;
723         double pos_f_tmp;
724 #ifdef pos_f_test
725         int show=0;
726         double diff;
727 #endif
728
729         calc_speed();
730
731         if ((speed_real==0) && (!fade_out)) return;
732         
733         
734         /* following code is problematic as adding speed_real*n is
735           different from adding speed_real n times to pos_f.
736           
737           well it speeds things up quite a bit and double precision
738           seems to do a satisfying job.
739           
740           #define pos_f_test to prove that.
741         */
742         
743         pos_f_tmp=pos_f+speed_real*samples_in_outputbuffer;
744         
745         if ((pos_f_tmp > 0) && (pos_f_tmp < maxpos))
746         {
747 #ifdef pos_f_test
748                 show=1;
749 #else   
750                 pos_f=pos_f_tmp;
751                 return;
752 #endif          
753         }
754                                 
755         /* now the slow way ;) */
756         
757         for (sample =0; sample < samples_in_outputbuffer; sample++)
758         {
759                         pos_f+=speed_real;
760
761                         if (pos_f>maxpos)
762                         {
763                                 pos_f-=maxpos;
764                                 if (res_pitch>0)
765                                 {
766                                         if (loop)
767                                         {
768                                         if (is_sync_master)
769                                         {
770                                                 master_triggered=1;
771                                                 master_triggered_at=sample;
772                                         }
773                                         }
774                                         else
775                                         {
776                                                 want_stop=1;
777                                         }
778                                         
779                                 }
780                         }
781                         else if (pos_f<0)
782                         {
783                                 pos_f+=maxpos;
784                                 if (res_pitch<0)
785                                 {
786                                         if (loop)
787                                         {
788                                         if (is_sync_master)
789                                         {
790                                                 master_triggered=1;
791                                                 master_triggered_at=sample;
792                                         }
793                                         }
794                                         else
795                                         {
796                                                 want_stop=1;
797                                         }
798                                 }
799                         }
800                 
801         }
802 #ifdef pos_f_test
803         if (show)
804         {
805                 diff=pos_f_tmp-pos_f;
806                 if (diff!=0) printf("fast: %f, slow: %f, diff: %f, tt: %s\n", pos_f_tmp, pos_f, diff, name);
807         }
808 #endif  
809 }       
810
811 /*
812         The following lowpass filter is based on some sample code by
813         Paul Kellett <paul.kellett@maxim.abel.co.uk>
814 */
815
816 void vtt_class :: render_lp()
817 {
818         f_prec *sample;
819                 
820         for (sample = output_buffer; sample<end_of_outputbuffer; sample++)
821         {
822                 lp_buf0 = lp_a * lp_buf0 + lp_freq * ((*sample)*lp_resgain + lp_b * (lp_buf0 - lp_buf1));
823                 lp_buf1 = lp_a * lp_buf1 + lp_freq * lp_buf0;
824                 
825                 *sample=lp_buf1;
826         }
827 }
828
829 void vtt_class :: render_ec()
830 {
831         f_prec *sample;
832         f_prec *ec_sample;
833         int i;
834
835         for (i=0, sample = output_buffer, ec_sample=ec_output_buffer; i<samples_in_outputbuffer; i++, ec_sample++,sample++, ec_ptr++)
836         {
837                 if (ec_ptr>ec_delay) ec_ptr=ec_buffer;
838                 *ec_sample=(*ec_ptr) *ec_feedback;
839                 *ec_ptr=*sample+*ec_sample;
840         }       
841 }
842
843 int vtt_class :: set_mix_buffer_size(int no_samples)
844 {
845         list <vtt_class *> :: iterator vtt;
846         int res=0;
847         
848 //      printf("vtt_class::set_mix_buffer_size(), mix_buffer: %12x, mix_out: %12x, samples: %i\n", mix_buffer, mix_out_buffer, no_samples);
849         
850         if (mix_buffer) tX_freemem(mix_buffer, "mix_buffer", "vtt set_mix_buffer_size()");
851         samples_in_mix_buffer=no_samples*2;
852
853         tX_malloc(mix_buffer, "mix_buffer", "vtt set_mix_buffer_size()", sizeof(float)*samples_in_mix_buffer, (float *));
854         mix_buffer_end=mix_buffer+samples_in_mix_buffer;
855
856 //      printf("mix_buffer: %12x\n", mix_buffer);
857 //      printf("mix_samples: %i, out_samples: %i", samples_in_mix_buffer, no_samples);
858         
859         if (mix_out_buffer) tX_freemem(mix_out_buffer, "mix_out_buffer", "vtt set_mix_buffer_size()");
860         tX_malloc(mix_out_buffer, "mix_out_buffer", "vtt set_mix_buffer_size()", sizeof(int16_t)*samples_in_mix_buffer + 4, (int16_t *));
861
862 //      printf("mix_out_buffer: %12x\n", mix_out_buffer);
863         
864         for (vtt=main_list.begin(); vtt!=main_list.end(); vtt++)
865         {
866                 res|=(*vtt)->set_output_buffer_size(no_samples);
867         }
868         
869         if ((!mix_buffer) || (!mix_out_buffer) || res) return(1);
870         return(0);
871 }
872
873 int16_t * vtt_class :: render_all_turntables()
874 {
875         list <vtt_class *> :: iterator vtt, next;
876         int sample;
877         int mix_sample;
878         f_prec temp;
879
880 #ifdef USE_3DNOW
881         mmx_t *mix;
882         mmx_t *vtt_buffer;
883         int32_t *mix_int;
884 #endif
885
886 #ifdef USE_FLASH
887         f_prec max;
888         f_prec min;
889 #ifdef USE_3DNOW
890         mmx_t mm_max;
891         mmx_t mm_min;
892         mmx_t mm_volume;
893         mmx_t mm_src1;
894         mmx_t mm_src2;
895
896 #ifndef OVERRIDE_MOVQ_AUTODETECT
897 #ifndef GCC_VERSION
898 #define GCC_VERSION (__GNUC__ * 1000 + __GNUC_MINOR__)
899 #endif /* GCC_VERSION */
900
901 #if (GCC_VERSION < 2096)
902 #warning "*************************"
903 #warning "* gcc < 2.96            *"
904 #warning "* assuming working movq *"
905 #warning "*************************"
906 #undef GCC_MOVQ_BUG_WORKAROUND
907 #else
908 #warning "*************************"
909 #warning "* gcc >= 2.96           *"
910 #warning "* using movq-workaround *"
911 #warning "*************************"
912 #define GCC_MOVQ_BUG_WORKAROUND 1
913 #endif /* GCC < 2.96 */
914 #endif /* OVERRIDE MOVQ AUTODETECVT */
915         
916 #ifdef GCC_MOVQ_BUG_WORKAROUND
917         /* REQUIRED DUE TO GCC BUG (2.96-3.0.2) */
918         mmx_t *mm_src1_ptr=&mm_src1;
919         mmx_t *mm_src2_ptr=&mm_src2;
920         mmx_t *mm_volume_ptr=&mm_volume;
921         mmx_t *mm_max_ptr=&mm_max;
922         mmx_t *mm_min_ptr=&mm_min;
923         
924 #define MM_VAR_ACC(var) (* var ## _ptr)
925 #define MM_VAR_MOVQ(var) * var ## _ptr
926 #else
927 #define MM_VAR_ACC(var) var
928 #define MM_VAR_MOVQ(var) var
929 #endif  
930         int32_t *temp_int=&mm_max.d[1];
931 #endif  
932 #endif  
933         
934         pthread_mutex_lock(&render_lock);
935         
936         if (render_list.size()==0)
937         {
938                 for (sample=0; sample<samples_in_mix_buffer; sample++)
939                 {
940                         mix_out_buffer[sample]=0;
941                 }
942         }
943         else
944         {
945                         vtt=render_list.begin();
946                         (*vtt)->render();                       
947                         max=(*vtt)->max_value;
948                         min=max;
949
950 #ifndef USE_3DNOW
951                         for (sample=0, mix_sample=0; sample<(*vtt)->samples_in_outputbuffer; sample++)
952                         {                               
953                                 temp=(*vtt)->output_buffer[sample];
954                                 mix_buffer[mix_sample]=temp*(*vtt)->res_volume_left;
955                                 mix_sample++;
956                                 mix_buffer[mix_sample]=temp*(*vtt)->res_volume_right;
957                                 mix_sample++;
958                                 
959                                 if (temp>max) max=temp;
960                                 else if (temp<min) min=temp;
961                         }
962 #else
963                         MM_VAR_ACC(mm_volume).s[0]=(*vtt)->res_volume_left;
964                         MM_VAR_ACC(mm_volume).s[1]=(*vtt)->res_volume_right;
965
966                         MM_VAR_ACC(mm_max).s[1]=MM_VAR_ACC(mm_max).s[0]=max;
967                         MM_VAR_ACC(mm_min).s[1]=MM_VAR_ACC(mm_min).s[0]=min;
968                         
969                         movq_m2r(MM_VAR_MOVQ(mm_max), mm1);
970                         movq_m2r(MM_VAR_MOVQ(mm_min), mm2);
971                                                         
972                         movq_m2r(MM_VAR_MOVQ(mm_volume), mm0);
973                         
974                         mix=(mmx_t*)mix_buffer;
975                         
976                         for (f_prec* src=(*vtt)->output_buffer; mix < (mmx_t*) mix_buffer_end;)
977                         {
978                                 /* first sample */
979                                 MM_VAR_ACC(mm_src1).s[0]=*src;
980                                 MM_VAR_ACC(mm_src1).s[1]=*src;
981                                         
982                                 /* sample * l/r volume */
983                                 movq_m2r(MM_VAR_MOVQ(mm_src1), mm3);
984                                 pfmul_r2r(mm0, mm3);
985                                 movq_r2m(mm3, *mix);
986                                         
987                                 /* next sample */
988                                 src++, mix++;
989                                 MM_VAR_ACC(mm_src2).s[0]=*src;
990                                 MM_VAR_ACC(mm_src2).s[1]=*src;
991                                         
992                                 /* sample * l/r volume */
993                                 movq_m2r(MM_VAR_MOVQ(mm_src2), mm3);
994                                 pfmul_r2r(mm0, mm3);
995                                 movq_r2m(mm3, *mix);
996                                         
997                                 /* calculating min/max */
998                                 MM_VAR_ACC(mm_src1).s[1]=MM_VAR_ACC(mm_src2).s[0];
999                                 movq_m2r(mm_src1, mm3);
1000                                 pfmax_r2r(mm3, mm1);
1001                                 pfmin_r2r(mm3, mm2);
1002                                 
1003                                 src++, mix++;
1004                         }
1005
1006                         movq_r2m(mm1, MM_VAR_MOVQ(mm_max));
1007                         movq_r2m(mm2, MM_VAR_MOVQ(mm_min));
1008                         
1009                         femms();
1010                         
1011                         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];
1012                         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];
1013 #endif                  
1014                         
1015                         min*=-1.0;
1016                         if (min>max) (*vtt)->max_value=min; else (*vtt)->max_value=max;
1017
1018                         if ((*vtt)->ec_enable)
1019                         {
1020 #ifndef USE_3DNOW                       
1021                                 for (sample=0, mix_sample=0; sample<(*vtt)->samples_in_outputbuffer; sample++)
1022                                 {                               
1023                                         temp=(*vtt)->ec_output_buffer[sample];
1024                                         
1025                                         mix_buffer[mix_sample]+=temp*(*vtt)->ec_volume_left;
1026                                         mix_sample++;
1027                                         mix_buffer[mix_sample]+=temp*(*vtt)->ec_volume_right;
1028                                         mix_sample++;
1029                                 }
1030 #else
1031                                 MM_VAR_ACC(mm_volume).s[0]=(*vtt)->ec_volume_left;
1032                                 MM_VAR_ACC(mm_volume).s[1]=(*vtt)->ec_volume_right;
1033                                                 
1034                                 movq_m2r(MM_VAR_MOVQ(mm_volume), mm0);
1035                                 mix =(mmx_t*)mix_buffer;
1036
1037                                 for (f_prec* src=(*vtt)->ec_output_buffer; mix < (mmx_t*) mix_buffer_end; src++, mix++)
1038                                 {
1039                                         /* first sample */
1040                                         MM_VAR_ACC(mm_src1).s[0]=*src;
1041                                         MM_VAR_ACC(mm_src1).s[1]=*src;
1042                                 
1043                                         /* sample * l/r volume */
1044                                         movq_m2r(MM_VAR_MOVQ(mm_src1), mm3);
1045                                         pfmul_r2r(mm0, mm3);
1046                                 
1047                                         /* accumulating complete mix */
1048                                         movq_m2r(*mix, mm4);
1049                                         pfadd_r2r(mm4, mm3);
1050                                         movq_r2m(mm3, *mix);
1051                                 }
1052                                 femms();
1053 #endif                          
1054                         }
1055                         
1056                         if (master_triggered)
1057                         {
1058                                 pthread_mutex_unlock(&render_lock);
1059                                 for (vtt=main_list.begin(); vtt!=main_list.end(); vtt++)
1060                                 {
1061                                         if ((*vtt)->is_sync_client)
1062                                         {
1063                                                 if ((*vtt)->sync_countdown)
1064                                                 {
1065                                                         (*vtt)->sync_countdown--;
1066                                                 }
1067                                                 else
1068                                                 {
1069                                                         (*vtt)->sync_countdown=(*vtt)->sync_cycles;
1070                                                         (*vtt)->trigger();
1071                                                 }
1072                                         }
1073                                 }
1074                                 pthread_mutex_lock(&render_lock);
1075                         }
1076                         
1077                         vtt=render_list.begin();
1078                         for (vtt++; vtt!=render_list.end(); vtt++)
1079                         {
1080                                 (*vtt)->render();                                       
1081                                 max=(*vtt)->max_value;
1082                                 min=max;
1083
1084 #ifndef USE_3DNOW
1085                                 for (sample=0, mix_sample=0; sample<(*vtt)->samples_in_outputbuffer; sample++)
1086                                 {                               
1087                                         temp=(*vtt)->output_buffer[sample];
1088                                         mix_buffer[mix_sample]+=temp*(*vtt)->res_volume_left;
1089                                         mix_sample++;                                   
1090                                         mix_buffer[mix_sample]+=temp*(*vtt)->res_volume_right;
1091                                         mix_sample++;
1092                                 
1093                                         if (temp>max) max=temp;
1094                                         else if (temp<min) min=temp;
1095                                 }
1096 #else
1097                                 MM_VAR_ACC(mm_volume).s[0]=(*vtt)->res_volume_left;
1098                                 MM_VAR_ACC(mm_volume).s[1]=(*vtt)->res_volume_right;
1099
1100                                 MM_VAR_ACC(mm_max).s[1]=MM_VAR_ACC(mm_max).s[0]=max;
1101                                 MM_VAR_ACC(mm_min).s[1]=MM_VAR_ACC(mm_min).s[0]=min;
1102                         
1103                                 movq_m2r(MM_VAR_MOVQ(mm_max), mm1);
1104                                 movq_m2r(MM_VAR_MOVQ(mm_min), mm2);
1105                                                         
1106                                 movq_m2r(MM_VAR_MOVQ(mm_volume), mm0);
1107                                 mix=(mmx_t*)mix_buffer;
1108
1109                                 for (f_prec* src=(*vtt)->output_buffer; mix < (mmx_t*) mix_buffer_end;)
1110                                 {
1111                                         /* first sample */
1112                                         MM_VAR_ACC(mm_src1).s[0]=*src;
1113                                         MM_VAR_ACC(mm_src1).s[1]=*src;
1114                                         
1115                                         /* sample * l/r volume */
1116                                         movq_m2r(MM_VAR_MOVQ(mm_src1), mm3);
1117                                         pfmul_r2r(mm0, mm3);
1118                                         
1119                                         /* accumulating complete mix */
1120                                         movq_m2r(*mix, mm4);
1121                                         pfadd_r2r(mm4, mm3);
1122                                         movq_r2m(mm3, *mix);
1123                                         
1124                                         /* next sample */
1125                                         src++, mix++;
1126                                         MM_VAR_ACC(mm_src2).s[0]=*src;
1127                                         MM_VAR_ACC(mm_src2).s[1]=*src;
1128                                         
1129                                         /* sample * l/r volume */
1130                                         movq_m2r(MM_VAR_MOVQ(mm_src2), mm3);
1131                                         pfmul_r2r(mm0, mm3);
1132
1133                                         /* accumulating complete mix */
1134                                         movq_m2r(*mix, mm4);
1135                                         pfadd_r2r(mm4, mm3);
1136                                         movq_r2m(mm3, *mix);
1137                                         
1138                                         /* calculating min/max */
1139                                         MM_VAR_ACC(mm_src1).s[1]=MM_VAR_ACC(mm_src2).s[0];
1140                                         movq_m2r(MM_VAR_MOVQ(mm_src1), mm3);
1141                                         pfmax_r2r(mm3, mm1);
1142                                         pfmin_r2r(mm3, mm2);
1143                                         
1144                                         src++, mix++;
1145                                 }
1146
1147                                 movq_r2m(mm1, MM_VAR_MOVQ(mm_max));
1148                                 movq_r2m(mm2, MM_VAR_MOVQ(mm_min));
1149                                 
1150                                 femms();
1151         
1152                                 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];
1153                                 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];
1154 #endif
1155                                 
1156                                 min*=-1.0;
1157                                 if (min>max) (*vtt)->max_value=min; else (*vtt)->max_value=max;
1158                                 
1159                                 if ((*vtt)->ec_enable)
1160                                 {
1161 #ifndef USE_3DNOW
1162                                         for (sample=0, mix_sample=0; sample<(*vtt)->samples_in_outputbuffer; sample++)
1163                                         {                               
1164                                                 temp=(*vtt)->ec_output_buffer[sample];
1165                                                 
1166                                                 mix_buffer[mix_sample]+=temp*(*vtt)->ec_volume_left;
1167                                                 mix_sample++;
1168                                                 mix_buffer[mix_sample]+=temp*(*vtt)->ec_volume_right;
1169                                                 mix_sample++;
1170                                         }
1171 #else
1172                                         MM_VAR_ACC(mm_volume).s[0]=(*vtt)->ec_volume_left;
1173                                         MM_VAR_ACC(mm_volume).s[1]=(*vtt)->ec_volume_right;
1174                                                 
1175                                         movq_m2r(MM_VAR_MOVQ(mm_volume), mm0);
1176                                         mix =(mmx_t*)mix_buffer;
1177
1178                                         for (f_prec* src=(*vtt)->ec_output_buffer; mix < (mmx_t*) mix_buffer_end; src++, mix++)
1179                                         {
1180                                                 /* first sample */
1181                                                 MM_VAR_ACC(mm_src1).s[0]=*src;
1182                                                 MM_VAR_ACC(mm_src1).s[1]=*src;
1183                                 
1184                                                 /* sample * l/r volume */
1185                                                 movq_m2r(MM_VAR_MOVQ(mm_src1), mm3);
1186                                                 pfmul_r2r(mm0, mm3);
1187                                 
1188                                                 /* accumulating complete mix */
1189                                                 movq_m2r(*mix, mm4);
1190                                                 pfadd_r2r(mm4, mm3);
1191                                                 movq_r2m(mm3, *mix);
1192                                         }
1193
1194                                         femms();
1195 #endif                                  
1196                                 }
1197                         }
1198                         
1199                         /* left */
1200                         
1201                         max=mix_max_l;
1202                         min=max;
1203
1204                         for (sample=0; sample<samples_in_mix_buffer; sample+=2)
1205                         {                               
1206                                 temp=mix_buffer[sample];
1207                                 mix_out_buffer[sample]=(int16_t) temp;
1208                         
1209                                 if (temp>max) max=temp;
1210                                 else if (temp<min) min=temp;
1211                         }
1212                         
1213                         min*=-1.0;
1214                         if (min>max) mix_max_l=min; else mix_max_l=max;         
1215                         
1216                         /* right */
1217                         
1218                         max=mix_max_r;
1219                         min=max;
1220
1221                         for (sample=1; sample<samples_in_mix_buffer; sample+=2)
1222                         {                               
1223                                 temp=mix_buffer[sample];
1224                                 mix_out_buffer[sample]=(int16_t) temp;
1225                         
1226                                 if (temp>max) max=temp;
1227                                 else if (temp<min) min=temp;
1228                         }
1229                         
1230                         min*=-1.0;
1231                         if (min>max) mix_max_r=min; else mix_max_r=max;         
1232                         
1233         }
1234         master_triggered=0;
1235                 
1236         vtt=render_list.begin();
1237         while (vtt!=render_list.end())
1238         {
1239                 next=vtt;
1240                 next++;
1241                 
1242                 if ((*vtt)->want_stop) (*vtt)->stop_nolock();
1243                 vtt=next;
1244         }
1245         pthread_mutex_unlock(&render_lock);
1246         
1247         return(mix_out_buffer);
1248 }
1249
1250 void vtt_class :: forward_all_turntables()
1251 {
1252         list <vtt_class *> :: iterator vtt, next;
1253
1254         if (render_list.size()>0)
1255         {
1256                  vtt=render_list.begin();
1257                  (*vtt)->forward_turntable();                    
1258
1259                  if (master_triggered)
1260                  {
1261                          for (vtt=main_list.begin(); vtt!=main_list.end(); vtt++)
1262                          {
1263                                  if ((*vtt)->is_sync_client)
1264                                  {
1265                                          if ((*vtt)->sync_countdown)
1266                                          {
1267                                                  (*vtt)->sync_countdown--;
1268                                          }
1269                                          else
1270                                          {
1271                                                  (*vtt)->sync_countdown=(*vtt)->sync_cycles;
1272                                                  (*vtt)->trigger();
1273                                          }
1274                                  }
1275                          }
1276                  }
1277
1278                  vtt=render_list.begin();
1279                  for (vtt++; vtt!=render_list.end(); vtt++)
1280                  {
1281                          (*vtt)->forward_turntable();
1282                  }
1283                  
1284         }
1285         master_triggered=0;
1286         vtt=render_list.begin();
1287         while (vtt!=render_list.end())
1288         {
1289                 next=vtt;
1290                 next++;
1291                 
1292                 if ((*vtt)->want_stop) (*vtt)->stop_nolock();
1293                 vtt=next;
1294         }
1295 }
1296
1297
1298 int vtt_class :: trigger()
1299 {
1300         list <vtt_fx *> :: iterator effect;
1301
1302         if (!buffer) return (1);
1303         
1304         if (!is_playing) pthread_mutex_lock(&render_lock);
1305         
1306         if (res_pitch>=0) pos_f=0;
1307         else pos_f=maxpos;
1308         fade=NEED_FADE_OUT;
1309         speed=res_pitch;
1310         speed_real=res_pitch;
1311         speed_target=res_pitch;
1312         want_stop=0;
1313
1314         /* activating plugins */
1315         for (effect=fx_list.begin(); effect != fx_list.end(); effect++)
1316         {
1317                 (*effect)->activate();
1318         }
1319
1320
1321 #ifdef USE_FLASH
1322         max_value=0;
1323 #endif
1324         
1325         if (is_sync_master)
1326         {
1327                 master_triggered=1;
1328                 master_triggered_at=0;
1329         }
1330         
1331         if (!is_playing)
1332         {
1333                 is_playing=1;
1334         
1335                 if (is_sync_master) 
1336                 {
1337                         render_list.push_front(this);           
1338                 }               
1339                 else
1340                 {
1341                         render_list.push_back(this);
1342                 }
1343                 pthread_mutex_unlock(&render_lock);
1344         }
1345         return(0);
1346 }
1347
1348 int vtt_class :: stop_nolock()
1349 {
1350         list <vtt_fx *> :: iterator effect;
1351
1352         if (!is_playing) 
1353         {
1354                 pthread_mutex_unlock(&render_lock);
1355                 return(1);
1356         }
1357         render_list.remove(this);
1358         want_stop=0;
1359
1360         is_playing=0;
1361
1362 #ifdef USE_FLASH
1363         max_value=0;
1364 #endif
1365         cleanup_vtt(this);
1366         sync_countdown=0;
1367         
1368         /* deactivating plugins */
1369         for (effect=fx_list.begin(); effect != fx_list.end(); effect++)
1370         {
1371                 (*effect)->deactivate();
1372         }
1373         
1374         return(0);
1375 }
1376
1377 int vtt_class :: stop()
1378 {
1379         int res;
1380         
1381         pthread_mutex_lock(&render_lock);
1382
1383         res=stop_nolock();
1384
1385         pthread_mutex_unlock(&render_lock);
1386
1387         return(res);
1388 }
1389
1390 void vtt_class :: set_sync_master(int master)
1391 {
1392         if (master)
1393         {
1394                 if (sync_master) sync_master->set_sync_master(0);
1395                 sync_master=this;
1396                 is_sync_master=1;
1397         }
1398         else
1399         {
1400                 if (sync_master==this) sync_master=0;
1401                 is_sync_master=0;
1402                 gui_clear_master_button(this);
1403         }
1404 }
1405
1406 void vtt_class :: set_sync_client(int slave, int cycles)
1407 {
1408         is_sync_client=slave;
1409         sync_cycles=cycles;
1410 //      sync_countdown=cycles; 
1411         sync_countdown=0;
1412 }
1413
1414 void vtt_class :: set_sync_client_ug(int slave, int cycles)
1415 {
1416         set_sync_client(slave, cycles);
1417 }
1418
1419 void vtt_class :: set_master_volume(f_prec new_volume)
1420 {
1421         list <vtt_class *> :: iterator vtt;
1422
1423         master_volume=new_volume;
1424         globals.volume=new_volume;
1425         
1426         if (main_list.size()>0)
1427         {
1428                 vol_channel_adjust=sqrt((f_prec) main_list.size());
1429                 res_master_volume=master_volume/vol_channel_adjust;             
1430         }
1431                 
1432         for (vtt=main_list.begin(); vtt!=main_list.end(); vtt++)
1433         {
1434                 (*vtt)->recalc_volume();
1435         }
1436 }
1437
1438 void vtt_class :: set_master_pitch(f_prec new_pitch)
1439 {
1440         list <vtt_class *> :: iterator vtt;
1441         
1442         globals.pitch=new_pitch;
1443         for (vtt=main_list.begin(); vtt!=main_list.end(); vtt++)
1444         {
1445                 (*vtt)->recalc_pitch();
1446         }
1447 }
1448
1449 void vtt_class :: enable_saturate (int newstate)
1450 {
1451         do_saturate=newstate;
1452 }
1453
1454 void vtt_class :: focus_no(int no)
1455 {
1456         list <vtt_class *> :: iterator vtt;
1457         int i;
1458
1459         for (i=0, vtt=main_list.begin(); vtt!=main_list.end(); vtt++, i++)
1460         {
1461                 if (i==no)
1462                 {
1463                         focused_vtt=(*vtt);
1464                 }
1465         }
1466 }
1467
1468 void vtt_class :: focus_next()
1469 {
1470         list <vtt_class *> :: iterator vtt;
1471         
1472         if (!focused_vtt)
1473         {
1474                 if (main_list.size())
1475                 {
1476                         focused_vtt=(*main_list.begin());
1477                 }
1478                 return;
1479         }
1480         
1481         for (vtt=main_list.begin(); vtt!=main_list.end() ; vtt++) {
1482                 if ((*vtt)==focused_vtt) {
1483                         /* Ok, we found ourselves.. */
1484                         
1485                         vtt++;
1486                         while ((vtt!=main_list.end()) && ((*vtt)->audio_hidden) ) {
1487                                 vtt++;
1488                         }
1489                         
1490                         if (vtt==main_list.end()) {
1491                                 /* No other "focusable" after this vtt so we're looking for the next */
1492                                 
1493                                 for (vtt=main_list.begin(); vtt!=main_list.end() ; vtt++) {
1494                                         if (! (*vtt)->audio_hidden) {
1495                                                 focused_vtt=(*vtt);
1496                                                 return;
1497                                         }
1498                                 }
1499                                 /* When we get here there's no "focusable" vtt at all... damn */
1500                                 focused_vtt=NULL;
1501                                 return;
1502                         } else {
1503                                 focused_vtt=(*vtt);
1504                                 return;
1505                         }
1506                 }
1507         }
1508         
1509         focused_vtt=(*main_list.begin());
1510 }
1511
1512 void vtt_class :: set_scratch(int newstate)
1513 {
1514         if (newstate)
1515         {
1516                 sp_spin.receive_input_value(0);
1517                 do_scratch=1;
1518                 sense_cycles=globals.sense_cycles;
1519         }
1520         else
1521         {
1522                 sp_spin.receive_input_value(1);
1523                 do_scratch=0;
1524         }
1525 }
1526
1527
1528 void vtt_class :: unfocus()
1529 {
1530         focused_vtt=NULL;
1531 }
1532
1533 void vtt_class :: set_x_input_parameter(tX_seqpar *sp)
1534 {
1535         x_par = sp;
1536 }
1537
1538 void vtt_class :: set_y_input_parameter(tX_seqpar *sp)
1539 {
1540         y_par = sp;
1541 }
1542
1543 void vtt_class :: xy_input(f_prec x_value, f_prec y_value)
1544 {
1545         if (x_par) x_par->handle_mouse_input(x_value*globals.mouse_speed);
1546         if (y_par) y_par->handle_mouse_input(y_value*globals.mouse_speed);
1547 }
1548
1549 #define store(data); if (fwrite((void *) &data, sizeof(data), 1, output)!=1) res+=1;
1550
1551 int  vtt_class :: save(FILE *rc, char *indent) {
1552         list <vtt_fx *> :: iterator effect;
1553         char tmp_xml_buffer[4096];
1554         
1555         int res=0;
1556
1557         fprintf(rc, "%s<turntable>\n", indent);
1558         strcat(indent, "\t");
1559         
1560         store_string("name", name);
1561         if (buffer) {
1562                 store_string("audiofile", filename);
1563         } else {
1564                 store_string("audiofile", "");
1565         }
1566         store_bool("sync_master", is_sync_master);
1567         store_bool("autotrigger", autotrigger);
1568         store_bool_id("loop", loop, sp_loop.get_persistence_id());
1569
1570         store_bool_id("sync_client", is_sync_client, sp_sync_client.get_persistence_id());
1571         store_int_id("sync_cycles", sync_cycles, sp_sync_cycles.get_persistence_id());
1572
1573         store_float_id("volume", rel_volume, sp_volume.get_persistence_id());
1574         store_float_id("pitch", rel_pitch, sp_pitch.get_persistence_id());      
1575         store_bool_id("mute", mute, sp_mute.get_persistence_id());
1576         store_float_id("pan", pan, sp_pan.get_persistence_id());
1577         
1578         store_bool_id("lowpass_enable", lp_enable, sp_lp_enable.get_persistence_id());
1579         store_float_id("lowpass_gain", lp_gain, sp_lp_gain.get_persistence_id());
1580         store_float_id("lowpass_reso", lp_reso, sp_lp_reso.get_persistence_id());
1581         store_float_id("lowpass_freq", lp_freq, sp_lp_freq.get_persistence_id());
1582
1583         store_bool_id("echo_enable", ec_enable, sp_ec_enable.get_persistence_id());
1584         store_float_id("echo_length", ec_length, sp_ec_length.get_persistence_id());
1585         store_float_id("echo_feedback", ec_feedback, sp_ec_feedback.get_persistence_id());
1586         store_float_id("echo_pan", ec_pan, sp_ec_pan.get_persistence_id());
1587         store_float_id("echo_volume", ec_volume, sp_ec_volume.get_persistence_id());
1588         
1589         store_id("speed", sp_speed.get_persistence_id());
1590         store_id("trigger", sp_trigger.get_persistence_id());
1591         store_id("spin", sp_spin.get_persistence_id());
1592
1593         
1594         if (x_par) {
1595                 store_int("x_axis_mapping", x_par->get_persistence_id());
1596         }
1597         
1598         if (y_par) {
1599                 store_int("y_axis_mapping", y_par->get_persistence_id());
1600         }
1601
1602         store_bool("audio_panel_hidden", audio_hidden);
1603         store_bool("control_panel_hidden", control_hidden);
1604         store_bool("main_panel_hidden", gui.main_panel->is_hidden());
1605         store_bool("trigger_panel_hidden", gui.trigger_panel->is_hidden());
1606         store_bool("lowpass_panel_hidden", gui.lp_panel->is_hidden());
1607         store_bool("echo_panel_hidden", gui.ec_panel->is_hidden());
1608
1609         store_float("audio_x_zoom", gui_get_audio_x_zoom(this));
1610         
1611         fprintf(rc, "%s<fx>\n", indent);
1612         strcat(indent, "\t");
1613         
1614         for (effect=fx_list.begin(); effect!=fx_list.end(); effect++) {
1615                 (*effect)->save(rc, indent);
1616         }
1617         indent[strlen(indent)-1]=0;
1618         fprintf(rc, "%s</fx>\n", indent);
1619         
1620         indent[strlen(indent)-1]=0;
1621         fprintf(rc, "%s</turntable>\n", indent);
1622         
1623         return(res);
1624 }
1625
1626 #define TX_XML_SETFILE_VERSION "1.0"
1627
1628 int  vtt_class :: save_all(FILE* rc) {
1629         int res=0;
1630         list <vtt_class *> :: iterator vtt;
1631         char indent[256];
1632         
1633         tX_seqpar :: create_persistence_ids();
1634
1635         fprintf(rc, "<?xml version=\"1.0\" encoding=\"US-ASCII\"?>\n\n");
1636         fprintf(rc, "<terminatorXset version=\"%s\">\n", TX_XML_SETFILE_VERSION);
1637         
1638         strcpy(indent, "\t");
1639
1640         //store_int(vtt_amount); obsolete
1641
1642         store_float_id("master_volume", master_volume, sp_master_volume.get_persistence_id());
1643         store_float_id("master_pitch", globals.pitch, sp_master_pitch.get_persistence_id());
1644
1645         for (vtt=main_list.begin(); vtt!=main_list.end(); vtt++) {
1646                 res+=(*vtt)->save(rc, indent);
1647         }
1648         
1649         sequencer.save(rc, indent);
1650         
1651         fprintf(rc, "</terminatorXset>\n");
1652         
1653         return(res);
1654 }
1655
1656 int vtt_class :: load(xmlDocPtr doc, xmlNodePtr node) {
1657         char buffer[1024];
1658         bool hidden;
1659         int xpar_id=-1;
1660         int ypar_id=-1;
1661         int elementFound;
1662         char *pid_attr;
1663         int pid;
1664         double dvalue;
1665         double tmp;
1666         
1667         for (xmlNodePtr cur=node->xmlChildrenNode; cur != NULL; cur = cur->next) {
1668                 if (cur->type == XML_ELEMENT_NODE) {
1669                         elementFound=0;
1670                         
1671                         restore_string_ac("name", buffer, set_name(buffer));
1672                         restore_string("audiofile", filename);
1673                         restore_bool("sync_master", is_sync_master);
1674                         restore_bool("autotrigger", autotrigger);
1675                         restore_bool_id("loop", loop, sp_loop, nop);
1676                         restore_bool_id("sync_client", is_sync_client, sp_sync_client, set_sync_client(is_sync_client, sync_cycles));
1677                         restore_int_id("sync_cycles", sync_cycles, sp_sync_cycles, set_sync_client(is_sync_client, sync_cycles));
1678                         restore_float_id("volume", rel_volume, sp_volume, recalc_volume());
1679                         restore_float_id("pitch", rel_pitch, sp_pitch, recalc_pitch());
1680                         restore_bool_id("mute", mute, sp_mute, set_mute(mute));
1681                         restore_float_id("pan", pan, sp_pan, set_pan(pan));
1682         
1683                         restore_bool_id("lowpass_enable", lp_enable, sp_lp_enable, lp_set_enable(lp_enable));
1684                         restore_float_id("lowpass_gain", lp_gain, sp_lp_gain, lp_set_gain(lp_gain)); 
1685                         restore_float_id("lowpass_reso", lp_reso, sp_lp_reso, lp_set_reso(lp_reso));
1686                         restore_float_id("lowpass_freq", lp_freq, sp_lp_freq, lp_set_freq(lp_freq));
1687         
1688                         restore_bool_id("echo_enable", ec_enable, sp_ec_enable, ec_set_enable(ec_enable));      
1689                         restore_float_id("echo_length", ec_length, sp_ec_length, ec_set_length(ec_length));
1690                         restore_float_id("echo_feedback", ec_feedback, sp_ec_feedback, ec_set_feedback(ec_feedback));
1691                         restore_float_id("echo_pan", ec_pan, sp_ec_pan, ec_set_pan(ec_pan));
1692                         restore_float_id("echo_volume", ec_volume, sp_ec_volume, ec_set_volume(ec_volume));             
1693                 
1694                         restore_id("speed", sp_speed);  
1695                         restore_id("trigger", sp_trigger);
1696                         restore_id("spin", sp_spin);
1697         
1698                         restore_int("x_axis_mapping", xpar_id);
1699                         restore_int("y_axis_mapping", ypar_id);
1700         
1701                         restore_bool("audio_panel_hidden", audio_hidden);
1702                         restore_bool("control_panel_hidden", control_hidden);
1703                         restore_bool_ac("main_panel_hidden", hidden, gui.main_panel->hide(hidden));
1704                         restore_bool_ac("trigger_panel_hidden", hidden, gui.trigger_panel->hide(hidden));
1705                         restore_bool_ac("lowpass_panel_hidden", hidden, gui.lp_panel->hide(hidden));                    
1706                         restore_bool_ac("echo_panel_hidden", hidden, gui.ec_panel->hide(hidden));
1707                         restore_float_ac("audio_x_zoom", tmp, gui_set_audio_x_zoom(this,tmp));
1708                         
1709                         if (xmlStrcmp(cur->name, (xmlChar *) "fx")==0) {
1710                                 xmlNodePtr fx=cur;
1711                                 elementFound=1;
1712                                 
1713                                 for (xmlNodePtr cur=fx->xmlChildrenNode; cur != NULL; cur = cur->next) {
1714                                         if (cur->type == XML_ELEMENT_NODE) {
1715                                                 int elementFound=0;
1716                                                 
1717                                                 if (xmlStrcmp(cur->name, (xmlChar *) "cutoff")==0) {
1718                                                         for (unsigned int t=0; t<fx_list.size(); t++) effect_down(lp_fx);
1719                                                         elementFound=1;
1720                                                 } else if (xmlStrcmp(cur->name, (xmlChar *) "lowpass")==0) {
1721                                                         for (unsigned int t=0; t<fx_list.size(); t++) effect_down(ec_fx);
1722                                                         elementFound=1;                                                         
1723                                                 } else if (xmlStrcmp(cur->name, (xmlChar *) "ladspa_plugin")==0) {
1724                                                         xmlNodePtr pluginNode=cur;
1725                                                         int ladspa_id=-1;
1726                                                         elementFound=1;
1727                                                         
1728                                                         for (xmlNodePtr cur=pluginNode->xmlChildrenNode; cur!=NULL; cur = cur->next) {
1729                                                                 int elementFound;
1730                                                                 if (cur->type == XML_ELEMENT_NODE) {
1731                                                                         elementFound=0;
1732
1733                                                                         restore_int("ladspa_id", ladspa_id);
1734                                                                         if (elementFound) break;
1735                                                                 }
1736                                                         }
1737                                                         
1738                                                         if (ladspa_id!=-1) {
1739                                                                 LADSPA_Plugin *plugin=LADSPA_Plugin::getPluginByUniqueID(ladspa_id);
1740                                                                 if (plugin) {
1741                                                                         vtt_fx_ladspa *ladspa_effect=add_effect(plugin);
1742                                                                         ladspa_effect->load(doc, pluginNode);
1743                                                                 } else {
1744                                                                         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);
1745                                                                         tx_note(buffer, true);                                                  
1746                                                                 }
1747                                                         } else {
1748                                                                 tX_warning("ladspa_plugin section without a ladspa_id element.");
1749                                                         }
1750                                                         
1751                                                 } else {
1752                                                         tX_warning("unhandled element %s in fx section.", cur->name);
1753                                                 }
1754                                         }
1755                                 }
1756                         }
1757                         
1758                         if(!elementFound) {
1759                                 tX_warning("unhandled element %s in turntable secion.", cur->name);
1760                         }
1761                 }
1762         }
1763
1764         recalc_volume();
1765
1766         if (xpar_id>=0) {
1767                 set_x_input_parameter(tX_seqpar :: get_sp_by_persistence_id(xpar_id));
1768         }
1769         else set_x_input_parameter(NULL);
1770         
1771         if (ypar_id) {
1772                 set_y_input_parameter(tX_seqpar :: get_sp_by_persistence_id(ypar_id));
1773         }
1774         else set_y_input_parameter(NULL);
1775                 
1776         return 0;
1777 }
1778
1779
1780 int vtt_class :: load_all(xmlDocPtr doc, char *fname) {
1781         xmlNodePtr root=xmlDocGetRootElement(doc);
1782         int elementFound=0;
1783         char fn_buff[4096];
1784         double dvalue;
1785         int res=0;
1786         int restmp=0;
1787         char *pid_attr;
1788         int pid;
1789
1790         
1791         if (!root) {
1792                 tX_error("no root element? What kind of XML document is this?");
1793                 return 1;
1794         }
1795         
1796         if (xmlStrcmp(root->name, (const xmlChar *) "terminatorXset")) {
1797                 tX_error("this is not a terminatorXset file.")
1798                 return 2;
1799         }
1800         
1801         if (xmlGetProp(root,(xmlChar *) "version")==NULL) {
1802                 tX_error("the set file lacks a version attribute.");
1803                 return 3;
1804         }
1805         
1806         if (xmlStrcmp(xmlGetProp(root, (xmlChar *) "version"), (xmlChar *) TX_XML_SETFILE_VERSION)) {
1807                 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);
1808         }
1809         
1810         /* delete current tables... */
1811         while (main_list.size()) {
1812                 delete((*main_list.begin()));
1813         }
1814
1815         int table_ctr=0;
1816         
1817         /* counting turntables.. */
1818         for (xmlNodePtr cur=root->xmlChildrenNode; cur != NULL; cur = cur->next) {
1819                 if (cur->type == XML_ELEMENT_NODE) {    
1820                         if (xmlStrcmp(cur->name, (xmlChar *) "turntable")==0) {
1821                                 table_ctr++;
1822                         }
1823                 }
1824         }
1825
1826         tX_debug("Found %i turntables in set.",  table_ctr);
1827
1828         ld_create_loaddlg(TX_LOADDLG_MODE_MULTI, table_ctr);
1829         ld_set_setname(fname);
1830
1831         /* parsing all */
1832         for (xmlNodePtr cur=root->xmlChildrenNode; cur != NULL; cur = cur->next) {
1833                 if (cur->type == XML_ELEMENT_NODE) {                    
1834                         elementFound=0;
1835                 
1836                         restore_float_id("master_volume", master_volume, sp_master_volume, set_master_volume(master_volume));
1837                         restore_float_id("master_pitch", globals.pitch, sp_master_pitch, set_master_pitch(globals.pitch));
1838                         
1839                         if ((!elementFound) && (xmlStrcmp(cur->name, (xmlChar *) "turntable")==0)) {
1840                                 elementFound=1;
1841                                 vtt_class *vtt=new vtt_class(1);
1842                                 vtt->load(doc, cur);
1843                                 
1844                                 tX_debug("loading a turntable..");
1845
1846                                 if (strlen(vtt->filename)) {
1847                                         strcpy(fn_buff, vtt->filename);
1848                                         ld_set_filename(fn_buff);
1849                                 
1850                                         restmp=(int) vtt->load_file(fn_buff);
1851                                         res+=restmp;
1852                                 }
1853         
1854                                 gtk_box_pack_start(GTK_BOX(control_parent), vtt->gui.control_box, TRUE, TRUE, 0);
1855                                 gtk_box_pack_start(GTK_BOX(audio_parent), vtt->gui.audio_box, TRUE, TRUE, 0);
1856                                 if (vtt->audio_hidden) vtt->hide_audio(vtt->audio_hidden);
1857                                 if (vtt->control_hidden) vtt->hide_control(vtt->control_hidden);\r
1858                         }
1859                         if ((!elementFound) && (xmlStrcmp(cur->name, (xmlChar *) "sequencer")==0)) {
1860                                 elementFound=1;
1861                                 sequencer.load(doc, cur);
1862                         }
1863                         if (!elementFound) {
1864                                 tX_warning("unhandled element %s in setfile %s", cur->name, fname);
1865                         }
1866                 }
1867         }
1868         
1869         ld_destroy();
1870         
1871         return(res);
1872 }
1873
1874 void add_vtt(GtkWidget *ctrl, GtkWidget *audio, char *fn)
1875 {
1876         vtt_class *hmmpg;
1877         hmmpg = new vtt_class(1);
1878         gtk_box_pack_start(GTK_BOX(ctrl), hmmpg->gui.control_box, TRUE, TRUE, 0);
1879         gtk_box_pack_start(GTK_BOX(audio), hmmpg->gui.audio_box, TRUE, TRUE, 0);
1880         if (fn) hmmpg->load_file(fn);
1881 }
1882
1883 extern void vg_move_fx_panel_up(GtkWidget *wid, vtt_class *vtt);
1884 extern void vg_move_fx_panel_down(GtkWidget *wid, vtt_class *vtt);
1885
1886 //#define debug_fx_stack(); for (i=fx_list.begin(); i != fx_list.end(); i++) puts((*i)->get_info_string());
1887 #define debug_fx_stack();
1888
1889 void vtt_class :: effect_up(vtt_fx *effect)
1890 {
1891         list <vtt_fx *> :: iterator i;
1892         list <vtt_fx *> :: iterator previous;
1893         int ok=0;
1894         
1895         debug_fx_stack();
1896         
1897         if ((*fx_list.begin())==effect) return;
1898         
1899         for (previous=i=fx_list.begin(); i != fx_list.end(); i++)
1900         {
1901                 if ((*i) == effect)
1902                 {
1903                         ok=1;
1904                         break;
1905                 }
1906                 previous=i;
1907         }
1908         
1909         if (ok)
1910         {       
1911                 pthread_mutex_lock(&render_lock);
1912                 fx_list.remove(effect);
1913                 fx_list.insert(previous, effect);
1914                 pthread_mutex_unlock(&render_lock);
1915
1916                 vg_move_fx_panel_up(effect->get_panel_widget(), this);
1917         }
1918         
1919         debug_fx_stack();
1920 }
1921
1922 void vtt_class :: effect_down(vtt_fx *effect)
1923 {
1924         list <vtt_fx *> :: iterator i;
1925         int ok=0;
1926
1927         debug_fx_stack();
1928                 
1929         for (i=fx_list.begin(); i != fx_list.end(); i++)
1930         {
1931                 if ((*i) == effect)
1932                 {
1933                         ok=1;
1934                         break;
1935                 }
1936         }
1937         
1938         if ((ok) && (i!=fx_list.end()))
1939         {
1940                 i++;
1941                 if (i==fx_list.end()) return;
1942                 i++;
1943
1944                 pthread_mutex_lock(&render_lock);
1945                 fx_list.remove(effect);
1946                 
1947                 fx_list.insert(i, effect);
1948                 vg_move_fx_panel_down(effect->get_panel_widget(), this);
1949                 pthread_mutex_unlock(&render_lock);
1950         }
1951         
1952 debug_fx_stack();       
1953 }
1954
1955 void vtt_class ::  effect_remove(vtt_fx_ladspa *effect)
1956 {
1957         pthread_mutex_lock(&render_lock);
1958         fx_list.remove(effect);
1959         pthread_mutex_unlock(&render_lock);
1960         
1961         delete effect;
1962 }
1963
1964 extern void gui_hide_control_panel(vtt_class *vtt, bool hide);
1965 extern void gui_hide_audio_panel(vtt_class *vtt, bool hide);
1966
1967 void vtt_class :: hide_audio(bool hide) {
1968         audio_hidden=hide;
1969         gui_hide_audio_panel(this, hide);
1970 }
1971
1972 void vtt_class :: hide_control(bool hide) {
1973         control_hidden=hide;
1974         gui_hide_control_panel(this, hide);     
1975 }