[SCM] calf/master: + JACK host: attempt at add/remove plugins at runtime, probably introducing more bugs in the process (at least incorrect size on remove!), fix VU meters + flanger: fix stereo phase

js at users.alioth.debian.org js at users.alioth.debian.org
Tue May 7 15:37:04 UTC 2013


The following commit has been merged in the master branch:
commit 1a04bdac130219181f48553434726782922a92ec
Author: kfoltman <kfoltman at 78b06b96-2940-0410-b7fc-879d825d01d8>
Date:   Sun Feb 17 22:12:36 2008 +0000

    + JACK host: attempt at add/remove plugins at runtime, probably introducing more bugs in the process (at least incorrect size on remove!), fix VU meters
    + flanger: fix stereo phase
    
    
    
    git-svn-id: https://calf.svn.sourceforge.net/svnroot/calf/trunk@130 78b06b96-2940-0410-b7fc-879d825d01d8

diff --git a/src/calf/fixed_point.h b/src/calf/fixed_point.h
index 953b47b..a9a1cf2 100644
--- a/src/calf/fixed_point.h
+++ b/src/calf/fixed_point.h
@@ -57,7 +57,7 @@ public:
     }
     */
     explicit inline fixed_point(double v) {
-        value = (int)(v*(1<<FracBits));
+        value = (T)(v*(1<<FracBits));
     }
 
     inline void set(T value) {
diff --git a/src/calf/gui.h b/src/calf/gui.h
index 7352778..23a3fc3 100644
--- a/src/calf/gui.h
+++ b/src/calf/gui.h
@@ -238,9 +238,13 @@ public:
     static void xml_element_end(void *data, const char *element);
 };
 
+class main_window_owner_iface;
+    
 class main_window_iface
 {
 public:
+    virtual void set_owner(main_window_owner_iface *owner)=0;
+
     virtual void add_plugin(plugin_ctl_iface *plugin)=0;
     virtual void del_plugin(plugin_ctl_iface *plugin)=0;
     
@@ -250,6 +254,14 @@ public:
     virtual ~main_window_iface() {}
 };
 
+class main_window_owner_iface
+{
+public:
+    virtual void new_plugin(const char *name) = 0;
+    virtual void remove_plugin(plugin_ctl_iface *plugin) = 0;
+    virtual ~main_window_owner_iface() {}
+};
+
 class plugin_gui_window
 {
 public:
diff --git a/src/calf/jackhost.h b/src/calf/jackhost.h
index e25b5f4..11f4877 100644
--- a/src/calf/jackhost.h
+++ b/src/calf/jackhost.h
@@ -24,17 +24,21 @@
 #if USE_JACK
 
 #include "gui.h"
+#include "utils.h"
+#include <pthread.h>
 
 namespace synth {
 
 class jack_host_base;
     
 class jack_client {
+protected:
+    std::vector<jack_host_base *> plugins;
+    ptmutex mutex;
 public:
     jack_client_t *client;
     int input_nr, output_nr, midi_nr;
     std::string input_name, output_name, midi_name;
-    std::vector<jack_host_base *> plugins;
     int sample_rate;
 
     jack_client()
@@ -49,9 +53,16 @@ public:
     
     void add(jack_host_base *plugin)
     {
+        ptlock lock(mutex);
         plugins.push_back(plugin);
     }
     
+    void del(int item)
+    {
+        ptlock lock(mutex);
+        plugins.erase(plugins.begin()+item);
+    }
+    
     void open(const char *client_name)
     {
         jack_status_t status;
@@ -78,6 +89,8 @@ public:
         jack_deactivate(client);        
     }
     
+    void delete_plugins();
+    
     void connect(const std::string &p1, const std::string &p2)
     {
         if (jack_connect(client, p1.c_str(), p2.c_str()) != 0)
@@ -174,16 +187,20 @@ public:
     void close() {
         port *inputs = get_inputs(), *outputs = get_outputs();
         int input_count = get_input_count(), output_count = get_output_count();
-        for (int i = 0; i < input_count; i++)
+        for (int i = 0; i < input_count; i++) {
+            jack_port_unregister(client->client, inputs[i].handle);
             inputs[i].data = NULL;
-        for (int i = 0; i < output_count; i++)
+        }
+        for (int i = 0; i < output_count; i++) {
+            jack_port_unregister(client->client, outputs[i].handle);
             outputs[i].data = NULL;
+        }
+        if (get_midi())
+            jack_port_unregister(client->client, midi_port.handle);
         client = NULL;
     }
 
     virtual ~jack_host_base() {
-        if (client)
-            close();
     }
 };
 
@@ -194,6 +211,7 @@ struct vumeter
     vumeter()
     {
         falloff = 0.999f;
+        level = 0;
     }
     
     inline void update(float *src, unsigned int len)
@@ -229,6 +247,12 @@ public:
         midi_meter = 0;
     }
     
+    ~jack_host()
+    {
+        if (client)
+            close();
+    }
+    
     virtual void init_module() {
         module.set_sample_rate(client->sample_rate);
         module.activate();
diff --git a/src/calf/main_win.h b/src/calf/main_win.h
index a6303fa..2093399 100644
--- a/src/calf/main_win.h
+++ b/src/calf/main_win.h
@@ -40,13 +40,23 @@ namespace synth {
             main_window *main_win;
             plugin_ctl_iface *plugin;
             plugin_gui_window *gui_win;
-            GtkWidget *name, *midi_in, *audio_in[2], *audio_out[2];
+            GtkWidget *name, *midi_in, *audio_in[2], *audio_out[2], *extra;
+        };
+        
+        struct add_plugin_params
+        {
+            main_window *main_win;
+            std::string name;
+            add_plugin_params(main_window *_main_win, const std::string &_name)
+            : main_win(_main_win), name(_name) {}
         };
         
     public:
         GtkWindow *toplevel;
         GtkWidget *all_vbox;
         GtkWidget *strips_table;
+        GtkUIManager *ui_mgr;
+        GtkActionGroup *std_actions, *plugin_actions;
         jack_client *client;
         std::map<plugin_ctl_iface *, plugin_strip *> plugins;
         std::set<std::string> conditions;
@@ -54,14 +64,19 @@ namespace synth {
         std::string prefix;
         bool is_closed;
         int source_id;
+        main_window_owner_iface *owner;
 
     protected:
         plugin_strip *create_strip(plugin_ctl_iface *plugin);
         void update_strip(plugin_ctl_iface *plugin);
         static gboolean on_idle(void *data);
+        std::string make_plugin_list(GtkActionGroup *actions);
+        static void add_plugin_action(GtkWidget *src, gpointer data);
 
     public:
         main_window();
+        void set_owner(main_window_owner_iface *_owner) { owner = _owner; }
+        void new_plugin(const char *name) { owner->new_plugin(name); }
         void add_plugin(plugin_ctl_iface *plugin);
         void del_plugin(plugin_ctl_iface *plugin);
         void set_window(plugin_ctl_iface *iface, plugin_gui_window *window);
diff --git a/src/calf/primitives.h b/src/calf/primitives.h
index 1aaad76..096f432 100644
--- a/src/calf/primitives.h
+++ b/src/calf/primitives.h
@@ -405,8 +405,6 @@ inline int fastf2i_drm(float f)
 	return v;
 }
 
-
-
 };
 
 #endif
diff --git a/src/calf/utils.h b/src/calf/utils.h
new file mode 100644
index 0000000..3f52e82
--- /dev/null
+++ b/src/calf/utils.h
@@ -0,0 +1,87 @@
+/* Calf DSP Library
+ * Utilities
+ *
+ * Copyright (C) 2008 Krzysztof Foltman
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This program 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+#ifndef __CALF_UTILS_H
+#define __CALF_UTILS_H
+
+#include <pthread.h>
+
+class ptmutex
+{
+public:
+    pthread_mutex_t pm;
+    
+    ptmutex(int type = PTHREAD_MUTEX_RECURSIVE)
+    {
+        pthread_mutexattr_t attr;
+        pthread_mutexattr_init(&attr);
+        pthread_mutexattr_settype(&attr, type);
+        pthread_mutex_init(&pm, &attr);
+        pthread_mutexattr_destroy(&attr);
+    }
+    
+    bool lock()
+    {
+        return pthread_mutex_lock(&pm) == 0;
+    }
+    
+    bool trylock()
+    {
+        return pthread_mutex_trylock(&pm) == 0;
+    }
+    
+    void unlock()
+    {
+        pthread_mutex_unlock(&pm);
+    }
+
+    ~ptmutex()
+    {
+        pthread_mutex_destroy(&pm);
+    }
+};
+
+class ptlock
+{
+    ptmutex &mutex;
+    bool locked;
+    
+public:
+    ptlock(ptmutex &_m) : mutex(_m), locked(true)
+    {
+        mutex.lock();
+    }
+    void unlock()
+    {
+        mutex.unlock();
+        locked = false;
+    }
+    void unlocked()
+    {
+        locked = false;
+    }
+    ~ptlock()
+    {
+        if (locked)
+            mutex.unlock();
+    }
+};
+
+#endif
diff --git a/src/jackhost.cpp b/src/jackhost.cpp
index 69d0d8a..3f55977 100644
--- a/src/jackhost.cpp
+++ b/src/jackhost.cpp
@@ -46,20 +46,20 @@ const char *client_name = "calfhost";
 
 jack_host_base *synth::create_jack_host(const char *effect_name)
 {
-    if (!strcmp(effect_name, "reverb"))
+    if (!strcasecmp(effect_name, "reverb"))
         return new jack_host<reverb_audio_module>();
-    else if (!strcmp(effect_name, "flanger"))
+    else if (!strcasecmp(effect_name, "flanger"))
         return new jack_host<flanger_audio_module>();
-    else if (!strcmp(effect_name, "filter"))
+    else if (!strcasecmp(effect_name, "filter"))
         return new jack_host<filter_audio_module>();
-    else if (!strcmp(effect_name, "monosynth"))
+    else if (!strcasecmp(effect_name, "monosynth"))
         return new jack_host<monosynth_audio_module>();
-    else if (!strcmp(effect_name, "vintagedelay"))
+    else if (!strcasecmp(effect_name, "vintagedelay"))
         return new jack_host<vintage_delay_audio_module>();
 #ifdef ENABLE_EXPERIMENTAL
-    else if (!strcmp(effect_name, "organ"))
+    else if (!strcasecmp(effect_name, "organ"))
         return new jack_host<organ_audio_module>();
-    else if (!strcmp(effect_name, "rotaryspeaker"))
+    else if (!strcasecmp(effect_name, "rotaryspeaker"))
         return new jack_host<rotary_speaker_audio_module>();
 #endif
     else
@@ -98,6 +98,7 @@ void print_help(char *argv[])
 int jack_client::do_jack_process(jack_nframes_t nframes, void *p)
 {
     jack_client *self = (jack_client *)p;
+    ptlock lock(self->mutex);
     for(unsigned int i = 0; i < self->plugins.size(); i++)
         self->plugins[i]->process(nframes);
     return 0;
@@ -106,12 +107,23 @@ int jack_client::do_jack_process(jack_nframes_t nframes, void *p)
 int jack_client::do_jack_bufsize(jack_nframes_t numsamples, void *p)
 {
     jack_client *self = (jack_client *)p;
+    ptlock lock(self->mutex);
     for(unsigned int i = 0; i < self->plugins.size(); i++)
         self->plugins[i]->cache_ports();
     return 0;
 }
 
-struct host_session
+void jack_client::delete_plugins()
+{
+    ptlock lock(mutex);
+    for (unsigned int i = 0; i < plugins.size(); i++) {
+        // plugins[i]->close();
+        delete plugins[i];
+    }
+    plugins.clear();
+}
+
+struct host_session: public main_window_owner_iface
 {
     string client_name, input_name, output_name, midi_name;
     vector<string> plugin_names;
@@ -149,6 +161,8 @@ struct host_session
         lash_send_config(lash_client, cfg);
     }
 #endif
+    virtual void new_plugin(const char *name);    
+    virtual void remove_plugin(plugin_ctl_iface *plugin);
 };
 
 host_session::host_session()
@@ -159,6 +173,7 @@ host_session::host_session()
     lash_source_id = 0;
     restoring_session = false;
     main_win = new main_window;
+    main_win->set_owner(this);
 }
 
 void host_session::open()
@@ -182,6 +197,7 @@ void host_session::open()
 #endif
         }
         jh->open(&client);
+        
         plugins.push_back(jh);
         client.add(jh);
         main_win->add_plugin(jh);
@@ -192,9 +208,36 @@ void host_session::open()
     gtk_signal_connect(GTK_OBJECT(main_win->toplevel), "destroy", G_CALLBACK(destroy), NULL);
 }
 
+void host_session::new_plugin(const char *name)
+{
+    jack_host_base *jh = create_jack_host(name);
+    if (!jh)
+        return;
+    jh->open(&client);
+    
+    plugins.push_back(jh);
+    client.add(jh);
+    main_win->add_plugin(jh);
+}
+
+void host_session::remove_plugin(plugin_ctl_iface *plugin)
+{
+    for (unsigned int i = 0; i < plugins.size(); i++)
+    {
+        if (plugins[i] == plugin)
+        {
+            client.del(i);
+            plugins.erase(plugins.begin() + i);
+            main_win->del_plugin(plugin);
+            delete plugin;
+            return;
+        }
+    }
+}
+
 void host_session::activate_preset(int i, const std::string &preset)
 {
-    string cur_plugin = plugin_names[i];
+    string cur_plugin = plugins[i]->get_id();
     preset_vector &pvec = global_presets.presets;
     bool found = false;
     for (unsigned int i = 0; i < pvec.size(); i++) {
@@ -275,14 +318,11 @@ void host_session::close()
 {
     if (lash_source_id)
         g_source_remove(lash_source_id);
-    client.deactivate();
-    client.close();
     main_win->on_closed();
     main_win->close_guis();
-    for (unsigned int i = 0; i < plugin_names.size(); i++) {
-        plugins[i]->close();
-        delete plugins[i];
-    }
+    client.delete_plugins();
+    client.deactivate();
+    client.close();
 }
 
 #if USE_LASH
@@ -301,7 +341,7 @@ void host_session::update_lash()
                 for (unsigned int i = 0; i < plugins.size(); i++) {
                     char ss[32];
                     plugin_preset preset;
-                    preset.plugin = plugin_names[i];
+                    preset.plugin = plugins[i]->get_id();
                     preset.get_from(plugins[i]);
                     sprintf(ss, "plugin%d", i);
                     string pstr = preset.to_xml();
@@ -426,10 +466,12 @@ int main(int argc, char *argv[])
             sess.plugin_names.push_back(argv[optind++]);
         }
     }
+    /*
     if (!sess.plugin_names.size()) {
         print_help(argv);
         return 0;
     }
+    */
     try {
         global_presets.load_defaults();
     }
diff --git a/src/main_win.cpp b/src/main_win.cpp
index 70a6cf1..49f1891 100644
--- a/src/main_win.cpp
+++ b/src/main_win.cpp
@@ -29,9 +29,34 @@
 using namespace synth;
 using namespace std;
 
+static const char *ui_xml = 
+"<ui>\n"
+"  <menubar>\n"
+"    <menu action=\"HostMenuAction\">\n"
+"      <menu action=\"AddPluginMenuAction\">\n"
+"      </menu>\n"
+"      <separator/>\n"
+"      <menuitem action=\"exit\"/>\n"
+"    </menu>\n"
+"  </menubar>\n"
+"</ui>\n"
+;
+
+static void exit_action(main_window *main)
+{
+    gtk_widget_destroy(GTK_WIDGET(main->toplevel));
+}
+
+static const GtkActionEntry actions[] = {
+    { "HostMenuAction", "", "_Host", NULL, "Host-related operations", NULL },
+    { "AddPluginMenuAction", "", "_Add plugin", NULL, "Add a plugin to the rack", NULL },
+    { "exit", "", "_Exit", NULL, "Exit application", (GCallback)exit_action },
+};
+
 main_window::main_window()
 {
     toplevel = NULL;
+    owner = NULL;
     is_closed = true;
 }
 
@@ -39,7 +64,9 @@ void main_window::add_plugin(plugin_ctl_iface *plugin)
 {
     if (toplevel)
     {
-        plugins[plugin] = create_strip(plugin);
+        plugin_strip *strip = create_strip(plugin);
+        plugins[plugin] = strip;
+        update_strip(plugin);
     }
     else {
         plugin_queue.push_back(plugin);
@@ -49,7 +76,51 @@ void main_window::add_plugin(plugin_ctl_iface *plugin)
 
 void main_window::del_plugin(plugin_ctl_iface *plugin)
 {
+    if (!plugins.count(plugin))
+        return;
+    plugin_strip *strip = plugins[plugin];
+    if (strip->gui_win)
+        strip->gui_win->close();
+
+    int row = -1;
+    for(GList *p = GTK_TABLE(strips_table)->children; p != NULL; p = p->next)
+    {
+        GtkTableChild *c = (GtkTableChild *)p->data;
+        if (c->widget == strip->name)
+        {
+            row = c->top_attach - 1;
+            break;
+        }
+    }
+    g_assert(row != -1);
+    
+    vector<GtkWidget *> to_destroy;
+    for(GList *p = GTK_TABLE(strips_table)->children; p != NULL; p = p->next)
+    {
+        GtkTableChild *c = (GtkTableChild *)p->data;
+        if (c->top_attach >= row && c->top_attach < row + 3)
+            to_destroy.push_back(c->widget);
+        if (c->top_attach >= row + 3)
+        {
+            c->top_attach -= 3;
+            c->bottom_attach -= 3;
+        }
+    }
+    
+    for (unsigned int i = 0; i < to_destroy.size(); i++)
+        gtk_container_remove(GTK_CONTAINER(strips_table), to_destroy[i]);
+    //for (unsigned int i = 0; i < to_destroy.size(); i++)
+    //    gtk_widget_destroy(to_destroy[i]);
+    
     plugins.erase(plugin);
+    for(GList *p = GTK_TABLE(strips_table)->children; p != NULL; p = p->next)
+    {
+        GtkTableChild *c = (GtkTableChild *)p->data;
+        if (c->top_attach == 0) {
+            c->ypadding = 0;
+            gtk_widget_set_size_request(c->widget, -1, -1);
+        }
+    }
 }
 
 void main_window::set_window(plugin_ctl_iface *plugin, plugin_gui_window *gui_win)
@@ -88,6 +159,14 @@ gui_button_pressed(GtkWidget *button, main_window::plugin_strip *strip)
     return TRUE;
 }
 
+static gboolean
+extra_button_pressed(GtkWidget *button, main_window::plugin_strip *strip)
+{
+    GtkButton *tb = GTK_BUTTON(button);
+    strip->main_win->owner->remove_plugin(strip->plugin);
+    return TRUE;
+}
+
 main_window::plugin_strip *main_window::create_strip(plugin_ctl_iface *plugin)
 {
     plugin_strip *strip = new plugin_strip;
@@ -99,7 +178,9 @@ main_window::plugin_strip *main_window::create_strip(plugin_ctl_iface *plugin)
     g_object_get(G_OBJECT(strips_table), "n-rows", &row, "n-columns", &cols, NULL);
     gtk_table_resize(GTK_TABLE(strips_table), row + 3, cols);
 
-    gtk_table_attach_defaults(GTK_TABLE(strips_table), gtk_hseparator_new(), 0, 4, row, row + 1);
+    GtkWidget *sep = gtk_hseparator_new();
+    gtk_table_attach_defaults(GTK_TABLE(strips_table), sep, 0, 4, row, row + 1);
+    gtk_widget_show(sep);
     row++;
     
     GtkWidget *label = gtk_toggle_button_new_with_label(plugin->get_name());
@@ -107,10 +188,12 @@ main_window::plugin_strip *main_window::create_strip(plugin_ctl_iface *plugin)
     strip->name = label;
     gtk_signal_connect(GTK_OBJECT(label), "toggled", G_CALLBACK(gui_button_pressed), 
         (plugin_ctl_iface *)strip);
+    gtk_widget_show(strip->name);
     
     label = gtk_label_new(plugin->get_midi() ? "MIDI" : "");
     gtk_table_attach_defaults(GTK_TABLE(strips_table), label, 1, 2, row, row + 2);
     strip->midi_in = label;
+    gtk_widget_show(strip->midi_in);
 
     for (int i = 0; i < 2; i++)
         strip->audio_in[i] = strip->audio_out[i] = NULL;
@@ -122,6 +205,8 @@ main_window::plugin_strip *main_window::create_strip(plugin_ctl_iface *plugin)
         label = calf_vumeter_new();
         gtk_table_attach_defaults(GTK_TABLE(strips_table), label, 2, 3, row + 1, row + 2);
         strip->audio_in[1] = label;
+        gtk_widget_show(strip->audio_in[0]);
+        gtk_widget_show(strip->audio_in[1]);
     }
 
     if (plugin->get_output_count() == 2) {
@@ -131,7 +216,16 @@ main_window::plugin_strip *main_window::create_strip(plugin_ctl_iface *plugin)
         label = calf_vumeter_new();
         gtk_table_attach_defaults(GTK_TABLE(strips_table), label, 3, 4, row + 1, row + 2);
         strip->audio_out[1] = label;
+        gtk_widget_show(strip->audio_out[0]);
+        gtk_widget_show(strip->audio_out[1]);
     }
+    GtkWidget *extra = gtk_button_new_with_label("X");
+    gtk_table_attach_defaults(GTK_TABLE(strips_table), extra, 4, 5, row, row + 2);
+    strip->extra = extra;
+    gtk_signal_connect(GTK_OBJECT(extra), "clicked", G_CALLBACK(extra_button_pressed), 
+        (plugin_ctl_iface *)strip);
+    gtk_widget_show(strip->extra);
+    
     return strip;
 }
 
@@ -150,13 +244,74 @@ void main_window::open_gui(plugin_ctl_iface *plugin)
     plugins[plugin]->gui_win = gui_win; 
 }
 
+static const char *plugin_pre_xml = 
+"<ui>\n"
+"  <menubar>\n"
+"    <menu action=\"AddPluginMenuAction\">\n"
+"      <placeholder name=\"plugin\">\n";
+
+static const char *plugin_post_xml = 
+"      </placeholder>\n"
+"    </menu>\n"
+"  </menubar>\n"
+"</ui>\n"
+;
+
+void main_window::add_plugin_action(GtkWidget *src, gpointer data)
+{
+    add_plugin_params *app = (add_plugin_params *)data;
+    app->main_win->new_plugin(app->name.c_str());
+}
+
+static void action_destroy_notify(gpointer data)
+{
+    delete (main_window::add_plugin_params *)data;
+}
+
+/*
+void main_window::new_plugin(const char *plugin)
+{
+    printf("new plugin %s\n", plugin);
+}
+*/
+
+std::string main_window::make_plugin_list(GtkActionGroup *actions)
+{
+    string s = plugin_pre_xml;
+    std::vector<giface_plugin_info> plugins;
+    synth::get_all_plugins(plugins);
+    for(unsigned int i = 0; i < plugins.size(); i++)
+    {
+        string action_name = "Add" + string(plugins[i].info->label)+"Action";
+        s += string("<menuitem action=\"") + action_name + "\" />";
+        GtkActionEntry ae = { action_name.c_str(), NULL, plugins[i].info->name, NULL, NULL, (GCallback)add_plugin_action };
+        gtk_action_group_add_actions_full(actions, &ae, 1, (gpointer)new add_plugin_params(this, plugins[i].info->label), action_destroy_notify);
+    }
+    return s + plugin_post_xml;
+}
+
 void main_window::create()
 {
     toplevel = GTK_WINDOW(gtk_window_new (GTK_WINDOW_TOPLEVEL));
     is_closed = false;
     
     all_vbox = gtk_vbox_new(0, FALSE);
-    strips_table = gtk_table_new(1, 5, FALSE);
+
+    ui_mgr = gtk_ui_manager_new();
+    std_actions = gtk_action_group_new("default");
+    gtk_action_group_add_actions(std_actions, actions, sizeof(actions)/sizeof(actions[0]), this);
+    GError *error = NULL;
+    gtk_ui_manager_insert_action_group(ui_mgr, std_actions, 0);
+    gtk_ui_manager_add_ui_from_string(ui_mgr, ui_xml, -1, &error);    
+    gtk_box_pack_start(GTK_BOX(all_vbox), gtk_ui_manager_get_widget(ui_mgr, "/ui/menubar"), false, false, 0);
+
+    plugin_actions = gtk_action_group_new("plugins");
+    string plugin_xml = make_plugin_list(plugin_actions);
+    gtk_ui_manager_insert_action_group(ui_mgr, plugin_actions, 0);    
+    gtk_ui_manager_add_ui_from_string(ui_mgr, plugin_xml.c_str(), -1, &error);
+
+    
+    strips_table = gtk_table_new(1, 6, FALSE);
     gtk_table_set_col_spacings(GTK_TABLE(strips_table), 10);
     gtk_table_set_row_spacings(GTK_TABLE(strips_table), 5);
     

-- 
calf audio plugins packaging



More information about the pkg-multimedia-commits mailing list