diff options
author | David Robillard <d@drobilla.net> | 2010-12-15 00:23:38 +0000 |
---|---|---|
committer | David Robillard <d@drobilla.net> | 2010-12-15 00:23:38 +0000 |
commit | ba2863f012866398efab12b6b3e6a113d5eb60bd (patch) | |
tree | d6eeb5c5e009bc3f42bd354afa25cfa684ed212d /src | |
parent | fb6cff045de58c304527efea4e85d53fd80d2758 (diff) | |
download | patchage-ba2863f012866398efab12b6b3e6a113d5eb60bd.tar.gz patchage-ba2863f012866398efab12b6b3e6a113d5eb60bd.tar.bz2 patchage-ba2863f012866398efab12b6b3e6a113d5eb60bd.zip |
Fix removal of ALSA duplex ports (remove both corresponding canvas ports).
Use simpler (and seemingly less lockup prone) blocking ALSA sequencer event API.
Only use a ringbuffer for JACK driver.
Reduce memory usage.
git-svn-id: http://svn.drobilla.net/lad/trunk/patchage@2690 a436a847-0d15-0410-975c-d299462d15a1
Diffstat (limited to 'src')
-rw-r--r-- | src/AlsaDriver.cpp | 134 | ||||
-rw-r--r-- | src/AlsaDriver.hpp | 10 | ||||
-rw-r--r-- | src/Driver.hpp | 15 | ||||
-rw-r--r-- | src/JackDbusDriver.cpp | 3 | ||||
-rw-r--r-- | src/JackDriver.cpp | 16 | ||||
-rw-r--r-- | src/JackDriver.hpp | 5 | ||||
-rw-r--r-- | src/PatchageCanvas.cpp | 10 | ||||
-rw-r--r-- | src/PortID.hpp | 14 |
8 files changed, 93 insertions, 114 deletions
diff --git a/src/AlsaDriver.cpp b/src/AlsaDriver.cpp index 19ebfa8..f044ceb 100644 --- a/src/AlsaDriver.cpp +++ b/src/AlsaDriver.cpp @@ -30,8 +30,7 @@ using namespace std; using namespace FlowCanvas; AlsaDriver::AlsaDriver(Patchage* app) - : Driver(128) - , _app(app) + : _app(app) , _seq(NULL) { } @@ -49,9 +48,7 @@ AlsaDriver::~AlsaDriver() void AlsaDriver::attach(bool /*launch_daemon*/) { - int ret = snd_seq_open(&_seq, "default", - SND_SEQ_OPEN_DUPLEX, - SND_SEQ_NONBLOCK); + int ret = snd_seq_open(&_seq, "default", SND_SEQ_OPEN_DUPLEX, 0); if (ret) { _app->status_msg("[ALSA] Unable to attach"); _seq = NULL; @@ -426,19 +423,14 @@ AlsaDriver::disconnect(boost::shared_ptr<PatchagePort> src_port, boost::shared_p bool AlsaDriver::create_refresh_port() { - // Mostly lifted from alsa-patch-bay, (C) 2002 Robert Ham, released under GPL - - int ret; snd_seq_port_info_t* port_info; - snd_seq_port_info_alloca(&port_info); snd_seq_port_info_set_name(port_info, "System Announcement Reciever"); + snd_seq_port_info_set_type(port_info, SND_SEQ_PORT_TYPE_APPLICATION); snd_seq_port_info_set_capability(port_info, SND_SEQ_PORT_CAP_WRITE|SND_SEQ_PORT_CAP_SUBS_WRITE|SND_SEQ_PORT_CAP_NO_EXPORT); - snd_seq_port_info_set_type(port_info, SND_SEQ_PORT_TYPE_APPLICATION); - - ret = snd_seq_create_port(_seq, port_info); + int ret = snd_seq_create_port(_seq, port_info); if (ret) { Raul::error << "[ALSA] Error creating port: " << snd_strerror(ret) << endl; return false; @@ -449,7 +441,6 @@ AlsaDriver::create_refresh_port() snd_seq_port_info_get_port(port_info), SND_SEQ_CLIENT_SYSTEM, SND_SEQ_PORT_SYSTEM_ANNOUNCE); - if (ret) { Raul::error << "[ALSA] Could not connect to system announcer port: " << snd_strerror(ret) << endl; @@ -477,77 +468,60 @@ AlsaDriver::_refresh_main() return; } - int ret = 0; - int nfds = snd_seq_poll_descriptors_count(_seq, POLLIN); - struct pollfd* pfds = new struct pollfd[nfds]; - unsigned short* revents = new unsigned short[nfds]; - - snd_seq_poll_descriptors(_seq, pfds, nfds, POLLIN); + int caps = 0; - while (true) { - ret = poll(pfds, nfds, -1); - if (ret == -1) { - if (errno == EINTR) - continue; + snd_seq_port_info_t* pinfo; + snd_seq_port_info_alloca(&pinfo); - Raul::error << "[ALSA] Error polling sequencer: " << strerror(errno) << endl; - continue; + snd_seq_event_t* ev; + while (snd_seq_event_input(_seq, &ev) > 0) { + assert(ev); + + Glib::Mutex::Lock lock(_events_mutex); + + switch (ev->type) { + case SND_SEQ_EVENT_PORT_SUBSCRIBED: + _events.push(PatchageEvent(PatchageEvent::CONNECTION, + ev->data.connect.sender, ev->data.connect.dest)); + break; + case SND_SEQ_EVENT_PORT_UNSUBSCRIBED: + _events.push(PatchageEvent(PatchageEvent::DISCONNECTION, + ev->data.connect.sender, ev->data.connect.dest)); + break; + case SND_SEQ_EVENT_PORT_START: + snd_seq_get_any_port_info(_seq, ev->data.addr.client, ev->data.addr.port, pinfo); + caps = snd_seq_port_info_get_capability(pinfo); + _events.push(PatchageEvent(PatchageEvent::PORT_CREATION, + PortID(ev->data.addr, (caps & SND_SEQ_PORT_CAP_READ)))); + break; + case SND_SEQ_EVENT_PORT_EXIT: + // Note: getting caps at this point does not work + // Delete both inputs and outputs (in case this is a duplex port) + _events.push(PatchageEvent(PatchageEvent::PORT_DESTRUCTION, + PortID(ev->data.addr, true))); + _events.push(PatchageEvent(PatchageEvent::PORT_DESTRUCTION, + PortID(ev->data.addr, false))); + break; + case SND_SEQ_EVENT_CLIENT_CHANGE: + case SND_SEQ_EVENT_CLIENT_EXIT: + case SND_SEQ_EVENT_CLIENT_START: + case SND_SEQ_EVENT_PORT_CHANGE: + case SND_SEQ_EVENT_RESET: + default: + //_events.push(PatchageEvent(PatchageEvent::REFRESH)); + break; } + } +} - ret = snd_seq_poll_descriptors_revents(_seq, pfds, nfds, revents); - if (ret) { - Raul::error << "[ALSA] Error getting sequencer poll events: " - << snd_strerror(ret) << endl; - continue; - } - snd_seq_port_info_t* pinfo; - snd_seq_port_info_alloca(&pinfo); - int caps = 0; - - for (int i = 0; i < nfds; ++i) { - if (revents[i] > 0) { - snd_seq_event_t* ev; - snd_seq_event_input(_seq, &ev); - if (!ev) - continue; - - switch (ev->type) { - case SND_SEQ_EVENT_PORT_SUBSCRIBED: - _events.push(PatchageEvent(PatchageEvent::CONNECTION, - ev->data.connect.sender, ev->data.connect.dest)); - break; - case SND_SEQ_EVENT_PORT_UNSUBSCRIBED: - _events.push(PatchageEvent(PatchageEvent::DISCONNECTION, - ev->data.connect.sender, ev->data.connect.dest)); - break; - case SND_SEQ_EVENT_PORT_START: - snd_seq_port_info_set_client(pinfo, ev->data.addr.client); - caps = snd_seq_port_info_get_capability(pinfo); - _events.push(PatchageEvent(PatchageEvent::PORT_CREATION, - PortID(ev->data.addr, (caps & SND_SEQ_PORT_CAP_READ)))); - break; - case SND_SEQ_EVENT_PORT_EXIT: - snd_seq_port_info_set_client(pinfo, ev->data.addr.client); - caps = snd_seq_port_info_get_capability(pinfo); - _events.push(PatchageEvent(PatchageEvent::PORT_DESTRUCTION, - PortID(ev->data.addr, (caps & SND_SEQ_PORT_CAP_READ)))); - break; - // TODO: What should happen for these? - case SND_SEQ_EVENT_PORT_CHANGE: - case SND_SEQ_EVENT_CLIENT_START: - case SND_SEQ_EVENT_CLIENT_EXIT: - case SND_SEQ_EVENT_CLIENT_CHANGE: - case SND_SEQ_EVENT_RESET: - default: - //_events.push(PatchageEvent(PatchageEvent::REFRESH)); - break; - } - } - } +void +AlsaDriver::process_events(Patchage* app) +{ + Glib::Mutex::Lock lock(_events_mutex); + while (!_events.empty()) { + PatchageEvent& ev = _events.front(); + ev.execute(app); + _events.pop(); } - - delete[] pfds; - delete[] revents; } - diff --git a/src/AlsaDriver.hpp b/src/AlsaDriver.hpp index ba20d95..23d635f 100644 --- a/src/AlsaDriver.hpp +++ b/src/AlsaDriver.hpp @@ -18,9 +18,12 @@ #ifndef PATCHAGE_ALSADRIVER_HPP #define PATCHAGE_ALSADRIVER_HPP +#include <string> +#include <queue> + #include <alsa/asoundlib.h> #include <pthread.h> -#include <string> + #include "Driver.hpp" class Patchage; class PatchagePort; @@ -53,6 +56,8 @@ public: void print_addr(snd_seq_addr_t addr); + void process_events(Patchage* app); + private: void refresh_ports(); void refresh_connections(); @@ -85,6 +90,9 @@ private: Patchage* _app; snd_seq_t* _seq; pthread_t _refresh_thread; + + Glib::Mutex _events_mutex; + std::queue<PatchageEvent> _events; }; #endif // PATCHAGE_ALSADRIVER_HPP diff --git a/src/Driver.hpp b/src/Driver.hpp index debcbb8..ae8d452 100644 --- a/src/Driver.hpp +++ b/src/Driver.hpp @@ -31,13 +31,7 @@ class Driver { public: virtual ~Driver() {} - virtual void process_events(Patchage* app) { - while (!events().empty()) { - PatchageEvent& ev = events().front(); - ev.execute(app); - events().pop(); - } - } + virtual void process_events(Patchage* app) = 0; virtual void attach(bool launch_daemon) = 0; virtual void detach() = 0; @@ -56,15 +50,8 @@ public: virtual bool disconnect(boost::shared_ptr<PatchagePort> src_port, boost::shared_ptr<PatchagePort> dst_port) = 0; - Raul::SRSWQueue<PatchageEvent>& events() { return _events; } - sigc::signal<void> signal_attached; sigc::signal<void> signal_detached; - -protected: - Driver(size_t event_queue_size) : _events(event_queue_size) {} - - Raul::SRSWQueue<PatchageEvent> _events; }; diff --git a/src/JackDbusDriver.cpp b/src/JackDbusDriver.cpp index b2ee169..15ee5f0 100644 --- a/src/JackDbusDriver.cpp +++ b/src/JackDbusDriver.cpp @@ -63,8 +63,7 @@ using namespace FlowCanvas; JackDriver::JackDriver(Patchage* app) - : Driver(128) - , _app(app) + : _app(app) , _dbus_connection(0) , _server_responding(false) , _server_started(false) diff --git a/src/JackDriver.cpp b/src/JackDriver.cpp index 0ebdb98..7bdcb72 100644 --- a/src/JackDriver.cpp +++ b/src/JackDriver.cpp @@ -36,9 +36,9 @@ using namespace FlowCanvas; JackDriver::JackDriver(Patchage* app) - : Driver(128) - , _app(app) + : _app(app) , _client(NULL) + , _events(128) , _is_activated(false) , _xruns(0) , _xrun_delay(0) @@ -611,3 +611,15 @@ JackDriver::reset_max_dsp_load() jack_reset_max_delayed_usecs(_client); } + +void +JackDriver::process_events(Patchage* app) +{ + while (!_events.empty()) { + PatchageEvent& ev = _events.front(); + ev.execute(app); + _events.pop(); + } +} + + diff --git a/src/JackDriver.hpp b/src/JackDriver.hpp index 03a758a..bbff422 100644 --- a/src/JackDriver.hpp +++ b/src/JackDriver.hpp @@ -88,8 +88,9 @@ public: float get_max_dsp_load(); -private: + void process_events(Patchage* app); +private: boost::shared_ptr<PatchagePort> create_port( boost::shared_ptr<PatchageModule> parent, jack_port_t* port); @@ -109,6 +110,8 @@ private: Patchage* _app; jack_client_t* _client; + Raul::SRSWQueue<PatchageEvent> _events; + Glib::Mutex _shutdown_mutex; bool _is_activated; diff --git a/src/PatchageCanvas.cpp b/src/PatchageCanvas.cpp index 4f6a12e..f3ffca0 100644 --- a/src/PatchageCanvas.cpp +++ b/src/PatchageCanvas.cpp @@ -115,8 +115,8 @@ PatchageCanvas::find_port(const PortID& id) && pp->alsa_addr()->client == id.id.alsa_addr.client && pp->alsa_addr()->port == id.id.alsa_addr.port) { if ((module->type() == InputOutput) - || (id.is_input && (module->type() == Input)) - || (!id.is_input && (module->type() == Output))) { + || (id.id.is_input && (module->type() == Input)) + || (!id.id.is_input && (module->type() == Output))) { return pp; } } @@ -158,10 +158,8 @@ PatchageCanvas::connect(boost::shared_ptr<Connectable> port1, boost::shared_ptr< void PatchageCanvas::disconnect(boost::shared_ptr<Connectable> port1, boost::shared_ptr<Connectable> port2) { - boost::shared_ptr<PatchagePort> input - = boost::dynamic_pointer_cast<PatchagePort>(port1); - boost::shared_ptr<PatchagePort> output - = boost::dynamic_pointer_cast<PatchagePort>(port2); + boost::shared_ptr<PatchagePort> input = boost::dynamic_pointer_cast<PatchagePort>(port1); + boost::shared_ptr<PatchagePort> output = boost::dynamic_pointer_cast<PatchagePort>(port2); if (!input || !output) return; diff --git a/src/PortID.hpp b/src/PortID.hpp index 82a892a..84cc28e 100644 --- a/src/PortID.hpp +++ b/src/PortID.hpp @@ -43,20 +43,18 @@ struct PortID { #ifdef HAVE_ALSA PortID(snd_seq_addr_t addr, bool in) - : type(ALSA_ADDR) { id.alsa_addr = addr; is_input = in; } - - bool is_input; + : type(ALSA_ADDR) { id.alsa_addr = addr; id.is_input = in; } #endif union { #ifdef USE_LIBJACK - struct { - jack_port_id_t jack_id; - int jack_flags; - }; + jack_port_id_t jack_id; #endif #ifdef HAVE_ALSA - snd_seq_addr_t alsa_addr; + struct { + snd_seq_addr_t alsa_addr; + bool is_input : 1; + }; #endif } id; }; |