2021-01-07 21:35:41 +00:00
|
|
|
#include "sameboy_application.h"
|
2021-01-09 18:09:15 +00:00
|
|
|
#include "config.h"
|
2021-01-07 21:35:41 +00:00
|
|
|
#include "widgets/main_window.h"
|
|
|
|
#include "widgets/about_dialog.h"
|
|
|
|
#include "widgets/preferences_window.h"
|
|
|
|
|
|
|
|
#define str(x) #x
|
|
|
|
#define xstr(x) str(x)
|
|
|
|
|
|
|
|
#define action_set_enabled(map, name, value) \
|
|
|
|
g_simple_action_set_enabled( \
|
|
|
|
G_SIMPLE_ACTION( \
|
|
|
|
g_action_map_lookup_action(G_ACTION_MAP(map), name) \
|
|
|
|
), \
|
|
|
|
value \
|
|
|
|
);
|
|
|
|
|
|
|
|
struct _SameBoyApplication {
|
|
|
|
GtkApplication parent;
|
|
|
|
|
2021-01-09 18:09:15 +00:00
|
|
|
struct CliOptionData cli_options;
|
|
|
|
|
2021-01-07 21:35:41 +00:00
|
|
|
const GThread *main_thread;
|
|
|
|
PreferencesWindow *preferences;
|
|
|
|
AboutDialog *about_dialog;
|
|
|
|
|
2021-01-09 18:09:15 +00:00
|
|
|
GDateTime *config_modification_date;
|
2021-01-07 21:35:41 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
G_DEFINE_TYPE(SameBoyApplication, sameboy_application, GTK_TYPE_APPLICATION);
|
|
|
|
|
|
|
|
static void sameboy_application_init(SameBoyApplication *app) {
|
2021-01-09 18:09:15 +00:00
|
|
|
g_debug("sameboy_application_init(%p)", app);
|
2021-01-07 21:35:41 +00:00
|
|
|
|
|
|
|
// Define our command line parameters
|
|
|
|
GOptionEntry entries[] = {
|
|
|
|
{ "version", 'v', G_OPTION_FLAG_NONE, G_OPTION_ARG_NONE, NULL, "Show the application version", NULL },
|
|
|
|
{ "fullscreen", 'f', G_OPTION_FLAG_NONE, G_OPTION_ARG_NONE, &app->cli_options.fullscreen, "Start in fullscreen mode", NULL },
|
|
|
|
{ "bootrom", 'b', G_OPTION_FLAG_NONE, G_OPTION_ARG_STRING, &app->cli_options.boot_rom_path, "Path to the boot ROM to use", "<file path>" },
|
|
|
|
{ "model", 'm', G_OPTION_FLAG_NONE, G_OPTION_ARG_STRING, NULL, "Override the model type to emulate", "<model type>" },
|
|
|
|
{ "config", 'c', G_OPTION_FLAG_NONE, G_OPTION_ARG_STRING, &app->cli_options.config_path, "Override the path of the configuration file", "<file path>" },
|
|
|
|
{ "no-gl", 's', G_OPTION_FLAG_NONE, G_OPTION_ARG_NONE, &app->cli_options.force_software_renderer, "Do not use OpenGL for rendering", NULL },
|
|
|
|
{ NULL }
|
|
|
|
};
|
|
|
|
|
|
|
|
// Setup our command line information
|
|
|
|
g_application_add_main_option_entries(G_APPLICATION(app), entries);
|
|
|
|
g_application_set_option_context_parameter_string(G_APPLICATION(app), "[FILE…]");
|
|
|
|
g_application_set_option_context_summary(G_APPLICATION(app), "SameBoy is an open source Game Boy (DMG) and Game Boy Color (CGB) emulator.");
|
|
|
|
}
|
|
|
|
|
|
|
|
static gint sameboy_application_handle_local_options(GApplication *gapp, GVariantDict *options) {
|
|
|
|
SameBoyApplication *app = SAMEBOY_APPLICATION(gapp);
|
|
|
|
g_debug("sameboy_application_handle_local_options");
|
|
|
|
|
|
|
|
guint32 count;
|
|
|
|
if (g_variant_dict_lookup(options, "version", "b", &count)) {
|
|
|
|
g_message("SameBoy v" xstr(VERSION));
|
|
|
|
return EXIT_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Handle model override
|
|
|
|
GVariant *model_name_var = g_variant_dict_lookup_value(options, "model", G_VARIANT_TYPE_STRING);
|
2021-01-09 18:09:15 +00:00
|
|
|
app->cli_options.model = -1;
|
|
|
|
|
2021-01-07 21:35:41 +00:00
|
|
|
if (model_name_var != NULL) {
|
|
|
|
const gchar *model_name = g_variant_get_string(model_name_var, NULL);
|
|
|
|
|
|
|
|
// TODO: Synchronize with GB_model_t (Core/gb.h)
|
|
|
|
if (g_str_has_prefix(model_name, "DMG")) {
|
|
|
|
if (g_str_has_suffix(model_name, "-B") || g_strcmp0(model_name, "DMG") == 0) {
|
|
|
|
app->cli_options.model = GB_MODEL_DMG_B;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
app->cli_options.model = GB_MODEL_DMG_B;
|
|
|
|
g_warning("Unsupported revision: %s\nFalling back to DMG-B", model_name);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (g_str_has_prefix(model_name, "SGB")) {
|
|
|
|
if (g_str_has_suffix(model_name, "-NTSC") || g_strcmp0(model_name, "SGB") == 0) {
|
|
|
|
app->cli_options.model = GB_MODEL_SGB;
|
|
|
|
}
|
|
|
|
else if (g_str_has_suffix(model_name, "-PAL")) {
|
|
|
|
app->cli_options.model = GB_MODEL_SGB | GB_MODEL_PAL_BIT;
|
|
|
|
}
|
|
|
|
else if (g_str_has_suffix(model_name, "2")) {
|
|
|
|
app->cli_options.model = GB_MODEL_SGB2;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
app->cli_options.model = GB_MODEL_SGB2;
|
|
|
|
g_warning("Unsupported revision: %s\nFalling back to SGB2", model_name);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (g_str_has_prefix(model_name, "CGB")) {
|
|
|
|
if (g_str_has_suffix(model_name, "-C")) {
|
|
|
|
app->cli_options.model = GB_MODEL_CGB_C;
|
|
|
|
}
|
|
|
|
else if (g_str_has_suffix(model_name, "-E") || g_strcmp0(model_name, "CGB") == 0) {
|
|
|
|
app->cli_options.model = GB_MODEL_CGB_E;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
app->cli_options.model = GB_MODEL_CGB_E;
|
|
|
|
g_warning("Unsupported revision: %s\nFalling back to CGB-E", model_name);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (g_str_has_prefix(model_name, "AGB")) {
|
|
|
|
app->cli_options.model = GB_MODEL_AGB;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
g_warning("Unknown model: %s", model_name);
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return G_APPLICATION_CLASS(sameboy_application_parent_class)->handle_local_options(G_APPLICATION(app), options);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void activate_open(GSimpleAction *action, GVariant *parameter, gpointer user_data) {
|
|
|
|
SameBoyApplication *app = SAMEBOY_APPLICATION(user_data);
|
|
|
|
MainWindow *window = SAMEBOY_MAIN_WINDOW(gtk_application_get_active_window(GTK_APPLICATION(app)));
|
|
|
|
}
|
|
|
|
|
|
|
|
static void activate_close(GSimpleAction *action, GVariant *parameter, gpointer user_data) {
|
|
|
|
SameBoyApplication *app = SAMEBOY_APPLICATION(user_data);
|
|
|
|
MainWindow *window = SAMEBOY_MAIN_WINDOW(gtk_application_get_active_window(GTK_APPLICATION(app)));
|
|
|
|
}
|
|
|
|
|
|
|
|
static void activate_reset(GSimpleAction *action, GVariant *parameter, gpointer user_data) {
|
|
|
|
SameBoyApplication *app = SAMEBOY_APPLICATION(user_data);
|
|
|
|
MainWindow *window = SAMEBOY_MAIN_WINDOW(gtk_application_get_active_window(GTK_APPLICATION(app)));
|
|
|
|
}
|
|
|
|
|
|
|
|
static void on_pause_changed(GSimpleAction *action, GVariant *parameter, gpointer user_data) {
|
|
|
|
SameBoyApplication *app = SAMEBOY_APPLICATION(user_data);
|
|
|
|
MainWindow *window = SAMEBOY_MAIN_WINDOW(gtk_application_get_active_window(GTK_APPLICATION(app)));
|
|
|
|
}
|
|
|
|
|
|
|
|
static void activate_show_console(GSimpleAction *action, GVariant *parameter, gpointer user_data) {
|
|
|
|
SameBoyApplication *app = SAMEBOY_APPLICATION(user_data);
|
|
|
|
MainWindow *window = SAMEBOY_MAIN_WINDOW(gtk_application_get_active_window(GTK_APPLICATION(app)));
|
|
|
|
main_window_open_console_window(window);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void activate_open_memory_viewer(GSimpleAction *action, GVariant *parameter, gpointer user_data) {
|
|
|
|
SameBoyApplication *app = SAMEBOY_APPLICATION(user_data);
|
|
|
|
MainWindow *window = SAMEBOY_MAIN_WINDOW(gtk_application_get_active_window(GTK_APPLICATION(app)));
|
|
|
|
main_window_open_memory_viewer_window(window);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void activate_open_vram_viewer(GSimpleAction *action, GVariant *parameter, gpointer user_data) {
|
|
|
|
SameBoyApplication *app = SAMEBOY_APPLICATION(user_data);
|
|
|
|
MainWindow *window = SAMEBOY_MAIN_WINDOW(gtk_application_get_active_window(GTK_APPLICATION(app)));
|
|
|
|
main_window_open_vram_viewer_window(window);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void activate_break_debugger(GSimpleAction *action, GVariant *parameter, gpointer user_data) {
|
|
|
|
SameBoyApplication *app = SAMEBOY_APPLICATION(user_data);
|
|
|
|
MainWindow *window = SAMEBOY_MAIN_WINDOW(gtk_application_get_active_window(GTK_APPLICATION(app)));
|
|
|
|
}
|
|
|
|
|
|
|
|
static void on_developer_mode_changed(GSimpleAction *action, GVariant *parameter, gpointer user_data) {
|
|
|
|
SameBoyApplication *app = SAMEBOY_APPLICATION(user_data);
|
|
|
|
MainWindow *window = SAMEBOY_MAIN_WINDOW(gtk_application_get_active_window(GTK_APPLICATION(app)));
|
|
|
|
}
|
|
|
|
|
|
|
|
static void activate_clear_console(GSimpleAction *action, GVariant *parameter, gpointer user_data) {
|
|
|
|
SameBoyApplication *app = SAMEBOY_APPLICATION(user_data);
|
|
|
|
MainWindow *window = SAMEBOY_MAIN_WINDOW(gtk_application_get_active_window(GTK_APPLICATION(app)));
|
|
|
|
}
|
|
|
|
|
|
|
|
static void activate_open_gtk_debugger(GSimpleAction *action, GVariant *parameter, gpointer user_data) {
|
|
|
|
gtk_window_set_interactive_debugging(true);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void activate_quit(GSimpleAction *action, GVariant *parameter, gpointer user_data) {
|
|
|
|
SameBoyApplication *app = SAMEBOY_APPLICATION(user_data);
|
|
|
|
MainWindow *window = SAMEBOY_MAIN_WINDOW(gtk_application_get_active_window(GTK_APPLICATION(app)));
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Opens the global about dialog.
|
|
|
|
*/
|
|
|
|
static void activate_about(GSimpleAction *action, GVariant *parameter, gpointer user_data) {
|
|
|
|
SameBoyApplication *app = SAMEBOY_APPLICATION(user_data);
|
|
|
|
gtk_dialog_run(GTK_DIALOG(app->about_dialog));
|
|
|
|
gtk_widget_hide(GTK_WIDGET(app->about_dialog));
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Opens the global preferences menu.
|
|
|
|
*/
|
|
|
|
static void activate_preferences(GSimpleAction *action, GVariant *parameter, gpointer user_data) {
|
|
|
|
SameBoyApplication *app = SAMEBOY_APPLICATION(user_data);
|
|
|
|
gtk_widget_show_all(GTK_WIDGET(app->preferences));
|
|
|
|
}
|
|
|
|
|
|
|
|
static void on_mute_changed(GSimpleAction *action, GVariant *parameter, gpointer user_data) {
|
|
|
|
SameBoyApplication *app = SAMEBOY_APPLICATION(user_data);
|
|
|
|
MainWindow *window = SAMEBOY_MAIN_WINDOW(gtk_application_get_active_window(GTK_APPLICATION(app)));
|
|
|
|
}
|
|
|
|
|
|
|
|
static const GActionEntry file_entries[] = {
|
|
|
|
{ "open", activate_open, NULL, NULL, NULL },
|
|
|
|
{ "close", activate_close, NULL, NULL, NULL },
|
|
|
|
};
|
|
|
|
|
|
|
|
static const GActionEntry emulation_entries[] = {
|
|
|
|
{ "reset", activate_reset, NULL, NULL, NULL },
|
|
|
|
{ "pause", NULL, NULL, "false", on_pause_changed },
|
|
|
|
{ "save_state", NULL, NULL, NULL, NULL },
|
|
|
|
{ "load_state", NULL, NULL, NULL, NULL },
|
|
|
|
};
|
|
|
|
|
|
|
|
static const GActionEntry developer_entries[] = {
|
|
|
|
{ "show_console", activate_show_console, NULL, NULL, NULL },
|
|
|
|
{ "open_memory_viewer", activate_open_memory_viewer, NULL, NULL, NULL },
|
|
|
|
{ "open_vram_viewer", activate_open_vram_viewer, NULL, NULL, NULL },
|
|
|
|
{ "break_debugger", activate_break_debugger, NULL, NULL, NULL },
|
|
|
|
{ "toggle_developer_mode", NULL, NULL, "false", on_developer_mode_changed },
|
|
|
|
{ "clear_console", activate_clear_console, NULL, NULL, NULL },
|
|
|
|
{ "open_gtk_debugger", activate_open_gtk_debugger, NULL, NULL, NULL },
|
|
|
|
};
|
|
|
|
|
|
|
|
static GActionEntry app_entries[] = {
|
|
|
|
{ "quit", activate_quit, NULL, NULL, NULL },
|
|
|
|
{ "about", activate_about, NULL, NULL, NULL },
|
|
|
|
{ "preferences", activate_preferences, NULL, NULL, NULL },
|
|
|
|
{ "toggle_mute", NULL, NULL, "false", on_mute_changed },
|
|
|
|
};
|
|
|
|
|
|
|
|
// WHY DO WE NEED SUCH AN UGLY METHOD, GTK?!
|
|
|
|
static void action_entries_set_enabled(SameBoyApplication *app, const GActionEntry *entries, unsigned n_entries, bool value) {
|
|
|
|
// Assumes null-terminated if n_entries == -1
|
|
|
|
for (unsigned i = 0; n_entries == -1 ? entries[i].name != NULL : i < n_entries; i++) {
|
|
|
|
const GActionEntry *entry = &entries[i];
|
|
|
|
if (entry->name == NULL) continue;
|
|
|
|
|
|
|
|
action_set_enabled(app, entry->name, value);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void create_action_groups(SameBoyApplication *app) {
|
|
|
|
g_action_map_add_action_entries(G_ACTION_MAP(app), emulation_entries, G_N_ELEMENTS(emulation_entries), app);
|
|
|
|
g_action_map_add_action_entries(G_ACTION_MAP(app), developer_entries, G_N_ELEMENTS(developer_entries), app);
|
|
|
|
g_action_map_add_action_entries(G_ACTION_MAP(app), app_entries, G_N_ELEMENTS(app_entries), app);
|
|
|
|
g_action_map_add_action_entries(G_ACTION_MAP(app), file_entries, G_N_ELEMENTS(file_entries), app);
|
|
|
|
|
|
|
|
action_set_enabled(app, "close", false);
|
|
|
|
action_entries_set_enabled(app, emulation_entries, G_N_ELEMENTS(emulation_entries), false);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void sameboy_application_startup(GApplication *gapp) {
|
|
|
|
G_APPLICATION_CLASS(sameboy_application_parent_class)->startup(gapp);
|
|
|
|
|
|
|
|
// TODO:
|
|
|
|
// signal(SIGINT, quit_interrupt);
|
|
|
|
|
|
|
|
g_debug("GTK version %u.%u.%u", gtk_get_major_version(), gtk_get_minor_version(), gtk_get_micro_version());
|
|
|
|
|
|
|
|
SameBoyApplication *app = SAMEBOY_APPLICATION(gapp);
|
|
|
|
g_debug("sameboy_application_startup");
|
2021-01-09 18:09:15 +00:00
|
|
|
g_debug("config_path: %s", app->cli_options.config_path);
|
|
|
|
g_debug("boot_rom_path: %s", app->cli_options.boot_rom_path);
|
|
|
|
g_debug("fullscreen: %d", app->cli_options.fullscreen);
|
|
|
|
g_debug("model: %d", app->cli_options.model);
|
|
|
|
g_debug("force_software_renderer: %d", app->cli_options.force_software_renderer);
|
2021-01-07 21:35:41 +00:00
|
|
|
|
2021-01-09 18:09:15 +00:00
|
|
|
init_config(G_APPLICATION(app), app->cli_options.config_path, &app->config_modification_date);
|
|
|
|
|
|
|
|
app->preferences = preferences_window_new();
|
2021-01-07 21:35:41 +00:00
|
|
|
app->about_dialog = about_dialog_new();
|
|
|
|
|
|
|
|
gtk_application_add_window(GTK_APPLICATION(gapp), GTK_WINDOW(app->preferences));
|
|
|
|
|
|
|
|
create_action_groups(app);
|
|
|
|
|
|
|
|
#if NDEBUG
|
|
|
|
// Disable when not compiled in debug mode
|
|
|
|
action_set_enabled(app, "open_gtk_debugger", false);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
GdkScreen *screen = gdk_screen_get_default();
|
|
|
|
GtkCssProvider *provider = gtk_css_provider_new();
|
|
|
|
gtk_css_provider_load_from_resource(provider, RESOURCE_PREFIX "css/main.css");
|
|
|
|
gtk_style_context_add_provider_for_screen(screen, GTK_STYLE_PROVIDER(provider), GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
|
2021-01-09 18:09:15 +00:00
|
|
|
|
|
|
|
// Just hide our sub-windows when closing them
|
|
|
|
g_signal_connect(app->preferences, "delete-event", G_CALLBACK(gtk_widget_hide_on_delete), NULL);
|
2021-01-07 21:35:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void open_file(SameBoyApplication *app, GFile *file) {
|
|
|
|
if (file != NULL) {
|
|
|
|
gchar *path = g_file_get_path(file);
|
|
|
|
g_debug("File path: %s", path);
|
|
|
|
g_free(path);
|
|
|
|
}
|
|
|
|
|
2021-01-09 18:09:15 +00:00
|
|
|
MainWindow *window = main_window_new(SAMEBOY_APPLICATION(app), app->cli_options.force_software_renderer);
|
|
|
|
main_window_setup_menu(window, config.emulation.model);
|
2021-01-07 21:35:41 +00:00
|
|
|
|
|
|
|
// Define a set of window icons
|
|
|
|
GList *icon_list = NULL;
|
|
|
|
static char* icons[] = {
|
|
|
|
RESOURCE_PREFIX "logo_256.png",
|
|
|
|
RESOURCE_PREFIX "logo_128.png",
|
|
|
|
RESOURCE_PREFIX "logo_64.png",
|
|
|
|
RESOURCE_PREFIX "logo_48.png",
|
|
|
|
RESOURCE_PREFIX "logo_32.png",
|
|
|
|
RESOURCE_PREFIX "logo_16.png"
|
|
|
|
};
|
|
|
|
|
|
|
|
GdkPixbuf *icon = gdk_pixbuf_new_from_resource(icons[5], NULL);
|
|
|
|
if (icon) {
|
|
|
|
gtk_window_set_icon(GTK_WINDOW(window), icon);
|
|
|
|
gtk_window_set_default_icon(icon);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Create list of GdkPixbufs
|
|
|
|
for (int i = 0; i < (sizeof(icons) / sizeof(const char*)); ++i) {
|
|
|
|
GdkPixbuf *icon = gdk_pixbuf_new_from_resource(icons[i], NULL);
|
|
|
|
if (!icon) continue;
|
|
|
|
|
|
|
|
icon_list = g_list_prepend(icon_list, icon);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Let GTK choose the proper icon
|
|
|
|
gtk_window_set_icon_list(GTK_WINDOW(window), icon_list);
|
|
|
|
gtk_window_set_default_icon_list(icon_list);
|
|
|
|
|
|
|
|
gtk_about_dialog_set_logo(GTK_ABOUT_DIALOG(app->about_dialog), gdk_pixbuf_new_from_resource(icons[2], NULL)); // reuse the 64x64 icon
|
|
|
|
gtk_about_dialog_set_version(GTK_ABOUT_DIALOG(app->about_dialog), "v" xstr(VERSION));
|
|
|
|
g_list_free_full(icon_list, g_object_unref);
|
|
|
|
|
|
|
|
if (app->cli_options.fullscreen) {
|
|
|
|
main_window_fullscreen(window, true);
|
|
|
|
}
|
|
|
|
|
|
|
|
gtk_window_present(GTK_WINDOW(window));
|
|
|
|
}
|
|
|
|
|
|
|
|
static void sameboy_application_activate(GApplication *gapp) {
|
|
|
|
SameBoyApplication *app = SAMEBOY_APPLICATION(gapp);
|
|
|
|
g_debug("sameboy_application_activate");
|
|
|
|
|
|
|
|
open_file(app, NULL);
|
|
|
|
|
|
|
|
G_APPLICATION_CLASS(sameboy_application_parent_class)->activate(gapp);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void sameboy_application_open(GApplication *gapp, GFile **files, int n_files, const char *hint) {
|
|
|
|
SameBoyApplication *app = SAMEBOY_APPLICATION(gapp);
|
|
|
|
g_debug("sameboy_application_open(hint = \"%s\")", hint);
|
|
|
|
|
|
|
|
if (n_files >= 1) {
|
|
|
|
if (n_files > 1) {
|
|
|
|
g_warning("More than one file specified");
|
|
|
|
}
|
|
|
|
|
|
|
|
open_file(app, files[0]);
|
|
|
|
}
|
|
|
|
|
|
|
|
G_APPLICATION_CLASS(sameboy_application_parent_class)->open(gapp, files, n_files, hint);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void sameboy_application_shutdown(GApplication *gapp) {
|
|
|
|
SameBoyApplication *app = SAMEBOY_APPLICATION(gapp);
|
|
|
|
g_debug("sameboy_application_shutdown");
|
|
|
|
|
|
|
|
G_APPLICATION_CLASS(sameboy_application_parent_class)->shutdown(gapp);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void sameboy_application_class_init(SameBoyApplicationClass *class) {
|
|
|
|
G_APPLICATION_CLASS(class)->handle_local_options = sameboy_application_handle_local_options;
|
|
|
|
G_APPLICATION_CLASS(class)->startup = sameboy_application_startup;
|
|
|
|
G_APPLICATION_CLASS(class)->activate = sameboy_application_activate;
|
|
|
|
G_APPLICATION_CLASS(class)->open = sameboy_application_open;
|
|
|
|
G_APPLICATION_CLASS(class)->shutdown = sameboy_application_shutdown;
|
|
|
|
}
|
|
|
|
|
|
|
|
SameBoyApplication *sameboy_application_new(void) {
|
|
|
|
return g_object_new(
|
|
|
|
SAMEBOY_APPLICATION_TYPE,
|
|
|
|
"application-id", APP_ID,
|
|
|
|
// "flags", G_APPLICATION_NON_UNIQUE | G_APPLICATION_HANDLES_OPEN,
|
|
|
|
"flags", G_APPLICATION_HANDLES_OPEN,
|
|
|
|
NULL
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
void sameboy_application_preferences_signal_connect(SameBoyApplication *app, const gchar *detailed_signal, GCallback c_handler, gpointer data) {
|
|
|
|
g_signal_connect(app->preferences, detailed_signal, c_handler, data);
|
|
|
|
}
|
2021-01-09 18:09:15 +00:00
|
|
|
|
|
|
|
struct CliOptionData *sameboy_application_get_cli_options(SameBoyApplication *self) {
|
|
|
|
return &self->cli_options;
|
|
|
|
}
|