This Trac instance is not used for development anymore!

We migrated our development workflow to git and Gitea.
To test the future redirection, replace trac by ariadne in the page URL.

source: ps/trunk/source/lib/sysdep/os/osx/dir_watch.cpp

Last change on this file was 24352, checked in by wraitii, 4 years ago

Further header & precompiled cleanup, fix no-PCH builds.

GUIObjectBase is made a IGUIObject* to avoid including those headers un-necessarily. Subsequent diffs ought to clean up the various of pointers for that with a similar type with reference semantics.

Also:

  • Add standard C and C++ headers (mostly cstring for memcpy, string and vector) where needed.
  • Swap out some includes for forward declarations
  • Clean up un-necessary boost includes in precompiled and other headers.
  • Clean up precompiled headers, including fewer things.
  • Move ACPI to the windows-specific folder as it's included there only and mostly specific to that platform.

Thanks Stan for the testing.

Differential Revision: https://code.wildfiregames.com/D3129

  • Property svn:eol-style set to native
File size: 6.2 KB
RevLine 
[24352]1/* Copyright (C) 2020 Wildfire Games.
[6830]2 *
[7316]3 * Permission is hereby granted, free of charge, to any person obtaining
4 * a copy of this software and associated documentation files (the
5 * "Software"), to deal in the Software without restriction, including
6 * without limitation the rights to use, copy, modify, merge, publish,
7 * distribute, sublicense, and/or sell copies of the Software, and to
8 * permit persons to whom the Software is furnished to do so, subject to
9 * the following conditions:
[18989]10 *
[7316]11 * The above copyright notice and this permission notice shall be included
12 * in all copies or substantial portions of the Software.
[18989]13 *
[7316]14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
18 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
19 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
20 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
[6830]21 */
22
[6828]23#include "precompiled.h"
[13821]24
[6828]25#include "lib/sysdep/dir_watch.h"
[13821]26#include "lib/file/file_system.h"
27#include "osx_sys_version.h"
[6828]28
[13821]29#include "lib/os_path.h"
30#include "lib/file/file.h"
31#include "lib/posix/posix_filesystem.h" // mode_t
[6828]32
[24352]33#include "ps/CLogger.h"
34
[14140]35#include <AvailabilityMacros.h> // MAC_OS_X_VERSION_MIN_REQUIRED
[18989]36#include <CoreFoundation/CoreFoundation.h>
37#include <CoreServices/CoreServices.h>
[13821]38
[24352]39#include <vector>
[13821]40
[18989]41static FSEventStreamRef g_Stream = NULL;
[13821]42
43struct DirWatch
[6828]44{
[13821]45 OsPath path;
46 int reqnum;
47};
48
49typedef std::vector<DirWatch> DirWatchMap;
50static DirWatchMap g_Paths;
51static DirWatchMap g_RootPaths;
52static DirWatchNotifications g_QueuedDirs;
53
[15997]54static bool CanRunNotifications()
[13821]55{
56 int major = 0;
[18989]57 int minor = 0;
58 int bugfix = 0;
[13821]59
60 GetSystemVersion( major, minor, bugfix);
61
62 if ((major == 10 && minor >= 7) || major >= 11)
63 return true;
64
65 return false;
66}
67
[14140]68#if MAC_OS_X_VERSION_MIN_REQUIRED < 1070
[13821]69 #define kFSEventStreamCreateFlagFileEvents 0x00000010
70 #define kFSEventStreamEventFlagItemIsFile 0x00010000
71 #define kFSEventStreamEventFlagItemRemoved 0x00000200
72 #define kFSEventStreamEventFlagItemRenamed 0x00000800
73 #define kFSEventStreamEventFlagItemCreated 0x00000100
74 #define kFSEventStreamEventFlagItemModified 0x00001000
75#endif
76
77static void fsevent_callback(
78 ConstFSEventStreamRef UNUSED(streamRef),
79 void * UNUSED(clientCallBackInfo),
80 size_t numEvents,
81 void *eventPaths,
82 const FSEventStreamEventFlags eventFlags[],
83 const FSEventStreamEventId UNUSED(eventIds)[] )
84{
85 unsigned long i;
86 char **paths = (char **)eventPaths;
[18989]87
[13821]88 for (i=0; i<numEvents; i++)
89 {
90 bool isWatched = false;
91 OsPath eventPath = OsPath(paths[i]);
92 unsigned long eventType = eventFlags[i];
93
94 if ( eventPath.Filename().string().c_str()[0] != '.' )
95 {
96 for ( DirWatchMap::iterator it = g_Paths.begin() ; it != g_Paths.end(); ++it)
97 if ( path_is_subpath( it->path.string().c_str(), eventPath.string().c_str() ) )
98 isWatched = true;
99 }
100
101 if ( ! isWatched )
102 return;
103
104 OsPath filename = Path( eventPath.string().c_str() );
105
106 if ( eventType & kFSEventStreamEventFlagItemIsFile)
107 {
108 if ( eventType & kFSEventStreamEventFlagItemRemoved )
109 g_QueuedDirs.push_back(DirWatchNotification( filename.string().c_str(), DirWatchNotification::Deleted ));
110 else if ( eventType & kFSEventStreamEventFlagItemRenamed )
111 g_QueuedDirs.push_back(DirWatchNotification( filename.string().c_str(), DirWatchNotification::Deleted ));
112 else if ( eventType & kFSEventStreamEventFlagItemCreated )
113 g_QueuedDirs.push_back(DirWatchNotification( filename.string().c_str(), DirWatchNotification::Created ));
114 else if ( eventType & kFSEventStreamEventFlagItemModified )
115 g_QueuedDirs.push_back(DirWatchNotification( filename.string().c_str(), DirWatchNotification::Changed ));
116 }
117 }
118
119}
120
[15997]121static FSEventStreamRef CreateEventStream( DirWatchMap path )
[13821]122{
[15748]123 if ( ( g_Stream == NULL ) && CanRunNotifications() && !path.empty() )
[13821]124 {
125 CFStringRef* pathLists = (CFStringRef*)malloc( sizeof(CFStringRef*) * path.size() );
126 int index = 0;
127 for ( DirWatchMap::iterator it = path.begin() ; it != path.end(); ++it)
128 {
129 pathLists[index] = CFStringCreateWithFileSystemRepresentation( NULL, OsString(it->path).c_str());
130 index++;
131 }
132 CFArrayRef pathsToWatch = CFArrayCreate(NULL, (const void **)pathLists, index, NULL);
133
134 FSEventStreamContext *callbackInfo = NULL;
[18989]135
[13821]136 FSEventStreamRef stream = FSEventStreamCreate(NULL, &fsevent_callback, callbackInfo, pathsToWatch,
137 kFSEventStreamEventIdSinceNow, 1.0, kFSEventStreamCreateFlagFileEvents );
138
139 CFRelease( pathsToWatch );
140 free( pathLists );
141
142 FSEventStreamScheduleWithRunLoop(stream, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
[18989]143 if (!FSEventStreamStart(stream))
144 debug_warn(L"event_loop FSEventStreamStart failed!");
[13821]145 else
146 return stream;
147 }
148 return NULL;
149}
150
[15997]151static void DeleteEventStream()
[13821]152{
153 if ( g_Stream != NULL )
154 {
155 FSEventStreamStop(g_Stream);
156 FSEventStreamInvalidate(g_Stream);
157 FSEventStreamRelease(g_Stream);
158
159 g_Stream = NULL;
160 }
161}
162
163
164Status dir_watch_Add(const OsPath& path, PDirWatch& dirWatch)
165{
166 PDirWatch tmpDirWatch(new DirWatch);
167 dirWatch.swap(tmpDirWatch);
168 dirWatch->path = path;
169 dirWatch->reqnum = 0;
170 g_Paths.push_back( *dirWatch );
171
172 bool alreadyInsideRootPath = false;
173 for ( DirWatchMap::iterator it = g_RootPaths.begin() ; it != g_RootPaths.end(); ++it)
174 {
175 if ( path_is_subpath( path.string().c_str(), it->path.string().c_str() ) )
176 alreadyInsideRootPath = true;
177 }
178
179 if ( !alreadyInsideRootPath )
180 {
181 DeleteEventStream();
182 g_RootPaths.push_back( *dirWatch );
183 }
184
[6828]185 return INFO::OK;
186}
187
[13821]188Status dir_watch_Poll(DirWatchNotifications& notifications)
[6828]189{
[13821]190 if ( g_Stream == NULL )
191 {
[18989]192 g_Stream = CreateEventStream( g_RootPaths );
[13821]193 }
194 else
195 {
196 for ( DirWatchNotifications::iterator it = g_QueuedDirs.begin() ; it != g_QueuedDirs.end(); ++it)
197 notifications.push_back(DirWatchNotification( *it ));
198
199 g_QueuedDirs.clear();
200 }
201
[6828]202 return INFO::OK;
203}
Note: See TracBrowser for help on using the repository browser.