aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJP Cimalando <jpcima@users.noreply.github.com>2018-07-07 02:03:01 +0200
committerJP Cimalando <jpcima@users.noreply.github.com>2018-07-07 02:40:02 +0200
commit7cb0fe9dad9f7ef24d1142d866450305102bf3a9 (patch)
tree392c55537731346ec8dc65a9f93afb35fbe4f73d
parent63f0c95a978902e0896513ca4c7e7e3907da7b9d (diff)
downloadlibADLMIDI-7cb0fe9dad9f7ef24d1142d866450305102bf3a9.tar.gz
libADLMIDI-7cb0fe9dad9f7ef24d1142d866450305102bf3a9.tar.bz2
libADLMIDI-7cb0fe9dad9f7ef24d1142d866450305102bf3a9.zip
sequencer API to turn tracks on/off/solo
-rw-r--r--include/adlmidi.h27
-rw-r--r--src/adlmidi.cpp57
-rw-r--r--src/midi_sequencer.hpp25
-rw-r--r--src/midi_sequencer_impl.hpp30
4 files changed, 138 insertions, 1 deletions
diff --git a/include/adlmidi.h b/include/adlmidi.h
index 387a30a..dc6fd8c 100644
--- a/include/adlmidi.h
+++ b/include/adlmidi.h
@@ -636,6 +636,33 @@ extern void adl_setTempo(struct ADL_MIDIPlayer *device, double tempo);
*/
extern int adl_atEnd(struct ADL_MIDIPlayer *device);
+/**
+ * @brief Returns the number of tracks of the current sequence
+ * @param device Instance of the library
+ * @return Count of tracks in the current sequence
+ */
+extern size_t adl_trackCount(struct ADL_MIDIPlayer *device);
+
+/**
+ * @brief Track options
+ */
+enum ADLMIDI_TrackOptions
+{
+ /*! Enabled track */
+ ADL_TrackOption_On = 1,
+ /*! Disabled track */
+ ADL_TrackOption_Off = 2,
+ /*! Solo track */
+ ADL_TrackOption_Solo = 3,
+};
+
+/**
+ * @brief Sets options on a track of the current sequence
+ * @param device Instance of the library
+ * @param trackNumber Identifier of the designated track.
+ * @return 0 on success, <0 when any error has occurred
+ */
+extern int adl_setTrackOptions(struct ADL_MIDIPlayer *device, size_t trackNumber, unsigned trackOptions);
diff --git a/src/adlmidi.cpp b/src/adlmidi.cpp
index 4fed13b..93d1bf1 100644
--- a/src/adlmidi.cpp
+++ b/src/adlmidi.cpp
@@ -1356,6 +1356,63 @@ ADLMIDI_EXPORT int adl_atEnd(struct ADL_MIDIPlayer *device)
#endif
}
+ADLMIDI_EXPORT size_t adl_trackCount(struct ADL_MIDIPlayer *device)
+{
+#ifndef ADLMIDI_DISABLE_MIDI_SEQUENCER
+ if(!device)
+ return 0;
+ MidiPlayer *play = GET_MIDI_PLAYER(device);
+ if(!play)
+ return 0;
+ return play->m_sequencer.getTrackCount();
+#else
+ ADL_UNUSED(device);
+ return 0;
+#endif
+}
+
+ADLMIDI_EXPORT int adl_setTrackOptions(struct ADL_MIDIPlayer *device, size_t trackNumber, unsigned trackOptions)
+{
+#ifndef ADLMIDI_DISABLE_MIDI_SEQUENCER
+ if(!device)
+ return -1;
+ MidiPlayer *play = GET_MIDI_PLAYER(device);
+ if(!play)
+ return -1;
+ MidiSequencer &seq = play->m_sequencer;
+
+ unsigned enableFlag = trackOptions & 3;
+ trackOptions &= ~3u;
+
+ // handle on/off/solo
+ switch(enableFlag)
+ {
+ default:
+ break;
+ case ADL_TrackOption_On:
+ case ADL_TrackOption_Off:
+ if(!seq.setTrackEnabled(trackNumber, enableFlag == ADL_TrackOption_On))
+ return -1;
+ break;
+ case ADL_TrackOption_Solo:
+ seq.setSoloTrack(trackNumber);
+ break;
+ }
+
+ // handle others...
+ if(trackOptions != 0)
+ return -1;
+
+ return 0;
+
+#else
+ ADL_UNUSED(device);
+ ADL_UNUSED(trackNumber);
+ ADL_UNUSED(trackOptions);
+ return -1;
+#endif
+}
+
ADLMIDI_EXPORT void adl_panic(struct ADL_MIDIPlayer *device)
{
if(!device)
diff --git a/src/midi_sequencer.hpp b/src/midi_sequencer.hpp
index 6eeefa9..71e06b5 100644
--- a/src/midi_sequencer.hpp
+++ b/src/midi_sequencer.hpp
@@ -343,6 +343,11 @@ private:
//! Are loop points invalid?
bool m_invalidLoop; /*Loop points are invalid (loopStart after loopEnd or loopStart and loopEnd are on same place)*/
+ //! Whether the nth track has playback disabled
+ std::vector<bool> m_trackDisable;
+ //! Index of solo track, or max for disabled
+ size_t m_trackSolo;
+
//! File parsing errors string (adding into m_errorString on aborting of the process)
std::string m_parsingErrorsString;
//! Common error string
@@ -365,6 +370,26 @@ public:
FileFormat getFormat();
/**
+ * @brief Returns the number of tracks
+ * @return Track count
+ */
+ size_t getTrackCount() const;
+
+ /**
+ * @brief Sets whether a track is playing
+ * @param track Track identifier
+ * @param enable Whether to enable track playback
+ * @return true on success, false if there was no such track
+ */
+ bool setTrackEnabled(size_t track, bool enable);
+
+ /**
+ * @brief Enables or disables solo on a track
+ * @param track Identifier of solo track, or max to disable
+ */
+ void setSoloTrack(size_t track);
+
+ /**
* @brief Get the list of CMF instruments (CMF only)
* @return Array of raw CMF instruments entries
*/
diff --git a/src/midi_sequencer_impl.hpp b/src/midi_sequencer_impl.hpp
index ce70c3e..d8edbfb 100644
--- a/src/midi_sequencer_impl.hpp
+++ b/src/midi_sequencer_impl.hpp
@@ -271,7 +271,8 @@ BW_MidiSequencer::BW_MidiSequencer() :
m_atEnd(false),
m_loopStart(false),
m_loopEnd(false),
- m_invalidLoop(false)
+ m_invalidLoop(false),
+ m_trackSolo(~(size_t)0)
{}
BW_MidiSequencer::~BW_MidiSequencer()
@@ -307,6 +308,25 @@ BW_MidiSequencer::FileFormat BW_MidiSequencer::getFormat()
return m_format;
}
+size_t BW_MidiSequencer::getTrackCount() const
+{
+ return m_trackData.size();
+}
+
+bool BW_MidiSequencer::setTrackEnabled(size_t track, bool enable)
+{
+ size_t trackCount = m_trackData.size();
+ if(track >= trackCount)
+ return false;
+ m_trackDisable[track] = !enable;
+ return true;
+}
+
+void BW_MidiSequencer::setSoloTrack(size_t track)
+{
+ m_trackSolo = track;
+}
+
const std::vector<BW_MidiSequencer::CmfInstrument> BW_MidiSequencer::getRawCmfInstruments()
{
return m_cmfInstruments;
@@ -362,6 +382,8 @@ bool BW_MidiSequencer::buildTrackData(const std::vector<std::vector<uint8_t> > &
m_fullSongTimeLength = 0.0;
m_loopStartTime = -1.0;
m_loopEndTime = -1.0;
+ m_trackDisable.clear();
+ m_trackSolo = ~(size_t)0;
m_musTitle.clear();
m_musCopyright.clear();
m_musTrackTitles.clear();
@@ -369,6 +391,7 @@ bool BW_MidiSequencer::buildTrackData(const std::vector<std::vector<uint8_t> > &
m_trackData.clear();
const size_t trackCount = trackData.size();
m_trackData.resize(trackCount, MidiTrackQueue());
+ m_trackDisable.resize(trackCount);
m_invalidLoop = false;
bool gotLoopStart = false, gotLoopEnd = false, gotLoopEventInThisRow = false;
@@ -1122,6 +1145,11 @@ BW_MidiSequencer::MidiEvent BW_MidiSequencer::parseEvent(const uint8_t **pptr, c
void BW_MidiSequencer::handleEvent(size_t track, const BW_MidiSequencer::MidiEvent &evt, int32_t &status)
{
+ if(m_trackSolo != ~(size_t)0 && track != m_trackSolo)
+ return;
+ if(m_trackDisable[track])
+ return;
+
if(m_interface->onEvent)
{
m_interface->onEvent(m_interface->onEvent_userData,