aboutsummaryrefslogtreecommitdiffstats
path: root/lvz/gui_wrapper.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lvz/gui_wrapper.cpp')
-rw-r--r--lvz/gui_wrapper.cpp211
1 files changed, 211 insertions, 0 deletions
diff --git a/lvz/gui_wrapper.cpp b/lvz/gui_wrapper.cpp
new file mode 100644
index 0000000..ca2b894
--- /dev/null
+++ b/lvz/gui_wrapper.cpp
@@ -0,0 +1,211 @@
+/* LVZ - A C++ interface for writing LV2 plugins.
+ * Copyright (C) 2008 Dave Robillard <http://drobilla.net>
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This library 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. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef UI_CLASS
+#error "This file requires UI_CLASS to be defined"
+#endif
+#ifndef URI_PREFIX
+#error "This file requires URI_PREFIX to be defined"
+#endif
+#ifndef UI_URI_SUFFIX
+#error "This file requires UI_URI_SUFFIX to be defined"
+#endif
+
+#include <stdlib.h>
+#include <glib.h>
+#include <gtk/gtk.h>
+#include <cassert>
+#include "AEffEditor.hpp"
+#include "lv2_ui.h"
+#include UI_HEADER
+#include PLUGIN_HEADER
+
+extern "C" {
+
+/* UI */
+
+typedef struct {
+ bool stolen;
+ UI_CLASS* ui;
+ GtkSocket* socket;
+ Window x_window;
+ AudioEffectX* effect;
+} MDAPluginUI;
+
+
+static gboolean
+mda_ui_idle(void* data)
+{
+ MDAPluginUI* ui = (MDAPluginUI*)data;
+ if (!ui->stolen) {
+ //gtk_socket_add_id(GTK_SOCKET(ui->socket), ui->x_window);
+ ui->x_window = (Window)gtk_socket_get_id(GTK_SOCKET(ui->socket));
+ bool success = ui->ui->open((void*)ui->x_window);
+ if (!success)
+ fprintf(stderr, "FAILED TO OPEN GUI\n");
+ ui->ui->getFrame()->draw();
+ ui->stolen = true;
+ }
+
+ ui->ui->idle();
+ return true;
+}
+
+
+static LV2UI_Handle
+mda_ui_instantiate(const struct _LV2UI_Descriptor* descriptor,
+ const char* plugin_uri,
+ const char* bundle_path,
+ LV2UI_Write_Function write_function,
+ LV2UI_Controller controller,
+ LV2UI_Widget* widget,
+ const LV2_Feature* const* features)
+{
+ /* Some extensions need to be defined for this to work. Hosts must:
+ * 1) Pass a pointer to the plugin (VST is crap and has no UI separation)
+ * 2) Call idle on the UI periodically (VST is crap and uses polling)
+ *
+ * Thoughts:
+ *
+ * 1) This wrapper could be written explicitly in GTK and just get at
+ * the idle handler that way. Less burden on the host...
+ *
+ * 2) A better idea is to have a 'get plugin extension data' feature
+ * the UI (or anything else) can use to ask for any URI-identified
+ * piece of extension data (failing in this case if plugin is remote)
+ */
+
+ MDAPluginUI* ui = (MDAPluginUI*)malloc(sizeof(MDAPluginUI));
+ ui->effect = NULL;
+
+ typedef struct { const void* (*extension_data)(const char* uri); } LV2_ExtensionData;
+
+ typedef const void* (*extension_data_func)(const char* uri);
+ typedef const AudioEffectX* (*get_effect_func)(LV2_Handle instance);
+
+ LV2_Handle instance = NULL;
+ get_effect_func get_effect = NULL;
+
+
+ if (features != NULL) {
+ const LV2_Feature* feature = features[0];
+ for (size_t i = 0; (feature = features[i]) != NULL; ++i) {
+ if (!strcmp(feature->URI, "http://lv2plug.in/ns/ext/dev/plugin-instance")) {
+ instance = (LV2_Handle)feature->data;
+ } else if (!strcmp(feature->URI, "http://lv2plug.in/ns/ext/dev/extension-data")) {
+ LV2_ExtensionData* ext_data = (LV2_ExtensionData*)feature->data;
+ extension_data_func func = (extension_data_func)feature->data;
+ get_effect = (get_effect_func)ext_data->extension_data(
+ "http://lv2plug.in/ns/ext/dev/vstgui");
+ }
+ }
+ }
+
+ if (instance && get_effect) {
+ ui->effect = (AudioEffectX*)get_effect(instance);
+ } else {
+ fprintf(stderr, "Host does not support required features, aborting.\n");
+ return NULL;
+ }
+
+ ui->ui = new UI_CLASS(ui->effect);
+ ui->ui->setBundlePath(bundle_path);
+ ui->stolen = false;
+
+ ui->socket = GTK_SOCKET(gtk_socket_new());
+ gtk_widget_show_all(GTK_WIDGET(ui->socket));
+
+ *widget = ui->socket;
+ g_timeout_add(30, mda_ui_idle, ui);
+
+ return ui;
+}
+
+
+static void
+mda_ui_cleanup(LV2UI_Handle instance)
+{
+ g_idle_remove_by_data(instance);
+}
+
+
+static void
+mda_ui_port_event(LV2UI_Handle ui,
+ uint32_t port_index,
+ uint32_t buffer_size,
+ uint32_t format,
+ const void* buffer)
+{
+ // VST UIs seem to not use this at all, it's all polling
+ // The shit the proprietary people come up (and get away) with...
+}
+
+
+static const void*
+mda_ui_extension_data(const char* uri)
+{
+ return NULL;
+}
+
+
+/* Library */
+
+static LV2UI_Descriptor *mda_ui_descriptor = NULL;
+
+static void
+init_ui_descriptor()
+{
+ mda_ui_descriptor = (LV2UI_Descriptor*)malloc(sizeof(LV2UI_Descriptor));
+
+ mda_ui_descriptor->URI = URI_PREFIX UI_URI_SUFFIX;
+ mda_ui_descriptor->instantiate = mda_ui_instantiate;
+ mda_ui_descriptor->cleanup = mda_ui_cleanup;
+ mda_ui_descriptor->port_event = mda_ui_port_event;
+ mda_ui_descriptor->extension_data = mda_ui_extension_data;
+}
+
+
+LV2_SYMBOL_EXPORT
+const LV2UI_Descriptor*
+lv2ui_descriptor(uint32_t index)
+{
+ if (!mda_ui_descriptor)
+ init_ui_descriptor();
+
+ switch (index) {
+ case 0:
+ return mda_ui_descriptor;
+ default:
+ return NULL;
+ }
+}
+
+
+LV2_SYMBOL_EXPORT
+AEffEditor*
+lvz_new_aeffeditor(AudioEffect* effect)
+{
+ UI_CLASS* ui = new UI_CLASS(effect);
+ ui->setURI(URI_PREFIX UI_URI_SUFFIX);
+ ui->setPluginURI(URI_PREFIX PLUGIN_URI_SUFFIX);
+ return ui;
+}
+
+
+} // extern "C"
+