diff options
-rw-r--r-- | src/AlsaDriver.cpp | 15 | ||||
-rw-r--r-- | src/Driver.h | 8 | ||||
-rw-r--r-- | src/JackDriver.cpp | 9 | ||||
-rw-r--r-- | src/JackDriver.h | 5 | ||||
-rw-r--r-- | src/Patchage.cpp | 34 | ||||
-rw-r--r-- | src/PatchageEvent.cpp | 112 | ||||
-rw-r--r-- | src/PatchageEvent.h | 43 | ||||
-rw-r--r-- | src/PatchagePort.h | 2 |
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 |