macVolume.mm

Engine/source/platformMac/macVolume.mm

More...

Classes:

Public Functions

fsNotifyCallback(ConstFSEventStreamRef stream, void * callbackInfo, size_t numEvents, void * eventPaths, const FSEventStreamEventFlags eventFlags, const FSEventStreamEventId eventIds)

Detailed Description

Public Functions

fsNotifyCallback(ConstFSEventStreamRef stream, void * callbackInfo, size_t numEvents, void * eventPaths, const FSEventStreamEventFlags eventFlags, const FSEventStreamEventId eventIds)

  1
  2//-----------------------------------------------------------------------------
  3// Copyright (c) 2012 GarageGames, LLC
  4//
  5// Permission is hereby granted, free of charge, to any person obtaining a copy
  6// of this software and associated documentation files (the "Software"), to
  7// deal in the Software without restriction, including without limitation the
  8// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  9// sell copies of the Software, and to permit persons to whom the Software is
 10// furnished to do so, subject to the following conditions:
 11//
 12// The above copyright notice and this permission notice shall be included in
 13// all copies or substantial portions of the Software.
 14//
 15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 20// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 21// IN THE SOFTWARE.
 22//-----------------------------------------------------------------------------
 23
 24#import <CoreServices/CoreServices.h>
 25#import "platform/platform.h"
 26#import "platformMac/macVolume.h"
 27#import "platform/platformVolume.h"
 28#import "console/console.h"
 29
 30struct MacFileSystemChangeNotifier::Event
 31{
 32   FSEventStreamRef mStream;
 33   Torque::Path mDir;
 34   bool mHasChanged;
 35};
 36
 37static void fsNotifyCallback(
 38   ConstFSEventStreamRef stream,
 39   void* callbackInfo,
 40   size_t numEvents,
 41   void* eventPaths,
 42   const FSEventStreamEventFlags eventFlags[],
 43   const FSEventStreamEventId eventIds[] )
 44{
 45   MacFileSystemChangeNotifier::Event* event =
 46      reinterpret_cast< MacFileSystemChangeNotifier::Event* >( callbackInfo );
 47      
 48   // Defer handling this to internalProcessOnce() so we stay in
 49   // line with how the volume system expects notifications to
 50   // be reported.
 51      
 52   event->mHasChanged = true;
 53}
 54
 55//-----------------------------------------------------------------------------
 56//    Change notifications.
 57//-----------------------------------------------------------------------------
 58
 59
 60MacFileSystemChangeNotifier::MacFileSystemChangeNotifier( MacFileSystem* fs )
 61   : Parent( fs )
 62{
 63   VECTOR_SET_ASSOCIATION( mEvents );   
 64}
 65
 66MacFileSystemChangeNotifier::~MacFileSystemChangeNotifier()
 67{
 68   for( U32 i = 0, num = mEvents.size(); i < num; ++ i )
 69   {
 70      FSEventStreamStop( mEvents[ i ]->mStream );
 71      FSEventStreamInvalidate( mEvents[ i ]->mStream );
 72      FSEventStreamRelease( mEvents[ i ]->mStream );
 73      
 74      SAFE_DELETE( mEvents[ i ] );
 75   }
 76}
 77
 78void MacFileSystemChangeNotifier::internalProcessOnce()
 79{
 80   for( U32 i = 0; i < mEvents.size(); ++ i )
 81      if( mEvents[ i ]->mHasChanged )
 82      {
 83         // Signal the change.
 84         
 85         #ifdef DEBUG_SPEW
 86         Platform::outputDebugString( "[MacFileSystemChangeNotifier] Directory %i changed: '%s'",
 87            i + 1, mEvents[ i ]->mDir.getFullPath().c_str() );
 88         #endif
 89         
 90         internalNotifyDirChanged( mEvents[ i ]->mDir );
 91         mEvents[i ]->mHasChanged = false;
 92      }
 93}
 94
 95bool MacFileSystemChangeNotifier::internalAddNotification( const Torque::Path& dir )
 96{
 97   // Map the path.
 98   
 99   Torque::Path fullFSPath = mFS->mapTo( dir );
100   String osPath = PathToOS( fullFSPath );
101
102   // Create event stream.
103   
104   Event* event = new Event;
105   
106   CFStringRef path = CFStringCreateWithCharacters( NULL, osPath.utf16(), osPath.numChars() );
107   CFArrayRef paths = CFArrayCreate( NULL, ( const void** ) &path, 1, NULL );
108
109   FSEventStreamRef stream;
110   CFAbsoluteTime latency = 3.f;
111
112   FSEventStreamContext context;
113   dMemset( &context, 0, sizeof( context ) );
114   context.info = event;
115   
116   stream = FSEventStreamCreate(
117      NULL,
118      &fsNotifyCallback,
119      &context,
120      paths,
121      kFSEventStreamEventIdSinceNow,
122      latency,
123      kFSEventStreamCreateFlagNone
124   );
125   
126   event->mStream = stream;
127   event->mDir = dir;
128   event->mHasChanged = false;
129   
130   mEvents.push_back( event );
131
132   // Put it in the run loop and start the stream.
133   
134   FSEventStreamScheduleWithRunLoop( stream, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode );
135   FSEventStreamStart( stream );
136   
137   CFRelease( path );
138   CFRelease( paths );
139         
140   #ifdef DEBUG_SPEW
141   Platform::outputDebugString( "[MacFileSystemChangeNotifier] Added change notification %i to '%s' (full path: %s)",
142      mEvents.size(), dir.getFullPath().c_str(), osPath.c_str() );
143   #endif
144   
145   return true;
146}
147
148bool MacFileSystemChangeNotifier::internalRemoveNotification( const Torque::Path& dir )
149{
150   for( U32 i = 0, num = mEvents.size(); i < num; ++ i )
151      if( mEvents[ i ]->mDir == dir )
152      {
153         #ifdef DEBUG_SPEW
154         Platform::outputDebugString( "[MacFileSystemChangeNotifier] Removing change notification %i from '%s'",
155            i + 1, dir.getFullPath().c_str() );
156         #endif
157         
158         FSEventStreamStop( mEvents[ i ]->mStream );
159         FSEventStreamInvalidate( mEvents[ i ]->mStream );
160         FSEventStreamRelease( mEvents[ i ]->mStream );
161         
162         SAFE_DELETE( mEvents[ i ] );
163         
164         mEvents.erase( i );
165         
166         return true;
167      }
168      
169   return false;
170}
171
172//-----------------------------------------------------------------------------
173//    Platform API.
174//-----------------------------------------------------------------------------
175
176Torque::FS::FileSystemRef Platform::FS::createNativeFS( const String &volume )
177{
178   return new MacFileSystem( volume );
179}
180
181bool Torque::FS::VerifyWriteAccess(const Torque::Path &path)
182{
183   return true;
184}
185