About that AudioPlayHead::CurrentPositionInfo

I’m running into some situations (with the AAX wrapper, but possibly in other places) in which the getCurrentPosition call doesn’t fill in the CurrentPositionInfo structure. There are many possible reasons for this, but they generally center around other things that aren’t initialized. There may be underlying reasons that need addressing, but I’d like to make a simple request (actually two).

  1. Jules, could you please provide a simple static initialization function for CurrentPositionInfo? If there’s been a failure in GetCurrentPosition, a lot of the info fields are full of junk and vulnerable to all sorts of errors (divide-by-zero, etc). Starting out with known and safe values in CurrentPositionInfo would make that a little more trustworthy.
  2. And in the case of getCurrentPosition (at least in the AAX wrapper) the function always returns true–even if an internal operation has failed. Might it return false in those cases?

I think you’re missing the point there - there’s no need for a default initialiser because any implementation of getCurrentPosition() has a responsibility to fill-in all the parameters with at least sensible null values.

Having a quick look, I notice that AAX wasn’t setting isPlaying or frameRate, so I’ll add some initialisers for those, but all the others seem to be ok?

Having a quick look, I notice that AAX wasn’t setting isPlaying or frameRate, so I’ll add some initialisers for those, but all the others seem to be ok?[/quote]
There’s more. The GetCurrentMeter call uses uninitialized values for num/denom. If the GetCurrentMeter call fails (which it does in some cases), then those uninitialized values are passed back in the info structure. Same thing goes for GetCurrentLoopPosition and perhaps a couple of other cases.

Ah… ok, try what I’ve just checked-in…

I get compile errors ([color=#BF0000]in argument to unary![/color] for example), but in looking at it I still see problems. Logic based on the result of the check call may actually be debug-dependent. I think there’s still a path through that leaves uninitted stuff in there. Many of the lower-level calls leave their parameters unchanged if there’s a missing descriptor or something along those lines. I think a better approach is to initialize the entire structure at the start of the call. If the internal calls succeed, then the values are replaced. If not, there’s still something safe in there. Here’s an example that works:

        bool getCurrentPosition (juce::AudioPlayHead::CurrentPositionInfo& info)
            const AAX_ITransport& transport = *Transport();

            info.bpm = 120.0f;
            info.timeSigNumerator = 4;
            info.timeSigDenominator = 4;
            info.timeInSamples = 0;
            info.timeInSeconds = 0.0f;
            info.editOriginTime = 0.0f;
            info.ppqPosition = 0.0f;
            info.ppqPositionOfLastBarStart = 0.0f;
            info.ppqLoopStart = 0.0f;
            info.ppqLoopEnd = 0.0f;
            info.isPlaying = false;
            info.isRecording = false;
            info.isLooping = false;
            info.frameRate = AudioPlayHead::fps30;
            check (transport.GetCurrentTempo (&info.bpm));

            transport.GetCurrentMeter (&info.timeSigNumerator, &info.timeSigDenominator);

            check (transport.GetCurrentNativeSampleLocation (&info.timeInSamples));
            info.timeInSeconds = info.timeInSamples / getSampleRate();

            int64_t ticks = 0;
            check (transport.GetCurrentTickPosition (&ticks));
            info.ppqPosition = ticks / 960000.0;

            int64_t loopStartTick = 0, loopEndTick = 0;
            check (transport.GetCurrentLoopPosition (&info.isLooping, &loopStartTick, &loopEndTick));
            info.ppqLoopStart = loopStartTick / 960000.0;
            info.ppqLoopEnd   = loopEndTick   / 960000.0;

            return true;

Thanks, will sort that out. Sorry about the compile error, am working very hurriedly today.

I sure know that feeling.