2 terminatorX - realtime audio scratching software
3 Copyright (C) 1999 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, write to the Free Software
17 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 Description: Contains the implementation of the Options and About
22 Dialogs. (And some really ugly "WE WANT TO
27 28 Jul 1999: Now display compiletime settings in the about dialog.
31 #include "tX_global.h"
32 #include "tX_dialog.h"
38 #include <X11/extensions/XInput.h>
43 #include "tX_wavfunc.h"
44 #include "tX_mastergui.h"
47 extern char *logo_xpm[];
49 GdkWindow *opt_window=NULL;
50 GtkWidget *opt_dialog;
54 GtkWidget *reset_filectr;
55 GtkWidget *audio_device;
56 GtkWidget *use_stdout;
59 GtkAdjustment *buff_no=NULL;
60 GtkWidget *buff_no_slider;
61 GtkAdjustment *buff_size=NULL;
62 GtkWidget *buff_size_slider;
64 GtkAdjustment *rec_size;
65 GtkWidget *rec_size_slider;
67 GtkAdjustment *sense_cycles=NULL;
68 GtkWidget *sense_cycles_slider;
70 GtkAdjustment *vtt_default_speed=NULL;
71 GtkWidget *vtt_default_speed_slider;
73 GtkWidget *xinput_enable;
74 GtkWidget *xinput_device;
75 GtkAdjustment *mouse_speed=NULL;
76 GtkWidget *mouse_speed_slider;
81 GtkAdjustment *update_idle=NULL;
82 GtkWidget *update_idle_slider;
84 GtkWidget *time_enable;
85 GtkAdjustment *time_update=NULL;
86 GtkWidget *time_update_slider;
90 GtkWidget *opt_cancel;
92 GtkTooltips *opt_tips;
100 strcpy(globals.prefix, gtk_entry_get_text(GTK_ENTRY(prefix)));
101 globals.reset_filectr=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(reset_filectr));
103 strcpy(globals.audio_device, gtk_entry_get_text(GTK_ENTRY(audio_device)));
104 globals.use_stdout=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(use_stdout));
105 globals.buff_no=(int)buff_no->value;
106 globals.buff_size=(int)buff_size->value;
108 globals.prelis=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(prelis));
110 globals.rec_size=(int)rec_size->value*1024;
111 if (malloc_recbuffer()) tx_note("Error: Failed to allocate recbuffer.");
113 globals.sense_cycles=(int) sense_cycles->value;
114 globals.vtt_default_speed=vtt_default_speed->value;
115 globals.xinput_enable=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(xinput_enable));
116 gtk_label_get(GTK_LABEL(GTK_BUTTON(xinput_device)->child), &text);
117 strcpy(globals.xinput_device, text);
118 globals.use_y=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(use_y));
120 globals.mouse_speed=mouse_speed->value;
121 globals.tooltips=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(tooltips));
122 globals.show_nag=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(show_nag));
123 globals.update_idle=(int) update_idle->value;
125 globals.time_enable=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(time_enable));
126 globals.time_update=(int)time_update->value;
129 #define WID_DYN TRUE, TRUE, 0
130 #define WID_FIX FALSE, FALSE, 0
132 #define my_new_subsec(s); \
133 separator=gtk_hseparator_new(); \
134 gtk_box_pack_start(GTK_BOX(vbox), separator, WID_DYN);\
135 gtk_widget_show(separator); \
136 label=gtk_label_new(s); \
137 gtk_misc_set_alignment (GTK_MISC(label), 0 ,0.5); \
138 gtk_box_pack_start(GTK_BOX(vbox), label, WID_DYN); \
139 gtk_widget_show(label);
141 #define my_new_button(btn, s); \
142 btn=gtk_button_new_with_label(s); \
143 gtk_box_pack_start(GTK_BOX(aa), btn, WID_DYN); \
144 gtk_widget_show(btn);
147 #define begin_box(); box=gtk_hbox_new(FALSE, 5);
149 #define begin_hom_box(); box=gtk_hbox_new(TRUE, 5);
151 #define end_box(); gtk_box_pack_start(GTK_BOX(vbox), box, WID_DYN); \
152 gtk_widget_show(box);
154 #define add_widget_dyn(wid); gtk_box_pack_start(GTK_BOX(box), wid, WID_DYN);\
155 gtk_widget_show(wid);
157 #define add_widget_fix(wid); gtk_box_pack_start(GTK_BOX(box), wid, WID_FIX);\
158 gtk_widget_show(wid);
160 #define add_expl(s); label=gtk_label_new(s); \
161 gtk_misc_set_alignment(GTK_MISC(label), 0.5, 0.5);\
162 add_widget_fix(label);
164 #define add_expl_dyn(s); label=gtk_label_new(s); \
165 gtk_misc_set_alignment(GTK_MISC(label), 0.5, 0.5);\
166 add_widget_dyn(label);
168 static gint showdevmenu(GtkWidget *widget, GdkEvent *event)
170 if (event->type == GDK_BUTTON_PRESS) {
171 GdkEventButton *bevent = (GdkEventButton *) event;
172 gtk_menu_popup (GTK_MENU (widget), NULL, NULL, NULL, NULL,
173 bevent->button, bevent->time);
181 XDeviceInfo *xdev=NULL;
184 void options_destroy(GtkWidget *widget)
186 /* Destroying everything that is NOT a direct part of
187 the dialog: adjustments, menu and XDeviceList.
190 gdk_window_hide(opt_window);
193 gtk_object_destroy(GTK_OBJECT(opt_dialog));
196 XFreeDeviceList(xdev);
201 void ok_options(GtkWidget *widget)
204 options_destroy(widget);
207 void select_input(GtkWidget *w, char *dev)
209 gtk_label_set(GTK_LABEL(GTK_BUTTON(xinput_device)->child), dev);
212 void create_options()
218 GtkWidget *separator;
225 opt_dialog=gtk_dialog_new();
226 w=&(GTK_DIALOG(opt_dialog)->window);
227 gtk_window_set_title(w, "terminatorX - Options");
229 opt_tips=gtk_tooltips_new();
231 vbox=GTK_WIDGET(GTK_DIALOG(opt_dialog)->vbox);
232 gtk_box_set_spacing(GTK_BOX(vbox), 5);
233 gtk_container_set_border_width(GTK_CONTAINER(w), 5);
234 // gtk_box_set_homogeneous(GTK_BOX(vbox), FALSE);
235 aa=GTK_WIDGET(GTK_DIALOG(opt_dialog)->action_area);
236 gtk_box_set_spacing(GTK_BOX(aa), 5);
237 // gtk_box_set_homogeneous(GTK_BOX(aa), FALSE);
239 label=gtk_label_new("Options:");
240 gtk_misc_set_alignment (GTK_MISC(label), 0.5 ,0.5);
241 gtk_box_pack_start(GTK_BOX(vbox), label, WID_DYN);
242 gtk_widget_show(label);
244 my_new_subsec("[ Audio: ]");
250 audio_device=gtk_entry_new_with_max_length(PATH_MAX);
251 gtk_entry_set_text(GTK_ENTRY(audio_device), globals.audio_device);
252 gtk_tooltips_set_tip(opt_tips, audio_device, "Enter the path to your audio device here. For most systems this should be /dev/dsp.", NULL);
253 add_widget_dyn(audio_device);
258 use_stdout=gtk_check_button_new_with_label("Use standard output instead of the above device");
259 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(use_stdout), globals.use_stdout);
260 add_widget_fix(use_stdout);
265 add_expl("No. of Buffers:");
267 buff_no=(GtkAdjustment*) gtk_adjustment_new(globals.buff_no, 1, 16, 1, 1, 1);
268 buff_no_slider=gtk_hscale_new(buff_no);
269 gtk_scale_set_digits(GTK_SCALE(buff_no_slider), 0);
270 gtk_scale_set_value_pos(GTK_SCALE(buff_no_slider), GTK_POS_LEFT);
271 gtk_tooltips_set_tip(opt_tips, buff_no_slider, "Sets the number of kernel level audio buffers. Actually most systems should run just fine with two.", NULL);
272 add_widget_dyn(buff_no_slider);
278 add_expl("Size of Buffers:");
280 buff_size=(GtkAdjustment*) gtk_adjustment_new(globals.buff_size, 1, 16, 1, 1, 1);
281 buff_size_slider=gtk_hscale_new(buff_size);
282 gtk_scale_set_digits(GTK_SCALE(buff_size_slider), 0);
283 gtk_scale_set_value_pos(GTK_SCALE(buff_size_slider), GTK_POS_LEFT);
284 gtk_tooltips_set_tip(opt_tips, buff_size_slider, "Sets the size of the kernel level audio buffers. On slower systems you might have to increase this value (if you hear \"clicks\"). Lower values mean lower latency though.", NULL);
285 add_widget_dyn(buff_size_slider);
291 add_expl("Turntable Default Speed:");
293 vtt_default_speed=(GtkAdjustment*) gtk_adjustment_new(globals.vtt_default_speed, -2.5, 2.5, 0.1, 0.01, 0.01);
294 vtt_default_speed_slider=gtk_hscale_new(vtt_default_speed);
295 gtk_scale_set_digits(GTK_SCALE(vtt_default_speed_slider), 2);
296 gtk_scale_set_value_pos(GTK_SCALE(vtt_default_speed_slider), GTK_POS_LEFT);
297 gtk_tooltips_set_tip(opt_tips, vtt_default_speed_slider, "Sets the \"motor\" speed of the turntable. 1.0 => real speed, 2.0 => double speed, negative values => play backwards.", NULL);
298 add_widget_dyn(vtt_default_speed_slider);
304 prelis=gtk_check_button_new_with_label("Pre-Listen to audio files in scratch/loop dialog");
305 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(prelis), globals.prelis);
306 add_widget_fix(prelis);
310 my_new_subsec("[ Recording: ]");
314 add_expl("Fast Save Prefix:");
316 prefix=gtk_entry_new_with_max_length(PATH_MAX);
317 gtk_entry_set_text(GTK_ENTRY(prefix), globals.prefix);
318 add_widget_dyn(prefix);
324 reset_filectr=gtk_check_button_new_with_label("Reset the file counter on startup");
325 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(reset_filectr), globals.reset_filectr);
326 add_widget_fix(reset_filectr);
332 add_expl("Record Buffer Size (KB):");
334 rec_size=(GtkAdjustment*) gtk_adjustment_new(globals.rec_size/1024, 100, 50000, 1000, 100, 100);
336 rec_size_slider=gtk_hscale_new(rec_size);
337 gtk_scale_set_digits(GTK_SCALE(rec_size_slider), 0);
338 gtk_scale_set_value_pos(GTK_SCALE(rec_size_slider), GTK_POS_LEFT);
339 gtk_tooltips_set_tip(opt_tips, rec_size_slider, "Sets the size of the buffer that stores recorded scratches. If you want to record longer scratches you need to increase this value.", NULL);
340 add_widget_dyn(rec_size_slider);
344 my_new_subsec("[ Mouse / Input: ]");
347 dpy=XOpenDisplay(NULL);
348 xdev=XListInputDevices(dpy, &devmax);
351 if (menu) gtk_object_destroy(GTK_OBJECT(menu));
353 menu = gtk_menu_new();
355 for (i=0; i<devmax; i++)
357 item = gtk_menu_item_new_with_label(xdev[i].name);
358 gtk_menu_append(GTK_MENU(menu), item);
359 gtk_signal_connect(GTK_OBJECT(item), "activate", GTK_SIGNAL_FUNC(select_input), xdev[i].name);
360 gtk_widget_show(item);
365 xinput_enable=gtk_check_button_new_with_label("XInput Device:");
366 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(xinput_enable), globals.xinput_enable);
367 gtk_tooltips_set_tip(opt_tips, xinput_enable, "Enable this if you want to use other input than your default X-Pointer. You have to select your desired device as well.", NULL);
368 add_widget_fix(xinput_enable);
370 if (strlen(globals.xinput_device)>0)
372 xinput_device=gtk_button_new_with_label(globals.xinput_device);
376 xinput_device=gtk_button_new_with_label("< NONE >");
379 gtk_signal_connect_object (GTK_OBJECT (xinput_device), "event", GTK_SIGNAL_FUNC (showdevmenu), GTK_OBJECT (menu));
380 add_widget_dyn(xinput_device);
388 add_expl("Mouse Speed:");
390 mouse_speed=(GtkAdjustment*) gtk_adjustment_new(globals.mouse_speed, -10, 10, 0.5, 0.1, 0.1);
391 mouse_speed_slider=gtk_hscale_new(mouse_speed);
392 gtk_scale_set_digits(GTK_SCALE(mouse_speed_slider), 1);
393 gtk_scale_set_value_pos(GTK_SCALE(mouse_speed_slider), GTK_POS_LEFT);
394 gtk_tooltips_set_tip(opt_tips, mouse_speed_slider, "The speed of your mouse in scratch mode. Use negative values to invert motion.", NULL);
395 add_widget_dyn(mouse_speed_slider);
401 add_expl("Stop Sense Cycles:");
403 sense_cycles=(GtkAdjustment*) gtk_adjustment_new(globals.sense_cycles, 1, 50, 5, 1, 1);
404 sense_cycles_slider=gtk_hscale_new(sense_cycles);
405 gtk_scale_set_digits(GTK_SCALE(sense_cycles_slider), 0);
406 gtk_scale_set_value_pos(GTK_SCALE(sense_cycles_slider), GTK_POS_LEFT);
407 gtk_tooltips_set_tip(opt_tips, sense_cycles_slider, "If there is no \"motion-event\" for x cycles, where x is the number of cycles you select here, terminatorX assumes mouse motion has stopped. For smaller buffer sizes (=> shorter cycle times) you might have to increase this value", NULL);
408 add_widget_dyn(sense_cycles_slider);
414 use_y=gtk_check_button_new_with_label("Use Y instead of X axis");
415 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(use_y), globals.use_y);
416 add_widget_dyn(use_y);
420 my_new_subsec("[ Graphics / GUI: ]");
424 tooltips=gtk_check_button_new_with_label("Main Window Tooltips");
425 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(tooltips), globals.tooltips);
426 add_widget_dyn(tooltips);
432 add_expl("Pos Update Idle:");
434 update_idle=(GtkAdjustment*) gtk_adjustment_new(globals.update_idle, 1, 100, 1, 10, 10);
435 update_idle_slider=gtk_hscale_new(update_idle);
436 gtk_scale_set_digits(GTK_SCALE(update_idle_slider), 0);
437 gtk_scale_set_value_pos(GTK_SCALE(update_idle_slider), GTK_POS_LEFT);
438 gtk_tooltips_set_tip(opt_tips, update_idle_slider, "The update thread will idle for the selcted amount of milliseconds. If you want to have a more responsive display update increase this value - if you have performance problems reduce this value.", NULL);
439 add_widget_dyn(update_idle_slider);
445 time_enable=gtk_check_button_new_with_label("Time Update:");
446 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(time_enable), globals.time_enable);
447 add_widget_fix(time_enable);
449 time_update=(GtkAdjustment*) gtk_adjustment_new(globals.time_update, 1, 50, 1, 5, 5);
450 time_update_slider=gtk_hscale_new(time_update);
451 gtk_scale_set_digits(GTK_SCALE(time_update_slider), 0);
452 gtk_scale_set_value_pos(GTK_SCALE(time_update_slider), GTK_POS_LEFT);
453 gtk_tooltips_set_tip(opt_tips, time_update_slider, "The update thread will update the time display every n-th position display update, where n is the value you select. If you want to have a more responsive display update increase this value - if you have performance problems reduce this value.", NULL);
454 add_widget_dyn(time_update_slider);
459 show_nag=gtk_check_button_new_with_label("Display nagbox on startup while loading data");
460 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(show_nag), globals.show_nag);
461 add_widget_dyn(show_nag);
466 my_new_button(opt_ok, "Ok");
467 gtk_signal_connect(GTK_OBJECT(opt_ok), "clicked", (GtkSignalFunc) ok_options, NULL);
468 my_new_button(opt_apply, "Apply");
469 gtk_signal_connect(GTK_OBJECT(opt_apply), "clicked", (GtkSignalFunc) apply_options, NULL);
470 my_new_button(opt_cancel, "Cancel");
471 gtk_signal_connect(GTK_OBJECT(opt_cancel), "clicked", (GtkSignalFunc) options_destroy, NULL);
474 gtk_widget_show(opt_dialog);
475 opt_window=opt_dialog->window;
476 gtk_signal_connect(GTK_OBJECT(opt_dialog), "delete-event", (GtkSignalFunc) options_destroy, NULL);
480 void display_options()
484 gdk_window_raise(opt_window);
492 GtkWidget *about=NULL;
497 gdk_window_raise(about->window);
505 gtk_widget_destroy(about);
512 #define add_about_wid(wid); gtk_box_pack_start(GTK_BOX(box), wid, WID_DYN); \
513 gtk_widget_show(wid);
515 GdkFont *GPL_font=NULL;
517 void show_about(int nag)
519 GtkWidget *window, *pwid;
529 GdkPixmap *pmap=NULL;
535 gdk_window_raise(about->window);
539 window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
540 gtk_container_set_border_width(GTK_CONTAINER(window), 5);
542 // GTK_WINDOW(window)->use_uposition=TRUE;
544 gtk_widget_realize(window);
546 gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
547 gtk_window_set_title(GTK_WINDOW(window), "terminatorX - About");
551 gdk_window_set_decorations(window->window, (enum GdkWMDecoration) 0);
555 style = gtk_widget_get_style( window );
559 pmap=gdk_pixmap_create_from_xpm_d(window->window, &mask, &style->bg[GTK_STATE_NORMAL], (gchar **)logo_xpm );
563 pwid = gtk_pixmap_new( pmap, mask );
565 gtk_widget_show( pwid );
569 gtk_container_add(GTK_CONTAINER(window), pwid);
570 gtk_widget_show(window);
572 while (gtk_events_pending()) gtk_main_iteration();
576 box=gtk_vbox_new(FALSE, 5);
579 sep=gtk_hseparator_new();
583 "\nThis is "PACKAGE" Release "VERSION" - Copyright (C) 1999 by Alexander König"
584 "\n\nSend comments, patches and scratches to: alkoit00@fht-esslingen.de\n"
585 "terminatorX-homepage: http://termX.cjb.net\n\nThis binary has been compiled with the following flags: "
592 " - mpg123 support: "
593 #ifdef USE_MPG123_INPUT
598 " - \nenhanced scheduling: "
604 " - keep device open: "
611 #ifdef BIG_ENDIAN_MACHINE
619 gtk_misc_set_alignment (GTK_MISC(label), 0.5 ,0.5);
620 add_about_wid(label);
622 sep=gtk_hseparator_new();
625 label=gtk_label_new("License (GPL V2):");
626 gtk_misc_set_alignment (GTK_MISC(label), 0.5 ,0.5);
627 add_about_wid(label);
629 hbox=gtk_hbox_new(FALSE, 5);
631 text=gtk_text_new(NULL,NULL);
632 scroll=gtk_vscrollbar_new(GTK_TEXT(text)->vadj);
633 gtk_text_set_editable(GTK_TEXT(text),0);
634 gtk_text_set_word_wrap( GTK_TEXT(text), 0);
638 GPL_font=gdk_font_load ("-misc-fixed-medium-r-*-*-*-120-*-*-*-*-*-*");
640 gtk_text_insert(GTK_TEXT(text), GPL_font, NULL, NULL, license, strlen(license));
642 gtk_box_pack_start(GTK_BOX(hbox), text, WID_DYN);
643 gtk_widget_show(text);
645 gtk_box_pack_start(GTK_BOX(hbox), scroll, WID_FIX);
646 gtk_widget_show(scroll);
650 sep=gtk_hseparator_new();
653 btn=gtk_button_new_with_label("Close");
656 gtk_container_add(GTK_CONTAINER(window), box);
657 gtk_widget_show(box);
659 gtk_signal_connect(GTK_OBJECT(btn), "clicked", (GtkSignalFunc) destroy_about, NULL);
660 gtk_signal_connect(GTK_OBJECT(window), "delete-event", (GtkSignalFunc) destroy_about, NULL);
662 gtk_widget_show(window);