[SCM] calf/master: Clean up the JACK host.

js at users.alioth.debian.org js at users.alioth.debian.org
Tue May 7 15:40:02 UTC 2013


The following commit has been merged in the master branch:
commit d08458e235440780e56916e14eb3555945a8254e
Author: Krzysztof Foltman <wdev at foltman.com>
Date:   Tue Apr 6 22:24:13 2010 +0100

    Clean up the JACK host.
    
    Remove excessive inlines from the header. Move parts of the definitions and
    code into separate files. Remove dead code.

diff --git a/src/Makefile.am b/src/Makefile.am
index 7942667..9efba46 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -29,7 +29,7 @@ if USE_JACK
 AM_CXXFLAGS += $(JACK_DEPS_CFLAGS)
 noinst_LTLIBRARIES += libcalfgui.la
 bin_PROGRAMS += calfjackhost 
-calfjackhost_SOURCES = jackhost.cpp
+calfjackhost_SOURCES = host_session.cpp jack_client.cpp jackhost.cpp
 calfjackhost_LDADD = libcalfgui.la libcalfstatic.la $(JACK_DEPS_LIBS) $(GUI_DEPS_LIBS) $(FLUIDSYNTH_DEPS_LIBS)
 if USE_LASH
 AM_CXXFLAGS += $(LASH_DEPS_CFLAGS)
diff --git a/src/calf/Makefile.am b/src/calf/Makefile.am
index b667f6e..b233562 100644
--- a/src/calf/Makefile.am
+++ b/src/calf/Makefile.am
@@ -1,6 +1,7 @@
 noinst_HEADERS = audio_fx.h benchmark.h biquad.h buffer.h custom_ctl.h \
     ctl_curve.h ctl_keyboard.h ctl_led.h \
-    delay.h envelope.h fft.h fixed_point.h giface.h gui.h gui_controls.h inertia.h jackhost.h ladspa_wrap.h loudness.h \
+    delay.h envelope.h fft.h fixed_point.h giface.h gui.h gui_controls.h inertia.h jackhost.h \
+    host_session.h ladspa_wrap.h loudness.h \
     lv2_contexts.h lv2_data_access.h lv2_event.h lv2_external_ui.h \
     lv2_progress.h lv2_polymorphic_port.h lv2_string_port.h lv2_ui.h \
     lv2_uri_map.h lv2-midiport.h lv2helpers.h lv2wrap.h \
diff --git a/src/calf/giface.h b/src/calf/giface.h
index 0f08327..c07f6df 100644
--- a/src/calf/giface.h
+++ b/src/calf/giface.h
@@ -18,8 +18,8 @@
  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 
  * Boston, MA 02111-1307, USA.
  */
-#ifndef __CALF_GIFACE_H
-#define __CALF_GIFACE_H
+#ifndef CALF_GIFACE_H
+#define CALF_GIFACE_H
 
 #include <stdint.h>
 #include <stdlib.h>
diff --git a/src/calf/host_session.h b/src/calf/host_session.h
new file mode 100644
index 0000000..90733ac
--- /dev/null
+++ b/src/calf/host_session.h
@@ -0,0 +1,91 @@
+/* Calf DSP Library Utility Application - calfjackhost
+ * Class for managing calfjackhost's 
+ *
+ * Copyright (C) 2007 Krzysztof Foltman
+ *
+ * This program 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, 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 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 Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+#ifndef CALF_HOST_SESSION_H
+#define CALF_HOST_SESSION_H
+
+#include <calf/jackhost.h>
+
+namespace calf_plugins {
+
+class main_window;
+
+struct host_session: public main_window_owner_iface, public calf_plugins::progress_report_iface
+{
+    std::string client_name, input_name, output_name, midi_name;
+    std::vector<std::string> plugin_names;
+    std::map<int, std::string> presets;
+#if USE_LASH
+    int lash_source_id;
+    lash_client_t *lash_client;
+# if !USE_LASH_0_6
+    lash_args_t *lash_args;
+# endif
+#endif
+    
+    // these are not saved
+    jack_client client;
+    std::string autoconnect_midi;
+    int autoconnect_midi_index;
+    std::set<int> chains;
+    std::vector<jack_host *> plugins;
+    main_window *main_win;
+    bool restoring_session;
+    std::set<std::string> instances;
+    GtkWidget *progress_window;
+    plugin_gui_window *gui_win;
+    
+    host_session();
+    void open();
+    void add_plugin(std::string name, std::string preset, std::string instance_name = std::string());
+    void create_plugins_from_list();
+    void connect();
+    void close();
+    bool activate_preset(int plugin, const std::string &preset, bool builtin);
+#if USE_LASH
+    static gboolean update_lash(void *self) { ((host_session *)self)->update_lash(); return TRUE; }
+    void update_lash();
+# if !USE_LASH_0_6
+    void send_lash(LASH_Event_Type type, const std::string &data) {
+        lash_send_event(lash_client, lash_event_new_with_all(type, data.c_str()));
+    }
+# endif
+#endif
+    virtual void new_plugin(const char *name);    
+    virtual void remove_plugin(plugin_ctl_iface *plugin);
+    void remove_all_plugins();
+    std::string get_next_instance_name(const std::string &effect_name);
+    
+    /// Create a toplevel window with progress bar
+    GtkWidget *create_progress_window();
+    /// Implementation of progress_report_iface function
+    void report_progress(float percentage, const std::string &message);
+    
+    /// Implementation of open file functionality (TODO)
+    virtual char *open_file(const char *name);
+    /// Implementation of save file functionality
+    virtual char *save_file(const char *name);
+    /// Implementation of connection to LASH (or, in future, other session manager)
+    void connect_to_session_manager(int argc, char *argv[]);
+};
+
+};
+
+#endif
diff --git a/src/calf/jackhost.h b/src/calf/jackhost.h
index a1506d6..30133a9 100644
--- a/src/calf/jackhost.h
+++ b/src/calf/jackhost.h
@@ -25,6 +25,9 @@
 
 #include <jack/jack.h>
 #include <jack/midiport.h>
+#if USE_LASH
+#include <lash/lash.h>
+#endif
 #include "gui.h"
 #include "utils.h"
 #include "vumeter.h"
@@ -44,72 +47,17 @@ public:
     std::string name, input_name, output_name, midi_name;
     int sample_rate;
 
-    jack_client()
-    {
-        input_nr = output_nr = midi_nr = 1;
-        input_name = "input_%d";
-        output_name = "output_%d";
-        midi_name = "midi_%d";
-        sample_rate = 0;
-        client = NULL;
-    }
-    
-    void add(jack_host *plugin)
-    {
-        calf_utils::ptlock lock(mutex);
-        plugins.push_back(plugin);
-    }
-    
-    void del(int item)
-    {
-        calf_utils::ptlock lock(mutex);
-        plugins.erase(plugins.begin()+item);
-    }
-    
-    void open(const char *client_name)
-    {
-        jack_status_t status;
-        client = jack_client_open(client_name, JackNullOption, &status);
-        if (!client)
-            throw calf_utils::text_exception("Could not initialize JACK subsystem");
-        sample_rate = jack_get_sample_rate(client);
-        jack_set_process_callback(client, do_jack_process, this);
-        jack_set_buffer_size_callback(client, do_jack_bufsize, this);
-        name = get_name();
-    }
-    
-    std::string get_name()
-    {
-        return std::string(jack_get_client_name(client));
-    }
-    
-    void activate()
-    {
-        jack_activate(client);        
-    }
-
-    void deactivate()
-    {
-        jack_deactivate(client);        
-    }
-    
+    jack_client();
+    void add(jack_host *plugin);
+    void del(int item);
+    void open(const char *client_name);
+    std::string get_name();
+    void activate();
+    void deactivate();
     void delete_plugins();
-    
-    void connect(const std::string &p1, const std::string &p2)
-    {
-        if (jack_connect(client, p1.c_str(), p2.c_str()) != 0)
-            throw calf_utils::text_exception("Could not connect JACK ports "+p1+" and "+p2);
-    }
-    
-    void close()
-    {
-        jack_client_close(client);
-    }
-    
-    const char **get_ports(const char *name_re, const char *type_re, unsigned long flags)
-    {
-        return jack_get_ports(client, name_re, type_re, flags);
-    }
+    void connect(const std::string &p1, const std::string &p2);
+    void close();
+    const char **get_ports(const char *name_re, const char *type_re, unsigned long flags);
     
     static int do_jack_process(jack_nframes_t nframes, void *p);
     static int do_jack_bufsize(jack_nframes_t numsamples, void *p);
@@ -121,13 +69,13 @@ public:
         jack_port_t *handle;
         float *data;
         std::string name;
+        vumeter meter;
         port() : handle(NULL), data(NULL) {}
         ~port() { }
     };
 public:
     float **ins, **outs, **params;
     std::vector<port> inputs, outputs;
-    std::vector<vumeter> input_vus, output_vus;
     float *param_values;
     float midi_meter;
     audio_module_iface *module;
@@ -141,179 +89,35 @@ public:
     std::string instance_name;
     int in_count, out_count;
     const plugin_metadata_iface *metadata;
-    port *get_midi_port() { return get_metadata_iface()->get_midi() ? &midi_port : NULL; }
     
-    void set_params(const float *params) {
-        memcpy(get_params(), params, get_metadata_iface()->get_param_count() * sizeof(float));
-        changed = true;
-    }
-
-    void set_params() {
-        changed = true;
-    }
-    
-    void open(jack_client *_client);
-    
-    virtual void create_ports();
-    
-    void close();
-    
-    jack_host(audio_module_iface *_module, const std::string &_name, const std::string &_instance_name, calf_plugins::progress_report_iface *_priface)
-    : module(_module)
-    {
-        name = _name;
-        instance_name = _instance_name;
-        
-        client = NULL;
-        changed = true;
-
-        module->get_port_arrays(ins, outs, params);
-        metadata = module->get_metadata_iface();
-        in_count = metadata->get_input_count();
-        out_count = metadata->get_output_count();
-        inputs.resize(in_count);
-        outputs.resize(out_count);
-        input_vus.resize(in_count);
-        output_vus.resize(out_count);
-        param_values = new float[metadata->get_param_count()];
-        for (int i = 0; i < metadata->get_param_count(); i++) {
-            params[i] = &param_values[i];
-        }
-        clear_preset();
-        midi_meter = 0;
-        module->set_progress_report_iface(_priface);
-        module->post_instantiate();
-    }
-    
-    ~jack_host()
-    {
-        delete []param_values;
-        if (client)
-            close();
-    }
-    
-    virtual void init_module() {
-        module->set_sample_rate(client->sample_rate);
-        module->activate();
-        module->params_changed();
-    }
-
-    virtual const parameter_properties* get_param_props(int param_no) { return metadata->get_param_props(param_no); }
-    
-    void handle_event(uint8_t *buffer, uint32_t size)
-    {
-        int value;
-        switch(buffer[0] >> 4)
-        {
-        case 8:
-            module->note_off(buffer[1], buffer[2]);
-            break;
-        case 9:
-            if (!buffer[2])
-                module->note_off(buffer[1], 0);
-            else
-                module->note_on(buffer[1], buffer[2]);
-            break;
-        case 11:
-            module->control_change(buffer[1], buffer[2]);
-            break;
-        case 12:
-            module->program_change(buffer[1]);
-            break;
-        case 13:
-            module->channel_pressure(buffer[1]);
-            break;
-        case 14:
-            value = buffer[1] + 128 * buffer[2] - 8192;
-            module->pitch_bend(value);
-            break;
-        }
-    }
-    void process_part(unsigned int time, unsigned int len)
-    {
-        if (!len)
-            return;
-        for (int i = 0; i < in_count; i++)
-            input_vus[i].update(ins[i] + time, len);
-        unsigned int mask = module->process(time, len, -1, -1);
-        for (int i = 0; i < out_count; i++)
-        {
-            if (!(mask & (1 << i))) {
-                dsp::zero(outs[i] + time, len);
-                output_vus[i].update_zeros(len);
-            } else
-                output_vus[i].update(outs[i] + time, len);
-        }
-        // decay linearly for 0.1s
-        float new_meter = midi_meter - len / (0.1 * client->sample_rate);
-        if (new_meter < 0)
-            new_meter = 0;
-        midi_meter = new_meter;
-    }
-    virtual float get_level(unsigned int port) { 
-        if (port < (unsigned)in_count)
-            return input_vus[port].level;
-        port -= in_count;
-        if (port < (unsigned)out_count)
-            return output_vus[port].level;
-        port -= out_count;
-        if (port == 0 && metadata->get_midi())
-            return midi_meter;
-        return 0.f;
-    }
-    int process(jack_nframes_t nframes)
-    {
-        for (int i=0; i<in_count; i++) {
-            ins[i] = inputs[i].data = (float *)jack_port_get_buffer(inputs[i].handle, nframes);
-        }
-        if (metadata->get_midi())
-            midi_port.data = (float *)jack_port_get_buffer(midi_port.handle, nframes);
-        if (changed) {
-            module->params_changed();
-            changed = false;
-        }
-
-        unsigned int time = 0;
-        if (metadata->get_midi())
-        {
-            jack_midi_event_t event;
-#ifdef OLD_JACK
-            int count = jack_midi_get_event_count(midi_port.data, nframes);
-#else
-            int count = jack_midi_get_event_count(midi_port.data);
-#endif
-            for (int i = 0; i < count; i++)
-            {
-#ifdef OLD_JACK
-                jack_midi_event_get(&event, midi_port.data, i, nframes);
-#else
-                jack_midi_event_get(&event, midi_port.data, i);
-#endif
-                unsigned int len = event.time - time;
-                process_part(time, len);
-                
-                midi_meter = 1.f;
-                handle_event(event.buffer, event.size);
-                
-                time = event.time;
-            }
-        }
-        process_part(time, nframes - time);
-        module->params_reset();
-        return 0;
-    }
-    
-    void cache_ports()
-    {
-        for (int i=0; i<out_count; i++) {
-            outs[i] = outputs[i].data = (float *)jack_port_get_buffer(outputs[i].handle, 0);
-        }
-    }
+public:
+    jack_host(audio_module_iface *_module, const std::string &_name, const std::string &_instance_name, calf_plugins::progress_report_iface *_priface);
+    void create(jack_client *_client);    
+    void create_ports();
+    void init_module();
+    void destroy();
+    ~jack_host();
+    
+    /// Handle JACK MIDI port data
+    void handle_event(uint8_t *buffer, uint32_t size);
+    /// Process audio and update meters
+    void process_part(unsigned int time, unsigned int len);
+    /// Get meter value for the Nth port
+    virtual float get_level(unsigned int port);
+    /// Process audio/MIDI buffers
+    int process(jack_nframes_t nframes);
+    /// Retrieve and cache output port buffers
+    void cache_ports();
     
-    virtual port *get_inputs() { return &inputs[0]; }
-    virtual port *get_outputs() { return &outputs[0]; }
-    virtual float *get_params() { return param_values; }
-    virtual bool activate_preset(int bank, int program) { return false; }
+public:
+    // Port access
+    port *get_inputs() { return &inputs[0]; }
+    port *get_outputs() { return &outputs[0]; }
+    float *get_params() { return param_values; }
+    port *get_midi_port() { return get_metadata_iface()->get_midi() ? &midi_port : NULL; }
+public:
+    // Implementations of methods in plugin_ctl_iface 
+    bool activate_preset(int bank, int program) { return false; }
     virtual float get_param_value(int param_no) {
         return param_values[param_no];
     }
diff --git a/src/jackhost.cpp b/src/host_session.cpp
similarity index 67%
copy from src/jackhost.cpp
copy to src/host_session.cpp
index 2ed27ae..6e1cbb3 100644
--- a/src/jackhost.cpp
+++ b/src/host_session.cpp
@@ -1,7 +1,7 @@
 /* Calf DSP Library Utility Application - calfjackhost
- * Standalone application module wrapper example.
+ * A class that contains a JACK host session
  *
- * Copyright (C) 2007 Krzysztof Foltman
+ * Copyright (C) 2007-2010 Krzysztof Foltman
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -18,6 +18,7 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  * 02110-1301, USA.
  */
+
 #include <set>
 #include <getopt.h>
 #include <stdint.h>
@@ -25,11 +26,8 @@
 #include <config.h>
 #include <glade/glade.h>
 #include <jack/jack.h>
-#if USE_LASH
-#include <lash/lash.h>
-#endif
 #include <calf/giface.h>
-#include <calf/jackhost.h>
+#include <calf/host_session.h>
 #include <calf/modules.h>
 #include <calf/modules_dev.h>
 #include <calf/organ.h>
@@ -39,206 +37,12 @@
 #include <calf/main_win.h>
 #include <calf/utils.h>
 #include <stdio.h>
+
 using namespace std;
 using namespace calf_utils;
 using namespace calf_plugins;
 
-// I don't need anyone to tell me this is stupid. I already know that :)
-plugin_gui_window *gui_win;
-
-const char *client_name = "calfhost";
-
-#if USE_LASH_0_6
-static bool save_data_set_cb(lash_config_handle_t *handle, void *user_data);
-static bool load_data_set_cb(lash_config_handle_t *handle, void *user_data);
-static bool quit_cb(void *user_data);
-#endif
-
-jack_host *calf_plugins::create_jack_host(const char *effect_name, const std::string &instance_name, calf_plugins::progress_report_iface *priface)
-{
-    #define PER_MODULE_ITEM(name, isSynth, jackname) if (!strcasecmp(effect_name, jackname)) return new jack_host(new name##_audio_module, effect_name, instance_name, priface);
-    #include <calf/modulelist.h>
-    return NULL;
-}
-
-void jack_host::open(jack_client *_client)
-{
-    client = _client; //jack_client_open(client_name, JackNullOption, &status);
-    
-    create_ports();
-    
-    cache_ports();
-    
-    init_module();
-    changed = false;
-}
-
-void jack_host::create_ports() {
-    char buf[32];
-    char buf2[64];
-    string prefix = client->name + ":";
-    static const char *suffixes[] = { "l", "r", "2l", "2r" };
-    port *inputs = get_inputs();
-    port *outputs = get_outputs();
-    int in_count = metadata->get_input_count(), out_count = metadata->get_output_count();
-    for (int i=0; i<in_count; i++) {
-        sprintf(buf, "%s_in_%s", instance_name.c_str(), suffixes[i]);
-        sprintf(buf2, client->input_name.c_str(), client->input_nr++);
-        inputs[i].name = buf2;
-        inputs[i].handle = jack_port_register(client->client, buf, JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput , 0);
-        inputs[i].data = NULL;
-        if (!inputs[i].handle)
-            throw text_exception("Could not create JACK input port");
-        jack_port_set_alias(inputs[i].handle, (prefix + buf2).c_str());
-    }
-    if (metadata->get_midi()) {
-        sprintf(buf, "%s_midi_in", instance_name.c_str());
-        sprintf(buf2, client->midi_name.c_str(), client->midi_nr++);
-        midi_port.name = buf2;
-        midi_port.handle = jack_port_register(client->client, buf, JACK_DEFAULT_MIDI_TYPE, JackPortIsInput, 0);
-        if (!midi_port.handle)
-            throw text_exception("Could not create JACK MIDI port");
-        jack_port_set_alias(midi_port.handle, (prefix + buf2).c_str());
-    }
-    for (int i=0; i<out_count; i++) {
-        sprintf(buf, "%s_out_%s", instance_name.c_str(), suffixes[i]);
-        sprintf(buf2, client->output_name.c_str(), client->output_nr++);
-        outputs[i].name = buf2;
-        outputs[i].handle = jack_port_register(client->client, buf, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput , 0);
-        outputs[i].data = NULL;
-        if (!outputs[i].handle)
-            throw text_exception("Could not create JACK output port");
-        jack_port_set_alias(outputs[i].handle, (prefix + buf2).c_str());
-    }
-}
-
-void jack_host::close() {
-    port *inputs = get_inputs(), *outputs = get_outputs();
-    int input_count = metadata->get_input_count(), output_count = metadata->get_output_count();
-    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++) {
-        jack_port_unregister(client->client, outputs[i].handle);
-        outputs[i].data = NULL;
-    }
-    if (metadata->get_midi())
-        jack_port_unregister(client->client, midi_port.handle);
-    client = NULL;
-}
-
-void destroy(GtkWindow *window, gpointer data)
-{
-    gtk_main_quit();
-}
-
-void gui_win_destroy(GtkWindow *window, gpointer data)
-{
-}
-
-static struct option long_options[] = {
-    {"help", 0, 0, 'h'},
-    {"version", 0, 0, 'v'},
-    {"client", 1, 0, 'c'},
-    {"effect", 0, 0, 'e'},
-    {"input", 1, 0, 'i'},
-    {"output", 1, 0, 'o'},
-    {"connect-midi", 1, 0, 'M'},
-    {0,0,0,0},
-};
-
-void print_help(char *argv[])
-{
-    printf("JACK host for Calf effects\n"
-        "Syntax: %s [--client <name>] [--input <name>] [--output <name>] [--midi <name>]\n"
-        "       [--connect-midi <name|capture-index>] [--help] [--version] [!] pluginname[:<preset>] [!] ...\n", 
-        argv[0]);
-}
-
-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;
-}
-
-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;
-}
-
-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, public calf_plugins::progress_report_iface
-{
-    string client_name, input_name, output_name, midi_name;
-    vector<string> plugin_names;
-    map<int, string> presets;
-#if USE_LASH
-    int lash_source_id;
-    lash_client_t *lash_client;
-# if !USE_LASH_0_6
-    lash_args_t *lash_args;
-# endif
-#endif
-    
-    // these are not saved
-    jack_client client;
-    string autoconnect_midi;
-    int autoconnect_midi_index;
-    set<int> chains;
-    vector<jack_host *> plugins;
-    main_window *main_win;
-    bool restoring_session;
-    std::set<std::string> instances;
-    GtkWidget *progress_window;
-    
-    host_session();
-    void open();
-    void add_plugin(string name, string preset, string instance_name = string());
-    void create_plugins_from_list();
-    void connect();
-    void close();
-    bool activate_preset(int plugin, const std::string &preset, bool builtin);
-#if USE_LASH
-    static gboolean update_lash(void *self) { ((host_session *)self)->update_lash(); return TRUE; }
-    void update_lash();
-# if !USE_LASH_0_6
-    void send_lash(LASH_Event_Type type, const std::string &data) {
-        lash_send_event(lash_client, lash_event_new_with_all(type, data.c_str()));
-    }
-# endif
-#endif
-    virtual void new_plugin(const char *name);    
-    virtual void remove_plugin(plugin_ctl_iface *plugin);
-    void remove_all_plugins();
-    std::string get_next_instance_name(const std::string &effect_name);
-    
-    /// Create a toplevel window with progress bar
-    GtkWidget *create_progress_window();
-    /// Implementation of progress_report_iface function
-    void report_progress(float percentage, const std::string &message);
-    
-    /// Implementation of open file functionality (TODO)
-    virtual char *open_file(const char *name);
-    /// Implementation of save file functionality
-    virtual char *save_file(const char *name);
-};
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 
 host_session::host_session()
 {
@@ -255,6 +59,7 @@ host_session::host_session()
     main_win->set_owner(this);
     progress_window = NULL;
     autoconnect_midi_index = -1;
+    gui_win = NULL;
 }
 
 std::string host_session::get_next_instance_name(const std::string &effect_name)
@@ -286,7 +91,7 @@ void host_session::add_plugin(string name, string preset, string instance_name)
         throw text_exception("Unknown plugin name; allowed are: " + s);
     }
     instances.insert(jh->instance_name);
-    jh->open(&client);
+    jh->create(&client);
     
     plugins.push_back(jh);
     client.add(jh);
@@ -349,6 +154,11 @@ GtkWidget *host_session::create_progress_window()
     return tlw;
 }
 
+static void window_destroy_cb(GtkWindow *window, gpointer data)
+{
+    gtk_main_quit();
+}
+
 void host_session::open()
 {
     if (!input_name.empty()) client.input_name = input_name;
@@ -362,7 +172,7 @@ void host_session::open()
     if (!restoring_session)
         create_plugins_from_list();
     main_win->create();
-    gtk_signal_connect(GTK_OBJECT(main_win->toplevel), "destroy", G_CALLBACK(destroy), NULL);
+    gtk_signal_connect(GTK_OBJECT(main_win->toplevel), "destroy", G_CALLBACK(window_destroy_cb), NULL);
 }
 
 void host_session::new_plugin(const char *name)
@@ -371,7 +181,7 @@ void host_session::new_plugin(const char *name)
     if (!jh)
         return;
     instances.insert(jh->instance_name);
-    jh->open(&client);
+    jh->create(&client);
     
     plugins.push_back(jh);
     client.add(jh);
@@ -711,7 +521,7 @@ void host_session::update_lash()
     lash_dispatch(lash_client);
 }
 
-bool save_data_set_cb(lash_config_handle_t *handle, void *user_data)
+static bool save_data_set_cb(lash_config_handle_t *handle, void *user_data)
 {
     host_session *sess = static_cast<host_session *>(user_data);
     dictionary tmp;
@@ -747,7 +557,7 @@ bool save_data_set_cb(lash_config_handle_t *handle, void *user_data)
     return true;
 }
 
-bool load_data_set_cb(lash_config_handle_t *handle, void *user_data)
+static bool load_data_set_cb(lash_config_handle_t *handle, void *user_data)
 {
     host_session *sess = static_cast<host_session *>(user_data);
     int size, type;
@@ -789,7 +599,7 @@ bool load_data_set_cb(lash_config_handle_t *handle, void *user_data)
     return true;
 }
 
-bool quit_cb(void *user_data)
+static bool quit_cb(void *user_data)
 {
     gtk_main_quit();
     return true;
@@ -798,116 +608,28 @@ bool quit_cb(void *user_data)
 # endif
 #endif
 
-host_session current_session;
-
-int main(int argc, char *argv[])
+void host_session::connect_to_session_manager(int argc, char *argv[])
 {
-    host_session &sess = current_session;
-    gtk_rc_add_default_file(PKGLIBDIR "calf.rc");
-    gtk_init(&argc, &argv);
-    
 #if USE_LASH
 # if !USE_LASH_0_6
     for (int i = 1; i < argc; i++)
     {
         if (!strncmp(argv[i], "--lash-project=", 14)) {
-            sess.restoring_session = true;
+            restoring_session = true;
             break;
         }
     }
-    sess.lash_args = lash_extract_args(&argc, &argv);
-    sess.lash_client = lash_init(sess.lash_args, PACKAGE_NAME, LASH_Config_Data_Set, LASH_PROTOCOL(2, 0));
+    lash_args = lash_extract_args(&argc, &argv);
+    lash_client = lash_init(lash_args, PACKAGE_NAME, LASH_Config_Data_Set, LASH_PROTOCOL(2, 0));
 # else
-    sess.lash_client = lash_client_open(PACKAGE_NAME, LASH_Config_Data_Set, argc, argv);
-    sess.restoring_session = lash_client_is_being_restored(sess.lash_client);
-    lash_set_save_data_set_callback(sess.lash_client, save_data_set_cb, &sess);
-    lash_set_load_data_set_callback(sess.lash_client, load_data_set_cb, &sess);
-    lash_set_quit_callback(sess.lash_client, quit_cb, NULL);
+    lash_client = lash_client_open(PACKAGE_NAME, LASH_Config_Data_Set, argc, argv);
+    restoring_session = lash_client_is_being_restored(lash_client);
+    lash_set_save_data_set_callback(lash_client, save_data_set_cb, this);
+    lash_set_load_data_set_callback(lash_client, load_data_set_cb, this);
+    lash_set_quit_callback(lash_client, quit_cb, NULL);
 # endif
-    if (!sess.lash_client) {
+    if (!lash_client) {
         g_warning("Warning: failed to create a LASH connection");
     }
 #endif
-    glade_init();
-    while(1) {
-        int option_index;
-        int c = getopt_long(argc, argv, "c:i:o:m:M:ehv", long_options, &option_index);
-        if (c == -1)
-            break;
-        switch(c) {
-            case 'h':
-            case '?':
-                print_help(argv);
-                return 0;
-            case 'v':
-                printf("%s\n", PACKAGE_STRING);
-                return 0;
-            case 'e':
-                fprintf(stderr, "Warning: switch -%c is deprecated!\n", c);
-                break;
-            case 'c':
-                sess.client_name = optarg;
-                break;
-            case 'i':
-                sess.input_name = string(optarg) + "_%d";
-                break;
-            case 'o':
-                sess.output_name = string(optarg) + "_%d";
-                break;
-            case 'm':
-                sess.midi_name = string(optarg) + "_%d";
-                break;
-            case 'M':
-                if (atoi(optarg)) {
-                    sess.autoconnect_midi_index = atoi(optarg);
-                }
-                else
-                    sess.autoconnect_midi = string(optarg);
-                break;
-        }
-    }
-    while(optind < argc) {
-        if (!strcmp(argv[optind], "!")) {
-            sess.chains.insert(sess.plugin_names.size());
-            optind++;
-        } else {
-            string plugname = argv[optind++];
-            size_t pos = plugname.find(":");
-            if (pos != string::npos) {
-                sess.presets[sess.plugin_names.size()] = plugname.substr(pos + 1);
-                plugname = plugname.substr(0, pos);
-            }
-            sess.plugin_names.push_back(plugname);
-        }
-    }
-    try {
-        get_builtin_presets().load_defaults(true);
-        get_user_presets().load_defaults(false);
-    }
-    catch(calf_plugins::preset_exception &e)
-    {
-        // XXXKF this exception is already handled by load_defaults, so this is redundant
-        fprintf(stderr, "Error while loading presets: %s\n", e.what());
-        exit(1);
-    }
-    try {
-        sess.open();
-        sess.connect();
-        sess.client.activate();
-        gtk_main();
-        sess.close();
-        
-#if USE_LASH && !USE_LASH_0_6
-        if (sess.lash_args)
-            lash_args_destroy(sess.lash_args);
-#endif
-        // this is now done on preset add
-        // save_presets(get_preset_filename().c_str());
-    }
-    catch(std::exception &e)
-    {
-        fprintf(stderr, "%s\n", e.what());
-        exit(1);
-    }
-    return 0;
 }
diff --git a/src/jack_client.cpp b/src/jack_client.cpp
new file mode 100644
index 0000000..c8557a9
--- /dev/null
+++ b/src/jack_client.cpp
@@ -0,0 +1,127 @@
+/* Calf DSP Library Utility Application - calfjackhost
+ * A class wrapping a JACK client
+ *
+ * Copyright (C) 2007-2010 Krzysztof Foltman
+ *
+ * This program 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, 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 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 Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <set>
+#include <getopt.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <config.h>
+#include <glade/glade.h>
+#include <jack/jack.h>
+#include <calf/giface.h>
+#include <calf/jackhost.h>
+
+using namespace std;
+using namespace calf_utils;
+using namespace calf_plugins;
+
+jack_client::jack_client()
+{
+    input_nr = output_nr = midi_nr = 1;
+    input_name = "input_%d";
+    output_name = "output_%d";
+    midi_name = "midi_%d";
+    sample_rate = 0;
+    client = NULL;
+}
+
+void jack_client::add(jack_host *plugin)
+{
+    calf_utils::ptlock lock(mutex);
+    plugins.push_back(plugin);
+}
+
+void jack_client::del(int item)
+{
+    calf_utils::ptlock lock(mutex);
+    plugins.erase(plugins.begin()+item);
+}
+
+void jack_client::open(const char *client_name)
+{
+    jack_status_t status;
+    client = jack_client_open(client_name, JackNullOption, &status);
+    if (!client)
+        throw calf_utils::text_exception("Could not initialize JACK subsystem");
+    sample_rate = jack_get_sample_rate(client);
+    jack_set_process_callback(client, do_jack_process, this);
+    jack_set_buffer_size_callback(client, do_jack_bufsize, this);
+    name = get_name();
+}
+
+std::string jack_client::get_name()
+{
+    return std::string(jack_get_client_name(client));
+}
+
+void jack_client::activate()
+{
+    jack_activate(client);        
+}
+
+void jack_client::deactivate()
+{
+    jack_deactivate(client);        
+}
+
+void jack_client::connect(const std::string &p1, const std::string &p2)
+{
+    if (jack_connect(client, p1.c_str(), p2.c_str()) != 0)
+        throw calf_utils::text_exception("Could not connect JACK ports "+p1+" and "+p2);
+}
+
+void jack_client::close()
+{
+    jack_client_close(client);
+}
+
+const char **jack_client::get_ports(const char *name_re, const char *type_re, unsigned long flags)
+{
+    return jack_get_ports(client, name_re, type_re, flags);
+}
+
+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;
+}
+
+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;
+}
+
+void jack_client::delete_plugins()
+{
+    ptlock lock(mutex);
+    for (unsigned int i = 0; i < plugins.size(); i++) {
+        delete plugins[i];
+    }
+    plugins.clear();
+}
+
diff --git a/src/jackhost.cpp b/src/jackhost.cpp
index 2ed27ae..566da1a 100644
--- a/src/jackhost.cpp
+++ b/src/jackhost.cpp
@@ -25,11 +25,8 @@
 #include <config.h>
 #include <glade/glade.h>
 #include <jack/jack.h>
-#if USE_LASH
-#include <lash/lash.h>
-#endif
 #include <calf/giface.h>
-#include <calf/jackhost.h>
+#include <calf/host_session.h>
 #include <calf/modules.h>
 #include <calf/modules_dev.h>
 #include <calf/organ.h>
@@ -39,21 +36,13 @@
 #include <calf/main_win.h>
 #include <calf/utils.h>
 #include <stdio.h>
+
 using namespace std;
 using namespace calf_utils;
 using namespace calf_plugins;
 
-// I don't need anyone to tell me this is stupid. I already know that :)
-plugin_gui_window *gui_win;
-
 const char *client_name = "calfhost";
 
-#if USE_LASH_0_6
-static bool save_data_set_cb(lash_config_handle_t *handle, void *user_data);
-static bool load_data_set_cb(lash_config_handle_t *handle, void *user_data);
-static bool quit_cb(void *user_data);
-#endif
-
 jack_host *calf_plugins::create_jack_host(const char *effect_name, const std::string &instance_name, calf_plugins::progress_report_iface *priface)
 {
     #define PER_MODULE_ITEM(name, isSynth, jackname) if (!strcasecmp(effect_name, jackname)) return new jack_host(new name##_audio_module, effect_name, instance_name, priface);
@@ -61,15 +50,48 @@ jack_host *calf_plugins::create_jack_host(const char *effect_name, const std::st
     return NULL;
 }
 
-void jack_host::open(jack_client *_client)
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+jack_host::jack_host(audio_module_iface *_module, const std::string &_name, const std::string &_instance_name, calf_plugins::progress_report_iface *_priface)
+: module(_module)
 {
-    client = _client; //jack_client_open(client_name, JackNullOption, &status);
+    name = _name;
+    instance_name = _instance_name;
     
-    create_ports();
+    client = NULL;
+    changed = true;
+
+    module->get_port_arrays(ins, outs, params);
+    metadata = module->get_metadata_iface();
+    in_count = metadata->get_input_count();
+    out_count = metadata->get_output_count();
+    inputs.resize(in_count);
+    outputs.resize(out_count);
+    param_values = new float[metadata->get_param_count()];
+    for (int i = 0; i < metadata->get_param_count(); i++) {
+        params[i] = &param_values[i];
+    }
+    clear_preset();
+    midi_meter = 0;
+    module->set_progress_report_iface(_priface);
+    module->post_instantiate();
+}
+
+jack_host::~jack_host()
+{
+    delete []param_values;
+    if (client)
+        destroy();
+}
+
+void jack_host::create(jack_client *_client)
+{
+    client = _client; //jack_client_open(client_name, JackNullOption, &status);
     
+    create_ports();    
     cache_ports();
-    
     init_module();
+    
     changed = false;
 }
 
@@ -112,7 +134,38 @@ void jack_host::create_ports() {
     }
 }
 
-void jack_host::close() {
+void jack_host::handle_event(uint8_t *buffer, uint32_t size)
+{
+    int value;
+    switch(buffer[0] >> 4)
+    {
+    case 8:
+        module->note_off(buffer[1], buffer[2]);
+        break;
+    case 9:
+        if (!buffer[2])
+            module->note_off(buffer[1], 0);
+        else
+            module->note_on(buffer[1], buffer[2]);
+        break;
+    case 11:
+        module->control_change(buffer[1], buffer[2]);
+        break;
+    case 12:
+        module->program_change(buffer[1]);
+        break;
+    case 13:
+        module->channel_pressure(buffer[1]);
+        break;
+    case 14:
+        value = buffer[1] + 128 * buffer[2] - 8192;
+        module->pitch_bend(value);
+        break;
+    }
+}
+
+void jack_host::destroy()
+{
     port *inputs = get_inputs(), *outputs = get_outputs();
     int input_count = metadata->get_input_count(), output_count = metadata->get_output_count();
     for (int i = 0; i < input_count; i++) {
@@ -128,706 +181,126 @@ void jack_host::close() {
     client = NULL;
 }
 
-void destroy(GtkWindow *window, gpointer data)
-{
-    gtk_main_quit();
-}
-
-void gui_win_destroy(GtkWindow *window, gpointer data)
-{
-}
-
-static struct option long_options[] = {
-    {"help", 0, 0, 'h'},
-    {"version", 0, 0, 'v'},
-    {"client", 1, 0, 'c'},
-    {"effect", 0, 0, 'e'},
-    {"input", 1, 0, 'i'},
-    {"output", 1, 0, 'o'},
-    {"connect-midi", 1, 0, 'M'},
-    {0,0,0,0},
-};
-
-void print_help(char *argv[])
-{
-    printf("JACK host for Calf effects\n"
-        "Syntax: %s [--client <name>] [--input <name>] [--output <name>] [--midi <name>]\n"
-        "       [--connect-midi <name|capture-index>] [--help] [--version] [!] pluginname[:<preset>] [!] ...\n", 
-        argv[0]);
-}
-
-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;
-}
-
-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;
-}
-
-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, public calf_plugins::progress_report_iface
+void jack_host::process_part(unsigned int time, unsigned int len)
 {
-    string client_name, input_name, output_name, midi_name;
-    vector<string> plugin_names;
-    map<int, string> presets;
-#if USE_LASH
-    int lash_source_id;
-    lash_client_t *lash_client;
-# if !USE_LASH_0_6
-    lash_args_t *lash_args;
-# endif
-#endif
-    
-    // these are not saved
-    jack_client client;
-    string autoconnect_midi;
-    int autoconnect_midi_index;
-    set<int> chains;
-    vector<jack_host *> plugins;
-    main_window *main_win;
-    bool restoring_session;
-    std::set<std::string> instances;
-    GtkWidget *progress_window;
-    
-    host_session();
-    void open();
-    void add_plugin(string name, string preset, string instance_name = string());
-    void create_plugins_from_list();
-    void connect();
-    void close();
-    bool activate_preset(int plugin, const std::string &preset, bool builtin);
-#if USE_LASH
-    static gboolean update_lash(void *self) { ((host_session *)self)->update_lash(); return TRUE; }
-    void update_lash();
-# if !USE_LASH_0_6
-    void send_lash(LASH_Event_Type type, const std::string &data) {
-        lash_send_event(lash_client, lash_event_new_with_all(type, data.c_str()));
-    }
-# endif
-#endif
-    virtual void new_plugin(const char *name);    
-    virtual void remove_plugin(plugin_ctl_iface *plugin);
-    void remove_all_plugins();
-    std::string get_next_instance_name(const std::string &effect_name);
-    
-    /// Create a toplevel window with progress bar
-    GtkWidget *create_progress_window();
-    /// Implementation of progress_report_iface function
-    void report_progress(float percentage, const std::string &message);
-    
-    /// Implementation of open file functionality (TODO)
-    virtual char *open_file(const char *name);
-    /// Implementation of save file functionality
-    virtual char *save_file(const char *name);
-};
-
-host_session::host_session()
-{
-    client_name = "calf";
-#if USE_LASH
-    lash_source_id = 0;
-    lash_client = NULL;
-# if !USE_LASH_0_6
-    lash_args = NULL;
-# endif
-#endif
-    restoring_session = false;
-    main_win = new main_window;
-    main_win->set_owner(this);
-    progress_window = NULL;
-    autoconnect_midi_index = -1;
-}
-
-std::string host_session::get_next_instance_name(const std::string &effect_name)
-{
-    if (!instances.count(effect_name))
-        return effect_name;
-    for (int i = 2; ; i++)
-    {
-        string tmp = string(effect_name) + i2s(i);
-        if (!instances.count(tmp))
-            return tmp;
-    }
-    assert(0);
-    return "-";
-}
-
-void host_session::add_plugin(string name, string preset, string instance_name)
-{
-    if (instance_name.empty())
-        instance_name = get_next_instance_name(name);
-    jack_host *jh = create_jack_host(name.c_str(), instance_name, this);
-    if (!jh) {
-        string s = 
-        #define PER_MODULE_ITEM(name, isSynth, jackname) jackname ", "
-        #include <calf/modulelist.h>
-        ;
-        if (!s.empty())
-            s = s.substr(0, s.length() - 2);
-        throw text_exception("Unknown plugin name; allowed are: " + s);
-    }
-    instances.insert(jh->instance_name);
-    jh->open(&client);
-    
-    plugins.push_back(jh);
-    client.add(jh);
-    main_win->add_plugin(jh);
-    if (!preset.empty()) {
-        if (!activate_preset(plugins.size() - 1, preset, false))
-        {
-            if (!activate_preset(plugins.size() - 1, preset, true))
-            {
-                fprintf(stderr, "Unknown preset: %s\n", preset.c_str());
-            }
-        }
-    }
-}
-
-void host_session::report_progress(float percentage, const std::string &message)
-{
-    if (percentage < 100)
-    {
-        if (!progress_window) {
-            progress_window = create_progress_window();
-            gtk_window_set_modal (GTK_WINDOW (progress_window), TRUE);
-            if (main_win->toplevel)
-                gtk_window_set_transient_for (GTK_WINDOW (progress_window), main_win->toplevel);
-        }
-        gtk_widget_show(progress_window);
-        GtkWidget *pbar = gtk_bin_get_child (GTK_BIN (progress_window));
-        if (!message.empty())
-            gtk_progress_bar_set_text (GTK_PROGRESS_BAR (pbar), message.c_str());
-        gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (pbar), percentage / 100.0);
-    }
-    else
-    {
-        if (progress_window) {
-            gtk_window_set_modal (GTK_WINDOW (progress_window), FALSE);
-            gtk_widget_destroy (progress_window);
-            progress_window = NULL;
-        }
-    }
-    
-    while (gtk_events_pending ())
-        gtk_main_iteration ();
-}
-
-
-void host_session::create_plugins_from_list()
-{
-    for (unsigned int i = 0; i < plugin_names.size(); i++) {
-        add_plugin(plugin_names[i], presets.count(i) ? presets[i] : string());
-    }
-}
-
-GtkWidget *host_session::create_progress_window()
-{
-    GtkWidget *tlw = gtk_window_new ( GTK_WINDOW_TOPLEVEL );
-    gtk_window_set_type_hint (GTK_WINDOW (tlw), GDK_WINDOW_TYPE_HINT_DIALOG);
-    GtkWidget *pbar = gtk_progress_bar_new();
-    gtk_container_add (GTK_CONTAINER(tlw), pbar);
-    gtk_widget_show_all (pbar);
-    return tlw;
-}
-
-void host_session::open()
-{
-    if (!input_name.empty()) client.input_name = input_name;
-    if (!output_name.empty()) client.output_name = output_name;
-    if (!midi_name.empty()) client.midi_name = midi_name;
-    
-    client.open(client_name.c_str());
-    main_win->prefix = client_name + " - ";
-    main_win->conditions.insert("jackhost");
-    main_win->conditions.insert("directlink");
-    if (!restoring_session)
-        create_plugins_from_list();
-    main_win->create();
-    gtk_signal_connect(GTK_OBJECT(main_win->toplevel), "destroy", G_CALLBACK(destroy), NULL);
-}
-
-void host_session::new_plugin(const char *name)
-{
-    jack_host *jh = create_jack_host(name, get_next_instance_name(name), this);
-    if (!jh)
+    if (!len)
         return;
-    instances.insert(jh->instance_name);
-    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++)
+    for (int i = 0; i < in_count; i++)
+        inputs[i].meter.update(ins[i] + time, len);
+    unsigned int mask = module->process(time, len, -1, -1);
+    for (int i = 0; i < out_count; i++)
     {
-        if (plugins[i] == plugin)
-        {
-            client.del(i);
-            plugins.erase(plugins.begin() + i);
-            main_win->del_plugin(plugin);
-            delete plugin;
-            return;
-        }
-    }
-}
-
-void host_session::remove_all_plugins()
+        if (!(mask & (1 << i))) {
+            dsp::zero(outs[i] + time, len);
+            outputs[i].meter.update_zeros(len);
+        } else
+            outputs[i].meter.update(outs[i] + time, len);
+    }
+    // decay linearly for 0.1s
+    float new_meter = midi_meter - len / (0.1 * client->sample_rate);
+    if (new_meter < 0)
+        new_meter = 0;
+    midi_meter = new_meter;
+}
+
+float jack_host::get_level(unsigned int port)
+{ 
+    if (port < (unsigned)in_count)
+        return inputs[port].meter.level;
+    port -= in_count;
+    if (port < (unsigned)out_count)
+        return outputs[port].meter.level;
+    port -= out_count;
+    if (port == 0 && metadata->get_midi())
+        return midi_meter;
+    return 0.f;
+}
+
+int jack_host::process(jack_nframes_t nframes)
 {
-    while(!plugins.empty())
-    {
-        plugin_ctl_iface *plugin = plugins[0];
-        client.del(0);
-        plugins.erase(plugins.begin());
-        main_win->del_plugin(plugin);
-        delete plugin;
+    for (int i=0; i<in_count; i++) {
+        ins[i] = inputs[i].data = (float *)jack_port_get_buffer(inputs[i].handle, nframes);
     }
-}
-
-bool host_session::activate_preset(int plugin_no, const std::string &preset, bool builtin)
-{
-    string cur_plugin = plugins[plugin_no]->metadata->get_id();
-    preset_vector &pvec = (builtin ? get_builtin_presets() : get_user_presets()).presets;
-    for (unsigned int i = 0; i < pvec.size(); i++) {
-        if (pvec[i].name == preset && pvec[i].plugin == cur_plugin)
-        {
-            pvec[i].activate(plugins[plugin_no]);
-            if (gui_win && gui_win->gui)
-                gui_win->gui->refresh();
-            return true;
-        }
+    if (metadata->get_midi())
+        midi_port.data = (float *)jack_port_get_buffer(midi_port.handle, nframes);
+    if (changed) {
+        module->params_changed();
+        changed = false;
     }
-    return false;
-}
 
-void host_session::connect()
-{
-    client.activate();
-#if USE_LASH && !USE_LASH_0_6
-    if (lash_client)
-        lash_jack_client_name(lash_client, client.get_name().c_str());
-#endif
-    if (!restoring_session) 
-    {
-        string cnp = client.get_name() + ":";
-        for (unsigned int i = 0; i < plugins.size(); i++) {
-            if (chains.count(i)) {
-                if (!i)
-                {
-                    if (plugins[0]->metadata->get_output_count() < 2)
-                    {
-                        fprintf(stderr, "Cannot connect input to plugin %s - incompatible ports\n", plugins[0]->name.c_str());
-                    } else {
-                        client.connect("system:capture_1", cnp + plugins[0]->get_inputs()[0].name);
-                        client.connect("system:capture_2", cnp + plugins[0]->get_inputs()[1].name);
-                    }
-                }
-                else
-                {
-                    if (plugins[i - 1]->metadata->get_output_count() < 2 || plugins[i]->metadata->get_input_count() < 2)
-                    {
-                        fprintf(stderr, "Cannot connect plugins %s and %s - incompatible ports\n", plugins[i - 1]->name.c_str(), plugins[i]->name.c_str());
-                    }
-                    else {
-                        client.connect(cnp + plugins[i - 1]->get_outputs()[0].name, cnp + plugins[i]->get_inputs()[0].name);
-                        client.connect(cnp + plugins[i - 1]->get_outputs()[1].name, cnp + plugins[i]->get_inputs()[1].name);
-                    }
-                }
-            }
-        }
-        if (chains.count(plugins.size()) && plugins.size())
-        {
-            int last = plugins.size() - 1;
-            if (plugins[last]->metadata->get_output_count() < 2)
-            {
-                fprintf(stderr, "Cannot connect plugin %s to output - incompatible ports\n", plugins[last]->name.c_str());
-            } else {
-                client.connect(cnp + plugins[last]->get_outputs()[0].name, "system:playback_1");
-                client.connect(cnp + plugins[last]->get_outputs()[1].name, "system:playback_2");
-            }
-        }
-        if (autoconnect_midi != "") {
-            for (unsigned int i = 0; i < plugins.size(); i++)
-            {
-                if (plugins[i]->metadata->get_midi())
-                    client.connect(autoconnect_midi, cnp + plugins[i]->get_midi_port()->name);
-            }
-        }
-        else
-        if (autoconnect_midi_index != -1) {
-            const char **ports = client.get_ports("(system|alsa_pcm):.*", JACK_DEFAULT_MIDI_TYPE, JackPortIsOutput);
-            for (int j = 0; ports && ports[j]; j++)
-            {
-                if (j + 1 == autoconnect_midi_index) {
-                    for (unsigned int i = 0; i < plugins.size(); i++)
-                    {
-                        if (plugins[i]->metadata->get_midi())
-                            client.connect(ports[j], cnp + plugins[i]->get_midi_port()->name);
-                    }
-                    break;
-                }
-            }
-        }
-    }
-#if USE_LASH
-    if (lash_client)
+    unsigned int time = 0;
+    if (metadata->get_midi())
     {
-# if !USE_LASH_0_6
-        send_lash(LASH_Client_Name, "calf-"+client_name);
-# endif
-        lash_source_id = g_timeout_add_full(G_PRIORITY_LOW, 250, update_lash, this, NULL); // 4 LASH reads per second... should be enough?
-    }
-#endif
-}
-
-void host_session::close()
-{
-#if USE_LASH
-    if (lash_source_id)
-        g_source_remove(lash_source_id);
+        jack_midi_event_t event;
+#ifdef OLD_JACK
+        int count = jack_midi_get_event_count(midi_port.data, nframes);
+#else
+        int count = jack_midi_get_event_count(midi_port.data);
 #endif
-    main_win->on_closed();
-    main_win->close_guis();
-    client.deactivate();
-    client.delete_plugins();
-    client.close();
-}
-
-static string stripfmt(string x)
-{
-    if (x.length() < 2)
-        return x;
-    if (x.substr(x.length() - 2) != "%d")
-        return x;
-    return x.substr(0, x.length() - 2);
-}
-
-char *host_session::open_file(const char *name)
-{
-    preset_list pl;
-    try {
-        remove_all_plugins();
-        pl.load(name, true);
-        printf("Size %d\n", (int)pl.plugins.size());
-        for (unsigned int i = 0; i < pl.plugins.size(); i++)
+        for (int i = 0; i < count; i++)
         {
-            preset_list::plugin_snapshot &ps = pl.plugins[i];
-            client.input_nr = ps.input_index;
-            client.output_nr = ps.output_index;
-            client.midi_nr = ps.midi_index;
-            printf("Loading %s\n", ps.type.c_str());
-            if (ps.preset_offset < (int)pl.presets.size())
-            {
-                add_plugin(ps.type, "", ps.instance_name);
-                pl.presets[ps.preset_offset].activate(plugins[i]);
-                main_win->refresh_plugin(plugins[i]);
-            }
-        }
-    }
-    catch(preset_exception &e)
-    {
-        // XXXKF this will leak
-        char *data = strdup(e.what());
-        return data;
-    }
-    
-    return NULL;
-}
-
-char *host_session::save_file(const char *name)
-{
-    string i_name = stripfmt(client.input_name);
-    string o_name = stripfmt(client.output_name);
-    string m_name = stripfmt(client.midi_name);
-    string data;
-    data = "<?xml version=\"1.1\" encoding=\"utf-8\">\n";
-    data = "<rack>\n";
-    for (unsigned int i = 0; i < plugins.size(); i++) {
-        jack_host *p = plugins[i];
-        plugin_preset preset;
-        preset.plugin = p->metadata->get_id();
-        preset.get_from(p);
-        data += "<plugin";
-        data += to_xml_attr("type", preset.plugin);
-        data += to_xml_attr("instance-name", p->instance_name);
-        if (p->metadata->get_input_count())
-            data += to_xml_attr("input-index", p->get_inputs()[0].name.substr(i_name.length()));
-        if (p->metadata->get_output_count())
-            data += to_xml_attr("output-index", p->get_outputs()[0].name.substr(o_name.length()));
-        if (p->get_midi_port())
-            data += to_xml_attr("midi-index", p->get_midi_port()->name.substr(m_name.length()));
-        data += ">\n";
-        data += preset.to_xml();
-        data += "</plugin>\n";
-    }
-    data += "</rack>\n";
-    FILE *f = fopen(name, "w");
-    if (!f || 1 != fwrite(data.c_str(), data.length(), 1, f))
-    {
-        int e = errno;
-        fclose(f);
-        return strdup(strerror(e));
-    }
-    if (fclose(f))
-        return strdup(strerror(errno));
-    
-    return NULL;
-}
-
-#if USE_LASH
-
-# if !USE_LASH_0_6
-
-void host_session::update_lash()
-{
-    do {
-        lash_event_t *event = lash_get_event(lash_client);
-        if (!event)
-            break;
-        
-        // printf("type = %d\n", lash_event_get_type(event));
-        
-        switch(lash_event_get_type(event)) {        
-            case LASH_Save_Data_Set:
-            {
-                lash_config_t *cfg = lash_config_new_with_key("global");
-                dictionary tmp;
-                string pstr;
-                string i_name = stripfmt(client.input_name);
-                string o_name = stripfmt(client.output_name);
-                string m_name = stripfmt(client.midi_name);
-                tmp["input_prefix"] = i_name;
-                tmp["output_prefix"] = stripfmt(client.output_name);
-                tmp["midi_prefix"] = stripfmt(client.midi_name);
-                pstr = encode_map(tmp);
-                lash_config_set_value(cfg, pstr.c_str(), pstr.length());
-                lash_send_config(lash_client, cfg);
-                
-                for (unsigned int i = 0; i < plugins.size(); i++) {
-                    jack_host *p = plugins[i];
-                    char ss[32];
-                    plugin_preset preset;
-                    preset.plugin = p->get_id();
-                    preset.get_from(p);
-                    sprintf(ss, "Plugin%d", i);
-                    pstr = preset.to_xml();
-                    tmp.clear();
-                    tmp["instance_name"] = p->instance_name;
-                    if (p->get_input_count())
-                        tmp["input_name"] = p->get_inputs()[0].name.substr(i_name.length());
-                    if (p->get_output_count())
-                        tmp["output_name"] = p->get_outputs()[0].name.substr(o_name.length());
-                    if (p->get_midi_port())
-                        tmp["midi_name"] = p->get_midi_port()->name.substr(m_name.length());
-                    tmp["preset"] = pstr;
-                    pstr = encode_map(tmp);
-                    lash_config_t *cfg = lash_config_new_with_key(ss);
-                    lash_config_set_value(cfg, pstr.c_str(), pstr.length());
-                    lash_send_config(lash_client, cfg);
-                }
-                send_lash(LASH_Save_Data_Set, "");
-                break;
-            }
+#ifdef OLD_JACK
+            jack_midi_event_get(&event, midi_port.data, i, nframes);
+#else
+            jack_midi_event_get(&event, midi_port.data, i);
+#endif
+            unsigned int len = event.time - time;
+            process_part(time, len);
             
-            case LASH_Restore_Data_Set:
-            {
-                // printf("!!!Restore data set!!!\n");
-                remove_all_plugins();
-                while(lash_config_t *cfg = lash_get_config(lash_client)) {
-                    const char *key = lash_config_get_key(cfg);
-                    // printf("key = %s\n", lash_config_get_key(cfg));
-                    string data = string((const char *)lash_config_get_value(cfg), lash_config_get_value_size(cfg));
-                    if (!strcmp(key, "global"))
-                    {
-                        dictionary dict;
-                        decode_map(dict, data);
-                        if (dict.count("input_prefix")) client.input_name = dict["input_prefix"]+"%d";
-                        if (dict.count("output_prefix")) client.output_name = dict["output_prefix"]+"%d";
-                        if (dict.count("midi_prefix")) client.midi_name = dict["midi_prefix"]+"%d";
-                    }
-                    if (!strncmp(key, "Plugin", 6))
-                    {
-                        unsigned int nplugin = atoi(key + 6);
-                        dictionary dict;
-                        decode_map(dict, data);
-                        data = dict["preset"];
-                        string instance_name;
-                        if (dict.count("instance_name")) instance_name = dict["instance_name"];
-                        if (dict.count("input_name")) client.input_nr = atoi(dict["input_name"].c_str());
-                        if (dict.count("output_name")) client.output_nr = atoi(dict["output_name"].c_str());
-                        if (dict.count("midi_name")) client.midi_nr = atoi(dict["midi_name"].c_str());
-                        preset_list tmp;
-                        tmp.parse("<presets>"+data+"</presets>", false);
-                        if (tmp.presets.size())
-                        {
-                            printf("Load plugin %s\n", tmp.presets[0].plugin.c_str());
-                            add_plugin(tmp.presets[0].plugin, "", instance_name);
-                            tmp.presets[0].activate(plugins[nplugin]);
-                            main_win->refresh_plugin(plugins[nplugin]);
-                        }
-                    }
-                    lash_config_destroy(cfg);
-                }
-                send_lash(LASH_Restore_Data_Set, "");
-                break;
-            }
-                
-            case LASH_Quit:
-                gtk_main_quit();
-                break;
+            midi_meter = 1.f;
+            handle_event(event.buffer, event.size);
             
-            default:
-                g_warning("Unhandled LASH event %d (%s)", lash_event_get_type(event), lash_event_get_string(event));
-                break;
+            time = event.time;
         }
-    } while(1);
+    }
+    process_part(time, nframes - time);
+    module->params_reset();
+    return 0;
 }
 
-# else
-
-void host_session::update_lash()
+void jack_host::init_module()
 {
-    lash_dispatch(lash_client);
+    module->set_sample_rate(client->sample_rate);
+    module->activate();
+    module->params_changed();
 }
 
-bool save_data_set_cb(lash_config_handle_t *handle, void *user_data)
+void jack_host::cache_ports()
 {
-    host_session *sess = static_cast<host_session *>(user_data);
-    dictionary tmp;
-    string pstr;
-    string i_name = stripfmt(sess->client.input_name);
-    string o_name = stripfmt(sess->client.output_name);
-    string m_name = stripfmt(sess->client.midi_name);
-    tmp["input_prefix"] = i_name;
-    tmp["output_prefix"] = stripfmt(sess->client.output_name);
-    tmp["midi_prefix"] = stripfmt(sess->client.midi_name);
-    pstr = encode_map(tmp);
-    lash_config_write_raw(handle, "global", pstr.c_str(), pstr.length());
-    for (unsigned int i = 0; i < sess->plugins.size(); i++) {
-        jack_host *p = sess->plugins[i];
-        char ss[32];
-        plugin_preset preset;
-        preset.plugin = p->metadata->get_id();
-        preset.get_from(p);
-        sprintf(ss, "Plugin%d", i);
-        pstr = preset.to_xml();
-        tmp.clear();
-        tmp["instance_name"] = p->instance_name;
-        if (p->metadata->get_input_count())
-            tmp["input_name"] = p->get_inputs()[0].name.substr(i_name.length());
-        if (p->metadata->get_output_count())
-            tmp["output_name"] = p->get_outputs()[0].name.substr(o_name.length());
-        if (p->get_midi_port())
-            tmp["midi_name"] = p->get_midi_port()->name.substr(m_name.length());
-        tmp["preset"] = pstr;
-        pstr = encode_map(tmp);
-        lash_config_write_raw(handle, ss, pstr.c_str(), pstr.length());
+    for (int i=0; i<out_count; i++) {
+        outs[i] = outputs[i].data = (float *)jack_port_get_buffer(outputs[i].handle, 0);
     }
-    return true;
 }
 
-bool load_data_set_cb(lash_config_handle_t *handle, void *user_data)
-{
-    host_session *sess = static_cast<host_session *>(user_data);
-    int size, type;
-    const char *key;
-    const char *value;
-    sess->remove_all_plugins();
-    while((size = lash_config_read(handle, &key, (void *)&value, &type))) {
-        if (size == -1 || type != LASH_TYPE_RAW)
-            continue;
-        string data = string(value, size);
-        if (!strcmp(key, "global"))
-        {
-            dictionary dict;
-            decode_map(dict, data);
-            if (dict.count("input_prefix")) sess->client.input_name = dict["input_prefix"]+"%d";
-            if (dict.count("output_prefix")) sess->client.output_name = dict["output_prefix"]+"%d";
-            if (dict.count("midi_prefix")) sess->client.midi_name = dict["midi_prefix"]+"%d";
-        } else if (!strncmp(key, "Plugin", 6)) {
-            unsigned int nplugin = atoi(key + 6);
-            dictionary dict;
-            decode_map(dict, data);
-            data = dict["preset"];
-            string instance_name;
-            if (dict.count("instance_name")) instance_name = dict["instance_name"];
-            if (dict.count("input_name")) sess->client.input_nr = atoi(dict["input_name"].c_str());
-            if (dict.count("output_name")) sess->client.output_nr = atoi(dict["output_name"].c_str());
-            if (dict.count("midi_name")) sess->client.midi_nr = atoi(dict["midi_name"].c_str());
-            preset_list tmp;
-            tmp.parse("<presets>"+data+"</presets>", false);
-            if (tmp.presets.size())
-            {
-                printf("Load plugin %s\n", tmp.presets[0].plugin.c_str());
-                sess->add_plugin(tmp.presets[0].plugin, "", instance_name);
-                tmp.presets[0].activate(sess->plugins[nplugin]);
-                sess->main_win->refresh_plugin(sess->plugins[nplugin]);
-            }
-        }
-    }
-    return true;
-}
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+static struct option long_options[] = {
+    {"help", 0, 0, 'h'},
+    {"version", 0, 0, 'v'},
+    {"client", 1, 0, 'c'},
+    {"effect", 0, 0, 'e'},
+    {"input", 1, 0, 'i'},
+    {"output", 1, 0, 'o'},
+    {"connect-midi", 1, 0, 'M'},
+    {0,0,0,0},
+};
 
-bool quit_cb(void *user_data)
+void print_help(char *argv[])
 {
-    gtk_main_quit();
-    return true;
+    printf("JACK host for Calf effects\n"
+        "Syntax: %s [--client <name>] [--input <name>] [--output <name>] [--midi <name>]\n"
+        "       [--connect-midi <name|capture-index>] [--help] [--version] [!] pluginname[:<preset>] [!] ...\n", 
+        argv[0]);
 }
 
-# endif
-#endif
-
-host_session current_session;
-
 int main(int argc, char *argv[])
 {
-    host_session &sess = current_session;
+    host_session sess;
+
     gtk_rc_add_default_file(PKGLIBDIR "calf.rc");
     gtk_init(&argc, &argv);
     
-#if USE_LASH
-# if !USE_LASH_0_6
-    for (int i = 1; i < argc; i++)
-    {
-        if (!strncmp(argv[i], "--lash-project=", 14)) {
-            sess.restoring_session = true;
-            break;
-        }
-    }
-    sess.lash_args = lash_extract_args(&argc, &argv);
-    sess.lash_client = lash_init(sess.lash_args, PACKAGE_NAME, LASH_Config_Data_Set, LASH_PROTOCOL(2, 0));
-# else
-    sess.lash_client = lash_client_open(PACKAGE_NAME, LASH_Config_Data_Set, argc, argv);
-    sess.restoring_session = lash_client_is_being_restored(sess.lash_client);
-    lash_set_save_data_set_callback(sess.lash_client, save_data_set_cb, &sess);
-    lash_set_load_data_set_callback(sess.lash_client, load_data_set_cb, &sess);
-    lash_set_quit_callback(sess.lash_client, quit_cb, NULL);
-# endif
-    if (!sess.lash_client) {
-        g_warning("Warning: failed to create a LASH connection");
-    }
-#endif
+    sess.connect_to_session_manager(argc, argv);
     glade_init();
     while(1) {
         int option_index;

-- 
calf audio plugins packaging



More information about the pkg-multimedia-commits mailing list