1 /** \file   settings_sampler.c
2  * \brief   Widget to control sampler settings
3  *
4  * \author  Bas Wassink <b.wassink@ziggo.nl>
5  */
6 
7 /*
8  * $VICERES SamplerDevice
9  * $VICERES SamplerGain
10  * $VICERES SampleName
11  */
12 
13 /*
14  * This file is part of VICE, the Versatile Commodore Emulator.
15  * See README for copyright notice.
16  *
17  *  This program is free software; you can redistribute it and/or modify
18  *  it under the terms of the GNU General Public License as published by
19  *  the Free Software Foundation; either version 2 of the License, or
20  *  (at your option) any later version.
21  *
22  *  This program is distributed in the hope that it will be useful,
23  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
24  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
25  *  GNU General Public License for more details.
26  *
27  *  You should have received a copy of the GNU General Public License
28  *  along with this program; if not, write to the Free Software
29  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
30  *  02111-1307  USA.
31  *
32  */
33 
34 #include "vice.h"
35 
36 #include <gtk/gtk.h>
37 
38 #include "debug_gtk3.h"
39 #include "openfiledialog.h"
40 #include "resources.h"
41 #include "sampler.h"
42 #include "ui.h"
43 #include "widgethelpers.h"
44 
45 #include "settings_sampler.h"
46 
47 
48 /** \brief  Function to retrieve the list of sampler input devices
49  */
50 static sampler_device_t *(*devices_getter)(void) = NULL;
51 
52 
53 /** \brief  Reference to the text entry
54  *
55  * Used by the "browse" button callback to set the new file name and trigger
56  * a resource update
57  */
58 static GtkWidget *entry_widget = NULL;
59 
60 
61 /** \brief  Reference to the "browse" button
62  */
63 static GtkWidget *browse_button = NULL;
64 
65 
66 /** \brief  Handler for the "changed" event of the devices combo box
67  *
68  * \param[in]   combo       combo box with devices
69  * \param[in]   user_data   extra data (unused)
70  */
on_device_changed(GtkComboBoxText * combo,gpointer user_data)71 static void on_device_changed(GtkComboBoxText *combo, gpointer user_data)
72 {
73     int index = gtk_combo_box_get_active(GTK_COMBO_BOX(combo));
74 
75     debug_gtk3("setting SamplerDevice to %d.", index);
76     resources_set_int("SamplerDevice", index);
77 
78     /* this assumes the "media file input" is always first in the list */
79     gtk_widget_set_sensitive(entry_widget, index == 0);
80     gtk_widget_set_sensitive(browse_button, index == 0);
81 }
82 
83 
84 /** \brief  Handler for the "value-changed" event of the gain slider
85  *
86  * \param[in]   scale       gain slider
87  * \param[in]   user_data   extra data (unused)
88  */
on_gain_changed(GtkScale * scale,gpointer user_data)89 static void on_gain_changed(GtkScale *scale, gpointer user_data)
90 {
91     int value = (int)gtk_range_get_value(GTK_RANGE(scale));
92 
93     debug_gtk3("setting SamplerGain to %d.", value);
94     resources_set_int("SamplerGain", value);
95 }
96 
97 
98 /** \brief  Handler for the "changed" event of the text entry box
99  *
100  * \param[in]   entry       input file text box
101  * \param[in]   user_data   extra data (unused)
102  */
on_entry_changed(GtkEntry * entry,gpointer user_data)103 static void on_entry_changed(GtkEntry *entry, gpointer user_data)
104 {
105     const char *text;
106 
107     text = gtk_entry_get_text(entry);
108     debug_gtk3("setting SampleName to '%s'.", text);
109     resources_set_string("SampleName", text);
110 }
111 
112 
browse_filename_callback(GtkDialog * dialog,gchar * filename,gpointer data)113 static void browse_filename_callback(GtkDialog *dialog,
114                                      gchar *filename,
115                                      gpointer data)
116 {
117     if (filename != NULL) {
118         gtk_entry_set_text(GTK_ENTRY(entry_widget), filename);
119         g_free(filename);
120     }
121 
122 }
123 
124 /** \brief  Handler for the "clicked" event of the "browse" button
125  *
126  * \param[in]   widget      browse button
127  * \param[in]   user_data   extra data (unused)
128  */
on_browse_clicked(GtkWidget * widget,gpointer user_data)129 static void on_browse_clicked(GtkWidget *widget, gpointer user_data)
130 {
131     vice_gtk3_open_file_dialog(
132             "Select input file",
133             NULL, NULL, NULL,
134             browse_filename_callback,
135             NULL);
136 }
137 
138 
139 /** \brief  Create combo box for the devices list
140  *
141  * \return  GtkComboBoxText
142  */
create_device_widget(void)143 static GtkWidget *create_device_widget(void)
144 {
145     GtkWidget *combo;
146     sampler_device_t *devices;
147     int current;
148     int i;
149 
150     resources_get_int("SamplerDevice", &current);
151 
152     combo = gtk_combo_box_text_new();
153     if (devices_getter != NULL) {
154         devices = devices_getter();
155     } else {
156         return combo;
157     }
158     for (i = 0; devices[i].name != NULL; i++) {
159         gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(combo),
160                 devices[i].name, devices[i].name);
161         if (i ==  current) {
162             gtk_combo_box_set_active(GTK_COMBO_BOX(combo), i);
163         }
164     }
165 
166     g_signal_connect(combo, "changed", G_CALLBACK(on_device_changed), NULL);
167     return combo;
168 }
169 
170 
171 /** \brief  Create slider for the gain
172  *
173  * \return  GtkScale
174  */
create_gain_widget(void)175 static GtkWidget *create_gain_widget(void)
176 {
177     GtkWidget *scale;
178     GtkWidget *label;
179     int value;
180     int i;
181 
182     label = gtk_label_new("Sampler gain");
183     g_object_set(label, "margin-left",16, NULL);
184 
185     scale = gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL,
186             0.0, 200.0, 25.0);
187     gtk_scale_set_digits(GTK_SCALE(scale), 0);
188 
189     /* add tick marks */
190     for (i = 0; i < 200; i += 25) {
191         gtk_scale_add_mark(GTK_SCALE(scale), (gdouble)i, GTK_POS_BOTTOM, NULL);
192     }
193 
194 
195     if (resources_get_int("SamplerGain", &value) >= 0) {
196         gtk_range_set_value(GTK_RANGE(scale), (gdouble)value);
197     } else {
198         gtk_range_set_value(GTK_RANGE(scale), 100.0);
199     }
200 
201     g_signal_connect(scale, "value-changed", G_CALLBACK(on_gain_changed), NULL);
202 
203     gtk_widget_show_all(scale);
204     return scale;
205 }
206 
207 
208 /** \brief  Create text entry for the input file name
209  *
210  * \return  GtkEntry
211  */
create_input_entry(void)212 static GtkWidget *create_input_entry(void)
213 {
214     GtkWidget *entry;
215     const char *text;
216 
217     resources_get_string("SampleName", &text);
218 
219     entry = gtk_entry_new();
220     if (text != NULL) {
221         gtk_entry_set_text(GTK_ENTRY(entry), text);
222     }
223 
224     g_signal_connect(entry, "changed", G_CALLBACK(on_entry_changed), NULL);
225     return entry;
226 }
227 
228 
229 /** \brief  Create the "browse" button
230  *
231  * \return  GtkButton
232  */
create_input_button(void)233 static GtkWidget *create_input_button(void)
234 {
235     GtkWidget *button;
236 
237     button = gtk_button_new_with_label("Browse ...");
238     g_signal_connect(button, "clicked", G_CALLBACK(on_browse_clicked), NULL);
239     return button;
240 }
241 
242 
243 /** \brief  Set the function to retrieve the input devices list
244  *
245  * \param[in]   func    pointer to function to retrieve devices list
246  */
settings_sampler_set_devices_getter(sampler_device_t * (func)(void))247 void settings_sampler_set_devices_getter(sampler_device_t *(func)(void))
248 {
249     devices_getter = func;
250 }
251 
252 
253 /** \brief  Create widget to control sampler settings
254  *
255  * \param[in]   parent  parent widget
256  *
257  * \return  GtkGrid
258  */
settings_sampler_widget_create(GtkWidget * parent)259 GtkWidget *settings_sampler_widget_create(GtkWidget *parent)
260 {
261     GtkWidget *grid;
262     GtkWidget *label;
263     GtkWidget *combo;
264     int index;
265 
266     grid = vice_gtk3_grid_new_spaced_with_label(-1, -1, "Sampler settings", 3);
267 
268     /* sampler device list */
269     label = gtk_label_new("Sampler device");
270     gtk_widget_set_halign(label, GTK_ALIGN_START);
271     g_object_set(label, "margin-left", 16, NULL);
272     gtk_grid_attach(GTK_GRID(grid), label, 0, 1, 1, 1);
273     combo = create_device_widget();
274     gtk_grid_attach(GTK_GRID(grid), combo, 1, 1, 2, 1);
275 
276     /* sampler gain */
277     label = gtk_label_new("Sampler gain");
278     gtk_widget_set_halign(label, GTK_ALIGN_START);
279     g_object_set(label, "margin-left", 16, NULL);
280     gtk_grid_attach(GTK_GRID(grid), label, 0, 2, 1, 1);
281     gtk_grid_attach(GTK_GRID(grid), create_gain_widget(), 1, 2, 2, 1);
282 
283     /* sampler input file text entry and browse button */
284     label = gtk_label_new("Sampler media file");
285     gtk_widget_set_halign(label, GTK_ALIGN_START);
286     g_object_set(label, "margin-left", 16, NULL);
287     gtk_grid_attach(GTK_GRID(grid), label, 0, 3, 1, 1);
288     entry_widget = create_input_entry();
289     gtk_widget_set_hexpand(entry_widget, TRUE);
290     gtk_grid_attach(GTK_GRID(grid), entry_widget, 1, 3, 1, 1);
291     browse_button = create_input_button();
292     gtk_grid_attach(GTK_GRID(grid), browse_button, 2, 3, 1, 1);
293 
294     /* update sensitivity of entry and button */
295     index = gtk_combo_box_get_active(GTK_COMBO_BOX(combo));
296 
297     gtk_widget_set_sensitive(entry_widget, index == 0);
298     gtk_widget_set_sensitive(browse_button, index == 0);
299 
300     gtk_widget_show_all(grid);
301     return grid;
302 }
303