|
|
|
@@ -2293,43 +2293,43 @@ private: |
|
|
|
if (p != nullptr) *p = value;
|
|
|
|
}
|
|
|
|
|
|
|
|
OSStatus getBeatAndTempo (Float64* outCurrentBeat, Float64* outCurrentTempo) const
|
|
|
|
/* If the AudioPlayHead is available, and has valid PositionInfo, this will return the result
|
|
|
|
of calling the specified getter on that PositionInfo. Otherwise, this will return a
|
|
|
|
default-constructed instance of the same type.
|
|
|
|
|
|
|
|
For getters that return an Optional, this function will return a nullopt if the playhead or
|
|
|
|
position info is invalid.
|
|
|
|
|
|
|
|
For getters that return a bool, this function will return false if the playhead or position
|
|
|
|
info is invalid.
|
|
|
|
*/
|
|
|
|
template <typename Result>
|
|
|
|
Result getFromPlayHead (Result (AudioPlayHead::PositionInfo::* member)() const) const
|
|
|
|
{
|
|
|
|
if (auto* ph = getPlayHead())
|
|
|
|
{
|
|
|
|
if (const auto pos = ph->getPosition())
|
|
|
|
{
|
|
|
|
setIfNotNull (outCurrentBeat, pos->getPpqPosition().orFallback (0.0));
|
|
|
|
setIfNotNull (outCurrentTempo, pos->getBpm().orFallback (0.0));
|
|
|
|
return noErr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return ((*pos).*member)();
|
|
|
|
|
|
|
|
setIfNotNull (outCurrentBeat, 0);
|
|
|
|
setIfNotNull (outCurrentTempo, 120.0);
|
|
|
|
return {};
|
|
|
|
}
|
|
|
|
|
|
|
|
OSStatus getBeatAndTempo (Float64* outCurrentBeat, Float64* outCurrentTempo) const
|
|
|
|
{
|
|
|
|
setIfNotNull (outCurrentBeat, getFromPlayHead (&AudioPlayHead::PositionInfo::getPpqPosition).orFallback (0));
|
|
|
|
setIfNotNull (outCurrentTempo, getFromPlayHead (&AudioPlayHead::PositionInfo::getBpm).orFallback (120.0));
|
|
|
|
return noErr;
|
|
|
|
}
|
|
|
|
|
|
|
|
OSStatus getMusicalTimeLocation (UInt32* outDeltaSampleOffsetToNextBeat, Float32* outTimeSig_Numerator,
|
|
|
|
UInt32* outTimeSig_Denominator, Float64* outCurrentMeasureDownBeat) const
|
|
|
|
{
|
|
|
|
if (auto* ph = getPlayHead())
|
|
|
|
{
|
|
|
|
if (const auto pos = ph->getPosition())
|
|
|
|
{
|
|
|
|
const auto signature = pos->getTimeSignature().orFallback (AudioPlayHead::TimeSignature{});
|
|
|
|
setIfNotNull (outDeltaSampleOffsetToNextBeat, (UInt32) 0); //xxx
|
|
|
|
setIfNotNull (outTimeSig_Numerator, (UInt32) signature.numerator);
|
|
|
|
setIfNotNull (outTimeSig_Denominator, (UInt32) signature.denominator);
|
|
|
|
setIfNotNull (outCurrentMeasureDownBeat, pos->getPpqPositionOfLastBarStart().orFallback (0.0)); //xxx wrong
|
|
|
|
return noErr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
setIfNotNull (outDeltaSampleOffsetToNextBeat, (UInt32) 0); //xxx
|
|
|
|
setIfNotNull (outCurrentMeasureDownBeat, getFromPlayHead (&AudioPlayHead::PositionInfo::getPpqPositionOfLastBarStart).orFallback (0.0));
|
|
|
|
|
|
|
|
const auto signature = getFromPlayHead (&AudioPlayHead::PositionInfo::getTimeSignature).orFallback (AudioPlayHead::TimeSignature{});
|
|
|
|
setIfNotNull (outTimeSig_Numerator, (UInt32) signature.numerator);
|
|
|
|
setIfNotNull (outTimeSig_Denominator, (UInt32) signature.denominator);
|
|
|
|
|
|
|
|
setIfNotNull (outDeltaSampleOffsetToNextBeat, (UInt32) 0);
|
|
|
|
setIfNotNull (outTimeSig_Numerator, (UInt32) 4);
|
|
|
|
setIfNotNull (outTimeSig_Denominator, (UInt32) 4);
|
|
|
|
setIfNotNull (outCurrentMeasureDownBeat, 0);
|
|
|
|
return noErr;
|
|
|
|
}
|
|
|
|
|
|
|
|
@@ -2337,34 +2337,16 @@ private: |
|
|
|
Float64* outCurrentSampleInTimeLine, Boolean* outIsCycling,
|
|
|
|
Float64* outCycleStartBeat, Float64* outCycleEndBeat)
|
|
|
|
{
|
|
|
|
if (auto* ph = getPlayHead())
|
|
|
|
{
|
|
|
|
AudioPlayHead::CurrentPositionInfo result;
|
|
|
|
const auto nowPlaying = getFromPlayHead (&AudioPlayHead::PositionInfo::getIsPlaying);
|
|
|
|
setIfNotNull (outIsPlaying, nowPlaying);
|
|
|
|
setIfNotNull (outTransportStateChanged, std::exchange (wasPlaying, nowPlaying) != nowPlaying);
|
|
|
|
setIfNotNull (outCurrentSampleInTimeLine, getFromPlayHead (&AudioPlayHead::PositionInfo::getTimeInSamples).orFallback (0));
|
|
|
|
setIfNotNull (outIsCycling, getFromPlayHead (&AudioPlayHead::PositionInfo::getIsLooping));
|
|
|
|
|
|
|
|
if (ph->getCurrentPosition (result))
|
|
|
|
{
|
|
|
|
setIfNotNull (outIsPlaying, result.isPlaying);
|
|
|
|
|
|
|
|
if (outTransportStateChanged != nullptr)
|
|
|
|
{
|
|
|
|
*outTransportStateChanged = result.isPlaying != wasPlaying;
|
|
|
|
wasPlaying = result.isPlaying;
|
|
|
|
}
|
|
|
|
|
|
|
|
setIfNotNull (outCurrentSampleInTimeLine, result.timeInSamples);
|
|
|
|
setIfNotNull (outIsCycling, result.isLooping);
|
|
|
|
setIfNotNull (outCycleStartBeat, result.ppqLoopStart);
|
|
|
|
setIfNotNull (outCycleEndBeat, result.ppqLoopEnd);
|
|
|
|
return noErr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
const auto loopPoints = getFromPlayHead (&AudioPlayHead::PositionInfo::getLoopPoints).orFallback (AudioPlayHead::LoopPoints{});
|
|
|
|
setIfNotNull (outCycleStartBeat, loopPoints.ppqStart);
|
|
|
|
setIfNotNull (outCycleEndBeat, loopPoints.ppqEnd);
|
|
|
|
|
|
|
|
setIfNotNull (outIsPlaying, false);
|
|
|
|
setIfNotNull (outTransportStateChanged, false);
|
|
|
|
setIfNotNull (outCurrentSampleInTimeLine, 0);
|
|
|
|
setIfNotNull (outIsCycling, false);
|
|
|
|
setIfNotNull (outCycleStartBeat, 0.0);
|
|
|
|
setIfNotNull (outCycleEndBeat, 0.0);
|
|
|
|
return noErr;
|
|
|
|
}
|
|
|
|
|
|
|
|
|