AudioProcessors need all the graphics code?

Hi, is there any reason that using an audio processor pulls in all the juce graphics code? Surely we should be able to pull in this basic audio functionality without needing all juce graphics code?

Is there any way to work around this?

Thx

1 Like

The problem is the AudioProcessorEditor. That one is a juce::Component.
The AudioProcessor has the createEditor method, so it has to include the AudioProcessorEditor.

At some point even under Fabian’s reign it was planned to untangle this, but it hasn’t happened.
I presume the plan was cancelled.

3 Likes

i think an easy solution is to just only treat the audio processor as the thing that connects audio and graphics, but let all the other hierarchical classes that process audio be something else

1 Like

@Mrugalla Not quite sure what you mean there, but audio processors should not really have any coupling to graphics. You can have an audio processing system that doesn’t need to interact with any graphical components.

yeah, in that case you could simply throw the include out of the cpp and return nullptr from createEditor and false from hasEditor

1 Like

That won’t solve the issue of having to build all of the Juce GUI and graphics stuff anyway for the project. The juce_audio_processors module depends on the juce_gui_extra module which in turn depends on juce_gui_basics which finally depends on juce_graphics. The original poster may have some special reason to want to avoid building all that other stuff.

1 Like

As @Daniel already said: AudioProcessor and AudioProcessorEditor are too co-depended on one anther. I also doubt that this will ever be changed.
@Mrugalla suggestions is the perfect work around. You can for example create a new target for a static library building only your audio related code with minimal dependencies and have bring that under unit test in-depended on any graphics code. Your final plugin compilation units may only contain the AudioProcessor forwarding everything to your static_library and returning nullptr for the editor stuff. I think this is as good as it is ever gonna get.

@xenakios - correct, I don’t want all the graphics code pulled in - for example, when delivering on Linux this pulls in a requirement to have freetype2 installed on the system which we don’t want as it’s a graphics library and we don’t have control of the target system and it’s not going to be there.

Does this mean you don’t host those AudioProcessors? In which case either using the dsp::ProcessorBase or a bespoke base class could be a solution.

1 Like

correct. thanks for the suggestion, but we’re using an AudioGraph so we need the AudioProcessors to add to the graph.

Ah I see, that’s a bummer.

Would be cool to have the AudioGraph with a different base class. TBH it would make a lot of sense, I think the only use case for AudioGraph with GUI is the AudioPluginHost…

1 Like

Just thinking out loud: seeing that the instance of the AudioProcessor of a plug-in is instantiated in a free function with signature:

AudioProcessor* JUCE_CALLTYPE createPluginFilter();

Maybe the editor for it could be created in a similar free function that takes the processor as a parameter:

AudioProcessorEditor* JUCE_CALLTYPE createPluginEditor(AudioProcessor*);

User classes derived from AudioProcessor that provide an editor, could still return it from a normal, not-overridden member function, like this:

class MyAudioProcessor : public AudioProcessor
{
...
public:
    /* this is a normal member function provided by MyAudioProcessor, 
     it does not override any function from base AudioProcessor, thus it's
     only at this point that the user code brings in the dependence from
     the graphics code. */
    AudioProcessorEditor* createMyEditor ();
... 
};

/* proposed implementation, maybe it could be improved with some template magic? */
AudioProcessorEditor* JUCE_CALLTYPE createPluginEditor(AudioProcessor* processor)
{
    if (processor == nullptr)
        return nullptr;

    if (auto* myAudioProcessor = dynamic_cast <MyAudioProcessor*> (processor))
        return myAudioProcessor->createMyEditor ();

    return new GenericAudioProcessorEditor (*processor);
}

1 Like