103 lines
3.5 KiB
C++
103 lines
3.5 KiB
C++
// Copyright (c) 2012-2024 Wojciech Figat. All rights reserved.
|
|
|
|
#if PLATFORM_MAC
|
|
#include "MacFileSystemWatcher.h"
|
|
#include "Engine/Platform/Apple/AppleUtils.h"
|
|
#include "Engine/Platform/CriticalSection.h"
|
|
#include "Engine/Platform/Thread.h"
|
|
#include "Engine/Threading/ThreadSpawner.h"
|
|
#include "Engine/Core/Collections/Array.h"
|
|
#include "Engine/Core/Types/StringView.h"
|
|
|
|
void DirectoryWatchCallback( ConstFSEventStreamRef StreamRef, void* FileWatcherPtr, size_t EventCount, void* EventPaths, const FSEventStreamEventFlags EventFlags[], const FSEventStreamEventId EventIDs[] )
|
|
{
|
|
MacFileSystemWatcher* macFileSystemWatcher = (MacFileSystemWatcher*)FileWatcherPtr;
|
|
if (macFileSystemWatcher)
|
|
{
|
|
CFArrayRef EventPathArray = (CFArrayRef)EventPaths;
|
|
for( size_t EventIndex = 0; EventIndex < EventCount; ++EventIndex )
|
|
{
|
|
const FSEventStreamEventFlags Flags = EventFlags[EventIndex];
|
|
if( !(Flags & kFSEventStreamEventFlagItemIsFile) && !(Flags & kFSEventStreamEventFlagItemIsDir) )
|
|
{
|
|
// events about symlinks don't concern us
|
|
continue;
|
|
}
|
|
|
|
auto action = FileSystemAction::Unknown;
|
|
|
|
const bool added = ( Flags & kFSEventStreamEventFlagItemCreated );
|
|
const bool renamed = ( Flags & kFSEventStreamEventFlagItemRenamed );
|
|
const bool modified = ( Flags & kFSEventStreamEventFlagItemModified );
|
|
const bool removed = ( Flags & kFSEventStreamEventFlagItemRemoved );
|
|
|
|
if (added)
|
|
{
|
|
action = FileSystemAction::Create;
|
|
}
|
|
if (renamed)
|
|
{
|
|
action = FileSystemAction::Rename;
|
|
}
|
|
if (rmodified)
|
|
{
|
|
action = FileSystemAction::Modify;
|
|
}
|
|
if (removed)
|
|
{
|
|
action = FileSystemAction::Delete;
|
|
}
|
|
|
|
const String resolvedPath = AppleUtils::ToString((CFStringRef)CFArrayGetValueAtIndex(EventPathArray,EventIndex));
|
|
|
|
macFileSystemWatcher->OnEvent(resolvedPath, action);
|
|
}
|
|
}
|
|
}
|
|
|
|
MacFileSystemWatcher::MacFileSystemWatcher(const String& directory, bool withSubDirs)
|
|
: FileSystemWatcherBase(directory, withSubDirs)
|
|
{
|
|
|
|
CFStringRef FullPathMac = AppleUtils::ToString(StringView(directory));
|
|
CFArrayRef PathsToWatch = CFArrayCreate(NULL, (const void**)&FullPathMac, 1, NULL);
|
|
|
|
CFAbsoluteTime Latency = 0.2;
|
|
|
|
FSEventStreamContext Context;
|
|
Context.version = 0;
|
|
Context.info = this;
|
|
Context.retain = NULL;
|
|
Context.release = NULL;
|
|
Context.copyDescription = NULL;
|
|
|
|
EventStream = FSEventStreamCreate( NULL,
|
|
&DirectoryWatchCallback,
|
|
&Context,
|
|
PathsToWatch,
|
|
kFSEventStreamEventIdSinceNow,
|
|
Latency,
|
|
kFSEventStreamCreateFlagUseCFTypes | kFSEventStreamCreateFlagNoDefer | kFSEventStreamCreateFlagFileEvents
|
|
);
|
|
|
|
CFRelease(PathsToWatch);
|
|
CFRelease(FullPathMac);
|
|
|
|
FSEventStreamScheduleWithRunLoop( EventStream, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode );
|
|
FSEventStreamStart( EventStream );
|
|
|
|
IsRunning = true;
|
|
}
|
|
|
|
MacFileSystemWatcher::~MacFileSystemWatcher()
|
|
{
|
|
if (IsRunning)
|
|
{
|
|
FSEventStreamStop(EventStream);
|
|
FSEventStreamUnscheduleFromRunLoop(EventStream, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
|
|
FSEventStreamInvalidate(EventStream);
|
|
FSEventStreamRelease(EventStream);
|
|
}
|
|
}
|
|
#endif
|