summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--muse/muse/audio.cpp2
-rw-r--r--muse/muse/driver/alsamidi.cpp181
-rw-r--r--muse/muse/driver/alsamidi.h32
-rw-r--r--muse/muse/driver/driver.h1
-rw-r--r--muse/muse/midififo.cpp1
-rw-r--r--muse/muse/route.cpp5
6 files changed, 152 insertions, 70 deletions
diff --git a/muse/muse/audio.cpp b/muse/muse/audio.cpp
index ee98f85f..124506a3 100644
--- a/muse/muse/audio.cpp
+++ b/muse/muse/audio.cpp
@@ -25,6 +25,7 @@
#include "globals.h"
#include "song.h"
#include "driver/audiodev.h"
+#include "driver/mididev.h"
#include "audioprefetch.h"
#include "audiowriteback.h"
#include "audio.h"
@@ -526,6 +527,7 @@ void Audio::process(unsigned frames, int jackState)
_pos += frames;
_curTickPos = _nextTickPos;
}
+ midiDriver->updateConnections();
}
//---------------------------------------------------------
diff --git a/muse/muse/driver/alsamidi.cpp b/muse/muse/driver/alsamidi.cpp
index be64eb48..ba3f303c 100644
--- a/muse/muse/driver/alsamidi.cpp
+++ b/muse/muse/driver/alsamidi.cpp
@@ -34,6 +34,34 @@ AlsaMidi alsaMidi;
AlsaMidi* midiDriver;
//---------------------------------------------------------
+// put
+// return true on fifo overflow
+//---------------------------------------------------------
+
+bool PortRouteFifo::put(const PortRoute& event)
+ {
+ if (size < PORT_ROUTE_FIFO_SIZE) {
+ fifo[wIndex] = event;
+ wIndex = (wIndex + 1) % PORT_ROUTE_FIFO_SIZE;
+ q_atomic_increment(&size);
+ return false;
+ }
+ return true;
+ }
+
+//---------------------------------------------------------
+// get
+//---------------------------------------------------------
+
+PortRoute PortRouteFifo::get()
+ {
+ PortRoute event(fifo[rIndex]);
+ rIndex = (rIndex + 1) % PORT_ROUTE_FIFO_SIZE;
+ q_atomic_decrement(&size);
+ return event;
+ }
+
+//---------------------------------------------------------
// AlsaMidi
//---------------------------------------------------------
@@ -330,89 +358,35 @@ void AlsaMidi::getOutputPollFd(struct pollfd** p, int* n)
//---------------------------------------------------------
// addConnection
// a new connection was added
+// called in MidiSeq context, FIFO synchronizes with
+// JACK callback
//---------------------------------------------------------
void AlsaMidi::addConnection(snd_seq_connect_t* ev)
{
Port rs(ev->sender.client, ev->sender.port);
Port rd(ev->dest.client, ev->dest.port);
-
- MidiOutPortList* opl = song->midiOutPorts();
- for (iMidiOutPort i = opl->begin(); i != opl->end(); ++i) {
- MidiOutPort* oport = *i;
- Port sPort = oport->alsaPort(0);
-
- if (sPort == rs) {
- RouteNode src(oport);
- RouteNode dst(rd, -1, RouteNode::MIDIPORT);
- Route r = Route(src, dst);
- if (oport->outRoutes()->indexOf(r) == -1)
- oport->outRoutes()->push_back(r);
- break;
- }
- }
-
- MidiInPortList* ipl = song->midiInPorts();
- for (iMidiInPort i = ipl->begin(); i != ipl->end(); ++i) {
- MidiInPort* iport = *i;
- Port dPort = iport->alsaPort(0);
-
- if (dPort == rd) {
- RouteNode src(rs, -1, RouteNode::MIDIPORT);
- RouteNode dst(iport);
- Route r = Route(src, dst);
- if (iport->inRoutes()->indexOf(r) == -1) {
-printf("add connection\n");
- iport->inRoutes()->push_back(r);
- }
- break;
- }
- }
+ PortRoute pr;
+ pr.src = rs;
+ pr.dst = rd;
+ addCon.put(pr);
}
//---------------------------------------------------------
// removeConnection
// a connection was removed
+// called in MidiSeq context, FIFO synchronizes with
+// JACK callback
//---------------------------------------------------------
void AlsaMidi::removeConnection(snd_seq_connect_t* ev)
{
Port rs(ev->sender.client, ev->sender.port);
Port rd(ev->dest.client, ev->dest.port);
-
- MidiInPortList* ipl = song->midiInPorts();
- for (iMidiInPort i = ipl->begin(); i != ipl->end(); ++i) {
- MidiInPort* iport = *i;
- Port dst = iport->alsaPort();
-
- if (dst == rd) {
- RouteList* irl = iport->outRoutes();
- for (iRoute r = irl->begin(); r != irl->end(); ++r) {
- if (!r->disconnected && (r->src.port == rs)) {
- iport->inRoutes()->erase(r);
- break;
- }
- }
- break;
- }
- }
-
- MidiOutPortList* opl = song->midiOutPorts();
- for (iMidiOutPort i = opl->begin(); i != opl->end(); ++i) {
- MidiOutPort* oport = *i;
- Port src = oport->alsaPort();
-
- if (src == rs) {
- RouteList* orl = oport->outRoutes();
- for (iRoute r = orl->begin(); r != orl->end(); ++r) {
- if (!r->disconnected && (r->dst.port == rd)) {
- orl->erase(r);
- break;
- }
- }
- break;
- }
- }
+ PortRoute pr;
+ pr.src = rs;
+ pr.dst = rd;
+ removeCon.put(pr);
}
//---------------------------------------------------------
@@ -673,4 +647,79 @@ bool AlsaMidi::putEvent(snd_seq_event_t* event)
return true;
}
+//---------------------------------------------------------
+// updateConnections
+// this is called in JACK callback context
+//---------------------------------------------------------
+
+void AlsaMidi::updateConnections()
+ {
+ while (!addCon.isEmpty()) {
+ PortRoute pr = addCon.get();
+ MidiOutPortList* opl = song->midiOutPorts();
+ for (iMidiOutPort i = opl->begin(); i != opl->end(); ++i) {
+ MidiOutPort* oport = *i;
+ Port sPort = oport->alsaPort(0);
+
+ if (sPort == pr.src) {
+ RouteNode src(oport);
+ RouteNode dst(pr.dst, -1, RouteNode::MIDIPORT);
+ Route r = Route(src, dst);
+ if (oport->outRoutes()->indexOf(r) == -1)
+ oport->outRoutes()->push_back(r);
+ break;
+ }
+ }
+
+ MidiInPortList* ipl = song->midiInPorts();
+ for (iMidiInPort i = ipl->begin(); i != ipl->end(); ++i) {
+ MidiInPort* iport = *i;
+ Port dPort = iport->alsaPort(0);
+
+ if (dPort == pr.dst) {
+ RouteNode src(pr.src, -1, RouteNode::MIDIPORT);
+ RouteNode dst(iport);
+ Route r = Route(src, dst);
+ if (iport->inRoutes()->indexOf(r) == -1)
+ iport->inRoutes()->push_back(r);
+ break;
+ }
+ }
+ }
+ while (!removeCon.isEmpty()) {
+ PortRoute pr = removeCon.get();
+
+ foreach(MidiInPort* iport, *(song->midiInPorts())) {
+ Port dst = iport->alsaPort();
+
+ if (dst == pr.dst) {
+ RouteList* irl = iport->inRoutes();
+ for (iRoute r = irl->begin(); r != irl->end(); ++r) {
+/*TODO*/ if (/*(!r->disconnected) &&*/ (r->src.port == pr.src)) {
+ iport->inRoutes()->erase(r);
+// printf("remove in connection\n");
+ break;
+ }
+ }
+ break;
+ }
+ }
+
+ foreach(MidiOutPort* oport, *(song->midiOutPorts())) {
+ Port src = oport->alsaPort();
+
+ if (src == pr.src) {
+ RouteList* orl = oport->outRoutes();
+ for (iRoute r = orl->begin(); r != orl->end(); ++r) {
+ if (/*(!r->disconnected) &&*/ (r->dst.port == pr.dst)) {
+ orl->erase(r);
+// printf("remove out connection\n");
+ break;
+ }
+ }
+ break;
+ }
+ }
+ }
+ }
diff --git a/muse/muse/driver/alsamidi.h b/muse/muse/driver/alsamidi.h
index 9c59f5dc..3073b63e 100644
--- a/muse/muse/driver/alsamidi.h
+++ b/muse/muse/driver/alsamidi.h
@@ -27,6 +27,34 @@
class MidiSeq;
class MidiEvent;
+#define PORT_ROUTE_FIFO_SIZE 16
+
+//---------------------------------------------------------
+// PortRoute
+//---------------------------------------------------------
+
+struct PortRoute {
+ Port src, dst;
+ };
+
+//---------------------------------------------------------
+// PortRouteFifo
+//---------------------------------------------------------
+
+class PortRouteFifo {
+ PortRoute fifo[PORT_ROUTE_FIFO_SIZE];
+ volatile int size;
+ int wIndex;
+ int rIndex;
+
+ public:
+ PortRouteFifo() { clear(); }
+ bool put(const PortRoute& event); // returns true on fifo overflow
+ PortRoute get();
+ bool isEmpty() const { return size == 0; }
+ void clear() { size = 0, wIndex = 0, rIndex = 0; }
+ };
+
//---------------------------------------------------------
// AlsaMidi
//---------------------------------------------------------
@@ -38,6 +66,9 @@ class AlsaMidi : public Driver {
void addConnection(snd_seq_connect_t* ev);
bool putEvent(snd_seq_event_t* event);
+ PortRouteFifo addCon;
+ PortRouteFifo removeCon;
+
public:
AlsaMidi();
virtual bool init();
@@ -61,6 +92,7 @@ class AlsaMidi : public Driver {
void read(MidiSeq*); // process events
void write();
+ void updateConnections();
};
extern AlsaMidi alsaMidi;
diff --git a/muse/muse/driver/driver.h b/muse/muse/driver/driver.h
index a165cea0..c8bbfc7f 100644
--- a/muse/muse/driver/driver.h
+++ b/muse/muse/driver/driver.h
@@ -57,6 +57,7 @@ class Driver {
virtual bool connect(Port, Port) = 0;
virtual bool disconnect(Port, Port) = 0;
virtual void putEvent(Port, const MidiEvent&) = 0;
+ virtual void updateConnections() {}
};
#endif
diff --git a/muse/muse/midififo.cpp b/muse/muse/midififo.cpp
index 51b6fd3a..4bb43346 100644
--- a/muse/muse/midififo.cpp
+++ b/muse/muse/midififo.cpp
@@ -33,7 +33,6 @@ bool MidiFifo::put(const MidiEvent& event)
q_atomic_increment(&size);
return false;
}
-printf("fifo overflow size %d\n", size);
return true;
}
diff --git a/muse/muse/route.cpp b/muse/muse/route.cpp
index c75a00da..127a2f4c 100644
--- a/muse/muse/route.cpp
+++ b/muse/muse/route.cpp
@@ -308,12 +308,11 @@ bool RouteNode::operator==(const RouteNode& a) const
return false;
switch(type) {
case TRACK:
- case MIDIPORT:
return (channel == a.channel) && (track == a.track);
+ case MIDIPORT:
case JACKMIDIPORT:
- return port == a.port;
case AUDIOPORT:
- return (channel == a.channel) && (port == a.port);
+ return port == a.port;
case AUXPLUGIN:
return plugin == a.plugin;
}