Closes #207tags/1.9.6
@@ -29,6 +29,7 @@ public: | |||
MidiFilePlugin(const NativeHostDescriptor* const host) | |||
: NativePluginClass(host), | |||
fMidiOut(this), | |||
fNeedsAllNotesOff(false), | |||
fWasPlayingBefore(false), | |||
leakDetector_MidiFilePlugin() {} | |||
@@ -54,32 +55,35 @@ protected: | |||
{ | |||
const NativeTimeInfo* const timePos(getTimeInfo()); | |||
if (timePos->playing) | |||
if (fWasPlayingBefore != timePos->playing) | |||
{ | |||
fMidiOut.play(timePos->frame, frames); | |||
fNeedsAllNotesOff = true; | |||
fWasPlayingBefore = timePos->playing; | |||
} | |||
else if (fWasPlayingBefore) | |||
if (fNeedsAllNotesOff) | |||
{ | |||
NativeMidiEvent midiEvent; | |||
midiEvent.port = 0; | |||
midiEvent.time = 0; | |||
midiEvent.data[0] = MIDI_STATUS_CONTROL_CHANGE; | |||
midiEvent.data[0] = 0; | |||
midiEvent.data[1] = MIDI_CONTROL_ALL_NOTES_OFF; | |||
midiEvent.data[2] = 0; | |||
midiEvent.data[3] = 0; | |||
midiEvent.size = 3; | |||
for (int i=0; i < MAX_MIDI_CHANNELS; ++i) | |||
for (int channel=MAX_MIDI_CHANNELS; --channel >= 0;) | |||
{ | |||
midiEvent.data[0] = uint8_t(MIDI_STATUS_CONTROL_CHANGE+i); | |||
midiEvent.data[0] = uint8_t(MIDI_STATUS_CONTROL_CHANGE | (channel & MIDI_CHANNEL_BIT)); | |||
NativePluginClass::writeMidiEvent(&midiEvent); | |||
} | |||
carla_stdout("WAS PLAYING BEFORE, NOW STOPPED"); | |||
fNeedsAllNotesOff = false; | |||
} | |||
fWasPlayingBefore = timePos->playing; | |||
if (fWasPlayingBefore) | |||
fMidiOut.play(timePos->frame, frames); | |||
} | |||
// ------------------------------------------------------------------- | |||
@@ -131,6 +135,7 @@ protected: | |||
private: | |||
MidiPattern fMidiOut; | |||
bool fNeedsAllNotesOff; | |||
bool fWasPlayingBefore; | |||
void _loadMidiFile(const char* const filename) | |||
@@ -200,6 +205,8 @@ private: | |||
fMidiOut.addRaw(static_cast<uint64_t>(time), midiMessage.getRawData(), static_cast<uint8_t>(dataSize)); | |||
} | |||
} | |||
fNeedsAllNotesOff = true; | |||
} | |||
PluginClassEND(MidiFilePlugin) | |||
@@ -32,6 +32,7 @@ public: | |||
MidiSequencerPlugin(const NativeHostDescriptor* const host) | |||
: NativePluginAndUiClass(host, CARLA_OS_SEP_STR "midiseq-ui"), | |||
fNeedsAllNotesOff(false), | |||
fWantInEvents(false), | |||
fWasPlayingBefore(false), | |||
fTicksPerFrame(0.0), | |||
@@ -76,17 +77,13 @@ protected: | |||
fInEvents.trySplice(); | |||
} | |||
if (fTimeInfo.playing) | |||
if (fWasPlayingBefore != fTimeInfo.playing) | |||
{ | |||
if (! fTimeInfo.bbt.valid) | |||
fTimeInfo.bbt.beatsPerMinute = 120.0; | |||
fTicksPerFrame = 48.0 / (60.0 / fTimeInfo.bbt.beatsPerMinute * getSampleRate()); | |||
fMidiOut.play(fTicksPerFrame*static_cast<long double>(fTimeInfo.frame), | |||
fTicksPerFrame*static_cast<double>(frames)); | |||
fNeedsAllNotesOff = true; | |||
fWasPlayingBefore = fTimeInfo.playing; | |||
} | |||
else if (fWasPlayingBefore) | |||
if (fNeedsAllNotesOff) | |||
{ | |||
NativeMidiEvent midiEvent; | |||
@@ -104,10 +101,19 @@ protected: | |||
NativePluginAndUiClass::writeMidiEvent(&midiEvent); | |||
} | |||
carla_stdout("WAS PLAYING BEFORE, NOW STOPPED"); | |||
fNeedsAllNotesOff = false; | |||
} | |||
fWasPlayingBefore = fTimeInfo.playing; | |||
if (fTimeInfo.playing) | |||
{ | |||
if (! fTimeInfo.bbt.valid) | |||
fTimeInfo.bbt.beatsPerMinute = 120.0; | |||
fTicksPerFrame = 48.0 / (60.0 / fTimeInfo.bbt.beatsPerMinute * getSampleRate()); | |||
fMidiOut.play(fTicksPerFrame*static_cast<long double>(fTimeInfo.frame), | |||
fTicksPerFrame*static_cast<double>(frames)); | |||
} | |||
} | |||
// ------------------------------------------------------------------- | |||
@@ -208,6 +214,7 @@ protected: | |||
if (std::strcmp(msg, "midi-clear-all") == 0) | |||
{ | |||
fMidiOut.clear(); | |||
fNeedsAllNotesOff = true; | |||
return true; | |||
} | |||
@@ -259,6 +266,7 @@ protected: | |||
// ------------------------------------------------------------------- | |||
private: | |||
bool fNeedsAllNotesOff; | |||
bool fWantInEvents; | |||
bool fWasPlayingBefore; | |||
@@ -366,7 +366,9 @@ private: | |||
bool _add(const T& value, const bool inTail, ListHead* const queue) noexcept | |||
{ | |||
return _add_internal(_allocate(), value, inTail, queue); | |||
if (Data* const data = _allocate()) | |||
return _add_internal(data, value, inTail, queue); | |||
return false; | |||
} | |||
bool _add_internal(Data* const data, const T& value, const bool inTail, ListHead* const queue) noexcept | |||