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 "widgethelpers.h"
39 #include "debug_gtk3.h"
40 #include "resources.h"
41 #include "sampler.h"
42 #include "openfiledialog.h"
43 
44 #include "settings_sampler.h"
45 
46 
47 /** \brief  Function to retrieve the list of sampler input devices
48  */
49 static sampler_device_t *(*devices_getter)(void) = NULL;
50 
51 
52 /** \brief  Reference to the text entry
53  *
54  * Used by the "browse" button callback to set the new file name and trigger
55  * a resource update
56  */
57 static GtkWidget *entry_widget = NULL;
58 
59 
60 /** \brief  Reference to the "browse" button
61  */
62 static GtkWidget *browse_button = NULL;
63 
64 
65 /** \brief  Handler for the "changed" event of the devices combo box
66  *
67  * \param[in]   combo       combo box with devices
68  * \param[in]   user_data   extra data (unused)
69  */
on_device_changed(GtkComboBoxText * combo,gpointer user_data)70 static void on_device_changed(GtkComboBoxText *combo, gpointer user_data)
71 {
72     int index = gtk_combo_box_get_active(GTK_COMBO_BOX(combo));
73 
74     debug_gtk3("setting SamplerDevice to %d.", index);
75     resources_set_int("SamplerDevice", index);
76 
77     /* this assumes the "media file input" is always first in the list */
78     gtk_widget_set_sensitive(entry_widget, index == 0);
79     gtk_widget_set_sensitive(browse_button, index == 0);
80 }
81 
82 
83 /** \brief  Handler for the "value-changed" event of the gain slider
84  *
85  * \param[in]   scale       gain slider
86  * \param[in]   user_data   extra data (unused)
87  */
on_gain_changed(GtkScale * scale,gpointer user_data)88 static void on_gain_changed(GtkScale *scale, gpointer user_data)
89 {
90     int value = (int)gtk_range_get_value(GTK_RANGE(scale));
91 
92     debug_gtk3("setting SamplerGain to %d.", value);
93     resources_set_int("SamplerGain", value);
94 }
95 
96 
97 /** \brief  Handler for the "changed" event of the text entry box
98  *
99  * \param[in]   entry       input file text box
100  * \param[in]   user_data   extra data (unused)
101  */
on_entry_changed(GtkEntry * entry,gpointer user_data)102 static void on_entry_changed(GtkEntry *entry, gpointer user_data)
103 {
104     const char *text;
105 
106     text = gtk_entry_get_text(entry);
107     debug_gtk3("setting SampleName to '%s'.", text);
108     resources_set_string("SampleName", text);
109 }
110 
111 
112 /** \brief  Handler for the "clicked" event of the "browse" button
113  *
114  * \param[in]   widget      browse button
115  * \param[in]   user_data   extra data (unused)
116  */
on_browse_clicked(GtkWidget * widget,gpointer user_data)117 static void on_browse_clicked(GtkWidget *widget, gpointer user_data)
118 {
119     gchar *filename;
120 
121     filename = vice_gtk3_open_file_dialog("Select input file", NULL, NULL, NULL);
122     if (filename != NULL) {
123         gtk_entry_set_text(GTK_ENTRY(entry_widget), filename);
124         g_free(filename);
125     }
126 }
127 
128 
129 /** \brief  Create combo box for the devices list
130  *
131  * \return  GtkComboBoxText
132  */
create_device_widget(void)133 static GtkWidget *create_device_widget(void)
134 {
135     GtkWidget *combo;
136     sampler_device_t *devices;
137     int current;
138     int i;
139 
140     resources_get_int("SamplerDevice", &current);
141 
142     combo = gtk_combo_box_text_new();
143     if (devices_getter != NULL) {
144         devices = devices_getter();
145     } else {
146         return combo;
147     }
148     for (i = 0; devices[i].name != NULL; i++) {
149         gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(combo),
150                 devices[i].name, devices[i].name);
151         if (i ==  current) {
152             gtk_combo_box_set_active(GTK_COMBO_BOX(combo), i);
153         }
154     }
155 
156     g_signal_connect(combo, "changed", G_CALLBACK(on_device_changed), NULL);
157     return combo;
158 }
159 
160 
161 /** \brief  Create slider for the gain
162  *
163  * \return  GtkScale
164  */
create_gain_widget(void)165 static GtkWidget *create_gain_widget(void)
166 {
167     GtkWidget *scale;
168     GtkWidget *label;
169     int value;
170     int i;
171 
172     label = gtk_label_new("Sampler gain");
173     g_object_set(label, "margin-left",16, NULL);
174 
175     scale = gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL,
176             0.0, 200.0, 25.0);
177     gtk_scale_set_digits(GTK_SCALE(scale), 0);
178 
179     /* add tick marks */
180     for (i = 0; i < 200; i += 25) {
181         gtk_scale_add_mark(GTK_SCALE(scale), (gdouble)i, GTK_POS_BOTTOM, NULL);
182     }
183 
184 
185     if (resources_get_int("SamplerGain", &value) >= 0) {
186         gtk_range_set_value(GTK_RANGE(scale), (gdouble)value);
187     } else {
188         gtk_range_set_value(GTK_RANGE(scale), 100.0);
189     }
190 
191     g_signal_connect(scale, "value-changed", G_CALLBACK(on_gain_changed), NULL);
192 
193     gtk_widget_show_all(scale);
194     return scale;
195 }
196 
197 
198 /** \brief  Create text entry for the input file name
199  *
200  * \return  GtkEntry
201  */
create_input_entry(void)202 static GtkWidget *create_input_entry(void)
203 {
204     GtkWidget *entry;
205     const char *text;
206 
207     resources_get_string("SampleName", &text);
208 
209     entry = gtk_entry_new();
210     if (text != NULL) {
211         gtk_entry_set_text(GTK_ENTRY(entry), text);
212     }
213 
214     g_signal_connect(entry, "changed", G_CALLBACK(on_entry_changed), NULL);
215     return entry;
216 }
217 
218 
219 /** \brief  Create the "browse" button
220  *
221  * \return  GtkButton
222  */
create_input_button(void)223 static GtkWidget *create_input_button(void)
224 {
225     GtkWidget *button;
226 
227     button = gtk_button_new_with_label("Browse ...");
228     g_signal_connect(button, "clicked", G_CALLBACK(on_browse_clicked), NULL);
229     return button;
230 }
231 
232 
233 /** \brief  Set the function to retrieve the input devices list
234  *
235  * \param[in]   func    pointer to function to retrieve devices list
236  */
settings_sampler_set_devices_getter(sampler_device_t * (func)(void))237 void settings_sampler_set_devices_getter(sampler_device_t *(func)(void))
238 {
239     devices_getter = func;
240 }
241 
242 
243 /** \brief  Create widget to control sampler settings
244  *
245  * \param[in]   parent  parent widget
246  *
247  * \return  GtkGrid
248  */
settings_sampler_widget_create(GtkWidget * parent)249 GtkWidget *settings_sampler_widget_create(GtkWidget *parent)
250 {
251     GtkWidget *grid;
252     GtkWidget *label;
253     GtkWidget *combo;
254     int index;
255 
256     grid = uihelpers_create_grid_with_label("Sampler settings", 3);
257     gtk_grid_set_column_spacing(GTK_GRID(grid), 8);
258 
259     /* sampler device list */
260     label = gtk_label_new("Sampler device");
261     gtk_widget_set_halign(label, GTK_ALIGN_START);
262     g_object_set(label, "margin-left", 16, NULL);
263     gtk_grid_attach(GTK_GRID(grid), label, 0, 1, 1, 1);
264     combo = create_device_widget();
265     gtk_grid_attach(GTK_GRID(grid), combo, 1, 1, 2, 1);
266 
267     /* sampler gain */
268     label = gtk_label_new("Sampler gain");
269     gtk_widget_set_halign(label, GTK_ALIGN_START);
270     g_object_set(label, "margin-left", 16, NULL);
271     gtk_grid_attach(GTK_GRID(grid), label, 0, 2, 1, 1);
272     gtk_grid_attach(GTK_GRID(grid), create_gain_widget(), 1, 2, 2, 1);
273 
274     /* sampler input file text entry and browse button */
275     label = gtk_label_new("Sampler media file");
276     gtk_widget_set_halign(label, GTK_ALIGN_START);
277     g_object_set(label, "margin-left", 16, NULL);
278     gtk_grid_attach(GTK_GRID(grid), label, 0, 3, 1, 1);
279     entry_widget = create_input_entry();
280     gtk_widget_set_hexpand(entry_widget, TRUE);
281     gtk_grid_attach(GTK_GRID(grid), entry_widget, 1, 3, 1, 1);
282     browse_button = create_input_button();
283     gtk_grid_attach(GTK_GRID(grid), browse_button, 2, 3, 1, 1);
284 
285     /* update sensitivity of entry and button */
286     index = gtk_combo_box_get_active(GTK_COMBO_BOX(combo));
287 
288     gtk_widget_set_sensitive(entry_widget, index == 0);
289     gtk_widget_set_sensitive(browse_button, index == 0);
290 
291     gtk_widget_show_all(grid);
292     return grid;
293 }
294