Call ChangeMessage() in HiResTimerCallback()

Hi there.
I’m working on an audio recording app, which will record continuously in windows of N minutes (the user can adjust the time of each audio file). I’ve decided to create a subclass of HighResolutionTimer and ChangeBroadcaster, because I have two Components (subclasses of ChangeListener) which record from an audio input device independently. There is a button calling sendSynchronousChangeMessage() and starting the timer to call sendSynchronousChangeMessage() repeatedly every N minutes.

The first time I push the button both components record the audio as expected. However, when the timer is called after N minutes I get the following:

ContinuousRecording.exe has triggered a breakpoint.

void ChangeBroadcaster::sendSynchronousChangeMessage()
{
    // This can only be called by the event thread.
    JUCE_ASSERT_MESSAGE_MANAGER_IS_LOCKED

    broadcastCallback.cancelPendingUpdate();
    callListeners();
}

It seems that I cannot call the changeMessage function in the timerCallback().

Is there a way to call a changeMessage function every N minutes without dealing with a Timer or HighResTimer??

Thanks!

HighResolutionTimer calls its timer callback on a dedicated thread, but Timer calls the timer callback on the message thread. For this reason, I’d recommend using a normal Timer rather than a HighResolutionTimer in this situation.

1 Like

Hi reuk, thanks for answering to my question. I’ve switched to a subclass of Timer. Now when the third recording start I get this:

void Component::internalRepaintUnchecked (Rectangle<int> area, bool isEntireComponent)
{
ContinuousRecording.exe has triggered a breakpoint.

    // if component methods are being called from threads other than the message
    // thread, you'll need to use a MessageManagerLock object to make sure it's thread-safe.
    JUCE_ASSERT_MESSAGE_MANAGER_IS_LOCKED

I’ve followed the AudioRecordingDemo project, so each RecordingComponent that I’ve created has a RecordingThumbnail showing the recorded audio and an AudioDeviceSelectorComponent. I can see that it has to do with a Component but I don’t know which one is triggering this error. I’m using VS2019, maybe there is a way to know which object it is.

Regarding the MessageManagerLock, the JUCE documentation shows an example, just by declaring a MessageManagerLock object. I’m not sure where to declare this object and how it would affect the performance of two audio recorders running at the same time.

I’m not an expert on threads or anything like that, so what would you recommend to solve this issue?

It’s difficult to say from the information you’ve provided. Visual Studio should show you the current stack trace at the point that the assertion is triggered. This stack trace will show you where the function is being called.

You probably shouldn’t add any additional MessageManagerLocks. Instead, it’s better to avoid calling component methods from background threads altogether.

1 Like

I think you’re right. I was trying to synchronise two recordings from different audio devices, that’s why I decided to use sendSynchronousChangeMessage(). It seems that it’s actually imposible to do that since there is no clock to sync them, so it wouldn’t make much difference to use ChangeListeners. I’ll try some other way. Thank you very very much!