[GTK3] Load/save settings from/to file

This commit is contained in:
Maximilian Mader 2019-09-25 02:48:07 +02:00
parent 6e263cd22a
commit 959f0cc88e
Signed by: Max
GPG Key ID: F71D56A3151C4FB3
4 changed files with 161 additions and 29 deletions

View File

@ -15,8 +15,8 @@
typedef struct UserData { typedef struct UserData {
bool fullscreen; bool fullscreen;
GFile *file; GFile *file;
const gchar *bootrom_path; gchar *bootrom_path;
const gchar *config_path; gchar *config_path;
GB_model_t model; GB_model_t model;
} UserData; } UserData;
@ -98,12 +98,12 @@ static void update_viewport(void) {
double x_factor = win_width / (double) GB_get_screen_width(&gb); double x_factor = win_width / (double) GB_get_screen_width(&gb);
double y_factor = win_height / (double) GB_get_screen_height(&gb); double y_factor = win_height / (double) GB_get_screen_height(&gb);
if (true /*configuration.scaling_mode == GB_SDL_SCALING_INTEGER_FACTOR*/) { if (config.use_integer_scaling) {
x_factor = (int)(x_factor); x_factor = (int)(x_factor);
y_factor = (int)(y_factor); y_factor = (int)(y_factor);
} }
if (true /*configuration.scaling_mode != GB_SDL_SCALING_ENTIRE_WINDOW*/) { if (config.keep_aspect_ratio) {
if (x_factor > y_factor) { if (x_factor > y_factor) {
x_factor = y_factor; x_factor = y_factor;
} }
@ -245,7 +245,7 @@ G_MODULE_EXPORT void gl_init() {
renderer = (char *) glGetString(GL_RENDERER); renderer = (char *) glGetString(GL_RENDERER);
g_print("GtkGLArea on %s\n", renderer ? renderer : "Unknown"); g_print("GtkGLArea on %s\n", renderer ? renderer : "Unknown");
if (!init_shader_with_name(&shader, /*configuration.filter*/ "OmniScale")) { if (config.shader == NULL || !init_shader_with_name(&shader, config.shader)) {
init_shader_with_name(&shader, "NearestNeighbor"); init_shader_with_name(&shader, "NearestNeighbor");
} }
} }
@ -380,6 +380,7 @@ static void shutdown(GApplication *app, GFile **files, gint n_files, const gchar
g_print("SHUTDOWN\n"); g_print("SHUTDOWN\n");
save_settings(); save_settings();
free_settings();
} }
// This function gets called after the parsing of the commandline options has occurred. // This function gets called after the parsing of the commandline options has occurred.
@ -520,7 +521,7 @@ static void run(UserData *user_data) {
// GB_set_sample_rate(&gb, have_aspec.freq); // GB_set_sample_rate(&gb, have_aspec.freq);
// GB_set_color_correction_mode(&gb, configuration.color_correction_mode); // GB_set_color_correction_mode(&gb, configuration.color_correction_mode);
// GB_set_highpass_filter_mode(&gb, configuration.highpass_mode); // GB_set_highpass_filter_mode(&gb, configuration.highpass_mode);
// GB_set_rewind_length(&gb, configuration.rewind_length); GB_set_rewind_length(&gb, config.rewind_duration);
// GB_set_update_input_hint_callback(&gb, handle_events); // GB_set_update_input_hint_callback(&gb, handle_events);
// GB_apu_set_sample_callback(&gb, gb_audio_callback); // GB_apu_set_sample_callback(&gb, gb_audio_callback);
} }

View File

@ -556,19 +556,19 @@ Maximilian Mader https://github.com/max-m</property>
<property name="active">0</property> <property name="active">0</property>
<property name="active_id">nearest_neighbour</property> <property name="active_id">nearest_neighbour</property>
<items> <items>
<item id="nearest_neighbour" translatable="yes">Nearest Neighbor (Pixelated)</item> <item id="NearestNeighbor" translatable="yes">Nearest Neighbor (Pixelated)</item>
<item id="bilinear" translatable="yes">Bilinear (Blurry)</item> <item id="Bilinear" translatable="yes">Bilinear (Blurry)</item>
<item id="smooth_bilinear" translatable="yes">Smooth Bilinear (Less blurry)</item> <item id="SmoothBilinear" translatable="yes">Smooth Bilinear (Less blurry)</item>
<item id="lcd" translatable="yes">LCD Display</item> <item id="LCD" translatable="yes">LCD Display</item>
<item id="crt" translatable="yes">CRT Display</item> <item id="CRT" translatable="yes">CRT Display</item>
<item id="scale2x" translatable="yes">Scale2x</item> <item id="Scale2x" translatable="yes">Scale2x</item>
<item id="scale4x" translatable="yes">Scale4x</item> <item id="Scale4x" translatable="yes">Scale4x</item>
<item id="scale2x_aa" translatable="yes">Anti-aliased Scale2x</item> <item id="AAScale2x" translatable="yes">Anti-aliased Scale2x</item>
<item id="scale4x_aa" translatable="yes">Anti-aliased Scale4x</item> <item id="AAScale4x" translatable="yes">Anti-aliased Scale4x</item>
<item id="hq2x" translatable="yes">HQ2x</item> <item id="HQ2x" translatable="yes">HQ2x</item>
<item id="omniscale" translatable="yes">OmniScale (Any factor)</item> <item id="OmniScale" translatable="yes">OmniScale (Any factor)</item>
<item id="omniscale_legacy" translatable="yes">OmniScale Legacy</item> <item id="OmniScaleLegacy" translatable="yes">OmniScale Legacy</item>
<item id="omniscale_legacy_aa" translatable="yes">Anti-aliased OmniScale Legacy</item> <item id="AAOmniScaleLegacy" translatable="yes">Anti-aliased OmniScale Legacy</item>
</items> </items>
<signal name="changed" handler="on_graphic_filter_changed" swapped="no"/> <signal name="changed" handler="on_graphic_filter_changed" swapped="no"/>
</object> </object>
@ -630,6 +630,24 @@ Maximilian Mader https://github.com/max-m</property>
<property name="position">4</property> <property name="position">4</property>
</packing> </packing>
</child> </child>
<child>
<object class="GtkCheckButton">
<property name="label" translatable="yes">Use Integer Scaling</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="margin_top">5</property>
<property name="margin_bottom">10</property>
<property name="active">True</property>
<property name="draw_indicator">True</property>
<signal name="toggled" handler="on_use_integer_scaling_changed" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">4</property>
</packing>
</child>
</object> </object>
<packing> <packing>
<property name="position">1</property> <property name="position">1</property>

View File

@ -1,9 +1,55 @@
#include "settings.h" #include "settings.h"
void init_settings(const gchar *path) { static void print_config_error(GError *error) {
key_file = g_key_file_new(); if (error == NULL) return;
GError *error = NULL; if (error->domain != G_KEY_FILE_ERROR_GROUP_NOT_FOUND && error->domain != G_KEY_FILE_ERROR_KEY_NOT_FOUND) {
g_printerr("Config error: %s\n", error->message);
}
}
void print_config(config_t *config) {
#define EXPAND_GROUP(group_name, members) \
g_print("[%s]\n", #group_name); \
members
#define EXPAND_GROUP_MEMBER(member, key_type) \
g_print("%s="FORMAT_FOR_KEY_TYPE(key_type)"\n", #member, config->member);
EXPAND_CONFIG
#undef EXPAND_GROUP
#undef EXPAND_GROUP_MEMBER
}
void load_config_from_key_file(config_t *config, GKeyFile *key_file) {
static GError *error = NULL;
gchar *group_name;
#define EXPAND_GROUP(name, members) \
group_name = #name; \
if (g_key_file_has_group(key_file, group_name)) { \
members \
}
#define EXPAND_GROUP_MEMBER(member, key_type) \
config->member = g_key_file_get_##key_type(key_file, group_name, #member, &error); \
print_config_error(error); \
if (error != NULL) g_clear_error(&error);
EXPAND_CONFIG
if (config->rewind_duration > 600) {
g_warning("Setting Emulation.rewind_duration too high might affect performance.\n");
}
#undef EXPAND_GROUP
#undef EXPAND_GROUP_MEMBER
}
void init_settings(gchar *path) {
free_settings();
key_file = g_key_file_new();
if (path != NULL) { if (path != NULL) {
settings_file_path = path; settings_file_path = path;
@ -15,15 +61,27 @@ void init_settings(const gchar *path) {
load_settings(); load_settings();
} }
void load_settings(void) { int load_settings(void) {
GError *error = NULL; GError *error = NULL;
g_print("Trying to load settings from %s\n", settings_file_path); g_print("Trying to load settings from %s\n", settings_file_path);
if (!g_key_file_load_from_file(key_file, settings_file_path, G_KEY_FILE_KEEP_COMMENTS | G_KEY_FILE_KEEP_TRANSLATIONS, &error)) { if (!g_key_file_load_from_file(key_file, settings_file_path, G_KEY_FILE_KEEP_COMMENTS | G_KEY_FILE_KEEP_TRANSLATIONS, &error)) {
g_warning("Error loading %s: %s", settings_file_path, error->message); if (error->domain == G_FILE_ERROR) {
g_error_free(error); g_warning("Unable to load %s: %s", settings_file_path, error->message);
} }
else if (error->domain == G_KEY_FILE_ERROR) {
g_warning("Failed to parse %s: %s", settings_file_path, error->message);
}
g_error_free(error);
return -1;
}
load_config_from_key_file(&config, key_file);
print_config(&config);
return 0;
} }
void save_settings(void) { void save_settings(void) {
@ -32,8 +90,15 @@ void save_settings(void) {
g_print("Trying to save settings to %s\n", settings_file_path); g_print("Trying to save settings to %s\n", settings_file_path);
if (!g_key_file_save_to_file(key_file, settings_file_path, &error)) { if (!g_key_file_save_to_file(key_file, settings_file_path, &error)) {
g_warning ("Error saving %s: %s", settings_file_path, error->message); g_warning ("Failed to save %s: %s", settings_file_path, error->message);
g_error_free(error); g_error_free(error);
return; return;
} }
} }
void free_settings(void) {
if (key_file != NULL) {
g_key_file_free(key_file);
key_file = NULL;
}
}

View File

@ -6,11 +6,59 @@
#define SETTINGS_FILE "sameboy-gtk3-settings.ini" #define SETTINGS_FILE "sameboy-gtk3-settings.ini"
GKeyFile *key_file; #define FORMAT_FOR_KEY_TYPE(type) KEY_FORMAT_##type
const gchar* settings_file_path; #define KEY_FORMAT_string "%s"
#define KEY_FORMAT_integer "%d"
#define KEY_FORMAT_boolean "%d"
void init_settings(const gchar *path); #define GTYPE_FOR_KEY_TYPE(type) GTYPE_##type
void load_settings(void); #define GTYPE_string gchar *
#define GTYPE_integer gint
#define GTYPE_boolean gboolean
// Note: Make sure to use a member name only once for the whole config struct
#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(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(Audio, \
EXPAND_GROUP_MEMBER(high_pass_filter_id, string) \
) \
EXPAND_GROUP(Controls, \
\
)
typedef struct config_t {
#define EXPAND_GROUP(group_name, members) members
#define EXPAND_GROUP_MEMBER(member, key_type) GTYPE_FOR_KEY_TYPE(key_type) member;
EXPAND_CONFIG
#undef EXPAND_GROUP
#undef EXPAND_GROUP_MEMBER
} config_t;
gchar* settings_file_path;
GKeyFile *key_file;
config_t config;
void print_config(config_t *config);
void load_config_from_key_file(config_t *config, GKeyFile *key_file);
void init_settings(gchar *path);
int load_settings(void);
void save_settings(void); void save_settings(void);
void free_settings(void);
enum scaling_mode get_scaling_mode(void);
void set_scaling_mode(enum scaling_mode);
#endif /* settings_h */ #endif /* settings_h */