From d3c3d0b05fb0ab210835c59707a49248e1262b8c Mon Sep 17 00:00:00 2001 From: Werner Schweer Date: Mon, 23 Oct 2006 12:36:58 +0000 Subject: updates --- muse/muse/audio.cpp | 4 +- muse/muse/driver/alsamidi.h | 5 +- muse/muse/driver/audiodev.h | 3 +- muse/muse/driver/driver.h | 3 + muse/muse/driver/dummyaudio.cpp | 1 + muse/muse/driver/jack.cpp | 29 +++++++ muse/muse/driver/jackaudio.h | 4 +- muse/muse/midi.cpp | 152 +------------------------------- muse/muse/midievent.h | 73 ---------------- muse/muse/midieventbase.h | 73 ++++++++++++++++ muse/muse/midioutport.cpp | 186 ++++++++++++++++++++++++++++++++++------ muse/muse/midioutport.h | 2 + muse/muse/undo.cpp | 4 + 13 files changed, 281 insertions(+), 258 deletions(-) delete mode 100644 muse/muse/midievent.h create mode 100644 muse/muse/midieventbase.h diff --git a/muse/muse/audio.cpp b/muse/muse/audio.cpp index ce55f2bd..e6e84ab6 100644 --- a/muse/muse/audio.cpp +++ b/muse/muse/audio.cpp @@ -460,7 +460,9 @@ void Audio::process(unsigned frames) } } - processMidi(frames); + MidiOutPortList* mol = song->midiOutPorts(); + for (iMidiOutPort i = mol->begin(); i != mol->end(); ++i) + audioDriver->startMidiCycle(mol->jackPort(0)); GroupList* gl = song->groups(); SynthIList* sl = song->syntis(); diff --git a/muse/muse/driver/alsamidi.h b/muse/muse/driver/alsamidi.h index 9e5e54f5..b68c4783 100644 --- a/muse/muse/driver/alsamidi.h +++ b/muse/muse/driver/alsamidi.h @@ -40,6 +40,7 @@ class AlsaMidi : public Driver { void removeConnection(snd_seq_connect_t* ev); void addConnection(snd_seq_connect_t* ev); + bool putEvent(snd_seq_event_t* event); public: AlsaMidi(); @@ -58,15 +59,13 @@ class AlsaMidi : public Driver { virtual bool connect(Port, Port); virtual bool disconnect(Port, Port); + virtual void putEvent(Port, const MidiEvent&); void getInputPollFd(struct pollfd**, int* n); void getOutputPollFd(struct pollfd**, int* n); void read(MidiSeq*); // process events void write(); - - void putEvent(Port, const MidiEvent&); - bool putEvent(snd_seq_event_t* event); }; extern AlsaMidi alsaMidi; diff --git a/muse/muse/driver/audiodev.h b/muse/muse/driver/audiodev.h index 416f91c0..5196375c 100644 --- a/muse/muse/driver/audiodev.h +++ b/muse/muse/driver/audiodev.h @@ -37,7 +37,7 @@ class AudioDriver : public Driver { virtual bool restart() { return false; } // return true on error virtual void stop () = 0; virtual unsigned framePos() const = 0; - virtual float* getBuffer(void* port, unsigned long nframes) = 0; + virtual float* getBuffer(Port, unsigned long nframes) = 0; virtual void registerClient() = 0; virtual Port registerOutPort(const QString& name, bool midi) = 0; virtual Port registerInPort(const QString& name, bool midi) = 0; @@ -49,6 +49,7 @@ class AudioDriver : public Driver { virtual void seekTransport(unsigned frame) = 0; virtual void setFreewheel(bool f) = 0; virtual void graphChanged() {} + virtual void startMidiCycle(Port) {} }; #endif diff --git a/muse/muse/driver/driver.h b/muse/muse/driver/driver.h index bd6a826a..d7147b52 100644 --- a/muse/muse/driver/driver.h +++ b/muse/muse/driver/driver.h @@ -28,6 +28,8 @@ struct PortName { QString name; }; +class MidiEvent; + //--------------------------------------------------------- // Driver // abstract driver base class; used for midi and @@ -54,6 +56,7 @@ class Driver { virtual bool connect(Port, Port) = 0; virtual bool disconnect(Port, Port) = 0; virtual bool equal(Port, Port) = 0; + virtual void putEvent(Port, const MidiEvent&) = 0; }; #endif diff --git a/muse/muse/driver/dummyaudio.cpp b/muse/muse/driver/dummyaudio.cpp index 2aa5a709..a55a69bb 100644 --- a/muse/muse/driver/dummyaudio.cpp +++ b/muse/muse/driver/dummyaudio.cpp @@ -143,6 +143,7 @@ class DummyAudio : public AudioDriver { virtual bool equal(Port a, Port b) { return a == b; } + virtual void putEvent(Port, const MidiEvent&) {} }; DummyAudio* dummyAudio; diff --git a/muse/muse/driver/jack.cpp b/muse/muse/driver/jack.cpp index 2bccbfcf..57a5348f 100644 --- a/muse/muse/driver/jack.cpp +++ b/muse/muse/driver/jack.cpp @@ -794,3 +794,32 @@ bool initJackAudio() return false; } +//--------------------------------------------------------- +// putEvent +//--------------------------------------------------------- + +void JackAudio::putEvent(Port p, const MidiEvent& e) + { + if (midiOutputTrace) { + printf("MidiOut<%s>: jackMidi: ", portName(p).toLatin1().data()); + e.dump(); + } + unsigned char* p = jack_midi_event_reserve(pb, pos, 3, segmentSize); + if (p == 0) { + fprintf(stderr, "JackMidi: buffer overflow, event lost\n"); + return; + } + p[0] = e.dataA(); + p[1] + } + +//--------------------------------------------------------- +// startMidiCycle +//--------------------------------------------------------- + +void JackAudio::startMidiCycle(Port port) + { + void* port_buf = jack_port_get_buffer(port, segmentSize); + jack_midi_clear_buffer(port_buf, segmentSize); + } + diff --git a/muse/muse/driver/jackaudio.h b/muse/muse/driver/jackaudio.h index 4b76cb80..c4d0cdaa 100644 --- a/muse/muse/driver/jackaudio.h +++ b/muse/muse/driver/jackaudio.h @@ -44,7 +44,7 @@ class JackAudio : public AudioDriver { virtual void zeroClientPtr() { _client = 0; } virtual unsigned framePos() const; - virtual float* getBuffer(void* port, unsigned long nframes) { + virtual float* getBuffer(Port port, unsigned long nframes) { return (float*)jack_port_get_buffer((jack_port_t*)port, nframes); } @@ -78,6 +78,8 @@ class JackAudio : public AudioDriver { } void graphChanged(); virtual bool equal(Port a, Port b) { return a == b; } + virtual void putEvent(Port, const MidiEvent&); + virutal void startMidiCycle(Port); }; #endif diff --git a/muse/muse/midi.cpp b/muse/muse/midi.cpp index 9741d9fb..8e15b9d4 100644 --- a/muse/muse/midi.cpp +++ b/muse/muse/midi.cpp @@ -27,6 +27,7 @@ #include "midictrl.h" #include "audio.h" #include "driver/mididev.h" +#include "driver/audiodev.h" #include "wave.h" #include "synth.h" #include "sync.h" @@ -666,154 +667,3 @@ void Audio::processMidi(unsigned frames) midiBusy = false; } -//--------------------------------------------------------- -// process -// "play" events for this process cycle -// if (from != to) then transport state is "playing" -//--------------------------------------------------------- - -void MidiOutPort::process(unsigned from, unsigned to, const Pos& pos, unsigned frames) - { - // - // erase already played events: - // - _playEvents.erase(_playEvents.begin(), _nextPlayEvent); - playFifo(); - - if (mute()) - return; - - // collect port controller - if (from != to) { - CtrlList* cl = controller(); - for (iCtrl ic = cl->begin(); ic != cl->end(); ++ic) { - Ctrl* c = ic->second; - iCtrlVal is = c->lower_bound(from); - iCtrlVal ie = c->lower_bound(to); - for (iCtrlVal ic = is; ic != ie; ++ic) { - unsigned frame = AL::tempomap.tick2frame(ic->first); - Event ev(Controller); - ev.setA(c->id()); - ev.setB(ic->second.i); - _playEvents.add(MidiEvent(frame, -1, ev)); - } - } - } - - int portVelo = 0; - for (int ch = 0; ch < MIDI_CHANNELS; ++ch) { - MidiChannel* mc = channel(ch); - - if (mc->mute() || mc->noInRoute()) - continue; - // collect channel controller - if (from != to) { - CtrlList* cl = mc->controller(); - for (iCtrl ic = cl->begin(); ic != cl->end(); ++ic) { - Ctrl* c = ic->second; - iCtrlVal is = c->lower_bound(from); - iCtrlVal ie = c->lower_bound(to); - for (; is != ie; ++is) { - unsigned frame = AL::tempomap.tick2frame(is->first); - Event ev(Controller); - ev.setA(c->id()); - ev.setB(is->second.i); - _playEvents.add(MidiEvent(frame, ch, ev)); - } - } - } - - // Collect midievents from all input tracks for outport - RouteList* rl = mc->inRoutes(); - for (iRoute i = rl->begin(); i != rl->end(); ++i) { - MidiTrackBase* track = (MidiTrackBase*)i->track; - if (track->isMute()) - continue; - MPEventList el; - track->getEvents(from, to, 0, &el); - int velo = 0; - for (iMPEvent i = el.begin(); i != el.end(); ++i) { - MidiEvent ev = *i; - ev.setChannel(ch); - _playEvents.insert(ev); - if (ev.type() == ME_NOTEON) - velo += ev.dataB(); - } - mc->addMidiMeter(velo); - portVelo += velo; - } - } - addMidiMeter(portVelo); - - // TODO: maybe this copying can be avoided - // - MPEventList il; - for (iMPEvent i = _playEvents.begin(); i != _playEvents.end(); ++i) { - il.add(*i); - } - _playEvents.clear(); - pipeline()->apply(from, to, &il, &_playEvents); - - _nextPlayEvent = _playEvents.begin(); - - // - // route events to destination - // - - if (_playEvents.empty()) - return; - - //printf("_playEvents.size() == %d\n", _playEvents.size()); - unsigned endFrame = pos.frame() + frames + audio->getFrameOffset(); - for (iRoute r = _outRoutes.begin(); r != _outRoutes.end(); ++r) { - switch (r->type) { - - // - // Send events to software synthesizer - // - case Route::SYNTIPORT: { - SynthI* s = (SynthI*)(r->track); - MPEventList* el = s->playEvents(); - iMPEvent is = _playEvents.begin(); - iMPEvent ie = _playEvents.end(); - - for (; is != ie; ++is) { - if ((from != to) && (is->time() >= endFrame)) { - break; - } - - el->insert(*is); - _nextPlayEvent = is; - _nextPlayEvent++; - } - } - break; - - // - // Send events to midi port - // - case Route::MIDIPORT: { - //playEventList(); - for (iMPEvent ev = _playEvents.begin(); ev != _playEvents.end(); ev++) { - if ((from != to) && (ev->time() >= endFrame)) { - break; - } - - midiDriver->putEvent(alsaPort(), *ev); - _nextPlayEvent = ev; - _nextPlayEvent++; - } - } - break; - - - // Invalid routetypes to send midi events to - should not happen - case Route::AUDIOPORT: - case Route::TRACK: - default: - printf("Error - invalid routetype\n"); - break; - } - } - } - diff --git a/muse/muse/midievent.h b/muse/muse/midievent.h deleted file mode 100644 index 93cb5529..00000000 --- a/muse/muse/midievent.h +++ /dev/null @@ -1,73 +0,0 @@ -//============================================================================= -// MusE -// Linux Music Editor -// $Id:$ -// -// Copyright (C) 2002-2006 by Werner Schweer and others -// -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License version 2. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -//============================================================================= - -#ifndef __MIDI_EVENT_H__ -#define __MIDI_EVENT_H__ - -#include "eventbase.h" - -//--------------------------------------------------------- -// MidiEventBase -//--------------------------------------------------------- - -class MidiEventBase : public EventBase { - int a, b, c; // pitch, velo-on, velo-off - EvData edata; - - virtual EventBase* clone() { return new MidiEventBase(*this); } - - public: - MidiEventBase(EventType t); - virtual ~MidiEventBase() {} - - virtual bool isNote() const { return type() == Note; } - virtual bool isNoteOff() const; - virtual bool isNoteOff(const Event&) const; - virtual int pitch() const { return a; } - virtual int program() const { return a; } - virtual int cntrl() const { return a; } - virtual int dataA() const { return a; } - virtual void setA(int val) { a = val; } - virtual void setPitch(int v) { a = v; } - - virtual int cntrlVal() const { return b; } - virtual int dataB() const { return b; } - virtual int velo() const { return b; } - virtual void setB(int val) { b = val; } - virtual void setVelo(int v) { b = v; } - - virtual int veloOff() const { return c; } - virtual int dataC() const { return c; } - virtual void setC(int val) { c = val; } - virtual void setVeloOff(int v) { c = v; } - - virtual const unsigned char* data() const { return edata.data; } - virtual int dataLen() const { return edata.dataLen; } - virtual void setData(const unsigned char* data, int len) { edata.setData(data, len); } - virtual const EvData eventData() const { return edata; } - - virtual void dump(int n = 0) const; - virtual void read(QDomNode); - virtual void write(Xml&, const Pos& offset) const; - virtual EventBase* mid(unsigned, unsigned); - }; - -#endif - diff --git a/muse/muse/midieventbase.h b/muse/muse/midieventbase.h new file mode 100644 index 00000000..93cb5529 --- /dev/null +++ b/muse/muse/midieventbase.h @@ -0,0 +1,73 @@ +//============================================================================= +// MusE +// Linux Music Editor +// $Id:$ +// +// Copyright (C) 2002-2006 by Werner Schweer and others +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License version 2. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +//============================================================================= + +#ifndef __MIDI_EVENT_H__ +#define __MIDI_EVENT_H__ + +#include "eventbase.h" + +//--------------------------------------------------------- +// MidiEventBase +//--------------------------------------------------------- + +class MidiEventBase : public EventBase { + int a, b, c; // pitch, velo-on, velo-off + EvData edata; + + virtual EventBase* clone() { return new MidiEventBase(*this); } + + public: + MidiEventBase(EventType t); + virtual ~MidiEventBase() {} + + virtual bool isNote() const { return type() == Note; } + virtual bool isNoteOff() const; + virtual bool isNoteOff(const Event&) const; + virtual int pitch() const { return a; } + virtual int program() const { return a; } + virtual int cntrl() const { return a; } + virtual int dataA() const { return a; } + virtual void setA(int val) { a = val; } + virtual void setPitch(int v) { a = v; } + + virtual int cntrlVal() const { return b; } + virtual int dataB() const { return b; } + virtual int velo() const { return b; } + virtual void setB(int val) { b = val; } + virtual void setVelo(int v) { b = v; } + + virtual int veloOff() const { return c; } + virtual int dataC() const { return c; } + virtual void setC(int val) { c = val; } + virtual void setVeloOff(int v) { c = v; } + + virtual const unsigned char* data() const { return edata.data; } + virtual int dataLen() const { return edata.dataLen; } + virtual void setData(const unsigned char* data, int len) { edata.setData(data, len); } + virtual const EvData eventData() const { return edata; } + + virtual void dump(int n = 0) const; + virtual void read(QDomNode); + virtual void write(Xml&, const Pos& offset) const; + virtual EventBase* mid(unsigned, unsigned); + }; + +#endif + diff --git a/muse/muse/midioutport.cpp b/muse/muse/midioutport.cpp index bdad88cc..3d96780f 100644 --- a/muse/muse/midioutport.cpp +++ b/muse/muse/midioutport.cpp @@ -21,6 +21,7 @@ #include "song.h" #include "midiplugin.h" #include "midictrl.h" +#include "al/tempo.h" #include "al/xml.h" #include "driver/mididev.h" #include "driver/audiodev.h" @@ -153,7 +154,7 @@ void MidiOutPort::putEvent(const MidiEvent& ev) } if (a == CTRL_PITCH) { - midiDriver->putEvent(alsaPort(), MidiEvent(0, chn, ME_PITCHBEND, b, 0)); + routeEvent(MidiEvent(0, chn, ME_PITCHBEND, b, 0)); return; } if (a == CTRL_PROGRAM) { @@ -163,10 +164,10 @@ void MidiOutPort::putEvent(const MidiEvent& ev) int lb = (b >> 8) & 0xff; int pr = b & 0x7f; if (hb != 0xff) - midiDriver->putEvent(alsaPort(), MidiEvent(0, chn, ME_CONTROLLER, CTRL_HBANK, hb)); + routeEvent(MidiEvent(0, chn, ME_CONTROLLER, CTRL_HBANK, hb)); if (lb != 0xff) midiDriver->putEvent(alsaPort(), MidiEvent(0, chn, ME_CONTROLLER, CTRL_LBANK, lb)); - midiDriver->putEvent(alsaPort(), MidiEvent(0, chn, ME_PROGRAM, pr, 0)); + routeEvent(MidiEvent(0, chn, ME_PROGRAM, pr, 0)); return; // } } @@ -178,63 +179,63 @@ void MidiOutPort::putEvent(const MidiEvent& ev) sysex[4] = b & 0x7f; sysex[5] = (b >> 7) & 0x7f; MidiEvent e(ev.time(), ME_SYSEX, sysex, 6); - midiDriver->putEvent(alsaPort(), e); + routeEvent(e); return; } #if 1 // if ALSA cannot handle RPN NRPN etc. if (a < 0x1000) { // 7 Bit Controller //putMidiEvent(MidiEvent(0, chn, ME_CONTROLLER, a, b)); - midiDriver->putEvent(alsaPort(), ev); + routeEvent(ev); } else if (a < 0x20000) { // 14 bit high resolution controller int ctrlH = (a >> 8) & 0x7f; int ctrlL = a & 0x7f; int dataH = (b >> 7) & 0x7f; int dataL = b & 0x7f; - midiDriver->putEvent(alsaPort(), MidiEvent(0, chn, ME_CONTROLLER, ctrlH, dataH)); - midiDriver->putEvent(alsaPort(), MidiEvent(0, chn, ME_CONTROLLER, ctrlL, dataL)); + routeEvent(MidiEvent(0, chn, ME_CONTROLLER, ctrlH, dataH)); + routeEvent(MidiEvent(0, chn, ME_CONTROLLER, ctrlL, dataL)); } else if (a < 0x30000) { // RPN 7-Bit Controller int ctrlH = (a >> 8) & 0x7f; int ctrlL = a & 0x7f; - midiDriver->putEvent(alsaPort(), MidiEvent(0, chn, ME_CONTROLLER, CTRL_HRPN, ctrlH)); - midiDriver->putEvent(alsaPort(), MidiEvent(0, chn, ME_CONTROLLER, CTRL_LRPN, ctrlL)); - midiDriver->putEvent(alsaPort(), MidiEvent(0, chn, ME_CONTROLLER, CTRL_HDATA, b)); + routeEvent(MidiEvent(0, chn, ME_CONTROLLER, CTRL_HRPN, ctrlH)); + routeEvent(MidiEvent(0, chn, ME_CONTROLLER, CTRL_LRPN, ctrlL)); + routeEvent(MidiEvent(0, chn, ME_CONTROLLER, CTRL_HDATA, b)); } else if (a < 0x40000) { // NRPN 7-Bit Controller int ctrlH = (a >> 8) & 0x7f; int ctrlL = a & 0x7f; - midiDriver->putEvent(alsaPort(), MidiEvent(0, chn, ME_CONTROLLER, CTRL_HNRPN, ctrlH)); - midiDriver->putEvent(alsaPort(), MidiEvent(0, chn, ME_CONTROLLER, CTRL_LNRPN, ctrlL)); - midiDriver->putEvent(alsaPort(), MidiEvent(0, chn, ME_CONTROLLER, CTRL_HDATA, b)); + routeEvent(MidiEvent(0, chn, ME_CONTROLLER, CTRL_HNRPN, ctrlH)); + routeEvent(MidiEvent(0, chn, ME_CONTROLLER, CTRL_LNRPN, ctrlL)); + routeEvent(MidiEvent(0, chn, ME_CONTROLLER, CTRL_HDATA, b)); } else if (a < 0x60000) { // RPN14 Controller int ctrlH = (a >> 8) & 0x7f; int ctrlL = a & 0x7f; int dataH = (b >> 7) & 0x7f; int dataL = b & 0x7f; - midiDriver->putEvent(alsaPort(), MidiEvent(0, chn, ME_CONTROLLER, CTRL_HRPN, ctrlH)); - midiDriver->putEvent(alsaPort(), MidiEvent(0, chn, ME_CONTROLLER, CTRL_LRPN, ctrlL)); - midiDriver->putEvent(alsaPort(), MidiEvent(0, chn, ME_CONTROLLER, CTRL_HDATA, dataH)); - midiDriver->putEvent(alsaPort(), MidiEvent(0, chn, ME_CONTROLLER, CTRL_LDATA, dataL)); + routeEvent(MidiEvent(0, chn, ME_CONTROLLER, CTRL_HRPN, ctrlH)); + routeEvent(MidiEvent(0, chn, ME_CONTROLLER, CTRL_LRPN, ctrlL)); + routeEvent(MidiEvent(0, chn, ME_CONTROLLER, CTRL_HDATA, dataH)); + routeEvent(MidiEvent(0, chn, ME_CONTROLLER, CTRL_LDATA, dataL)); } else if (a < 0x70000) { // NRPN14 Controller int ctrlH = (a >> 8) & 0x7f; int ctrlL = a & 0x7f; int dataH = (b >> 7) & 0x7f; int dataL = b & 0x7f; - midiDriver->putEvent(alsaPort(), MidiEvent(0, chn, ME_CONTROLLER, CTRL_HNRPN, ctrlH)); - midiDriver->putEvent(alsaPort(), MidiEvent(0, chn, ME_CONTROLLER, CTRL_LNRPN, ctrlL)); - midiDriver->putEvent(alsaPort(), MidiEvent(0, chn, ME_CONTROLLER, CTRL_HDATA, dataH)); - midiDriver->putEvent(alsaPort(), MidiEvent(0, chn, ME_CONTROLLER, CTRL_LDATA, dataL)); + routeEvent(MidiEvent(0, chn, ME_CONTROLLER, CTRL_HNRPN, ctrlH)); + routeEvent(MidiEvent(0, chn, ME_CONTROLLER, CTRL_LNRPN, ctrlL)); + routeEvent(MidiEvent(0, chn, ME_CONTROLLER, CTRL_HDATA, dataH)); + routeEvent(MidiEvent(0, chn, ME_CONTROLLER, CTRL_LDATA, dataL)); } else { printf("putEvent: unknown controller type 0x%x\n", a); } #endif } - midiDriver->putEvent(alsaPort(), ev); + routeEvent(ev); } //--------------------------------------------------------- @@ -244,7 +245,7 @@ void MidiOutPort::putEvent(const MidiEvent& ev) void MidiOutPort::playEventList() { for (; _nextPlayEvent != _playEvents.end(); ++_nextPlayEvent) - midiDriver->putEvent(alsaPort(), *_nextPlayEvent); + routeEvent(*_nextPlayEvent); } //--------------------------------------------------------- @@ -385,15 +386,13 @@ void MidiOutPort::playMidiEvent(MidiEvent* ev) RouteList* orl = outRoutes(); bool sendToFifo = false; for (iRoute i = orl->begin(); i != orl->end(); ++i) { - if (i->type == Route::MIDIPORT) - sendToFifo = true; - else if (i->type == Route::SYNTIPORT) { + if (i->type == Route::SYNTIPORT) { SynthI* synti = (SynthI*)i->track; if (synti->eventFifo()->put(*ev)) printf("MidiOut::playMidiEvent(): synti overflow, drop event\n"); } - else - printf("MidiOutPort::playMidiEvent: bad route type\n"); + else + sendToFifo = true; } if (sendToFifo) { if (eventFifo.put(*ev)) @@ -401,6 +400,114 @@ void MidiOutPort::playMidiEvent(MidiEvent* ev) } } +//--------------------------------------------------------- +// process +// "play" events for this process cycle +// if (from != to) then transport state is "playing" +//--------------------------------------------------------- + +void MidiOutPort::process(unsigned from, unsigned to, const Pos& pos, unsigned frames) + { + // + // erase already played events: + // + _playEvents.erase(_playEvents.begin(), _nextPlayEvent); + playFifo(); + + if (mute()) + return; + + // collect port controller + if (from != to) { + CtrlList* cl = controller(); + for (iCtrl ic = cl->begin(); ic != cl->end(); ++ic) { + Ctrl* c = ic->second; + iCtrlVal is = c->lower_bound(from); + iCtrlVal ie = c->lower_bound(to); + for (iCtrlVal ic = is; ic != ie; ++ic) { + unsigned frame = AL::tempomap.tick2frame(ic->first); + Event ev(Controller); + ev.setA(c->id()); + ev.setB(ic->second.i); + _playEvents.add(MidiEvent(frame, -1, ev)); + } + } + } + + int portVelo = 0; + for (int ch = 0; ch < MIDI_CHANNELS; ++ch) { + MidiChannel* mc = channel(ch); + + if (mc->mute() || mc->noInRoute()) + continue; + // collect channel controller + if (from != to) { + CtrlList* cl = mc->controller(); + for (iCtrl ic = cl->begin(); ic != cl->end(); ++ic) { + Ctrl* c = ic->second; + iCtrlVal is = c->lower_bound(from); + iCtrlVal ie = c->lower_bound(to); + for (; is != ie; ++is) { + unsigned frame = AL::tempomap.tick2frame(is->first); + Event ev(Controller); + ev.setA(c->id()); + ev.setB(is->second.i); + _playEvents.add(MidiEvent(frame, ch, ev)); + } + } + } + + // Collect midievents from all input tracks for outport + RouteList* rl = mc->inRoutes(); + for (iRoute i = rl->begin(); i != rl->end(); ++i) { + MidiTrackBase* track = (MidiTrackBase*)i->track; + if (track->isMute()) + continue; + MPEventList el; + track->getEvents(from, to, 0, &el); + int velo = 0; + for (iMPEvent i = el.begin(); i != el.end(); ++i) { + MidiEvent ev = *i; + ev.setChannel(ch); + _playEvents.insert(ev); + if (ev.type() == ME_NOTEON) + velo += ev.dataB(); + } + mc->addMidiMeter(velo); + portVelo += velo; + } + } + addMidiMeter(portVelo); + + // TODO: maybe this copying can be avoided + // + MPEventList il; + for (iMPEvent i = _playEvents.begin(); i != _playEvents.end(); ++i) { + il.add(*i); + } + _playEvents.clear(); + pipeline()->apply(from, to, &il, &_playEvents); + + _nextPlayEvent = _playEvents.begin(); + + // + // route events to destination + // + + unsigned endFrame = pos.frame() + frames + audio->getFrameOffset(); + iMPEvent is = _playEvents.begin(); + iMPEvent ie = _playEvents.end(); + + for (_nextPlayEvent = is; _nextPlayEvent != ie; _nextPlayEvent++) { + if ((from != to) && (_nextPlayEvent->time() >= endFrame)) { + ++_nextPlayEvent; // ?? + break; + } + routeEvent(*_nextPlayEvent); + } + } + + //--------------------------------------------------------- // setInstrument //--------------------------------------------------------- @@ -421,4 +528,27 @@ void MidiOutPort::setSendSync(bool val) emit sendSyncChanged(val); } +//--------------------------------------------------------- +// routeEvent +//--------------------------------------------------------- + +void MidiOutPort::routeEvent(const MidiEvent& event) + { + for (iRoute r = _outRoutes.begin(); r != _outRoutes.end(); ++r) { + switch (r->type) { + case Route::MIDIPORT: + midiDriver->putEvent(alsaPort(0), *_nextPlayEvent); + break; + case Route::SYNTIPORT: + ((SynthI*)(r->track))->playEvents()->insert(*_nextPlayEvent); + break; + case Route::JACKMIDIPORT: + audioDriver->putEvent(jackPort(0), *_nextPlayEvent); + break; + default: + fprintf(stderr, "MidiOutPort::process(): invalid routetype\n"); + break; + } + } + } diff --git a/muse/muse/midioutport.h b/muse/muse/midioutport.h index f90ad376..9999a92d 100644 --- a/muse/muse/midioutport.h +++ b/muse/muse/midioutport.h @@ -44,6 +44,8 @@ class MidiOutPort : public MidiTrackBase { MidiFifo eventFifo; + void routeEvent(const MidiEvent&); + signals: void instrumentChanged(); void sendSyncChanged(bool); diff --git a/muse/muse/undo.cpp b/muse/muse/undo.cpp index 61d9c7e9..b65269f4 100644 --- a/muse/muse/undo.cpp +++ b/muse/muse/undo.cpp @@ -463,6 +463,10 @@ void Song::doUndo3() break; case UndoOp::DeleteTrack: emit trackAdded(i->track, i->id); + if (i->track->selected()) { + i->track->setSelected(false); + selectTrack(i->track); + } break; case UndoOp::ModifyPart: if (i->oPart->track() != i->nPart->track()) -- cgit v1.2.3