diff options
Diffstat (limited to 'src/jalv_gtk.c')
-rw-r--r-- | src/jalv_gtk.c | 184 |
1 files changed, 104 insertions, 80 deletions
diff --git a/src/jalv_gtk.c b/src/jalv_gtk.c index 5b7240b..16cff34 100644 --- a/src/jalv_gtk.c +++ b/src/jalv_gtk.c @@ -3,23 +3,23 @@ #include "control.h" #include "frontend.h" -#include "jalv_internal.h" +#include "jalv.h" #include "log.h" #include "options.h" -#include "port.h" +#include "query.h" #include "state.h" #include "types.h" -#include "lilv/lilv.h" -#include "lv2/atom/atom.h" -#include "lv2/atom/forge.h" -#include "lv2/atom/util.h" -#include "lv2/core/lv2.h" -#include "lv2/ui/ui.h" -#include "lv2/urid/urid.h" -#include "suil/suil.h" -#include "zix/attributes.h" -#include "zix/sem.h" +#include <lilv/lilv.h> +#include <lv2/atom/atom.h> +#include <lv2/atom/forge.h> +#include <lv2/atom/util.h> +#include <lv2/core/lv2.h> +#include <lv2/ui/ui.h> +#include <lv2/urid/urid.h> +#include <suil/suil.h> +#include <zix/attributes.h> +#include <zix/sem.h> #include <gdk/gdk.h> #include <glib-object.h> @@ -48,10 +48,10 @@ static Jalv* s_jalv = NULL; static GtkCheckMenuItem* active_preset_item = NULL; static bool updating = false; -/// Widget for a control +/// Widget(s) for a control port or parameter typedef struct { - GtkSpinButton* spin; - GtkWidget* control; + GtkSpinButton* spin; ///< Spinner for numbers, or null + GtkWidget* control; ///< Primary value control } Controller; static float @@ -63,13 +63,15 @@ get_float(const LilvNode* node, float fallback) } static void -on_window_destroy(GtkWidget* ZIX_UNUSED(widget), gpointer ZIX_UNUSED(data)) +on_window_destroy(GtkWidget* widget, gpointer data) { + (void)widget; + (void)data; gtk_main_quit(); } int -jalv_frontend_init(int* argc, char*** argv, JalvOptions* opts) +jalv_frontend_init(JalvFrontendArgs* const args, JalvOptions* const opts) { const GOptionEntry entries[] = { {"preset", @@ -97,7 +99,7 @@ jalv_frontend_init(int* argc, char*** argv, JalvOptions* opts) 'b', 0, G_OPTION_ARG_INT, - &opts->buffer_size, + &opts->ring_size, "Buffer size for plugin <=> UI communication", "SIZE"}, {"control", @@ -181,8 +183,8 @@ jalv_frontend_init(int* argc, char*** argv, JalvOptions* opts) GError* error = NULL; const int err = - gtk_init_with_args(argc, - argv, + gtk_init_with_args(args->argc, + args->argv, "PLUGIN_URI - Run an LV2 plugin as a Jack application", entries, NULL, @@ -192,6 +194,8 @@ jalv_frontend_init(int* argc, char*** argv, JalvOptions* opts) fprintf(stderr, "%s\n", error->message); } + --*args->argc; + ++*args->argv; return !err; } @@ -305,10 +309,10 @@ typedef struct { } PresetMenu; static PresetMenu* -pset_menu_new(const char* label) +pset_menu_new(char* const label) { PresetMenu* menu = (PresetMenu*)malloc(sizeof(PresetMenu)); - menu->label = g_strdup(label); + menu->label = label; menu->item = GTK_MENU_ITEM(gtk_menu_item_new_with_label(menu->label)); menu->menu = GTK_MENU(gtk_menu_new()); menu->banks = NULL; @@ -338,22 +342,35 @@ menu_cmp(gconstpointer a, gconstpointer b, gpointer ZIX_UNUSED(data)) return strcmp(((const PresetMenu*)a)->label, ((const PresetMenu*)b)->label); } +static char* +get_label_string(Jalv* const jalv, const LilvNode* const node) +{ + LilvNode* const label_node = + lilv_world_get(jalv->world, node, jalv->nodes.rdfs_label, NULL); + + if (!label_node) { + return g_strdup(lilv_node_as_string(node)); + } + + char* const label = g_strdup(lilv_node_as_string(label_node)); + lilv_node_free(label_node); + return label; +} + static PresetMenu* get_bank_menu(Jalv* jalv, PresetMenu* menu, const LilvNode* bank) { - LilvNode* label = - lilv_world_get(jalv->world, bank, jalv->nodes.rdfs_label, NULL); - - const char* uri = lilv_node_as_string(bank); - const char* str = label ? lilv_node_as_string(label) : uri; - PresetMenu key = {NULL, (char*)str, NULL, NULL}; - GSequenceIter* i = g_sequence_lookup(menu->banks, &key, menu_cmp, NULL); + char* const label = get_label_string(jalv, bank); + PresetMenu key = {NULL, label, NULL, NULL}; + GSequenceIter* i = g_sequence_lookup(menu->banks, &key, menu_cmp, NULL); if (!i) { - PresetMenu* bank_menu = pset_menu_new(str); + PresetMenu* const bank_menu = pset_menu_new(label); gtk_menu_item_set_submenu(bank_menu->item, GTK_WIDGET(bank_menu->menu)); g_sequence_insert_sorted(menu->banks, bank_menu, menu_cmp, NULL); return bank_menu; } + + g_free(label); return (PresetMenu*)g_sequence_get(i); } @@ -373,7 +390,7 @@ add_preset_to_menu(Jalv* jalv, active_preset_item = GTK_CHECK_MENU_ITEM(item); } - LilvNode* bank = + const LilvNode* bank = lilv_world_get(jalv->world, node, jalv->nodes.pset_bank, NULL); if (bank) { @@ -569,20 +586,21 @@ differ_enough(float a, float b) static void set_float_control(const ControlID* control, float value) { - if (control->value_type == control->forge->Int) { + const LV2_Atom_Forge* const forge = &s_jalv->forge; + if (control->value_type == forge->Int) { const int32_t ival = lrintf(value); - set_control(control, sizeof(ival), control->forge->Int, &ival); - } else if (control->value_type == control->forge->Long) { + set_control(control, sizeof(ival), forge->Int, &ival); + } else if (control->value_type == forge->Long) { const int64_t lval = lrintf(value); - set_control(control, sizeof(lval), control->forge->Long, &lval); - } else if (control->value_type == control->forge->Float) { - set_control(control, sizeof(value), control->forge->Float, &value); - } else if (control->value_type == control->forge->Double) { + set_control(control, sizeof(lval), forge->Long, &lval); + } else if (control->value_type == forge->Float) { + set_control(control, sizeof(value), forge->Float, &value); + } else if (control->value_type == forge->Double) { const double dval = value; - set_control(control, sizeof(dval), control->forge->Double, &dval); - } else if (control->value_type == control->forge->Bool) { + set_control(control, sizeof(dval), forge->Double, &dval); + } else if (control->value_type == forge->Bool) { const int32_t ival = value; - set_control(control, sizeof(ival), control->forge->Bool, &ival); + set_control(control, sizeof(ival), forge->Bool, &ival); } Controller* controller = (Controller*)control->widget; @@ -593,7 +611,7 @@ set_float_control(const ControlID* control, float value) } static double -get_atom_double(Jalv* jalv, +get_atom_double(const Jalv* jalv, uint32_t ZIX_UNUSED(size), LV2_URID type, const void* body) @@ -618,7 +636,7 @@ get_atom_double(Jalv* jalv, } static void -control_changed(Jalv* jalv, +control_changed(const Jalv* jalv, Controller* controller, uint32_t size, LV2_URID type, @@ -716,8 +734,8 @@ on_request_value(LV2UI_Feature_Handle handle, const LV2_URID ZIX_UNUSED(type), const LV2_Feature* const* ZIX_UNUSED(features)) { - Jalv* jalv = (Jalv*)handle; - ControlID* control = get_property_control(&jalv->controls, key); + Jalv* const jalv = (Jalv*)handle; + const ControlID* control = get_property_control(&jalv->controls, key); if (!control) { return LV2UI_REQUEST_VALUE_ERR_UNKNOWN; @@ -760,11 +778,11 @@ property_changed(Jalv* jalv, LV2_URID key, const LV2_Atom* value) } void -jalv_ui_port_event(Jalv* jalv, - uint32_t port_index, - uint32_t buffer_size, - uint32_t protocol, - const void* buffer) +jalv_frontend_port_event(Jalv* jalv, + uint32_t port_index, + uint32_t buffer_size, + uint32_t protocol, + const void* buffer) { if (jalv->ui_instance) { suil_instance_port_event( @@ -772,17 +790,13 @@ jalv_ui_port_event(Jalv* jalv, return; } - if (protocol == 0 && (Controller*)jalv->ports[port_index].widget) { - control_changed(jalv, - (Controller*)jalv->ports[port_index].widget, - buffer_size, - jalv->forge.Float, - buffer); - return; - } - if (protocol == 0) { - return; // No widget (probably notOnGUI) + Controller* const controller = (Controller*)jalv->ports[port_index].widget; + if (controller) { + control_changed(jalv, controller, buffer_size, jalv->forge.Float, buffer); + } + + return; } if (protocol != jalv->urids.atom_eventTransfer) { @@ -803,8 +817,7 @@ jalv_ui_port_event(Jalv* jalv, } else if (obj->body.otype == jalv->urids.patch_Put) { const LV2_Atom_Object* body = NULL; if (!patch_put_get(jalv, obj, &body)) { - LV2_ATOM_OBJECT_FOREACH(body, prop) - { + LV2_ATOM_OBJECT_FOREACH (body, prop) { property_changed(jalv, prop->key, &prop->value); } } @@ -886,17 +899,17 @@ switch_changed(GtkSwitch* toggle_switch, gboolean state, gpointer data) static void string_changed(GtkEntry* widget, gpointer data) { - ControlID* control = (ControlID*)data; - const char* string = gtk_entry_get_text(widget); + const ControlID* control = (const ControlID*)data; + const char* string = gtk_entry_get_text(widget); - set_control(control, strlen(string) + 1, control->forge->String, string); + set_control(control, strlen(string) + 1, s_jalv->forge.String, string); } static void file_changed(GtkFileChooserButton* widget, gpointer data) { - ControlID* control = (ControlID*)data; - const char* filename = + const ControlID* control = (const ControlID*)data; + const char* filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(widget)); set_control(control, strlen(filename) + 1, s_jalv->forge.Path, filename); @@ -1095,9 +1108,11 @@ make_controller(ControlID* control, float value) static GtkWidget* new_label(const char* text, bool title, GtkAlign xalign, GtkAlign yalign) { - GtkWidget* label = gtk_label_new(NULL); - const char* fmt = title ? "<span font_weight=\"bold\">%s</span>" : "%s:"; - gchar* str = g_markup_printf_escaped(fmt, text); + GtkWidget* const label = gtk_label_new(NULL); + gchar* const str = + title + ? g_markup_printf_escaped("<span font_weight=\"bold\">%s</span>", text) + : g_markup_printf_escaped("%s:", text); gtk_widget_set_halign(label, xalign); gtk_widget_set_valign(label, yalign); @@ -1153,8 +1168,8 @@ build_control_widget(Jalv* jalv, GtkWidget* window) g_array_sort_with_data(controls, control_group_cmp, jalv); // Add controls in group order - LilvNode* last_group = NULL; - int n_rows = 0; + const LilvNode* last_group = NULL; + int n_rows = 0; for (size_t i = 0; i < controls->len; ++i) { ControlID* record = g_array_index(controls, ControlID*, i); Controller* controller = NULL; @@ -1175,6 +1190,7 @@ build_control_widget(Jalv* jalv, GtkWidget* window) GTK_ALIGN_START, GTK_ALIGN_BASELINE); + lilv_node_free(group_name); gtk_grid_attach(GTK_GRID(port_grid), group_label, 0, n_rows, 3, 1); ++n_rows; } @@ -1192,7 +1208,7 @@ build_control_widget(Jalv* jalv, GtkWidget* window) record->widget = controller; if (record->type == PORT) { - jalv->ports[record->index].widget = controller; + jalv->ports[record->id.index].widget = controller; } if (controller) { // Add row to table for this controller @@ -1289,13 +1305,13 @@ build_menu(Jalv* jalv, GtkWidget* window, GtkWidget* vbox) } bool -jalv_frontend_discover(Jalv* ZIX_UNUSED(jalv)) +jalv_frontend_discover(const Jalv* ZIX_UNUSED(jalv)) { return TRUE; } float -jalv_frontend_refresh_rate(Jalv* ZIX_UNUSED(jalv)) +jalv_frontend_refresh_rate(const Jalv* ZIX_UNUSED(jalv)) { GdkDisplay* const display = gdk_display_get_default(); GdkMonitor* const monitor = gdk_display_get_primary_monitor(display); @@ -1306,7 +1322,7 @@ jalv_frontend_refresh_rate(Jalv* ZIX_UNUSED(jalv)) } float -jalv_frontend_scale_factor(Jalv* ZIX_UNUSED(jalv)) +jalv_frontend_scale_factor(const Jalv* ZIX_UNUSED(jalv)) { GdkDisplay* const display = gdk_display_get_default(); GdkMonitor* const monitor = gdk_display_get_primary_monitor(display); @@ -1318,7 +1334,7 @@ static void on_row_activated(GtkTreeView* const tree_view, GtkTreePath* const path, GtkTreeViewColumn* const column, - const void* const user_data) + void* const user_data) { (void)tree_view; (void)path; @@ -1473,7 +1489,8 @@ jalv_frontend_open(Jalv* jalv) GtkWidget* widget = (GtkWidget*)suil_instance_get_widget(jalv->ui_instance); gtk_container_add(GTK_CONTAINER(ui_box), widget); - gtk_window_set_resizable(GTK_WINDOW(window), jalv_ui_is_resizable(jalv)); + gtk_window_set_resizable(GTK_WINDOW(window), + jalv_ui_is_resizable(jalv->world, jalv->ui)); gtk_widget_show_all(vbox); gtk_widget_grab_focus(widget); } else { @@ -1501,20 +1518,27 @@ jalv_frontend_open(Jalv* jalv) jalv_init_ui(jalv); - g_timeout_add(1000 / jalv->ui_update_hz, (GSourceFunc)jalv_update, jalv); + const float update_interval_ms = 1000.0f / jalv->settings.ui_update_hz; + g_timeout_add((unsigned)update_interval_ms, (GSourceFunc)jalv_update, jalv); gtk_window_present(GTK_WINDOW(window)); gtk_main(); suil_instance_free(jalv->ui_instance); + + for (unsigned i = 0U; i < jalv->controls.n_controls; ++i) { + free(jalv->controls.controls[i]->widget); // free Controller + } + jalv->ui_instance = NULL; zix_sem_post(&jalv->done); return 0; } int -jalv_frontend_close(Jalv* ZIX_UNUSED(jalv)) +jalv_frontend_close(Jalv* jalv) { + (void)jalv; gtk_main_quit(); s_jalv = NULL; return 0; |