aboutsummaryrefslogtreecommitdiff
path: root/src/midi_sequencer_impl.hpp
diff options
context:
space:
mode:
authorVitaly Novichkov <admin@wohlnet.ru>2019-11-15 23:16:22 +0300
committerVitaly Novichkov <admin@wohlnet.ru>2019-11-15 23:16:22 +0300
commit2a2613b2da30dcb835440f9d80f2fbf2a068e29f (patch)
treea75778dc8a14bff6e11b663c24d489598db89169 /src/midi_sequencer_impl.hpp
parent45190534246f6c5186aa1708187d5010363db03d (diff)
parentd21b27084532dca78f07ff87f578330f7c6f9755 (diff)
downloadlibADLMIDI-2a2613b2da30dcb835440f9d80f2fbf2a068e29f.tar.gz
libADLMIDI-2a2613b2da30dcb835440f9d80f2fbf2a068e29f.tar.bz2
libADLMIDI-2a2613b2da30dcb835440f9d80f2fbf2a068e29f.zip
Merge remote-tracking branch 'origin/master' into wip-new-embedded-banks
Diffstat (limited to 'src/midi_sequencer_impl.hpp')
-rw-r--r--src/midi_sequencer_impl.hpp83
1 files changed, 72 insertions, 11 deletions
diff --git a/src/midi_sequencer_impl.hpp b/src/midi_sequencer_impl.hpp
index 2af80ea..4dc3013 100644
--- a/src/midi_sequencer_impl.hpp
+++ b/src/midi_sequencer_impl.hpp
@@ -48,6 +48,36 @@ typedef int32_t ssize_t;
# endif
#endif
+#if defined(_MSC_VER) && _MSC_VER < 1900
+
+#define snprintf c99_snprintf
+#define vsnprintf c99_vsnprintf
+
+__inline int c99_vsnprintf(char *outBuf, size_t size, const char *format, va_list ap)
+{
+ int count = -1;
+
+ if (size != 0)
+ count = _vsnprintf_s(outBuf, size, _TRUNCATE, format, ap);
+ if (count == -1)
+ count = _vscprintf(format, ap);
+
+ return count;
+}
+
+__inline int c99_snprintf(char *outBuf, size_t size, const char *format, ...)
+{
+ int count;
+ va_list ap;
+
+ va_start(ap, format);
+ count = c99_vsnprintf(outBuf, size, format, ap);
+ va_end(ap);
+
+ return count;
+}
+#endif
+
#ifndef BWMIDI_DISABLE_MUS_SUPPORT
#include "cvt_mus2mid.hpp"
#endif//MUS
@@ -272,13 +302,14 @@ BW_MidiSequencer::BW_MidiSequencer() :
m_smfFormat(0),
m_loopFormat(Loop_Default),
m_loopEnabled(false),
+ m_loopHooksOnly(false),
m_fullSongTimeLength(0.0),
m_postSongWaitDelay(1.0),
m_loopStartTime(-1.0),
m_loopEndTime(-1.0),
m_tempoMultiplier(1.0),
m_atEnd(false),
- m_trackSolo(~(size_t)0),
+ m_trackSolo(~static_cast<size_t>(0)),
m_triggerHandler(NULL),
m_triggerUserData(NULL)
{
@@ -364,6 +395,11 @@ void BW_MidiSequencer::setLoopEnabled(bool enabled)
m_loopEnabled = enabled;
}
+void BW_MidiSequencer::setLoopHooksOnly(bool enabled)
+{
+ m_loopHooksOnly = enabled;
+}
+
const std::string &BW_MidiSequencer::getMusicTitle()
{
return m_musTitle;
@@ -951,6 +987,7 @@ bool BW_MidiSequencer::processEvents(bool isSeek)
unsigned caughLoopStart = 0;
unsigned caughLoopStackStart = 0;
unsigned caughLoopStackEnds = 0;
+ double caughLoopStackEndsTime = 0.0;
unsigned caughLoopStackBreaks = 0;
#ifdef DEBUG_TIME_CALCULATION
@@ -983,12 +1020,18 @@ bool BW_MidiSequencer::processEvents(bool isSeek)
if(m_loop.caughtStart)
{
+ if(m_interface->onloopStart)//Loop Start hook
+ m_interface->onloopStart(m_interface->onloopStart_userData);
+
caughLoopStart++;
m_loop.caughtStart = false;
}
if(m_loop.caughtStackStart)
{
+ if(m_interface->onloopStart && (m_loopStartTime >= track.pos->time))//Loop Start hook
+ m_interface->onloopStart(m_interface->onloopStart_userData);
+
caughLoopStackStart++;
m_loop.caughtStackStart = false;
}
@@ -1005,6 +1048,7 @@ bool BW_MidiSequencer::processEvents(bool isSeek)
{
m_loop.caughtStackEnd = false;
caughLoopStackEnds++;
+ caughLoopStackEndsTime = track.pos->time;
}
doLoopJump = true;
break;//Stop event handling on catching loopEnd event!
@@ -1094,6 +1138,15 @@ bool BW_MidiSequencer::processEvents(bool isSeek)
LoopStackEntry &s = m_loop.getCurStack();
if(s.infinity)
{
+ if(m_interface->onloopEnd && (m_loopEndTime >= caughLoopStackEndsTime))//Loop End hook
+ {
+ m_interface->onloopEnd(m_interface->onloopEnd_userData);
+ if(m_loopHooksOnly)//Stop song on reaching loop end
+ {
+ m_atEnd = true; //Don't handle events anymore
+ m_currentPosition.wait += m_postSongWaitDelay;//One second delay until stop playing
+ }
+ }
m_currentPosition = s.startPosition;
m_loop.skipStackStart = true;
return true;
@@ -1127,10 +1180,14 @@ bool BW_MidiSequencer::processEvents(bool isSeek)
if(shortest_no || m_loop.caughtEnd)
{
+ if(m_interface->onloopEnd)//Loop End hook
+ m_interface->onloopEnd(m_interface->onloopEnd_userData);
+
//Loop if song end or loop end point has reached
m_loop.caughtEnd = false;
shortest = 0;
- if(!m_loopEnabled)
+
+ if(!m_loopEnabled || m_loopHooksOnly)
{
m_atEnd = true; //Don't handle events anymore
m_currentPosition.wait += m_postSongWaitDelay;//One second delay until stop playing
@@ -1545,7 +1602,7 @@ void BW_MidiSequencer::handleEvent(size_t track, const BW_MidiSequencer::MidiEve
}
else
{
- if(m_trackSolo != ~(size_t)0 && track != m_trackSolo)
+ if(m_trackSolo != ~static_cast<size_t>(0) && track != m_trackSolo)
return;
if(m_trackDisable[track])
return;
@@ -1576,8 +1633,8 @@ void BW_MidiSequencer::handleEvent(size_t track, const BW_MidiSequencer::MidiEve
{
// Special event FF
uint8_t evtype = evt.subtype;
- uint64_t length = (uint64_t)evt.data.size();
- const char *data(length ? (const char *)evt.data.data() : "");
+ uint64_t length = static_cast<uint64_t>(evt.data.size());
+ const char *data(length ? reinterpret_cast<const char *>(evt.data.data()) : "");
if(evtype == MidiEvent::ST_ENDTRACK)//End Of Track
{
@@ -1628,8 +1685,8 @@ void BW_MidiSequencer::handleEvent(size_t track, const BW_MidiSequencer::MidiEve
m_loop.skipStackStart = false;
return;
}
- LoopStackEntry &s = m_loop.stack[(m_loop.stackLevel + 1)];
- s.loops = (int)data[0];
+ LoopStackEntry &s = m_loop.stack[static_cast<size_t>(m_loop.stackLevel + 1)];
+ s.loops = static_cast<int>(data[0]);
s.infinity = (data[0] == 0);
m_loop.caughtStackStart = true;
return;
@@ -1942,14 +1999,14 @@ static bool detectIMF(const char *head, FileAndMemReader &fr)
uint8_t raw[4];
size_t end = static_cast<size_t>(head[0]) + 256 * static_cast<size_t>(head[1]);
- if(!end || (end & 3))
+ if(end & 3)
return false;
size_t backup_pos = fr.tell();
int64_t sum1 = 0, sum2 = 0;
- fr.seek(2, FileAndMemReader::SET);
+ fr.seek((end > 0 ? 2 : 0), FileAndMemReader::SET);
- for(unsigned n = 0; n < 42; ++n)
+ for(size_t n = 0; n < 16383; ++n)
{
if(fr.read(raw, 1, 4) != 4)
break;
@@ -2108,7 +2165,11 @@ bool BW_MidiSequencer::parseIMF(FileAndMemReader &fr)
event.absPosition = 0;
event.data.resize(2);
- fr.seek(2, FileAndMemReader::SET);
+ fr.seek((imfEnd > 0) ? 2 : 0, FileAndMemReader::SET);
+
+ if(imfEnd == 0) // IMF Type 0 with unlimited file length
+ imfEnd = fr.fileSize();
+
while(fr.tell() < imfEnd && !fr.eof())
{
if(fr.read(imfRaw, 1, 4) != 4)