diff options
Diffstat (limited to 'src/jalv_gtk2.c')
-rw-r--r-- | src/jalv_gtk2.c | 597 |
1 files changed, 0 insertions, 597 deletions
diff --git a/src/jalv_gtk2.c b/src/jalv_gtk2.c deleted file mode 100644 index 9ff2013..0000000 --- a/src/jalv_gtk2.c +++ /dev/null @@ -1,597 +0,0 @@ -/* - Copyright 2007-2012 David Robillard <http://drobilla.net> - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ - -#include <math.h> - -#include <gtk/gtk.h> - -#include "lv2/lv2plug.in/ns/ext/port-props/port-props.h" - -#include "jalv_internal.h" - -static void -on_window_destroy(GtkWidget* widget, - gpointer data) -{ - Jalv* jalv = (Jalv*)data; - suil_instance_free(jalv->ui_instance); - jalv->ui_instance = NULL; - gtk_main_quit(); -} - -int -jalv_init(int* argc, char*** argv, JalvOptions* opts) -{ - GOptionEntry entries[] = { - { "uuid", 'u', 0, G_OPTION_ARG_STRING, &opts->uuid, - "UUID for Jack session restoration", "UUID" }, - { "load", 'l', 0, G_OPTION_ARG_STRING, &opts->load, - "Load state from save directory", "DIR" }, - { "dump", 'd', 0, G_OPTION_ARG_NONE, &opts->dump, - "Dump plugin <=> UI communication", NULL }, - { "generic-ui", 'g', 0, G_OPTION_ARG_NONE, &opts->generic_ui, - "Use Jalv generic UI and not the plugin UI", NULL}, - { "buffer-size", 'b', 0, G_OPTION_ARG_INT, &opts->buffer_size, - "Buffer size for plugin <=> UI communication", "SIZE"}, - { 0, 0, 0, 0, 0, 0, 0 } }; - GError* error = NULL; - const int err = gtk_init_with_args( - argc, argv, - "PLUGIN_URI - Run an LV2 plugin as a Jack application", - entries, NULL, &error); - - if (!err) { - fprintf(stderr, "%s\n", error->message); - } - - return !err; -} - -LilvNode* -jalv_native_ui_type(Jalv* jalv) -{ - return lilv_new_uri(jalv->world, - "http://lv2plug.in/ns/extensions/ui#GtkUI"); -} - -static void -on_save_activate(GtkWidget* widget, void* ptr) -{ - Jalv* jalv = (Jalv*)ptr; - GtkWidget* dialog = gtk_file_chooser_dialog_new( - "Save State", - jalv->window, - GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER, - GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, - GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT, - NULL); - - if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) { - char* path = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog)); - char* base = g_build_filename(path, "/", NULL); - jalv_save(jalv, base); - g_free(path); - g_free(base); - } - - gtk_widget_destroy(dialog); -} - -static void -on_quit_activate(GtkWidget* widget, gpointer data) -{ - GtkWidget* window = (GtkWidget*)data; - gtk_widget_destroy(window); -} - -typedef struct { - Jalv* jalv; - LilvNode* preset; -} PresetRecord; - -char* -symbolify(const char* in) -{ - const size_t len = strlen(in); - char* out = calloc(len + 1, 1); - for (size_t i = 0; i < len; ++i) { - if (g_ascii_isalnum(in[i])) { - out[i] = in[i]; - } else { - out[i] = '_'; - } - } - return out; -} - -static void -on_save_preset_activate(GtkWidget* widget, void* ptr) -{ - Jalv* jalv = (Jalv*)ptr; - - GtkWidget* dialog = gtk_file_chooser_dialog_new( - "Save Preset", - jalv->window, - GTK_FILE_CHOOSER_ACTION_SAVE, - GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT, - GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT, - NULL); - - char* dot_lv2 = g_build_filename(g_get_home_dir(), ".lv2", NULL); - gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), dot_lv2); - free(dot_lv2); - - GtkWidget* content = gtk_dialog_get_content_area(GTK_DIALOG(dialog)); - GtkBox* box = GTK_BOX(gtk_hbox_new(FALSE, 8)); - GtkWidget* uri_label = gtk_label_new("URI (Optional):"); - GtkWidget* uri_entry = gtk_entry_new(); - - gtk_box_pack_start(box, uri_label, FALSE, TRUE, 2); - gtk_box_pack_start(box, uri_entry, TRUE, TRUE, 2); - gtk_box_pack_start(GTK_BOX(content), GTK_WIDGET(box), FALSE, FALSE, 6); - - gtk_widget_show_all(GTK_WIDGET(dialog)); - gtk_entry_set_activates_default(GTK_ENTRY(uri_entry), TRUE); - gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_ACCEPT); - if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) { - const char* path = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog)); - const char* uri = gtk_entry_get_text(GTK_ENTRY(uri_entry)); - - char* dirname = g_path_get_dirname(path); - char* basename = g_path_get_basename(path); - char* sym = symbolify(basename); - char* bundle = g_strjoin(NULL, sym, ".lv2", NULL); - char* file = g_strjoin(NULL, sym, ".ttl", NULL); - char* dir = g_build_filename(dirname, bundle, NULL); - - jalv_save_preset(jalv, dir, (strlen(uri) ? uri : NULL), basename, file); - - g_free(dir); - g_free(file); - g_free(bundle); - free(sym); - g_free(basename); - g_free(dirname); - } - - gtk_widget_destroy(GTK_WIDGET(dialog)); -} - -static void -on_preset_activate(GtkWidget* widget, gpointer data) -{ - PresetRecord* record = (PresetRecord*)data; - jalv_apply_preset(record->jalv, record->preset); -} - -static void -on_preset_destroy(gpointer data, GClosure* closure) -{ - PresetRecord* record = (PresetRecord*)data; - lilv_node_free(record->preset); - free(record); -} - -static int -add_preset_to_menu(Jalv* jalv, - const LilvNode* node, - const LilvNode* title, - void* data) -{ - GtkWidget* presets_menu = GTK_WIDGET(data); - const char* label = lilv_node_as_string(title); - GtkWidget* item = gtk_menu_item_new_with_label(label); - - PresetRecord* record = (PresetRecord*)malloc(sizeof(PresetRecord)); - record->jalv = jalv; - record->preset = lilv_node_duplicate(node); - - g_signal_connect_data(G_OBJECT(item), "activate", - G_CALLBACK(on_preset_activate), - record, on_preset_destroy, - 0); - - gtk_menu_shell_append(GTK_MENU_SHELL(presets_menu), item); - return 0; -} - -void -jalv_ui_port_event(Jalv* jalv, - uint32_t port_index, - uint32_t buffer_size, - uint32_t protocol, - const void* buffer) -{ - GtkWidget* widget = jalv->ports[port_index].widget; - if (!widget) { - return; - } - - if (GTK_IS_COMBO_BOX(widget)) { - GtkTreeModel* model = gtk_combo_box_get_model(GTK_COMBO_BOX(widget)); - GValue value = { 0, { { 0 } } }; - GtkTreeIter i; - bool valid = gtk_tree_model_get_iter_first(model, &i); - while (valid) { - gtk_tree_model_get_value(model, &i, 0, &value); - const double v = g_value_get_double(&value); - g_value_unset(&value); - if (fabs(v - *(float*)buffer) < FLT_EPSILON) { - gtk_combo_box_set_active_iter(GTK_COMBO_BOX(widget), &i); - return; - } - valid = gtk_tree_model_iter_next(model, &i); - } - } else if (GTK_IS_TOGGLE_BUTTON(widget)) { - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), - *(float*)buffer > 0.0f); - } else if (GTK_IS_RANGE(widget)) { - gtk_range_set_value(GTK_RANGE(widget), *(float*)buffer); - } else { - fprintf(stderr, "Unknown widget type for port %d\n", port_index); - } -} - -static gboolean -slider_changed(GtkRange* range, gpointer data) -{ - ((struct Port*)data)->control = gtk_range_get_value(range); - return FALSE; -} - -static gboolean -log_slider_changed(GtkRange* range, gpointer data) -{ - ((struct Port*)data)->control = expf(gtk_range_get_value(range)); - return FALSE; -} - -static void -combo_changed(GtkComboBox* box, gpointer data) -{ - GtkTreeIter iter; - if (gtk_combo_box_get_active_iter(box, &iter)) { - GtkTreeModel* model = gtk_combo_box_get_model(box); - GValue value = { 0, { { 0 } } }; - - gtk_tree_model_get_value(model, &iter, 0, &value); - const double v = g_value_get_double(&value); - g_value_unset(&value); - - ((struct Port*)data)->control = v; - } -} - -static gboolean -toggle_changed(GtkToggleButton* button, gpointer data) -{ - float fval = gtk_toggle_button_get_active(button) ? 1.0f : 0.0f; - ((struct Port*)data)->control = fval; - return FALSE; -} - -static gchar* -scale_format(GtkScale* scale, gdouble value, gpointer user_data) -{ - gpointer hval = g_hash_table_lookup(user_data, &value); - return hval ? g_strdup(hval) : - g_strdup_printf("%0.*f", gtk_scale_get_digits(scale), value); -} - -static gchar* -log_scale_format(GtkScale* scale, gdouble value, gpointer user_data) -{ - return g_strdup_printf("%0.6g", exp(gtk_range_get_value(GTK_RANGE(scale)))); -} - -static gint -dcmp(gconstpointer a, gconstpointer b) -{ - double y = *(double*)a; - double z = *(double*)b; - return y < z ? -1 : z < y ? 1 : 0; -} - -static GtkWidget* -make_combo(struct Port* port, GHashTable* points, int deft) -{ - GList* list = g_hash_table_get_keys(points); - GtkListStore* list_store = gtk_list_store_new( - 2, G_TYPE_DOUBLE, G_TYPE_STRING); - for (GList* cur = g_list_sort(list, dcmp); cur; cur = cur->next) { - GtkTreeIter iter; - gtk_list_store_append(list_store, &iter); - gtk_list_store_set(list_store, &iter, - 0, *(double*)cur->data, - 1, g_hash_table_lookup(points, cur->data), - -1); - } - g_list_free(list); - - GtkWidget* combo = gtk_combo_box_new_with_model(GTK_TREE_MODEL(list_store)); - gtk_combo_box_set_active(GTK_COMBO_BOX(combo), deft); - g_object_unref(list_store); - - GtkCellRenderer* cell = gtk_cell_renderer_text_new(); - gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(combo), cell, TRUE); - gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(combo), cell, "text", 1, NULL); - - g_signal_connect(G_OBJECT(combo), - "changed", G_CALLBACK(combo_changed), port); - - return combo; -} - -static GtkWidget* -make_log_slider(struct Port* port, GHashTable* points, - float min, float max, float deft) -{ - float lmin = logf(min); - float lmax = logf(max); - float ldft = logf(deft); - GtkWidget* slider = gtk_hscale_new_with_range(lmin, lmax, 0.001); - gtk_scale_set_digits(GTK_SCALE(slider), 6); - gtk_range_set_value(GTK_RANGE(slider), ldft); - g_signal_connect(G_OBJECT(slider), - "format-value", G_CALLBACK(log_scale_format), points); - g_signal_connect(G_OBJECT(slider), - "value-changed", G_CALLBACK(log_slider_changed), port); - - return slider; -} - -static GtkWidget* -make_slider(struct Port* port, GHashTable* points, - bool is_int, float min, float max, float deft) -{ - const double step = is_int ? 1.0 : ((max - min) / 100.0); - GtkWidget* slider = gtk_hscale_new_with_range(min, max, step); - gtk_range_set_value(GTK_RANGE(slider), deft); - if (points) { - g_signal_connect(G_OBJECT(slider), - "format-value", G_CALLBACK(scale_format), points); - } - - g_signal_connect(G_OBJECT(slider), - "value-changed", G_CALLBACK(slider_changed), port); - - return slider; -} - -static GtkWidget* -make_toggle(struct Port* port, float deft) -{ - GtkWidget* check = gtk_check_button_new(); - if (deft) { - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check), TRUE); - } - g_signal_connect(G_OBJECT(check), - "toggled", G_CALLBACK(toggle_changed), port); - return check; -} - -static GtkWidget* -build_control_widget(Jalv* jalv, GtkWidget* window) -{ - LilvNode* lv2_sampleRate = lilv_new_uri(jalv->world, LV2_CORE__sampleRate); - LilvNode* lv2_integer = lilv_new_uri(jalv->world, LV2_CORE__integer); - LilvNode* lv2_toggled = lilv_new_uri(jalv->world, LV2_CORE__toggled); - LilvNode* lv2_enum = lilv_new_uri(jalv->world, LV2_CORE__enumeration); - LilvNode* lv2_log = lilv_new_uri(jalv->world, LV2_PORT_PROPS__logarithmic); - LilvNode* rdfs_comment = lilv_new_uri(jalv->world, LILV_NS_RDFS "comment"); - GtkWidget* port_table = gtk_table_new(jalv->num_ports, 2, false); - float* defaults = calloc(jalv->num_ports, sizeof(float)); - float* mins = calloc(jalv->num_ports, sizeof(float)); - float* maxs = calloc(jalv->num_ports, sizeof(float)); - int num_controls = 0; - lilv_plugin_get_port_ranges_float(jalv->plugin, mins, maxs, defaults); - for (unsigned i = 0; i < jalv->num_ports; i++) { - if (jalv->ports[i].type != TYPE_CONTROL) { - continue; - } - ++num_controls; - - const LilvPort* port = jalv->ports[i].lilv_port; - LilvNode* name = lilv_port_get_name(jalv->plugin, port); - - if (lilv_port_has_property(jalv->plugin, port, lv2_sampleRate)) { - mins[i] *= jalv->sample_rate; - maxs[i] *= jalv->sample_rate; - } - - /* Get scale points */ - LilvScalePoints* sp = lilv_port_get_scale_points(jalv->plugin, port); - GHashTable* points = NULL; - if (sp) { - points = g_hash_table_new(g_double_hash, g_double_equal); - gdouble* values = malloc(lilv_scale_points_size(sp) * sizeof(gdouble)); - int idx = 0; - LILV_FOREACH(scale_points, i, sp) { - const LilvScalePoint* p = lilv_scale_points_get(sp, i); - values[idx] = lilv_node_as_float(lilv_scale_point_get_value(p)); - char* label = g_strdup( - lilv_node_as_string(lilv_scale_point_get_label(p))); - g_hash_table_insert(points, values + idx, label); - ++idx; - } - lilv_scale_points_free(sp); - } - - /* Make control */ - GtkWidget* control = NULL; - bool is_integer = lilv_port_has_property( - jalv->plugin, port, lv2_integer); - if (lilv_port_has_property(jalv->plugin, port, lv2_toggled)) { - control = make_toggle(&jalv->ports[i], defaults[i]); - } else if (lilv_port_has_property(jalv->plugin, port, lv2_enum) - || (is_integer && points && - (g_hash_table_size(points) - == (unsigned)(maxs[i] - mins[i] + 1)))) { - control = make_combo(&jalv->ports[i], points, defaults[i]); - } else if (lilv_port_has_property(jalv->plugin, port, lv2_log)) { - control = make_log_slider(&jalv->ports[i], points, - mins[i], maxs[i], defaults[i]); - } else { - control = make_slider(&jalv->ports[i], points, is_integer, - mins[i], maxs[i], defaults[i]); - } - jalv->ports[i].widget = control; - - /* Set tooltip text */ - LilvNodes* comments = lilv_port_get_value( - jalv->plugin, port, rdfs_comment); - if (comments) { - gtk_widget_set_tooltip_text( - control, lilv_node_as_string(lilv_nodes_get_first(comments))); - } - lilv_nodes_free(comments); - - /* Add control table row */ - GtkWidget* label = gtk_label_new(NULL); - gchar* markup = g_markup_printf_escaped( - "<span font_weight=\"bold\">%s:</span>", - lilv_node_as_string(name)); - gtk_label_set_markup(GTK_LABEL(label), markup); - g_free(markup); - gtk_misc_set_alignment(GTK_MISC(label), 1.0, 0.5); - gtk_table_attach(GTK_TABLE(port_table), - label, - 0, 1, i, i + 1, - GTK_FILL, GTK_FILL | GTK_EXPAND, 15, 15); - gtk_table_attach(GTK_TABLE(port_table), control, - 1, 2, i, i + 1, - GTK_FILL | GTK_EXPAND, 0, 0, 0); - lilv_node_free(name); - } - - free(defaults); - free(mins); - free(maxs); - lilv_node_free(lv2_sampleRate); - lilv_node_free(lv2_integer); - lilv_node_free(lv2_toggled); - lilv_node_free(lv2_enum); - lilv_node_free(rdfs_comment); - - if (num_controls > 0) { - gtk_window_set_resizable(GTK_WINDOW(window), TRUE); - GtkWidget* alignment = gtk_alignment_new(0.5, 0.0, 1.0, 0.0); - gtk_alignment_set_padding(GTK_ALIGNMENT(alignment), 0, 0, 8, 8); - gtk_container_add(GTK_CONTAINER(alignment), port_table); - return alignment; - } else { - gtk_widget_destroy(port_table); - GtkWidget* button = gtk_button_new_with_label("Close"); - g_signal_connect_swapped( - button, "clicked", G_CALLBACK(gtk_widget_destroy), window); - gtk_window_set_resizable(GTK_WINDOW(window), FALSE); - return button; - } -} - -int -jalv_open_ui(Jalv* jalv, - SuilInstance* instance) -{ - GtkWidget* window = gtk_window_new(GTK_WINDOW_TOPLEVEL); - jalv->window = window; - - g_signal_connect(window, "destroy", - G_CALLBACK(on_window_destroy), jalv); - - LilvNode* name = lilv_plugin_get_name(jalv->plugin); - gtk_window_set_title(GTK_WINDOW(window), lilv_node_as_string(name)); - lilv_node_free(name); - - GtkWidget* vbox = gtk_vbox_new(FALSE, 0); - GtkWidget* menu_bar = gtk_menu_bar_new(); - GtkWidget* file = gtk_menu_item_new_with_mnemonic("_File"); - GtkWidget* file_menu = gtk_menu_new(); - - GtkAccelGroup* ag = gtk_accel_group_new(); - gtk_window_add_accel_group(GTK_WINDOW(window), ag); - - GtkWidget* save = gtk_image_menu_item_new_from_stock(GTK_STOCK_SAVE, ag); - GtkWidget* quit = gtk_image_menu_item_new_from_stock(GTK_STOCK_QUIT, ag); - - gtk_menu_item_set_submenu(GTK_MENU_ITEM(file), file_menu); - gtk_menu_shell_append(GTK_MENU_SHELL(file_menu), save); - gtk_menu_shell_append(GTK_MENU_SHELL(file_menu), quit); - gtk_menu_shell_append(GTK_MENU_SHELL(menu_bar), file); - - GtkWidget* presets = gtk_menu_item_new_with_mnemonic("_Presets"); - GtkWidget* presets_menu = gtk_menu_new(); - GtkWidget* save_preset = gtk_menu_item_new_with_mnemonic( - "_Save Preset..."); - gtk_menu_item_set_submenu(GTK_MENU_ITEM(presets), presets_menu); - gtk_menu_shell_append(GTK_MENU_SHELL(presets_menu), save_preset); - gtk_menu_shell_append(GTK_MENU_SHELL(presets_menu), - gtk_separator_menu_item_new()); - gtk_menu_shell_append(GTK_MENU_SHELL(menu_bar), presets); - - jalv_load_presets(jalv, add_preset_to_menu, presets_menu); - - gtk_container_add(GTK_CONTAINER(window), vbox); - gtk_box_pack_start(GTK_BOX(vbox), menu_bar, FALSE, FALSE, 0); - - g_signal_connect(G_OBJECT(quit), "activate", - G_CALLBACK(on_quit_activate), window); - - g_signal_connect(G_OBJECT(save), "activate", - G_CALLBACK(on_save_activate), jalv); - - g_signal_connect(G_OBJECT(save_preset), "activate", - G_CALLBACK(on_save_preset_activate), jalv); - - if (instance && !jalv->opts.generic_ui) { - GtkWidget* alignment = gtk_alignment_new(0.5, 0.5, 1.0, 1.0); - GtkWidget* widget = (GtkWidget*)suil_instance_get_widget(instance); - - gtk_box_pack_start(GTK_BOX(vbox), alignment, TRUE, TRUE, 0); - gtk_container_add(GTK_CONTAINER(alignment), widget); - gtk_window_set_resizable(GTK_WINDOW(window), jalv_ui_is_resizable(jalv)); - gtk_widget_show_all(vbox); - } else { - GtkWidget* controls = build_control_widget(jalv, window); - GtkWidget* scroll_win = gtk_scrolled_window_new(NULL, NULL); - gtk_scrolled_window_add_with_viewport( - GTK_SCROLLED_WINDOW(scroll_win), controls); - gtk_scrolled_window_set_policy( - GTK_SCROLLED_WINDOW(scroll_win), - GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); - gtk_box_pack_start(GTK_BOX(vbox), scroll_win, TRUE, TRUE, 0); - gtk_widget_show_all(vbox); - - GtkRequisition controls_size, box_size; - gtk_widget_size_request(GTK_WIDGET(controls), &controls_size); - gtk_widget_size_request(GTK_WIDGET(vbox), &box_size); - - gtk_window_set_default_size( - GTK_WINDOW(window), - MAX(MAX(box_size.width, controls_size.width) + 24, 640), - box_size.height + controls_size.height); - } - - g_timeout_add(1000 / jalv->ui_update_hz, - (GSourceFunc)jalv_emit_ui_events, jalv); - - jalv->has_ui = TRUE; - gtk_window_present(GTK_WINDOW(window)); - - gtk_main(); - zix_sem_post(jalv->done); - return 0; -} |