2 terminatorX - realtime audio scratching software
3 Copyright (C) 1999-2020 Alexander König
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.
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.
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
20 Description: This implements the gtk+ GUI for the virtual turntable
21 class implemented in tX_vtt.cc. This code is not in tX_vtt.cc
22 for mainly to keep the GUI code divided from the audio-rendering
23 code and as gtk+ callback to C++ method call wrapper.
28 #include "tX_vttgui.h"
30 #include "tX_widget.h"
31 #include "tX_mastergui.h"
32 #include "tX_loaddlg.h"
33 #include "tX_prelis.h"
34 #include "tX_pbutton.h"
35 #include "tX_global.h"
36 #include "tX_extdial.h"
38 #include "tX_ladspa.h"
39 #include "tX_ladspa_class.h"
40 #include "tX_engine.h"
41 #include "tX_ui_interface.h"
42 #include "tX_ui_support.h"
43 #include "tX_dialog.h"
54 #define WID_DYN TRUE, TRUE, 0
55 #define WID_FIX FALSE, FALSE, 0
57 void nicer_filename(char *dest, char *source)
62 fn=strrchr(source, '/');
68 fn=strrchr(temp, '.');
71 if (strlen(temp) > (unsigned int) globals.filename_length) {
72 temp[globals.filename_length-3]='.';
73 temp[globals.filename_length-2]='.';
74 temp[globals.filename_length-1]='.';
75 temp[globals.filename_length]=0;
80 void name_changed(GtkWidget *wid, vtt_class *vtt)
82 vtt->set_name((char *) gtk_entry_get_text(GTK_ENTRY(wid)));
85 void volume_changed(GtkWidget *wid, vtt_class *vtt)
87 vtt->sp_volume.receive_gui_value(2.0-gtk_adjustment_get_value(GTK_ADJUSTMENT(wid)));
90 void pan_changed(GtkWidget *wid, vtt_class *vtt)
92 vtt->sp_pan.receive_gui_value(gtk_adjustment_get_value(GTK_ADJUSTMENT(wid)));
95 void pitch_changed(GtkWidget *wid, vtt_class *vtt)
97 vtt->sp_pitch.receive_gui_value(gtk_adjustment_get_value(GTK_ADJUSTMENT(wid)));
100 GCallback chooser_prelis(GtkWidget *w)
102 GtkFileChooser *fc=GTK_FILE_CHOOSER(gtk_widget_get_toplevel(w));
103 char *filename=gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(fc));
106 prelis_start(filename);
114 char global_filename_buffer[PATH_MAX];
116 void load_part(char *newfile, vtt_class *vtt)
118 tX_audio_error ret=TX_AUDIO_SUCCESS;
120 ld_create_loaddlg(TX_LOADDLG_MODE_SINGLE, 1);
121 ld_set_filename(newfile);
123 ret = vtt->load_file(newfile);
128 case TX_AUDIO_ERR_ALLOC:
129 tx_note("Failed to load audiofile - there's not enough memory available.", true);
131 case TX_AUDIO_ERR_PIPE_READ:
132 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);
134 case TX_AUDIO_ERR_SOX:
135 tx_note("Failed to run sox - to load the given audiofile please ensure that sox is installed correctly.", true);
137 case TX_AUDIO_ERR_MPG123:
138 tx_note("Failed to run mpg123 - to load the given mp3 file please ensure that mpg123 (or mpg321) is installed correctly.", true);
140 case TX_AUDIO_ERR_WAV_NOTFOUND:
141 tx_note("Couldn't acces the audiofile - file not found.", true);
143 case TX_AUDIO_ERR_NOT_16BIT:
144 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);
146 case TX_AUDIO_ERR_NOT_MONO:
147 tx_note("The wav file is not mono - please compile terminatorX with libaudiofile support to enable loading of such files.", true);
149 case TX_AUDIO_ERR_WAV_READ:
150 tx_note("The wav file seems to be corrupt.", true);
152 case TX_AUDIO_ERR_NOT_SUPPORTED:
153 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);
155 case TX_AUDIO_ERR_MAD_OPEN:
156 tx_note("Failed to open this mp3 file - please ensure that the file exists and is readable.", true);
158 case TX_AUDIO_ERR_MAD_STAT:
159 tx_note("Failed to 'stat' this mp3 file - please ensure that the file exists and is readable.", true);
161 case TX_AUDIO_ERR_MAD_DECODE:
162 tx_note("Failed to decode the mp3 stream - file is corrupt.", true);
164 case TX_AUDIO_ERR_MAD_MMAP:
165 tx_note("Failed to map the audiofile to memory - please ensure the file is readable.", true);
167 case TX_AUDIO_ERR_MAD_MUNMAP:
168 tx_note("Failed to unmap audiofile.", true);
170 case TX_AUDIO_ERR_VORBIS_OPEN:
171 tx_note("Failed to open ogg file - please ensure the file is an ogg stream and that it is readable.", true);
173 case TX_AUDIO_ERR_VORBIS_NODATA:
174 tx_note("The vorbis codec failed to decode any data - possibly this ogg stream is corrupt.", true);
176 case TX_AUDIO_ERR_AF_OPEN:
177 tx_note("Failed to open this file with libaudiofile - please check terminatorX' INSTALL file on howto configure terminatorX for files of this format.",true);
179 case TX_AUDIO_ERR_AF_NODATA:
180 tx_note("libaudiofile failed to decode any data - possilby the audiofile is corrupt.", true);
183 tx_note("An unknown error occured - if this bug is reproducible please report it, thanks.", true);
186 nicer_filename(global_filename_buffer, newfile);
187 gtk_button_set_label(GTK_BUTTON(vtt->gui.file), global_filename_buffer);
191 void drop_file(GtkWidget *widget, GdkDragContext *context,
192 gint x, gint y, GtkSelectionData *selection_data,
193 guint info, guint time, vtt_class *vtt)
195 char filename[PATH_MAX];
198 strncpy(filename, (char *) gtk_selection_data_get_data(selection_data), (size_t) gtk_selection_data_get_length(selection_data));
199 gtk_drag_finish(context, TRUE, FALSE, time);
200 filename[gtk_selection_data_get_length(selection_data)]=0;
202 fn = strchr (filename, '\r');
208 realfn=g_filename_from_uri(filename, &host, NULL);
212 fn = strchr (filename, ':');
213 if (fn) fn++; else fn=(char *) gtk_selection_data_get_data(selection_data);
218 if (realfn) g_free(realfn);
219 if (host) g_free(host);
222 GCallback load_file(GtkWidget *wid, vtt_class *vtt)
224 const char *extensions[]={ "mp3", "wav", "ogg", "flac", "iff", "aiff", "voc", "au", "spx", NULL };
226 sprintf(name_buf, "Select Audio File for %s", vtt->name);
228 GtkWidget * dialog = gtk_file_chooser_dialog_new (name_buf,
229 GTK_WINDOW(main_window), GTK_FILE_CHOOSER_ACTION_OPEN,
230 "_Cancel", GTK_RESPONSE_CANCEL,
231 "_Open", GTK_RESPONSE_ACCEPT, NULL);
234 GtkFileFilter *filter=gtk_file_filter_new();
235 for (int i=0; extensions[i]!=NULL; i++) {
236 char buffer[32]="*.";
238 gtk_file_filter_add_pattern(filter, strcat(buffer, extensions[i]));
239 for (unsigned int c=0; c<strlen(buffer); c++) {
240 buffer[c]=toupper(buffer[c]);
242 gtk_file_filter_add_pattern(filter, buffer);
245 gtk_file_filter_set_name(filter, "Audio Files");
246 gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog), filter);
248 filter=gtk_file_filter_new();
249 gtk_file_filter_add_pattern (filter, "*");
250 gtk_file_filter_set_name(filter, "All Files");
251 gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog), filter);
253 if (vtt->audiofile) {
254 gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(dialog), vtt->filename);
255 } else if (strlen(globals.current_path)>0 ) {
256 gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(dialog), globals.current_path);
259 g_signal_connect (G_OBJECT(dialog), "selection-changed", G_CALLBACK(chooser_prelis), vtt);
261 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) {
262 char * filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
263 gtk_widget_hide(dialog);
264 tX_cursor::set_cursor(tX_cursor::WAIT_CURSOR);
265 load_part(filename, vtt);
266 strcpy(globals.current_path, filename);
267 tX_cursor::reset_cursor();
271 gtk_widget_destroy(dialog);
276 void delete_vtt(GtkWidget *wid, vtt_class *vtt)
278 if (audioon) tx_note("Sorry, you'll have to stop playback first.");
284 void edit_vtt_buffer(GtkWidget *wid, vtt_class *vtt)
286 char command[2*PATH_MAX+32];
288 if (vtt->samples_in_buffer == 0) {
289 tx_note("No audiofile loaded - so there's nothing to edit.", true);
290 } else if (strlen(globals.file_editor)>0) {
291 snprintf(command, sizeof(command), "%s \"%s\" &", globals.file_editor, vtt->filename);
292 if (system(command) < 0) {
293 tx_note("Error running the soundfile editor.");
296 tx_note("No soundfile editor has been configured - to do so enter the soundfile editor of your choice in the options dialog.", true);
300 void reload_vtt_buffer(GtkWidget *wid, vtt_class *vtt)
302 char reload_buffer[PATH_MAX];
304 while (gtk_events_pending()) gtk_main_iteration();
306 if (vtt->samples_in_buffer > 0) {
307 strcpy(reload_buffer, vtt->filename);
308 load_part(reload_buffer, vtt);
310 else tx_note("No audiofile loaded - so there's nothing to reload.", true);
313 void clone_vtt(GtkWidget *wid, vtt_class *vtt)
318 void trigger_vtt(GtkWidget *wid, vtt_class *vtt)
320 vtt->sp_trigger.receive_gui_value((float) 1.0);
323 void stop_vtt(GtkWidget *wid, vtt_class *vtt)
325 vtt->sp_trigger.receive_gui_value((float) 0.0);
328 void autotrigger_toggled(GtkWidget *wid, vtt_class *vtt)
330 vtt->set_autotrigger(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(wid)));
333 void loop_toggled(GtkWidget *wid, vtt_class *vtt)
335 vtt->sp_loop.receive_gui_value(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(wid)));
338 void lp_enabled(GtkWidget *wid, vtt_class *vtt)
340 vtt->sp_lp_enable.receive_gui_value(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(wid)));
343 void lp_gain_changed(GtkWidget *wid, vtt_class *vtt)
345 vtt->sp_lp_gain.receive_gui_value(gtk_adjustment_get_value(GTK_ADJUSTMENT(wid)));
348 void lp_reso_changed(GtkWidget *wid, vtt_class *vtt)
350 vtt->sp_lp_reso.receive_gui_value(gtk_adjustment_get_value(GTK_ADJUSTMENT(wid)));
353 void lp_freq_changed(GtkWidget *wid, vtt_class *vtt)
355 vtt->sp_lp_freq.receive_gui_value(gtk_adjustment_get_value(GTK_ADJUSTMENT(wid)));
358 void ec_enabled(GtkWidget *wid, vtt_class *vtt)
360 vtt->sp_ec_enable.receive_gui_value(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(wid)));
363 #ifdef USE_ALSA_MIDI_IN
364 void midi_mapping_clicked(GtkWidget *wid, vtt_class *vtt)
366 tX_engine::get_instance()->get_midi()->configure_bindings(vtt);
370 void ec_length_changed(GtkWidget *wid, vtt_class *vtt)
372 vtt->sp_ec_length.receive_gui_value(gtk_adjustment_get_value(GTK_ADJUSTMENT(wid)));
375 void ec_feedback_changed(GtkWidget *wid, vtt_class *vtt)
377 vtt->sp_ec_feedback.receive_gui_value(gtk_adjustment_get_value(GTK_ADJUSTMENT(wid)));
380 void ec_pan_changed(GtkWidget *wid, vtt_class *vtt)
382 vtt->sp_ec_pan.receive_gui_value(gtk_adjustment_get_value(GTK_ADJUSTMENT(wid)));
385 void ec_volume_changed(GtkWidget *wid, vtt_class *vtt)
387 vtt->sp_ec_volume.receive_gui_value(gtk_adjustment_get_value(GTK_ADJUSTMENT(wid)));
390 void master_setup(GtkWidget *wid, vtt_class *vtt)
392 vtt->set_sync_master(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(wid)));
395 void client_setup(GtkWidget *wid, vtt_class *vtt)
399 client=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(vtt->gui.sync_client));
400 vtt->sp_sync_client.receive_gui_value(client);
403 void client_setup_number(GtkWidget *wid, vtt_class *vtt)
407 cycles=(int) gtk_adjustment_get_value(GTK_ADJUSTMENT(vtt->gui.cycles));
409 vtt->sp_sync_cycles.receive_gui_value(cycles);
412 void mute_volume(GtkWidget *widget, vtt_class *vtt)
414 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))) {
415 vtt->set_mix_mute(1);
417 vtt->set_mix_mute(0);
421 void solo_vtt(GtkWidget *widget, vtt_class *vtt)
423 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget))) {
424 vtt->set_mix_solo(1);
426 vtt->set_mix_solo(0);
430 void minimize_control_panel(GtkWidget *wid, vtt_class *vtt)
432 vtt->hide_control(true);
435 void unminimize_control_panel(GtkWidget *wid, vtt_class *vtt)
437 vtt->hide_control(false);
440 void minimize_audio_panel(GtkWidget *wid, vtt_class *vtt)
442 vtt->hide_audio(true);
445 void unminimize_audio_panel(GtkWidget *wid, vtt_class *vtt)
447 vtt->hide_audio(false);
450 void vg_xcontrol_dis(GtkWidget *wid, vtt_class *vtt)
452 vtt->set_x_input_parameter(NULL);
455 void vg_ycontrol_dis(GtkWidget *wid, vtt_class *vtt)
457 vtt->set_y_input_parameter(NULL);
460 void vg_xcontrol_set(GtkWidget *wid, tX_seqpar *sp)
462 vtt_class *vtt=(vtt_class *) sp->vtt;
463 vtt->set_x_input_parameter(sp);
466 void vg_ycontrol_set(GtkWidget *wid, tX_seqpar *sp)
468 vtt_class *vtt=(vtt_class *) sp->vtt;
469 vtt->set_y_input_parameter(sp);
472 gboolean vg_delete_pitch_adjust (GtkWidget *wid, vtt_class *vtt) {
473 vtt->gui.adjust_dialog=NULL;
477 void vg_do_pitch_adjust (GtkWidget *wid, vtt_class *vtt) {
478 int master_cycles=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(lookup_widget(vtt->gui.adjust_dialog, "master_cycles")));
479 int cycles=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(lookup_widget(vtt->gui.adjust_dialog, "cycles")));
480 bool create_event=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(lookup_widget(vtt->gui.adjust_dialog, "create_event")));
482 vtt->adjust_to_master_pitch(master_cycles, cycles, create_event);
484 gtk_widget_destroy(vtt->gui.adjust_dialog);
487 void vg_cancel_pitch_adjust (GtkWidget *wid, vtt_class *vtt) {
488 gtk_widget_destroy(vtt->gui.adjust_dialog);
491 void vg_adjust_pitch_vtt(GtkWidget *wid, vtt_class *vtt) {
492 if (vtt->gui.adjust_dialog) {
493 gtk_widget_destroy(vtt->gui.adjust_dialog);
497 if (!vtt_class::sync_master) {
498 tx_note("No master turntable to adjust pitch to selected.", true);
502 if (vtt==vtt_class::sync_master) {
503 tx_note("This is the master turntable - cannot adjust a turntable to itself.", true);
507 vtt->gui.adjust_dialog=create_tx_adjust();
508 tX_set_icon(vtt->gui.adjust_dialog);
509 gtk_widget_show(vtt->gui.adjust_dialog);
511 GtkWidget *ok_button=lookup_widget(vtt->gui.adjust_dialog, "ok");
512 GtkWidget *cancel_button=lookup_widget(vtt->gui.adjust_dialog, "cancel");
514 g_signal_connect(G_OBJECT(ok_button), "clicked", G_CALLBACK(vg_do_pitch_adjust), vtt);
515 g_signal_connect(G_OBJECT(vtt->gui.adjust_dialog), "destroy", G_CALLBACK(vg_delete_pitch_adjust), vtt);
516 g_signal_connect(G_OBJECT(cancel_button), "clicked", G_CALLBACK(vg_cancel_pitch_adjust), vtt);
519 static gint vg_mouse_mapping_pressed(GtkWidget *wid, GdkEventButton *event, vtt_class *vtt) {
520 if (vtt->gui.mouse_mapping_menu) {
521 gtk_widget_destroy(vtt->gui.mouse_mapping_menu);
522 vtt->gui.mouse_mapping_menu=NULL;
524 /* gtk+ seems to cleanup the submenus automatically */
526 vtt->gui.mouse_mapping_menu=gtk_menu_new();
530 x_item=gtk_menu_item_new_with_label("X-axis (Left <-> Right)");
531 gtk_menu_shell_append(GTK_MENU_SHELL(vtt->gui.mouse_mapping_menu), x_item);
532 gtk_widget_show(x_item);
534 y_item=gtk_menu_item_new_with_label("Y-axis (Up <-> Down)");
535 gtk_menu_shell_append(GTK_MENU_SHELL(vtt->gui.mouse_mapping_menu), y_item);
536 gtk_widget_show(y_item);
538 vtt->gui.mouse_mapping_menu_x=gtk_menu_new();
539 vtt->gui.mouse_mapping_menu_y=gtk_menu_new();
542 GtkWidget *item_to_activate=NULL;
544 /* Filling the X menu */
545 item = gtk_check_menu_item_new_with_label("Disable");
546 gtk_menu_shell_append(GTK_MENU_SHELL(vtt->gui.mouse_mapping_menu_x), item);
547 gtk_widget_show(item);
548 g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(vg_xcontrol_dis), vtt);
549 if (vtt->x_par==NULL) item_to_activate=item;
551 list <tX_seqpar *> :: iterator sp;
553 for (sp=tX_seqpar::all->begin(); sp!=tX_seqpar::all->end(); sp++) {
554 if (((*sp)->is_mappable) && ((*sp)->vtt) == (void*) vtt) {
555 item=gtk_check_menu_item_new_with_label((*sp)->get_name());
556 gtk_menu_shell_append(GTK_MENU_SHELL(vtt->gui.mouse_mapping_menu_x), item);
557 gtk_widget_show(item);
558 g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(vg_xcontrol_set), (void*) (*sp));
560 if (vtt->x_par==(*sp)) item_to_activate=item;
564 if (item_to_activate) gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item_to_activate), TRUE);
566 /* Filling the Y menu */
567 item_to_activate=NULL;
569 item = gtk_check_menu_item_new_with_label("Disable");
570 gtk_menu_shell_append(GTK_MENU_SHELL(vtt->gui.mouse_mapping_menu_y), item);
571 gtk_widget_show(item);
572 g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(vg_ycontrol_dis), vtt);
573 if (vtt->y_par==NULL) item_to_activate=item;
575 for (sp=tX_seqpar::all->begin(); sp!=tX_seqpar::all->end(); sp++) {
576 if (((*sp)->is_mappable) && ((*sp)->vtt) == (void*) vtt) {
577 item=gtk_check_menu_item_new_with_label((*sp)->get_name());
578 gtk_menu_shell_append(GTK_MENU_SHELL(vtt->gui.mouse_mapping_menu_y), item);
579 gtk_widget_show(item);
580 g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(vg_ycontrol_set), (void*) (*sp));
582 if (vtt->y_par==(*sp)) item_to_activate=item;
586 if (item_to_activate) gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item_to_activate), TRUE);
588 gtk_menu_item_set_submenu(GTK_MENU_ITEM(x_item), vtt->gui.mouse_mapping_menu_x);
589 gtk_menu_item_set_submenu(GTK_MENU_ITEM(y_item), vtt->gui.mouse_mapping_menu_y);
590 gtk_menu_popup (GTK_MENU(vtt->gui.mouse_mapping_menu), NULL, NULL, NULL, NULL, 0, 0);
592 g_signal_emit_by_name(G_OBJECT(wid), "released", vtt);
597 static gint vg_file_button_pressed(GtkWidget *wid, GdkEventButton *event, vtt_class *vtt) {
598 if (vtt->gui.file_menu==NULL) {
601 vtt->gui.file_menu=gtk_menu_new();
602 item=gtk_menu_item_new_with_label("Load audio file");
603 gtk_menu_shell_append(GTK_MENU_SHELL(vtt->gui.file_menu), item);
604 gtk_widget_show(item);
606 g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(load_file), vtt);
608 item=gtk_menu_item_new_with_label("Edit audio file");
609 gtk_menu_shell_append(GTK_MENU_SHELL(vtt->gui.file_menu), item);
610 gtk_widget_show(item);
612 g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(edit_vtt_buffer), vtt);
614 item=gtk_menu_item_new_with_label("Reload current audio file");
615 gtk_menu_shell_append(GTK_MENU_SHELL(vtt->gui.file_menu), item);
616 gtk_widget_show(item);
618 g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(reload_vtt_buffer), vtt);
621 gtk_menu_popup(GTK_MENU(vtt->gui.file_menu), NULL, NULL, NULL, NULL, 0,0);
622 /* gtk+ is really waiting for this.. */
623 g_signal_emit_by_name(G_OBJECT(wid), "released", vtt);
628 void vg_adjust_zoom(GtkWidget *wid, vtt_class *vtt) {
629 GtkAdjustment *adj=gtk_range_get_adjustment(GTK_RANGE(vtt->gui.zoom));
630 gtk_tx_set_zoom(GTK_TX(vtt->gui.display), gtk_adjustment_get_value(adj)/100.0, vtt->is_playing);
633 static gint fx_button_pressed(GtkWidget *wid, GdkEventButton *event, vtt_class *vtt)
635 vtt_gui *g=&vtt->gui;
637 LADSPA_Class::set_current_vtt(vtt);
639 if (g->ladspa_menu) gtk_widget_destroy(GTK_WIDGET(g->ladspa_menu));
640 g->ladspa_menu=LADSPA_Class::get_ladspa_menu();
641 gtk_menu_popup (GTK_MENU(g->ladspa_menu), NULL, NULL, NULL, NULL, 0, 0);
643 /* gtk+ is really waiting for this.. */
644 g_signal_emit_by_name(G_OBJECT(wid), "released", vtt);
649 static gint stereo_fx_button_pressed(GtkWidget *wid, GdkEventButton *event, vtt_class *vtt)
651 vtt_gui *g=&vtt->gui;
653 LADSPA_Class::set_current_vtt(vtt);
655 if (g->ladspa_menu) gtk_widget_destroy(GTK_WIDGET(g->ladspa_menu));
656 g->ladspa_menu=LADSPA_Class::get_stereo_ladspa_menu();
657 gtk_menu_popup (GTK_MENU(g->ladspa_menu), NULL, NULL, NULL, NULL, 0, 0);
659 /* gtk+ is really waiting for this.. */
660 g_signal_emit_by_name(G_OBJECT(wid), "released", vtt);
666 void update_vtt_css(vtt_class *vtt, GdkRGBA* rgba) {
669 memcpy(©, rgba, sizeof(GdkRGBA));
670 copy.alpha = globals.title_bar_alpha;
671 char *color_str = gdk_rgba_to_string(©);
672 snprintf(css, sizeof(css), ".%08x { background-color: %s; }", vtt, color_str);
674 gtk_css_provider_load_from_data(vtt->gui.css_provider, css, -1, NULL);
675 gtk_style_context_add_provider_for_screen(gdk_screen_get_default(), GTK_STYLE_PROVIDER(vtt->gui.css_provider), GTK_STYLE_PROVIDER_PRIORITY_USER);
677 gtk_tx_update_colors(GTK_TX(vtt->gui.display), rgba);
678 gtk_widget_queue_draw(vtt->gui.display);
681 static void gui_color_set(GtkWidget *widget, vtt_class *vtt) {
682 gtk_color_chooser_get_rgba(GTK_COLOR_CHOOSER(widget), vtt->get_color());
684 update_vtt_css(vtt, vtt->get_color());
687 void gui_set_color(vtt_class *vtt, GdkRGBA* rgba) {
688 gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(vtt->gui.color_button), rgba);
689 update_vtt_css(vtt, rgba);
693 #define TOOLTIP_LENGTH 2048
695 void gui_set_name(vtt_class *vtt, char *newname)
698 strcpy(bold_name, "<b>");
699 strcat(bold_name, newname);
700 strcat(bold_name, "</b>");
702 gtk_label_set_markup(GTK_LABEL(vtt->gui.audio_label), bold_name);
703 gtk_label_set_markup(GTK_LABEL(vtt->gui.control_label), bold_name);
704 gtk_entry_set_text(GTK_ENTRY(vtt->gui.name), newname);
707 if (vtt->gui.audio_minimized_panel_bar_button!=NULL) {
708 gtk_label_set_text(GTK_LABEL(vtt->gui.audio_minimized_panel_bar_label), newname);
709 snprintf(tooltip, TOOLTIP_LENGTH, "Show \"%s\" audio panel.", newname);
710 gui_set_tooltip(vtt->gui.audio_minimized_panel_bar_button, tooltip);
713 if (vtt->gui.control_minimized_panel_bar_button!=NULL) {
714 gtk_label_set_text(GTK_LABEL(vtt->gui.control_minimized_panel_bar_label), newname);
715 snprintf(tooltip, TOOLTIP_LENGTH, "Show \"%s\" control panel.", newname);
716 gui_set_tooltip(vtt->gui.control_minimized_panel_bar_button, tooltip);
720 f_prec gui_get_audio_x_zoom(vtt_class *vtt) {
721 return gtk_tx_get_zoom(GTK_TX(vtt->gui.display));
724 int vttgui_zoom_depth=0;
726 void gui_set_audio_x_zoom(vtt_class *vtt, f_prec value) {
727 if (vttgui_zoom_depth==0) {
729 gtk_range_set_value(GTK_RANGE(vtt->gui.zoom), value*100.0);
732 gtk_tx_set_zoom(GTK_TX(vtt->gui.display), value, vtt->is_playing);
736 void gui_scroll_callback(GtkWidget *tx, GdkEventScroll *eventScroll, gpointer userdata) {
737 vtt_class *vtt = (vtt_class *) userdata;
738 f_prec zoom = gui_get_audio_x_zoom(vtt);
740 if ((eventScroll->direction == GDK_SCROLL_UP) || (eventScroll->direction == GDK_SCROLL_RIGHT)) {
742 } else if ((eventScroll->direction == GDK_SCROLL_DOWN) || (eventScroll->direction == GDK_SCROLL_LEFT)) {
745 gui_set_audio_x_zoom(vtt, zoom);
749 #define connect_entry(wid, func); g_signal_connect(G_OBJECT(g->wid), "activate", G_CALLBACK(func), (void *) vtt);
750 #define connect_adj(wid, func); g_signal_connect(G_OBJECT(g->wid), "value_changed", G_CALLBACK(func), (void *) vtt);
751 #define connect_button(wid, func); g_signal_connect(G_OBJECT(g->wid), "clicked", G_CALLBACK(func), (void *) vtt);
752 #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);
753 #define connect_scale_format(wid, func); g_signal_connect(G_OBJECT(g->wid), "format-value", G_CALLBACK(func), (void *) vtt);
754 #define connect_press_button(wid, func); g_signal_connect(G_OBJECT(g->wid), "button_press_event", G_CALLBACK(func), (void *) vtt);
755 #define connect_rel_button(wid, func); g_signal_connect(G_OBJECT(g->wid), "released", G_CALLBACK(func), (void *) vtt);
759 void gui_connect_signals(vtt_class *vtt)
761 vtt_gui *g=&vtt->gui;
762 strncpy(dnd_uri, "text/uri-list", 128);
764 connect_entry(name, name_changed);
765 connect_adj(volume, volume_changed);
766 connect_adj(pitch, pitch_changed);
767 connect_adj(pan, pan_changed);
768 connect_press_button(file, vg_file_button_pressed);
770 connect_button(del, delete_vtt);
771 connect_button(trigger, trigger_vtt);
772 connect_button(stop, stop_vtt);
773 connect_button(autotrigger, autotrigger_toggled);
774 connect_button(loop, loop_toggled);
775 connect_button(sync_master, master_setup);
776 connect_button(sync_client, client_setup);
777 connect_button(adjust_button, vg_adjust_pitch_vtt);
778 connect_adj(cycles, client_setup_number);
779 connect_press_button(fx_button, fx_button_pressed);
780 connect_press_button(stereo_fx_button, stereo_fx_button_pressed);
782 connect_button(lp_enable, lp_enabled);
783 connect_adj(lp_gain, lp_gain_changed);
784 connect_adj(lp_reso, lp_reso_changed);
785 connect_adj(lp_freq, lp_freq_changed);
787 connect_button(ec_enable, ec_enabled);
788 #ifdef USE_ALSA_MIDI_IN
789 connect_button(midi_mapping, midi_mapping_clicked);
791 connect_adj(ec_length, ec_length_changed);
792 connect_adj(ec_feedback, ec_feedback_changed);
793 connect_adj(ec_pan, ec_pan_changed);
794 connect_adj(ec_volume, ec_volume_changed);
795 connect_range(zoom, vg_adjust_zoom);
796 //connect_scale_format(zoom, vg_format_zoom);
797 connect_press_button(mouse_mapping, vg_mouse_mapping_pressed);
798 connect_button(control_minimize, minimize_control_panel);
799 connect_button(audio_minimize, minimize_audio_panel);
801 gtk_widget_add_events(GTK_WIDGET(g->display), GDK_SCROLL_MASK);
802 g_signal_connect(G_OBJECT(g->display), "scroll-event", G_CALLBACK(gui_scroll_callback), vtt);
804 static GtkTargetEntry drop_types [] = {
807 static gint n_drop_types = sizeof (drop_types) / sizeof(drop_types[0]);
809 gtk_drag_dest_set (GTK_WIDGET (g->file), (GtkDestDefaults) (GTK_DEST_DEFAULT_MOTION |GTK_DEST_DEFAULT_HIGHLIGHT |GTK_DEST_DEFAULT_DROP),
810 drop_types, n_drop_types,
813 g_signal_connect (G_OBJECT (g->file), "drag_data_received",
814 G_CALLBACK(drop_file), (void *) vtt);
816 gtk_drag_dest_set (GTK_WIDGET (g->display), (GtkDestDefaults) (GTK_DEST_DEFAULT_MOTION |GTK_DEST_DEFAULT_HIGHLIGHT |GTK_DEST_DEFAULT_DROP),
817 drop_types, n_drop_types,
820 g_signal_connect (G_OBJECT (g->display), "drag_data_received",
821 G_CALLBACK(drop_file), (void *) vtt);
825 void build_vtt_gui(vtt_class *vtt)
838 snprintf(g->style_class, sizeof(g->style_class), "%0x", vtt);
840 g->css_provider = gtk_css_provider_new();
845 /* Building Audio Box */
846 g->audio_box=gtk_box_new(GTK_ORIENTATION_VERTICAL,2);
847 gtk_widget_show(g->audio_box);
849 tempbox2=gtk_box_new(GTK_ORIENTATION_HORIZONTAL,2);
850 gtk_widget_show(tempbox2);
851 gtk_box_pack_start(GTK_BOX(g->audio_box), tempbox2, WID_FIX);
853 tempbox=gtk_box_new(GTK_ORIENTATION_HORIZONTAL,2);
854 gtk_box_set_homogeneous(GTK_BOX(tempbox), TRUE);
855 gtk_widget_show(tempbox);
856 gtk_box_pack_start(GTK_BOX(tempbox2), tempbox, WID_DYN);
859 g->audio_minimize=create_top_button(MINIMIZE);
860 gtk_box_pack_end(GTK_BOX(tempbox2), g->audio_minimize, WID_FIX);
861 gtk_widget_show(g->audio_minimize);
863 g->audio_label=gtk_label_new(vtt->name);
864 gtk_style_context_add_class(gtk_widget_get_style_context(tempbox2), g->style_class);
865 gtk_widget_set_halign(g->audio_label, GTK_ALIGN_START);
866 gtk_widget_set_margin_start(g->audio_label, 10);
867 gtk_widget_show(g->audio_label);
868 gtk_box_pack_start(GTK_BOX(tempbox), g->audio_label, WID_DYN);
870 nicer_filename(nice_name, vtt->filename);
871 g->file = gtk_button_new_with_label(nice_name);
872 gtk_style_context_add_class(gtk_widget_get_style_context(g->file), g->style_class);
873 gtk_widget_show(g->file);
874 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.");
875 gtk_box_pack_start(GTK_BOX(tempbox), g->file, WID_DYN);
877 g->mouse_mapping=gtk_button_new_with_label("Mouse");
878 gtk_widget_show(g->mouse_mapping);
879 gui_set_tooltip(g->mouse_mapping, "Determines what parameters should be affected on mouse motion in mouse grab mode.");
880 gtk_style_context_add_class(gtk_widget_get_style_context(g->mouse_mapping), g->style_class);
881 gtk_box_pack_start(GTK_BOX(tempbox2), g->mouse_mapping, WID_FIX);
883 #ifdef USE_ALSA_MIDI_IN
884 g->midi_mapping=gtk_button_new_with_label("MIDI");
885 gtk_widget_show(g->midi_mapping);
886 gui_set_tooltip(g->midi_mapping, "Determines what parameters should be bound to what MIDI events.");
887 gtk_style_context_add_class(gtk_widget_get_style_context(g->midi_mapping), g->style_class);
888 gtk_box_pack_start(GTK_BOX(tempbox2), g->midi_mapping, WID_FIX);
890 if (!tX_engine::get_instance()->get_midi()->get_is_open()) {
891 gtk_widget_set_sensitive(g->midi_mapping, FALSE);
895 tempbox=gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 2);
897 g->display=gtk_tx_new(vtt->buffer, vtt->samples_in_buffer);
898 gtk_box_pack_start(GTK_BOX(tempbox), g->display, WID_DYN);
899 gtk_widget_show(g->display);
901 g->zoom=gtk_scale_new_with_range(GTK_ORIENTATION_VERTICAL, 0,99.0,1.0);
902 gtk_range_set_inverted(GTK_RANGE(g->zoom), TRUE);
903 gtk_scale_set_draw_value(GTK_SCALE(g->zoom), TRUE);
904 gtk_scale_set_digits(GTK_SCALE(g->zoom), 0);
905 gtk_scale_set_value_pos(GTK_SCALE(g->zoom), GTK_POS_BOTTOM);
906 gtk_adjustment_set_value(gtk_range_get_adjustment(GTK_RANGE(g->zoom)), 0);
908 gui_set_tooltip(g->zoom, "Set the zoom-level for the audio data display.");
909 gtk_box_pack_start(GTK_BOX(tempbox), g->zoom, WID_FIX);
910 gtk_widget_show(g->zoom);
912 gtk_box_pack_start(GTK_BOX(g->audio_box), tempbox, WID_DYN);
913 gtk_widget_show(tempbox);
915 /* Building Control Box */
917 g->control_box=gtk_box_new(GTK_ORIENTATION_VERTICAL,2);
918 gtk_widget_show(g->control_box);
920 tempbox2=gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 2);
921 gtk_widget_show(tempbox2);
922 gtk_box_pack_start(GTK_BOX(g->control_box), tempbox2, WID_FIX);
924 g->control_label=gtk_label_new(vtt->name);
925 gtk_style_context_add_class(gtk_widget_get_style_context(tempbox2), g->style_class);
926 gtk_widget_show(g->control_label);
927 gtk_box_pack_start(GTK_BOX(tempbox2), g->control_label, WID_DYN);
929 g->control_minimize=create_top_button(MINIMIZE);
930 gtk_box_pack_end(GTK_BOX(tempbox2), g->control_minimize, WID_FIX);
931 gtk_widget_show(g->control_minimize);
933 g->scrolled_win=gtk_scrolled_window_new (NULL, NULL);
934 gtk_container_set_border_width (GTK_CONTAINER (g->scrolled_win), 0);
935 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (g->scrolled_win),
936 GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
937 gtk_widget_show(g->scrolled_win);
938 gtk_box_pack_start(GTK_BOX(g->control_box), g->scrolled_win, WID_DYN);
940 g->control_subbox=gtk_box_new(GTK_ORIENTATION_VERTICAL,0);
941 #if GTK_CHECK_VERSION(3,8,0)
942 gtk_container_add(GTK_CONTAINER(g->scrolled_win), g->control_subbox);
944 gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(g->scrolled_win), g->control_subbox);
946 gtk_widget_show(g->control_subbox);
948 g->static_box = gtk_list_box_new();
949 gtk_list_box_set_selection_mode (GTK_LIST_BOX (g->static_box), GTK_SELECTION_NONE);
950 gtk_widget_show(g->static_box);
951 gtk_container_add(GTK_CONTAINER(g->control_subbox), g->static_box);
955 tX_panel *p=new tX_panel("Main", g->control_subbox);
958 GtkWidget *mainbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
959 g->name = gtk_entry_new();
960 gtk_entry_set_max_length(GTK_ENTRY(g->name), 256);
961 gtk_entry_set_text(GTK_ENTRY(g->name), vtt->name);
962 gtk_entry_set_width_chars(GTK_ENTRY(g->name), 10);
963 gtk_entry_set_max_width_chars(GTK_ENTRY(g->name), 10);
964 gtk_container_add_with_properties(GTK_CONTAINER(mainbox), g->name, "expand", TRUE, NULL);
965 g->color_button = gtk_color_button_new();
966 gtk_color_chooser_set_use_alpha(GTK_COLOR_CHOOSER(g->color_button), FALSE);
967 gui_set_color(vtt, vtt->get_color());
968 g_signal_connect(G_OBJECT(g->color_button), "color_set", (GCallback) gui_color_set , vtt);
970 gtk_button_set_relief(GTK_BUTTON(g->color_button), GTK_RELIEF_NONE);
971 gtk_container_add(GTK_CONTAINER(mainbox), g->color_button);
972 gtk_widget_show(g->color_button);
973 gtk_widget_show(g->name);
975 p->add_client_widget(mainbox);
976 gui_set_tooltip(g->name, "Enter the turntable's name here.");
977 //gtk_widget_set_size_request(g->name, 40, -1);
979 g->del=gtk_button_new_with_label("Delete");
980 gui_set_tooltip(g->del, "Click here to annihilate this turntable. All events recorded for this turntable will be erased, too.");
981 p->add_client_widget(g->del);
983 g->adjust_button=gtk_button_new_with_label("Pitch Adj.");
984 gui_set_tooltip(g->adjust_button, "Activate this button to adjust this turntable's speed to the master turntable's speed.");
985 p->add_client_widget(g->adjust_button);
987 gtk_list_box_insert(GTK_LIST_BOX(g->static_box), p->get_list_box_row(), -1);
989 p=new tX_panel("Playback", g->control_subbox);
992 g->trigger=gtk_button_new_with_label("Trigger");
993 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.");
994 p->add_client_widget(g->trigger);
996 g->stop=gtk_button_new_with_label("Stop");
997 gui_set_tooltip(g->stop, "Stop this turntable's playback.");
998 p->add_client_widget(g->stop);
999 g_signal_connect(G_OBJECT(g->trigger), "button_press_event", (GCallback) tX_seqpar::tX_seqpar_press, &vtt->sp_trigger);
1000 g_signal_connect(G_OBJECT(g->stop), "button_press_event", (GCallback) tX_seqpar::tX_seqpar_press, &vtt->sp_trigger);
1002 g->autotrigger=gtk_check_button_new_with_label("Auto");
1003 p->add_client_widget(g->autotrigger);
1004 gui_set_tooltip(g->autotrigger, "If turned on, this turntable will be automagically triggered whenever the audio engine is turned on.");
1005 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(g->autotrigger), vtt->autotrigger);
1007 g->loop=gtk_check_button_new_with_label("Loop");
1008 p->add_client_widget(g->loop);
1009 gui_set_tooltip(g->loop, "Enable this option to make the turntable loop the audio data.");
1010 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(g->loop), vtt->loop);
1011 g_signal_connect(G_OBJECT(g->loop), "button_press_event", (GCallback) tX_seqpar::tX_seqpar_press, &vtt->sp_loop);
1013 g->sync_master=gtk_check_button_new_with_label("Master");
1014 p->add_client_widget(g->sync_master);
1015 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.");
1016 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(g->sync_master), vtt->is_sync_master);
1018 g->sync_client=gtk_check_button_new_with_label("Client");
1019 p->add_client_widget(g->sync_client);
1020 gui_set_tooltip(g->sync_client, "If enabled this turntable will be (re-)triggerd in relation to the sync-master turntable.");
1021 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(g->sync_client), vtt->is_sync_client);
1022 g_signal_connect(G_OBJECT(g->sync_client), "button_press_event", (GCallback) tX_seqpar::tX_seqpar_press, &vtt->sp_sync_client);
1024 g->cycles=GTK_ADJUSTMENT(gtk_adjustment_new(vtt->sync_cycles, 0, 10.0, 1,1,0));
1025 dummy=gtk_spin_button_new(g->cycles, 1.0, 0);
1026 p->add_client_widget(dummy);
1027 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.");
1028 g_signal_connect(G_OBJECT(dummy), "button_press_event", (GCallback) tX_seqpar::tX_seqpar_press, &vtt->sp_sync_cycles);
1030 gtk_list_box_insert(GTK_LIST_BOX(g->static_box), p->get_list_box_row(), -1);
1032 dummy=gtk_header_bar_new();
1033 gtk_header_bar_set_title(GTK_HEADER_BAR(dummy), "FX");
1034 gtk_header_bar_set_has_subtitle(GTK_HEADER_BAR(dummy), FALSE);
1035 gtk_widget_show(dummy);
1036 g->fx_button=create_top_button(ADD_ITEM);
1037 gtk_header_bar_pack_end(GTK_HEADER_BAR(dummy), g->fx_button);
1038 gtk_widget_show(g->fx_button);
1039 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.");
1040 gtk_box_pack_start(GTK_BOX(g->control_subbox), dummy, WID_FIX);
1042 g->fx_box = gtk_list_box_new();
1043 gtk_list_box_set_selection_mode (GTK_LIST_BOX (g->fx_box), GTK_SELECTION_NONE);
1044 gtk_box_pack_start(GTK_BOX(g->control_subbox), g->fx_box, WID_FIX);
1045 gtk_widget_show(g->fx_box);
1049 p=new tX_panel("Lowpass", g->control_subbox, NULL, vtt->get_lp_effect());
1052 g->lp_enable=gtk_check_button_new_with_label("Enable");
1053 gui_set_tooltip(g->lp_enable, "Click here to enable the built-in lowpass effect.");
1054 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(g->lp_enable), vtt->lp_enable);
1055 g_signal_connect(G_OBJECT(g->lp_enable), "button_press_event", (GCallback) tX_seqpar::tX_seqpar_press, &vtt->sp_lp_enable);
1057 p->add_client_widget(g->lp_enable);
1059 g->lp_gain=GTK_ADJUSTMENT(gtk_adjustment_new(vtt->lp_gain, 0, 2, 0.1, 0.01, 0.01));
1060 g->lp_reso=GTK_ADJUSTMENT(gtk_adjustment_new(vtt->lp_reso, 0, 0.99, 0.1, 0.01, 0.01));
1061 g->lp_freq=GTK_ADJUSTMENT(gtk_adjustment_new(vtt->lp_freq, 0, 1, 0.1, 0.01, 0.01));
1063 g->lp_gaind=new tX_extdial("Input Gain", g->lp_gain, &vtt->sp_lp_gain);
1064 p->add_client_widget(g->lp_gaind->get_widget());
1065 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.");
1067 g->lp_freqd=new tX_extdial("Frequency", g->lp_freq, &vtt->sp_lp_freq);
1068 p->add_client_widget(g->lp_freqd->get_widget());
1069 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.");
1071 g->lp_resod=new tX_extdial("Resonance", g->lp_reso, &vtt->sp_lp_reso);
1072 p->add_client_widget(g->lp_resod->get_widget());
1073 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.");
1075 gtk_list_box_insert(GTK_LIST_BOX(g->fx_box), p->get_list_box_row(), -1);
1079 p=new tX_panel("Echo", g->control_subbox, NULL, vtt->get_ec_effect());
1082 g->ec_enable=gtk_check_button_new_with_label("Enable");
1083 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(g->ec_enable), vtt->ec_enable);
1084 p->add_client_widget(g->ec_enable);
1085 gui_set_tooltip(g->ec_enable, "Enable the built-in echo effect.");
1086 g_signal_connect(G_OBJECT(g->ec_enable), "button_press_event", (GCallback) tX_seqpar::tX_seqpar_press, &vtt->sp_ec_enable);
1088 g->ec_length=GTK_ADJUSTMENT(gtk_adjustment_new(vtt->ec_length, 0, 1, 0.1, 0.01, 0.001));
1089 g->ec_feedback=GTK_ADJUSTMENT(gtk_adjustment_new(vtt->ec_feedback, 0, 1, 0.1, 0.01, 0.001));
1090 g->ec_pan=GTK_ADJUSTMENT(gtk_adjustment_new(vtt->ec_pan, -1.0, 1, 0.1, 0.01, 0.001));
1091 g->ec_volume=GTK_ADJUSTMENT(gtk_adjustment_new(vtt->ec_volume, 0.0, 3.0, 0.1, 0.01, 0.001));
1093 g->ec_lengthd=new tX_extdial("Duration", g->ec_length, &vtt->sp_ec_length);
1094 p->add_client_widget(g->ec_lengthd->get_widget());
1095 gui_set_tooltip(g->ec_lengthd->get_entry(), "Adjust the length of the echo buffer.");
1097 g->ec_feedbackd=new tX_extdial("Feedback", g->ec_feedback, &vtt->sp_ec_feedback);
1098 p->add_client_widget(g->ec_feedbackd->get_widget());
1099 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.");
1101 g->ec_volumed=new tX_extdial("Volume", g->ec_volume, &vtt->sp_ec_volume);
1102 p->add_client_widget(g->ec_volumed->get_widget());
1103 gui_set_tooltip(g->ec_volumed->get_entry(), "Adjust the volume of the echo effect.");
1105 g->ec_pand=new tX_extdial("Pan", g->ec_pan, &vtt->sp_ec_pan);
1106 p->add_client_widget(g->ec_pand->get_widget());
1107 gui_set_tooltip(g->ec_pand->get_entry(), "Adjust the panning of the echo effect.");
1109 gtk_list_box_insert(GTK_LIST_BOX(g->fx_box), p->get_list_box_row(), -1);
1111 dummy=gtk_header_bar_new();
1112 gtk_header_bar_set_title(GTK_HEADER_BAR(dummy), "Stereo FX");
1113 gtk_header_bar_set_has_subtitle(GTK_HEADER_BAR(dummy), FALSE);
1114 gtk_widget_show(dummy);
1115 g->stereo_fx_button=create_top_button(ADD_ITEM);
1116 gtk_header_bar_pack_end(GTK_HEADER_BAR(dummy), g->stereo_fx_button);
1117 gtk_widget_show(g->stereo_fx_button);
1118 gtk_box_pack_start(GTK_BOX(g->control_subbox), dummy, WID_FIX);
1120 g->stereo_fx_box = gtk_list_box_new();
1121 gtk_list_box_set_selection_mode (GTK_LIST_BOX (g->stereo_fx_box), GTK_SELECTION_NONE);
1122 gtk_box_pack_start(GTK_BOX(g->control_subbox), g->stereo_fx_box, WID_FIX);
1123 gtk_widget_show(g->stereo_fx_box);
1127 tempbox=gtk_box_new(GTK_ORIENTATION_HORIZONTAL,2);
1128 gtk_widget_show(tempbox);
1129 gtk_box_pack_end(GTK_BOX(g->control_box), tempbox, WID_FIX);
1131 tempbox2=gtk_box_new(GTK_ORIENTATION_VERTICAL,0);
1132 gtk_widget_show(tempbox2);
1133 gtk_box_pack_start(GTK_BOX(tempbox), tempbox2, WID_FIX);
1135 g->pitch=GTK_ADJUSTMENT(gtk_adjustment_new(vtt->rel_pitch, -3, +3, 0.1, 0.01, 0.001));
1136 g->pan=GTK_ADJUSTMENT(gtk_adjustment_new(0, -1, 1, 0.1, 0.01, 0.001));
1138 g->pitchd=new tX_extdial("Pitch", g->pitch, &vtt->sp_pitch);
1139 gui_set_tooltip(g->pitchd->get_entry(), "Adjust this turntable's pitch.");
1141 gtk_box_pack_start(GTK_BOX(tempbox2), g->pitchd->get_widget(), WID_FIX);
1143 g->pand=new tX_extdial("Pan", g->pan, &vtt->sp_pan);
1144 gtk_box_pack_start(GTK_BOX(tempbox2), g->pand->get_widget(), WID_FIX);
1145 gui_set_tooltip(g->pand->get_entry(), "Specifies the position of this turntable within the stereo spectrum: -1 -> left, 0-> center, 1->right.");
1147 tempbox3=gtk_box_new(GTK_ORIENTATION_HORIZONTAL,2);
1148 gtk_widget_show(tempbox3);
1150 g->mute=gtk_check_button_new_with_label("M");
1151 gtk_box_pack_start(GTK_BOX(tempbox3), g->mute, WID_FIX);
1152 g_signal_connect(G_OBJECT(g->mute),"clicked", (GCallback) mute_volume, vtt);
1153 gtk_widget_show(g->mute);
1154 gui_set_tooltip(g->mute, "Mute this turntable's mixer output.");
1156 g->solo=gtk_check_button_new_with_label("S");
1157 gtk_box_pack_start(GTK_BOX(tempbox3), g->solo, WID_FIX);
1158 g_signal_connect(G_OBJECT(g->solo),"clicked", (GCallback) solo_vtt, vtt);
1159 gtk_widget_show(g->solo);
1160 gui_set_tooltip(g->solo, "Allow only this and other solo-switched turntabels' signal to be routed to the mixer.");
1162 gtk_box_pack_start(GTK_BOX(tempbox2), tempbox3, WID_FIX);
1164 tempbox2=gtk_box_new(GTK_ORIENTATION_HORIZONTAL,0);
1165 gtk_widget_show(tempbox2);
1166 gtk_box_pack_start(GTK_BOX(tempbox), tempbox2, WID_FIX);
1168 g->volume=GTK_ADJUSTMENT(gtk_adjustment_new(2.0-vtt->rel_volume, 0, 2, 0.01, 0.01, 0.01));
1169 dummy=gtk_scale_new(GTK_ORIENTATION_VERTICAL, GTK_ADJUSTMENT(g->volume));
1170 gtk_scale_set_draw_value(GTK_SCALE(dummy), FALSE);
1171 gui_set_tooltip(dummy, "Adjust this turntable's volume.");
1172 g_signal_connect(G_OBJECT(dummy), "button_press_event", (GCallback) tX_seqpar::tX_seqpar_press, &vtt->sp_volume);
1174 gtk_box_pack_start(GTK_BOX(tempbox2), dummy, WID_FIX);
1175 gtk_widget_show(dummy);
1177 g->flash=gtk_tx_flash_new();
1178 gtk_box_pack_start(GTK_BOX(tempbox2), g->flash, WID_FIX);
1179 gtk_widget_show(g->flash);
1181 gui_connect_signals(vtt);
1183 g->audio_minimized_panel_bar_button=NULL;
1184 g->control_minimized_panel_bar_button=NULL;
1186 g->mouse_mapping_menu=NULL;
1187 g->mouse_mapping_menu_x=NULL;
1188 g->mouse_mapping_menu_y=NULL;
1190 g->adjust_dialog=NULL;
1192 gui_set_name(vtt, vtt->name);
1195 void fx_up(GtkWidget *wid, vtt_fx *effect)
1199 vtt=(vtt_class*)effect->get_vtt();
1200 vtt->effect_up(effect);
1203 void fx_down(GtkWidget *wid, vtt_fx *effect)
1207 vtt=(vtt_class*)effect->get_vtt();
1208 vtt->effect_down(effect);
1211 void fx_kill(GtkWidget *wid, vtt_fx_ladspa *effect)
1215 vtt=(vtt_class*)effect->get_vtt();
1216 vtt->effect_remove(effect);
1219 int gtk_box_get_widget_pos(GtkBox *box, GtkWidget *child)
1224 list = gtk_container_get_children(GTK_CONTAINER(box));
1227 GtkWidget *child_widget = (GtkWidget *) list->data;
1228 if (child_widget == child)
1230 list = list->next; i++;
1235 void vg_move_fx_panel_up(tX_panel *panel, vtt_class *vtt, bool stereo)
1237 GtkWidget *list_box=(stereo ? vtt->gui.stereo_fx_box : vtt->gui.fx_box);
1238 GtkWidget *row=panel->get_list_box_row();
1240 int pos=gtk_list_box_row_get_index(GTK_LIST_BOX_ROW(row));
1242 gtk_container_remove(GTK_CONTAINER(list_box), row);
1243 gtk_list_box_insert(GTK_LIST_BOX(list_box), row, pos-1);
1244 g_object_unref(row);
1247 void vg_move_fx_panel_down(tX_panel *panel, vtt_class *vtt, bool stereo)
1249 GtkWidget *list_box=(stereo ? vtt->gui.stereo_fx_box : vtt->gui.fx_box);
1250 GtkWidget *row=panel->get_list_box_row();
1252 int pos=gtk_list_box_row_get_index(GTK_LIST_BOX_ROW(row));
1254 gtk_container_remove(GTK_CONTAINER(list_box), row);
1255 gtk_list_box_insert(GTK_LIST_BOX(list_box), row, pos+1);
1256 g_object_unref(row);
1259 void vg_toggle_drywet(GtkWidget *wid, vtt_fx *effect)
1261 tX_panel *panel = effect->get_panel();
1262 effect->toggle_drywet();
1264 if (effect->has_drywet_feature() == DRYWET_ACTIVE) {
1265 gtk_widget_hide(panel->get_add_drywet_button());
1266 gtk_widget_show(panel->get_remove_drywet_button());
1268 gtk_widget_show(panel->get_add_drywet_button());
1269 gtk_widget_hide(panel->get_remove_drywet_button());
1273 void vg_create_fx_gui(vtt_class *vtt, vtt_fx_ladspa *effect, LADSPA_Plugin *plugin)
1280 list <tX_seqpar_vttfx *> :: iterator sp;
1282 strcpy(buffer, plugin->getName());
1283 if (strlen(buffer) > 8) {
1290 p=new tX_panel(buffer, g->control_subbox, G_CALLBACK(fx_kill), effect);
1292 for (sp = effect->controls.begin(); sp != effect->controls.end(); sp++) {
1293 if ((strcmp((*sp)->get_label_name(), "Enable") == 0) && ((effect->has_drywet_feature() != NOT_DRYWET_CAPABLE))) {
1294 GtkWidget *box=gtk_box_new(GTK_ORIENTATION_HORIZONTAL,0);
1295 gtk_container_add_with_properties(GTK_CONTAINER(box), (*sp)->get_widget(), "expand", TRUE, NULL);
1296 gtk_widget_show((*sp)->get_widget());
1298 g_signal_connect(G_OBJECT(p->get_add_drywet_button()), "clicked", G_CALLBACK(vg_toggle_drywet), effect);
1299 gtk_widget_set_tooltip_text(p->get_add_drywet_button(), "Click to add Dry/Wet controls for this effect.");
1300 gtk_container_add(GTK_CONTAINER(box), p->get_add_drywet_button());
1301 if (effect->has_drywet_feature() == DRYWET_AVAILABLE) {
1302 gtk_widget_show(p->get_add_drywet_button());
1305 g_signal_connect(G_OBJECT(p->get_remove_drywet_button()), "clicked", G_CALLBACK(vg_toggle_drywet), effect);
1306 gtk_widget_set_tooltip_text(p->get_remove_drywet_button(), "Click to remove Dry/Wet controls for this effect.");
1307 gtk_container_add(GTK_CONTAINER(box), p->get_remove_drywet_button());
1308 if (effect->has_drywet_feature() == DRYWET_ACTIVE) {
1309 gtk_widget_show(p->get_remove_drywet_button());
1312 p->add_client_widget(box);
1314 p->add_client_widget((*sp)->get_widget());
1318 effect->set_panel_widget(p->get_widget());
1319 effect->set_panel(p);
1321 gtk_list_box_insert(GTK_LIST_BOX(effect->is_stereo() ? g->stereo_fx_box : g->fx_box), p->get_list_box_row(), -1);
1324 void gui_set_filename (vtt_class *vtt, char *newname)
1326 gtk_button_set_label(GTK_BUTTON(vtt->gui.file), newname);
1329 void gui_update_display(vtt_class *vtt)
1331 nicer_filename(global_filename_buffer, vtt->filename);
1332 gtk_button_set_label(GTK_BUTTON(vtt->gui.file), global_filename_buffer);
1333 gtk_tx_set_data(GTK_TX(vtt->gui.display), vtt->buffer, vtt->samples_in_buffer);
1336 void gui_hide_control_panel(vtt_class *vtt, bool hide) {
1340 gtk_widget_hide(vtt->gui.control_box);
1341 vtt->gui.control_minimized_panel_bar_button=tx_xpm_button_new(MIN_CONTROL, vtt->name, 0, &vtt->gui.control_minimized_panel_bar_label);
1342 gtk_style_context_add_class(gtk_widget_get_style_context(vtt->gui.control_minimized_panel_bar_button), vtt->gui.style_class);
1343 g_signal_connect(G_OBJECT(vtt->gui.control_minimized_panel_bar_button), "clicked", (GCallback) unminimize_control_panel, vtt);
1344 gtk_widget_show(vtt->gui.control_minimized_panel_bar_button);
1345 snprintf(tooltip, TOOLTIP_LENGTH, "Show \"%s\" control panel.", vtt->name);
1346 gui_set_tooltip(vtt->gui.control_minimized_panel_bar_button, tooltip);
1347 add_to_panel_bar(vtt->gui.control_minimized_panel_bar_button);
1349 gtk_widget_show(vtt->gui.control_box);
1350 remove_from_panel_bar(vtt->gui.control_minimized_panel_bar_button);
1351 if (!tX_shutdown) gtk_widget_destroy(vtt->gui.control_minimized_panel_bar_button);
1352 vtt->gui.control_minimized_panel_bar_button=NULL;
1356 void gui_hide_audio_panel(vtt_class *vtt, bool hide) {
1360 gtk_widget_hide(vtt->gui.audio_box);
1361 vtt->gui.audio_minimized_panel_bar_button=tx_xpm_button_new(MIN_AUDIO, vtt->name, 0, &vtt->gui.audio_minimized_panel_bar_label);
1362 gtk_style_context_add_class(gtk_widget_get_style_context(vtt->gui.audio_minimized_panel_bar_button), vtt->gui.style_class);
1363 g_signal_connect(G_OBJECT(vtt->gui.audio_minimized_panel_bar_button), "clicked", (GCallback) unminimize_audio_panel, vtt);
1364 gtk_widget_show(vtt->gui.audio_minimized_panel_bar_button);
1365 snprintf(tooltip, TOOLTIP_LENGTH, "Show \"%s\" audio panel.", vtt->name);
1366 gui_set_tooltip(vtt->gui.audio_minimized_panel_bar_button, tooltip);
1367 add_to_panel_bar(vtt->gui.audio_minimized_panel_bar_button);
1369 gtk_widget_show(vtt->gui.audio_box);
1370 remove_from_panel_bar(vtt->gui.audio_minimized_panel_bar_button);
1371 if (!tX_shutdown) gtk_widget_destroy(vtt->gui.audio_minimized_panel_bar_button);
1372 vtt->gui.audio_minimized_panel_bar_button=NULL;
1376 void delete_gui(vtt_class *vtt)
1378 if (vtt->gui.control_minimized_panel_bar_button!=NULL) gui_hide_control_panel(vtt, false);
1379 if (vtt->gui.audio_minimized_panel_bar_button!=NULL) gui_hide_audio_panel(vtt, false);
1381 delete vtt->gui.main_panel;
1382 delete vtt->gui.trigger_panel;
1384 delete vtt->gui.pitchd;
1385 delete vtt->gui.pand;
1387 delete vtt->gui.lp_gaind;
1388 delete vtt->gui.lp_resod;
1389 delete vtt->gui.lp_freqd;
1390 delete vtt->gui.lp_panel;
1392 delete vtt->gui.ec_lengthd;
1393 delete vtt->gui.ec_feedbackd;
1394 delete vtt->gui.ec_volumed;
1395 delete vtt->gui.ec_pand;
1396 delete vtt->gui.ec_panel;
1398 gtk_widget_destroy(vtt->gui.control_box);
1399 gtk_widget_destroy(vtt->gui.audio_box);
1400 if (vtt->gui.file_menu) gtk_widget_destroy(vtt->gui.file_menu);
1401 if (vtt->gui.mouse_mapping_menu) gtk_widget_destroy(vtt->gui.mouse_mapping_menu);
1402 if (vtt->gui.ladspa_menu) gtk_widget_destroy(vtt->gui.ladspa_menu);
1404 gtk_style_context_remove_provider_for_screen(gdk_screen_get_default(), GTK_STYLE_PROVIDER(vtt->gui.css_provider));
1407 void cleanup_vtt(vtt_class *vtt)
1409 gtk_tx_cleanup_pos_display(GTK_TX(vtt->gui.display));
1410 gtk_tx_flash_set_level(vtt->gui.flash, 0.0, 0.0);
1411 gtk_tx_flash_clear(vtt->gui.flash);
1412 vtt->cleanup_required=false;
1415 void update_all_vtts()
1417 list <vtt_class *> :: iterator vtt;
1420 for (vtt=vtt_class::main_list.begin(); vtt!=vtt_class::main_list.end(); vtt++)
1422 if ((*vtt)->is_playing) {
1423 gtk_tx_update_pos_display(GTK_TX((*vtt)->gui.display), (*vtt)->pos_i, (*vtt)->mute);
1424 temp=(*vtt)->max_value*(*vtt)->res_volume*vtt_class::vol_channel_adjust;
1425 temp2=(*vtt)->max_value2*(*vtt)->res_volume*vtt_class::vol_channel_adjust;
1426 // tX_msg("Setting value: %f, %f -> %f; %f, %f -> %f (%f)\n",
1427 // (*vtt)->max_value, (*vtt)->res_volume, temp,
1428 // (*vtt)->max_value2, (*vtt)->res_volume, temp2,
1429 // vtt_class::vol_channel_adjust
1431 gtk_tx_flash_set_level((*vtt)->gui.flash, temp, temp2);
1433 (*vtt)->max_value=0;
1434 (*vtt)->max_value2=0;
1437 if ((*vtt)->needs_cleaning_up()) {
1438 cleanup_vtt((*vtt));
1443 void cleanup_all_vtts()
1445 list <vtt_class *> :: iterator vtt;
1447 for (vtt=vtt_class::main_list.begin(); vtt!=vtt_class::main_list.end(); vtt++)
1449 if ((*vtt)->buffer) gtk_tx_cleanup_pos_display(GTK_TX((*vtt)->gui.display));
1450 gtk_tx_flash_set_level((*vtt)->gui.flash, 0.0, 0.0);
1451 gtk_tx_flash_clear((*vtt)->gui.flash);
1455 void gui_clear_master_button(vtt_class *vtt)
1457 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(vtt->gui.sync_master), 0);
1460 void gui_show_focus(vtt_class *vtt, int show)
1462 gtk_tx_show_focus(GTK_TX(vtt->gui.display), show);
1465 #define vgui (*vtt)->gui
1468 void vg_enable_critical_buttons(int enable)
1470 list <vtt_class *> :: iterator vtt;
1471 for (vtt=vtt_class::main_list.begin(); vtt!=vtt_class::main_list.end(); vtt++)
1473 gtk_widget_set_sensitive(vgui.del, enable);
1474 gtk_widget_set_sensitive(vgui.sync_master, enable);
1478 void vg_init_all_non_seqpars()
1480 list <vtt_class *> :: iterator vtt;
1482 for (vtt=vtt_class::main_list.begin(); vtt!=vtt_class::main_list.end(); vtt++)
1484 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON((*vtt)->gui.autotrigger), (*vtt)->autotrigger);
1485 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON((*vtt)->gui.sync_master), (*vtt)->is_sync_master);