From 34de91a9bd25d150509912607543235cbee9fa9d Mon Sep 17 00:00:00 2001 From: Werner Schweer Date: Thu, 9 Nov 2006 22:02:25 +0000 Subject: midi routing fixes --- muse/muse/audio.cpp | 2 + muse/muse/driver/alsamidi.cpp | 181 +++++++++++++++++++++++++++--------------- muse/muse/driver/alsamidi.h | 32 ++++++++ muse/muse/driver/driver.h | 1 + muse/muse/midififo.cpp | 1 - muse/muse/route.cpp | 5 +- 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 @@ -33,6 +33,34 @@ static const unsigned int outCap = SND_SEQ_PORT_CAP_SUBS_WRITE; 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; } -- cgit v1.2.3