f9e651a4761f90c6db98f17dc813fdc04ab5d846
[terminatorX.git] / src / tX_seqpar.cc
1 /*
2     terminatorX - realtime audio scratching software
3     Copyright (C) 1999, 2000 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_seqpar.cc
20  
21     Description: This implements the "sequenceable parameters".
22 */    
23
24 #include "tX_seqpar.h"
25 #include "tX_vtt.h"
26 #include <stdio.h>
27 #include "tX_mastergui.h"
28 #include "tX_global.h"
29 #include "tX_sequencer.h"
30 #include "tX_extdial.h"
31 #include <malloc.h>
32
33 #define TX_SEQPAR_DEFAULT_SCALE 0.05
34
35 list <tX_seqpar *> tX_seqpar :: all;
36 list <tX_seqpar *> tX_seqpar :: update;
37 pthread_mutex_t tX_seqpar :: update_lock = PTHREAD_MUTEX_INITIALIZER;
38
39 #define tt ((vtt_class *) vtt)
40
41 void tX_seqpar :: default_constructor()
42 {
43         touched=0;
44         gui_active=1;
45         vtt=NULL;
46         max_value=0;
47         min_value=0;
48         scale_value=0;
49         is_mappable=1;
50         all.push_back(this);
51         last_event_recorded=NULL;
52 }
53
54 tX_seqpar :: tX_seqpar ()
55 {
56         default_constructor();
57 }
58
59 /*
60 tX_seqpar :: tX_seqpar (void * mytt)
61 {
62         default_constructor();
63         vtt=mytt;
64 }
65
66 tX_seqpar :: tX_seqpar (float max, float min, float scale, int mappable)
67 {
68         default_constructor();
69         max_value=max;
70         min_value=min;
71         scale_value=scale;
72         is_mappable=mappable;
73 }*/
74
75 void tX_seqpar :: set_mapping_parameters(float max, float min, float scale, int mappable)
76 {
77         max_value=max;
78         min_value=min;
79         scale_value=scale;
80         is_mappable=mappable;
81 }
82
83 /*
84 tX_seqpar :: tX_seqpar (void *mytt, float max, float min, float scale, int mappable)
85 {
86         default_constructor();
87         vtt=mytt;
88         max_value=max;
89         min_value=min;
90         scale_value=scale;
91         is_mappable=mappable;   
92 }
93 */
94
95 void tX_seqpar :: handle_mouse_input(float adjustment)
96 {
97         float tmpvalue;
98         
99         tmpvalue=get_value()+adjustment*scale_value;
100         if (tmpvalue>max_value) tmpvalue=max_value;
101         if (tmpvalue<min_value) tmpvalue=min_value;
102         
103         /*printf("Handling %s, max %f, min %f, scale %f,  val: %f\n", get_name(), max_value, min_value, scale_value, tmpvalue);*/
104         
105         receive_input_value(tmpvalue);
106 }
107
108 void tX_seqpar :: set_vtt (void *mytt)
109 {
110         vtt=mytt;
111 }
112
113 tX_seqpar :: ~tX_seqpar()
114 {
115         pthread_mutex_lock(&update_lock);
116         update.remove(this);
117         pthread_mutex_unlock(&update_lock);
118         sequencer.delete_all_events_for_sp(this);
119         all.remove(this);
120 }
121
122 void tX_seqpar :: do_touch()
123 {
124         if (sequencer.is_recording())
125         {
126                 touched=1;
127                 touch_timestamp=sequencer.get_timestamp();
128         }
129 }
130
131 void tX_seqpar :: untouch_all()
132 {
133         list <tX_seqpar *> :: iterator sp;
134         
135         for (sp=all.begin(); sp!=all.end(); sp++)
136         {
137                 (*sp)->untouch();
138         }
139 }
140
141 void tX_seqpar :: create_persistence_ids()
142 {
143         list <tX_seqpar *> :: iterator sp;
144         int pid=0;
145         
146         for (sp=all.begin(); sp!=all.end(); sp++)
147         {
148                 pid++;
149                 (*sp)->set_persistence_id(pid);
150         }
151 }
152
153 tX_seqpar* tX_seqpar :: get_sp_by_persistence_id(int pid)
154 {
155         list <tX_seqpar *> :: iterator sp;
156         
157         for (sp=all.begin(); sp!=all.end(); sp++)
158         {
159                 if ((*sp)->get_persistence_id()==pid) return ((*sp));
160         }
161         
162         fprintf (stderr, "oops: failed to lookup persistence id [%i].\n", pid); 
163         return (NULL);
164 }
165
166
167 void tX_seqpar :: record_value(const float value)
168 {
169 #define last_event ((tX_event *) last_event_recorded)
170
171         /* recording more than one event per seqpar for
172           one timestamp doesn't make sense... so if the 
173           last_event_recorded was for the current timestamp
174           we simply set that event's value to the current one.
175         */
176         if ((last_event) && (last_event->get_timestamp() == sequencer.get_timestamp()))
177         {
178                 last_event->set_value(value);
179         }
180         else last_event_recorded=(void *) sequencer.record(this, value);
181 }
182
183 void tX_seqpar :: receive_gui_value(const float value)
184 {
185         if (gui_active)
186         {
187                 touch();
188                 do_exec(value);
189                 record_value(value);
190         }
191 }
192
193 void tX_seqpar :: receive_input_value(const float value)
194 {
195         touch();
196         exec_value(value);
197         record_value(value);
198 }
199
200 void tX_seqpar :: receive_forward_value(const float value)
201 {
202         fwd_value=value;
203 }
204
205 void tX_seqpar :: materialize_forward_values()
206 {
207         list <tX_seqpar *> :: iterator sp;
208         
209         for (sp=all.begin(); sp!=all.end(); sp++)
210         {
211                 (*sp)->exec_value((*sp)->fwd_value);
212         }       
213         gdk_flush();
214 }
215
216 char * tX_seqpar :: get_vtt_name()
217 {       
218         if (vtt) return tt->name;
219         else return "Master Track";
220 }
221
222 const char * tX_seqpar :: get_name()
223 {
224         return "This string means trouble!";
225 }
226
227 float tX_seqpar :: get_value()
228 {
229         printf("Ooops. tX_seqpar::get_value() called. Trouble.");
230         return 0.0;     
231 }
232
233 void tX_seqpar :: do_exec(const float value)
234 {
235         fprintf(stderr, "oops: called do_exec() of tX_seqpar.\n");
236 }
237
238 void tX_seqpar :: exec_value(const float value)
239 {
240         fprintf(stderr, "oops: called exec_value() of tX_seqpar.\n");
241 }
242
243 void tX_seqpar :: do_update_graphics()
244 {
245         fprintf(stderr, "oops: called do_update_graphics() of tX_seqpar.\n");
246 }
247
248 void tX_seqpar :: update_graphics()
249 {
250         gui_active=0;
251         do_update_graphics();
252         while (gtk_events_pending()) gtk_main_iteration();      /* gtk_flush */
253         gui_active=1;
254 }
255
256 void tX_seqpar :: update_all_graphics()
257 {
258         list <tX_seqpar *> :: iterator sp;
259
260         pthread_mutex_lock(&update_lock);
261
262         if (!update.size())
263         {
264                 pthread_mutex_unlock(&update_lock);
265                 return; 
266         }
267         
268         while (gtk_events_pending()) gtk_main_iteration();      
269         for (sp=update.begin(); sp!=update.end(); sp++)
270         {
271                 (*sp)->update_graphics();
272         }
273         update.erase(update.begin(), update.end());
274         pthread_mutex_unlock(&update_lock);
275 }
276
277 void tX_seqpar :: init_all_graphics()
278 {
279         list <tX_seqpar *> :: iterator sp;
280
281         pthread_mutex_lock(&update_lock);
282         
283         for (sp=all.begin(); sp!=all.end(); sp++)
284         {
285                 (*sp)->update_graphics();
286         }
287         while (gtk_events_pending()) gtk_main_iteration();      
288
289         pthread_mutex_unlock(&update_lock);
290 }
291
292 void tX_seqpar_update :: exec_value(const float value)
293 {
294         do_exec(value);
295         pthread_mutex_lock(&update_lock);
296         update.push_front(this);
297         pthread_mutex_unlock(&update_lock);
298 }
299
300 void tX_seqpar_no_update :: exec_value(const float value)
301 {
302         do_exec(value);
303 }
304
305 void tX_seqpar_no_update :: do_update_graphics()
306 {
307         /* NOP */
308 }
309
310
311 void tX_seqpar_no_update_active_forward :: receive_forward_value(const float value)
312 {
313         fwd_value=value;
314         do_exec(value);
315 }       
316
317 void tX_seqpar_update_active_forward :: receive_forward_value(const float value)
318 {
319         fwd_value=value;
320         do_exec(value);
321 }
322
323 /* "real" classes */
324
325 /**** Sequencable Parameter: MASTER VOLUME ****/
326
327 tX_seqpar_master_volume :: tX_seqpar_master_volume()
328 {
329         set_mapping_parameters(2.5, 0, 0.1, 0);
330 }
331
332 void tX_seqpar_master_volume :: do_exec(const float value)
333 {
334         vtt_class :: set_master_volume(value);
335 }
336
337 void tX_seqpar_master_volume :: do_update_graphics ()
338 {
339         gtk_adjustment_set_value(volume_adj, vtt_class::master_volume);
340 }
341
342 const char * tX_seqpar_master_volume :: get_name()
343 {
344         return "Master Volume";
345 }
346
347 /**** Sequencable Parameter: MASTER PITCH ****/
348
349 tX_seqpar_master_pitch :: tX_seqpar_master_pitch()
350 {
351         set_mapping_parameters(3.0, -3.0, 0.1, 0);
352 }
353
354 void tX_seqpar_master_pitch :: do_exec(const float value)
355 {
356         vtt_class :: set_master_pitch(value);
357 }
358
359 void tX_seqpar_master_pitch :: do_update_graphics ()
360 {
361         gtk_adjustment_set_value(pitch_adj, globals.pitch);
362 }
363
364 const char * tX_seqpar_master_pitch :: get_name()
365 {
366         return "Master Pitch";
367 }
368
369 /**** Sequencable Parameter: TURNTABLE SPEED ****/
370
371 tX_seqpar_vtt_speed :: tX_seqpar_vtt_speed()
372 {
373         // min max scale are not required for this parameter
374         set_mapping_parameters(3.0, -3.0, 0.1, 1);
375 }
376
377 /* speed works differently so we need an extra input-handler */
378
379 void tX_seqpar_vtt_speed :: handle_mouse_input(float adjustment)
380 {
381         if (tt->do_scratch) tt->sp_speed.receive_input_value(adjustment);
382         tt->sense_cycles=globals.sense_cycles;
383 }
384
385 void tX_seqpar_vtt_speed :: do_exec(const float value)
386 {
387         tt->speed=value;
388 }
389
390 const char * tX_seqpar_vtt_speed :: get_name()
391 {
392         return "Speed (Scratching)";
393 }
394
395 /**** Sequencable Parameter: TURNTABLE SPIN ****/
396
397 tX_seqpar_spin :: tX_seqpar_spin()
398 {
399         set_mapping_parameters(1, 0, 0, 0);
400 }
401
402 void tX_seqpar_spin :: do_exec(const float value)
403 {
404         if (value > 0) tt->speed=tt->res_pitch;
405         else tt->speed=0;
406 }
407
408 const char * tX_seqpar_spin :: get_name()
409 {
410         return "Motor Spin (On/Off)";
411 }
412
413 /**** Sequencable Parameter: TURNTABLE VOLUME ****/
414
415 tX_seqpar_vtt_volume :: tX_seqpar_vtt_volume()
416 {
417         set_mapping_parameters(2.0, 0, TX_SEQPAR_DEFAULT_SCALE, 1);
418 }
419
420 float tX_seqpar_vtt_volume :: get_value(){ return tt->rel_volume; }
421
422 void tX_seqpar_vtt_volume :: do_exec(const float value)
423 {
424         tt->set_volume(value);
425 }
426
427 void tX_seqpar_vtt_volume :: do_update_graphics ()
428 {
429         gtk_adjustment_set_value(tt->gui.volume, 2.0-tt->rel_volume);
430 }
431
432 const char * tX_seqpar_vtt_volume :: get_name()
433 {
434         return "Volume";
435 }
436
437 /**** Sequencable Parameter : Pan ****/
438
439 tX_seqpar_vtt_pan :: tX_seqpar_vtt_pan()
440 {
441         set_mapping_parameters(1.0, -1.0, TX_SEQPAR_DEFAULT_SCALE, 1);
442 }
443
444 float tX_seqpar_vtt_pan :: get_value(){ return tt->pan; }
445
446 void tX_seqpar_vtt_pan :: do_exec(const float value)
447 {
448         tt->set_pan(value);
449 }
450
451 void tX_seqpar_vtt_pan :: do_update_graphics ()
452 {
453         gtk_adjustment_set_value(tt->gui.pan, tt->pan);
454 }
455
456 const char * tX_seqpar_vtt_pan :: get_name()
457 {
458         return "Pan";
459 }
460
461 /**** Sequencable Parameter: TURNTABLE PITCH ****/
462
463 tX_seqpar_vtt_pitch :: tX_seqpar_vtt_pitch()
464 {
465         set_mapping_parameters(3.0, -3.0, TX_SEQPAR_DEFAULT_SCALE, 1);
466 }
467
468 float tX_seqpar_vtt_pitch :: get_value(){ return tt->rel_pitch; }
469
470 void tX_seqpar_vtt_pitch :: do_exec(const float value)
471 {
472         tt->set_pitch(value);
473 }
474
475 void tX_seqpar_vtt_pitch :: do_update_graphics ()
476 {
477         gtk_adjustment_set_value(tt->gui.pitch, tt->rel_pitch);
478 }
479
480 const char * tX_seqpar_vtt_pitch :: get_name()
481 {
482         return "Pitch";
483 }
484
485 /**** Sequencable Parameter: TURNTABLE TRIGGER ****/
486
487 tX_seqpar_vtt_trigger :: tX_seqpar_vtt_trigger()
488 {
489         set_mapping_parameters(0, 0, 0, 0);
490 }
491
492 void tX_seqpar_vtt_trigger :: do_exec(const float value)
493 {
494         if (value > 0) tt->trigger();
495         else tt->stop();
496 }
497
498 const char * tX_seqpar_vtt_trigger :: get_name()
499 {
500         return "Trigger (Start/Stop)";
501 }
502
503 /**** Sequencable Parameter: TURNTABLE LOOP ****/
504
505 tX_seqpar_vtt_loop :: tX_seqpar_vtt_loop()
506 {
507         set_mapping_parameters(0, 0, 0, 0);
508 }
509
510 void tX_seqpar_vtt_loop :: do_exec(const float value)
511 {
512         tt->set_loop(value>0);
513 }
514
515 const char * tX_seqpar_vtt_loop :: get_name()
516 {
517         return "Loop (On/Off)";
518 }
519
520 void tX_seqpar_vtt_loop :: do_update_graphics ()
521 {
522         gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(tt->gui.loop), tt->loop);
523 }
524
525 /**** Sequencable Parameter: TURNTABLE SYNC CLIENT ****/
526
527 tX_seqpar_vtt_sync_client :: tX_seqpar_vtt_sync_client()
528 {
529         set_mapping_parameters(0,0,0,0);
530 }
531
532 void tX_seqpar_vtt_sync_client :: do_exec(const float value)
533 {
534         tt->set_sync_client((value>0), tt->sync_cycles);
535 }
536
537 void tX_seqpar_vtt_sync_client :: do_update_graphics ()
538 {
539         gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(tt->gui.sync_client), tt->is_sync_client);
540 }
541
542 const char * tX_seqpar_vtt_sync_client :: get_name()
543 {
544         return "Sync Client (On/Off)";
545 }
546
547 /**** Sequencable Parameter: TURNTABLE SYNC CYCLES ****/
548
549 tX_seqpar_vtt_sync_cycles :: tX_seqpar_vtt_sync_cycles()
550 {
551         set_mapping_parameters(0,0,0,0);
552 }
553
554 void tX_seqpar_vtt_sync_cycles :: do_exec(const float value)
555 {
556         tt->set_sync_client(tt->is_sync_client, (int) value);
557 }
558
559 void tX_seqpar_vtt_sync_cycles :: do_update_graphics ()
560 {
561         gtk_adjustment_set_value(tt->gui.cycles, tt->sync_cycles);
562 }
563
564 const char * tX_seqpar_vtt_sync_cycles :: get_name()
565 {
566         return "Sync Cycles";
567 }
568
569 /**** Sequencable Parameter: TURNTABLE LP ENABLE ****/
570
571 tX_seqpar_vtt_lp_enable :: tX_seqpar_vtt_lp_enable()
572 {
573         set_mapping_parameters(0,0,0,0);
574 }
575
576 void tX_seqpar_vtt_lp_enable :: do_exec(const float value)
577 {
578         tt->lp_set_enable(value>0);
579 }
580
581 void tX_seqpar_vtt_lp_enable :: do_update_graphics ()
582 {
583         gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(tt->gui.lp_enable), tt->lp_enable);
584 }
585
586 const char * tX_seqpar_vtt_lp_enable :: get_name()
587 {
588         return "Lowpass: Enable (On/Off)";
589 }
590
591 /**** Sequencable Parameter: TURNTABLE LP GAIN ****/
592
593 tX_seqpar_vtt_lp_gain :: tX_seqpar_vtt_lp_gain()
594 {
595         set_mapping_parameters(2.0,0, TX_SEQPAR_DEFAULT_SCALE, 1);
596 }
597
598 float tX_seqpar_vtt_lp_gain :: get_value() { return tt->lp_gain; }
599
600 void tX_seqpar_vtt_lp_gain :: do_exec(const float value)
601 {
602         tt->lp_set_gain(value);
603 }
604
605 const char * tX_seqpar_vtt_lp_gain :: get_name()
606 {
607         return "Lowpass: Input Gain";
608 }
609
610 void tX_seqpar_vtt_lp_gain :: do_update_graphics ()
611 {
612         gtk_adjustment_set_value(tt->gui.lp_gain, tt->lp_gain);
613 }
614
615 /**** Sequencable Parameter: TURNTABLE LP RESO ****/
616
617 tX_seqpar_vtt_lp_reso :: tX_seqpar_vtt_lp_reso()
618 {
619         set_mapping_parameters(0.99, 0, TX_SEQPAR_DEFAULT_SCALE, 1);
620 }
621
622 float tX_seqpar_vtt_lp_reso :: get_value() { return tt->lp_reso; }
623
624 void tX_seqpar_vtt_lp_reso :: do_exec(const float value)
625 {
626         tt->lp_set_reso(value);
627 }
628
629 void tX_seqpar_vtt_lp_reso :: do_update_graphics ()
630 {
631         gtk_adjustment_set_value(tt->gui.lp_reso, tt->lp_reso);
632 }
633
634 const char * tX_seqpar_vtt_lp_reso :: get_name()
635 {
636         return "Lowpass: Resonance";
637 }
638
639 /**** Sequencable Parameter: TURNTABLE LP FREQUENCY ****/
640
641 tX_seqpar_vtt_lp_freq :: tX_seqpar_vtt_lp_freq()
642 {
643         set_mapping_parameters(1.0, 0, TX_SEQPAR_DEFAULT_SCALE, 1);
644 }
645
646 float tX_seqpar_vtt_lp_freq :: get_value() { return tt->lp_freq; }
647
648 void tX_seqpar_vtt_lp_freq :: do_exec(const float value)
649 {
650         tt->lp_set_freq(value);
651 }
652
653 const char * tX_seqpar_vtt_lp_freq :: get_name()
654 {
655         return "Lowpass: Cutoff Frequency";
656 }
657
658 void tX_seqpar_vtt_lp_freq :: do_update_graphics ()
659 {
660         gtk_adjustment_set_value(tt->gui.lp_freq, tt->lp_freq);
661 }
662
663 /**** Sequencable Parameter: TURNTABLE ECHO ENABLE ****/
664
665 tX_seqpar_vtt_ec_enable :: tX_seqpar_vtt_ec_enable()
666 {
667         set_mapping_parameters(1.0, 0, 0, 0);
668 }
669
670 void tX_seqpar_vtt_ec_enable :: do_exec(const float value)
671 {
672         tt->ec_set_enable(value>0);
673 }
674
675 void tX_seqpar_vtt_ec_enable :: do_update_graphics ()
676 {
677         gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(tt->gui.ec_enable), tt->ec_enable);
678 }
679
680 const char * tX_seqpar_vtt_ec_enable :: get_name()
681 {
682         return "Echo: Enable (On/Off)";
683 }
684
685 /**** Sequencable Parameter: TURNTABLE ECHO LENGTH ****/
686
687 tX_seqpar_vtt_ec_length :: tX_seqpar_vtt_ec_length()
688 {
689         set_mapping_parameters(1.0, 0, TX_SEQPAR_DEFAULT_SCALE, 1);
690 }
691
692 float tX_seqpar_vtt_ec_length :: get_value() { return tt->ec_length; }
693
694 void tX_seqpar_vtt_ec_length :: do_exec(const float value)
695 {
696         tt->ec_set_length(value);
697 }
698
699 void tX_seqpar_vtt_ec_length :: do_update_graphics ()
700 {
701         gtk_adjustment_set_value(tt->gui.ec_length, tt->ec_length);
702 }
703
704 const char * tX_seqpar_vtt_ec_length :: get_name()
705 {
706         return "Echo: Duration";
707 }
708
709 /**** Sequencable Parameter: TURNTABLE ECHO FEEDBACK ****/
710
711 tX_seqpar_vtt_ec_feedback :: tX_seqpar_vtt_ec_feedback()
712 {
713         set_mapping_parameters(1.0, 0, TX_SEQPAR_DEFAULT_SCALE, 1);
714 }
715
716 float tX_seqpar_vtt_ec_feedback :: get_value() { return tt->ec_feedback; }
717
718 void tX_seqpar_vtt_ec_feedback :: do_exec(const float value)
719 {
720         tt->ec_set_feedback(value);
721 }
722
723 void tX_seqpar_vtt_ec_feedback :: do_update_graphics ()
724 {
725         gtk_adjustment_set_value(tt->gui.ec_feedback, tt->ec_feedback);
726 }
727
728 const char * tX_seqpar_vtt_ec_feedback :: get_name()
729 {
730         return "Echo: Feedback";
731 }
732
733 /**** Sequencable Parameter: TURNTABLE ECHO PAN ****/
734
735 tX_seqpar_vtt_ec_pan :: tX_seqpar_vtt_ec_pan()
736 {
737         set_mapping_parameters(1.0, -1.0, TX_SEQPAR_DEFAULT_SCALE, 1);
738 }
739
740 float tX_seqpar_vtt_ec_pan :: get_value() { return tt->ec_pan; }
741
742 void tX_seqpar_vtt_ec_pan :: do_exec(const float value)
743 {
744         tt->ec_set_pan(value);
745 }
746
747 void tX_seqpar_vtt_ec_pan :: do_update_graphics ()
748 {
749         gtk_adjustment_set_value(tt->gui.ec_pan, tt->ec_pan);
750 }
751
752 const char * tX_seqpar_vtt_ec_pan :: get_name()
753 {
754         return "Echo: Pan";
755 }
756
757 /**** Sequencable Parameter: TURNTABLE ECHO VOLUME ****/
758
759 tX_seqpar_vtt_ec_volume :: tX_seqpar_vtt_ec_volume()
760 {
761         set_mapping_parameters(0.0, 3.0, TX_SEQPAR_DEFAULT_SCALE, 1);
762 }
763
764 float tX_seqpar_vtt_ec_volume :: get_value() { return tt->ec_volume; }
765
766 void tX_seqpar_vtt_ec_volume :: do_exec(const float value)
767 {
768         tt->ec_set_volume(value);
769 }
770
771 void tX_seqpar_vtt_ec_volume :: do_update_graphics ()
772 {
773         gtk_adjustment_set_value(tt->gui.ec_volume, tt->ec_volume);
774 }
775
776 const char * tX_seqpar_vtt_ec_volume :: get_name()
777 {
778         return "Echo: Volume";
779 }
780
781
782 /**** Sequencable Parameter: TURNTABLE MUTE ****/
783
784 tX_seqpar_vtt_mute :: tX_seqpar_vtt_mute()
785 {
786         set_mapping_parameters(0,0,0,0);
787 }
788
789 void tX_seqpar_vtt_mute :: do_exec(const float value)
790 {
791         tt->set_mute(value>0);
792 }
793
794 const char * tX_seqpar_vtt_mute :: get_name()
795 {
796         return "Mute (On/Off)";
797 }
798
799 /** LADSPA fx parameters **/
800
801 tX_seqpar_vttfx :: tX_seqpar_vttfx()
802 {
803         fx_value=(float *) malloc(sizeof(float));
804         *fx_value=0;
805         set_mapping_parameters(0,0,0,0);        
806 }
807
808 tX_seqpar_vttfx :: ~tX_seqpar_vttfx()
809 {
810         free(fx_value);
811 }
812
813 void tX_seqpar_vttfx :: set_name(const char *n, const char *sn)
814 {
815         strcpy(name, n);
816         strcpy(label_name, sn);
817         create_widget();
818 }
819
820 float tX_seqpar_vttfx :: get_value()
821 {
822         return *fx_value;
823 }
824
825 void tX_seqpar_vttfx :: create_widget()
826 {
827         fprintf(stderr, "tX: Ooops. create_widget() for tX_seqpar_vttfx.\n");
828 }
829
830 const char * tX_seqpar_vttfx :: get_name()
831 {
832         return name;    
833 }
834
835 void tX_seqpar_vttfx_float :: create_widget()
836 {
837         float tmp=max_value - min_value/1000;
838
839         *fx_value=min_value;
840         myadj=GTK_ADJUSTMENT(gtk_adjustment_new(*fx_value, min_value, max_value, tmp, tmp, tmp));
841         mydial=new tX_extdial(label_name, myadj);
842         gtk_signal_connect(GTK_OBJECT(myadj), "value_changed", (GtkSignalFunc) tX_seqpar_vttfx_float :: gtk_callback, this);
843         widget = mydial->get_widget();  
844 }
845
846 tX_seqpar_vttfx_float :: ~tX_seqpar_vttfx_float()
847 {
848         delete mydial;  
849 }
850
851 void tX_seqpar_vttfx_float :: do_exec(const float value)
852 {
853         *fx_value=value;
854 }
855
856 void tX_seqpar_vttfx_float :: do_update_graphics()
857 {
858         gtk_adjustment_set_value(myadj, *fx_value);
859 }
860
861 GtkSignalFunc tX_seqpar_vttfx_float :: gtk_callback(GtkWidget* w, tX_seqpar_vttfx_float *sp)
862 {
863         sp->receive_gui_value(sp->myadj->value);        
864         return NULL;    
865 }
866
867 #define WID_DYN TRUE, TRUE, 0
868 #define WID_FIX FALSE, FALSE, 0
869
870 void tX_seqpar_vttfx_int :: create_widget()
871 {
872         float tmp=max_value - min_value/1000;
873         GtkWidget *tmpwid;
874
875         *fx_value=min_value;
876         myadj=GTK_ADJUSTMENT(gtk_adjustment_new(*fx_value, min_value, max_value, tmp, tmp, tmp));
877         widget=gtk_hbox_new(FALSE, 2);
878         tmpwid=gtk_label_new(label_name);
879         gtk_widget_show(tmpwid);
880         gtk_box_pack_start(GTK_BOX(widget), tmpwid, WID_FIX);
881
882         tmpwid=gtk_spin_button_new(myadj,1.0,0);
883         gtk_widget_show(tmpwid);
884         gtk_box_pack_start(GTK_BOX(widget), tmpwid, WID_DYN);
885         
886         gtk_signal_connect(GTK_OBJECT(myadj), "value_changed", (GtkSignalFunc) tX_seqpar_vttfx_int :: gtk_callback, this);
887 }
888
889 tX_seqpar_vttfx_int :: ~tX_seqpar_vttfx_int()
890 {
891         gtk_widget_destroy(widget);
892 }
893
894 void tX_seqpar_vttfx_int :: do_exec(const float value)
895 {
896         *fx_value=value;
897 }
898
899 void tX_seqpar_vttfx_int :: do_update_graphics()
900 {
901         gtk_adjustment_set_value(myadj, *fx_value);
902 }
903
904 GtkSignalFunc tX_seqpar_vttfx_int :: gtk_callback(GtkWidget* w, tX_seqpar_vttfx_int *sp)
905 {
906         sp->receive_gui_value(sp->myadj->value);        
907         return NULL;
908 }
909
910 void tX_seqpar_vttfx_bool :: create_widget()
911 {
912         *fx_value=min_value;
913         widget=gtk_check_button_new_with_label(label_name);
914         gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), 0);
915         gtk_signal_connect(GTK_OBJECT(widget), "clicked", (GtkSignalFunc) tX_seqpar_vttfx_bool :: gtk_callback, this);
916 }
917
918 tX_seqpar_vttfx_bool :: ~tX_seqpar_vttfx_bool()
919 {
920         gtk_widget_destroy(widget);
921 }
922
923 void tX_seqpar_vttfx_bool :: do_exec(const float value)
924 {
925         *fx_value=value;
926 }
927
928 GtkSignalFunc tX_seqpar_vttfx_bool :: gtk_callback(GtkWidget* w, tX_seqpar_vttfx_bool *sp)
929 {
930         sp->receive_gui_value(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(sp->widget)));     
931         return NULL;
932 }
933
934 void tX_seqpar_vttfx_bool :: do_update_graphics()
935 {
936         gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), *fx_value==max_value);
937 }