summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--muse/muse/audio.cpp4
-rw-r--r--muse/muse/driver/alsamidi.h5
-rw-r--r--muse/muse/driver/audiodev.h3
-rw-r--r--muse/muse/driver/driver.h3
-rw-r--r--muse/muse/driver/dummyaudio.cpp1
-rw-r--r--muse/muse/driver/jack.cpp29
-rw-r--r--muse/muse/driver/jackaudio.h4
-rw-r--r--muse/muse/midi.cpp152
-rw-r--r--muse/muse/midieventbase.h (renamed from muse/muse/midievent.h)0
-rw-r--r--muse/muse/midioutport.cpp186
-rw-r--r--muse/muse/midioutport.h2
-rw-r--r--muse/muse/undo.cpp4
12 files changed, 208 insertions, 185 deletions
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/midieventbase.h
index 93cb5529..93cb5529 100644
--- a/muse/muse/midievent.h
+++ b/muse/muse/midieventbase.h
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))
@@ -402,6 +401,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())