File Chooser async

I’m working on a port to AUv3 and it still has a few problems. One of them is the file chooser.
In the AUv3 version on Mac and iOS it dosen’t work at all. And on the standalone-app on iOS it opens a file chooser, but I can’t load files and if I creat and save a file it’s empty. Maybe it has to that it’s not implemented in an async way?

if (b == &savePreset){
    auto presetManager = processor->getPresetManager();
        
    String currentPresetPath = presetManager->getCurrentPresetDirectory() + directorySeparator + presetManager->getCurrentPresetName();
    
    FileChooser chooser ("Save Preset: ", File (currentPresetPath) ,presetFileExtensionWildcard);
    
    if (chooser.browseForFileToSave (true)){
        presetManager->savePreset (chooser.getResult());
        updatePresetComboBox();
    }
}

How would you do the same thing with asyncCallback? Or is there anything else specific to AUv3 that has to be done?

There is a minimal example of how to use launchAsync in the JUCE: FileChooser Class Reference documentation.

The gotchas I had when upgrading my plugins to JUCE 6.1 (not for AUv3):

  • FileChooser must not be stack allocated, else it will go out of scope and then “To abort the file selection, simply delete the FileChooser object.” comes into play.
  • Finding the flags in JUCE: FileBrowserComponent Class Reference took me longer than it should have.

Otherwise the process is pretty straightforward and you should have no problem adapting the example in the docs to your use case.

2 Likes

Thanks for your response, but I still have a few problems implementing it.
This is what I came up with so far

    auto presetManager = processor->getPresetManager();
    String currentPresetPath = presetManager->getCurrentPresetDirectory() + directorySeparator + presetManager->getCurrentPresetName();
    
    std::unique_ptr<FileChooser> myChooser;
    
    myChooser = std::make_unique<FileChooser> ("Please select the moose you want to save...",
                                               File (currentPresetPath),
                                               presetFileExtensionWildcard);
    
    auto folderChooserFlags = FileBrowserComponent::saveMode; // | FileBrowserComponent::warnAboutOverwriting;
    
    myChooser->launchAsync (folderChooserFlags, [this] (const FileChooser& chooser)
        {
        presetManager->savePreset (chooser.getResult());
        updatePresetComboBox();
    });

But I’m getting an error for “presetManager->savePreset (chooser.getResult());”
“Variable ‘presetManager’ cannot be implicitly captured in a lambda with no capture-default specified”

Your myChooser should be a member variable otherwise it will go out of scope and the dialogue will be dismissed.

You can solve the compile error either like this:

    myChooser->launchAsync (folderChooserFlags, [this, presetManager] (const FileChooser& chooser)
        {
        presetManager->savePreset (chooser.getResult());
        updatePresetComboBox();
    });

or by moving copying auto presetManager = processor->getPresetManager(); into the lambda. (I hadn’t noticed you use presetManager on the very next line! :man_facepalming:)

1 Like

Hmm, now it compiles but if I click the button it’s doing nothing.

What button?

Did you remember to move the std::unique_ptr<FileChooser> myChooser; into the header file?

void YourClass::savePreset()
{
    auto presetManager = processor->getPresetManager();
    String currentPresetPath = presetManager->getCurrentPresetDirectory() + directorySeparator + presetManager->getCurrentPresetName();
    
    std::unique_ptr<FileChooser> myChooser;    // you can't define myChooser here!
    
    myChooser = std::make_unique<FileChooser> ("Please select the moose you want to save...",
                                               File (currentPresetPath),
                                               presetFileExtensionWildcard);
    
    auto folderChooserFlags = FileBrowserComponent::saveMode; // | FileBrowserComponent::warnAboutOverwriting;
    
    myChooser->launchAsync (folderChooserFlags, [this] (const FileChooser& chooser)
        {
        presetManager->savePreset (chooser.getResult());
        updatePresetComboBox();
    });

    // myChooser goes out of scope here and the dialogue will be dismissed
}
1 Like

:man_facepalming: Damn should have seen this myself, thanks anyway

3 Likes

Just one more thing I found that has to be done to work in an AUv3, is changing

myChooser = std::make_unique (“Please select the moose you want to save…”, File (currentPresetPath), presetFileExtensionWildcard);

to

myChooser = std::make_unique (“Please select the moose you want to load…”, File (currentPresetDirectory), presetFileExtensionWildcard, true, false, this);

So I got the filechooser running on the standalone app, but it won’t open or save files outside the appfolder and the AUv3 (mac and iOS) dosen’t open or save files at all (Mac AUv3 dosen’t even open the filechooser)