[SOLVED] juce::FileChooser has no member browseForFileToOpen

Anybody knows how to fix that ? I am using latest JUCE 6.1.

Modal loops were disabled by default in the latest release. There’s an explanation in BreakingChanges.txt.

You can set the preprocessor definition JUCE_MODAL_LOOPS_PERMITTED=1 to re-enable them.

4 Likes

Thanks Connor!

I changed my code from:

class LoadSound : public ThreadWithProgressWindow
{
public:
    EightAudioProcessorEditor* editor;
    LoadSound(EightAudioProcessorEditor* editorInstance) : ThreadWithProgressWindow("Loading...", true, false)
    {
        editor = editorInstance;
    }

    void run()
    {
        wait(Random::getSystemRandom().nextInt(50) + 6);

        FileChooser chooser{ "Please load a File" };

        if (chooser.browseForFileToOpen())
        {
            auto file = chooser.getResult();
            std::unique_ptr<AudioFormatReader> formatReader(editor->mFormatManager.createReaderFor(file));
            if (formatReader)
            {
                editor->processor.clearSamplerSounds();
                BigInteger rangeMidiNotes;
                String fileName = file.getFileName();
                String fullFilePath = file.getFullPathName();
                String path = fullFilePath.substring(0, fullFilePath.length() - fileName.length() - 1);
                String parentPath = fullFilePath.substring(0, fullFilePath.length() - file.getParentDirectory().getFileName().length() - fileName.length() - 1);
                String fileNameWithoutVelocityNumber = SplitStringUntilSecondLastSeparator(fileName, "_");
                String fileNameWithoutVelocityNumberWithoutSampleNumber = SplitStringUntilSecondLastSeparator(fileNameWithoutVelocityNumber.substring(0, fileNameWithoutVelocityNumber.length() - 1), "_");

                int samples[6] = { 0, 1, 2, 7, 8, 10 };
                int samplesKeyAndPitch[6] = { 60, 62, 64, 67, 65, 69 };

                editor->keyboardComponent.setPlayRange(samplesKeyAndPitch[0] - 1, samplesKeyAndPitch[5] + 1);
                editor->keyboardComponent.repaint();

                int percentageIdx = 0;
                for (int sampleIdx = 0; sampleIdx < 6; sampleIdx++)
                {
                    int fileIdx = 1;
                    while (fileIdx <= 127)
                    {
                        if (threadShouldExit())
                            break;

                        file = File(parentPath + "note_" + std::to_string(samples[sampleIdx]) + "\\" + fileNameWithoutVelocityNumberWithoutSampleNumber + std::to_string(samples[sampleIdx]) + "_" + std::to_string(fileIdx) + ".wav");
                        if (file.existsAsFile())
                        {
                            rangeMidiNotes.setRange(samplesKeyAndPitch[sampleIdx], 1, true);
                            Range<float> rangeVelocity;
                            rangeVelocity.setStart(1.f / 127 * (fileIdx - 1));
                            rangeVelocity.setEnd(1.f / 127 * fileIdx);
                            editor->processor.addSamplerSound(fileIdx, file, rangeMidiNotes, samplesKeyAndPitch, rangeVelocity, sampleIdx);
                        }
                        fileIdx++;
                        percentageIdx++;
                        if (false) DBG(percentageIdx);
                        if (false) DBG((1 / (6 * 127)) * percentageIdx);
                        setProgress((1. / (6 * 127)) * percentageIdx);
                    }
                }
            }
        }
    }
};

to:

class LoadSound : public ThreadWithProgressWindow
{
public:
    EightAudioProcessorEditor* editor;
    LoadSound(EightAudioProcessorEditor* editorInstance) : ThreadWithProgressWindow("Loading...", true, false)
    {
        editor = editorInstance;
    }

    void run()
    {
        while (!threadShouldExit())
        {

            MessageManagerLock mmLock(Thread::getCurrentThread());

            if (!mmLock.lockWasGained())
                return;

            auto soundChooser = std::make_unique<FileChooser>("Please load a File");
            soundChooser->launchAsync(FileBrowserComponent::openMode | FileBrowserComponent::canSelectFiles, [this](const FileChooser& chooser)
                {

                    auto file = chooser.getResult();
                    if (file.exists())
                    {
                        auto file = chooser.getResult();
                        std::unique_ptr<AudioFormatReader> formatReader(editor->mFormatManager.createReaderFor(file));
                        if (formatReader)
                        {
                            editor->processor.clearSamplerSounds();
                            BigInteger rangeMidiNotes;
                            String fileName = file.getFileName();
                            String fullFilePath = file.getFullPathName();
                            String path = fullFilePath.substring(0, fullFilePath.length() - fileName.length() - 1);
                            String parentPath = fullFilePath.substring(0, fullFilePath.length() - file.getParentDirectory().getFileName().length() - fileName.length() - 1);
                            String fileNameWithoutVelocityNumber = SplitStringUntilSecondLastSeparator(fileName, "_");
                            String fileNameWithoutVelocityNumberWithoutSampleNumber = SplitStringUntilSecondLastSeparator(fileNameWithoutVelocityNumber.substring(0, fileNameWithoutVelocityNumber.length() - 1), "_");

                            int samples[6] = { 0, 1, 2, 7, 8, 10 };
                            int samplesKeyAndPitch[6] = { 60, 62, 64, 67, 65, 69 };

                            editor->keyboardComponent.setPlayRange(samplesKeyAndPitch[0] - 1, samplesKeyAndPitch[5] + 1);
                            editor->keyboardComponent.repaint();

                            int percentageIdx = 0;
                            for (int sampleIdx = 0; sampleIdx < 6; sampleIdx++)
                            {
                                int fileIdx = 1;
                                while (fileIdx <= 127)
                                {
                                    if (threadShouldExit())
                                        break;

                                    file = File(parentPath + "note_" + std::to_string(samples[sampleIdx]) + "\\" + fileNameWithoutVelocityNumberWithoutSampleNumber + std::to_string(samples[sampleIdx]) + "_" + std::to_string(fileIdx) + ".wav");
                                    if (file.existsAsFile())
                                    {
                                        rangeMidiNotes.setRange(samplesKeyAndPitch[sampleIdx], 1, true);
                                        Range<float> rangeVelocity;
                                        rangeVelocity.setStart(1.f / 127 * (fileIdx - 1));
                                        rangeVelocity.setEnd(1.f / 127 * fileIdx);
                                        editor->processor.addSamplerSound(fileIdx, file, rangeMidiNotes, samplesKeyAndPitch, rangeVelocity, sampleIdx);
                                    }
                                    fileIdx++;
                                    percentageIdx++;
                                    if (false) DBG(percentageIdx);
                                    if (false) DBG((1 / (6 * 127)) * percentageIdx);
                                    setProgress((1. / (6 * 127)) * percentageIdx);
                                }
                            }
                        }
                    }
                });
        }
    }
};

But now the dialog doesn’t open at all.

The FileChooser object is being deleted before you’ve had a chance to interact with it. If you make the std::unique_ptr<FileChooser> soundChooser a member of your class, it should work.

1 Like

Made it a class member but seems not to work.

class LoadSound : public ThreadWithProgressWindow
{
public:
    EightAudioProcessorEditor* editor;
    LoadSound(EightAudioProcessorEditor* editorInstance) : ThreadWithProgressWindow("Loading...", true, false)
    {
        editor = editorInstance;
    }

    std::unique_ptr<FileChooser> soundChooser;

    void run()
    {
        while (!threadShouldExit())
        {
            MessageManagerLock mmLock(Thread::getCurrentThread());

            if (!mmLock.lockWasGained())
                return;

            soundChooser = std::make_unique<FileChooser>("Please load a File");
            soundChooser->launchAsync(FileBrowserComponent::openMode | FileBrowserComponent::canSelectFiles, [this](const FileChooser& chooser)
                {

                    auto file = chooser.getResult();
                    if (file.exists())
                    {
                        auto file = chooser.getResult();
                        std::unique_ptr<AudioFormatReader> formatReader(editor->mFormatManager.createReaderFor(file));
                        if (formatReader)
                        {
                            editor->processor.clearSamplerSounds();
                            BigInteger rangeMidiNotes;
                            String fileName = file.getFileName();
                            String fullFilePath = file.getFullPathName();
                            String path = fullFilePath.substring(0, fullFilePath.length() - fileName.length() - 1);
                            String parentPath = fullFilePath.substring(0, fullFilePath.length() - file.getParentDirectory().getFileName().length() - fileName.length() - 1);
                            String fileNameWithoutVelocityNumber = SplitStringUntilSecondLastSeparator(fileName, "_");
                            String fileNameWithoutVelocityNumberWithoutSampleNumber = SplitStringUntilSecondLastSeparator(fileNameWithoutVelocityNumber.substring(0, fileNameWithoutVelocityNumber.length() - 1), "_");

                            int samples[6] = { 0, 1, 2, 7, 8, 10 };
                            int samplesKeyAndPitch[6] = { 60, 62, 64, 67, 65, 69 };

                            editor->keyboardComponent.setPlayRange(samplesKeyAndPitch[0] - 1, samplesKeyAndPitch[5] + 1);
                            editor->keyboardComponent.repaint();

                            int percentageIdx = 0;
                            for (int sampleIdx = 0; sampleIdx < 6; sampleIdx++)
                            {
                                int fileIdx = 1;
                                while (fileIdx <= 127)
                                {
                                    if (threadShouldExit())
                                        break;

                                    file = File(parentPath + "note_" + std::to_string(samples[sampleIdx]) + "\\" + fileNameWithoutVelocityNumberWithoutSampleNumber + std::to_string(samples[sampleIdx]) + "_" + std::to_string(fileIdx) + ".wav");
                                    if (file.existsAsFile())
                                    {
                                        rangeMidiNotes.setRange(samplesKeyAndPitch[sampleIdx], 1, true);
                                        Range<float> rangeVelocity;
                                        rangeVelocity.setStart(1.f / 127 * (fileIdx - 1));
                                        rangeVelocity.setEnd(1.f / 127 * fileIdx);
                                        editor->processor.addSamplerSound(fileIdx, file, rangeMidiNotes, samplesKeyAndPitch, rangeVelocity, sampleIdx);
                                    }
                                    fileIdx++;
                                    percentageIdx++;
                                    if (false) DBG(percentageIdx);
                                    if (false) DBG((1 / (6 * 127)) * percentageIdx);
                                    setProgress((1. / (6 * 127)) * percentageIdx);
                                }
                            }
                        }
                    }
                });
        }
    }
};

Also tried this one.

class LoadSound : public ThreadWithProgressWindow
{
public:
    EightAudioProcessorEditor* editor;
    LoadSound(EightAudioProcessorEditor* editorInstance) : ThreadWithProgressWindow("Loading...", true, false)
    {
        editor = editorInstance;
    }

    std::unique_ptr<FileChooser> soundChooser = std::make_unique<FileChooser>("Please load a File");;

    void run()
    {
        while (!threadShouldExit())
        {
            MessageManagerLock mmLock(Thread::getCurrentThread());

            if (!mmLock.lockWasGained())
                return;

            soundChooser->launchAsync(FileBrowserComponent::openMode | FileBrowserComponent::canSelectFiles, [this](const FileChooser& chooser)
                {
...

I’m just now noticing that you’re invoking this from a non-message thread. I’m guessing that’s the issue now, since your MessageManagerLock is going out of scope while the FileChooser does its thing asynchronously. I’ve not used FileChooser functions from a background thread like this, so I’m not 100% sure.

If your previous implementation using browseForFileToOpen() was working, it’s probably easiest to just add JUCE_MODAL_LOOPS_PERMITTED=1 to the Projucer’s “Preprocessor Definitions” field and stick to that. Otherwise I’d suggest launching the FileChooser from the message thread, and passing its results to your Thread object before you start the thread.

Thanks Connor for your help! I will use the preprocessor definition JUCE_MODAL_LOOPS_PERMITTED.

GREAT CALL! Thanks for this thread!

Hi. I have exactly the same problem.
And if I just have a FileChooser as a class member, I get this error when I destroy (close) a component:
Capture

It is enough just to have it as a class member to get this error. No need to call lanchAsync.

I suspect that error is due to another issue in your code somehwere, because making a FileChooser a class member on its own is not going to cause a runtime error…

How is the class to which you’re adding the FileChooser member defined, and how are you using it?