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