diff options
| -rw-r--r-- | muse/muse/audio.cpp | 2 | ||||
| -rw-r--r-- | muse/muse/driver/alsamidi.cpp | 181 | ||||
| -rw-r--r-- | muse/muse/driver/alsamidi.h | 32 | ||||
| -rw-r--r-- | muse/muse/driver/driver.h | 1 | ||||
| -rw-r--r-- | muse/muse/midififo.cpp | 1 | ||||
| -rw-r--r-- | 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 @@ -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;              } | 
