[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