diff options
author | David Robillard <d@drobilla.net> | 2008-08-12 00:20:16 +0000 |
---|---|---|
committer | David Robillard <d@drobilla.net> | 2008-08-12 00:20:16 +0000 |
commit | 102e899c331bd2ed9902467a077164e209c918f9 (patch) | |
tree | b7fe5ec873582cc8a0fc0862f9da045d12b2259a /lvz/gui_wrapper.cpp | |
parent | 2b679f152e1c3104ac178b6c78ac0b1edf954ff6 (diff) | |
download | mda.lv2-102e899c331bd2ed9902467a077164e209c918f9.tar.gz mda.lv2-102e899c331bd2ed9902467a077164e209c918f9.tar.bz2 mda.lv2-102e899c331bd2ed9902467a077164e209c918f9.zip |
VSTUI X11 port and embeddable GTK wrapper.
Build mdaSpecMeter and GUI.
git-svn-id: http://svn.drobilla.net/lad/mda-lv2@1340 a436a847-0d15-0410-975c-d299462d15a1
Diffstat (limited to 'lvz/gui_wrapper.cpp')
-rw-r--r-- | lvz/gui_wrapper.cpp | 211 |
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" + |