mirror of
https://github.com/OpenRCT2/OpenRCT2.git
synced 2025-01-22 10:21:57 -05:00
Close #11473: Implement FileWatcher for macOS
This commit is contained in:
parent
f5043183f7
commit
960a989d05
7 changed files with 96 additions and 14 deletions
|
@ -3,7 +3,7 @@
|
|||
function(target_link_platform_libraries target)
|
||||
|
||||
if (APPLE)
|
||||
target_link_libraries(${target} "-framework Cocoa")
|
||||
target_link_libraries(${target} "-framework Cocoa -framework CoreServices")
|
||||
elseif(WIN32)
|
||||
target_link_libraries(${target} gdi32)
|
||||
endif ()
|
||||
|
|
|
@ -101,6 +101,7 @@ The following people are not part of the development team, but have been contrib
|
|||
* Andrew Pratt (andrewpratt64) - Added api hook for vehicle crashes, api function to get entities on a tile
|
||||
* Karst van Galen Last (AuraSpecs) - Ride paint (bounding boxes, extra track pieces), soundtrack, sound effects, misc.
|
||||
* (8street) - Misc.
|
||||
* Umar Ahmed (umar-ahmed) - MacOS file watcher
|
||||
|
||||
## Bug fixes
|
||||
* (KirilAngelov)
|
||||
|
|
|
@ -73,7 +73,7 @@ private:
|
|||
std::stack<DirectoryState> _directoryStack;
|
||||
|
||||
// Current
|
||||
FileInfo* _currentFileInfo;
|
||||
FileScanner::FileInfo* _currentFileInfo;
|
||||
utf8* _currentPath;
|
||||
|
||||
public:
|
||||
|
@ -84,7 +84,7 @@ public:
|
|||
_patterns = GetPatterns(Path::GetFileName(pattern));
|
||||
|
||||
_currentPath = Memory::Allocate<utf8>(MAX_PATH);
|
||||
_currentFileInfo = Memory::Allocate<FileInfo>();
|
||||
_currentFileInfo = Memory::Allocate<FileScanner::FileInfo>();
|
||||
|
||||
Reset();
|
||||
}
|
||||
|
@ -95,7 +95,7 @@ public:
|
|||
Memory::Free(_currentFileInfo);
|
||||
}
|
||||
|
||||
const FileInfo* GetFileInfo() const override
|
||||
const FileScanner::FileInfo* GetFileInfo() const override
|
||||
{
|
||||
return _currentFileInfo;
|
||||
}
|
||||
|
@ -349,7 +349,7 @@ void Path::QueryDirectory(QueryDirectoryResult* result, const std::string& patte
|
|||
auto scanner = Path::ScanDirectory(pattern, true);
|
||||
while (scanner->Next())
|
||||
{
|
||||
const FileInfo* fileInfo = scanner->GetFileInfo();
|
||||
const FileScanner::FileInfo* fileInfo = scanner->GetFileInfo();
|
||||
const utf8* path = scanner->GetPath();
|
||||
|
||||
result->TotalFiles++;
|
||||
|
|
|
@ -16,18 +16,21 @@
|
|||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
struct FileInfo
|
||||
namespace FileScanner
|
||||
{
|
||||
const utf8* Name;
|
||||
uint64_t Size;
|
||||
uint64_t LastModified;
|
||||
};
|
||||
struct FileInfo
|
||||
{
|
||||
const utf8* Name;
|
||||
uint64_t Size;
|
||||
uint64_t LastModified;
|
||||
};
|
||||
} // namespace FileScanner
|
||||
|
||||
struct IFileScanner
|
||||
{
|
||||
virtual ~IFileScanner() = default;
|
||||
|
||||
virtual const FileInfo* GetFileInfo() const abstract;
|
||||
virtual const FileScanner::FileInfo* GetFileInfo() const abstract;
|
||||
virtual const utf8* GetPath() const abstract;
|
||||
virtual const utf8* GetPathRelative() const abstract;
|
||||
|
||||
|
|
|
@ -18,8 +18,11 @@
|
|||
# include <sys/inotify.h>
|
||||
# include <sys/types.h>
|
||||
# include <unistd.h>
|
||||
#elif defined(__APPLE__)
|
||||
# include <CoreServices/CoreServices.h>
|
||||
#endif
|
||||
|
||||
#include "../core/Guard.hpp"
|
||||
#include "../core/Path.hpp"
|
||||
#include "../core/String.hpp"
|
||||
#include "FileSystem.hpp"
|
||||
|
@ -82,6 +85,39 @@ FileWatcher::WatchDescriptor::~WatchDescriptor()
|
|||
}
|
||||
#endif
|
||||
|
||||
#if defined(__APPLE__)
|
||||
|
||||
static int eventModified = kFSEventStreamEventFlagItemFinderInfoMod | kFSEventStreamEventFlagItemModified
|
||||
| kFSEventStreamEventFlagItemInodeMetaMod | kFSEventStreamEventFlagItemChangeOwner | kFSEventStreamEventFlagItemXattrMod;
|
||||
|
||||
static int eventRenamed = kFSEventStreamEventFlagItemCreated | kFSEventStreamEventFlagItemRemoved
|
||||
| kFSEventStreamEventFlagItemRenamed;
|
||||
|
||||
void FileWatcher::FSEventsCallback(
|
||||
ConstFSEventStreamRef streamRef, void* clientCallBackInfo, size_t numEvents, void* eventPaths,
|
||||
const FSEventStreamEventFlags eventFlags[], const FSEventStreamEventId eventIds[])
|
||||
{
|
||||
FileWatcher* fileWatcher = static_cast<FileWatcher*>(clientCallBackInfo);
|
||||
|
||||
Guard::Assert(fileWatcher != nullptr, "FileWatcher is null");
|
||||
Guard::Assert(fileWatcher->OnFileChanged != nullptr, "OnFileChanged is null");
|
||||
|
||||
char** paths = static_cast<char**>(eventPaths);
|
||||
for (size_t i = 0; i < numEvents; i++)
|
||||
{
|
||||
if (eventFlags[i] & eventModified)
|
||||
log_verbose("Modified: %s\n", paths[i]);
|
||||
if (eventFlags[i] & eventRenamed)
|
||||
log_verbose("Renamed: %s\n", paths[i]);
|
||||
|
||||
if (eventFlags[i] & eventModified || eventFlags[i] & eventRenamed)
|
||||
{
|
||||
fileWatcher->OnFileChanged(paths[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
FileWatcher::FileWatcher(u8string_view directoryPath)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
|
@ -103,6 +139,22 @@ FileWatcher::FileWatcher(u8string_view directoryPath)
|
|||
_watchDescs.emplace_back(_fileDesc.Fd, p.path().string());
|
||||
}
|
||||
}
|
||||
#elif defined(__APPLE__)
|
||||
CFStringRef path = CFStringCreateWithCString(kCFAllocatorDefault, directoryPath.data(), kCFStringEncodingUTF8);
|
||||
CFArrayRef pathsToWatch = CFArrayCreate(kCFAllocatorDefault, reinterpret_cast<const void**>(&path), 1, nullptr);
|
||||
CFAbsoluteTime latencyInSeconds = 0.5;
|
||||
FSEventStreamContext context = { 0, this, nullptr, nullptr, nullptr };
|
||||
|
||||
_stream = FSEventStreamCreate(
|
||||
NULL, &FSEventsCallback, &context, pathsToWatch, kFSEventStreamEventIdSinceNow, latencyInSeconds,
|
||||
kFSEventStreamCreateFlagFileEvents);
|
||||
|
||||
if (!_stream)
|
||||
{
|
||||
throw std::runtime_error("Unable to create FSEventStream");
|
||||
}
|
||||
|
||||
_runLoop = CFRunLoopGetCurrent();
|
||||
#else
|
||||
throw std::runtime_error("FileWatcher not supported on this platform.");
|
||||
#endif
|
||||
|
@ -119,6 +171,16 @@ FileWatcher::~FileWatcher()
|
|||
_finished = true;
|
||||
_watchThread.join();
|
||||
_fileDesc.Close();
|
||||
#elif defined(__APPLE__)
|
||||
if (_stream)
|
||||
{
|
||||
FSEventStreamStop(_stream);
|
||||
FSEventStreamUnscheduleFromRunLoop(_stream, _runLoop, kCFRunLoopDefaultMode);
|
||||
FSEventStreamInvalidate(_stream);
|
||||
FSEventStreamRelease(_stream);
|
||||
}
|
||||
_watchThread.join();
|
||||
_stream = nullptr;
|
||||
#else
|
||||
return;
|
||||
#endif
|
||||
|
@ -186,5 +248,12 @@ void FileWatcher::WatchDirectory()
|
|||
// Sleep for 1/2 second
|
||||
usleep(500000);
|
||||
}
|
||||
#elif defined(__APPLE__)
|
||||
if (_stream)
|
||||
{
|
||||
FSEventStreamScheduleWithRunLoop(_stream, _runLoop, kCFRunLoopDefaultMode);
|
||||
FSEventStreamStart(_stream);
|
||||
CFRunLoopRun();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -20,6 +20,8 @@
|
|||
# include "FileSystem.hpp"
|
||||
|
||||
typedef void* HANDLE;
|
||||
#elif defined(__APPLE__)
|
||||
# include <CoreServices/CoreServices.h>
|
||||
#endif
|
||||
|
||||
/**
|
||||
|
@ -54,6 +56,9 @@ private:
|
|||
|
||||
FileDescriptor _fileDesc;
|
||||
std::vector<WatchDescriptor> _watchDescs;
|
||||
#elif defined(__APPLE__)
|
||||
FSEventStreamRef _stream{};
|
||||
CFRunLoopRef _runLoop{};
|
||||
#endif
|
||||
|
||||
public:
|
||||
|
@ -65,6 +70,10 @@ public:
|
|||
private:
|
||||
#if defined(_WIN32) || defined(__linux__)
|
||||
bool _finished{};
|
||||
#elif defined(__APPLE__)
|
||||
static void FSEventsCallback(
|
||||
ConstFSEventStreamRef streamRef, void* clientCallBackInfo, size_t numEvents, void* eventPaths,
|
||||
const FSEventStreamEventFlags eventFlags[], const FSEventStreamEventId eventIds[]);
|
||||
#endif
|
||||
|
||||
void WatchDirectory();
|
||||
|
|
|
@ -1851,9 +1851,9 @@ Ride* Guest::FindBestRideToGoOn()
|
|||
return mostExcitingRide;
|
||||
}
|
||||
|
||||
BitSet<OpenRCT2::Limits::MaxRidesInPark> Guest::FindRidesToGoOn()
|
||||
OpenRCT2::BitSet<OpenRCT2::Limits::MaxRidesInPark> Guest::FindRidesToGoOn()
|
||||
{
|
||||
BitSet<OpenRCT2::Limits::MaxRidesInPark> rideConsideration;
|
||||
OpenRCT2::BitSet<OpenRCT2::Limits::MaxRidesInPark> rideConsideration;
|
||||
|
||||
// FIX Originally checked for a toy, likely a mistake and should be a map,
|
||||
// but then again this seems to only allow the peep to go on
|
||||
|
@ -3134,7 +3134,7 @@ template<typename T> static void peep_head_for_nearest_ride(Guest* peep, bool co
|
|||
}
|
||||
}
|
||||
|
||||
BitSet<OpenRCT2::Limits::MaxRidesInPark> rideConsideration;
|
||||
OpenRCT2::BitSet<OpenRCT2::Limits::MaxRidesInPark> rideConsideration;
|
||||
if (!considerOnlyCloseRides && (peep->HasItem(ShopItem::Map)))
|
||||
{
|
||||
// Consider all rides in the park
|
||||
|
|
Loading…
Reference in a new issue