FileSystemWatcher

A few people have asked for this in the past, I finally needed it, so here it is: https://github.com/FigBug/FileSystemWatcher

Monitor a directory and get notified when it changes. Implemented for Windows, Mac and Linux.

Enjoy.

18 Likes

I’m trying to make use of this class but must be doing something dumb as I can’t get it to work :confused:

class Blah 
{
public:
...
    class FileListener : public gin::FileSystemWatcher::Listener
    {
    public:
        FileListener() {};
        void folderChanged (const File folder) override;
        void fileChanged (const File file, gin::FileSystemWatcher::FileSystemEvent fsEvent) override;
    };
...
private:
...
    gin::FileSystemWatcher fileWatcher;
    FileListener fileListener;
}

I’m registering some folders to watch with fileWatcher.addFolder(...) and registering the listener with fileWatcher.addListener(&fileListener), but I never receive callbacks when anything changes under the folders I’m watching.
@RolandMR what am I doing wrong? Please help! :slight_smile:

What OS are you on? There are differences between the OSes how they handle recursive folders. If it’s not that, it should ā€˜just work’.

Does the demo app work for you? It watches the files on your desktop.

macOS 10.12.6
I’ll try out the demo. From the comments in the header I assumed on macOS and Windows it would watch all the way, and Linux didn’t do recursive watching. I did try even messing with the actual folder I was watching (renaming it) to no avail.

edit: point to clear up, I’m using the class contained in your gin module, I assume that should make no difference?

Demo works fine, callback is happening when deleting files in folders on my Desktop. I noticed that there is no virtual void fileChanged (const File, FileSystemEvent) {} in the Listener on the version linked above. I think for my purposes watching the folder will suffice, so I’ll give that a go instead of the gin version, but although my implementation seems essentially similar to the demo for this class, unfortunately it’s not working on my system :frowning:

ps. thanks for sharing this code anyway :slight_smile:

Yes, use the one in Gin. I stopped maintaining the one in it’s own repo. I don’t think you’ll get a notification if you modify the actual folder being watched, you just get notifications when it’s contents change.

OK, I think what I’ll try is making a noddy app like the demo to check that it’s not something about the rest of my app that is making the Gin version refuse to work.

pps. Gin is a great name. I want to grow up to be a muthaf…in’ hustla :joy:

OK, must be something up with my app that is causing a problem, because it does ā€œjust workā€ exactly as advertised when I implement a noddy app. :slight_smile: Dang…

I can’t think of anything that would stop it from working. Make sure you path is valid and that your listener isn’t going out of scope. Not sure what else it could be.

I have it working now.

What I didn’t mention above was that my actual class with FileSystemWatcher as a member was inheriting Thread and ActionBroadcaster, and after a process of elimination it seems FileSystemWatcher does not like to play ball in a class that inherits Thread.

Double checked the Listener wasn’t going out of scope, and the path name was correct, but it didn’t like to play with Thread, so after a bit of rearranging of my classes it’s now behaving exactly as expected.

@RolandMR I think this should be path.exists() rather than existsAsFile(). With existsAsFile() it sends a fileRenamedOldName event when a new folder is dropped into a watched folder, but I would expect a fileRenamedNewName event.

Fixed.

1 Like

I’m having the following issue with FileSystemWatcher on Windows:

basically, I’ve set it to watch only one folder, that’s inside my user directory.

While the watcher is watching folder, I do this on the message thread:

folder.deleteRecursively();

jassert (folder.isDirectory() == false);  // this assertion is passed 

folder.createDirectory();

jassert (folder.isDirectory() == true);   // this assertion is hit

Basically, it appears that the internals of FileSystemWatcher keep an handle on the original path of folder, that prevents it from being re-created.

I can take a look this weekend. I’m not sure what should happen here, probably the FileSystemWatcher should shut itself down when the folder gets delete. If you want to watch the newly created folder, you’ll need to manually restart the watcher.

Yes, I thought that would be the most sensible behavior.
Also, maybe an appropriate event (e.g. folderChange) could be signaled to the listeners so that they are notified about that.

One doubt about this, though: since the implementation relies on a background thread to watch for changes, is there a way to guarantee that it has a chance to run between these lines?

folder.deleteRecursively();
folder.createDirectory();

Because if there is no such guarantee, the watcher may pick up the folder deletion (and free up its handle) too late, when its creation has already been attempted and failed.