summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2010-12-15 00:23:38 +0000
committerDavid Robillard <d@drobilla.net>2010-12-15 00:23:38 +0000
commitba2863f012866398efab12b6b3e6a113d5eb60bd (patch)
treed6eeb5c5e009bc3f42bd354afa25cfa684ed212d
parentfb6cff045de58c304527efea4e85d53fd80d2758 (diff)
downloadpatchage-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
-rw-r--r--src/AlsaDriver.cpp134
-rw-r--r--src/AlsaDriver.hpp10
-rw-r--r--src/Driver.hpp15
-rw-r--r--src/JackDbusDriver.cpp3
-rw-r--r--src/JackDriver.cpp16
-rw-r--r--src/JackDriver.hpp5
-rw-r--r--src/PatchageCanvas.cpp10
-rw-r--r--src/PortID.hpp14
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;
};