summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/AlsaDriver.cpp15
-rw-r--r--src/Driver.h8
-rw-r--r--src/JackDriver.cpp9
-rw-r--r--src/JackDriver.h5
-rw-r--r--src/Patchage.cpp34
-rw-r--r--src/PatchageEvent.cpp112
-rw-r--r--src/PatchageEvent.h43
-rw-r--r--src/PatchagePort.h2
8 files changed, 162 insertions, 66 deletions
diff --git a/src/AlsaDriver.cpp b/src/AlsaDriver.cpp
index 87ef6d3..9a46d14 100644
--- a/src/AlsaDriver.cpp
+++ b/src/AlsaDriver.cpp
@@ -87,6 +87,8 @@ AlsaDriver::detach()
void
AlsaDriver::refresh()
{
+ cerr << "ALSA REFRESH" << endl;
+
if (!is_attached())
return;
@@ -505,6 +507,14 @@ AlsaDriver::_refresh_main()
continue;
switch (ev->type) {
+ case SND_SEQ_EVENT_PORT_SUBSCRIBED:
+ _events.push(PatchageEvent(_app, PatchageEvent::CONNECTION,
+ ev->data.connect.sender, ev->data.connect.dest));
+ break;
+ case SND_SEQ_EVENT_PORT_UNSUBSCRIBED:
+ _events.push(PatchageEvent(_app, PatchageEvent::DISCONNECTION,
+ ev->data.connect.sender, ev->data.connect.dest));
+ break;
case SND_SEQ_EVENT_RESET:
case SND_SEQ_EVENT_CLIENT_START:
case SND_SEQ_EVENT_CLIENT_EXIT:
@@ -512,9 +522,8 @@ AlsaDriver::_refresh_main()
case SND_SEQ_EVENT_PORT_START:
case SND_SEQ_EVENT_PORT_EXIT:
case SND_SEQ_EVENT_PORT_CHANGE:
- case SND_SEQ_EVENT_PORT_SUBSCRIBED:
- case SND_SEQ_EVENT_PORT_UNSUBSCRIBED:
- _is_dirty = true;
+ break;
+
break;
default:
break;
diff --git a/src/Driver.h b/src/Driver.h
index 3e550e3..18489ae 100644
--- a/src/Driver.h
+++ b/src/Driver.h
@@ -20,6 +20,8 @@
#include <boost/shared_ptr.hpp>
#include <sigc++/sigc++.h>
+#include <raul/SRSWQueue.h>
+#include "PatchageEvent.h"
class PatchagePort;
@@ -40,6 +42,8 @@ public:
virtual bool disconnect(boost::shared_ptr<PatchagePort> src_port,
boost::shared_ptr<PatchagePort> dst_port) = 0;
+ Raul::SRSWQueue<PatchageEvent>& events() { return _events; }
+
/** Returns whether or not a refresh is required (pending). */
inline bool is_dirty() const { return _is_dirty; }
@@ -50,9 +54,11 @@ public:
sigc::signal<void> signal_detached;
protected:
- Driver() : _is_dirty(false) {}
+ Driver() : _is_dirty(false), _events(1024) /* FIXME: size? */ {}
bool _is_dirty;
+
+ Raul::SRSWQueue<PatchageEvent> _events;
};
diff --git a/src/JackDriver.cpp b/src/JackDriver.cpp
index 5489905..47bfda1 100644
--- a/src/JackDriver.cpp
+++ b/src/JackDriver.cpp
@@ -39,7 +39,6 @@ using namespace FlowCanvas;
JackDriver::JackDriver(Patchage* app)
: _app(app)
, _client(NULL)
-, _events(1024) // FIXME: size?
, _is_activated(false)
, _xruns(0)
, _xrun_delay(0)
@@ -99,19 +98,17 @@ JackDriver::attach(bool launch_daemon)
void
JackDriver::detach()
{
- _mutex.lock();
-
if (_client) {
jack_deactivate(_client);
jack_client_close(_client);
+ _mutex.lock();
_client = NULL;
+ _mutex.unlock();
destroy_all_ports();
_is_activated = false;
signal_detached.emit();
_app->status_message("[JACK] Detached");
}
-
- _mutex.unlock();
}
@@ -182,6 +179,8 @@ JackDriver::shutdown()
void
JackDriver::refresh()
{
+ cerr << "JACK REFRESH" << endl;
+
const char** ports;
jack_port_t* port;
diff --git a/src/JackDriver.h b/src/JackDriver.h
index 816d7d5..0ee94ae 100644
--- a/src/JackDriver.h
+++ b/src/JackDriver.h
@@ -23,7 +23,6 @@
#include <boost/shared_ptr.hpp>
#include <jack/jack.h>
#include <jack/statistics.h>
-#include <raul/SRSWQueue.h>
#include <raul/Mutex.h>
#include <raul/AtomicPtr.h>
#include "Driver.h"
@@ -53,8 +52,6 @@ public:
bool is_attached() const { return (_client != NULL); }
bool is_realtime() const { return _client && jack_is_realtime(_client); }
- Raul::SRSWQueue<PatchageEvent>& events() { return _events; }
-
void refresh();
bool connect(boost::shared_ptr<PatchagePort> src,
@@ -108,8 +105,6 @@ private:
Patchage* _app;
jack_client_t* _client;
- Raul::SRSWQueue<PatchageEvent> _events;
-
Raul::Mutex _mutex;
bool _is_activated;
diff --git a/src/Patchage.cpp b/src/Patchage.cpp
index 603f306..c8a32a5 100644
--- a/src/Patchage.cpp
+++ b/src/Patchage.cpp
@@ -293,6 +293,7 @@ Patchage::attach()
bool
Patchage::idle_callback()
{
+ // Process any JACK events
if (_jack_driver) {
while (!_jack_driver->events().empty()) {
PatchageEvent& ev = _jack_driver->events().front();
@@ -300,34 +301,43 @@ Patchage::idle_callback()
ev.execute();
}
}
-
- bool refresh = _refresh;
-
- refresh = refresh || (_jack_driver && _jack_driver->is_dirty());
+ // Process any ALSA events
#ifdef HAVE_ALSA
- refresh = refresh || (_alsa_driver && _alsa_driver->is_dirty());
+ if (_alsa_driver) {
+ while (!_alsa_driver->events().empty()) {
+ PatchageEvent& ev = _alsa_driver->events().front();
+ _alsa_driver->events().pop();
+ ev.execute();
+ }
+ }
#endif
- if (refresh) {
-
+ // Do a full refresh (ie user clicked refresh)
+ if (_refresh) {
_canvas->flag_all_connections();
-
_jack_driver->refresh();
#ifdef HAVE_ALSA
- _alsa_driver->refresh();
+ if (_alsa_driver)
+ _alsa_driver->refresh();
#endif
}
+ // Jack driver needs refreshing
+ if (_refresh || _jack_driver->is_dirty()) {
+ _canvas->flag_all_connections();
+ _jack_driver->refresh();
+ _canvas->destroy_all_flagged_connections();
+ _refresh = false;
+ }
+
#ifdef HAVE_LASH
if (_lash_driver->is_attached())
_lash_driver->process_events();
#endif
- if (refresh) {
- _canvas->destroy_all_flagged_connections();
+ if (_refresh)
_refresh = false;
- }
update_load();
diff --git a/src/PatchageEvent.cpp b/src/PatchageEvent.cpp
index 70d1c43..aaec3dc 100644
--- a/src/PatchageEvent.cpp
+++ b/src/PatchageEvent.cpp
@@ -22,38 +22,68 @@
#include "PatchageEvent.h"
#include "JackDriver.h"
-void
-PatchageEvent::execute()
+
+SharedPtr<PatchagePort>
+PatchageEvent::find_port(const PortRef& ref)
{
- //cerr << "{ EXECUTING EVENT" << endl;
+ if (ref.type == ALSA_MIDI) {
+ return _patchage->canvas()->find_port(&ref.id.alsa);
+ } else {
+ jack_port_t* jack_port = NULL;
+ if (_patchage->jack_driver()->client())
+ jack_port = jack_port_by_id(_patchage->jack_driver()->client(), ref.id.jack);
+
+ if (!jack_port)
+ return boost::shared_ptr<PatchagePort>();
- jack_port_t* jack_port = NULL;
- if (_patchage->jack_driver()->client())
- jack_port = jack_port_by_id(_patchage->jack_driver()->client(), _port_id);
+ const string full_name = jack_port_name(jack_port);
+ const string module_name = full_name.substr(0, full_name.find(":"));
+ const string port_name = full_name.substr(full_name.find(":")+1);
- if (!jack_port)
- return;
+ SharedPtr<PatchageModule> module = PtrCast<PatchageModule>(
+ _patchage->canvas()->get_item(module_name));
+
+ if (module)
+ return PtrCast<PatchagePort>(module->get_port(port_name));
+ else
+ return boost::shared_ptr<PatchagePort>();
+ }
+
+ return boost::shared_ptr<PatchagePort>();
+}
- const string full_name = jack_port_name(jack_port);
- const string module_name = full_name.substr(0, full_name.find(":"));
- const string port_name = full_name.substr(full_name.find(":")+1);
- SharedPtr<PatchageModule> module = PtrCast<PatchageModule>(
- _patchage->canvas()->get_item(module_name));
+void
+PatchageEvent::execute()
+{
+ //cerr << "{ EXECUTING EVENT" << endl;
if (_type == PORT_CREATION) {
+ jack_port_t* jack_port = NULL;
+ if (_patchage->jack_driver()->client())
+ jack_port = jack_port_by_id(_patchage->jack_driver()->client(), _port_1.id.jack);
+ if (!jack_port)
+ return;
+
+ const string full_name = jack_port_name(jack_port);
+ const string module_name = full_name.substr(0, full_name.find(":"));
+ const string port_name = full_name.substr(full_name.find(":")+1);
+
+ SharedPtr<PatchageModule> module = _patchage->canvas()->find_module(module_name,
+ (jack_port_flags(jack_port) & JackPortIsInput) ? Input : Output);
+
if (!module) {
- module = boost::shared_ptr<PatchageModule>(
+ module = SharedPtr<PatchageModule>(
new PatchageModule(_patchage, module_name, InputOutput));
module->load_location();
module->store_location();
_patchage->canvas()->add_item(module);
module->show();
}
-
+
boost::shared_ptr<PatchagePort> port = PtrCast<PatchagePort>(
- module->get_port(port_name));
+ module->get_port(port_name));
if (!port) {
port = _patchage->jack_driver()->create_port(module, jack_port);
module->add_port(port);
@@ -62,28 +92,42 @@ PatchageEvent::execute()
} else if (_type == PORT_DESTRUCTION) {
- if (!module) {
- cerr << "Unable to find module for port " << full_name << endl;
- return;
- }
+ SharedPtr<PatchagePort> port = find_port(_port_1);
- boost::shared_ptr<PatchagePort> port = PtrCast<PatchagePort>(
- module->remove_port(full_name.substr(full_name.find(":")+1)));
-
- if (!port)
- cerr << "Destroy port: Unable to find port " << full_name << endl;
- else {
- //cerr << "Destroyed port " << full_name << endl;
- port->hide();
- port.reset(); // FIXME: leak?
+ if (port) {
+ SharedPtr<PatchageModule> module = PtrCast<PatchageModule>(port->module().lock());
+ assert(module);
+
+ //SharedPtr<PatchagePort> removed_port = PtrCast<PatchagePort>(
+ module->remove_port(port);
+ //assert(removed_port == port);
+ if (module->num_ports() == 0) {
+ _patchage->canvas()->remove_item(module);
+ module.reset();
+ }
+ } else {
+ cerr << "Unable to find port to destroy" << endl;
}
- }
+ } else if (_type == CONNECTION) {
+
+ SharedPtr<PatchagePort> port_1 = find_port(_port_1);
+ SharedPtr<PatchagePort> port_2 = find_port(_port_2);
+
+ if (port_1 && port_2)
+ _patchage->canvas()->add_connection(port_1, port_2, port_1->color() + 0x22222200);
+ else
+ cerr << "Unable to find port to connect" << endl;
+
+ } else if (_type == DISCONNECTION) {
+
+ SharedPtr<PatchagePort> port_1 = find_port(_port_1);
+ SharedPtr<PatchagePort> port_2 = find_port(_port_2);
- if (module->num_ports() == 0) {
- _patchage->canvas()->remove_item(module);
- module->hide();
- module.reset();
+ if (port_1 && port_2)
+ _patchage->canvas()->remove_connection(port_1, port_2);
+ else
+ cerr << "Unable to find port to disconnect" << endl;
}
//cerr << "}" << endl << endl;
diff --git a/src/PatchageEvent.h b/src/PatchageEvent.h
index a5109ee..da2526b 100644
--- a/src/PatchageEvent.h
+++ b/src/PatchageEvent.h
@@ -20,6 +20,8 @@
#include <string>
#include <jack/jack.h>
+#include "../config.h"
+#include "PatchagePort.h"
class Patchage;
@@ -31,7 +33,9 @@ public:
enum Type {
NULL_EVENT,
PORT_CREATION,
- PORT_DESTRUCTION
+ PORT_DESTRUCTION,
+ CONNECTION,
+ DISCONNECTION
};
PatchageEvent(Patchage* patchage)
@@ -39,21 +43,50 @@ public:
, _type(NULL_EVENT)
{}
- PatchageEvent(Patchage* patchage, Type type, jack_port_id_t port_id)
+ PatchageEvent(Patchage* patchage, Type type, jack_port_id_t port)
: _patchage(patchage)
, _type(type)
- , _port_id(port_id)
+ , _port_1(port)
+ {}
+
+ PatchageEvent(Patchage* patchage, Type type,
+ snd_seq_addr_t port_1, snd_seq_addr_t port_2)
+ : _patchage(patchage)
+ , _type(type)
+ , _port_1(port_1)
+ , _port_2(port_2)
{}
void execute();
Type type() { return _type; }
- jack_port_id_t port_id() { return _port_id; }
private:
Patchage* _patchage;
Type _type;
- jack_port_id_t _port_id;
+
+ struct PortRef {
+ PortRef() : type((PortType)0xdeadbeef) { id.jack = 0; }
+
+ PortRef(jack_port_id_t jack_id) : type(JACK_ANY) { id.jack = jack_id; }
+
+#ifdef HAVE_ALSA
+ PortRef(snd_seq_addr_t addr) : type(ALSA_MIDI) { id.alsa = addr; }
+#endif
+
+ PortType type;
+ union {
+ jack_port_id_t jack;
+#ifdef HAVE_ALSA
+ snd_seq_addr_t alsa;
+#endif
+ } id;
+ };
+
+ PortRef _port_1;
+ PortRef _port_2;
+
+ boost::shared_ptr<PatchagePort> find_port(const PortRef& ref);
};
diff --git a/src/PatchagePort.h b/src/PatchagePort.h
index 6109fba..4552b85 100644
--- a/src/PatchagePort.h
+++ b/src/PatchagePort.h
@@ -32,7 +32,7 @@
using namespace FlowCanvas;
using std::string; using std::list;
-enum PortType { JACK_AUDIO, JACK_MIDI, ALSA_MIDI };
+enum PortType { JACK_ANY, JACK_AUDIO, JACK_MIDI, ALSA_MIDI };
/** A Port on a PatchageModule