[GTK3] Add interference volume slider

This commit is contained in:
Maximilian Mader 2021-01-01 17:03:16 +01:00
parent 50326f4058
commit 92cc8b6c6e
Signed by: Max
GPG Key ID: F71D56A3151C4FB3
8 changed files with 97 additions and 25 deletions

View File

@ -172,7 +172,7 @@ void save_config(GtkWindow *main_window, GDateTime *saved_modification_date) {
GError *error = NULL; GError *error = NULL;
g_message("Trying to save config to %s", config_file_path); g_message("Trying to save config to %s", config_file_path);
g_autoptr(GFile) file = g_file_new_for_path(config_file_path); g_autoptr(GFile) file = g_file_new_for_path(config_file_path);
g_autoptr(GFileInfo) file_info = g_file_query_info(file, "time::*", G_FILE_QUERY_INFO_NONE, NULL, NULL); g_autoptr(GFileInfo) file_info = g_file_query_info(file, "time::*", G_FILE_QUERY_INFO_NONE, NULL, NULL);
@ -429,7 +429,7 @@ const GB_rumble_mode_t config_get_rumble_mode(void) {
} }
// This should not happen // This should not happen
g_warning("Unknown highpass mode: %s\nFalling back to “Never”", config.controls.rumble_mode); g_warning("Unknown rumble mode: %s\nFalling back to “Never”", config.controls.rumble_mode);
default_value: return GB_RUMBLE_DISABLED; default_value: return GB_RUMBLE_DISABLED;
} }

View File

@ -47,11 +47,12 @@
EXPAND_GROUP(audio, \ EXPAND_GROUP(audio, \
EXPAND_GROUP_MEMBER(high_pass_filter_id, string, "emulate_hardware") \ EXPAND_GROUP_MEMBER(high_pass_filter_id, string, "emulate_hardware") \
EXPAND_GROUP_MEMBER(sample_rate, integer, -1) \ EXPAND_GROUP_MEMBER(sample_rate, integer, -1) \
EXPAND_GROUP_MEMBER(interference_volume, integer, 0) \
EXPAND_GROUP_MEMBER(muted, boolean, false) \ EXPAND_GROUP_MEMBER(muted, boolean, false) \
) \ ) \
EXPAND_GROUP(controls, \ EXPAND_GROUP(controls, \
EXPAND_GROUP_MEMBER(analog_speed_controls, boolean, false) \ EXPAND_GROUP_MEMBER(analog_speed_controls, boolean, false) \
EXPAND_GROUP_MEMBER(rumble_mode, string, "Never") \ EXPAND_GROUP_MEMBER(rumble_mode, string, "never") \
) \ ) \
EXPAND_GROUP(window, \ EXPAND_GROUP(window, \
\ \

View File

@ -87,7 +87,7 @@ static const GActionEntry file_entries[] = {
}; };
static const GActionEntry edit_entries[] = { static const GActionEntry edit_entries[] = {
}; };
static const GActionEntry emulation_entries[] = { static const GActionEntry emulation_entries[] = {
@ -252,7 +252,7 @@ static gboolean init_controllers(void) {
if (s->haptic == NULL) { if (s->haptic == NULL) {
g_warning("%s", SDL_GetError()); g_warning("%s", SDL_GetError());
} }
SDL_HapticClose(s->haptic); SDL_HapticClose(s->haptic);
s->haptic = NULL; s->haptic = NULL;
} }
@ -298,7 +298,7 @@ static gboolean init_audio(void) {
GB_audio_init(gui_data.sample_rate); GB_audio_init(gui_data.sample_rate);
GB_set_sample_rate(&gb, GB_audio_get_sample_rate()); GB_set_sample_rate(&gb, GB_audio_get_sample_rate());
// restore playing state // restore playing state
GB_audio_set_paused(!audio_playing); GB_audio_set_paused(!audio_playing);
@ -583,12 +583,12 @@ static void handle_events(GB_gameboy_t *gb) {
gui_data.last_used_controller = s; gui_data.last_used_controller = s;
controller_state |= BUTTON_MASK_A; controller_state |= BUTTON_MASK_A;
} }
if (SDL_GameControllerGetButton(s->controller, SDL_CONTROLLER_BUTTON_B)) { if (SDL_GameControllerGetButton(s->controller, SDL_CONTROLLER_BUTTON_B)) {
gui_data.last_used_controller = s; gui_data.last_used_controller = s;
controller_state |= BUTTON_MASK_B; controller_state |= BUTTON_MASK_B;
} }
if (SDL_GameControllerGetButton(s->controller, SDL_CONTROLLER_BUTTON_BACK)) { if (SDL_GameControllerGetButton(s->controller, SDL_CONTROLLER_BUTTON_BACK)) {
gui_data.last_used_controller = s; gui_data.last_used_controller = s;
controller_state |= BUTTON_MASK_SELECT; controller_state |= BUTTON_MASK_SELECT;
@ -698,9 +698,10 @@ static void init(void) {
} }
GB_apu_set_sample_callback(&gb, gb_audio_callback); GB_apu_set_sample_callback(&gb, gb_audio_callback);
GB_set_sample_rate(&gb, GB_audio_get_sample_rate()); GB_set_sample_rate(&gb, GB_audio_get_sample_rate());
GB_set_highpass_filter_mode(&gb, config_get_highpass_mode()); GB_set_highpass_filter_mode(&gb, config_get_highpass_mode());
GB_set_interference_volume(&gb, (double) config.audio.interference_volume / 255.0);
GB_set_log_callback(&gb, wrapped_console_log); GB_set_log_callback(&gb, wrapped_console_log);
GB_set_input_callback(&gb, wrapped_console_get_sync_input); GB_set_input_callback(&gb, wrapped_console_get_sync_input);
@ -837,7 +838,7 @@ static gpointer run_thread(gpointer null_ptr) {
char *path = g_file_get_path(gui_data.file); char *path = g_file_get_path(gui_data.file);
size_t path_length = strlen(path); size_t path_length = strlen(path);
/* At the worst case, size is strlen(path) + 4 bytes for .sav + NULL */ /* At the worst case, size is strlen(path) + 4 bytes for .sav + NULL */
char battery_save_path[path_length + 5]; char battery_save_path[path_length + 5];
char cheats_save_path[path_length + 5]; char cheats_save_path[path_length + 5];
@ -915,14 +916,14 @@ static void create_action_groups(GApplication *app) {
static gboolean on_key_press(GtkWidget *w, GdkEventKey *event, gpointer data) { static gboolean on_key_press(GtkWidget *w, GdkEventKey *event, gpointer data) {
uint8_t mask; uint8_t mask;
if (event->keyval == key_map[INPUT_UP]) mask = BUTTON_MASK_UP; if (event->keyval == key_map[INPUT_UP]) mask = BUTTON_MASK_UP;
if (event->keyval == key_map[INPUT_DOWN]) mask = BUTTON_MASK_DOWN; if (event->keyval == key_map[INPUT_DOWN]) mask = BUTTON_MASK_DOWN;
if (event->keyval == key_map[INPUT_LEFT]) mask = BUTTON_MASK_LEFT; if (event->keyval == key_map[INPUT_LEFT]) mask = BUTTON_MASK_LEFT;
if (event->keyval == key_map[INPUT_RIGHT]) mask = BUTTON_MASK_RIGHT; if (event->keyval == key_map[INPUT_RIGHT]) mask = BUTTON_MASK_RIGHT;
if (event->keyval == key_map[INPUT_START]) mask = BUTTON_MASK_START; if (event->keyval == key_map[INPUT_START]) mask = BUTTON_MASK_START;
if (event->keyval == key_map[INPUT_SELECT]) mask = BUTTON_MASK_SELECT; if (event->keyval == key_map[INPUT_SELECT]) mask = BUTTON_MASK_SELECT;
if (event->keyval == key_map[INPUT_A]) mask = BUTTON_MASK_A; if (event->keyval == key_map[INPUT_A]) mask = BUTTON_MASK_A;
if (event->keyval == key_map[INPUT_B]) mask = BUTTON_MASK_B; if (event->keyval == key_map[INPUT_B]) mask = BUTTON_MASK_B;
if (event->keyval == key_map[INPUT_REWIND]) { if (event->keyval == key_map[INPUT_REWIND]) {
gui_data.rewind_down = event->type == GDK_KEY_PRESS; gui_data.rewind_down = event->type == GDK_KEY_PRESS;
@ -956,7 +957,7 @@ static gboolean on_key_press(GtkWidget *w, GdkEventKey *event, gpointer data) {
} }
} }
} }
if (event->type == GDK_KEY_PRESS) { if (event->type == GDK_KEY_PRESS) {
gui_data.pressed_buttons |= mask; gui_data.pressed_buttons |= mask;
} }
@ -1120,6 +1121,12 @@ void on_preferences_notify_sample_rate(PreferencesWindow *pref, const guint *sam
init_audio(); init_audio();
} }
void on_preferences_notify_interference_volume(PreferencesWindow *pref, const guint *interference_volume) {
if (GB_is_inited(&gb)) {
GB_set_interference_volume(&gb, (double) *interference_volume / 255.0);
}
}
static void connect_signal_handlers(GApplication *app) { static void connect_signal_handlers(GApplication *app) {
// Connect signal handlers // Connect signal handlers
gtk_widget_add_events(GTK_WIDGET(gui_data.main_window), GDK_KEY_PRESS_MASK); gtk_widget_add_events(GTK_WIDGET(gui_data.main_window), GDK_KEY_PRESS_MASK);
@ -1140,6 +1147,7 @@ static void connect_signal_handlers(GApplication *app) {
g_signal_connect(gui_data.preferences, "pref-update::video-display-border-mode", G_CALLBACK(on_preferences_notify_border), NULL); g_signal_connect(gui_data.preferences, "pref-update::video-display-border-mode", G_CALLBACK(on_preferences_notify_border), NULL);
g_signal_connect(gui_data.preferences, "pref-update::video-shader", G_CALLBACK(on_preferences_notify_shader), NULL); g_signal_connect(gui_data.preferences, "pref-update::video-shader", G_CALLBACK(on_preferences_notify_shader), NULL);
g_signal_connect(gui_data.preferences, "pref-update::audio-sample-rate", G_CALLBACK(on_preferences_notify_sample_rate), NULL); g_signal_connect(gui_data.preferences, "pref-update::audio-sample-rate", G_CALLBACK(on_preferences_notify_sample_rate), NULL);
g_signal_connect(gui_data.preferences, "pref-update::audio-interference-volume", G_CALLBACK(on_preferences_notify_interference_volume), NULL);
} }
// This function gets called when the GApplication gets activated, i.e. it is ready to show widgets. // This function gets called when the GApplication gets activated, i.e. it is ready to show widgets.
@ -1167,7 +1175,7 @@ static void shutdown(GApplication *app, GFile **files, gint n_files, const gchar
stop(); stop();
SDL_Quit(); SDL_Quit();
GB_free(&gb); GB_free(&gb);
g_object_unref(gui_data.builder); g_object_unref(gui_data.builder);
} }
@ -1193,7 +1201,6 @@ static void activate_about(GSimpleAction *action, GVariant *parameter, gpointer
gtk_widget_hide(GTK_WIDGET(dialog)); gtk_widget_hide(GTK_WIDGET(dialog));
} }
// app.preferences GAction // app.preferences GAction
// Opens the preferences window // Opens the preferences window
static void activate_preferences(GSimpleAction *action, GVariant *parameter, gpointer app) { static void activate_preferences(GSimpleAction *action, GVariant *parameter, gpointer app) {
@ -1234,7 +1241,7 @@ static void activate_clear_console(GSimpleAction *action, GVariant *parameter, g
static void close_rom(void) { static void close_rom(void) {
stop(); stop();
GB_free(&gb); GB_free(&gb);
gb_screen_clear(gui_data.screen); gb_screen_clear(gui_data.screen);
gb_screen_queue_render(gui_data.screen); gb_screen_queue_render(gui_data.screen);
@ -1244,7 +1251,7 @@ static void close_rom(void) {
// Update menu action states // Update menu action states
action_set_enabled(gui_data.main_application, "close", false); action_set_enabled(gui_data.main_application, "close", false);
action_entries_set_enabled(emulation_entries, G_N_ELEMENTS(emulation_entries), false); action_entries_set_enabled(emulation_entries, G_N_ELEMENTS(emulation_entries), false);
// Try force the queued redraws // Try force the queued redraws
while (g_main_context_pending(NULL)) { while (g_main_context_pending(NULL)) {
g_main_context_iteration(NULL, FALSE); g_main_context_iteration(NULL, FALSE);

View File

@ -19,6 +19,7 @@ struct _PreferencesWindow {
GtkCheckButton *aspect_ratio_toggle; GtkCheckButton *aspect_ratio_toggle;
GtkComboBoxText *highpass_filter_selector; GtkComboBoxText *highpass_filter_selector;
GtkComboBoxText *sample_rate_selector; GtkComboBoxText *sample_rate_selector;
GtkScale *interference_volume_slider;
GtkCheckButton *analog_speed_controls_toggle; GtkCheckButton *analog_speed_controls_toggle;
GtkComboBoxText *rumble_mode_selector; GtkComboBoxText *rumble_mode_selector;
GtkButton *configure_joypad_skip; GtkButton *configure_joypad_skip;
@ -206,6 +207,18 @@ static void on_sample_rate_changed(GtkWidget *w, PreferencesWindow *self) {
); );
} }
static void on_interference_volume_changed(GtkWidget *w, PreferencesWindow *self) {
GtkRange *range = GTK_RANGE(w);
gdouble value = gtk_range_get_value(range);
config.audio.interference_volume = (guint32) clamp_double(0, 255, value);
g_signal_emit(
self,
preferences_signals[PREF_UPDATE],
g_quark_from_static_string("audio-interference-volume"),
&config.audio.interference_volume
);
}
static void preferences_window_realize(GtkWidget *widget) { static void preferences_window_realize(GtkWidget *widget) {
PreferencesWindow *self = (PreferencesWindow *)widget; PreferencesWindow *self = (PreferencesWindow *)widget;
@ -225,6 +238,7 @@ static void preferences_window_realize(GtkWidget *widget) {
gtk_combo_box_set_active_id(GTK_COMBO_BOX(self->highpass_filter_selector), config.audio.high_pass_filter_id); gtk_combo_box_set_active_id(GTK_COMBO_BOX(self->highpass_filter_selector), config.audio.high_pass_filter_id);
gtk_combo_box_set_active_id(GTK_COMBO_BOX(self->sample_rate_selector), g_strdup_printf("%i", config.audio.sample_rate)); gtk_combo_box_set_active_id(GTK_COMBO_BOX(self->sample_rate_selector), g_strdup_printf("%i", config.audio.sample_rate));
gtk_range_set_value(GTK_RANGE(self->interference_volume_slider), (double) config.audio.interference_volume);
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(self->analog_speed_controls_toggle), config.controls.analog_speed_controls); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(self->analog_speed_controls_toggle), config.controls.analog_speed_controls);
gtk_combo_box_set_active_id(GTK_COMBO_BOX(self->rumble_mode_selector), config.controls.rumble_mode); gtk_combo_box_set_active_id(GTK_COMBO_BOX(self->rumble_mode_selector), config.controls.rumble_mode);
@ -251,6 +265,7 @@ static void preferences_window_class_init(PreferencesWindowClass *class) {
gtk_widget_class_bind_template_child(GTK_WIDGET_CLASS(class), PreferencesWindow, aspect_ratio_toggle); gtk_widget_class_bind_template_child(GTK_WIDGET_CLASS(class), PreferencesWindow, aspect_ratio_toggle);
gtk_widget_class_bind_template_child(GTK_WIDGET_CLASS(class), PreferencesWindow, highpass_filter_selector); gtk_widget_class_bind_template_child(GTK_WIDGET_CLASS(class), PreferencesWindow, highpass_filter_selector);
gtk_widget_class_bind_template_child(GTK_WIDGET_CLASS(class), PreferencesWindow, sample_rate_selector); gtk_widget_class_bind_template_child(GTK_WIDGET_CLASS(class), PreferencesWindow, sample_rate_selector);
gtk_widget_class_bind_template_child(GTK_WIDGET_CLASS(class), PreferencesWindow, interference_volume_slider);
gtk_widget_class_bind_template_child(GTK_WIDGET_CLASS(class), PreferencesWindow, analog_speed_controls_toggle); gtk_widget_class_bind_template_child(GTK_WIDGET_CLASS(class), PreferencesWindow, analog_speed_controls_toggle);
gtk_widget_class_bind_template_child(GTK_WIDGET_CLASS(class), PreferencesWindow, rumble_mode_selector); gtk_widget_class_bind_template_child(GTK_WIDGET_CLASS(class), PreferencesWindow, rumble_mode_selector);
gtk_widget_class_bind_template_child(GTK_WIDGET_CLASS(class), PreferencesWindow, configure_joypad_skip); gtk_widget_class_bind_template_child(GTK_WIDGET_CLASS(class), PreferencesWindow, configure_joypad_skip);
@ -269,6 +284,7 @@ static void preferences_window_class_init(PreferencesWindowClass *class) {
gtk_widget_class_bind_template_callback(GTK_WIDGET_CLASS(class), on_keep_aspect_ratio_changed); gtk_widget_class_bind_template_callback(GTK_WIDGET_CLASS(class), on_keep_aspect_ratio_changed);
gtk_widget_class_bind_template_callback(GTK_WIDGET_CLASS(class), on_highpass_filter_changed); gtk_widget_class_bind_template_callback(GTK_WIDGET_CLASS(class), on_highpass_filter_changed);
gtk_widget_class_bind_template_callback(GTK_WIDGET_CLASS(class), on_sample_rate_changed); gtk_widget_class_bind_template_callback(GTK_WIDGET_CLASS(class), on_sample_rate_changed);
gtk_widget_class_bind_template_callback(GTK_WIDGET_CLASS(class), on_interference_volume_changed);
gtk_widget_class_bind_template_callback(GTK_WIDGET_CLASS(class), on_analog_speed_controls_changed); gtk_widget_class_bind_template_callback(GTK_WIDGET_CLASS(class), on_analog_speed_controls_changed);
gtk_widget_class_bind_template_callback(GTK_WIDGET_CLASS(class), on_rumble_mode_changed); gtk_widget_class_bind_template_callback(GTK_WIDGET_CLASS(class), on_rumble_mode_changed);

View File

@ -573,6 +573,8 @@ Author: Maximilian Mader
</child> </child>
<child> <child>
<object class="GtkComboBoxText" id="sample_rate_selector"> <object class="GtkComboBoxText" id="sample_rate_selector">
<property name="margin_top">5</property>
<property name="margin_bottom">10</property>
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">False</property> <property name="can_focus">False</property>
<items> <items>
@ -590,6 +592,35 @@ Author: Maximilian Mader
<property name="position">3</property> <property name="position">3</property>
</packing> </packing>
</child> </child>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Interference volume:</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">4</property>
</packing>
</child>
<child>
<object class="GtkScale" id="interference_volume_slider">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="adjustment">byteAdjustment</property>
<property name="round_digits">0</property>
<property name="digits">0</property>
<property name="value_pos">left</property>
<signal name="value-changed" handler="on_interference_volume_changed" swapped="no"/>
<signal name="format-value" handler="format_scale_value_pct" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">5</property>
</packing>
</child>
</object> </object>
<packing> <packing>
<property name="position">2</property> <property name="position">2</property>
@ -976,4 +1007,10 @@ Author: Maximilian Mader
</row> </row>
</data> </data>
</object> </object>
<object class="GtkAdjustment" id="byteAdjustment">
<property name="upper">255</property>
<property name="step_increment">1</property>
<property name="page_increment">8</property>
</object>
</interface> </interface>

View File

@ -37,7 +37,7 @@ Author: Maximilian Mader
<property name="can_focus">False</property> <property name="can_focus">False</property>
<property name="type_hint">normal</property> <property name="type_hint">normal</property>
<property name="program_name">SameBoy</property> <property name="program_name">SameBoy</property>
<property name="copyright" translatable="yes">Copyright © 2015-2019 Lior Halphon</property> <property name="copyright" translatable="yes">Copyright © 2015-2021 Lior Halphon</property>
<property name="website">https://sameboy.github.io</property> <property name="website">https://sameboy.github.io</property>
<property name="website_label" translatable="yes">sameboy.github.io</property> <property name="website_label" translatable="yes">sameboy.github.io</property>
<property name="authors">Lior Halphon https://github.com/LIJI32 <property name="authors">Lior Halphon https://github.com/LIJI32

View File

@ -103,7 +103,7 @@ GB_model_t config_get_model_type(GuiData *gui_data) {
GtkWidget *menubar_to_menu(GtkMenuBar *menubar) { GtkWidget *menubar_to_menu(GtkMenuBar *menubar) {
GtkWidget *menu = gtk_menu_new(); GtkWidget *menu = gtk_menu_new();
g_autoptr(GList) iter = gtk_container_get_children(GTK_CONTAINER(menubar)); g_autoptr(GList) iter = gtk_container_get_children(GTK_CONTAINER(menubar));
while (iter) { while (iter) {
GtkWidget *item = GTK_WIDGET(iter->data); GtkWidget *item = GTK_WIDGET(iter->data);
gtk_widget_reparent(item, menu); gtk_widget_reparent(item, menu);
@ -157,3 +157,12 @@ gboolean scroll_to_bottom(GtkTextView *textview, GtkTextMark *mark) {
return true; return true;
} }
gchar* format_scale_value_pct(GtkScale *scale, gdouble value) {
GtkAdjustment *adj = gtk_range_get_adjustment(GTK_RANGE(scale));
gdouble lower = gtk_adjustment_get_lower(adj);
gdouble upper = gtk_adjustment_get_upper(adj);
gdouble range = fabs(upper - lower);
gdouble pct = (value / range) * 100.0;
return g_strdup_printf ("%.1f%% ", pct);
}

View File

@ -27,4 +27,6 @@ void set_combo_box_row_separator_func(GtkContainer *container);
gboolean scroll_to_bottom(GtkTextView *textview, GtkTextMark *mark); gboolean scroll_to_bottom(GtkTextView *textview, GtkTextMark *mark);
gchar* format_scale_value_pct(GtkScale *scale, gdouble value);
#endif #endif