From f3f2e66faf1dc2764e760c6ab237db2706134aa1 Mon Sep 17 00:00:00 2001 From: Maximilian Mader Date: Fri, 27 Sep 2019 23:10:28 +0200 Subject: [PATCH] [GTK3] More work on preferences done --- gtk3/macros.h | 10 +++ gtk3/main.c | 55 ++++++++++------ gtk3/resources/gtk/menus-common.ui | 1 + gtk3/resources/ui/window.ui | 101 +++++++++++++++++------------ gtk3/settings.c | 61 ++++++++++++++--- gtk3/settings.h | 34 ++++++---- 6 files changed, 182 insertions(+), 80 deletions(-) create mode 100644 gtk3/macros.h diff --git a/gtk3/macros.h b/gtk3/macros.h new file mode 100644 index 0000000..74874f4 --- /dev/null +++ b/gtk3/macros.h @@ -0,0 +1,10 @@ +#ifndef macros_h +#define macros_h + +#define str(x) #x +#define xstr(x) str(x) +#define get_object(id) gtk_builder_get_object(builder, id) +#define gtkget(type, id) type(gtk_builder_get_object(builder, id)) +#define itoa(val) g_strdup_printf("%i", val) + +#endif /* macros_h */ diff --git a/gtk3/main.c b/gtk3/main.c index 4a4d1b3..da6e110 100644 --- a/gtk3/main.c +++ b/gtk3/main.c @@ -6,12 +6,10 @@ #include #include +#include "macros.h" #include "settings.h" #include "shader.h" -#define str(x) #x -#define xstr(x) str(x) - typedef struct UserData { bool fullscreen; GFile *file; @@ -57,11 +55,6 @@ static uint32_t tileset_buffer[tileset_buffer_length] = {0}; static const size_t tilemap_buffer_length = 256 * 256 * 4; static uint32_t tilemap_buffer[tilemap_buffer_length] = {0}; -// Returns a GObject by ID from our GtkBuilder instance -static GObject *get_object(gchararray id) { - return gtk_builder_get_object(builder, id); -} - static unsigned char number_of_buffers(void) { bool should_blend = true; @@ -296,11 +289,11 @@ G_MODULE_EXPORT void gl_draw() { G_MODULE_EXPORT void gl_finish() { } -G_MODULE_EXPORT void on_vram_viewer_realize(gpointer visible) { +G_MODULE_EXPORT void on_vram_viewer_realize() { vram_viewer_visible = true; } -G_MODULE_EXPORT void on_vram_viewer_unrealize(gpointer visible) { +G_MODULE_EXPORT void on_vram_viewer_unrealize() { vram_viewer_visible = false; } @@ -412,7 +405,19 @@ G_MODULE_EXPORT void on_rewind_duration_changed(GtkWidget *w, gpointer user_data G_MODULE_EXPORT void on_boot_rom_location_changed(GtkWidget *w, gpointer user_data_gptr) { GtkComboBox *box = GTK_COMBO_BOX(w); - g_print("New value: %s\n", gtk_combo_box_get_active_id(box)); + const gchar *id = gtk_combo_box_get_active_id(box); + + if (g_strcmp0(id, "other") == 0) { + g_print("TODO: Open path picker\n"); + update_boot_rom_selector(builder); + } + else { + config.boot_rom_path = (gchar *)id; + } +} + +G_MODULE_EXPORT void on_color_menubar_override_changed(GtkWidget *w, gpointer user_data_gptr) { + config.menubar_override = (gchar *)gtk_combo_box_get_active_id(GTK_COMBO_BOX(w)); } // This functions gets called immediately after registration of the GApplication @@ -422,18 +427,25 @@ static void startup(GApplication *app, gpointer user_data_gptr) { builder = gtk_builder_new_from_resource(RESOURCE_PREFIX "ui/window.ui"); gtk_builder_connect_signals(builder, NULL); + // Setup application actions g_action_map_add_action_entries(G_ACTION_MAP(app), app_entries, G_N_ELEMENTS(app_entries), app); - GtkWindow *preferences = GTK_WINDOW(get_object("preferences")); - set_combo_box_row_separator_func(GTK_CONTAINER(preferences)); +#if NDEBUG + // Disable when not compiled in debug mode + g_simple_action_set_enabled(G_SIMPLE_ACTION(g_action_map_lookup_action(G_ACTION_MAP(app), "open_gtk_debugger")), false); + // Remove the menubar override + gtk_widget_destroy(gtkget(GTK_WIDGET, "menubar_override_selector_label")); + gtk_widget_destroy(gtkget(GTK_WIDGET, "menubar_override_selector")); +#endif + + GtkWindow *preferences = GTK_WINDOW(get_object("preferences")); + + g_signal_connect(preferences, "realize", G_CALLBACK(on_preferences_realize), (gpointer) builder); init_settings(user_data->config_path, preferences); vram_viewer = GTK_WINDOW(get_object("vram_viewer")); - set_combo_box_row_separator_func(GTK_CONTAINER(vram_viewer)); - memory_viewer = GTK_WINDOW(get_object("memory_viewer")); - set_combo_box_row_separator_func(GTK_CONTAINER(memory_viewer)); console = GTK_WINDOW(get_object("console")); printer = GTK_WINDOW(get_object("printer")); @@ -446,6 +458,11 @@ static void startup(GApplication *app, gpointer user_data_gptr) { gl_area = GTK_GL_AREA(gtk_gl_area_new()); gtk_gl_area_set_auto_render(gl_area, false); + // Insert separators into `GtkComboBox`es + set_combo_box_row_separator_func(GTK_CONTAINER(preferences)); + set_combo_box_row_separator_func(GTK_CONTAINER(vram_viewer)); + set_combo_box_row_separator_func(GTK_CONTAINER(memory_viewer)); + // Connect signal handlers g_signal_connect(gl_area, "realize", G_CALLBACK(gl_init), NULL); g_signal_connect(gl_area, "render", G_CALLBACK(gl_draw), NULL); @@ -468,9 +485,10 @@ static void startup(GApplication *app, gpointer user_data_gptr) { gtk_container_add(GTK_CONTAINER(main_window), GTK_WIDGET(gl_area)); // Handle the whole menubar situation … + GMenuModel *menubar = get_menu_model(app, "menubar"); + if (show_menubar()) { // Show a classic menubar - GMenuModel *menubar = get_menu_model(app, "menubar"); gtk_application_set_menubar(GTK_APPLICATION(app), menubar); } else { @@ -483,8 +501,7 @@ static void startup(GApplication *app, gpointer user_data_gptr) { // Hook menubar up to the hamburger button GtkMenuButton *hamburger_button = GTK_MENU_BUTTON(get_object("hamburger_button")); - GMenuModel *hamburger_menu = get_menu_model(app, "menubar"); - gtk_menu_button_set_menu_model(hamburger_button, hamburger_menu); + gtk_menu_button_set_menu_model(hamburger_button, menubar); } gtk_window_set_title(GTK_WINDOW(main_window), "SameBoy"); diff --git a/gtk3/resources/gtk/menus-common.ui b/gtk3/resources/gtk/menus-common.ui index 276a7ef..07fdb16 100644 --- a/gtk3/resources/gtk/menus-common.ui +++ b/gtk3/resources/gtk/menus-common.ui @@ -388,6 +388,7 @@ Author: Maximilian Mader Show GTK Debugger app.open_gtk_debugger + action-disabled diff --git a/gtk3/resources/ui/window.ui b/gtk3/resources/ui/window.ui index 9072597..531d204 100644 --- a/gtk3/resources/ui/window.ui +++ b/gtk3/resources/ui/window.ui @@ -318,13 +318,7 @@ Maximilian Mader https://github.com/max-m False 5 10 - 0 - auto - - Use Built-in Boot ROMs - <separator> - Other - + @@ -346,13 +340,11 @@ Maximilian Mader https://github.com/max-m - + True False 5 10 - 0 - 10 10 Seconds 30 Seconds @@ -394,13 +386,12 @@ Maximilian Mader https://github.com/max-m - + True False 5 10 dmg_models - 3 0 @@ -431,13 +422,11 @@ Maximilian Mader https://github.com/max-m - + True False 5 10 - 0 - SGB1_NTSC Super Game Boy (NTSC) Super Game Boy (PAL) @@ -464,13 +453,12 @@ Maximilian Mader https://github.com/max-m - + True False 5 10 cgb_models - 5 0 @@ -548,13 +536,11 @@ Maximilian Mader https://github.com/max-m - + True False 5 10 - 0 - nearest_neighbour Nearest Neighbor (Pixelated) Bilinear (Blurry) @@ -591,13 +577,11 @@ Maximilian Mader https://github.com/max-m - + True False 5 10 - 2 - emulate_hardware Disabled Correct Color Curves @@ -613,14 +597,30 @@ Maximilian Mader https://github.com/max-m - + + Keep Aspect Ratio + True + True + False + 5 + 10 + True + + + + False + True + 4 + + + + Use Integer Scaling True True False 5 10 - True True @@ -631,21 +631,32 @@ Maximilian Mader https://github.com/max-m - - Keep Aspect Ratio - True - True - False - 5 - 10 - True - True - + + False + False + Main Menu Override False True - 4 + 6 + + + + + False + False + + Automatic + Force Menubar + Force Hamburger Menu + + + + + False + True + 7 @@ -712,12 +723,11 @@ Maximilian Mader https://github.com/max-m - + True False 5 10 - 0 Disabled (Keep DC Offset) Accurate (Emulate Hardware) @@ -806,7 +816,6 @@ Maximilian Mader https://github.com/max-m 5 5 0 - 0 Player 1 Player 2 @@ -873,7 +882,6 @@ Maximilian Mader https://github.com/max-m 5 10 0 - none None @@ -1098,6 +1106,19 @@ Maximilian Mader https://github.com/max-m True True in + + + True + False + none + + + True + False + + + + diff --git a/gtk3/settings.c b/gtk3/settings.c index c6af238..e5e9ac0 100644 --- a/gtk3/settings.c +++ b/gtk3/settings.c @@ -13,7 +13,7 @@ void print_config(config_t *config) { g_print("[%s]\n", #group_name); \ members -#define EXPAND_GROUP_MEMBER(member, key_type) \ +#define EXPAND_GROUP_MEMBER(member, key_type, default_value) \ g_print("%s="FORMAT_FOR_KEY_TYPE(key_type)"\n", #member, config->member); EXPAND_CONFIG @@ -33,10 +33,13 @@ void load_config_from_key_file(config_t *config, GKeyFile *key_file) { members \ } -#define EXPAND_GROUP_MEMBER(member, key_type) \ +#define EXPAND_GROUP_MEMBER(member, key_type, default_value) \ config->member = g_key_file_get_##key_type(key_file, group_name, #member, &error); \ - print_config_error(error); \ - g_clear_error(&error); + if (error != NULL) { \ + config->member = default_value; \ + print_config_error(error); \ + g_clear_error(&error); \ + } EXPAND_CONFIG @@ -57,10 +60,10 @@ void save_config_to_key_file(config_t *config, GKeyFile *key_file) { group_name = #name; \ members -#define EXPAND_GROUP_MEMBER_IF_0(member, key_type) \ +#define EXPAND_GROUP_MEMBER_IF_0(member, key_type, default_value) \ g_key_file_set_##key_type(key_file, group_name, #member, config->member); -#define EXPAND_GROUP_MEMBER_IF_1(member, key_type) \ +#define EXPAND_GROUP_MEMBER_IF_1(member, key_type, default_value) \ if (config->member != NULL) { \ g_key_file_set_##key_type(key_file, group_name, #member, config->member); \ } \ @@ -76,9 +79,9 @@ void save_config_to_key_file(config_t *config, GKeyFile *key_file) { } \ } -#define EXPAND_GROUP_MEMBER_IF_EVAL(y, member, key_type) EXPAND_GROUP_MEMBER_IF_ ## y(member, key_type) -#define EXPAND_GROUP_MEMBER_IF(member, key_type, is_pointer) EXPAND_GROUP_MEMBER_IF_EVAL(is_pointer, member, key_type) -#define EXPAND_GROUP_MEMBER(member, key_type) EXPAND_GROUP_MEMBER_IF(member, key_type, GTYPE_IS_POINTER(key_type)) +#define EXPAND_GROUP_MEMBER_IF_EVAL(y, member, key_type, default_value) EXPAND_GROUP_MEMBER_IF_ ## y(member, key_type, default_value) +#define EXPAND_GROUP_MEMBER_IF(member, key_type, is_pointer, default_value) EXPAND_GROUP_MEMBER_IF_EVAL(is_pointer, member, key_type, default_value) +#define EXPAND_GROUP_MEMBER(member, key_type, default_value) EXPAND_GROUP_MEMBER_IF(member, key_type, GTYPE_IS_POINTER(key_type), default_value) EXPAND_CONFIG @@ -90,6 +93,33 @@ void save_config_to_key_file(config_t *config, GKeyFile *key_file) { #undef EXPAND_GROUP_MEMBER_IF_1 } +G_MODULE_EXPORT void on_preferences_realize(GtkWidget *w, gpointer builder_ptr) { + GtkWindow *preferences = GTK_WINDOW(w); + GtkBuilder *builder = (GtkBuilder *) builder_ptr; + + update_boot_rom_selector(builder); + + // Hook up the static preferences + gtk_combo_box_set_active_id(gtkget(GTK_COMBO_BOX, "rewind_duration_selector"), itoa(config.rewind_duration)); + gtk_combo_box_set_active_id(gtkget(GTK_COMBO_BOX, "dmg_revision_selector"), config.dmg_revision_name); + gtk_combo_box_set_active_id(gtkget(GTK_COMBO_BOX, "sgb_revision_selector"), config.sgb_revision_name); + gtk_combo_box_set_active_id(gtkget(GTK_COMBO_BOX, "cgb_revision_selector"), config.cgb_revision_name); + gtk_combo_box_set_active_id(gtkget(GTK_COMBO_BOX, "shader_selector"), config.shader); + gtk_combo_box_set_active_id(gtkget(GTK_COMBO_BOX, "color_correction_selector"), config.color_correction_id); + gtk_toggle_button_set_active(gtkget(GTK_TOGGLE_BUTTON, "integer_scaling_toggle"), config.use_integer_scaling); + gtk_toggle_button_set_active(gtkget(GTK_TOGGLE_BUTTON, "aspect_ratio_toggle"), config.keep_aspect_ratio); + gtk_combo_box_set_active_id(gtkget(GTK_COMBO_BOX, "highpass_filter_selector"), config.high_pass_filter_id); + +#if ! NDEBUG + gtk_combo_box_set_active_id(gtkget(GTK_COMBO_BOX, "menubar_override_selector"), config.menubar_override); +#else + if (gtkget(GTK_COMBO_BOX, "menubar_override_selector") != NULL) { + gtk_widget_destroy(GTK_WIDGET(gtkget(GTK_COMBO_BOX, "menubar_override_selector"))); + gtk_widget_destroy(GTK_WIDGET(gtkget(GTK_COMBO_BOX, "menubar_override_selector_label"))); + } +#endif +} + void init_settings(gchar *path, GtkWindow *preferences) { free_settings(); key_file = g_key_file_new(); @@ -148,6 +178,19 @@ void free_settings(void) { } } +void update_boot_rom_selector(GtkBuilder *builder) { + GtkComboBoxText *combo_box = gtkget(GTK_COMBO_BOX_TEXT, "boot_rom_selector"); + gtk_combo_box_text_remove_all(combo_box); + gtk_combo_box_text_append(combo_box, "auto", "Use Built-in Boot ROMs"); + gtk_combo_box_set_active_id(GTK_COMBO_BOX(combo_box), "auto"); + if (config.boot_rom_path != NULL && !g_str_equal(config.boot_rom_path, "auto") && !g_str_equal(config.boot_rom_path, "other")) { + gtk_combo_box_text_append(combo_box, config.boot_rom_path, config.boot_rom_path); + gtk_combo_box_set_active_id(GTK_COMBO_BOX(combo_box), config.boot_rom_path); + } + gtk_combo_box_text_append_text(combo_box, ""); + gtk_combo_box_text_append(combo_box, "other", "Other"); +} + enum menubar_override get_show_menubar(void) { if (config.menubar_override == NULL) goto default_value; diff --git a/gtk3/settings.h b/gtk3/settings.h index c46527d..9c51bf2 100644 --- a/gtk3/settings.h +++ b/gtk3/settings.h @@ -3,6 +3,7 @@ #include #include +#include "macros.h" #define SETTINGS_FILE "sameboy-gtk3-settings.ini" @@ -22,23 +23,28 @@ #define GTYPE_IS_POINTER_boolean 0 // Note: Make sure to use a member name only once for the whole config struct +// +// Macro usage: +// EXPAND_CONFIG(EXPAND_GROUP(…) EXPAND_GROUP(…) …) +// EXPAND_GROUP(group_name, group_members) +// EXPAND_GROUP_MEMBER(member_name, key_type, default_value) #define EXPAND_CONFIG \ EXPAND_GROUP(Emulation, \ - EXPAND_GROUP_MEMBER(boot_rom_path, string) /* overrides search location for boot ROMs by name */ \ - EXPAND_GROUP_MEMBER(rewind_duration, integer) \ - EXPAND_GROUP_MEMBER(dmg_revision_name, string) \ - EXPAND_GROUP_MEMBER(sgb_revision_name, string) \ - EXPAND_GROUP_MEMBER(cgb_revision_name, string) \ + EXPAND_GROUP_MEMBER(boot_rom_path, string, "auto") /* overrides search location for boot ROMs by name */ \ + EXPAND_GROUP_MEMBER(rewind_duration, integer, 0) \ + EXPAND_GROUP_MEMBER(dmg_revision_name, string, "DMG_CPU_C") \ + EXPAND_GROUP_MEMBER(sgb_revision_name, string, "SGB2") \ + EXPAND_GROUP_MEMBER(cgb_revision_name, string, "CPU_CGB_E") \ ) \ EXPAND_GROUP(Video, \ - EXPAND_GROUP_MEMBER(shader, string) \ - EXPAND_GROUP_MEMBER(color_correction_id, string) \ - EXPAND_GROUP_MEMBER(keep_aspect_ratio, boolean) \ - EXPAND_GROUP_MEMBER(use_integer_scaling, boolean) \ - EXPAND_GROUP_MEMBER(menubar_override, string) \ + EXPAND_GROUP_MEMBER(shader, string, "NearestNeighbour") \ + EXPAND_GROUP_MEMBER(color_correction_id, string, "emulate_hardware") \ + EXPAND_GROUP_MEMBER(keep_aspect_ratio, boolean, true) \ + EXPAND_GROUP_MEMBER(use_integer_scaling, boolean, true) \ + EXPAND_GROUP_MEMBER(menubar_override, string, "auto") \ ) \ EXPAND_GROUP(Audio, \ - EXPAND_GROUP_MEMBER(high_pass_filter_id, string) \ + EXPAND_GROUP_MEMBER(high_pass_filter_id, string, "emulate_hardware") \ ) \ EXPAND_GROUP(Controls, \ \ @@ -46,7 +52,7 @@ typedef struct config_t { #define EXPAND_GROUP(group_name, members) members -#define EXPAND_GROUP_MEMBER(member, key_type) GTYPE_OF_KEY_TYPE(key_type) member; +#define EXPAND_GROUP_MEMBER(member, key_type, default_value) GTYPE_OF_KEY_TYPE(key_type) member; EXPAND_CONFIG #undef EXPAND_GROUP #undef EXPAND_GROUP_MEMBER @@ -62,6 +68,8 @@ gchar* settings_file_path; GKeyFile *key_file; config_t config; +G_MODULE_EXPORT void on_preferences_realize(GtkWidget *w, gpointer builder_ptr); + void print_config(config_t *config); void load_config_from_key_file(config_t *config, GKeyFile *key_file); @@ -70,6 +78,8 @@ int load_settings(void); void save_settings(void); void free_settings(void); +void update_boot_rom_selector(GtkBuilder *builder); + enum menubar_override get_show_menubar(void); void set_show_menubar(enum menubar_override);