JUCE Class to get list of files in folder

I have used the “juce::FileChooser” to allow the synth I am building to load a wav file and use as a wavetable/LUT waveform, and it works great.

I am aware that I can specify the folder where to pick a file, however it is still tedious to open the file browser each time I want to load the next wav file.

I am looking for a class that let’s me retrieve to a list, all in this case wav files in a folder, so I can use my own interface to quickly browse through and play/test wav files. Is there such a JUCE class?

You mean File::findChildFiles ? That’ll give you the list of files for sure. In terms of browsing them, you have a few ways to skin that cat from a UI perspective!

1 Like

Great it looks to be exactly what I am looking for, thanks!

Ok using findChildFiles I get files to an Array of type .

File f ("d:/documents/development/");
Array<File> waveformList;
waveformList = f.findChildFiles (2, false, "*.wav");

And I can see how many files the array contains using; waveformList.size ().

But for starters I just want to output to my screen component the file names, but I failed to discover how to convert a Array element to a String so I can draw the name on the screen with something similar to this;

String test = String (waveformList[0]); // However this won't work!

Well I guess that problem needs to go in a separate post.

Well, what about the name or String you want pull out? And where + how do you plan on storing and displaying the data?

Fundamentally, you need to iterate the provided Array and get the specific info you need. Say you just wanted the filenames, no path, no extension. You could store those details in a StringArray for, say, a ListBox.

// A member var for your ListBoxModel (https://docs.juce.com/master/classListBoxModel.html):
StringArray filenames;

// Some function that updates your filenames:
filenames.clear();

for (const auto& filenameThatWasFound : File ("PathToSearchForWavFiles").findChildFiles (2, false, "*.wav"))
    filenames.add (filenameThatWasFound.getFileNameWithoutExtension());

// Tell the ListBox that the stuff has changed, assuming the model is based on the member var 'filenames':
myListboxMemberVar.updateContent();

There’s also RangedDirectoryIterator:
https://docs.juce.com/master/classRangedDirectoryIterator.html

std::vector<juce::File> hiddenFiles;
 
for (juce::DirectoryEntry entry : juce::RangedDirectoryIterator (juce::File ("/path/to/folder"), isRecursive))
    if (entry.isHidden())
        hiddenFiles.push_back (entry.getFile());

Ok I gotten so far that I can display a list of wav files in a Component, but rather than reinventing the wheel and make code to scroll through files and load, I see that there is a “FileBrowserComponent”. So I am trying to replace my normal Component with this, but I can’t figure out it’s needed constructor.

This is what I got in my h file;

class WaveformLoad  : public juce::FileBrowserComponent, public juce::Button::Listener
{
public:
    WaveformLoad();
    ~WaveformLoad() override;
    ...

private:
    File f = "d:/documents/development/";

and in my cpp file;

WaveformLoad::WaveformLoad() : FileBrowserComponent (1, f)
{
}

I would appreciate if someone will tell what I am doing wrong here, thanks!

You don’t say what is going wrong. Are you getting a compile error or something? My guess is you wouldn’t be able to select any files in the list. That’s because the canSelectFiles flag is not set.

You should really use the flag symbols, not integers, for the flags. If you want to select a single file for opening, for example, you can pass:

FileBrowserComponent::openMode+FileBrowserComponent::canSelectFiles

Is that enough info for you?

Thanks for your continued assistance. I get the following error at the opening parenthesis;
“C++ no instance of constructor matches the argument list argument types are: (int, juce::File)”

Look at the constructor for FileBrowserComponent, in the header file. As you can see, it takes four parameters, but you only pass two. They are not optional parameters (as you can see by the fact that they are not given default values). You can pass nullptr for those last two, but you can’t leave them out.

1 Like

Ok I read “optional” and though they could be left out, thanks one step closer now :slight_smile:

Ouch I spoke too soon. Plugin now crashes upon start attempt, damn.

WaveformLoad::WaveformLoad() : FileBrowserComponent (5, f, nullptr, nullptr)
{
}

Seems I am not understanding how to use the FileBrowserComponent. I assumed I could keep my regular component’s paint(), resize() and so on functions/code.

Seems I do need to make a custom browser, because my component needs the user to smoothly scroll through a list of wav files, and display a visual waveform graph of the file currently selected, along with an interface to select a segment or all of the waveform to import into a wavetable/look up table.

Ah, that’s a documentation problem you could let JUCE know about (if they aren’t reading this already). The function definition says otherwise. :slight_smile:

I’d still recommend using the flag names, not integers, in case those values ever change (and to make it easier to look at your code and know what it means).

I just plop a FileBrowserComponent down onto my component. I don’t try deriving a new class from it. Here’s a snippet from my Component’s constructor:

//[Constructor_pre] You can add your own custom stuff here..
int flags = FileBrowserComponent::saveMode + FileBrowserComponent::canSelectDirectories + FileBrowserComponent::useTreeView;
	initialFileOrDirectoryPath = trackedAudioManager.getTrackedDataFolderPath();
if (initialFileOrDirectoryPath.isEmpty())
	initialFileOrDirectoryPath = File::getSpecialLocation(File::userDocumentsDirectory).getFullPathName();
	File initialFileOrDirectory( initialFileOrDirectoryPath );
//[/Constructor_pre]

fileMgmtBrowser.reset (new FileBrowserComponent (flags, initialFileOrDirectory, nullptr, nullptr));
addAndMakeVisible (fileMgmtBrowser.get());
fileMgmtBrowser->setName ("fileMgmtBrowser");