Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

LV2 support for Anklang #32

Closed
wants to merge 117 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
117 commits
Select commit Hold shift + click to select a range
8fd06b7
ASE: datautils: support fast_copy for bytes -> memcpy
swesterfeld Nov 14, 2023
c6cdbfc
MISC: config-checks.mk: add lv2 dependencies
swesterfeld Nov 14, 2023
f59bfdd
ASE: add LV2 device
swesterfeld Nov 14, 2023
2e5ffec
ASE: LV2Device: implement plugin list
swesterfeld Nov 16, 2023
a9331d2
ASE: lv2device.hh: fix include guard name
swesterfeld Nov 18, 2023
92effc5
ASE: lv2device: fix device name for LV2 plugins
swesterfeld Nov 22, 2023
56bf05b
MISC: depend on libsuil for ui support
swesterfeld Nov 22, 2023
3dc4d4c
ASE: implement initial hacky custom ui support for LV2
swesterfeld Nov 22, 2023
a97e760
ASE: lv2device.cc: use singleton for PluginHost
swesterfeld Nov 22, 2023
e7d90a2
ASE: lv2device.cc: use new parameter map API
swesterfeld Nov 27, 2023
0ace442
ASE: lv2device.cc: handle ui events
swesterfeld Nov 27, 2023
3299cab
ASE: lv2device.cc: implement LV2_Extension_Data_Feature
swesterfeld Nov 27, 2023
c20718f
ASE: lv2device.cc: send port events from dsp to ui
swesterfeld Nov 28, 2023
ae1fe81
ASE: lv2device.cc: use loft allocator for control events
swesterfeld Nov 28, 2023
2818ff7
ASE: lv2device.cc: implement unmap feature: URID -> string "unmapping"
swesterfeld Nov 28, 2023
ee3b087
ASE: lv2device.cc: don't use libsuil anymore
swesterfeld Nov 29, 2023
236c092
ASE: gtk2wrap: don't support libsuil wrapping anymore
swesterfeld Nov 29, 2023
1f5007f
MISC: no longer depend on libsuil for ui support
swesterfeld Nov 29, 2023
ebe4957
ASE: lv2device.cc: delete plugin UI if window is closed
swesterfeld Nov 29, 2023
f72410b
ASE: lv2device.cc: remove ui timer if the ui is closed
swesterfeld Nov 30, 2023
9bb5522
ASE: lv2device.cc: send initial control port values to ui
swesterfeld Nov 30, 2023
06fa796
ASE: lv2device.cc: set proper window title
swesterfeld Nov 30, 2023
ce6f035
ASE: lv2device: add basic support for properties
swesterfeld Nov 30, 2023
c0e0e52
ASE: processor: add method to change parameter value from render func…
swesterfeld Nov 30, 2023
f9379c0
ASE: lv2device.cc: update Anklang UI if LV2 custom UI parameter is ch…
swesterfeld Nov 30, 2023
fd74079
ASE: lv2device.cc: only send DSP->UI notifications if UI is visible
swesterfeld Nov 30, 2023
15c7c37
ASE: no longer use RingBuffer for worker thread communication
swesterfeld Nov 30, 2023
1644e8a
ASE: lv2device.cc: refactor/cleanup control event handling
swesterfeld Nov 30, 2023
0e23715
ASE: lv2device.cc: cleanup free trash events code
swesterfeld Nov 30, 2023
d505218
ASE: lv2device.cc: send ui updates less frequently for small block sizes
swesterfeld Dec 1, 2023
f91ee60
ASE: lv2device.cc: set timer period from ui_update_fps
swesterfeld Dec 1, 2023
00dfd24
ASE: lv2device.cc: avoid printf / fprintf (use printerr)
swesterfeld Dec 1, 2023
2d046fb
ASE: lv2device.cc: refactor: move ui related setup to constructor
swesterfeld Dec 1, 2023
7456634
ASE: lv2device.cc: PluginUI refactoring / improvements
swesterfeld Dec 1, 2023
906e176
ASE: platform: implement gtk thread check (this_thread_is_gtk)
swesterfeld Dec 2, 2023
3d8a57b
ASE: gtk2wrap: add new functions required by LV2 plugin implementation
swesterfeld Dec 2, 2023
3e8d65f
ASE: clapplugin.cc: add gtk thread to TaskRegistry
swesterfeld Dec 2, 2023
3f0d889
ASE: lv2device: use gtk thread for non-RT plugin functions
swesterfeld Dec 2, 2023
8402de1
MISC: use libsuil, but only for gtk2wrap
swesterfeld Dec 3, 2023
3708fdb
ASE: gtk2wrap: wrap suil functions
swesterfeld Dec 3, 2023
048cf6f
ASE: lv2device.cc: use libsuil to display plugin UI
swesterfeld Dec 3, 2023
183450a
ASE: clapplugin.cc: load gtk2wrap with RTLD_GLOBAL to provide gtk sym…
swesterfeld Dec 4, 2023
9e6f16a
ASE: implement LV2 ui parent feature
swesterfeld Dec 4, 2023
3d2a402
ASE: lv2device.cc: free lilv instance in Gtk thread
swesterfeld Dec 4, 2023
ac7f6da
ASE: lv2device.cc: add TODO list
swesterfeld Dec 5, 2023
a6370c8
ASE: gtk2wrap: wrap suil get widget
swesterfeld Dec 5, 2023
957ac42
ASE: lv2device.cc: support external UIs
swesterfeld Dec 5, 2023
11f547d
ASE: lv2device.cc: simplify PluginUI creation
swesterfeld Dec 5, 2023
18a9105
ASE: lv2device.cc: cleanup UI feature generation code
swesterfeld Dec 5, 2023
3f94c60
ASE: add external UI header for LV2 support
swesterfeld Dec 5, 2023
4dfcebb
ASE: lv2device.cc: guess nicks for now
swesterfeld Dec 5, 2023
a122db7
ASE: use LV2 optionalFeature to determine if UI window should be resi…
swesterfeld Dec 5, 2023
81c30c7
ASE: lv2device.cc: simplify no user resize check
swesterfeld Dec 5, 2023
4767308
ASE: lv2device: implement simple save state function (no path mapping)
swesterfeld Dec 6, 2023
78225bf
ASE: lv2device.cc: sort LV2 plugins by name
swesterfeld Dec 9, 2023
1cd1755
ASE: lv2device.cc: implement simple load state function (no path mapp…
swesterfeld Dec 10, 2023
34172b2
ASE: lv2device.cc: enable DSP->UI notifications early on
swesterfeld Dec 10, 2023
db99832
ASE: lv2device.cc: support setting minimum size using LV2 resize port…
swesterfeld Dec 10, 2023
722454d
ASE: lv2device.cc: provide transport information to plugin
swesterfeld Dec 11, 2023
fd68c01
ASE: lv2device.cc: use the right port for time position and midi input
swesterfeld Dec 11, 2023
b0ed01c
ASE: lv2device.cc: check required features before using a plugin
swesterfeld Dec 11, 2023
2728726
ASE: lv2device.cc: detect required UI features that we don't support
swesterfeld Dec 12, 2023
cf35e05
ASE: lv2device.cc: implement symbol to port index lookup function
swesterfeld Dec 12, 2023
47ddd7a
ASE: lv2device.cc: implement loading plugin default state
swesterfeld Dec 12, 2023
fb27c38
ASE: lv2device.cc: update supported ui features
swesterfeld Dec 12, 2023
fece237
ASE: lv2device.cc: implement basic path mapping
swesterfeld Dec 16, 2023
5facf9d
ASE: lv2device.cc: unify preset and state loading port value setting …
swesterfeld Dec 16, 2023
853a778
ASE: lv2device.cc: support standard LV2 port units for text conversion
swesterfeld Dec 17, 2023
2e648c6
ASE: lv2device.cc: implement logarithmic port property
swesterfeld Dec 18, 2023
8e1615d
ASE: lv2device.cc: implement integer, toggled and enumeration ports
swesterfeld Dec 18, 2023
4568b29
ASE: lv2device.cc: support setting custom unit symbols for ports
swesterfeld Dec 18, 2023
d94022d
ASE: lv2device.cc: refactor state load code
swesterfeld Dec 19, 2023
e8a5eeb
ASE: lv2device.cc: refactor save to string
swesterfeld Dec 19, 2023
154d3c0
ASE: lv2device.cc: merge save / restore feature code
swesterfeld Dec 19, 2023
1225b1f
ASE: lv2device.cc: refactor PluginInstance constructor
swesterfeld Dec 19, 2023
1b4d75f
ASE: lv2device.cc: properly free allocated memory to avoid leaks
swesterfeld Dec 20, 2023
cddb19c
ASE: lv2device.cc: create worker thread only if plugin really needs one
swesterfeld Dec 20, 2023
15b8972
ASE: lv2device.cc: load default state only if plugin wants us to
swesterfeld Dec 20, 2023
6e6b5fb
ASE: LV2: move responsibility for switching to gtk thread to processor
swesterfeld Dec 20, 2023
2673412
ASE: lv2device.cc: make more PluginInstance members private
swesterfeld Dec 21, 2023
c287d71
ASE: lv2device.cc: simplify save
swesterfeld Dec 21, 2023
3afcc87
ASE: lv2device.cc: remove processor from plugin list
swesterfeld Dec 21, 2023
d2c4ca3
ASE: lv2device.cc: make more PluginInstance members private
swesterfeld Dec 21, 2023
3a1d10e
ASE: lv2device.cc: make more PluginInstance members private
swesterfeld Dec 21, 2023
e1ed19e
ASE: lv2device.cc: merge port flags and type
swesterfeld Dec 21, 2023
8bcaee7
ASE: lv2device.cc: make more stuff private in PluginInstance class
swesterfeld Dec 21, 2023
fa37b75
ASE: lv2device.cc: cleanup plugin instance/ui APIs
swesterfeld Dec 22, 2023
b8a8e7d
ASE: lv2device.cc: make PluginUI members private
swesterfeld Dec 22, 2023
5a800e1
ASE: lv2device.cc: get rid of static ui type variable
swesterfeld Dec 22, 2023
da23bce
ASE: lv2device.cc: check for plugin ui once in PluginInstance constru…
swesterfeld Dec 22, 2023
a6f0e8d
ASE: lv2device.cc: cleanup control inputs in PluginInstance
swesterfeld Dec 22, 2023
7d2ae47
ASE: lv2device.cc: fix member variable names
swesterfeld Dec 22, 2023
72c23a7
ASE: lv2device.cc: make control changed callback private
swesterfeld Dec 22, 2023
8fd3d31
ASE: lv2device.cc: consistency fixes
swesterfeld Dec 23, 2023
ad2bf01
ASE: lv2device.cc: make Worker implementation details private
swesterfeld Dec 23, 2023
b3f630b
ASE: lv2device.cc: cleanup Worker class a bit more
swesterfeld Dec 23, 2023
8ae825e
ASE: lv2device.cc: move options from plugin host to plugin instance
swesterfeld Dec 23, 2023
6bae3d5
ASE: lv2device.cc: use assert_return instead of assert where possible
swesterfeld Dec 31, 2023
2f4e97c
ASE: lv2device.cc: support bpm ports
swesterfeld Dec 31, 2023
1697717
ASE: lv2device.cc: support notOnGUI port property
swesterfeld Dec 31, 2023
9862159
ASE: lv2device.cc: update TODO comments
swesterfeld Dec 31, 2023
34f8093
ASE: lv2device.cc: support building with old LV2 headers without free…
swesterfeld Jan 1, 2024
8c1a575
EXTERNAL: lilv: add our version of lilv and its dependencies
swesterfeld Jan 7, 2024
7cd643b
MISC: use / build our own liblilv
swesterfeld Jan 7, 2024
a544abb
ASE: link against our own statically compiled liblilv
swesterfeld Jan 7, 2024
639e928
MISC: build-lilv.sh: don't fail if PKG_CONFIG_PATH is empty
swesterfeld Jan 7, 2024
575b91b
MISC: Dockerfile.arch: add suil for lv2 ui support
swesterfeld Jan 7, 2024
5b0d20c
MISC: Dockerfile.arch: install meson as well
swesterfeld Jan 7, 2024
0a4bf23
MISC: build-lilv.sh: support both, debian-like and normal library dir
swesterfeld Jan 7, 2024
88bb7e7
ASE: update LV2 event buffer to latest version from jalv
swesterfeld Jan 8, 2024
9419ddb
ASE: use public domain version of LV2 external UI header
swesterfeld Jan 8, 2024
706f212
MISC: mkcopyright.py: support SPDX identifier for ISC license
swesterfeld Jan 8, 2024
bd9dea8
MISC: build-lilv.sh - don't need to --reconfigure for meson
swesterfeld Jan 8, 2024
d9ed57f
ASE: lv2device.cc: cleanup feature code for external UIs
swesterfeld Jan 8, 2024
a1ca1ed
X11TEST: run AnklangSynthEngine with $DISPLAY set to virtual X11 server
swesterfeld Jan 14, 2024
558e317
X11TEST: replay.sh: don't fail if there are no subprocesses to kill
swesterfeld Jan 14, 2024
e705869
ASE: Makefile.mk: reorder static libs, liblilv depends on the others
swesterfeld Jan 25, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,22 @@
[submodule "websocketpp"]
path = external/websocketpp
url = https://github.com/zaphoyd/websocketpp.git
# lilv and its dependencies
[submodule "lilv"]
path = external/lilv
url = https://github.com/swesterfeld/lilv
[submodule "lv2"]
path = external/lv2
url = https://github.com/drobilla/lv2.git
[submodule "serd"]
path = external/serd
url = https://github.com/drobilla/serd.git
[submodule "sord"]
path = external/sord
url = https://github.com/drobilla/sord.git
[submodule "sratom"]
path = external/sratom
url = https://github.com/drobilla/sratom.git
[submodule "zix"]
path = external/zix
url = https://github.com/drobilla/zix.git
18 changes: 16 additions & 2 deletions ase/Makefile.mk
Original file line number Diff line number Diff line change
Expand Up @@ -133,21 +133,35 @@ CLEANDIRS += $>/sndfile/
CLEANFILES += $>/lib/libsndfile.*
ase/sndfile.cc: $>/lib/libsndfile.so # includes $>/sndfile/src/config.h

# == lilv ==
$>/lib/liblilv-0.a: .submodule-stamp external/lilv/include/lilv/lilv.h | $>/lib/
$(QGEN)
$Q misc/build-lilv.sh $>

# == AnklangSynthEngine ==
ASE_EXTERNAL_INCLUDES := $(strip \
-Iexternal/clap/include \
-Iexternal/libsndfile/include \
-Iexternal/lilv/include \
-Iexternal/rapidjson/include \
-Iexternal/websocketpp \
)
LILV_LIBS := $(strip \
$>/lib/liblilv-0.a \
$>/lib/libserd-0.a \
$>/lib/libsord-0.a \
$>/lib/libsratom-0.a \
$>/lib/libzix-0.a \
)

$(ase/AnklangSynthEngine.objects): $(ase/include.deps) $(ase/libase.deps)
$(ase/AnklangSynthEngine.objects): EXTRA_INCLUDES ::= $(ASE_EXTERNAL_INCLUDES) -I$> -I$>/external/ $(ASEDEPS_CFLAGS)
$(lib/AnklangSynthEngine): $>/lib/libsndfile.so | $>/lib/
$(lib/AnklangSynthEngine): $>/lib/libsndfile.so $>/lib/liblilv-0.a | $>/lib/
$(call BUILD_PROGRAM, \
$(lib/AnklangSynthEngine), \
$(ase/AnklangSynthEngine.objects), \
$(lib/libase.so), \
$(BOOST_SYSTEM_LIBS) $(ASEDEPS_LIBS) $(ALSA_LIBS) -lzstd -ldl $>/lib/libsndfile.so, \
$(BOOST_SYSTEM_LIBS) $(ASEDEPS_LIBS) $(ALSA_LIBS) -lzstd -ldl $(LILV_LIBS) $>/lib/libsndfile.so, \
../lib)
# Work around legacy code in external/websocketpp/*.hpp
ase/websocket.cc.FLAGS = -Wno-deprecated-dynamic-exception-spec -Wno-sign-promo
Expand Down
11 changes: 10 additions & 1 deletion ase/clapplugin.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1971,12 +1971,21 @@ try_load_x11wrapper()
return_unless (x11wrapper == nullptr);
static Gtk2DlWrapEntry *gtk2wrapentry = [] () {
String gtk2wrapso = anklang_runpath (RPath::LIBDIR, "gtk2wrap.so");
void *gtkdlhandle_ = dlopen (gtk2wrapso.c_str(), RTLD_LOCAL | RTLD_NOW);
void *gtkdlhandle_ = dlopen (gtk2wrapso.c_str(), RTLD_GLOBAL | RTLD_NOW);
const char *symname = "Ase__Gtk2__wrapentry";
void *ptr = gtkdlhandle_ ? dlsym (gtkdlhandle_, symname) : nullptr;
return (Gtk2DlWrapEntry*) ptr;
} ();
x11wrapper = gtk2wrapentry;
if (x11wrapper)
TaskRegistry::set_gtk_thread_id (x11wrapper->gtk_thread_id());
}

Gtk2DlWrapEntry *
get_x11wrapper()
{
try_load_x11wrapper();
return x11wrapper;
}

// == ClapPluginHandle ==
Expand Down
3 changes: 3 additions & 0 deletions ase/clapplugin.hh
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

#include <ase/device.hh>
#include <clap/clap.h>
#include <ase/gtk2wrap.hh>

namespace Ase {

Expand Down Expand Up @@ -96,6 +97,8 @@ const char* clap_event_type_string (int etype);
String clap_event_to_string (const clap_event_note_t *enote);
DeviceInfo clap_device_info (const ClapPluginDescriptor &descriptor);

Gtk2DlWrapEntry *get_x11wrapper();

} // Ase

#endif // __ASE_CLAP_PLUGIN_HH__
1 change: 1 addition & 0 deletions ase/defs.hh
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ ASE_CLASS_DECLS (Emittable);
ASE_CLASS_DECLS (FileCrawler);
ASE_CLASS_DECLS (Gadget);
ASE_CLASS_DECLS (GadgetImpl);
ASE_CLASS_DECLS (LV2DeviceImpl);
ASE_CLASS_DECLS (Monitor);
ASE_CLASS_DECLS (NativeDevice);
ASE_CLASS_DECLS (NativeDeviceImpl);
Expand Down
147 changes: 144 additions & 3 deletions ase/gtk2wrap.cc
Original file line number Diff line number Diff line change
@@ -1,13 +1,19 @@
// This Source Code Form is licensed MPL-2.0: http://mozilla.org/MPL/2.0
#include "gtk2wrap.hh"
#include <gtk/gtk.h>
#include <suil/suil.h>
#include <semaphore.h>
#include <thread>
#include <map>
#include <cassert>

namespace { // Anon
using namespace Ase;

static std::thread *gtkthred = nullptr;
using std::string;

static std::thread *gtk_thread = nullptr;
static std::thread::id gtk_thread_id {};

// == Semaphore ==
class Semaphore {
Expand Down Expand Up @@ -96,6 +102,17 @@ create_window (const Gtk2WindowSetup &wsetup)
return windowid;
}

static void *
create_suil_window (const string &window_title, bool resizable, const std::function<void()>& deleterequest_mt)
{
GtkWidget *window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_resizable (GTK_WINDOW (window), resizable);
BWrap *bw = vwrap (deleterequest_mt);
g_signal_connect_data (window, "delete-event", (GCallback) bw->truefunc, bw, (GClosureNotify) bw->deleter, G_CONNECT_SWAPPED);
gtk_window_set_title (GTK_WINDOW (window), window_title.c_str());
return window;
}

static bool
destroy_window (ulong windowid)
{
Expand Down Expand Up @@ -137,11 +154,71 @@ hide_window (ulong windowid)
return true;
}

static std::thread::id
get_gtk_thread_id()
{
return std::this_thread::get_id();
}

struct TimerHelper
{
std::function<bool()> callback;
guint id = 0;
};

std::map<guint, std::unique_ptr<TimerHelper>> timer_helper_map;

static guint
register_timer (const std::function<bool()>& callback, guint interval_ms)
{
auto timer_helper_ptr = std::make_unique<TimerHelper> (callback, 0);

guint id = g_timeout_add (interval_ms,
[] (gpointer data) -> int
{
TimerHelper *helper = (TimerHelper *) data;
auto again = helper->callback();
if (!again)
timer_helper_map.erase (helper->id);
return again;
},
timer_helper_ptr.get());

timer_helper_ptr->id = id;
timer_helper_map[id] = std::move (timer_helper_ptr);
return id;
}

static bool
remove_timer (uint timer_id)
{
if (timer_helper_map.erase (timer_id) != 1)
fprintf (stderr, "Gtk2Wrap: removing timer callback id=%u from map failed\n", timer_id);

if (g_source_remove (timer_id))
return true;

fprintf (stderr, "Gtk2Wrap: removing timer with id=%u failed", timer_id);
return false;
}

static bool
exec_in_gtk_thread (const std::function<void()>& func)
{
func();
return true;
}

template<typename Ret, typename ...Args, typename ...Params> static Ret
gtkidle_call (Ret (*func) (Params...), Args &&...args)
{
if (!gtkthred) // FIXME: need thread cleanup
gtkthred = new std::thread (gtkmain);
if (!gtk_thread) // FIXME: need thread cleanup
{
gtk_thread = new std::thread (gtkmain);
gtk_thread_id = gtk_thread->get_id();
}
// using this function from gtk thread would block execution (and never return)
assert (std::this_thread::get_id() != gtk_thread_id);
Semaphore sem;
Ret ret = {};
BWrap *bw = bwrap ([&sem, &ret, func, &args...] () -> bool {
Expand All @@ -157,6 +234,12 @@ gtkidle_call (Ret (*func) (Params...), Args &&...args)
return ret;
}

void
check_gtk_thread()
{
assert (std::this_thread::get_id() == gtk_thread_id);
}

} // Anon

extern "C" {
Expand All @@ -178,5 +261,63 @@ Ase::Gtk2DlWrapEntry Ase__Gtk2__wrapentry {
},
.threads_enter = gdk_threads_enter,
.threads_leave = gdk_threads_leave,
.gtk_thread_id = [] () -> std::thread::id {
return gtkidle_call (get_gtk_thread_id);
},
.register_timer = [] (const std::function<bool()>& callback, uint interval_ms) -> uint {
check_gtk_thread();
return register_timer (callback, interval_ms);
},
.remove_timer = [] (uint timer_id) -> bool {
check_gtk_thread();
return remove_timer (timer_id);
},
.exec_in_gtk_thread = [] (const std::function<void()>& func) {
gtkidle_call (exec_in_gtk_thread, func);
},
.create_suil_host = [] (SPortWriteFunc write_func, SPortIndexFunc index_func) -> void * {
return gtkidle_call (suil_host_new, write_func, index_func, nullptr, nullptr);
},
.create_suil_instance = [] (void *host, void *controller,
const string &container_type_uri, const string &plugin_uri,
const string &ui_uri, const string &ui_type_uri,
const string &ui_bundle_path, const string &ui_binary_path,
const LV2_Feature *const *features) -> void * {
check_gtk_thread();
return suil_instance_new ((SuilHost *) host, (SuilController *) controller,
container_type_uri.c_str(), plugin_uri.c_str(),
ui_uri.c_str(), ui_type_uri.c_str(),
ui_bundle_path.c_str(), ui_binary_path.c_str(),
features);
},
.destroy_suil_instance = [] (void *instance) {
check_gtk_thread();
suil_instance_free ((SuilInstance *) instance);
},
.create_suil_window = [] (const string &window_title, bool resizable, const std::function<void()>& deleterequest_mt) -> void * {
check_gtk_thread();
return create_suil_window (window_title, resizable, deleterequest_mt);
},
.add_suil_widget_to_window = [] (void *window, void *instance) {
check_gtk_thread();
gtk_container_add (GTK_CONTAINER (window), GTK_WIDGET (suil_instance_get_widget ((SuilInstance *) instance)));
gtk_widget_show_all (GTK_WIDGET (window));
},
.destroy_suil_window = [] (void *window) -> void {
check_gtk_thread();
gtk_widget_destroy (GTK_WIDGET (window));
},
.suil_ui_supported = [] (const string& host_type_uri, const string& ui_type_uri) -> unsigned {
check_gtk_thread();
return suil_ui_supported (host_type_uri.c_str(), ui_type_uri.c_str());
},
.suil_instance_port_event = [] (void *instance, uint32_t port_index, uint32_t buffer_size, uint32_t format, const void *buffer) {
check_gtk_thread();
return suil_instance_port_event ((SuilInstance *) instance, port_index, buffer_size, format, buffer);
},
.get_suil_widget = [] (void *instance) {
check_gtk_thread();
return suil_instance_get_widget ((SuilInstance *) instance);
}
};
} // "C"
37 changes: 30 additions & 7 deletions ase/gtk2wrap.hh
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@

#include <string>
#include <functional>
#include <thread>

#include <lv2/core/lv2.h>

namespace Ase {

Expand All @@ -13,14 +16,34 @@ struct Gtk2WindowSetup {
std::function<void()> deleterequest_mt;
};

typedef void (*SPortWriteFunc) (void *controller, uint32_t port_index, uint32_t buffer_size, uint32_t protocol, void const* buffer);
typedef uint32_t (*SPortIndexFunc) (void *controller, const char* port_symbol);

struct Gtk2DlWrapEntry {
ulong (*create_window) (const Gtk2WindowSetup &windowsetup);
bool (*resize_window) (ulong windowid, int width, int height);
void (*show_window) (ulong windowid);
void (*hide_window) (ulong windowid);
void (*destroy_window) (ulong windowid);
void (*threads_enter) ();
void (*threads_leave) ();
ulong (*create_window) (const Gtk2WindowSetup &windowsetup);
bool (*resize_window) (ulong windowid, int width, int height);
void (*show_window) (ulong windowid);
void (*hide_window) (ulong windowid);
void (*destroy_window) (ulong windowid);
void (*threads_enter) ();
void (*threads_leave) ();
std::thread::id (*gtk_thread_id) ();
uint (*register_timer) (const std::function<bool()>& callback, uint interval_ms);
bool (*remove_timer) (uint timer_id);
void (*exec_in_gtk_thread) (const std::function<void()>& func);
void *(*create_suil_host) (SPortWriteFunc write_func, SPortIndexFunc index_func);
void *(*create_suil_instance) (void *host, void *controller,
const std::string &container_type_uri, const std::string &plugin_uri,
const std::string &ui_uri, const std::string &ui_type_uri,
const std::string &ui_bundle_path, const std::string &ui_binary_path,
const LV2_Feature *const *features);
void (*destroy_suil_instance) (void *instance);
void *(*create_suil_window) (const std::string &window_title, bool resizable, const std::function<void()>& deleterequest_mt);
void (*add_suil_widget_to_window) (void *window, void *instance);
void (*destroy_suil_window) (void *window);
uint (*suil_ui_supported) (const std::string& host_type_uri, const std::string& ui_type_uri);
void (*suil_instance_port_event) (void *instance, uint32_t port_index, uint32_t buffer_size, uint32_t format, const void *buffer);
void *(*get_suil_widget) (void *instance);
};

} // Ase
Expand Down
Loading