I am building a basic console app on macOS, juce 7.0.9. I eventually realized that the MessageManager is not running, and so neither are timers, events, etc.
My goal is just to have timers and events - particularly ChangeListeners and ChangeBroadcasters.
I thought this was the recommended way
int main (int argc, char* argv[])
{
ScopedJuceInitialiser_GUI initialiser;
// other stuff
}
This does not work. MM might be created, but it is not servicing events. I tried adding
int main (int argc, char* argv[])
{
ScopedJuceInitialiser_GUI initialiser;
// other stuff
auto *mm = MessageManager::getInstance();
mm->setCurrentThreadAsMessageThread();
mm->runDispatchLoop();
}
Yes, having the message manager is not the same as it running the message loop.
When I want to run tests that need the message loop running, I make a GUI app with the start application macro have the app launch my code on a background thread.
If anyone has other ways, I’d be interested but that has been working for me.
Surge has a non gui cli version we use to do things like run raspberry pi headless stuff. To make osc work on it it has to run the message manager
We do it the kind obvious way. Or I guess the obvious way if you wrote uis back when you had to run your own message loop At the end of our main we do while true dispatch and have a break handler.
Thanks - not seeing anything in your test runner that would help.
Following the surge example, it is similar to what I tried. But it seems to assume that runDispatchLoop won’t block which is not what the documentation says
“This method is only intended to be run by the application’s startup routine, as it blocks, and will only return after the stopDispatchLoop() method has been used.”
runDispatchLoop was falling through in my code, which indicated to me that it was not working. It appears it is designed to fall through in the surge code. So I tried the surge approach anyway.
int main (int argc, char* argv[])
{
ScopedJuceInitialiser_GUI initialiser;
auto *mm = MessageManager::getInstance();
mm->setCurrentThreadAsMessageThread();
// create stuff that has timers
while (!done)
{
mm->runDispatchLoop();
Thread::sleep(25);
}
return 0;
}
Still doesn’t work. However, maybe “stuff that creates timers” needs to be in a different thread that somehow runs after runDispatchLoop? Not sure how that would be implemented.
You need to use START_JUCE_APPLICATION and inherit from JUCEApplication, and generally create stateful objects that extend the singular function call of main.
I created this ConsoleAppMessage thread example here that also spawns a timer:
Thanks. That fails when the projucer project type is “console application” because juce::JUCEApplication is not visible. The code you provided appears to be a stripped down version of the juce GUI application template, so I assume you intended for the projucer setting to be “GUI Application”.
I am trying to build a console application because that fits my needs best, however I have built it as a GUI app and it does work for a short while. The key problem with a GUI app is that when it is in the background, on macOS 12, mac mini…it stops running for 10 second intervals, and that will never work for what I am doing.
No - My example is using CMake, and not the Projucer, and it’s using juce_add_console_app which is the equivalent of the Projucer console app template.
You can generate a project from it by going to the root of the repo and type cmake -G Xcode -B build which would generate an Xcode project.
If you want to use the Projucer, you need to add the module “juce_gui_basics” to the Console app template.
(But I don’t recommend using the Projucer in this day and age).
Thanks for the github project! I was able to download and compare to my projucer project. I was missing the juce_graphics and juce_gui_basics modules. Tentatively, it looks like it will work for me - thanks!