.jucer GUI project run on Linux without desktop... can I?

@kcoul,
Glad to hear that, so I’ll try to stick with JUCE 6.

Regarding CMake… I did use it to build JUCE examples/extras to include Projucer and DemoRunner among others. The application in question is just using the LinuxMake environment that Projucer originally created. The work was originally done on a Pi, but was moved over to Ubuntu a while back.

My hopeful plan is that I have only one build with conditional logic that will make the GUI-or-NOTGUI decisions.

@kcoul,
I don’t understand why the thread context would matter; but I moved all calls to loadImpulseResponse() to be done on the first invocation of getNextAudioBlock().
Didn’t make any difference.

You shouldn’t create any Component at all. They will when added to the desktop create a ComponentPeer, which is the connection to the window system. From that point the X libraries will be loaded and it won’t run without X11.

You can use AudioDeviceManager to open the audio device and AudioSourcePlayer to play from any kind of AudioSource.
Hosting AudioProcessors is already tricky, I don’t know if it will work, since the createEditor() will return a Component. The juce_audio_processors depends on juce_gui_basics and juce_gui_extra for that reason.

@daniel,
ok, now that’s scaring me…
First, note that this is an already-created project (actually, its a few years old now), that just recently has the need to run headless. I’m not sure what you mean by “You shouldn’t create any Component at all”; but that sounds like your saying that creation of the MainComponent implies that X11 is an underlying requirement. Is that the case?
By the way, just in case it isn’t already obvious, I am very new to JUCE, so I apologize if I’m asking some dumb questions here…

You might get away if it is not added to the desktop: Component.addToDesktop (windowFlags)

Alternatively there was a wrapper you can use on linux to run even if it’s headless.
xvfb is the command

xvfb…
I’ll look into that, thanks…

@edsut it would be best if you move the issues that you are having with the Convolution class into a separate thread so that we can help you there and address your original question about headless Linux support in this thread.

If you run your application built with the latest version of JUCE the headless support allows you to run the same executable on a system both with and without the X11 libraries installed and you can use the Desktop::isHeadless() method to query this at runtime.

2 Likes

Ok, I’ll start a new topic for the crash…
Glad to hear I’m on the right track with JUCE 6.

Thanks for that answer, @reuk, I do have to say, that documentation is a bit confusing to me.

I see two use cases here:

  1. The ‘load’ function happens from the GUI/Preset load/etc.

In that case I’m totally fine with the sync mechanism of the convolution engine taking a bit of time and maybe still running the old impulse response on a couple of process calls until loading is done.

  1. The ‘load’ function happens as a part of a linear process.
    For example when loading the impulse response and immediately doing the processing on it, such as the case with offline export, or with a visualizer of the IR.

In that case, I need a way to be absolutely sure that the IR is loaded when I call process(), and I’m willing to take the cost of the extra waiting/memory allocation just to get predictable results.

What is the correct way to call this method for each use case?

In general, calls to loadImpulseResponse load the impulse response (IR) asynchronously. The IR will become active once it has been completely loaded and processed, which may take some time.

Calling prepare() will ensure that the IR supplied to the most recent call to loadImpulseResponse() is fully initialised. This IR will then be active during the next call to process(). You can call loadImpulseResponse() before prepare() if a specific IR must be active during the first process() call.

For case 1, you’d call loadImpulseResponse from within the context of the audio callback. The loading will then happen asynchronously.

For case 2, you’d call loadImpulseResponse before prepare, which would make the IR available for immediate use in the next audio callback. There is not currently a way to replace the IR “immediately” without calling prepare, so replacing the IR at a particular sample count during offline rendering (for example) is not possible.

1 Like

Thanks @reuk for the detailed answer!

Can you explain more on the need to call loadImpulseResponse from the audio thread instead of the message thread (for case 1)

I was under the impression that this function would return immediately regardless of which thread is called, and then would sync the result in a background thread, to be ready for the audio thread whenever process() is called (or after a few process() calls)

Is that not the case?

If indeed it’s needed on the audio thread, the I need to add yet another sync mechanism to sync from the GUI to the audio thread before making that call, which is not trivial for something like a file, buffer, etc.

How about making the loadImpulseResponse() a new thread as well? This communication here is all over the place :wink:

2 Likes

Yep, seconded. Please start a new thread for this question, and I’ll answer there.

1 Like

@ed95,
Ok, I’m sticking to just the desktop issue in this thread…
I created an empty “Audio” application with Projucer and added a check for the desktop as you suggest. I assume it has at the top of Main.cpp…

    if (!juce::Desktop::getInstance().isHeadless())
        mainWindow.reset (new MainWindow (getApplicationName()));

Assuming this is the correct place to put it, I immediately see that this causes MainComponent to not be instantiated when headless. That’s good; but then how do I get the equivalent of MainComponent::getNextAudioBlock()?

BTW, your welcome to just point me to docs, I’m not trying to be a mooch here, just trying to get over this hump quickly.

The Audio project template is just a quick way of setting up a window with some audio and MIDI I/O capabilities and isn’t really designed for more complex applications since the audio functionality is tightly coupled to the window itself.

I’d recommend starting a new project using the GUI template, adding the juce_audio_devices module, and taking a look at the docs for the AudioDeviceManager and AudioIODeviceCallback classes to set up your audio processing independent from the GUI.

1 Like

Thanks for this tip! I think with this info it should be possible for me to make a template for dual headless/withGUI modes in a single project. @edsut I’ll share it on Github and post it here, it sounds like if you had it you could refactor your codebase using the template.

@kcoul,
That would be great, thanks.
Ed

Is there currently -any- example of JUCE audio processing that is not derived from a GUI based application?

@KottVV,
Thanks, AFAIK MIDI is command/control/sync for musical instrumentation right?
Sorry if this is a dumb question, aside from some reading, I’ve done nothing with MIDI…
Does this actually do any audio signal processing? If yes, I couldn’t find it.