// SPDX-FileCopyrightText: 2022 Geoffrey D. Bennett // SPDX-License-Identifier: GPL-3.0-or-later #include "about.h" #include "file.h" #include "menu.h" #include "window-hardware.h" // helper for common code of activate_*() functions static void update_visibility( GSimpleAction *action, GtkWidget *widget ) { GVariant *state = g_action_get_state(G_ACTION(action)); gboolean new_state = !g_variant_get_boolean(state); g_action_change_state(G_ACTION(action), g_variant_new_boolean(new_state)); gtk_widget_set_visible(widget, new_state); } static void activate_hardware( GSimpleAction *action, GVariant *parameter, gpointer data ) { (void) data; update_visibility(action, window_hardware); } static void activate_quit( GSimpleAction *action, GVariant *parameter, gpointer data ) { g_application_quit(G_APPLICATION(data)); } static void activate_routing( GSimpleAction *action, GVariant *parameter, gpointer data ) { struct alsa_card *card = data; update_visibility(action, card->window_routing); } static void activate_mixer( GSimpleAction *action, GVariant *parameter, gpointer data ) { struct alsa_card *card = data; update_visibility(action, card->window_mixer); } static void activate_levels( GSimpleAction *action, GVariant *parameter, gpointer data ) { struct alsa_card *card = data; update_visibility(action, card->window_levels); } static void activate_startup( GSimpleAction *action, GVariant *parameter, gpointer data ) { struct alsa_card *card = data; update_visibility(action, card->window_startup); } static const GActionEntry app_entries[] = { {"hardware", activate_hardware, NULL, "false"}, {"quit", activate_quit}, }; struct menu_item { const char *label; const char *action_name; const char *accelerators[2]; }; struct menu_data { const char *label; struct menu_item *items; }; static const struct menu_data menus[] = { { "_File", (struct menu_item[]){ { "_Load Configuration", "win.load", { "O", NULL } }, { "_Save Configuration", "win.save", { "S", NULL } }, { "_Interface Simulation", "win.sim", { "I", NULL } }, { "E_xit", "app.quit", { "Q", NULL } }, {} } }, { "_View", (struct menu_item[]){ { "_Routing", "win.routing", { "R", NULL } }, { "_Mixer", "win.mixer", { "M", NULL } }, { "_Levels", "win.levels", { "L", NULL } }, { "_Startup", "win.startup", { "T", NULL } }, {} } }, { "_Help", (struct menu_item[]){ { "_Supported Hardware", "app.hardware", { "H", NULL } }, { "_About", "win.about", { "slash", NULL } }, {} } }, {} }; void populate_submenu( GtkApplication *app, GMenu *menu, const struct menu_data *data ) { GMenu *submenu = g_menu_new(); g_menu_append_submenu(menu, data->label, G_MENU_MODEL(submenu)); // An empty-initialised menu_item marks the end for (struct menu_item *item = data->items; item->label; item++) { g_menu_append(submenu, item->label, item->action_name); gtk_application_set_accels_for_action( app, item->action_name, item->accelerators ); } } GMenu *create_app_menu(GtkApplication *app) { g_action_map_add_action_entries( G_ACTION_MAP(app), app_entries, G_N_ELEMENTS(app_entries), app ); GMenu *menu = g_menu_new(); for (const struct menu_data *menu_data = menus; menu_data->label; menu_data++) populate_submenu(app, menu, menu_data); return menu; } static const GActionEntry win_entries[] = { {"about", activate_about}, {"sim", activate_sim} }; void add_window_action_map(GtkWindow *w) { g_action_map_add_action_entries( G_ACTION_MAP(w), win_entries, G_N_ELEMENTS(win_entries), w ); } static const GActionEntry load_save_entries[] = { {"load", activate_load}, {"save", activate_save} }; void add_load_save_action_map(struct alsa_card *card) { g_action_map_add_action_entries( G_ACTION_MAP(card->window_main), load_save_entries, G_N_ELEMENTS(load_save_entries), card ); } static const GActionEntry startup_entry[] = { {"startup", activate_startup, NULL, "false"} }; void add_startup_action_map(struct alsa_card *card) { g_action_map_add_action_entries( G_ACTION_MAP(card->window_main), startup_entry, G_N_ELEMENTS(startup_entry), card ); } static const GActionEntry mixer_entries[] = { {"routing", activate_routing, NULL, "false"}, {"mixer", activate_mixer, NULL, "false"} }; static const GActionEntry levels_entries[] = { {"levels", activate_levels, NULL, "false"} }; void add_mixer_action_map(struct alsa_card *card) { g_action_map_add_action_entries( G_ACTION_MAP(card->window_main), mixer_entries, G_N_ELEMENTS(mixer_entries), card ); // Hide the levels menu item if there is no "Firmware Version" // control (working kernel support for level meters was added in the // same version as the "Firmware Version" control) if (get_elem_by_name(card->elems, "Firmware Version")) { g_action_map_add_action_entries( G_ACTION_MAP(card->window_main), levels_entries, G_N_ELEMENTS(levels_entries), card ); } }