diff --git a/source/graphics/ColladaManager.cpp b/source/graphics/ColladaManager.cpp index 412d40e234..ab41b42a09 100644 --- a/source/graphics/ColladaManager.cpp +++ b/source/graphics/ColladaManager.cpp @@ -279,7 +279,7 @@ public: m_skeletonHashes.clear(); m_skeletonHashes.resize(paths.size()*2); - FileInfo fileInfo; + CFileInfo fileInfo; for (VfsPaths::const_iterator it = paths.begin(); it != paths.end(); ++it) { // This will cause an assertion failure if *it doesn't exist, diff --git a/source/lib/file/archive/archive.h b/source/lib/file/archive/archive.h index 8dca5e0eb1..e23e9d608b 100644 --- a/source/lib/file/archive/archive.h +++ b/source/lib/file/archive/archive.h @@ -55,7 +55,7 @@ struct IArchiveReader * called for each archive entry. * @param pathname full pathname of entry; only valid during the callback. **/ - typedef void (*ArchiveEntryCallback)(const VfsPath& pathname, const FileInfo& fileInfo, PIArchiveFile archiveFile, uintptr_t cbData); + typedef void (*ArchiveEntryCallback)(const VfsPath& pathname, const CFileInfo& fileInfo, PIArchiveFile archiveFile, uintptr_t cbData); virtual Status ReadEntries(ArchiveEntryCallback cb, uintptr_t cbData) = 0; }; diff --git a/source/lib/file/archive/archive_builder.cpp b/source/lib/file/archive/archive_builder.cpp index 49fd806818..4333c739af 100644 --- a/source/lib/file/archive/archive_builder.cpp +++ b/source/lib/file/archive/archive_builder.cpp @@ -141,7 +141,7 @@ static IdMgr id_mgr; // optimizations like reading from vfs_tree container directly. class FileGatherer { - static void EntCb(const char* path, const FileInfo* ent, uintptr_t cbData) + static void EntCb(const char* path, const CFileInfo* ent, uintptr_t cbData) { FileNodes* file_nodes = (FileNodes*)cbData; @@ -544,7 +544,7 @@ public: archive_ext = path_extension(archive_fn); } - bool operator()(FileInfo& ent) const + bool operator()(CFileInfo& ent) const { // remove if not file if(ent.IsDirectory) diff --git a/source/lib/file/archive/archive_zip.cpp b/source/lib/file/archive/archive_zip.cpp index 2cbd31fa8f..5b6ac78510 100644 --- a/source/lib/file/archive/archive_zip.cpp +++ b/source/lib/file/archive/archive_zip.cpp @@ -109,7 +109,7 @@ enum ZipMethod class LFH { public: - void Init(const FileInfo& fileInfo, off_t csize, ZipMethod method, u32 checksum, const Path& pathname) + void Init(const CFileInfo& fileInfo, off_t csize, ZipMethod method, u32 checksum, const Path& pathname) { const std::string pathnameUTF8 = utf8_from_wstring(pathname.string()); const size_t pathnameSize = pathnameUTF8.length(); @@ -157,7 +157,7 @@ cassert(sizeof(LFH) == 30); class CDFH { public: - void Init(const FileInfo& fileInfo, off_t ofs, off_t csize, ZipMethod method, u32 checksum, const Path& pathname, size_t slack) + void Init(const CFileInfo& fileInfo, off_t ofs, off_t csize, ZipMethod method, u32 checksum, const Path& pathname, size_t slack) { const std::string pathnameUTF8 = utf8_from_wstring(pathname.string()); const size_t pathnameLength = pathnameUTF8.length(); @@ -415,7 +415,7 @@ private: PFile m_file; - // all relevant LFH/CDFH fields not covered by FileInfo + // all relevant LFH/CDFH fields not covered by CFileInfo mutable off_t m_ofs; off_t m_csize; u32 m_checksum; @@ -434,7 +434,7 @@ public: ArchiveReader_Zip(const OsPath& pathname) : m_file(new File(pathname, O_RDONLY)) { - FileInfo fileInfo; + CFileInfo fileInfo; GetFileInfo(pathname, &fileInfo); m_fileSize = fileInfo.Size(); const size_t minFileSize = sizeof(LFH)+sizeof(CDFH)+sizeof(ECDR); @@ -466,7 +466,7 @@ public: if(!relativePathname.IsDirectory()) { const OsPath name = relativePathname.Filename(); - FileInfo fileInfo(name, cdfh->USize(), cdfh->MTime()); + CFileInfo fileInfo(name, cdfh->USize(), cdfh->MTime()); shared_ptr archiveFile(new ArchiveFile_Zip(m_file, cdfh->HeaderOffset(), cdfh->CSize(), cdfh->Checksum(), cdfh->Method())); cb(relativePathname, fileInfo, archiveFile, cbData); } @@ -612,7 +612,7 @@ public: Status AddFile(const OsPath& pathname, const OsPath& pathnameInArchive) { - FileInfo fileInfo; + CFileInfo fileInfo; RETURN_STATUS_IF_ERR(GetFileInfo(pathname, &fileInfo)); PFile file(new File); @@ -623,12 +623,12 @@ public: Status AddMemory(const u8* data, size_t size, time_t mtime, const OsPath& pathnameInArchive) { - FileInfo fileInfo(pathnameInArchive, size, mtime); + CFileInfo fileInfo(pathnameInArchive, size, mtime); return AddFileOrMemory(fileInfo, pathnameInArchive, PFile(), data); } - Status AddFileOrMemory(const FileInfo& fileInfo, const OsPath& pathnameInArchive, const PFile& file, const u8* data) + Status AddFileOrMemory(const CFileInfo& fileInfo, const OsPath& pathnameInArchive, const PFile& file, const u8* data) { ENSURE((file && !data) || (data && !file)); diff --git a/source/lib/file/file_system.cpp b/source/lib/file/file_system.cpp index 21b3dabd73..1c2606d208 100644 --- a/source/lib/file/file_system.cpp +++ b/source/lib/file/file_system.cpp @@ -62,7 +62,7 @@ u64 FileSize(const OsPath& pathname) } -Status GetFileInfo(const OsPath& pathname, FileInfo* pfileInfo) +Status GetFileInfo(const OsPath& pathname, CFileInfo* pPtrInfo) { errno = 0; struct stat s; @@ -70,7 +70,7 @@ Status GetFileInfo(const OsPath& pathname, FileInfo* pfileInfo) if(wstat(pathname, &s) != 0) WARN_RETURN(StatusFromErrno()); - *pfileInfo = FileInfo(pathname.Filename(), s.st_size, s.st_mtime); + *pPtrInfo = CFileInfo(pathname.Filename(), s.st_size, s.st_mtime); return INFO::OK; } @@ -84,7 +84,7 @@ struct DirDeleter } }; -Status GetDirectoryEntries(const OsPath& path, FileInfos* files, DirectoryNames* subdirectoryNames) +Status GetDirectoryEntries(const OsPath& path, CFileInfos* files, DirectoryNames* subdirectoryNames) { // open directory errno = 0; @@ -123,7 +123,7 @@ Status GetDirectoryEntries(const OsPath& path, FileInfos* files, DirectoryNames* #endif if(files && S_ISREG(s.st_mode)) - files->push_back(FileInfo(name, s.st_size, s.st_mtime)); + files->push_back(CFileInfo(name, s.st_size, s.st_mtime)); else if(subdirectoryNames && S_ISDIR(s.st_mode) && name != L"." && name != L"..") subdirectoryNames->push_back(name); } @@ -166,7 +166,7 @@ Status DeleteDirectory(const OsPath& path) // note: we have to recursively empty the directory before it can // be deleted (required by Windows and POSIX rmdir()). - FileInfos files; DirectoryNames subdirectoryNames; + CFileInfos files; DirectoryNames subdirectoryNames; RETURN_STATUS_IF_ERR(GetDirectoryEntries(path, &files, &subdirectoryNames)); // delete files diff --git a/source/lib/file/file_system.h b/source/lib/file/file_system.h index e135fd092d..ae0db3634e 100644 --- a/source/lib/file/file_system.h +++ b/source/lib/file/file_system.h @@ -38,14 +38,14 @@ LIB_API u64 FileSize(const OsPath& pathname); // (bundling size and mtime avoids a second expensive call to stat()) -class FileInfo +class CFileInfo { public: - FileInfo() + CFileInfo() { } - FileInfo(const OsPath& name, off_t size, time_t mtime) + CFileInfo(const OsPath& name, off_t size, time_t mtime) : name(name), size(size), mtime(mtime) { } @@ -71,12 +71,12 @@ private: time_t mtime; }; -LIB_API Status GetFileInfo(const OsPath& pathname, FileInfo* fileInfo); +LIB_API Status GetFileInfo(const OsPath& pathname, CFileInfo* fileInfo); -typedef std::vector FileInfos; +typedef std::vector CFileInfos; typedef std::vector DirectoryNames; -LIB_API Status GetDirectoryEntries(const OsPath& path, FileInfos* files, DirectoryNames* subdirectoryNames); +LIB_API Status GetDirectoryEntries(const OsPath& path, CFileInfos* files, DirectoryNames* subdirectoryNames); // same as boost::filesystem::create_directories, except that mkdir is invoked with // instead of 0755. diff --git a/source/lib/file/vfs/vfs.cpp b/source/lib/file/vfs/vfs.cpp index 1bb145eca0..a585da68b0 100644 --- a/source/lib/file/vfs/vfs.cpp +++ b/source/lib/file/vfs/vfs.cpp @@ -77,7 +77,7 @@ public: return INFO::OK; } - virtual Status GetFileInfo(const VfsPath& pathname, FileInfo* pfileInfo) const + virtual Status GetFileInfo(const VfsPath& pathname, CFileInfo* pfileInfo) const { ScopedLock s; VfsDirectory* directory; VfsFile* file; @@ -85,7 +85,7 @@ public: if(!pfileInfo) // just indicate if the file exists without raising warnings. return ret; WARN_RETURN_STATUS_IF_ERR(ret); - *pfileInfo = FileInfo(file->Name(), file->Size(), file->MTime()); + *pfileInfo = CFileInfo(file->Name(), file->Size(), file->MTime()); return INFO::OK; } @@ -98,7 +98,7 @@ public: return INFO::OK; } - virtual Status GetDirectoryEntries(const VfsPath& path, FileInfos* fileInfos, DirectoryNames* subdirectoryNames) const + virtual Status GetDirectoryEntries(const VfsPath& path, CFileInfos* fileInfos, DirectoryNames* subdirectoryNames) const { ScopedLock s; VfsDirectory* directory; @@ -112,7 +112,7 @@ public: for(VfsDirectory::VfsFiles::const_iterator it = files.begin(); it != files.end(); ++it) { const VfsFile& file = it->second; - fileInfos->push_back(FileInfo(file.Name(), file.Size(), file.MTime())); + fileInfos->push_back(CFileInfo(file.Name(), file.Size(), file.MTime())); } } diff --git a/source/lib/file/vfs/vfs.h b/source/lib/file/vfs/vfs.h index e038c5b48d..79a73e712a 100644 --- a/source/lib/file/vfs/vfs.h +++ b/source/lib/file/vfs/vfs.h @@ -28,7 +28,7 @@ #ifndef INCLUDED_VFS #define INCLUDED_VFS -#include "lib/file/file_system.h" // FileInfo +#include "lib/file/file_system.h" // CFileInfo #include "lib/file/vfs/vfs_path.h" namespace ERR @@ -109,7 +109,7 @@ struct IVFS * * @return Status. **/ - virtual Status GetFileInfo(const VfsPath& pathname, FileInfo* pfileInfo) const = 0; + virtual Status GetFileInfo(const VfsPath& pathname, CFileInfo* pfileInfo) const = 0; /** * Retrieve mount priority for a file. @@ -132,7 +132,7 @@ struct IVFS * - we cannot efficiently provide routines for returning files and * subdirectories separately due to the underlying POSIX interface. **/ - virtual Status GetDirectoryEntries(const VfsPath& path, FileInfos* fileInfos, DirectoryNames* subdirectoryNames) const = 0; + virtual Status GetDirectoryEntries(const VfsPath& path, CFileInfos* fileInfos, DirectoryNames* subdirectoryNames) const = 0; /** * Create a file with the given contents. diff --git a/source/lib/file/vfs/vfs_populate.cpp b/source/lib/file/vfs/vfs_populate.cpp index 8e3975ebf3..2826c681fc 100644 --- a/source/lib/file/vfs/vfs_populate.cpp +++ b/source/lib/file/vfs/vfs_populate.cpp @@ -41,7 +41,7 @@ static size_t s_numArchivedFiles; struct CompareFileInfoByName { - bool operator()(const FileInfo& a, const FileInfo& b) + bool operator()(const CFileInfo& a, const CFileInfo& b) { return a.Name() < b.Name(); } @@ -64,7 +64,7 @@ public: s_looseFiles.reserve(10000); #endif - FileInfos files; files.reserve(500); + CFileInfos files; files.reserve(500); DirectoryNames subdirectoryNames; subdirectoryNames.reserve(50); RETURN_STATUS_IF_ERR(GetDirectoryEntries(m_realDirectory->Path(), &files, &subdirectoryNames)); @@ -82,7 +82,7 @@ public: } private: - void AddFile(const FileInfo& fileInfo) const + void AddFile(const CFileInfo& fileInfo) const { const VfsPath name = fileInfo.Name(); if(name.Extension() == L".DELETED") @@ -108,7 +108,7 @@ private: #endif } - static void AddArchiveFile(const VfsPath& pathname, const FileInfo& fileInfo, PIArchiveFile archiveFile, uintptr_t cbData) + static void AddArchiveFile(const VfsPath& pathname, const CFileInfo& fileInfo, PIArchiveFile archiveFile, uintptr_t cbData) { PopulateHelper* this_ = (PopulateHelper*)cbData; @@ -133,7 +133,7 @@ private: #endif } - Status AddFiles(const FileInfos& files) const + Status AddFiles(const CFileInfos& files) const { const OsPath path(m_realDirectory->Path()); diff --git a/source/lib/file/vfs/vfs_tree.h b/source/lib/file/vfs/vfs_tree.h index 61ee2558e1..071c402828 100644 --- a/source/lib/file/vfs/vfs_tree.h +++ b/source/lib/file/vfs/vfs_tree.h @@ -29,7 +29,7 @@ #include -#include "lib/file/file_system.h" // FileInfo +#include "lib/file/file_system.h" // CFileInfo #include "lib/file/common/file_loader.h" // PIFileLoader #include "lib/file/common/real_directory.h" // PRealDirectory #include "lib/file/vfs/vfs_path.h" diff --git a/source/lib/file/vfs/vfs_util.cpp b/source/lib/file/vfs/vfs_util.cpp index 72cb58de2d..421d7e708c 100644 --- a/source/lib/file/vfs/vfs_util.cpp +++ b/source/lib/file/vfs/vfs_util.cpp @@ -39,7 +39,7 @@ namespace vfs { Status GetPathnames(const PIVFS& fs, const VfsPath& path, const wchar_t* filter, VfsPaths& pathnames) { - std::vector files; + std::vector files; RETURN_STATUS_IF_ERR(fs->GetDirectoryEntries(path, &files, 0)); pathnames.clear(); @@ -58,7 +58,7 @@ Status GetPathnames(const PIVFS& fs, const VfsPath& path, const wchar_t* filter, Status ForEachFile(const PIVFS& fs, const VfsPath& startPath, FileCallback cb, uintptr_t cbData, const wchar_t* pattern, size_t flags) { // (declare here to avoid reallocations) - FileInfos files; DirectoryNames subdirectoryNames; + CFileInfos files; DirectoryNames subdirectoryNames; // (a FIFO queue is more efficient than recursion because it uses less // stack space and avoids seeks due to breadth-first traversal.) @@ -72,11 +72,11 @@ Status ForEachFile(const PIVFS& fs, const VfsPath& startPath, FileCallback cb, u for(size_t i = 0; i < files.size(); i++) { - const FileInfo fileInfo = files[i]; + const CFileInfo fileInfo = files[i]; if(!match_wildcard(fileInfo.Name().string().c_str(), pattern)) continue; - const VfsPath pathname(path / fileInfo.Name()); // (FileInfo only stores the name) + const VfsPath pathname(path / fileInfo.Name()); // (CFileInfo only stores the name) cb(pathname, fileInfo, cbData); } @@ -105,7 +105,7 @@ void NextNumberedFilename(const PIVFS& fs, const VfsPath& pathnameFormat, size_t const VfsPath path = pathnameFormat.Parent()/""; size_t maxNumber = 0; - FileInfos files; + CFileInfos files; fs->GetDirectoryEntries(path, &files, 0); for(size_t i = 0; i < files.size(); i++) { diff --git a/source/lib/file/vfs/vfs_util.h b/source/lib/file/vfs/vfs_util.h index c6150a4d97..775951e75a 100644 --- a/source/lib/file/vfs/vfs_util.h +++ b/source/lib/file/vfs/vfs_util.h @@ -37,7 +37,7 @@ extern Status GetPathnames(const PIVFS& fs, const VfsPath& path, const wchar_t* /** * called for files in a directory. * - * @param pathname full pathname (since FileInfo only gives the name). + * @param pathname full pathname (since CFileInfo only gives the name). * @param fileInfo file information * @param cbData user-specified context * @return INFO::CONTINUE on success; any other value will immediately @@ -46,7 +46,7 @@ extern Status GetPathnames(const PIVFS& fs, const VfsPath& path, const wchar_t* * CAVEAT: pathname and fileInfo are only valid until the function * returns! **/ -typedef Status (*FileCallback)(const VfsPath& pathname, const FileInfo& fileInfo, const uintptr_t cbData); +typedef Status (*FileCallback)(const VfsPath& pathname, const CFileInfo& fileInfo, const uintptr_t cbData); enum DirFlags { diff --git a/source/lib/sysdep/os/osx/dir_watch.cpp b/source/lib/sysdep/os/osx/dir_watch.cpp index dce8ed3a5d..80d180f653 100644 --- a/source/lib/sysdep/os/osx/dir_watch.cpp +++ b/source/lib/sysdep/os/osx/dir_watch.cpp @@ -21,16 +21,182 @@ */ #include "precompiled.h" + #include "lib/sysdep/dir_watch.h" +#include "lib/file/file_system.h" +#include "osx_sys_version.h" -// stub implementations +#include "lib/os_path.h" +#include "lib/file/file.h" +#include "lib/posix/posix_filesystem.h" // mode_t -Status dir_watch_Add(const OsPath& UNUSED(path), PDirWatch& UNUSED(dirWatch)) +#include +#include + + +#include "ps/CLogger.h" + +FSEventStreamRef g_Stream = NULL; + +struct DirWatch { + OsPath path; + int reqnum; +}; + +typedef std::vector DirWatchMap; +static DirWatchMap g_Paths; +static DirWatchMap g_RootPaths; +static DirWatchNotifications g_QueuedDirs; + +bool CanRunNotifications() +{ + int major = 0; + int minor = 0; + int bugfix = 0; + + GetSystemVersion( major, minor, bugfix); + + if ((major == 10 && minor >= 7) || major >= 11) + return true; + + return false; +} + +#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1070 +#else + #define kFSEventStreamCreateFlagFileEvents 0x00000010 + #define kFSEventStreamEventFlagItemIsFile 0x00010000 + #define kFSEventStreamEventFlagItemRemoved 0x00000200 + #define kFSEventStreamEventFlagItemRenamed 0x00000800 + #define kFSEventStreamEventFlagItemCreated 0x00000100 + #define kFSEventStreamEventFlagItemModified 0x00001000 +#endif + +static void fsevent_callback( + ConstFSEventStreamRef UNUSED(streamRef), + void * UNUSED(clientCallBackInfo), + size_t numEvents, + void *eventPaths, + const FSEventStreamEventFlags eventFlags[], + const FSEventStreamEventId UNUSED(eventIds)[] ) +{ + unsigned long i; + char **paths = (char **)eventPaths; + + for (i=0; ipath.string().c_str(), eventPath.string().c_str() ) ) + isWatched = true; + } + + if ( ! isWatched ) + return; + + OsPath filename = Path( eventPath.string().c_str() ); + + if ( eventType & kFSEventStreamEventFlagItemIsFile) + { + if ( eventType & kFSEventStreamEventFlagItemRemoved ) + g_QueuedDirs.push_back(DirWatchNotification( filename.string().c_str(), DirWatchNotification::Deleted )); + else if ( eventType & kFSEventStreamEventFlagItemRenamed ) + g_QueuedDirs.push_back(DirWatchNotification( filename.string().c_str(), DirWatchNotification::Deleted )); + else if ( eventType & kFSEventStreamEventFlagItemCreated ) + g_QueuedDirs.push_back(DirWatchNotification( filename.string().c_str(), DirWatchNotification::Created )); + else if ( eventType & kFSEventStreamEventFlagItemModified ) + g_QueuedDirs.push_back(DirWatchNotification( filename.string().c_str(), DirWatchNotification::Changed )); + } + } + +} + +FSEventStreamRef CreateEventStream( DirWatchMap path ) +{ + if ( ( g_Stream == NULL ) && CanRunNotifications() ) + { + CFStringRef* pathLists = (CFStringRef*)malloc( sizeof(CFStringRef*) * path.size() ); + int index = 0; + for ( DirWatchMap::iterator it = path.begin() ; it != path.end(); ++it) + { + pathLists[index] = CFStringCreateWithFileSystemRepresentation( NULL, OsString(it->path).c_str()); + index++; + } + CFArrayRef pathsToWatch = CFArrayCreate(NULL, (const void **)pathLists, index, NULL); + + FSEventStreamContext *callbackInfo = NULL; + + FSEventStreamRef stream = FSEventStreamCreate(NULL, &fsevent_callback, callbackInfo, pathsToWatch, + kFSEventStreamEventIdSinceNow, 1.0, kFSEventStreamCreateFlagFileEvents ); + + CFRelease( pathsToWatch ); + free( pathLists ); + + FSEventStreamScheduleWithRunLoop(stream, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode); + if (!FSEventStreamStart(stream)) + debug_warn(L"event_loop FSEventStreamStart failed!"); + else + return stream; + } + return NULL; +} + +void DeleteEventStream() +{ + if ( g_Stream != NULL ) + { + FSEventStreamStop(g_Stream); + FSEventStreamInvalidate(g_Stream); + FSEventStreamRelease(g_Stream); + + g_Stream = NULL; + } +} + + +Status dir_watch_Add(const OsPath& path, PDirWatch& dirWatch) +{ + PDirWatch tmpDirWatch(new DirWatch); + dirWatch.swap(tmpDirWatch); + dirWatch->path = path; + dirWatch->reqnum = 0; + g_Paths.push_back( *dirWatch ); + + bool alreadyInsideRootPath = false; + for ( DirWatchMap::iterator it = g_RootPaths.begin() ; it != g_RootPaths.end(); ++it) + { + if ( path_is_subpath( path.string().c_str(), it->path.string().c_str() ) ) + alreadyInsideRootPath = true; + } + + if ( !alreadyInsideRootPath ) + { + DeleteEventStream(); + g_RootPaths.push_back( *dirWatch ); + } + return INFO::OK; } -Status dir_watch_Poll(DirWatchNotifications& UNUSED(notifications)) +Status dir_watch_Poll(DirWatchNotifications& notifications) { + if ( g_Stream == NULL ) + { + g_Stream = CreateEventStream( g_RootPaths ); + } + else + { + for ( DirWatchNotifications::iterator it = g_QueuedDirs.begin() ; it != g_QueuedDirs.end(); ++it) + notifications.push_back(DirWatchNotification( *it )); + + g_QueuedDirs.clear(); + } + return INFO::OK; } diff --git a/source/lib/sysdep/os/osx/osx_sys_version.h b/source/lib/sysdep/os/osx/osx_sys_version.h new file mode 100644 index 0000000000..ac207d5bfc --- /dev/null +++ b/source/lib/sysdep/os/osx/osx_sys_version.h @@ -0,0 +1,28 @@ +/* Copyright (c) 2013 Wildfire Games + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef OSX_SYS_VERSION_H +#define OSX_SYS_VERSION_H + +void GetSystemVersion( int &major, int &minor, int &bugfix ); + +#endif //OSX_SYS_VERSION_H \ No newline at end of file diff --git a/source/lib/sysdep/os/osx/osx_sys_version.mm b/source/lib/sysdep/os/osx/osx_sys_version.mm new file mode 100644 index 0000000000..abe99eca64 --- /dev/null +++ b/source/lib/sysdep/os/osx/osx_sys_version.mm @@ -0,0 +1,67 @@ +/* Copyright (c) 2013 Wildfire Games + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +#import // MAC_OS_X_VERSION_MIN_REQUIRED +#import +#import + +#import "osx_bundle.h" + +#define STRINGIZE2(id) # id +#define STRINGIZE(id) STRINGIZE2(id) + +// Pass the bundle identifier string as a build option +#ifdef BUNDLE_IDENTIFIER +static const char* BUNDLE_ID_STR = STRINGIZE(BUNDLE_IDENTIFIER); +#else +static const char* BUNDLE_ID_STR = ""; +#endif + + +void GetSystemVersion( int &major, int &minor, int &bugfix ) +{ + // sensible default + static int mMajor = 10; + static int mMinor = 8; + static int mBugfix = 0; + + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + NSString* versionString = [[NSDictionary dictionaryWithContentsOfFile:@"/System/Library/CoreServices/SystemVersion.plist"] objectForKey:@"ProductVersion"]; + NSArray* versions = [versionString componentsSeparatedByString:@"."]; + check( versions.count >= 2 ); + if ( versions.count >= 1 ) { + mMajor = [[versions objectAtIndex:0] integerValue]; + } + if ( versions.count >= 2 ) { + mMinor = [[versions objectAtIndex:1] integerValue]; + } + if ( versions.count >= 3 ) { + mBugfix = [[versions objectAtIndex:2] integerValue]; + } + }); + + major = mMajor; + minor = mMinor; + bugfix = mBugfix; +} diff --git a/source/lib/sysdep/os/win/wsnd.cpp b/source/lib/sysdep/os/win/wsnd.cpp index 73d8a84c0d..35a71a0465 100644 --- a/source/lib/sysdep/os/win/wsnd.cpp +++ b/source/lib/sysdep/os/win/wsnd.cpp @@ -55,7 +55,7 @@ typedef std::set StringSet; // same name in the system directory. static void add_oal_dlls_in_dir(const OsPath& path, StringSet& dlls, VersionList& versionList) { - FileInfos files; + CFileInfos files; (void)GetDirectoryEntries(path, &files, 0); for(size_t i = 0; i < files.size(); i++) { diff --git a/source/ps/ArchiveBuilder.cpp b/source/ps/ArchiveBuilder.cpp index 3315075039..4d3137fcc8 100644 --- a/source/ps/ArchiveBuilder.cpp +++ b/source/ps/ArchiveBuilder.cpp @@ -173,7 +173,7 @@ void CArchiveBuilder::Build(const OsPath& archive, bool compress) } } -Status CArchiveBuilder::CollectFileCB(const VfsPath& pathname, const FileInfo& UNUSED(fileInfo), const uintptr_t cbData) +Status CArchiveBuilder::CollectFileCB(const VfsPath& pathname, const CFileInfo& UNUSED(fileInfo), const uintptr_t cbData) { CArchiveBuilder* self = static_cast((void*)cbData); self->m_Files.push_back(pathname); diff --git a/source/ps/ArchiveBuilder.h b/source/ps/ArchiveBuilder.h index ad1ba4ad79..e51f9b5aa8 100644 --- a/source/ps/ArchiveBuilder.h +++ b/source/ps/ArchiveBuilder.h @@ -57,7 +57,7 @@ public: void Build(const OsPath& archive, bool compress); private: - static Status CollectFileCB(const VfsPath& pathname, const FileInfo& fileInfo, const uintptr_t cbData); + static Status CollectFileCB(const VfsPath& pathname, const CFileInfo& fileInfo, const uintptr_t cbData); PIVFS m_VFS; std::vector m_Files; diff --git a/source/ps/CacheLoader.cpp b/source/ps/CacheLoader.cpp index 928d44f0e7..f31b7d9738 100644 --- a/source/ps/CacheLoader.cpp +++ b/source/ps/CacheLoader.cpp @@ -95,7 +95,7 @@ bool CCacheLoader::CanUseArchiveCache(const VfsPath& sourcePath, const VfsPath& // If source file is more recent than the archive cache (i.e. the user has edited it), // don't use the old cache - FileInfo sourceInfo, archiveCacheInfo; + CFileInfo sourceInfo, archiveCacheInfo; if (m_VFS->GetFileInfo(sourcePath, &sourceInfo) >= 0 && m_VFS->GetFileInfo(archiveCachePath, &archiveCacheInfo) >= 0) { @@ -116,7 +116,7 @@ VfsPath CCacheLoader::ArchiveCachePath(const VfsPath& sourcePath) VfsPath CCacheLoader::LooseCachePath(const VfsPath& sourcePath, const MD5& initialHash, u32 version) { - FileInfo fileInfo; + CFileInfo fileInfo; if (m_VFS->GetFileInfo(sourcePath, &fileInfo) < 0) { debug_warn(L"source file disappeared"); // this should never happen diff --git a/source/ps/SavedGame.cpp b/source/ps/SavedGame.cpp index 55b6a56b18..274d22f566 100644 --- a/source/ps/SavedGame.cpp +++ b/source/ps/SavedGame.cpp @@ -98,7 +98,7 @@ Status SavedGames::Save(const std::wstring& name, const std::wstring& descriptio archiveWriter.reset(); // close the file WriteBuffer buffer; - FileInfo tempSaveFile; + CFileInfo tempSaveFile; WARN_RETURN_STATUS_IF_ERR(GetFileInfo(tempSaveFileRealPath, &tempSaveFile)); buffer.Reserve(tempSaveFile.Size()); WARN_RETURN_STATUS_IF_ERR(io::Load(tempSaveFileRealPath, buffer.Data().get(), buffer.Size())); @@ -123,12 +123,12 @@ public: { } - static void ReadEntryCallback(const VfsPath& pathname, const FileInfo& fileInfo, PIArchiveFile archiveFile, uintptr_t cbData) + static void ReadEntryCallback(const VfsPath& pathname, const CFileInfo& fileInfo, PIArchiveFile archiveFile, uintptr_t cbData) { ((CGameLoader*)cbData)->ReadEntry(pathname, fileInfo, archiveFile); } - void ReadEntry(const VfsPath& pathname, const FileInfo& fileInfo, PIArchiveFile archiveFile) + void ReadEntry(const VfsPath& pathname, const CFileInfo& fileInfo, PIArchiveFile archiveFile) { if (pathname == L"metadata.json" && m_Metadata) { diff --git a/source/ps/scripting/JSInterface_VFS.cpp b/source/ps/scripting/JSInterface_VFS.cpp index 3ba402b045..791484a180 100644 --- a/source/ps/scripting/JSInterface_VFS.cpp +++ b/source/ps/scripting/JSInterface_VFS.cpp @@ -66,7 +66,7 @@ struct BuildDirEntListState }; // called for each matching directory entry; add its full pathname to array. -static Status BuildDirEntListCB(const VfsPath& pathname, const FileInfo& UNUSED(fileINfo), uintptr_t cbData) +static Status BuildDirEntListCB(const VfsPath& pathname, const CFileInfo& UNUSED(fileINfo), uintptr_t cbData) { BuildDirEntListState* s = (BuildDirEntListState*)cbData; @@ -140,7 +140,7 @@ JSBool JSI_VFS::GetFileMTime(JSContext* cx, uintN argc, jsval* vp) if (!ToPrimitive (cx, JS_ARGV(cx, vp)[0], filename)) return JS_FALSE; - FileInfo fileInfo; + CFileInfo fileInfo; Status err = g_VFS->GetFileInfo(filename, &fileInfo); JS_CHECK_FILE_ERR(err); @@ -161,7 +161,7 @@ JSBool JSI_VFS::GetFileSize(JSContext* cx, uintN argc, jsval* vp) if (!ToPrimitive (cx, JS_ARGV(cx, vp)[0], filename)) return JS_FALSE; - FileInfo fileInfo; + CFileInfo fileInfo; Status err = g_VFS->GetFileInfo(filename, &fileInfo); JS_CHECK_FILE_ERR(err); diff --git a/source/scriptinterface/DebuggingServer.cpp b/source/scriptinterface/DebuggingServer.cpp index 93c18d6d02..f9fa7750aa 100644 --- a/source/scriptinterface/DebuggingServer.cpp +++ b/source/scriptinterface/DebuggingServer.cpp @@ -176,7 +176,7 @@ bool CDebuggingServer::GetSettingSimultaneousThreadBreak() } -static Status AddFileResponse(const VfsPath& pathname, const FileInfo& UNUSED(fileInfo), const uintptr_t cbData) +static Status AddFileResponse(const VfsPath& pathname, const CFileInfo& UNUSED(fileInfo), const uintptr_t cbData) { std::vector& templates = *(std::vector*)cbData; std::wstring str(pathname.string()); diff --git a/source/simulation2/components/CCmpTemplateManager.cpp b/source/simulation2/components/CCmpTemplateManager.cpp index 257a205aa2..075f0e5bfb 100644 --- a/source/simulation2/components/CCmpTemplateManager.cpp +++ b/source/simulation2/components/CCmpTemplateManager.cpp @@ -429,7 +429,7 @@ void CCmpTemplateManager::ConstructTemplateActor(const std::string& actorName, C CParamNode::LoadXMLString(out, xml.c_str(), actorNameW.c_str()); } -static Status AddToTemplates(const VfsPath& pathname, const FileInfo& UNUSED(fileInfo), const uintptr_t cbData) +static Status AddToTemplates(const VfsPath& pathname, const CFileInfo& UNUSED(fileInfo), const uintptr_t cbData) { std::vector& templates = *(std::vector*)cbData; @@ -446,7 +446,7 @@ static Status AddToTemplates(const VfsPath& pathname, const FileInfo& UNUSED(fil return INFO::OK; } -static Status AddActorToTemplates(const VfsPath& pathname, const FileInfo& UNUSED(fileInfo), const uintptr_t cbData) +static Status AddActorToTemplates(const VfsPath& pathname, const CFileInfo& UNUSED(fileInfo), const uintptr_t cbData) { std::vector& templates = *(std::vector*)cbData; diff --git a/source/simulation2/components/ICmpAIManager.cpp b/source/simulation2/components/ICmpAIManager.cpp index 5745827de5..a86ec4852e 100644 --- a/source/simulation2/components/ICmpAIManager.cpp +++ b/source/simulation2/components/ICmpAIManager.cpp @@ -47,7 +47,7 @@ public: vfs::ForEachFile(g_VFS, L"simulation/ai/", Callback, (uintptr_t)this, L"*.json", vfs::DIR_RECURSIVE); } - static Status Callback(const VfsPath& pathname, const FileInfo& UNUSED(fileInfo), const uintptr_t cbData) + static Status Callback(const VfsPath& pathname, const CFileInfo& UNUSED(fileInfo), const uintptr_t cbData) { GetAIsHelper* self = (GetAIsHelper*)cbData; diff --git a/source/simulation2/system/ComponentManager.cpp b/source/simulation2/system/ComponentManager.cpp index 3200378a67..7a0e519bc7 100644 --- a/source/simulation2/system/ComponentManager.cpp +++ b/source/simulation2/system/ComponentManager.cpp @@ -962,7 +962,7 @@ CScriptVal CComponentManager::ReadJSONFile(void* cbdata, std::wstring filePath, return componentManager->GetScriptInterface().ReadJSONFile(path).get(); } -Status CComponentManager::FindJSONFilesCallback(const VfsPath& pathname, const FileInfo& UNUSED(fileInfo), const uintptr_t cbData) +Status CComponentManager::FindJSONFilesCallback(const VfsPath& pathname, const CFileInfo& UNUSED(fileInfo), const uintptr_t cbData) { FindJSONFilesCallbackData* data = (FindJSONFilesCallbackData*)cbData; diff --git a/source/simulation2/system/ComponentManager.h b/source/simulation2/system/ComponentManager.h index 17cc16536f..8e02023116 100644 --- a/source/simulation2/system/ComponentManager.h +++ b/source/simulation2/system/ComponentManager.h @@ -245,7 +245,7 @@ private: static CScriptVal ReadJSONFile(void *cbdata, std::wstring filePath, std::wstring fileName); // callback function to handle recursively finding files in a directory - static Status FindJSONFilesCallback(const VfsPath&, const FileInfo&, const uintptr_t); + static Status FindJSONFilesCallback(const VfsPath&, const CFileInfo&, const uintptr_t); CMessage* ConstructMessage(int mtid, CScriptVal data); void SendGlobalMessage(entity_id_t ent, const CMessage& msg) const; diff --git a/source/soundmanager/SoundManager.cpp b/source/soundmanager/SoundManager.cpp index e26a7f7f84..9f457a99cb 100644 --- a/source/soundmanager/SoundManager.cpp +++ b/source/soundmanager/SoundManager.cpp @@ -20,6 +20,8 @@ #include "ISoundManager.h" #include "SoundManager.h" +#include "ps/Filesystem.h" + #include "soundmanager/data/SoundData.h" #include "soundmanager/items/CSoundItem.h" #include "soundmanager/items/CBufferItem.h" @@ -208,7 +210,8 @@ private: void ISoundManager::CreateSoundManager() { - g_SoundManager = new CSoundManager(); + if ( !g_SoundManager ) + g_SoundManager = new CSoundManager(); } void ISoundManager::SetEnabled(bool doEnable) @@ -217,7 +220,7 @@ void ISoundManager::SetEnabled(bool doEnable) { SAFE_DELETE(g_SoundManager); } - else if ( ! g_SoundManager && doEnable ) + else if ( !g_SoundManager && doEnable ) { ISoundManager::CreateSoundManager(); } @@ -240,6 +243,18 @@ void CSoundManager::al_check(const char* caller, int line) al_ReportError(err, caller, line); } +Status CSoundManager::ReloadChangedFiles(const VfsPath& UNUSED(path)) +{ +// LOGERROR(L"GUI file '%ls' changed - reloading page", path.string().c_str()); + + return INFO::OK; +} + +/*static*/ Status CSoundManager::ReloadChangedFileCB(void* param, const VfsPath& path) +{ + return static_cast(param)->ReloadChangedFiles(path); +} + CSoundManager::CSoundManager() { m_CurrentEnvirons = 0; @@ -282,10 +297,14 @@ CSoundManager::CSoundManager() m_Worker = new CSoundManagerWorker(); m_Worker->SetEnabled( true ); } + + RegisterFileReloadFunc(ReloadChangedFileCB, this); } CSoundManager::~CSoundManager() { + UnregisterFileReloadFunc(ReloadChangedFileCB, this); + if (m_Worker ) { AL_CHECK @@ -649,11 +668,14 @@ void CSoundManager::PlayGroupItem(ISoundItem* anItem, ALfloat groupGain ) void CSoundManager::SetMusicEnabled (bool isEnabled) { + LOGERROR(L"entering enabled area", isEnabled); + if (m_CurrentTune && !isEnabled) { m_CurrentTune->FadeAndDelete(1.00); m_CurrentTune = 0L; } + LOGERROR(L"exiting enabled area", isEnabled); m_MusicEnabled = isEnabled; } diff --git a/source/soundmanager/SoundManager.h b/source/soundmanager/SoundManager.h index 8dfb7a86b3..ad41403f40 100644 --- a/source/soundmanager/SoundManager.h +++ b/source/soundmanager/SoundManager.h @@ -102,6 +102,8 @@ public: ISoundItem* ItemForData(CSoundData* itemData); ISoundItem* ItemForEntity( entity_id_t source, CSoundData* sndData); + Status ReloadChangedFiles(const VfsPath& path); + void ClearPlayListItems(); void StartPlayList( bool doLoop ); void AddPlayListItem( const VfsPath* itemPath); @@ -109,6 +111,8 @@ public: static void ScriptingInit(); static void CreateSoundManager(); static void SetEnabled(bool doEnable); + static Status ReloadChangedFileCB(void* param, const VfsPath& path); + static void CloseGame(); static void al_ReportError(ALenum err, const char* caller, int line);