| 
							- commit 109070a71a1e780385b803731fbdd2689752c644
 - Author: Robin Gareus <robin@gareus.org>
 - Date:   Tue Jan 7 17:48:52 2014 +0100
 - 
 -     add support for externalUI
 - 
 - diff --git a/jalv/src/jalv.c b/jalv/src/jalv.c
 - index e80f9f9..e0aa1a0 100644
 - --- a/jalv/src/jalv.c
 - +++ b/jalv/src/jalv.c
 - @@ -649,32 +649,73 @@ void
 -  jalv_ui_instantiate(Jalv* jalv, const char* native_ui_type, void* parent)
 -  {
 -  	jalv->ui_host = suil_host_new(jalv_ui_write, jalv_ui_port_index, NULL, NULL);
 - +	jalv->extuiptr = NULL;
 - +
 - +	if (jalv->externalui) {
 - +
 - +		const LV2_Feature external_lv_feature = {
 - +			LV2_EXTERNAL_UI_DEPRECATED_URI, parent
 - +		};
 - +		const LV2_Feature external_kx_feature = {
 - +			LV2_EXTERNAL_UI__Host, parent
 - +		};
 - +		const LV2_Feature instance_feature = {
 - +			NS_EXT "instance-access", lilv_instance_get_handle(jalv->instance)
 - +		};
 - +		const LV2_Feature* ui_features[] = {
 - +			&uri_map_feature, &map_feature, &unmap_feature,
 - +			&instance_feature,
 - +			&log_feature,
 - +			&external_lv_feature,
 - +			&external_kx_feature,
 - +			&options_feature,
 - +			NULL
 - +		};
 - +
 - +		jalv->ui_instance = suil_instance_new(
 - +			jalv->ui_host,
 - +			jalv,
 - +			native_ui_type,
 - +			lilv_node_as_uri(lilv_plugin_get_uri(jalv->plugin)),
 - +			lilv_node_as_uri(lilv_ui_get_uri(jalv->ui)),
 - +			lilv_node_as_uri(jalv->ui_type),
 - +			lilv_uri_to_path(lilv_node_as_uri(lilv_ui_get_bundle_uri(jalv->ui))),
 - +			lilv_uri_to_path(lilv_node_as_uri(lilv_ui_get_binary_uri(jalv->ui))),
 - +			ui_features);
 -  
 - -	const LV2_Feature parent_feature = {
 - -		LV2_UI__parent, parent
 - -	};
 - -	const LV2_Feature instance_feature = {
 - -		NS_EXT "instance-access", lilv_instance_get_handle(jalv->instance)
 - -	};
 - -	const LV2_Feature* ui_features[] = {
 - -		&uri_map_feature, &map_feature, &unmap_feature,
 - -		&instance_feature,
 - -		&log_feature,
 - -		&parent_feature,
 - -		&options_feature,
 - -		NULL
 - -	};
 - +		if (jalv->ui_instance) {
 - +			jalv->extuiptr = suil_instance_get_widget((SuilInstance*)jalv->ui_instance);
 - +		} else {
 - +			jalv->externalui = false;
 - +		}
 - +	} else {
 -  
 - -	jalv->ui_instance = suil_instance_new(
 - -		jalv->ui_host,
 - -		jalv,
 - -		native_ui_type,
 - -		lilv_node_as_uri(lilv_plugin_get_uri(jalv->plugin)),
 - -		lilv_node_as_uri(lilv_ui_get_uri(jalv->ui)),
 - -		lilv_node_as_uri(jalv->ui_type),
 - -		lilv_uri_to_path(lilv_node_as_uri(lilv_ui_get_bundle_uri(jalv->ui))),
 - -		lilv_uri_to_path(lilv_node_as_uri(lilv_ui_get_binary_uri(jalv->ui))),
 - -		ui_features);
 - +		const LV2_Feature parent_feature = {
 - +			LV2_UI__parent, parent
 - +		};
 - +		const LV2_Feature instance_feature = {
 - +			NS_EXT "instance-access", lilv_instance_get_handle(jalv->instance)
 - +		};
 - +		const LV2_Feature* ui_features[] = {
 - +			&uri_map_feature, &map_feature, &unmap_feature,
 - +			&instance_feature,
 - +			&log_feature,
 - +			&parent_feature,
 - +			&options_feature,
 - +			NULL
 - +		};
 - +
 - +		jalv->ui_instance = suil_instance_new(
 - +			jalv->ui_host,
 - +			jalv,
 - +			native_ui_type,
 - +			lilv_node_as_uri(lilv_plugin_get_uri(jalv->plugin)),
 - +			lilv_node_as_uri(lilv_ui_get_uri(jalv->ui)),
 - +			lilv_node_as_uri(jalv->ui_type),
 - +			lilv_uri_to_path(lilv_node_as_uri(lilv_ui_get_bundle_uri(jalv->ui))),
 - +			lilv_uri_to_path(lilv_node_as_uri(lilv_ui_get_binary_uri(jalv->ui))),
 - +			ui_features);
 - +	}
 -  
 -  	/* Set initial control values on UI */
 -  	if (jalv->ui_instance) {
 - @@ -688,6 +729,7 @@ jalv_ui_instantiate(Jalv* jalv, const char* native_ui_type, void* parent)
 -  	}
 -  }
 -  
 - +
 -  bool
 -  jalv_ui_is_resizable(Jalv* jalv)
 -  {
 - @@ -795,6 +837,9 @@ jalv_emit_ui_events(Jalv* jalv)
 -  			jalv_ui_port_event(jalv, ev.index, ev.size, ev.protocol, buf);
 -  		}
 -  	}
 - +	if (jalv->externalui && jalv->extuiptr) {
 - +		LV2_EXTERNAL_UI_RUN(jalv->extuiptr);
 - +	}
 -  
 -  	return true;
 -  }
 - @@ -938,6 +983,8 @@ main(int argc, char** argv)
 -  	jalv.nodes.rsz_minimumSize        = lilv_new_uri(world, LV2_RESIZE_PORT__minimumSize);
 -  	jalv.nodes.work_interface         = lilv_new_uri(world, LV2_WORKER__interface);
 -  	jalv.nodes.work_schedule          = lilv_new_uri(world, LV2_WORKER__schedule);
 - +	jalv.nodes.ui_externallv          = lilv_new_uri(world, "http://lv2plug.in/ns/extensions/ui#external");
 - +	jalv.nodes.ui_externalkx          = lilv_new_uri(world, "http://kxstudio.sf.net/ns/lv2ext/external-ui#Widget");
 -  	jalv.nodes.end                    = NULL;
 -  
 -  	/* Get plugin URI from loaded state or command line */
 - @@ -1013,11 +1060,31 @@ main(int argc, char** argv)
 -  			}
 -  		}
 -  	}
 - +	if (!jalv.ui) {
 - +		LILV_FOREACH(uis, u, jalv.uis) {
 - +			const LilvUI* ui = lilv_uis_get(jalv.uis, u);
 - +			const LilvNodes* types = lilv_ui_get_classes(ui);
 - +			LILV_FOREACH(nodes, t, types) {
 - +				const char * pt = lilv_node_as_uri(lilv_nodes_get(types, t));
 - +				if (!strcmp(pt, "http://kxstudio.sf.net/ns/lv2ext/external-ui#Widget")) {
 - +					jalv.externalui = true;
 - +					jalv.ui = ui;
 - +					jalv.ui_type = jalv.nodes.ui_externalkx;
 - +				} else if (!strcmp(pt, "http://lv2plug.in/ns/extensions/ui#external")) {
 - +					jalv.externalui = true;
 - +					jalv.ui_type = jalv.nodes.ui_externallv;
 - +					jalv.ui = ui;
 - +				}
 - +			}
 - +		}
 - +	}
 -  
 -  	/* Create ringbuffers for UI if necessary */
 -  	if (jalv.ui) {
 -  		fprintf(stderr, "UI:           %s\n",
 -  		        lilv_node_as_uri(lilv_ui_get_uri(jalv.ui)));
 - +		fprintf(stderr, "UI Type:      %s\n",
 - +				lilv_node_as_uri(jalv.ui_type));
 -  	} else {
 -  		fprintf(stderr, "No appropriate UI found\n");
 -  	}
 - diff --git a/jalv/src/jalv_gtk.c b/jalv/src/jalv_gtk.c
 - index bb92dbb..5599c0c 100644
 - --- a/jalv/src/jalv_gtk.c
 - +++ b/jalv/src/jalv_gtk.c
 - @@ -803,18 +803,28 @@ build_menu(Jalv* jalv, GtkWidget* window, GtkWidget* vbox)
 -  	gtk_box_pack_start(GTK_BOX(vbox), menu_bar, FALSE, FALSE, 0);
 -  }
 -  
 - +void
 - +on_external_ui_closed(void* controller)
 - +{
 - +	Jalv* jalv = (Jalv*) controller;
 - +	jalv_close_ui(jalv);
 - +}
 - +
 -  int
 -  jalv_open_ui(Jalv* jalv)
 -  {
 - +	LV2_External_UI_Host extui;
 -  	GtkWidget* window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
 -  	jalv->window = window;
 -  	jalv->has_ui = TRUE;
 - +	extui.ui_closed = on_external_ui_closed;
 -  
 -  	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));
 - +	extui.plugin_human_id = jalv_strdup(lilv_node_as_string(name));
 -  	lilv_node_free(name);
 -  
 -  	GtkWidget* vbox = new_box(false, 0);
 - @@ -832,10 +842,16 @@ jalv_open_ui(Jalv* jalv)
 -  
 -  	/* Attempt to instantiate custom UI if necessary */
 -  	if (jalv->ui && !jalv->opts.generic_ui) {
 - -		jalv_ui_instantiate(jalv, jalv_native_ui_type(jalv), alignment);
 - +		if (jalv->externalui) {
 - +			jalv_ui_instantiate(jalv, lilv_node_as_uri(jalv->ui_type), &extui);
 - +		} else {
 - +			jalv_ui_instantiate(jalv, jalv_native_ui_type(jalv), alignment);
 - +		}
 -  	}
 -  
 - -	if (jalv->ui_instance) {
 - +	if (jalv->externalui && jalv->extuiptr) {
 - +		LV2_EXTERNAL_UI_SHOW(jalv->extuiptr);
 - +	} else if (jalv->ui_instance) {
 -  		GtkWidget* widget = (GtkWidget*)suil_instance_get_widget(
 -  			jalv->ui_instance);
 -  
 - @@ -843,6 +859,7 @@ jalv_open_ui(Jalv* jalv)
 -  		gtk_window_set_resizable(GTK_WINDOW(window), jalv_ui_is_resizable(jalv));
 -  		gtk_widget_show_all(vbox);
 -  		gtk_widget_grab_focus(widget);
 - +		gtk_window_present(GTK_WINDOW(window));
 -  	} else {
 -  		GtkWidget* controls   = build_control_widget(jalv, window);
 -  		GtkWidget* scroll_win = gtk_scrolled_window_new(NULL, NULL);
 - @@ -862,13 +879,12 @@ jalv_open_ui(Jalv* jalv)
 -  			GTK_WINDOW(window),
 -  			MAX(MAX(box_size.width, controls_size.width) + 24, 640),
 -  			box_size.height + controls_size.height);
 - +		gtk_window_present(GTK_WINDOW(window));
 -  	}
 -  
 -  	g_timeout_add(1000 / jalv->ui_update_hz,
 -  	              (GSourceFunc)jalv_emit_ui_events, jalv);
 -  
 - -	gtk_window_present(GTK_WINDOW(window));
 - -
 -  	gtk_main();
 -  	zix_sem_post(jalv->done);
 -  	return 0;
 - diff --git a/jalv/src/jalv_internal.h b/jalv/src/jalv_internal.h
 - index 4531ee6..f24c05a 100644
 - --- a/jalv/src/jalv_internal.h
 - +++ b/jalv/src/jalv_internal.h
 - @@ -44,6 +44,8 @@
 -  #include "lv2_evbuf.h"
 -  #include "symap.h"
 -  
 - +#include "lv2_external_ui.h"
 - +
 -  #ifdef __cplusplus
 -  extern "C" {
 -  #endif
 - @@ -139,6 +141,8 @@ typedef struct {
 -  	LilvNode* rsz_minimumSize;
 -  	LilvNode* work_interface;
 -  	LilvNode* work_schedule;
 - +	LilvNode* ui_externallv;
 - +	LilvNode* ui_externalkx;
 -  	LilvNode* end;  ///< NULL terminator for easy freeing of entire structure
 -  } JalvNodes;
 -  
 - @@ -204,6 +208,8 @@ typedef struct {
 -  	bool               buf_size_set;   ///< True iff buffer size callback fired
 -  	bool               exit;           ///< True iff execution is finished
 -  	bool               has_ui;         ///< True iff a control UI is present
 - +	bool               externalui;     ///< True iff plugin has an external-ui
 - +	LV2_External_UI_Widget* extuiptr;  ///< data structure used for external-ui
 -  } Jalv;
 -  
 -  int
 - diff --git a/jalv/src/lv2_external_ui.h b/jalv/src/lv2_external_ui.h
 - new file mode 100644
 - index 0000000..2c9e6ee
 - --- /dev/null
 - +++ b/jalv/src/lv2_external_ui.h
 - @@ -0,0 +1,109 @@
 - +/*
 - +  LV2 External UI extension
 - +  This work is in public domain.
 - +
 - +  This file is distributed in the hope that it will be useful,
 - +  but WITHOUT ANY WARRANTY; without even the implied warranty of
 - +  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 - +
 - +  If you have questions, contact Filipe Coelho (aka falkTX) <falktx@falktx.com>
 - +  or ask in #lad channel, FreeNode IRC network.
 - +*/
 - +
 - +/**
 - +   @file lv2_external_ui.h
 - +   C header for the LV2 External UI extension <http://kxstudio.sf.net/ns/lv2ext/external-ui>.
 - +*/
 - +
 - +#ifndef LV2_EXTERNAL_UI_H
 - +#define LV2_EXTERNAL_UI_H
 - +
 - +#include "lv2/lv2plug.in/ns/extensions/ui/ui.h"
 - +
 - +#define LV2_EXTERNAL_UI_URI     "http://kxstudio.sf.net/ns/lv2ext/external-ui"
 - +#define LV2_EXTERNAL_UI_PREFIX  LV2_EXTERNAL_UI_URI "#"
 - +
 - +#define LV2_EXTERNAL_UI__Host   LV2_EXTERNAL_UI_PREFIX "Host"
 - +#define LV2_EXTERNAL_UI__Widget LV2_EXTERNAL_UI_PREFIX "Widget"
 - +
 - +/** This extension used to be defined by a lv2plug.in URI */
 - +#define LV2_EXTERNAL_UI_DEPRECATED_URI "http://lv2plug.in/ns/extensions/ui#external"
 - +
 - +#ifdef __cplusplus
 - +extern "C" {
 - +#endif
 - +
 - +/**
 - + * When LV2_EXTERNAL_UI__Widget UI is instantiated, the returned
 - + * LV2UI_Widget handle must be cast to pointer to LV2_External_UI_Widget.
 - + * UI is created in invisible state.
 - + */
 - +typedef struct _LV2_External_UI_Widget {
 - +  /**
 - +   * Host calls this function regulary. UI library implementing the
 - +   * callback may do IPC or redraw the UI.
 - +   *
 - +   * @param _this_ the UI context
 - +   */
 - +  void (*run)(struct _LV2_External_UI_Widget * _this_);
 - +
 - +  /**
 - +   * Host calls this function to make the plugin UI visible.
 - +   *
 - +   * @param _this_ the UI context
 - +   */
 - +  void (*show)(struct _LV2_External_UI_Widget * _this_);
 - +
 - +  /**
 - +   * Host calls this function to make the plugin UI invisible again.
 - +   *
 - +   * @param _this_ the UI context
 - +   */
 - +  void (*hide)(struct _LV2_External_UI_Widget * _this_);
 - +
 - +} LV2_External_UI_Widget;
 - +
 - +#define LV2_EXTERNAL_UI_RUN(ptr)  (ptr)->run(ptr)
 - +#define LV2_EXTERNAL_UI_SHOW(ptr) (ptr)->show(ptr)
 - +#define LV2_EXTERNAL_UI_HIDE(ptr) (ptr)->hide(ptr)
 - +
 - +/**
 - + * On UI instantiation, host must supply LV2_EXTERNAL_UI__Host feature.
 - + * LV2_Feature::data must be pointer to LV2_External_UI_Host.
 - + */
 - +typedef struct _LV2_External_UI_Host {
 - +  /**
 - +   * Callback that plugin UI will call when UI (GUI window) is closed by user.
 - +   * This callback will be called during execution of LV2_External_UI_Widget::run()
 - +   * (i.e. not from background thread).
 - +   *
 - +   * After this callback is called, UI is defunct. Host must call LV2UI_Descriptor::cleanup().
 - +   * If host wants to make the UI visible again, the UI must be reinstantiated.
 - +   *
 - +   * @note When using the depreated URI LV2_EXTERNAL_UI_DEPRECATED_URI,
 - +   *       some hosts will not call LV2UI_Descriptor::cleanup() as they should,
 - +   *       and may call show() again without re-initialization.
 - +   *
 - +   * @param controller Host context associated with plugin UI, as
 - +   *                   supplied to LV2UI_Descriptor::instantiate().
 - +   */
 - +  void (*ui_closed)(LV2UI_Controller controller);
 - +
 - +  /**
 - +   * Optional (may be NULL) "user friendly" identifier which the UI
 - +   * may display to allow a user to easily associate this particular
 - +   * UI instance with the correct plugin instance as it is represented
 - +   * by the host (e.g. "track 1" or "channel 4").
 - +   *
 - +   * If supplied by host, the string will be referenced only during
 - +   * LV2UI_Descriptor::instantiate()
 - +   */
 - +  const char * plugin_human_id;
 - +
 - +} LV2_External_UI_Host;
 - +
 - +#ifdef __cplusplus
 - +} /* extern "C" */
 - +#endif
 - +
 - +#endif /* LV2_EXTERNAL_UI_H */
 
 
  |