[SCM] calf/master: More external GUI related changes.
js at users.alioth.debian.org
js at users.alioth.debian.org
Tue May 7 15:39:59 UTC 2013
The following commit has been merged in the master branch:
commit c5dc170ee85df3bbf385d92b0d8ba6c3ad4e2150
Author: Krzysztof Foltman <wdev at foltman.com>
Date: Sat Apr 3 19:56:36 2010 +0100
More external GUI related changes.
Separate OSC server code into base class that can receive data from socket when
requested to, and a Glib-specific class that uses a Glib main loop. Allow DSSI
GUI to accept both plugin URIs and plugin IDs. Implement skeleton DSSI GUI host
in the LV2 UI library - some essential functionality is still missing. Rename
osc_socket::get_uri to get_url (more fitting). Add OSC server code to the LV2
GUI library.
diff --git a/src/Makefile.am b/src/Makefile.am
index 1f7ca74..dd7d6a0 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -61,7 +61,7 @@ calf_la_LDFLAGS = -rpath $(ladspadir) -avoid-version -module -lexpat -disable-st
endif
if USE_LV2_GUI
-calflv2gui_la_SOURCES = gui.cpp gui_controls.cpp ctl_curve.cpp ctl_keyboard.cpp ctl_led.cpp custom_ctl.cpp modules.cpp giface.cpp preset.cpp synth.cpp lv2gui.cpp main_win.cpp osctl.cpp osctlnet.cpp utils.cpp
+calflv2gui_la_SOURCES = gui.cpp gui_controls.cpp ctl_curve.cpp ctl_keyboard.cpp ctl_led.cpp custom_ctl.cpp modules.cpp giface.cpp preset.cpp synth.cpp lv2gui.cpp main_win.cpp osctl.cpp osctlnet.cpp osctlserv.cpp utils.cpp
if USE_DEBUG
calflv2gui_la_LDFLAGS = -rpath $(lv2dir) -avoid-version -module -lexpat $(GUI_DEPS_LIBS) -disable-static
else
diff --git a/src/calf/giface.h b/src/calf/giface.h
index e6c0736..9dc9e53 100644
--- a/src/calf/giface.h
+++ b/src/calf/giface.h
@@ -393,6 +393,8 @@ public:
const plugin_vector &get_all() { return plugins; }
/// Get single plugin metadata object by URI
const plugin_metadata_iface *get_by_uri(const char *URI);
+ /// Get single plugin metadata object by URI
+ const plugin_metadata_iface *get_by_id(const char *id, bool case_sensitive = false);
};
/// Load and strdup a text file with GUI definition
diff --git a/src/calf/osctlnet.h b/src/calf/osctlnet.h
index 47b2989..5117be0 100644
--- a/src/calf/osctlnet.h
+++ b/src/calf/osctlnet.h
@@ -36,7 +36,7 @@ struct osc_socket
osc_socket() : socket(-1), srcid(0) {}
void bind(const char *hostaddr = "0.0.0.0", int port = 0);
- std::string get_uri() const;
+ std::string get_url() const;
virtual void on_bind() {}
virtual ~osc_socket();
};
diff --git a/src/calf/osctlserv.h b/src/calf/osctlserv.h
index 5b44c47..84535c8 100644
--- a/src/calf/osctlserv.h
+++ b/src/calf/osctlserv.h
@@ -28,19 +28,30 @@
namespace osctl
{
+
+
struct osc_server: public osc_socket
{
- GIOChannel *ioch;
osc_message_dump<osc_strstream, std::ostream> dump;
osc_message_sink<osc_strstream> *sink;
- osc_server() : ioch(NULL), dump(std::cout), sink(&dump) {}
+ osc_server() : dump(std::cout), sink(&dump) {}
+
+ void read_from_socket();
+ void parse_message(const char *buffer, int len);
+ ~osc_server();
+};
+
+struct osc_glib_server: public osc_server
+{
+ GIOChannel *ioch;
+
+ osc_glib_server() : ioch(NULL) {}
virtual void on_bind();
static gboolean on_data(GIOChannel *channel, GIOCondition cond, void *obj);
- void parse_message(const char *buffer, int len);
- ~osc_server();
+ ~osc_glib_server();
};
};
diff --git a/src/dssigui.cpp b/src/dssigui.cpp
index 927bdcf..11c3e7f 100644
--- a/src/dssigui.cpp
+++ b/src/dssigui.cpp
@@ -141,7 +141,7 @@ struct plugin_proxy: public plugin_ctl_iface, public plugin_metadata_proxy, publ
map<int, param_line_graphs> graphs;
bool update_graphs;
- plugin_proxy(plugin_metadata_iface *md)
+ plugin_proxy(const plugin_metadata_iface *md)
: plugin_metadata_proxy(md)
{
client = NULL;
@@ -281,7 +281,7 @@ GMainLoop *mainloop;
static bool osc_debug = false;
-struct dssi_osc_server: public osc_server, public osc_message_sink<osc_strstream>
+struct dssi_osc_server: public osc_glib_server, public osc_message_sink<osc_strstream>
{
plugin_proxy *plugin;
main_window *main_win;
@@ -304,6 +304,20 @@ struct dssi_osc_server: public osc_server, public osc_message_sink<osc_strstream
osc_link_active = false;
}
+ void set_plugin(const char *arg)
+ {
+ const plugin_metadata_iface *pmi = plugin_registry::instance().get_by_id(arg);
+ if (!pmi)
+ pmi = plugin_registry::instance().get_by_uri(arg);
+ if (!pmi)
+ {
+ fprintf(stderr, "Unknown plugin: %s\n", arg);
+ exit(1);
+ }
+ effect_name = pmi->get_id();
+ plugin = new plugin_proxy(pmi);
+ }
+
static void on_destroy(GtkWindow *window, dssi_osc_server *self)
{
debug_printf("on_destroy, have to send \"exiting\"\n");
@@ -316,21 +330,6 @@ struct dssi_osc_server: public osc_server, public osc_message_sink<osc_strstream
void create_window()
{
- plugin = NULL;
- const plugin_registry::plugin_vector &plugins = plugin_registry::instance().get_all();
- for (unsigned int i = 0; i < plugins.size(); i++)
- {
- if (!strcmp(plugins[i]->get_id(), effect_name.c_str()))
- {
- plugin = new plugin_proxy(plugins[i]);
- break;
- }
- }
- if (!plugin)
- {
- fprintf(stderr, "Unknown plugin: %s\n", effect_name.c_str());
- exit(1);
- }
plugin->client = &cli;
plugin->send_osc = true;
((main_window *)window->main)->conditions.insert("dssi");
@@ -365,7 +364,7 @@ void dssi_osc_server::set_osc_update(bool enabled)
osc_link_active = enabled;
osc_inline_typed_strstream data;
data << "OSC:FEEDBACK_URI";
- data << (enabled ? get_uri() : "");
+ data << (enabled ? get_url() : "");
cli.send("/configure", data);
}
@@ -527,6 +526,7 @@ void dssi_osc_server::receive_osc_message(std::string address, std::string args,
}
else if (address == prefix + "/show")
{
+ printf("show received\n");
set_osc_update(true);
gtk_widget_show_all(GTK_WIDGET(window->toplevel));
@@ -610,10 +610,8 @@ int main(int argc, char *argv[])
}
dssi_osc_server srv;
- srv.prefix = "/dssi/"+string(argv[optind + 1]) + "/" + string(argv[optind + 2]);
- for (char *p = argv[optind + 2]; *p; p++)
- *p = tolower(*p);
- srv.effect_name = argv[optind + 2];
+ srv.set_plugin(argv[optind + 2]);
+ srv.prefix = "/dssi/"+string(argv[optind + 1]) + "/" + srv.effect_name;
srv.title = argv[optind + 3];
srv.bind();
@@ -624,11 +622,10 @@ int main(int argc, char *argv[])
srv.cli.bind();
srv.cli.set_url(argv[optind]);
- debug_printf("URI = %s\n", srv.get_uri().c_str());
+ debug_printf("URI = %s\n", srv.get_url().c_str());
- string data_buf, type_buf;
osc_inline_typed_strstream data;
- data << srv.get_uri();
+ data << srv.get_url();
if (!srv.cli.send("/update", data))
{
g_error("Could not send the initial update message via OSC to %s", argv[optind]);
diff --git a/src/giface.cpp b/src/giface.cpp
index 9085b18..0e9b573 100644
--- a/src/giface.cpp
+++ b/src/giface.cpp
@@ -314,6 +314,17 @@ const plugin_metadata_iface *calf_plugins::plugin_registry::get_by_uri(const cha
return NULL;
}
+const plugin_metadata_iface *calf_plugins::plugin_registry::get_by_id(const char *id, bool case_sensitive)
+{
+ typedef int (*comparator)(const char *, const char *);
+ comparator comp = case_sensitive ? strcmp : strcasecmp;
+ for (unsigned int i = 0; i < plugins.size(); i++)
+ {
+ if (!comp(plugins[i]->get_id(), id))
+ return plugins[i];
+ }
+ return NULL;
+}
///////////////////////////////////////////////////////////////////////////////////////
#if USE_DSSI
diff --git a/src/lv2gui.cpp b/src/lv2gui.cpp
index eca03f7..9ca247b 100644
--- a/src/lv2gui.cpp
+++ b/src/lv2gui.cpp
@@ -31,6 +31,8 @@
#include <calf/lv2_ui.h>
#include <calf/lv2_uri_map.h>
#include <calf/lv2_external_ui.h>
+#include <calf/osctlnet.h>
+#include <calf/osctlserv.h>
#include <calf/preset_gui.h>
#include <calf/utils.h>
#include <calf/lv2helpers.h>
@@ -39,6 +41,7 @@ using namespace std;
using namespace dsp;
using namespace calf_plugins;
using namespace calf_utils;
+using namespace osctl;
struct LV2_Calf_Descriptor {
plugin_ctl_iface *(*get_pci)(LV2_Handle Instance);
@@ -282,7 +285,7 @@ void store_preset(GtkWindow *toplevel, plugin_gui *gui)
///////////////////////////////////////////////////////////////////////////////////////
-class ext_plugin_gui: public lv2_external_ui
+class ext_plugin_gui: public lv2_external_ui, public osc_message_sink<osc_strstream>
{
public:
LV2UI_Write_Function write_function;
@@ -290,21 +293,27 @@ public:
const LV2_Feature* const* features;
lv2_external_ui_host *host;
GPid child_pid;
+ osc_server srv;
+ osc_client cli;
+ bool confirmed;
+ string prefix;
ext_plugin_gui(LV2UI_Write_Function wf, LV2UI_Controller c, const LV2_Feature* const* f);
bool initialise();
- void show_impl() { printf("show\n"); }
- void hide_impl() { printf("hide\n"); }
+ void show_impl();
+ void hide_impl();
void run_impl();
+ void port_event_impl(uint32_t port, uint32_t buffer_size, uint32_t format, const void *buffer);
+ virtual void receive_osc_message(std::string address, std::string args, osc_strstream &buffer);
virtual ~ext_plugin_gui() {}
+private:
static void show_(lv2_external_ui *h) { ((ext_plugin_gui *)(h))->show_impl(); }
static void hide_(lv2_external_ui *h) { ((ext_plugin_gui *)(h))->hide_impl(); }
static void run_(lv2_external_ui *h) { ((ext_plugin_gui *)(h))->run_impl(); }
-
};
ext_plugin_gui::ext_plugin_gui(LV2UI_Write_Function wf, LV2UI_Controller c, const LV2_Feature* const* f)
@@ -313,6 +322,7 @@ ext_plugin_gui::ext_plugin_gui(LV2UI_Write_Function wf, LV2UI_Controller c, cons
controller = c;
features = f;
host = NULL;
+ confirmed = false;
show = show_;
hide = hide_;
@@ -329,18 +339,62 @@ bool ext_plugin_gui::initialise()
break;
}
}
- return (host != NULL);
+ if (host == NULL)
+ return false;
+
+ srv.sink = this;
+ srv.bind("127.0.0.1");
+
+ return true;
+}
+
+void ext_plugin_gui::show_impl()
+{
+ printf("show\n");
+ cli.send("/show");
+}
+
+void ext_plugin_gui::hide_impl()
+{
+ printf("hide\n");
+ cli.send("/hide");
+}
+
+void ext_plugin_gui::port_event_impl(uint32_t port, uint32_t buffer_size, uint32_t format, const void *buffer)
+{
+ assert(confirmed);
+ osc_inline_typed_strstream data;
+ if (format == 0)
+ {
+ data << port;
+ data << *(float *)buffer;
+ cli.send("/control", data);
+ printf("control %d %f\n", port, *(float *)buffer);
+ }
}
void ext_plugin_gui::run_impl()
{
- int status = 0;
- if (waitpid(child_pid, &status, WNOHANG) != 0)
+ if (waitpid(child_pid, NULL, WNOHANG) != 0)
{
host->ui_closed(controller);
}
+ srv.read_from_socket();
}
+void ext_plugin_gui::receive_osc_message(std::string address, std::string args, osc_strstream &buffer)
+{
+ if (address == "/bridge/update" && args == "s")
+ {
+ string url;
+ buffer >> url;
+ cli.bind();
+ cli.set_url(url.c_str());
+ confirmed = true;
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////
LV2UI_Handle extgui_instantiate(const struct _LV2UI_Descriptor* descriptor,
const char* plugin_uri,
@@ -354,16 +408,33 @@ LV2UI_Handle extgui_instantiate(const struct _LV2UI_Descriptor* descriptor,
if (!ui->initialise())
return NULL;
- const gchar *argv[] = { "./calf_gtk", "url", "calf.so", plugin_uri, (ui->host->plugin_human_id ? ui->host->plugin_human_id : "Unknown"), NULL };
+ string url = ui->srv.get_url() + "/bridge";
+ const gchar *argv[] = { "./calf_gtk", url.c_str(), "calf.so", plugin_uri, (ui->host->plugin_human_id ? ui->host->plugin_human_id : "Unknown"), NULL };
GError *error = NULL;
- if (g_spawn_async(bundle_path, (gchar **)argv, NULL, (GSpawnFlags)0, NULL, NULL, &ui->child_pid, &error))
+ if (g_spawn_async(bundle_path, (gchar **)argv, NULL, (GSpawnFlags)G_SPAWN_DO_NOT_REAP_CHILD, NULL, NULL, &ui->child_pid, &error))
{
- *(lv2_external_ui **)widget = ui;
- return (LV2UI_Handle)ui;
+ // wait for the sign of life from the GUI
+ while(!ui->confirmed && waitpid(ui->child_pid, NULL, WNOHANG) == 0)
+ {
+ printf("Waiting for the GUI to open\n");
+ ui->srv.read_from_socket();
+ usleep(500000);
+ }
+
+ if (ui->confirmed)
+ {
+ *(lv2_external_ui **)widget = ui;
+ return (LV2UI_Handle)ui;
+ }
+ else
+ {
+ g_warning("The GUI exited before establishing contact with the host");
+ return NULL;
+ }
}
else
{
- g_warning("%s\n", error->message);
+ g_warning("%s", error->message);
return NULL;
}
}
@@ -377,7 +448,7 @@ void extgui_cleanup(LV2UI_Handle handle)
void extgui_port_event(LV2UI_Handle handle, uint32_t port, uint32_t buffer_size, uint32_t format, const void *buffer)
{
- printf("port event %d\n", port);
+ ((ext_plugin_gui *)handle)->port_event_impl(port, buffer_size, format, buffer);;
}
const void *extgui_extension(const char *uri)
diff --git a/src/makerdf.cpp b/src/makerdf.cpp
index b1988fd..1fd6d8a 100644
--- a/src/makerdf.cpp
+++ b/src/makerdf.cpp
@@ -338,7 +338,8 @@ void make_ttl(string path_prefix)
gui_header = gtkgui_uri + "\n"
" a uiext:GtkUI ;\n"
" uiext:binary <calflv2gui.so> ;\n"
- " uiext:requiredFeature uiext:makeResident .\n"
+ " uiext:requiredFeature uiext:makeResident ;\n"
+ " uiext:requiredFeature uiext:gimmeACrocodileMyDear .\n"
"\n"
;
string extgui_uri = "<http://calf.sourceforge.net/plugins/gui/ext-gui>";
diff --git a/src/osctlnet.cpp b/src/osctlnet.cpp
index 210f5cd..e108468 100644
--- a/src/osctlnet.cpp
+++ b/src/osctlnet.cpp
@@ -44,7 +44,7 @@ void osc_socket::bind(const char *hostaddr, int port)
on_bind();
}
-std::string osc_socket::get_uri() const
+std::string osc_socket::get_url() const
{
sockaddr_in sadr;
socklen_t len = sizeof(sadr);
@@ -75,6 +75,7 @@ void osc_client::set_addr(const char *hostaddr, int port)
void osc_client::set_url(const char *url)
{
+ const char *orig_url = url;
if (strncmp(url, "osc.udp://", 10))
throw osc_net_bad_address(url);
url += 10;
@@ -82,11 +83,11 @@ void osc_client::set_url(const char *url)
const char *pos = strchr(url, ':');
const char *pos2 = strchr(url, '/');
if (!pos || !pos2)
- throw osc_net_bad_address(url);
+ throw osc_net_bad_address(orig_url);
// XXXKF perhaps there is a default port for osc.udp?
if (pos2 - pos < 0)
- throw osc_net_bad_address(url);
+ throw osc_net_bad_address(orig_url);
string hostname = string(url, pos - url);
int port = atoi(pos + 1);
diff --git a/src/osctlserv.cpp b/src/osctlserv.cpp
index dda8bef..6a2def2 100644
--- a/src/osctlserv.cpp
+++ b/src/osctlserv.cpp
@@ -45,33 +45,42 @@ void osc_server::parse_message(const char *buffer, int len)
}
}
-void osc_server::on_bind()
-{
- ioch = g_io_channel_unix_new(socket);
- srcid = g_io_add_watch(ioch, G_IO_IN, on_data, this);
-}
-
-gboolean osc_server::on_data(GIOChannel *channel, GIOCondition cond, void *obj)
+void osc_server::read_from_socket()
{
- osc_server *self = (osc_server *)obj;
char buf[16384];
- int len = recv(self->socket, buf, 16384, 0);
+ int len = recv(socket, buf, 16384, MSG_DONTWAIT);
if (len > 0)
{
if (buf[0] == '/')
{
- self->parse_message(buf, len);
+ parse_message(buf, len);
}
if (buf[0] == '#')
{
// XXXKF bundles are not supported yet
}
}
- return TRUE;
}
osc_server::~osc_server()
{
+}
+
+void osc_glib_server::on_bind()
+{
+ ioch = g_io_channel_unix_new(socket);
+ srcid = g_io_add_watch(ioch, G_IO_IN, on_data, this);
+}
+
+gboolean osc_glib_server::on_data(GIOChannel *channel, GIOCondition cond, void *obj)
+{
+ osc_server *self = (osc_server *)obj;
+ self->read_from_socket();
+ return TRUE;
+}
+
+osc_glib_server::~osc_glib_server()
+{
if (ioch)
g_source_remove(srcid);
}
--
calf audio plugins packaging
More information about the pkg-multimedia-commits
mailing list