summaryrefslogtreecommitdiff
path: root/muse2/muse/mididev.cpp
diff options
context:
space:
mode:
authorTim E. Real <termtech@rogers.com>2011-04-28 06:14:25 +0000
committerTim E. Real <termtech@rogers.com>2011-04-28 06:14:25 +0000
commitdcef2c49e36e86036a4caa08a6bcc0580cc53da7 (patch)
tree3c8832519a9e41c5c14f8e740a49294ed0251e7c /muse2/muse/mididev.cpp
parente2cec3f03fdee64da1c5080498476c1cdd43bbdb (diff)
Small scoreedit and dssi controls out fix. More separation of Alsa/Jack midi processing -
as a possible fix for crash report by Geoff B. Please see ChangeLog
Diffstat (limited to 'muse2/muse/mididev.cpp')
-rw-r--r--muse2/muse/mididev.cpp180
1 files changed, 179 insertions, 1 deletions
diff --git a/muse2/muse/mididev.cpp b/muse2/muse/mididev.cpp
index 10be79ef..b5445b71 100644
--- a/muse2/muse/mididev.cpp
+++ b/muse2/muse/mididev.cpp
@@ -19,11 +19,14 @@
#include "midiport.h"
#include "mididev.h"
#include "config.h"
+#include "gconfig.h"
#include "globals.h"
#include "audio.h"
#include "midiseq.h"
-//#include "sync.h"
+#include "sync.h"
#include "midiitransform.h"
+#include "part.h"
+//#include "mpevent.h"
#ifdef MIDI_DRIVER_MIDI_SERIAL
extern void initMidiSerial();
@@ -572,3 +575,178 @@ bool MidiDevice::putEvent(const MidiPlayEvent& ev)
}
return putMidiEvent(ev);
}
+
+//---------------------------------------------------------
+// handleStop
+//---------------------------------------------------------
+
+void MidiDevice::handleStop()
+{
+ // If the device is not in use by a port, don't bother it.
+ if(_port == -1)
+ return;
+
+ //---------------------------------------------------
+ // Clear all notes and handle stuck notes
+ //---------------------------------------------------
+
+ _playEvents.clear();
+ for(iMPEvent i = _stuckNotes.begin(); i != _stuckNotes.end(); ++i)
+ {
+ MidiPlayEvent ev = *i;
+ ev.setTime(0);
+ _playEvents.add(ev);
+ }
+ _stuckNotes.clear();
+ //setNextPlayEvent(_playEvents.begin());
+
+
+ //---------------------------------------------------
+ // reset sustain
+ //---------------------------------------------------
+
+ MidiPort* mp = &midiPorts[_port];
+ for(int ch = 0; ch < MIDI_CHANNELS; ++ch)
+ {
+ if(mp->hwCtrlState(ch, CTRL_SUSTAIN) == 127)
+ {
+ //printf("send clear sustain!!!!!!!! port %d ch %d\n", i,ch);
+ MidiPlayEvent ev(0, _port, ch, ME_CONTROLLER, CTRL_SUSTAIN, 0);
+ putEvent(ev);
+ }
+ }
+
+ //---------------------------------------------------
+ // send midi stop
+ //---------------------------------------------------
+
+ // Don't send if external sync is on. The master, and our sync routing system will take care of that. p3.3.31
+ if(!extSyncFlag.value())
+ {
+ // Shall we check open flags?
+ //if(!(dev->rwFlags() & 0x1) || !(dev->openFlags() & 1))
+ //if(!(dev->openFlags() & 1))
+ // return;
+
+ MidiSyncInfo& si = mp->syncInfo();
+ if(si.MMCOut())
+ mp->sendMMCStop();
+
+ if(si.MRTOut())
+ {
+ // Send STOP
+ mp->sendStop();
+
+ // p3.3.31
+ // Added check of option send continue not start.
+ // Hmm, is this required? Seems to make other devices unhappy.
+ // (Could try now that this is in MidiDevice. p4.0.22 )
+ /*
+ if(!si.sendContNotStart())
+ mp->sendSongpos(audio->tickPos() * 4 / config.division);
+ */
+ }
+ }
+}
+
+//---------------------------------------------------------
+// handleSeek
+//---------------------------------------------------------
+
+void MidiDevice::handleSeek()
+{
+ // If the device is not in use by a port, don't bother it.
+ if(_port == -1)
+ return;
+
+ //---------------------------------------------------
+ // If playing, clear all notes and handle stuck notes
+ //---------------------------------------------------
+
+ if(audio->isPlaying())
+ {
+ _playEvents.clear();
+ for(iMPEvent i = _stuckNotes.begin(); i != _stuckNotes.end(); ++i)
+ {
+ MidiPlayEvent ev = *i;
+ ev.setTime(0);
+ _playEvents.add(ev);
+ }
+ _stuckNotes.clear();
+ }
+ //else
+ // Removed p4.0.15 Device now leaves beginning pointing at next event,
+ // immediately after playing some notes.
+ // NOTE: This removal needs testing. I'm not sure about this.
+ //_playEvents.erase(_playEvents.begin(), _nextPlayEvent);
+
+ MidiPort* mp = &midiPorts[_port];
+ MidiCtrlValListList* cll = mp->controller();
+ int pos = audio->tickPos();
+
+ //---------------------------------------------------
+ // Send new contoller values
+ //---------------------------------------------------
+
+ for(iMidiCtrlValList ivl = cll->begin(); ivl != cll->end(); ++ivl)
+ {
+ MidiCtrlValList* vl = ivl->second;
+ //int val = vl->value(pos);
+ //if (val != CTRL_VAL_UNKNOWN) {
+ // int channel = ivl->first >> 24;
+ // el->add(MidiPlayEvent(0, port, channel, ME_CONTROLLER, vl->num(), val));
+ // }
+ iMidiCtrlVal imcv = vl->iValue(pos);
+ if(imcv != vl->end())
+ {
+ Part* p = imcv->second.part;
+ unsigned t = (unsigned)imcv->first;
+ // Do not add values that are outside of the part.
+ if(p && t >= p->tick() && t < (p->tick() + p->lenTick()) )
+ _playEvents.add(MidiPlayEvent(0, _port, ivl->first >> 24, ME_CONTROLLER, vl->num(), imcv->second.val));
+ }
+ }
+ //_nextPlayEvent = (_playEvents.begin()); // Removed p4.0.15
+
+ //---------------------------------------------------
+ // Send STOP and "set song position pointer"
+ //---------------------------------------------------
+
+ // Don't send if external sync is on. The master, and our sync routing system will take care of that. p3.3.31
+ if(!extSyncFlag.value())
+ {
+ if(mp->syncInfo().MRTOut())
+ {
+ // Shall we check for device write open flag to see if it's ok to send?...
+ // This means obey what the user has chosen for read/write in the midi port config dialog,
+ // which already takes into account whether the device is writable or not.
+ //if(!(rwFlags() & 0x1) || !(openFlags() & 1))
+ //if(!(openFlags() & 1))
+ // continue;
+
+ //int port = midiPort();
+
+ // By checking for no port here (-1), (and out of bounds), it means
+ // the device must be assigned to a port for these MMC commands to be sent.
+ // Without this check, interesting sync things can be done by the user without ever
+ // assigning any devices to ports !
+ //if(port < 0 || port > MIDI_PORTS)
+ //if(port < -1 || port > MIDI_PORTS)
+ // continue;
+
+ int beat = (pos * 4) / config.division;
+
+ //bool isPlaying = false;
+ //if(state == PLAY)
+ // isPlaying = true;
+ bool isPlaying = audio->isPlaying(); // Check this it includes LOOP1 and LOOP2 besides PLAY. p4.0.22
+
+ mp->sendStop();
+ mp->sendSongpos(beat);
+ if(isPlaying)
+ mp->sendContinue();
+ }
+ }
+}
+
+