b0a0eab40986fd482d1836db3a7006f1de9e1c0c
[terminatorX.git] / src / tX_vttgui.cc
1 /*
2     terminatorX - realtime audio scratching software
3     Copyright (C) 1999-2003  Alexander K├Ânig
4  
5     This program is free software; you can redistribute it and/or modify
6     it under the terms of the GNU General Public License as published by
7     the Free Software Foundation; either version 2 of the License, or
8     (at your option) any later version.
9  
10     This program is distributed in the hope that it will be useful,
11     but WITHOUT ANY WARRANTY; without even the implied warranty of
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13     GNU General Public License for more details.
14  
15     You should have received a copy of the GNU General Public License
16     along with this program; if not, write to the Free Software
17     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18  
19     File: tX_vttgui.cc
20  
21     Description: This implements the gtk+ GUI for the virtual turntable
22                  class implemented in tX_vtt.cc. This code is not in tX_vtt.cc
23                  for mainly to keep the GUI code divided from the audio-rendering
24                  code and as gtk+ callback to C++ method call wrapper.
25                  
26     Changes:
27     
28     before 11-26-2001: too many changes.
29     
30     11-26-2001: applied Adrian's solo/mute patch - Alex
31     
32     11-27-2001: modified solo/mute to use the set_mix_mute/solo function
33                 of the vtts. The previous approach messed up the sequencer
34                 and more. Removed some old unnecessary code, too.
35 */    
36
37 #include <gdk/gdk.h>
38 #include <gtk/gtk.h>
39 #include "tX_vttgui.h"
40 #include "tX_vtt.h"
41 #include "tX_widget.h"
42 #include "tX_mastergui.h"
43 #include "tX_loaddlg.h"
44 #include "tX_prelis.h"
45 #include "tX_pbutton.h"
46 #include "tX_global.h"
47 #include "tX_extdial.h"
48 #include "tX_panel.h"
49 #include "tX_ladspa.h"
50 #include "tX_ladspa_class.h"
51 #include "tX_engine.h"
52 #include "tX_glade_interface.h"
53 #include "tX_glade_support.h"
54 #include "tX_dialog.h"
55
56 #ifdef USE_DIAL
57 #include "tX_dial.h"
58 #endif
59
60 #include "tX_flash.h"
61 #include <stdio.h>
62
63 #define WID_DYN TRUE, TRUE, 0
64 #define WID_FIX FALSE, FALSE, 0
65
66 void nicer_filename(char *dest, char *source)
67 {
68                 char *fn;
69                 char temp[PATH_MAX];
70                 
71                 fn=strrchr(source, '/');
72                 if (fn) fn++;
73                 else fn=source;
74                 
75                 strcpy (temp, fn);
76                 
77                 fn=strrchr(temp, '.');
78                 if (fn) *fn=0;
79                 
80                 if (strlen(temp) > (unsigned int) globals.filename_length) {
81                         temp[globals.filename_length-3]='.';
82                         temp[globals.filename_length-2]='.';
83                         temp[globals.filename_length-1]='.';
84                         temp[globals.filename_length]=0;
85                 } 
86                 strcpy (dest, temp);
87 }
88
89 void name_changed(GtkWidget *wid, vtt_class *vtt)
90 {
91         vtt->set_name((char *) gtk_entry_get_text(GTK_ENTRY(wid)));
92 }
93
94 void volume_changed(GtkWidget *wid, vtt_class *vtt)
95 {
96         vtt->sp_volume.receive_gui_value(2.0-GTK_ADJUSTMENT(wid)->value);
97 }
98
99 void pan_changed(GtkWidget *wid, vtt_class *vtt)
100 {
101       vtt->sp_pan.receive_gui_value(GTK_ADJUSTMENT(wid)->value);
102 }
103
104 void pitch_changed(GtkWidget *wid, vtt_class *vtt)
105 {
106         vtt->sp_pitch.receive_gui_value(GTK_ADJUSTMENT(wid)->value);
107 }
108
109 GtkSignalFunc trigger_prelis(GtkWidget *w)
110 {
111         GtkFileSelection *fs;
112
113         fs=GTK_FILE_SELECTION(gtk_widget_get_toplevel(w));
114         
115         prelis_start((char *) gtk_file_selection_get_filename(GTK_FILE_SELECTION(fs)));
116         return(0);
117 }
118
119 void cancel_load_file(GtkWidget *wid, vtt_class *vtt)
120 {
121         prelis_stop();
122         
123         vtt->gui.file_dialog=NULL;
124         if (vtt->gui.fs) gtk_widget_destroy(GTK_WIDGET(vtt->gui.fs));
125 }
126
127 int quit_load_file(GtkWidget *wid, vtt_class *vtt)
128 {
129         return 1;
130 }
131
132 char global_filename_buffer[PATH_MAX];
133
134 void load_part(char *newfile, vtt_class *vtt)
135 {
136         tX_audio_error ret=TX_AUDIO_SUCCESS;
137
138         ld_create_loaddlg(TX_LOADDLG_MODE_SINGLE, 1);
139         ld_set_filename(newfile);
140
141         ret = vtt->load_file(newfile);
142         
143         ld_destroy();
144         if (ret) {
145                 switch(ret) {
146                         case TX_AUDIO_ERR_ALLOC:
147                         tx_note("Failed to load audiofile - there's not enough memory available.", true);
148                         break;
149                         case TX_AUDIO_ERR_PIPE_READ:
150                         tx_note("An error occured on reading from the piped process - probably the file format of the audiofile is not supported by this configuration - please check terminatorX' INSTALL file on howto configure terminatorX for files of this format.", true);
151                         break;
152                         case TX_AUDIO_ERR_SOX:
153                         tx_note("Failed to run sox - to load the given audiofile please ensure that sox is installed correctly.", true);
154                         break;
155                         case TX_AUDIO_ERR_MPG123:
156                         tx_note("Failed to run mpg123 - to load the given mp3 file please ensure that mpg123 (or mpg321) is installed correctly.", true);
157                         break;
158                         case TX_AUDIO_ERR_WAV_NOTFOUND:
159                         tx_note("Couldn't acces the audiofile - file not found.", true);
160                         break;
161                         case TX_AUDIO_ERR_NOT_16BIT:
162                         tx_note("The wav file doesn't use 16 bit wide samples - please compile terminatorX with libaudiofile support to enable loading of such files.", true);
163                         break;
164                         case TX_AUDIO_ERR_NOT_MONO:
165                         tx_note("The wav file is not mono - please compile terminatorX with libaudiofile support to enable loading of such files.", true);
166                         break;
167                         case TX_AUDIO_ERR_WAV_READ:
168                         tx_note("The wav file seems to be corrupt.", true);
169                         break;
170                         case TX_AUDIO_ERR_NOT_SUPPORTED:
171                         tx_note("The file format of the audiofile is not supported - please check terminatorX' INSTALL file on howto configure terminatorX for files of this format.", true);
172                         break;
173                         case TX_AUDIO_ERR_MAD_OPEN:
174                         tx_note("Failed to open this mp3 file - please ensure that the file exists and is readable.", true);
175                         break;  
176                         case TX_AUDIO_ERR_MAD_STAT:
177                         tx_note("Failed to 'stat' this mp3 file - please ensure that the file exists and is readable.", true);
178                         break;
179                         case TX_AUDIO_ERR_MAD_DECODE:
180                         tx_note("Failed to decode the mp3 stream - file is corrupt.", true);
181                         break;
182                         case TX_AUDIO_ERR_MAD_MMAP:
183                         tx_note("Failed to map the audiofile to memory - please ensure the file is readable.", true);
184                         break;
185                         case TX_AUDIO_ERR_MAD_MUNMAP:
186                         tx_note("Failed to unmap audiofile.", true);
187                         break;
188                         case TX_AUDIO_ERR_VORBIS_OPEN:
189                         tx_note("Failed to open ogg file - please ensure the file is an ogg stream and that it is readable.", true);
190                         break;                  
191                         case TX_AUDIO_ERR_VORBIS_NODATA:
192                         tx_note("The vorbis codec failed to decode any data - possibly this ogg stream is corrupt.", true);
193                         break;
194                         case TX_AUDIO_ERR_AF_OPEN:
195                         tx_note("Failed to open this file with libaudiofile - please check terminatorX' INSTALL file on howto configure terminatorX for files of this format.",true);
196                         break;
197                         case TX_AUDIO_ERR_AF_NODATA:
198                         tx_note("libaudiofile failed to decode any data - possilby the audiofile is corrupt.", true);
199                         break;
200                         default:                                        
201                         tx_note("An unknown error occured - if this bug is reproducible please report it, thanks.", true);      
202                 }
203         } else {
204                 nicer_filename(global_filename_buffer, newfile);
205         gtk_button_set_label(GTK_BUTTON(vtt->gui.file), global_filename_buffer);
206         }       
207 }
208
209 void do_load_file(GtkWidget *wid, vtt_class *vtt)
210 {
211         char newfile[PATH_MAX];
212         
213         prelis_stop();
214
215         strcpy(newfile, gtk_file_selection_get_filename(GTK_FILE_SELECTION(vtt->gui.fs)));
216         gtk_widget_destroy(GTK_WIDGET(vtt->gui.fs));
217         
218         tX_cursor::set_cursor(tX_cursor::WAIT_CURSOR);
219         
220         load_part(newfile, vtt);
221         
222         strcpy(globals.current_path, newfile);
223
224         vtt->gui.file_dialog=NULL;
225         
226         tX_cursor::reset_cursor();
227 }
228
229 void drop_file(GtkWidget *widget, GdkDragContext *context,
230                 gint x, gint y, GtkSelectionData *selection_data,
231                 guint info, guint time, vtt_class *vtt)
232 {
233         char filename[PATH_MAX];
234         char *fn;
235         
236         strncpy(filename, (char *) selection_data->data, (size_t) selection_data->length);
237         gtk_drag_finish(context, TRUE, FALSE, time);
238         filename[selection_data->length]=0;
239
240         fn = strchr (filename, '\r');
241         *fn=0;  
242         
243         char *realfn=NULL;
244         char *host=NULL;
245         
246         realfn=g_filename_from_uri(filename, &host, NULL);
247         if (realfn) {
248                 fn=realfn;
249         } else {
250                 fn = strchr (filename, ':');
251                 if (fn) fn++; else fn=(char *) selection_data->data;
252         }
253
254         load_part(fn, vtt);
255
256         if (realfn) g_free(realfn);
257         if (host) g_free(host);
258 }
259
260
261 GtkSignalFunc load_file(GtkWidget *wid, vtt_class *vtt)
262 {       
263         char buffer[512];
264         
265         if (vtt->gui.file_dialog) {
266                 gdk_window_raise(vtt->gui.file_dialog);
267                 return(0);
268         }
269         
270         sprintf(buffer, "Select Audio File for %s", vtt->name);
271         vtt->gui.fs=gtk_file_selection_new(buffer);
272         
273         if (vtt->audiofile) {
274                 gtk_file_selection_set_filename(GTK_FILE_SELECTION(vtt->gui.fs), vtt->filename);        
275         } else if (strlen(globals.current_path)>0 ) {
276                 gtk_file_selection_set_filename(GTK_FILE_SELECTION(vtt->gui.fs),globals.current_path);
277         }
278         
279         gtk_widget_show(GTK_WIDGET(vtt->gui.fs));       
280         vtt->gui.file_dialog=vtt->gui.fs->window;
281         
282         g_signal_connect (G_OBJECT(GTK_FILE_SELECTION(vtt->gui.fs)->ok_button), "clicked", G_CALLBACK(do_load_file), vtt);
283         g_signal_connect (G_OBJECT(GTK_FILE_SELECTION(vtt->gui.fs)->cancel_button), "clicked", G_CALLBACK (cancel_load_file), vtt);     
284         g_signal_connect (G_OBJECT(vtt->gui.fs), "delete-event", G_CALLBACK(quit_load_file), vtt);      
285         g_signal_connect (G_OBJECT(GTK_FILE_SELECTION(vtt->gui.fs)->file_list), "cursor_changed", G_CALLBACK(trigger_prelis), vtt->gui.fs);             
286         return NULL;
287 }
288
289 void delete_vtt(GtkWidget *wid, vtt_class *vtt)
290 {
291         if (audioon) tx_note("Sorry, you'll have to stop playback first.");
292         else delete(vtt);
293                 
294         mg_update_status();
295 }
296
297 void edit_vtt_buffer(GtkWidget *wid, vtt_class *vtt)
298 {
299         char command[2*PATH_MAX];
300
301         if (vtt->samples_in_buffer == 0) {
302                 tx_note("No audiofile loaded - so there's nothing to edit.", true);
303         } else if (strlen(globals.file_editor)>0) {
304                 sprintf(command, "%s \"%s\" &", globals.file_editor, vtt->filename);
305                 system(command); /*) tx_note("Failed to run the soundfile editor."); */
306         } else {
307                 tx_note("No soundfile editor has been configured - to do so enter the soundfile editor of your choice in the options dialog.", true);
308         }
309 }
310
311 void reload_vtt_buffer(GtkWidget *wid, vtt_class *vtt)
312 {
313         char reload_buffer[PATH_MAX];
314         
315         while (gtk_events_pending()) gtk_main_iteration();
316         
317         if (vtt->samples_in_buffer > 0) {
318                 strcpy(reload_buffer, vtt->filename);
319                 load_part(reload_buffer, vtt);
320         }
321         else tx_note("No audiofile loaded - so there's nothing to reload.", true);
322 }
323
324 void clone_vtt(GtkWidget *wid, vtt_class *vtt)
325 {
326         vtt->stop();
327 }
328
329 void trigger_vtt(GtkWidget *wid, vtt_class *vtt)
330 {
331         vtt->sp_trigger.receive_gui_value((float) 1.0);
332 }
333
334 void stop_vtt(GtkWidget *wid, vtt_class *vtt)
335 {
336         vtt->sp_trigger.receive_gui_value((float) 0.0);
337 }
338
339 void autotrigger_toggled(GtkWidget *wid, vtt_class *vtt)
340 {
341         vtt->set_autotrigger(GTK_TOGGLE_BUTTON(wid)->active);
342 }
343
344 void loop_toggled(GtkWidget *wid, vtt_class *vtt)
345 {
346         vtt->sp_loop.receive_gui_value(GTK_TOGGLE_BUTTON(wid)->active);
347 }
348
349 void lp_enabled(GtkWidget *wid, vtt_class *vtt)
350 {
351         vtt->sp_lp_enable.receive_gui_value(GTK_TOGGLE_BUTTON(wid)->active);
352 }
353
354 void lp_gain_changed(GtkWidget *wid, vtt_class *vtt)
355 {
356         vtt->sp_lp_gain.receive_gui_value(GTK_ADJUSTMENT(wid)->value);
357 }
358
359 void lp_reso_changed(GtkWidget *wid, vtt_class *vtt)
360 {
361         vtt->sp_lp_reso.receive_gui_value(GTK_ADJUSTMENT(wid)->value);
362 }
363
364 void lp_freq_changed(GtkWidget *wid, vtt_class *vtt)
365 {
366         vtt->sp_lp_freq.receive_gui_value(GTK_ADJUSTMENT(wid)->value);
367 }
368
369 void ec_enabled(GtkWidget *wid, vtt_class *vtt)
370 {
371         vtt->sp_ec_enable.receive_gui_value(GTK_TOGGLE_BUTTON(wid)->active);
372 }
373
374 #ifdef USE_ALSA_MIDI_IN
375 void midi_mapping_clicked(GtkWidget *wid, vtt_class *vtt)
376 {
377         tX_engine::get_instance()->midi->configure_bindings(vtt);
378 }
379 #endif
380
381 void ec_length_changed(GtkWidget *wid, vtt_class *vtt)
382 {
383         vtt->sp_ec_length.receive_gui_value(GTK_ADJUSTMENT(wid)->value);
384 }
385
386 void ec_feedback_changed(GtkWidget *wid, vtt_class *vtt)
387 {
388         vtt->sp_ec_feedback.receive_gui_value(GTK_ADJUSTMENT(wid)->value);
389 }
390
391 void ec_pan_changed(GtkWidget *wid, vtt_class *vtt)
392 {
393         vtt->sp_ec_pan.receive_gui_value(GTK_ADJUSTMENT(wid)->value);
394 }
395
396 void ec_volume_changed(GtkWidget *wid, vtt_class *vtt)
397 {
398         vtt->sp_ec_volume.receive_gui_value(GTK_ADJUSTMENT(wid)->value);
399 }
400
401 void master_setup(GtkWidget *wid, vtt_class *vtt)
402 {
403         vtt->set_sync_master(GTK_TOGGLE_BUTTON(wid)->active);
404 }
405
406 void client_setup(GtkWidget *wid, vtt_class *vtt)
407 {
408         int client;
409         
410         client=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(vtt->gui.sync_client));   
411         vtt->sp_sync_client.receive_gui_value(client);
412 }
413
414 void client_setup_number(GtkWidget *wid, vtt_class *vtt)
415 {
416         int cycles;
417         
418         cycles=(int) GTK_ADJUSTMENT(vtt->gui.cycles)->value;    
419         
420         vtt->sp_sync_cycles.receive_gui_value(cycles);
421 }
422
423 void mute_volume(GtkWidget *widget, vtt_class *vtt)
424 {
425         if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))) {
426                 vtt->set_mix_mute(1);
427         } else {
428                 vtt->set_mix_mute(0);
429         }
430 }
431
432 void solo_vtt(GtkWidget *widget, vtt_class *vtt)
433 {
434         if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))) {
435                 vtt->set_mix_solo(1);
436         } else {
437                 vtt->set_mix_solo(0);
438         }
439 }      
440
441 void minimize_control_panel(GtkWidget *wid, vtt_class *vtt)
442 {
443         vtt->hide_control(true);
444 }
445
446 void unminimize_control_panel(GtkWidget *wid, vtt_class *vtt)
447 {
448         vtt->hide_control(false);
449 }
450
451 void minimize_audio_panel(GtkWidget *wid, vtt_class *vtt)
452 {
453         vtt->hide_audio(true);
454 }
455
456 void unminimize_audio_panel(GtkWidget *wid, vtt_class *vtt)
457 {
458         vtt->hide_audio(false);
459 }
460
461 void vg_xcontrol_dis(GtkWidget *wid, vtt_class *vtt)
462 {
463         vtt->set_x_input_parameter(NULL);
464 }
465
466 void vg_ycontrol_dis(GtkWidget *wid, vtt_class *vtt)
467 {
468         vtt->set_y_input_parameter(NULL);
469 }
470
471 void vg_xcontrol_set(GtkWidget *wid, tX_seqpar *sp)
472 {
473         vtt_class *vtt=(vtt_class *) sp->vtt;
474         vtt->set_x_input_parameter(sp);
475 }
476
477 void vg_ycontrol_set(GtkWidget *wid, tX_seqpar *sp)
478 {
479         vtt_class *vtt=(vtt_class *) sp->vtt;
480         vtt->set_y_input_parameter(sp);
481 }
482
483 gboolean vg_delete_pitch_adjust (GtkWidget *wid, vtt_class *vtt) {
484         vtt->gui.adjust_dialog=NULL;
485         return FALSE;
486 }
487
488 void vg_do_pitch_adjust (GtkWidget *wid, vtt_class *vtt) {
489         int master_cycles=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(lookup_widget(vtt->gui.adjust_dialog, "master_cycles")));
490         int cycles=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(lookup_widget(vtt->gui.adjust_dialog, "cycles")));
491         bool create_event=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(lookup_widget(vtt->gui.adjust_dialog, "create_event")));
492
493         vtt->adjust_to_master_pitch(master_cycles, cycles, create_event);
494         
495         gtk_widget_destroy(vtt->gui.adjust_dialog);
496 }
497
498 void vg_cancel_pitch_adjust (GtkWidget *wid, vtt_class *vtt) {
499         gtk_widget_destroy(vtt->gui.adjust_dialog);
500 }
501
502 void vg_adjust_pitch_vtt(GtkWidget *wid, vtt_class *vtt) {
503         if (vtt->gui.adjust_dialog) {
504                 gtk_widget_destroy(vtt->gui.adjust_dialog);
505                 return;
506         }
507         
508         if (!vtt_class::sync_master) {
509                 tx_note("No master turntable to adjust pitch to selected.", true);
510                 return;
511         }
512         
513         if (vtt==vtt_class::sync_master) {
514                 tx_note("This is the master turntable - cannot adjust a turntable to itself.", true);
515                 return;
516         }
517         
518         vtt->gui.adjust_dialog=create_tx_adjust();
519         tX_set_icon(vtt->gui.adjust_dialog);
520         gtk_widget_show(vtt->gui.adjust_dialog);
521         
522         GtkWidget *ok_button=lookup_widget(vtt->gui.adjust_dialog, "ok");
523         GtkWidget *cancel_button=lookup_widget(vtt->gui.adjust_dialog, "cancel");
524         
525         g_signal_connect(G_OBJECT(ok_button), "clicked", G_CALLBACK(vg_do_pitch_adjust), vtt);
526         g_signal_connect(G_OBJECT(vtt->gui.adjust_dialog), "destroy", G_CALLBACK(vg_delete_pitch_adjust), vtt);
527         g_signal_connect(G_OBJECT(cancel_button), "clicked", G_CALLBACK(vg_cancel_pitch_adjust), vtt);
528 }
529
530 void vg_mouse_mapping_pressed(GtkWidget *wid, vtt_class *vtt) {
531         if (vtt->gui.mouse_mapping_menu) {
532                 gtk_widget_destroy(vtt->gui.mouse_mapping_menu);
533                 vtt->gui.mouse_mapping_menu=NULL;
534         }
535         /* gtk+ seems to cleanup the submenus automatically */
536         
537         vtt->gui.mouse_mapping_menu=gtk_menu_new();
538         GtkWidget *x_item;
539         GtkWidget *y_item;
540         
541         x_item=gtk_menu_item_new_with_label("X-axis (Left <-> Right)");
542         gtk_menu_shell_append(GTK_MENU_SHELL(vtt->gui.mouse_mapping_menu), x_item);
543         gtk_widget_show(x_item);
544
545         y_item=gtk_menu_item_new_with_label("Y-axis (Up <-> Down)");
546         gtk_menu_shell_append(GTK_MENU_SHELL(vtt->gui.mouse_mapping_menu), y_item);
547         gtk_widget_show(y_item);
548         
549         vtt->gui.mouse_mapping_menu_x=gtk_menu_new();
550         vtt->gui.mouse_mapping_menu_y=gtk_menu_new();
551         
552         GtkWidget *item;
553         GtkWidget *item_to_activate=NULL;
554         
555         /* Filling the X menu */
556         item = gtk_check_menu_item_new_with_label("Disable");
557         gtk_menu_shell_append(GTK_MENU_SHELL(vtt->gui.mouse_mapping_menu_x), item);
558         gtk_widget_show(item);
559         g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(vg_xcontrol_dis), vtt);
560         if (vtt->x_par==NULL) item_to_activate=item;
561
562         list <tX_seqpar *> :: iterator sp;
563
564         for (sp=tX_seqpar::all.begin(); sp!=tX_seqpar::all.end(); sp++) {
565                 if (((*sp)->is_mappable) && ((*sp)->vtt) == (void*) vtt) {
566                         item=gtk_check_menu_item_new_with_label((*sp)->get_name());
567                         gtk_menu_shell_append(GTK_MENU_SHELL(vtt->gui.mouse_mapping_menu_x), item);
568                         gtk_widget_show(item);
569                         g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(vg_xcontrol_set), (void*) (*sp));
570                         
571                         if (vtt->x_par==(*sp)) item_to_activate=item;
572                 }
573         }
574
575         if (item_to_activate) gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item_to_activate), TRUE);
576         
577         /* Filling the Y menu */
578         item_to_activate=NULL;
579         
580         item = gtk_check_menu_item_new_with_label("Disable");
581         gtk_menu_shell_append(GTK_MENU_SHELL(vtt->gui.mouse_mapping_menu_y), item);
582         gtk_widget_show(item);
583         g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(vg_ycontrol_dis), vtt);
584         if (vtt->y_par==NULL) item_to_activate=item;
585
586         for (sp=tX_seqpar::all.begin(); sp!=tX_seqpar::all.end(); sp++) {
587                 if (((*sp)->is_mappable) && ((*sp)->vtt) == (void*) vtt) {
588                         item=gtk_check_menu_item_new_with_label((*sp)->get_name());
589                         gtk_menu_shell_append(GTK_MENU_SHELL(vtt->gui.mouse_mapping_menu_y), item);
590                         gtk_widget_show(item);
591                         g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(vg_ycontrol_set), (void*) (*sp));
592                         
593                         if (vtt->y_par==(*sp)) item_to_activate=item;
594                 }
595         }
596
597         if (item_to_activate) gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item_to_activate), TRUE);
598         
599         gtk_menu_item_set_submenu(GTK_MENU_ITEM(x_item), vtt->gui.mouse_mapping_menu_x);
600         gtk_menu_item_set_submenu(GTK_MENU_ITEM(y_item), vtt->gui.mouse_mapping_menu_y);
601         
602         gtk_menu_popup (GTK_MENU(vtt->gui.mouse_mapping_menu), NULL, NULL, NULL, NULL, 0, 0);
603
604         g_signal_emit_by_name(G_OBJECT(wid), "released", vtt);
605 }
606
607 void vg_file_button_pressed(GtkWidget *wid, vtt_class *vtt) {
608         if (vtt->gui.file_menu==NULL) {
609                 GtkWidget *item;
610                 
611                 vtt->gui.file_menu=gtk_menu_new();
612                 item=gtk_menu_item_new_with_label("Load audio file");
613                 gtk_menu_shell_append(GTK_MENU_SHELL(vtt->gui.file_menu), item);
614                 gtk_widget_show(item);
615                 
616                 g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(load_file), vtt);
617                 
618                 item=gtk_menu_item_new_with_label("Edit audio file");
619                 gtk_menu_shell_append(GTK_MENU_SHELL(vtt->gui.file_menu), item);
620                 gtk_widget_show(item);
621
622                 g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(edit_vtt_buffer), vtt);
623
624                 item=gtk_menu_item_new_with_label("Reload current audio file");
625                 gtk_menu_shell_append(GTK_MENU_SHELL(vtt->gui.file_menu), item);
626                 gtk_widget_show(item);
627
628                 g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(reload_vtt_buffer), vtt);
629         }
630         
631         gtk_menu_popup(GTK_MENU(vtt->gui.file_menu), NULL, NULL, NULL, NULL, 0,0);
632
633         /* gtk+ is really waiting for this.. */
634         g_signal_emit_by_name(G_OBJECT(wid), "released", vtt);
635 }
636
637 void vg_adjust_zoom(GtkWidget *wid, vtt_class *vtt) {   
638         GtkAdjustment *adj=gtk_range_get_adjustment(GTK_RANGE(vtt->gui.zoom));
639         gtk_tx_set_zoom(GTK_TX(vtt->gui.display), adj->value/100.0);
640 }
641
642 void fx_button_pressed(GtkWidget *wid, vtt_class *vtt)
643 {
644         vtt_gui *g=&vtt->gui;
645
646         LADSPA_Class::set_current_vtt(vtt);
647
648         if (g->ladspa_menu) gtk_object_destroy(GTK_OBJECT(g->ladspa_menu));
649         g->ladspa_menu=LADSPA_Class::get_ladspa_menu();
650         gtk_menu_popup (GTK_MENU(g->ladspa_menu), NULL, NULL, NULL, NULL, 0, 0);
651
652         /* gtk+ is really waiting for this.. */
653         g_signal_emit_by_name(G_OBJECT(wid), "released", vtt);
654 }
655
656 void gui_set_name(vtt_class *vtt, char *newname)
657 {
658         char bold_name[128];
659         strcpy(bold_name, "<b>");
660         strcat(bold_name, newname);
661         strcat(bold_name, "</b>");
662         
663         gtk_label_set_markup(GTK_LABEL(vtt->gui.audio_label), bold_name);
664         gtk_label_set_markup(GTK_LABEL(vtt->gui.control_label), bold_name);
665         gtk_entry_set_text(GTK_ENTRY(vtt->gui.name), newname);
666         
667         if (vtt->gui.audio_minimized_panel_bar_button!=NULL) {
668                 gtk_label_set_text(GTK_LABEL(vtt->gui.audio_minimized_panel_bar_label), newname);
669         }
670
671         if (vtt->gui.control_minimized_panel_bar_button!=NULL) {
672                 gtk_label_set_text(GTK_LABEL(vtt->gui.control_minimized_panel_bar_label), newname);
673         }
674 }
675
676 #define connect_entry(wid, func); g_signal_connect(G_OBJECT(g->wid), "activate", G_CALLBACK(func), (void *) vtt);
677 #define connect_adj(wid, func); g_signal_connect(G_OBJECT(g->wid), "value_changed", G_CALLBACK(func), (void *) vtt);
678 #define connect_button(wid, func); g_signal_connect(G_OBJECT(g->wid), "clicked", G_CALLBACK(func), (void *) vtt);
679 #define connect_range(wid, func); g_signal_connect(G_OBJECT(gtk_range_get_adjustment(GTK_RANGE(g->wid))), "value_changed", G_CALLBACK(func), (void *) vtt);
680 #define connect_scale_format(wid, func); g_signal_connect(G_OBJECT(g->wid), "format-value", G_CALLBACK(func), (void *) vtt);
681 #define connect_press_button(wid, func); g_signal_connect(G_OBJECT(g->wid), "pressed", G_CALLBACK(func), (void *) vtt);
682 #define connect_rel_button(wid, func); g_signal_connect(G_OBJECT(g->wid), "released", G_CALLBACK(func), (void *) vtt);
683
684 GtkWidget *vg_create_fx_bar(vtt_class *vtt, vtt_fx *effect, int showdel);
685
686 void gui_connect_signals(vtt_class *vtt)
687 {
688         vtt_gui *g=&vtt->gui;
689
690         connect_entry(name, name_changed);
691         connect_adj(volume, volume_changed);
692         connect_adj(pitch, pitch_changed);
693         connect_adj(pan, pan_changed);
694         connect_press_button(file, vg_file_button_pressed);
695         
696         connect_button(del, delete_vtt);
697         connect_button(trigger, trigger_vtt);
698         connect_button(stop, stop_vtt);
699         connect_button(autotrigger, autotrigger_toggled);
700         connect_button(loop, loop_toggled);
701         connect_button(sync_master, master_setup);
702         connect_button(sync_client, client_setup);
703         connect_button(adjust_button, vg_adjust_pitch_vtt);
704         connect_adj(cycles, client_setup_number);
705         connect_press_button(fx_button, fx_button_pressed);
706         
707         connect_button(lp_enable, lp_enabled);
708         connect_adj(lp_gain, lp_gain_changed);
709         connect_adj(lp_reso, lp_reso_changed);
710         connect_adj(lp_freq, lp_freq_changed);
711         
712         connect_button(ec_enable, ec_enabled);
713 #ifdef USE_ALSA_MIDI_IN 
714         connect_button(midi_mapping, midi_mapping_clicked);
715 #endif  
716         connect_adj(ec_length, ec_length_changed);
717         connect_adj(ec_feedback, ec_feedback_changed);
718         connect_adj(ec_pan, ec_pan_changed);
719         connect_adj(ec_volume, ec_volume_changed);      
720         connect_range(zoom, vg_adjust_zoom);
721         //connect_scale_format(zoom, vg_format_zoom);
722         connect_press_button(mouse_mapping, vg_mouse_mapping_pressed);
723         connect_button(control_minimize, minimize_control_panel);
724         connect_button(audio_minimize, minimize_audio_panel);
725
726         static GtkTargetEntry drop_types [] = {
727                 { "text/uri-list", 0, 0}
728         };
729         static gint n_drop_types = sizeof (drop_types) / sizeof(drop_types[0]);
730         
731         gtk_drag_dest_set (GTK_WIDGET (g->file), (GtkDestDefaults) (GTK_DEST_DEFAULT_MOTION |GTK_DEST_DEFAULT_HIGHLIGHT |GTK_DEST_DEFAULT_DROP),
732                         drop_types, n_drop_types,
733                         GDK_ACTION_COPY);
734                                                 
735         g_signal_connect (G_OBJECT (g->file), "drag_data_received",
736                         G_CALLBACK(drop_file), (void *) vtt);
737
738         gtk_drag_dest_set (GTK_WIDGET (g->display), (GtkDestDefaults) (GTK_DEST_DEFAULT_MOTION |GTK_DEST_DEFAULT_HIGHLIGHT |GTK_DEST_DEFAULT_DROP),
739                         drop_types, n_drop_types,
740                         GDK_ACTION_COPY);
741                                                 
742         g_signal_connect (G_OBJECT (g->display), "drag_data_received",
743                         G_CALLBACK(drop_file), (void *) vtt);
744         
745 }
746
747 void vg_show_fx_menu(GtkWidget *, vtt_fx *effect);
748
749 void build_vtt_gui(vtt_class *vtt)
750 {
751         GtkWidget *tempbox;
752         GtkWidget *tempbox2;
753         GtkWidget *tempbox3;
754         GtkWidget *dummy;
755         char nice_name[256];
756         
757         vtt_gui *g;
758         
759         g=&vtt->gui;
760         vtt->have_gui=1;
761         g->par_menu=NULL;
762         g->ladspa_menu=NULL;
763
764         /* Building Audio Box */
765         g->audio_box=gtk_vbox_new(FALSE,2);
766         gtk_widget_show(g->audio_box);
767         
768         tempbox2=gtk_hbox_new(FALSE,2);
769         gtk_widget_show(tempbox2);
770         gtk_box_pack_start(GTK_BOX(g->audio_box), tempbox2, WID_FIX);
771         
772         tempbox=gtk_hbox_new(TRUE,2);
773         gtk_widget_show(tempbox);
774         gtk_box_pack_start(GTK_BOX(tempbox2), tempbox, WID_DYN);
775
776         GtkWidget *pixmap;
777         g->audio_minimize=gtk_button_new();
778         pixmap=tx_pixmap_widget(TX_ICON_MINIMIZE_PANEL);
779         gtk_container_add (GTK_CONTAINER (g->audio_minimize), pixmap);  
780         gtk_box_pack_end(GTK_BOX(tempbox2), g->audio_minimize, WID_FIX);
781         gtk_widget_show(pixmap);
782         gtk_widget_show(g->audio_minimize);
783
784
785         g->audio_label=gtk_label_new(vtt->name);
786         gtk_misc_set_alignment(GTK_MISC(g->audio_label), 0.025, 0.5);
787         gtk_widget_show(g->audio_label);
788         gtk_box_pack_start(GTK_BOX(tempbox), g->audio_label, WID_DYN);
789
790         nicer_filename(nice_name, vtt->filename);
791         g->file = gtk_button_new_with_label(nice_name);
792         gtk_widget_show(g->file);
793         gui_set_tooltip(g->file, "Click to Load/Edit/Reload a sample for this turntable. To load you can also drag a file and drop it over this button or the sound data display below.");
794         gtk_box_pack_start(GTK_BOX(tempbox), g->file, WID_DYN);
795
796         g->mouse_mapping=gtk_button_new_with_label("Mouse");
797         gtk_widget_show(g->mouse_mapping);
798         gui_set_tooltip(g->mouse_mapping, "Determines what parameters should be affected on mouse moition in mouse grab mode.");
799         gtk_box_pack_start(GTK_BOX(tempbox2), g->mouse_mapping, WID_FIX);
800
801 #ifdef USE_ALSA_MIDI_IN
802         g->midi_mapping=gtk_button_new_with_label("MIDI");
803         gtk_widget_show(g->midi_mapping);
804         gui_set_tooltip(g->midi_mapping, "Determines what parameters should be bound to what MIDI events.");
805         gtk_box_pack_start(GTK_BOX(tempbox2), g->midi_mapping, WID_FIX);
806         
807         if (!tX_engine::get_instance()->get_midi()->get_is_open()) {
808                 gtk_widget_set_sensitive(g->midi_mapping, FALSE);
809         }
810 #endif
811
812         tempbox=gtk_hbox_new(FALSE, 2);
813
814         g->display=gtk_tx_new(vtt->buffer, vtt->samples_in_buffer);
815         gtk_box_pack_start(GTK_BOX(tempbox), g->display, WID_DYN);
816         gtk_widget_show(g->display);    
817         
818         g->zoom=gtk_vscale_new_with_range(0,99.0,1.0);
819         gtk_range_set_inverted(GTK_RANGE(g->zoom), TRUE);
820         gtk_scale_set_draw_value(GTK_SCALE(g->zoom), TRUE);
821         gtk_scale_set_digits(GTK_SCALE(g->zoom), 0);
822         gtk_scale_set_value_pos(GTK_SCALE(g->zoom), GTK_POS_BOTTOM);
823         gtk_adjustment_set_value(gtk_range_get_adjustment(GTK_RANGE(g->zoom)), 0);
824         
825         gui_set_tooltip(g->zoom, "Set the zoom-level for the audio data display.");
826         gtk_box_pack_start(GTK_BOX(tempbox), g->zoom, WID_FIX);
827         gtk_widget_show(g->zoom);
828         
829         gtk_box_pack_start(GTK_BOX(g->audio_box), tempbox, WID_DYN);
830         gtk_widget_show(tempbox);
831         
832         /* Building Control Box */
833         
834         g->control_box=gtk_vbox_new(FALSE,2);
835         gtk_widget_show(g->control_box);
836
837         tempbox2=gtk_hbox_new(FALSE, 2);
838         gtk_widget_show(tempbox2);
839         gtk_box_pack_start(GTK_BOX(g->control_box), tempbox2, WID_FIX);
840
841         g->control_label=gtk_label_new(vtt->name);
842         gtk_widget_show(g->control_label);
843         gtk_box_pack_start(GTK_BOX(tempbox2), g->control_label, WID_DYN);
844
845         g->control_minimize=gtk_button_new();
846         pixmap=tx_pixmap_widget(TX_ICON_MINIMIZE_PANEL);
847         gtk_container_add (GTK_CONTAINER (g->control_minimize), pixmap);        
848         gtk_box_pack_end(GTK_BOX(tempbox2), g->control_minimize, WID_FIX);
849         gtk_widget_show(pixmap);
850         gtk_widget_show(g->control_minimize);
851
852         g->scrolled_win=gtk_scrolled_window_new (NULL, NULL);
853         gtk_container_set_border_width (GTK_CONTAINER (g->scrolled_win), 0);
854         gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (g->scrolled_win),
855                                     GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
856         gtk_widget_show(g->scrolled_win);
857         gtk_box_pack_start(GTK_BOX(g->control_box), g->scrolled_win, WID_DYN);
858                                     
859         g->control_subbox=gtk_vbox_new(FALSE,0);
860         gtk_scrolled_window_add_with_viewport (
861                    GTK_SCROLLED_WINDOW (g->scrolled_win), g->control_subbox);
862         gtk_widget_show(g->control_subbox);
863                    
864
865         /* Main panel */
866         
867         tX_panel *p=new tX_panel("Main", g->control_subbox);
868         g->main_panel=p;
869                         
870         g->name = gtk_entry_new();
871         gtk_entry_set_max_length(GTK_ENTRY(g->name), 256);
872         gtk_entry_set_text(GTK_ENTRY(g->name), vtt->name);
873         p->add_client_widget(g->name);
874         gui_set_tooltip(g->name, "Enter the turntable's name here.");
875         gtk_widget_set_size_request(g->name, 40, -1);
876
877         g->del=gtk_button_new_with_label("Delete");
878         gui_set_tooltip(g->del, "Click here to annihilate this turntable. All events recorded for this turntable will be erased, too.");
879         p->add_client_widget(g->del);
880         
881         g->adjust_button=gtk_button_new_with_label("Pitch Adj.");
882         gui_set_tooltip(g->adjust_button, "Activate this button to adjust this turntable's speed to the master turntable's speed.");
883         p->add_client_widget(g->adjust_button);
884
885         gtk_box_pack_start(GTK_BOX(g->control_subbox), p->get_widget(), WID_FIX);
886                                 
887         p=new tX_panel("Trigger", g->control_subbox);
888         g->trigger_panel=p;
889         
890         g->trigger=gtk_button_new_with_label("Trigger!");
891         gui_set_tooltip(g->trigger, "Click here to trigger this turntable right now. If the audio engine is disabled this turntable will be triggerd as soon as the engine is turned on.");
892         p->add_client_widget(g->trigger);
893         
894         g->stop=gtk_button_new_with_label("Stop.");
895         gui_set_tooltip(g->stop, "Stop this turntable's playback.");
896         p->add_client_widget(g->stop);
897         g_signal_connect(G_OBJECT(g->trigger), "button_press_event", (GtkSignalFunc) tX_seqpar::tX_seqpar_press, &vtt->sp_trigger);             
898         g_signal_connect(G_OBJECT(g->stop), "button_press_event", (GtkSignalFunc) tX_seqpar::tX_seqpar_press, &vtt->sp_trigger);                
899         
900         g->autotrigger=gtk_check_button_new_with_label("Auto");
901         p->add_client_widget(g->autotrigger);
902         gui_set_tooltip(g->autotrigger, "If turned on, this turntable will be automagically triggered whenever the audio engine is turned on.");
903         gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(g->autotrigger), vtt->autotrigger);
904
905         g->loop=gtk_check_button_new_with_label("Loop");
906         p->add_client_widget(g->loop);
907         gui_set_tooltip(g->loop, "Enable this option to make the turntable loop the audio data.");
908         gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(g->loop), vtt->loop);
909         g_signal_connect(G_OBJECT(g->loop), "button_press_event", (GtkSignalFunc) tX_seqpar::tX_seqpar_press, &vtt->sp_loop);           
910         
911         g->sync_master=gtk_check_button_new_with_label("Master");
912         p->add_client_widget(g->sync_master);
913         gui_set_tooltip(g->sync_master, "Click here to make this turntable the sync-master. All turntables marked as sync-clients will be (re-)triggered in relation to the sync-master. Note that only *one* turntable can be the sync-master.");
914         gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(g->sync_master), vtt->is_sync_master);
915         
916         g->sync_client=gtk_check_button_new_with_label("Client");
917         p->add_client_widget(g->sync_client);
918         gui_set_tooltip(g->sync_client, "If enabled this turntable will be (re-)triggerd in relation to the sync-master turntable.");
919         gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(g->sync_client), vtt->is_sync_client);
920         g_signal_connect(G_OBJECT(g->sync_client), "button_press_event", (GtkSignalFunc) tX_seqpar::tX_seqpar_press, &vtt->sp_sync_client);     
921         
922         g->cycles=GTK_ADJUSTMENT(gtk_adjustment_new(vtt->sync_cycles, 0, 10.0, 1,1,1));
923         dummy=gtk_spin_button_new(g->cycles, 1.0, 0);
924         p->add_client_widget(dummy);
925         gui_set_tooltip(dummy, "Determines how often a sync-client turntable gets triggered. 0 -> this turntable will be triggered with every trigger of the sync-master table, 1 -> the table will be triggered every 2nd master trigger and so on.");
926         g_signal_connect(G_OBJECT(dummy), "button_press_event", (GtkSignalFunc) tX_seqpar::tX_seqpar_press, &vtt->sp_sync_cycles);      
927
928         gtk_box_pack_start(GTK_BOX(g->control_subbox), p->get_widget(), WID_FIX);
929
930         dummy=gtk_button_new_with_label("FX");
931         gtk_container_foreach(GTK_CONTAINER(dummy), (GtkCallback) tX_panel_make_label_bold, NULL);
932         gtk_widget_show(dummy);
933         g->fx_button=dummy;
934         gui_set_tooltip(g->fx_button, "Click here to load a LADSPA plugin. You will get a menu from which you can choose which plugin to load.");
935         gtk_box_pack_start(GTK_BOX(g->control_subbox), dummy, WID_FIX);
936         
937         /* Lowpass Panel */
938
939         p=new tX_panel("Lowpass", g->control_subbox);
940         g_signal_connect(G_OBJECT(p->get_labelbutton()), "clicked", G_CALLBACK(vg_show_fx_menu), vtt->lp_fx);
941         g->lp_panel=p;
942                 
943         g->lp_enable=gtk_check_button_new_with_label("Enable");
944         gui_set_tooltip(g->lp_enable, "Click here to enable the built-in lowpass effect.");
945         gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(g->lp_enable), vtt->lp_enable);
946         p->add_client_widget(vg_create_fx_bar(vtt, vtt->lp_fx, 0));
947         g_signal_connect(G_OBJECT(g->lp_enable), "button_press_event", (GtkSignalFunc) tX_seqpar::tX_seqpar_press, &vtt->sp_ec_enable); 
948
949         p->add_client_widget(g->lp_enable);
950
951         g->lp_gain=GTK_ADJUSTMENT(gtk_adjustment_new(vtt->lp_gain, 0, 2, 0.1, 0.01, 0.01));
952         g->lp_reso=GTK_ADJUSTMENT(gtk_adjustment_new(vtt->lp_reso, 0, 0.99, 0.1, 0.01, 0.01));
953         g->lp_freq=GTK_ADJUSTMENT(gtk_adjustment_new(vtt->lp_freq, 0, 1, 0.1, 0.01, 0.01));
954
955         g->lp_gaind=new tX_extdial("Input Gain", g->lp_gain, &vtt->sp_lp_gain);
956         p->add_client_widget(g->lp_gaind->get_widget());
957         gui_set_tooltip(g->lp_gaind->get_entry(), "Adjust the input gain. with this parameter you can either amplify or damp the input-signal for the lowpass effect.");
958
959         g->lp_freqd=new tX_extdial("Frequency", g->lp_freq, &vtt->sp_lp_freq);
960         p->add_client_widget(g->lp_freqd->get_widget());
961         gui_set_tooltip(g->lp_freqd->get_entry(), "Adjust the cutoff frequency of the lowpass filter. 0 is 0 Hz, 1 is 22.1 kHz.");
962
963         g->lp_resod=new tX_extdial("Resonance", g->lp_reso, &vtt->sp_lp_reso);
964         p->add_client_widget(g->lp_resod->get_widget());
965         gui_set_tooltip(g->lp_resod->get_entry(), "Adjust the resonance of the lowpass filter. This value determines how much the signal at the cutoff frequency will be amplified.");
966
967         gtk_box_pack_start(GTK_BOX(g->control_subbox), p->get_widget(), WID_FIX);
968
969         /* Echo Panel */
970
971         p=new tX_panel("Echo", g->control_subbox);
972         g_signal_connect(G_OBJECT(p->get_labelbutton()), "clicked",  G_CALLBACK(vg_show_fx_menu), vtt->ec_fx);
973         g->ec_panel=p;
974
975         p->add_client_widget(vg_create_fx_bar(vtt, vtt->ec_fx, 0));
976         
977         g->ec_enable=gtk_check_button_new_with_label("Enable");
978         gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(g->ec_enable), vtt->ec_enable);
979         p->add_client_widget(g->ec_enable);
980         gui_set_tooltip(g->ec_enable, "Enable the built-in echo effect.");
981         g_signal_connect(G_OBJECT(g->ec_enable), "button_press_event", (GtkSignalFunc) tX_seqpar::tX_seqpar_press, &vtt->sp_ec_enable); 
982
983         g->ec_length=GTK_ADJUSTMENT(gtk_adjustment_new(vtt->ec_length, 0, 1, 0.1, 0.01, 0.001));
984         g->ec_feedback=GTK_ADJUSTMENT(gtk_adjustment_new(vtt->ec_feedback, 0, 1, 0.1, 0.01, 0.001));
985         g->ec_pan=GTK_ADJUSTMENT(gtk_adjustment_new(vtt->ec_pan, -1.0, 1, 0.1, 0.01, 0.001));
986         g->ec_volume=GTK_ADJUSTMENT(gtk_adjustment_new(vtt->ec_volume, 0.0, 3.0, 0.1, 0.01, 0.001));
987
988         g->ec_lengthd=new tX_extdial("Duration", g->ec_length, &vtt->sp_ec_length);
989         p->add_client_widget(g->ec_lengthd->get_widget());
990         gui_set_tooltip(g->ec_lengthd->get_entry(), "Adjust the length of the echo buffer.");
991
992         g->ec_feedbackd=new tX_extdial("Feedback", g->ec_feedback, &vtt->sp_ec_feedback);
993         p->add_client_widget(g->ec_feedbackd->get_widget());
994         gui_set_tooltip(g->ec_feedbackd->get_entry(), "Adjust the feedback of the echo effect. Note that a value of 1 will result in a constant signal.");
995
996         g->ec_volumed=new tX_extdial("Volume", g->ec_volume, &vtt->sp_ec_volume);
997         p->add_client_widget(g->ec_volumed->get_widget());
998         gui_set_tooltip(g->ec_volumed->get_entry(), "Adjust the volume of the echo effect.");
999
1000         g->ec_pand=new tX_extdial("Pan", g->ec_pan, &vtt->sp_ec_pan);
1001         p->add_client_widget(g->ec_pand->get_widget());
1002         gui_set_tooltip(g->ec_pand->get_entry(), "Adjust the panning of the echo effect.");
1003
1004         gtk_box_pack_start(GTK_BOX(g->control_subbox), p->get_widget(), WID_FIX);
1005         
1006         /* Output */
1007         
1008         tempbox=gtk_hbox_new(FALSE,2);
1009         gtk_widget_show(tempbox);
1010         gtk_box_pack_end(GTK_BOX(g->control_box), tempbox, WID_FIX);
1011         
1012         tempbox2=gtk_vbox_new(FALSE,0);
1013         gtk_widget_show(tempbox2);
1014         gtk_box_pack_start(GTK_BOX(tempbox), tempbox2, WID_FIX);
1015         
1016         g->pitch=GTK_ADJUSTMENT(gtk_adjustment_new(vtt->rel_pitch, -3, +3, 0.1, 0.01, 0.001));
1017         g->pan=GTK_ADJUSTMENT(gtk_adjustment_new(0, -1, 1, 0.1, 0.01, 0.001));
1018
1019         g->pitchd=new tX_extdial("Pitch", g->pitch, &vtt->sp_pitch);
1020         gui_set_tooltip(g->pitchd->get_entry(), "Adjust this turntable's pitch.");
1021
1022         gtk_box_pack_start(GTK_BOX(tempbox2), g->pitchd->get_widget(), WID_FIX);
1023
1024         g->pand=new tX_extdial("Pan", g->pan, &vtt->sp_pan);
1025         gtk_box_pack_start(GTK_BOX(tempbox2), g->pand->get_widget(), WID_FIX);
1026         gui_set_tooltip(g->pand->get_entry(), "Specifies the position of this turntable within the stereo spectrum: -1 -> left, 0-> center, 1->right.");
1027
1028         tempbox3=gtk_hbox_new(FALSE,2);
1029         gtk_widget_show(tempbox3);
1030
1031         g->mute=gtk_check_button_new_with_label("M");
1032         gtk_box_pack_start(GTK_BOX(tempbox3), g->mute, WID_FIX);
1033         g_signal_connect(G_OBJECT(g->mute),"clicked", (GtkSignalFunc) mute_volume, vtt);
1034         gtk_widget_show(g->mute);
1035         gui_set_tooltip(g->mute, "Mute this turntable's mixer output.");
1036
1037         g->solo=gtk_check_button_new_with_label("S");
1038         gtk_box_pack_start(GTK_BOX(tempbox3), g->solo, WID_FIX);
1039         g_signal_connect(G_OBJECT(g->solo),"clicked", (GtkSignalFunc) solo_vtt, vtt);
1040         gtk_widget_show(g->solo);
1041         gui_set_tooltip(g->solo, "Allow only this and other solo-switched turntabels' signal to be routed to the mixer.");
1042
1043         gtk_box_pack_start(GTK_BOX(tempbox2), tempbox3, WID_FIX);
1044
1045         tempbox2=gtk_hbox_new(FALSE,0);
1046         gtk_widget_show(tempbox2);
1047         gtk_box_pack_start(GTK_BOX(tempbox), tempbox2, WID_FIX);
1048         
1049         g->volume=GTK_ADJUSTMENT(gtk_adjustment_new(2.0-vtt->rel_volume, 0, 2, 0.01, 0.01, 0.01));
1050         dummy=gtk_vscale_new(GTK_ADJUSTMENT(g->volume)); 
1051         gtk_scale_set_draw_value(GTK_SCALE(dummy), False);
1052         gui_set_tooltip(dummy, "Adjust this turntable's volume.");
1053         g_signal_connect(G_OBJECT(dummy), "button_press_event", (GtkSignalFunc) tX_seqpar::tX_seqpar_press, &vtt->sp_volume);   
1054
1055         gtk_box_pack_start(GTK_BOX(tempbox2), dummy, WID_FIX);
1056         gtk_widget_show(dummy);
1057
1058         g->flash=gtk_tx_flash_new();
1059         gtk_box_pack_start(GTK_BOX(tempbox2), g->flash, WID_FIX);
1060         gtk_widget_show(g->flash);              
1061
1062         g->file_dialog=NULL;
1063
1064         gui_connect_signals(vtt);
1065         
1066         g->audio_minimized_panel_bar_button=NULL;
1067         g->control_minimized_panel_bar_button=NULL;
1068         g->file_menu=NULL;
1069         g->mouse_mapping_menu=NULL;
1070         g->mouse_mapping_menu_x=NULL;
1071         g->mouse_mapping_menu_y=NULL;
1072         
1073         g->adjust_dialog=NULL;
1074         
1075         gui_set_name(vtt, vtt->name);   
1076 }
1077
1078 void fx_up(GtkWidget *wid, vtt_fx *effect)
1079 {
1080         vtt_class *vtt;
1081         
1082         vtt=(vtt_class*)effect->get_vtt();
1083         vtt->effect_up(effect);
1084 }
1085
1086 void fx_down(GtkWidget *wid, vtt_fx *effect)
1087 {
1088         vtt_class *vtt;
1089         
1090         vtt=(vtt_class*)effect->get_vtt();
1091         vtt->effect_down(effect);
1092 }
1093
1094 void fx_kill(GtkWidget *wid, vtt_fx_ladspa *effect)
1095 {
1096         vtt_class *vtt;
1097         
1098         vtt=(vtt_class*)effect->get_vtt();
1099         vtt->effect_remove(effect);
1100 }
1101
1102 GtkWidget *vg_create_fx_bar(vtt_class *vtt, vtt_fx *effect, int showdel)
1103 {
1104         GtkWidget *box;
1105         GtkWidget *pixmap;
1106         GtkWidget *button;
1107         
1108         box=gtk_hbox_new(FALSE,0);
1109
1110         if (showdel)
1111         {
1112                 button=gtk_button_new();
1113                 pixmap=tx_pixmap_widget(TX_ICON_FX_CLOSE);
1114                 gtk_container_add (GTK_CONTAINER (button), pixmap);     
1115                 gtk_box_pack_end(GTK_BOX(box), button, WID_FIX);
1116                 gtk_widget_show(pixmap);
1117                 gtk_widget_show(button);
1118                 g_signal_connect(G_OBJECT(button), "clicked", (GtkSignalFunc) fx_kill, (void *) effect);
1119         }
1120
1121         button=gtk_button_new();
1122         pixmap=tx_pixmap_widget(TX_ICON_FX_DOWN);
1123         gtk_container_add (GTK_CONTAINER (button), pixmap);     
1124         gtk_box_pack_end(GTK_BOX(box), button, WID_FIX);
1125         gtk_widget_show(pixmap);
1126         gtk_widget_show(button);
1127         g_signal_connect(G_OBJECT(button), "clicked", (GtkSignalFunc) fx_down, (void *) effect);
1128
1129         button=gtk_button_new();
1130         pixmap=tx_pixmap_widget(TX_ICON_FX_UP);
1131         gtk_container_add (GTK_CONTAINER (button), pixmap);     
1132         gtk_box_pack_end(GTK_BOX(box), button, WID_FIX);
1133         gtk_widget_show(pixmap);
1134         gtk_widget_show(button);
1135         g_signal_connect(G_OBJECT(button), "clicked", (GtkSignalFunc) fx_up, (void *) effect);
1136         
1137         gtk_widget_show(box);
1138         
1139         return box;
1140 }
1141
1142
1143 int gtk_box_get_widget_pos(GtkBox *box, GtkWidget *child)
1144 {
1145         int i=0;
1146         GList *list;
1147  
1148         list = box->children;
1149         while (list)
1150         {
1151                 GtkBoxChild *child_info;
1152                 child_info = (GtkBoxChild *) list->data;
1153                 if (child_info->widget == child)
1154                 break;
1155                 list = list->next; i++;
1156         }
1157         return i;
1158 }
1159
1160 void vg_move_fx_panel_up(GtkWidget *wid, vtt_class *vtt)
1161 {
1162         int pos=gtk_box_get_widget_pos(GTK_BOX(vtt->gui.control_subbox), wid);
1163         gtk_box_reorder_child(GTK_BOX(vtt->gui.control_subbox), wid, pos-1);
1164 }
1165
1166 void vg_move_fx_panel_down(GtkWidget *wid, vtt_class *vtt)
1167 {
1168         int pos=gtk_box_get_widget_pos(GTK_BOX(vtt->gui.control_subbox), wid);
1169         gtk_box_reorder_child(GTK_BOX(vtt->gui.control_subbox), wid, pos+1);
1170 }
1171
1172 void vg_show_fx_info(GtkWidget *wid, vtt_fx *effect)
1173 {
1174         tx_l_note(effect->get_info_string());
1175 }
1176
1177 void vg_toggle_drywet(GtkWidget *wid, vtt_fx *effect)
1178 {
1179         effect->toggle_drywet();
1180 }
1181
1182 void vg_show_fx_menu(GtkWidget *wid, vtt_fx *effect)
1183 {
1184         GtkWidget *menu=gtk_menu_new();
1185         GtkWidget *item=gtk_menu_item_new_with_label("Show Info");
1186         gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
1187         gtk_widget_set_sensitive(item, (effect->has_drywet_feature()!=NOT_DRYWET_CAPABLE));
1188         gtk_widget_show(item);
1189         g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(vg_show_fx_info), effect);
1190         
1191         switch (effect->has_drywet_feature()) {
1192                 case (NOT_DRYWET_CAPABLE):
1193                         item=gtk_menu_item_new_with_label("Add Dry/Wet Control");
1194                         gtk_widget_set_sensitive(item, FALSE);
1195                         break;
1196                 case (DRYWET_ACTIVE):
1197                         item=gtk_menu_item_new_with_label("Remove Dry/Wet Control");
1198                         break;
1199                 case (DRYWET_AVAILABLE):
1200                         item=gtk_menu_item_new_with_label("Add Dry/Wet Control");
1201                         break;
1202         }
1203         
1204         g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(vg_toggle_drywet), effect);
1205         
1206         gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
1207         gtk_widget_show(item);
1208
1209         gtk_menu_popup (GTK_MENU(menu), NULL, NULL, NULL, NULL, 0, 0);
1210
1211         /* gtk+ is really waiting for this.. */
1212         g_signal_emit_by_name(G_OBJECT(wid), "released", effect);
1213 }
1214
1215 void vg_create_fx_gui(vtt_class *vtt, vtt_fx_ladspa *effect, LADSPA_Plugin *plugin)
1216 {
1217         char buffer[1024];
1218         
1219         vtt_gui *g;
1220         g=&vtt->gui;    
1221         tX_panel *p;
1222         list <tX_seqpar_vttfx *> :: iterator sp;
1223         
1224         strcpy(buffer, plugin->getLabel());
1225         if (strlen(buffer) > 6)
1226         {
1227                 buffer[5]='.';
1228                 buffer[6]='.';
1229                 buffer[7]='.';
1230                 buffer[8]=0;
1231         }
1232
1233         p=new tX_panel(buffer, g->control_subbox);
1234         
1235         p->add_client_widget(vg_create_fx_bar(vtt, effect, 1));
1236         
1237         for (sp = effect->controls.begin(); sp != effect->controls.end(); sp++)
1238         {
1239                         p->add_client_widget((*sp)->get_widget());
1240         }
1241
1242         g_signal_connect(G_OBJECT(p->get_labelbutton()), "clicked", (GtkSignalFunc) vg_show_fx_menu, (void *) effect);
1243         gui_set_tooltip(p->get_labelbutton(), "Click here for menu");
1244         effect->set_panel_widget(p->get_widget());
1245         effect->set_panel(p);
1246
1247         gtk_box_pack_start(GTK_BOX(g->control_subbox), p->get_widget(), WID_FIX);
1248 }
1249
1250 void gui_set_filename (vtt_class *vtt, char *newname)
1251 {
1252         gtk_button_set_label(GTK_BUTTON(vtt->gui.file), newname);
1253 }
1254
1255 void gui_update_display(vtt_class *vtt)
1256 {
1257         nicer_filename(global_filename_buffer, vtt->filename);
1258         gtk_button_set_label(GTK_BUTTON(vtt->gui.file), global_filename_buffer);
1259         gtk_tx_set_data(GTK_TX(vtt->gui.display), vtt->buffer, vtt->samples_in_buffer);
1260 }
1261
1262 void gui_hide_control_panel(vtt_class *vtt, bool hide) {
1263         if (hide) {
1264                 gtk_widget_hide(vtt->gui.control_box);
1265                 vtt->gui.control_minimized_panel_bar_button=tx_xpm_button_new(TX_ICON_MIN_CONTROL, vtt->name, 0, &vtt->gui.control_minimized_panel_bar_label);
1266                 g_signal_connect(G_OBJECT(vtt->gui.control_minimized_panel_bar_button), "clicked", (GtkSignalFunc) unminimize_control_panel, vtt);
1267                 gtk_widget_show(vtt->gui.control_minimized_panel_bar_button);
1268                 add_to_panel_bar(vtt->gui.control_minimized_panel_bar_button);
1269         } else {
1270                 gtk_widget_show(vtt->gui.control_box);
1271                 remove_from_panel_bar(vtt->gui.control_minimized_panel_bar_button);
1272                 if (!tX_shutdown) gtk_widget_destroy(vtt->gui.control_minimized_panel_bar_button);
1273                 vtt->gui.control_minimized_panel_bar_button=NULL;
1274         }
1275 }
1276
1277 void gui_hide_audio_panel(vtt_class *vtt, bool hide) {
1278         if (hide) {
1279                 gtk_widget_hide(vtt->gui.audio_box);
1280                 vtt->gui.audio_minimized_panel_bar_button=tx_xpm_button_new(TX_ICON_MIN_AUDIO, vtt->name, 0, &vtt->gui.audio_minimized_panel_bar_label);
1281                 g_signal_connect(G_OBJECT(vtt->gui.audio_minimized_panel_bar_button), "clicked", (GtkSignalFunc) unminimize_audio_panel, vtt);          
1282                 gtk_widget_show(vtt->gui.audio_minimized_panel_bar_button);
1283                 add_to_panel_bar(vtt->gui.audio_minimized_panel_bar_button);
1284         } else {
1285                 gtk_widget_show(vtt->gui.audio_box);
1286                 remove_from_panel_bar(vtt->gui.audio_minimized_panel_bar_button);
1287                 if (!tX_shutdown) gtk_widget_destroy(vtt->gui.audio_minimized_panel_bar_button);
1288                 vtt->gui.audio_minimized_panel_bar_button=NULL;
1289         }
1290 }
1291
1292 void delete_gui(vtt_class *vtt)
1293 {
1294         if (vtt->gui.control_minimized_panel_bar_button!=NULL) gui_hide_control_panel(vtt, false);
1295         if (vtt->gui.audio_minimized_panel_bar_button!=NULL) gui_hide_audio_panel(vtt, false);
1296
1297         delete vtt->gui.main_panel;
1298         delete vtt->gui.trigger_panel;
1299         
1300         delete vtt->gui.pitchd;
1301         delete vtt->gui.pand;
1302         
1303         delete vtt->gui.lp_gaind;
1304         delete vtt->gui.lp_resod;
1305         delete vtt->gui.lp_freqd;
1306         delete vtt->gui.lp_panel;
1307         
1308         delete vtt->gui.ec_lengthd;
1309         delete vtt->gui.ec_feedbackd;
1310         delete vtt->gui.ec_volumed;
1311         delete vtt->gui.ec_pand;
1312         delete vtt->gui.ec_panel;
1313
1314         gtk_widget_destroy(vtt->gui.control_box);
1315         gtk_widget_destroy(vtt->gui.audio_box);
1316         if (vtt->gui.file_menu) gtk_widget_destroy(vtt->gui.file_menu);
1317         if (vtt->gui.mouse_mapping_menu) gtk_widget_destroy(vtt->gui.mouse_mapping_menu);
1318         if (vtt->gui.ladspa_menu) gtk_widget_destroy(vtt->gui.ladspa_menu);
1319 }
1320
1321 void cleanup_vtt(vtt_class *vtt)
1322 {
1323         gtk_tx_cleanup_pos_display(GTK_TX(vtt->gui.display));   
1324         gtk_tx_flash_set_level(vtt->gui.flash, 0.0);
1325         gtk_tx_flash_clear(vtt->gui.flash);
1326         vtt->cleanup_required=false;
1327 }
1328
1329 void update_all_vtts()
1330 {
1331         list <vtt_class *> :: iterator vtt;
1332         f_prec temp;
1333         
1334         for (vtt=vtt_class::main_list.begin(); vtt!=vtt_class::main_list.end(); vtt++)
1335         {
1336                 if ((*vtt)->is_playing) {
1337                         gtk_tx_update_pos_display(GTK_TX((*vtt)->gui.display), (*vtt)->pos_i, (*vtt)->mute);
1338                         temp=(*vtt)->max_value*(*vtt)->res_volume*vtt_class::vol_channel_adjust;
1339                         (*vtt)->max_value=0;
1340                         gtk_tx_flash_set_level((*vtt)->gui.flash, temp);
1341                 }
1342                 
1343                 if ((*vtt)->needs_cleaning_up()) {
1344                         cleanup_vtt((*vtt));
1345                 }
1346         }
1347 }
1348
1349 void cleanup_all_vtts()
1350 {
1351         list <vtt_class *> :: iterator vtt;
1352         
1353         for (vtt=vtt_class::main_list.begin(); vtt!=vtt_class::main_list.end(); vtt++)
1354         {
1355                 if ((*vtt)->buffer) gtk_tx_cleanup_pos_display(GTK_TX((*vtt)->gui.display));
1356                 gtk_tx_flash_set_level((*vtt)->gui.flash, 0.0);
1357                 gtk_tx_flash_clear((*vtt)->gui.flash);
1358         }
1359 }
1360
1361 void gui_clear_master_button(vtt_class *vtt)
1362 {
1363         gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(vtt->gui.sync_master), 0);
1364 }
1365
1366 void gui_show_frame(vtt_class *vtt, int show)
1367 {
1368         gtk_tx_show_frame(GTK_TX(vtt->gui.display), show);
1369 }
1370
1371 #define vgui (*vtt)->gui
1372 #define v (*vtt)
1373
1374 void vg_enable_critical_buttons(int enable)
1375 {
1376         list <vtt_class *> :: iterator vtt;
1377         for (vtt=vtt_class::main_list.begin(); vtt!=vtt_class::main_list.end(); vtt++)
1378         {
1379                 gtk_widget_set_sensitive(vgui.del, enable);
1380                 gtk_widget_set_sensitive(vgui.sync_master, enable);
1381         }
1382 }
1383
1384
1385 void vg_init_all_non_seqpars()
1386 {
1387         list <vtt_class *> :: iterator vtt;
1388         
1389         for (vtt=vtt_class::main_list.begin(); vtt!=vtt_class::main_list.end(); vtt++)
1390         {
1391                 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON((*vtt)->gui.autotrigger), (*vtt)->autotrigger);
1392                 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON((*vtt)->gui.sync_master), (*vtt)->is_sync_master);
1393         }       
1394 }
1395
1396 f_prec gui_get_audio_x_zoom(vtt_class *vtt) {
1397         return gtk_tx_get_zoom(GTK_TX(vtt->gui.display));
1398 }
1399
1400 /* Yes, this is yet another evil hack. Fix it :) */
1401 int vttgui_zoom_depth=0;
1402
1403 extern void gui_set_audio_x_zoom(vtt_class *vtt, f_prec value) {
1404         if (vttgui_zoom_depth==0) {
1405                 vttgui_zoom_depth=1;
1406                 gtk_range_set_value(GTK_RANGE(vtt->gui.zoom), value*100.0);
1407                 vttgui_zoom_depth=0;
1408         } else {
1409                 gtk_tx_set_zoom(GTK_TX(vtt->gui.display), value);
1410         }
1411 }