aboutsummaryrefslogtreecommitdiffstats
path: root/src/jalv_gtk.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/jalv_gtk.c')
-rw-r--r--src/jalv_gtk.c184
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;