added tuning knob
[nekobee.git] / src / gtk / interface.c
blob7a245375b7c5344ce0bb3b02e73dcc8de88be342
1 /* nekobee DSSI software synthesizer GUI
3 * Copyright (C) 2004 Sean Bolton
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation; either version 2 of
8 * the License, or (at your option) any later version.
10 * This program is distributed in the hope that it will be
11 * useful, but WITHOUT ANY WARRANTY; without even the implied
12 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
13 * PURPOSE. See the GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public
16 * License along with this program; if not, write to the Free
17 * Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
18 * MA 02111-1307, USA.
21 #ifdef HAVE_CONFIG_H
22 # include <config.h>
23 #endif
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <gdk/gdkkeysyms.h>
29 #include <gtk/gtk.h>
30 #include "knob.h"
31 #include "slider.h"
33 #include "nekobee.h"
34 #include "nekobee_ports.h"
35 #include "nekobee_synth.h"
36 #include "callbacks.h"
37 #include "interface.h"
39 GtkWidget *main_window;
40 GtkWidget *save_file_selection;
42 GtkWidget *osc1_waveform_pixmap;
44 GtkObject *tuning_adj;
45 GtkObject *polyphony_adj;
46 GtkWidget *monophonic_option_menu;
47 GtkWidget *glide_option_menu;
48 GtkObject *bendrange_adj;
50 GtkObject *voice_widget[XSYNTH_PORTS_COUNT];
52 #if GTK_CHECK_VERSION(2, 0, 0)
53 #define GTK20SIZEGROUP GtkSizeGroup
54 #else
55 #define GTK20SIZEGROUP gpointer
56 #endif
58 static void
59 create_voice_knob(GtkWidget *main_window, int index, GtkWidget *fixed,
60 gint column, gint row, const char *text)
62 GtkWidget *knob;
63 GtkObject *adjustment;
65 adjustment = gtk_adjustment_new (0, 0, 10, 0.005, 1, 0);
66 voice_widget[index] = adjustment;
68 knob = gtk_knob_new (GTK_ADJUSTMENT (adjustment));
70 // gjcp - FIXME horrible one-off to add the tuning knob
71 if (index == XSYNTH_PORT_TUNING) GTK_KNOB(knob)->knobtype=1;
73 gtk_widget_ref (knob);
74 gtk_object_set_data_full (GTK_OBJECT (main_window), text, knob,
75 (GtkDestroyNotify) gtk_widget_unref);
77 gtk_widget_show (knob);
78 gtk_fixed_put (GTK_FIXED (fixed), knob, column, row);
81 static void
82 create_voice_slider(GtkWidget *main_window, int index, GtkWidget *fixed,
83 gint column, gint row, const char *text)
85 GtkWidget *knob;
86 GtkObject *adjustment;
88 adjustment = gtk_adjustment_new (0, 0, 10, 0.005, 1, 0);
89 voice_widget[index] = adjustment;
91 knob = gtk_slider_new (GTK_ADJUSTMENT (adjustment));
93 gtk_widget_ref (knob);
94 gtk_object_set_data_full (GTK_OBJECT (main_window), text, knob,
95 (GtkDestroyNotify) gtk_widget_unref);
96 gtk_widget_show (knob);
97 gtk_fixed_put (GTK_FIXED (fixed), knob, column, row);
102 void
103 create_main_window (const char *tag)
105 GtkWidget *fixed;
106 GtkStyle *bg_style;
107 GdkPixbuf *bg_buf;
108 GdkPixmap *bg_map = NULL;
110 int i;
112 main_window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
113 gtk_object_set_data (GTK_OBJECT (main_window), "main_window", main_window);
114 gtk_window_set_title (GTK_WINDOW (main_window), tag);
116 // gjcp - FIXME - put these somewhere in a header
117 gtk_widget_set_size_request (main_window, 600, 108);
118 gtk_window_set_default_size (GTK_WINDOW (main_window), 600, 108);
119 gtk_window_set_resizable (GTK_WINDOW (main_window), FALSE);
121 gtk_widget_realize(main_window); /* window must be realized for create_*_pixmap() */
123 // load the background up
124 bg_buf = gdk_pixbuf_new_from_file(INSTALL_DIR"/bg.png", NULL );
125 gdk_pixbuf_render_pixmap_and_mask(bg_buf, &bg_map, NULL, 255);
126 bg_style = gtk_style_copy(gtk_widget_get_style(main_window));
127 bg_style->bg_pixmap[GTK_STATE_NORMAL] = bg_map;
128 gtk_widget_set_style(main_window, bg_style);
130 // rather than the table layout I'm going to use fixed
131 fixed = gtk_fixed_new ();
132 gtk_widget_show (fixed);
133 gtk_container_add (GTK_CONTAINER (main_window), fixed);
136 /* Patch Edit tab */
137 for (i = 0; i < XSYNTH_PORTS_COUNT; i++) voice_widget[i] = NULL;
139 // tuning can go from -12 to +12, so needs special poking
140 create_voice_knob(main_window, XSYNTH_PORT_TUNING, fixed, 26, 46, "Tuning");
142 GTK_ADJUSTMENT(voice_widget[XSYNTH_PORT_TUNING])->lower = -12.0f;
143 GTK_ADJUSTMENT(voice_widget[XSYNTH_PORT_TUNING])->upper = 12.0f;
145 gtk_adjustment_changed (GTK_ADJUSTMENT(voice_widget[XSYNTH_PORT_TUNING]));
147 // wave switch also needs special poking
148 create_voice_slider(main_window, XSYNTH_PORT_WAVEFORM, fixed, 116, 43, "Waveform");
149 GTK_ADJUSTMENT(voice_widget[XSYNTH_PORT_WAVEFORM])->upper = 1.0f;
150 GTK_ADJUSTMENT(voice_widget[XSYNTH_PORT_WAVEFORM])->step_increment = 1.0f;
151 gtk_adjustment_changed (GTK_ADJUSTMENT(voice_widget[XSYNTH_PORT_WAVEFORM]));
153 create_voice_knob(main_window, XSYNTH_PORT_CUTOFF, fixed, 170, 46, "Cutoff");
154 create_voice_knob(main_window, XSYNTH_PORT_RESONANCE, fixed, 242, 46, "Resonance");
155 create_voice_knob(main_window, XSYNTH_PORT_ENVMOD, fixed, 314, 46, "Envmod");
156 create_voice_knob(main_window, XSYNTH_PORT_DECAY, fixed, 386, 46, "Decay");
157 create_voice_knob(main_window, XSYNTH_PORT_ACCENT, fixed, 458, 46, "Accent");
158 create_voice_knob(main_window, XSYNTH_PORT_VOLUME, fixed, 530, 46, "Volume");
160 gtk_signal_connect(GTK_OBJECT(main_window), "destroy",
161 GTK_SIGNAL_FUNC(gtk_main_quit), NULL);
162 gtk_signal_connect (GTK_OBJECT (main_window), "delete_event",
163 (GtkSignalFunc)on_delete_event_wrapper,
164 (gpointer)on_menu_quit_activate);
167 /* connect patch edit widgets */
168 gtk_signal_connect (GTK_OBJECT (voice_widget[XSYNTH_PORT_TUNING]),
169 "value_changed", GTK_SIGNAL_FUNC(on_voice_slider_change),
170 (gpointer)XSYNTH_PORT_TUNING);
171 gtk_signal_connect (GTK_OBJECT (voice_widget[XSYNTH_PORT_WAVEFORM]),
172 "value_changed", GTK_SIGNAL_FUNC(on_voice_slider_change),
173 (gpointer)XSYNTH_PORT_WAVEFORM);
174 gtk_signal_connect (GTK_OBJECT (voice_widget[XSYNTH_PORT_CUTOFF]),
175 "value_changed", GTK_SIGNAL_FUNC (on_voice_slider_change),
176 (gpointer)XSYNTH_PORT_CUTOFF);
177 gtk_signal_connect (GTK_OBJECT (voice_widget[XSYNTH_PORT_RESONANCE]),
178 "value_changed", GTK_SIGNAL_FUNC(on_voice_slider_change),
179 (gpointer)XSYNTH_PORT_RESONANCE);
181 gtk_signal_connect (GTK_OBJECT (voice_widget[XSYNTH_PORT_ENVMOD]),
182 "value_changed", GTK_SIGNAL_FUNC(on_voice_slider_change),
183 (gpointer)XSYNTH_PORT_ENVMOD);
184 gtk_signal_connect (GTK_OBJECT (voice_widget[XSYNTH_PORT_DECAY]),
185 "value_changed", GTK_SIGNAL_FUNC(on_voice_slider_change),
186 (gpointer)XSYNTH_PORT_DECAY);
187 gtk_signal_connect (GTK_OBJECT (voice_widget[XSYNTH_PORT_ACCENT]),
188 "value_changed", GTK_SIGNAL_FUNC(on_voice_slider_change),
189 (gpointer)XSYNTH_PORT_ACCENT);
190 gtk_signal_connect (GTK_OBJECT (voice_widget[XSYNTH_PORT_VOLUME]),
191 "value_changed", GTK_SIGNAL_FUNC(on_voice_slider_change),
192 (gpointer)XSYNTH_PORT_VOLUME);
195 void
196 create_windows(const char *instance_tag)
198 char tag[50];
200 /* build a nice identifier string for the window titles */
201 if (strlen(instance_tag) == 0) {
202 strcpy(tag, "nekobee");
203 } else if (strstr(instance_tag, "nekobee-DSSI") ||
204 strstr(instance_tag, "nekobee-dssi")) {
205 if (strlen(instance_tag) > 49) {
206 snprintf(tag, 50, "...%s", instance_tag + strlen(instance_tag) - 46); /* hope the unique info is at the end */
207 } else {
208 strcpy(tag, instance_tag);
210 } else {
211 if (strlen(instance_tag) > 37) {
212 snprintf(tag, 50, "nekobee ...%s", instance_tag + strlen(instance_tag) - 34);
213 } else {
214 snprintf(tag, 50, "nekobee %s", instance_tag);
218 create_main_window(tag);