mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-02-05 03:50:07 +00:00
This commit is contained in:
parent
8bbd575344
commit
6c5297c829
5 changed files with 32 additions and 1055 deletions
|
|
@ -1,841 +0,0 @@
|
|||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library - "Jules' Utility Class Extensions"
|
||||
Copyright 2004-7 by Raw Material Software ltd.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
JUCE can be redistributed and/or modified under the terms of the
|
||||
GNU General Public License, as published by the Free Software Foundation;
|
||||
either version 2 of the License, or (at your option) any later version.
|
||||
|
||||
JUCE is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with JUCE; if not, visit www.gnu.org/licenses or write to the
|
||||
Free Software Foundation, Inc., 59 Temple Place, Suite 330,
|
||||
Boston, MA 02111-1307 USA
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
If you'd like to release a closed-source product which uses JUCE, commercial
|
||||
licenses are also available: visit www.rawmaterialsoftware.com/juce for
|
||||
more information.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#include "../../../src/juce_core/basics/juce_StandardHeader.h"
|
||||
#include <ApplicationServices/ApplicationServices.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/dir.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/mount.h>
|
||||
#include <unistd.h>
|
||||
#include <fnmatch.h>
|
||||
#include <utime.h>
|
||||
#include <pwd.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
BEGIN_JUCE_NAMESPACE
|
||||
|
||||
#include "../../../src/juce_core/io/files/juce_FileInputStream.h"
|
||||
#include "../../../src/juce_core/io/files/juce_FileOutputStream.h"
|
||||
#include "../../../src/juce_core/io/network/juce_URL.h"
|
||||
#include "../../../src/juce_core/basics/juce_SystemStats.h"
|
||||
#include "../../../src/juce_core/misc/juce_PlatformUtilities.h"
|
||||
#include "../../../src/juce_core/io/files/juce_NamedPipe.h"
|
||||
#include "../../../src/juce_core/threads/juce_InterProcessLock.h"
|
||||
#include "../../../src/juce_core/threads/juce_Thread.h"
|
||||
|
||||
//==============================================================================
|
||||
/*
|
||||
Note that a lot of methods that you'd expect to find in this file actually
|
||||
live in juce_posix_SharedCode.h!
|
||||
*/
|
||||
#include "juce_posix_SharedCode.h"
|
||||
|
||||
|
||||
//==============================================================================
|
||||
static File executableFile;
|
||||
|
||||
|
||||
//==============================================================================
|
||||
void PlatformUtilities::copyToStr255 (Str255& d, const String& s)
|
||||
{
|
||||
unsigned char* t = (unsigned char*) d;
|
||||
t[0] = jmin (254, s.length());
|
||||
s.copyToBuffer ((char*) t + 1, 254);
|
||||
}
|
||||
|
||||
void PlatformUtilities::copyToStr63 (Str63& d, const String& s)
|
||||
{
|
||||
unsigned char* t = (unsigned char*) d;
|
||||
t[0] = jmin (62, s.length());
|
||||
s.copyToBuffer ((char*) t + 1, 62);
|
||||
}
|
||||
|
||||
const String PlatformUtilities::cfStringToJuceString (CFStringRef cfString)
|
||||
{
|
||||
String result;
|
||||
|
||||
if (cfString != 0)
|
||||
{
|
||||
#if JUCE_STRINGS_ARE_UNICODE
|
||||
CFRange range = { 0, CFStringGetLength (cfString) };
|
||||
UniChar* const u = (UniChar*) juce_malloc (sizeof (UniChar) * (range.length + 1));
|
||||
|
||||
CFStringGetCharacters (cfString, range, u);
|
||||
u[range.length] = 0;
|
||||
|
||||
result = convertUTF16ToString (u);
|
||||
|
||||
juce_free (u);
|
||||
#else
|
||||
const int len = CFStringGetLength (cfString);
|
||||
char* buffer = (char*) juce_malloc (len + 1);
|
||||
CFStringGetCString (cfString, buffer, len + 1, CFStringGetSystemEncoding());
|
||||
result = buffer;
|
||||
juce_free (buffer);
|
||||
#endif
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
CFStringRef PlatformUtilities::juceStringToCFString (const String& s)
|
||||
{
|
||||
#if JUCE_STRINGS_ARE_UNICODE
|
||||
const int len = s.length();
|
||||
const juce_wchar* t = (const juce_wchar*) s;
|
||||
|
||||
UniChar* temp = (UniChar*) juce_malloc (sizeof (UniChar) * len + 4);
|
||||
|
||||
for (int i = 0; i <= len; ++i)
|
||||
temp[i] = t[i];
|
||||
|
||||
CFStringRef result = CFStringCreateWithCharacters (kCFAllocatorDefault, temp, len);
|
||||
juce_free (temp);
|
||||
|
||||
return result;
|
||||
|
||||
#else
|
||||
return CFStringCreateWithCString (kCFAllocatorDefault,
|
||||
(const char*) s,
|
||||
CFStringGetSystemEncoding());
|
||||
#endif
|
||||
}
|
||||
|
||||
const String PlatformUtilities::convertUTF16ToString (const UniChar* utf16)
|
||||
{
|
||||
String s;
|
||||
|
||||
while (*utf16 != 0)
|
||||
s += (juce_wchar) *utf16++;
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
const String PlatformUtilities::convertToPrecomposedUnicode (const String& s)
|
||||
{
|
||||
UnicodeMapping map;
|
||||
|
||||
map.unicodeEncoding = CreateTextEncoding (kTextEncodingUnicodeDefault,
|
||||
kUnicodeNoSubset,
|
||||
kTextEncodingDefaultFormat);
|
||||
|
||||
map.otherEncoding = CreateTextEncoding (kTextEncodingUnicodeDefault,
|
||||
kUnicodeCanonicalCompVariant,
|
||||
kTextEncodingDefaultFormat);
|
||||
|
||||
map.mappingVersion = kUnicodeUseLatestMapping;
|
||||
|
||||
UnicodeToTextInfo conversionInfo = 0;
|
||||
String result;
|
||||
|
||||
if (CreateUnicodeToTextInfo (&map, &conversionInfo) == noErr)
|
||||
{
|
||||
const int len = s.length();
|
||||
|
||||
UniChar* const tempIn = (UniChar*) juce_calloc (sizeof (UniChar) * len + 4);
|
||||
UniChar* const tempOut = (UniChar*) juce_calloc (sizeof (UniChar) * len + 4);
|
||||
|
||||
for (int i = 0; i <= len; ++i)
|
||||
tempIn[i] = s[i];
|
||||
|
||||
ByteCount bytesRead = 0;
|
||||
ByteCount outputBufferSize = 0;
|
||||
|
||||
if (ConvertFromUnicodeToText (conversionInfo,
|
||||
len * sizeof (UniChar), tempIn,
|
||||
kUnicodeDefaultDirectionMask,
|
||||
0, 0, 0, 0,
|
||||
len * sizeof (UniChar), &bytesRead,
|
||||
&outputBufferSize, tempOut) == noErr)
|
||||
{
|
||||
result.preallocateStorage (bytesRead / sizeof (UniChar) + 2);
|
||||
|
||||
tchar* t = const_cast <tchar*> ((const tchar*) result);
|
||||
|
||||
int i;
|
||||
for (i = 0; i < bytesRead / sizeof (UniChar); ++i)
|
||||
t[i] = (tchar) tempOut[i];
|
||||
|
||||
t[i] = 0;
|
||||
}
|
||||
|
||||
juce_free (tempIn);
|
||||
juce_free (tempOut);
|
||||
|
||||
DisposeUnicodeToTextInfo (&conversionInfo);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
const unsigned int macTimeToUnixTimeDiff = 0x7c25be90;
|
||||
|
||||
static uint64 utcDateTimeToUnixTime (const UTCDateTime& d) throw()
|
||||
{
|
||||
if (d.highSeconds == 0 && d.lowSeconds == 0 && d.fraction == 0)
|
||||
return 0;
|
||||
|
||||
return (((((uint64) d.highSeconds) << 32) | (uint64) d.lowSeconds) * 1000)
|
||||
+ ((d.fraction * 1000) >> 16)
|
||||
- 2082844800000ll;
|
||||
}
|
||||
|
||||
static void unixTimeToUtcDateTime (uint64 t, UTCDateTime& d) throw()
|
||||
{
|
||||
if (t != 0)
|
||||
t += 2082844800000ll;
|
||||
|
||||
d.highSeconds = (t / 1000) >> 32;
|
||||
d.lowSeconds = (t / 1000) & (uint64) 0xffffffff;
|
||||
d.fraction = ((t % 1000) << 16) / 1000;
|
||||
}
|
||||
|
||||
void juce_getFileTimes (const String& fileName,
|
||||
int64& modificationTime,
|
||||
int64& accessTime,
|
||||
int64& creationTime) throw()
|
||||
{
|
||||
modificationTime = 0;
|
||||
accessTime = 0;
|
||||
creationTime = 0;
|
||||
|
||||
FSRef fileRef;
|
||||
if (PlatformUtilities::makeFSRefFromPath (&fileRef, fileName))
|
||||
{
|
||||
FSRefParam info;
|
||||
zerostruct (info);
|
||||
|
||||
info.ref = &fileRef;
|
||||
info.whichInfo = kFSCatInfoAllDates;
|
||||
|
||||
FSCatalogInfo catInfo;
|
||||
info.catInfo = &catInfo;
|
||||
|
||||
if (PBGetCatalogInfoSync (&info) == noErr)
|
||||
{
|
||||
creationTime = utcDateTimeToUnixTime (catInfo.createDate);
|
||||
accessTime = utcDateTimeToUnixTime (catInfo.accessDate);
|
||||
modificationTime = utcDateTimeToUnixTime (catInfo.contentModDate);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool juce_setFileTimes (const String& fileName,
|
||||
int64 modificationTime,
|
||||
int64 accessTime,
|
||||
int64 creationTime) throw()
|
||||
{
|
||||
FSRef fileRef;
|
||||
if (PlatformUtilities::makeFSRefFromPath (&fileRef, fileName))
|
||||
{
|
||||
FSRefParam info;
|
||||
zerostruct (info);
|
||||
|
||||
info.ref = &fileRef;
|
||||
info.whichInfo = kFSCatInfoAllDates;
|
||||
|
||||
FSCatalogInfo catInfo;
|
||||
info.catInfo = &catInfo;
|
||||
|
||||
if (PBGetCatalogInfoSync (&info) == noErr)
|
||||
{
|
||||
if (creationTime != 0)
|
||||
unixTimeToUtcDateTime (creationTime, catInfo.createDate);
|
||||
|
||||
if (modificationTime != 0)
|
||||
unixTimeToUtcDateTime (modificationTime, catInfo.contentModDate);
|
||||
|
||||
if (accessTime != 0)
|
||||
unixTimeToUtcDateTime (accessTime, catInfo.accessDate);
|
||||
|
||||
return PBSetCatalogInfoSync (&info) == noErr;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool juce_setFileReadOnly (const String& fileName, bool isReadOnly) throw()
|
||||
{
|
||||
const char* const fileNameUTF8 = fileName.toUTF8();
|
||||
|
||||
struct stat info;
|
||||
const int res = stat (fileNameUTF8, &info);
|
||||
|
||||
bool ok = false;
|
||||
|
||||
if (res == 0)
|
||||
{
|
||||
info.st_mode &= 0777; // Just permissions
|
||||
|
||||
if (isReadOnly)
|
||||
info.st_mode &= ~(S_IWUSR | S_IWGRP | S_IWOTH);
|
||||
else
|
||||
// Give everybody write permission?
|
||||
info.st_mode |= S_IWUSR | S_IWGRP | S_IWOTH;
|
||||
|
||||
ok = chmod (fileNameUTF8, info.st_mode) == 0;
|
||||
}
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
bool juce_copyFile (const String& src, const String& dst) throw()
|
||||
{
|
||||
const File destFile (dst);
|
||||
|
||||
if (! destFile.create())
|
||||
return false;
|
||||
|
||||
FSRef srcRef, dstRef;
|
||||
|
||||
if (! (PlatformUtilities::makeFSRefFromPath (&srcRef, src)
|
||||
&& PlatformUtilities::makeFSRefFromPath (&dstRef, dst)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
int okForks = 0;
|
||||
|
||||
CatPositionRec iter;
|
||||
iter.initialize = 0;
|
||||
HFSUniStr255 forkName;
|
||||
|
||||
// can't just copy the data because this is a bloody Mac, so we need to copy each
|
||||
// fork separately...
|
||||
while (FSIterateForks (&srcRef, &iter, &forkName, 0, 0) == noErr)
|
||||
{
|
||||
SInt16 srcForkNum = 0, dstForkNum = 0;
|
||||
OSErr err = FSOpenFork (&srcRef, forkName.length, forkName.unicode, fsRdPerm, &srcForkNum);
|
||||
|
||||
if (err == noErr)
|
||||
{
|
||||
err = FSOpenFork (&dstRef, forkName.length, forkName.unicode, fsRdWrPerm, &dstForkNum);
|
||||
|
||||
if (err == noErr)
|
||||
{
|
||||
MemoryBlock buf (32768);
|
||||
SInt64 pos = 0;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
ByteCount bytesRead = 0;
|
||||
err = FSReadFork (srcForkNum, fsFromStart, pos, buf.getSize(), (char*) buf, &bytesRead);
|
||||
|
||||
if (bytesRead > 0)
|
||||
{
|
||||
err = FSWriteFork (dstForkNum, fsFromStart, pos, bytesRead, (const char*) buf, &bytesRead);
|
||||
pos += bytesRead;
|
||||
}
|
||||
|
||||
if (err != noErr)
|
||||
{
|
||||
if (err == eofErr)
|
||||
++okForks;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
FSFlushFork (dstForkNum);
|
||||
FSCloseFork (dstForkNum);
|
||||
}
|
||||
|
||||
FSCloseFork (srcForkNum);
|
||||
}
|
||||
}
|
||||
|
||||
if (okForks > 0) // some files seem to be ok even if not all their forks get copied..
|
||||
{
|
||||
// copy permissions..
|
||||
struct stat info;
|
||||
if (juce_stat (src, info))
|
||||
chmod (dst.toUTF8(), info.st_mode & 0777);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
const StringArray juce_getFileSystemRoots() throw()
|
||||
{
|
||||
StringArray s;
|
||||
s.add (T("/"));
|
||||
return s;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
static bool isFileOnDriveType (const File* const f, const char** types) throw()
|
||||
{
|
||||
struct statfs buf;
|
||||
|
||||
if (doStatFS (f, buf))
|
||||
{
|
||||
const String type (buf.f_fstypename);
|
||||
|
||||
while (*types != 0)
|
||||
if (type.equalsIgnoreCase (*types++))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool File::isOnCDRomDrive() const throw()
|
||||
{
|
||||
static const char* const cdTypes[] = { "cd9660", "cdfs", "cddafs", "udf", 0 };
|
||||
|
||||
return isFileOnDriveType (this, (const char**) cdTypes);
|
||||
}
|
||||
|
||||
bool File::isOnHardDisk() const throw()
|
||||
{
|
||||
static const char* const nonHDTypes[] = { "nfs", "smbfs", "ramfs", 0 };
|
||||
|
||||
return ! (isOnCDRomDrive() || isFileOnDriveType (this, (const char**) nonHDTypes));
|
||||
}
|
||||
|
||||
bool File::isOnRemovableDrive() const throw()
|
||||
{
|
||||
jassertfalse // xxx not implemented for mac!
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool juce_isHiddenFile (const String& path) throw()
|
||||
{
|
||||
FSRef ref;
|
||||
if (! PlatformUtilities::makeFSRefFromPath (&ref, path))
|
||||
return false;
|
||||
|
||||
FSCatalogInfo info;
|
||||
FSGetCatalogInfo (&ref, kFSCatInfoNodeFlags | kFSCatInfoFinderInfo, &info, 0, 0, 0);
|
||||
|
||||
if ((info.nodeFlags & kFSNodeIsDirectoryBit) != 0)
|
||||
return (((FolderInfo*) &info.finderInfo)->finderFlags & kIsInvisible) != 0;
|
||||
|
||||
return (((FileInfo*) &info.finderInfo)->finderFlags & kIsInvisible) != 0;
|
||||
}
|
||||
|
||||
bool File::isHidden() const throw()
|
||||
{
|
||||
return juce_isHiddenFile (getFullPathName());
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
const File File::getSpecialLocation (const SpecialLocationType type)
|
||||
{
|
||||
const char* resultPath = 0;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case userHomeDirectory:
|
||||
resultPath = getenv ("HOME");
|
||||
|
||||
if (resultPath == 0)
|
||||
{
|
||||
struct passwd* const pw = getpwuid (getuid());
|
||||
if (pw != 0)
|
||||
resultPath = pw->pw_dir;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case userDocumentsDirectory:
|
||||
resultPath = "~/Documents";
|
||||
break;
|
||||
|
||||
case userDesktopDirectory:
|
||||
resultPath = "~/Desktop";
|
||||
break;
|
||||
|
||||
case userApplicationDataDirectory:
|
||||
resultPath = "~/Library";
|
||||
break;
|
||||
|
||||
case commonApplicationDataDirectory:
|
||||
resultPath = "/Library";
|
||||
break;
|
||||
|
||||
case globalApplicationsDirectory:
|
||||
resultPath = "/Applications";
|
||||
break;
|
||||
|
||||
case userMusicDirectory:
|
||||
resultPath = "~/Music";
|
||||
break;
|
||||
|
||||
case userMoviesDirectory:
|
||||
resultPath = "~/Movies";
|
||||
break;
|
||||
|
||||
case tempDirectory:
|
||||
{
|
||||
File tmp (T("~/Library/Caches/") + executableFile.getFileNameWithoutExtension());
|
||||
|
||||
tmp.createDirectory();
|
||||
return tmp.getFullPathName();
|
||||
}
|
||||
|
||||
case currentExecutableFile:
|
||||
return executableFile;
|
||||
|
||||
case currentApplicationFile:
|
||||
{
|
||||
const File parent (executableFile.getParentDirectory());
|
||||
|
||||
return parent.getFullPathName().endsWithIgnoreCase (T("Contents/MacOS"))
|
||||
? parent.getParentDirectory().getParentDirectory()
|
||||
: executableFile;
|
||||
}
|
||||
|
||||
default:
|
||||
jassertfalse // unknown type?
|
||||
break;
|
||||
}
|
||||
|
||||
if (resultPath != 0)
|
||||
return File (PlatformUtilities::convertToPrecomposedUnicode (resultPath));
|
||||
|
||||
return File::nonexistent;
|
||||
}
|
||||
|
||||
void juce_setCurrentExecutableFileName (const String& filename) throw()
|
||||
{
|
||||
executableFile = File::getCurrentWorkingDirectory()
|
||||
.getChildFile (PlatformUtilities::convertToPrecomposedUnicode (filename));
|
||||
}
|
||||
|
||||
void juce_setCurrentExecutableFileNameFromBundleId (const String& bundleId) throw()
|
||||
{
|
||||
CFStringRef bundleIdStringRef = PlatformUtilities::juceStringToCFString (bundleId);
|
||||
CFBundleRef bundleRef = CFBundleGetBundleWithIdentifier (bundleIdStringRef);
|
||||
CFRelease (bundleIdStringRef);
|
||||
|
||||
if (bundleRef != 0)
|
||||
{
|
||||
CFURLRef exeURLRef = CFBundleCopyExecutableURL (bundleRef);
|
||||
|
||||
if (exeURLRef != 0)
|
||||
{
|
||||
CFStringRef pathStringRef = CFURLCopyFileSystemPath (exeURLRef, kCFURLPOSIXPathStyle);
|
||||
CFRelease (exeURLRef);
|
||||
|
||||
if (pathStringRef != 0)
|
||||
{
|
||||
juce_setCurrentExecutableFileName (PlatformUtilities::cfStringToJuceString (pathStringRef));
|
||||
CFRelease (pathStringRef);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
const File File::getCurrentWorkingDirectory() throw()
|
||||
{
|
||||
char buf [2048];
|
||||
getcwd (buf, sizeof(buf));
|
||||
|
||||
return File (PlatformUtilities::convertToPrecomposedUnicode (buf));
|
||||
}
|
||||
|
||||
bool File::setAsCurrentWorkingDirectory() const throw()
|
||||
{
|
||||
return chdir (getFullPathName().toUTF8()) == 0;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
struct FindFileStruct
|
||||
{
|
||||
String parentDir, wildCard;
|
||||
DIR* dir;
|
||||
|
||||
bool getNextMatch (String& result, bool* const isDir, bool* const isHidden, int64* const fileSize,
|
||||
Time* const modTime, Time* const creationTime, bool* const isReadOnly) throw()
|
||||
{
|
||||
const char* const wildCardUTF8 = wildCard.toUTF8();
|
||||
|
||||
for (;;)
|
||||
{
|
||||
struct dirent* const de = readdir (dir);
|
||||
|
||||
if (de == 0)
|
||||
break;
|
||||
|
||||
if (fnmatch (wildCardUTF8, de->d_name, 0) == 0)
|
||||
{
|
||||
result = PlatformUtilities::convertToPrecomposedUnicode (String::fromUTF8 ((const uint8*) de->d_name));
|
||||
|
||||
const String path (parentDir + result);
|
||||
|
||||
if (isDir != 0 || fileSize != 0)
|
||||
{
|
||||
struct stat info;
|
||||
const bool statOk = juce_stat (path, info);
|
||||
|
||||
if (isDir != 0)
|
||||
*isDir = path.isEmpty() || (statOk && ((info.st_mode & S_IFDIR) != 0));
|
||||
|
||||
if (isHidden != 0)
|
||||
*isHidden = (de->d_name[0] == '.')
|
||||
|| juce_isHiddenFile (path);
|
||||
|
||||
if (fileSize != 0)
|
||||
*fileSize = statOk ? info.st_size : 0;
|
||||
}
|
||||
|
||||
if (modTime != 0 || creationTime != 0)
|
||||
{
|
||||
int64 m, a, c;
|
||||
juce_getFileTimes (path, m, a, c);
|
||||
|
||||
if (modTime != 0)
|
||||
*modTime = m;
|
||||
|
||||
if (creationTime != 0)
|
||||
*creationTime = c;
|
||||
}
|
||||
|
||||
if (isReadOnly != 0)
|
||||
*isReadOnly = ! juce_canWriteToFile (path);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
// returns 0 on failure
|
||||
void* juce_findFileStart (const String& directory, const String& wildCard, String& firstResultFile,
|
||||
bool* isDir, bool* isHidden, int64* fileSize, Time* modTime,
|
||||
Time* creationTime, bool* isReadOnly) throw()
|
||||
{
|
||||
DIR* const d = opendir (directory.toUTF8());
|
||||
|
||||
if (d != 0)
|
||||
{
|
||||
FindFileStruct* const ff = new FindFileStruct();
|
||||
ff->parentDir = directory;
|
||||
|
||||
if (!ff->parentDir.endsWithChar (File::separator))
|
||||
ff->parentDir += File::separator;
|
||||
|
||||
ff->wildCard = wildCard;
|
||||
ff->dir = d;
|
||||
|
||||
if (ff->getNextMatch (firstResultFile, isDir, isHidden, fileSize, modTime, creationTime, isReadOnly))
|
||||
{
|
||||
return ff;
|
||||
}
|
||||
else
|
||||
{
|
||||
firstResultFile = String::empty;
|
||||
isDir = false;
|
||||
closedir (d);
|
||||
delete ff;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool juce_findFileNext (void* handle, String& resultFile,
|
||||
bool* isDir, bool* isHidden, int64* fileSize, Time* modTime, Time* creationTime, bool* isReadOnly) throw()
|
||||
{
|
||||
FindFileStruct* const ff = (FindFileStruct*) handle;
|
||||
|
||||
if (ff != 0)
|
||||
return ff->getNextMatch (resultFile, isDir, isHidden, fileSize, modTime, creationTime, isReadOnly);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void juce_findFileClose (void* handle) throw()
|
||||
{
|
||||
FindFileStruct* const ff = (FindFileStruct*)handle;
|
||||
|
||||
if (ff != 0)
|
||||
{
|
||||
closedir (ff->dir);
|
||||
delete ff;
|
||||
}
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
bool juce_launchExecutable (const String& pathAndArguments) throw()
|
||||
{
|
||||
char* const argv[4] = { "/bin/sh", "-c", (char*) (const char*) pathAndArguments, 0 };
|
||||
|
||||
const int cpid = fork();
|
||||
|
||||
if (cpid == 0)
|
||||
{
|
||||
// Child process
|
||||
if (execve (argv[0], argv, 0) < 0)
|
||||
exit (0);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (cpid < 0)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool juce_launchFile (const String& fileName,
|
||||
const String& parameters) throw()
|
||||
{
|
||||
bool ok = false;
|
||||
|
||||
if (fileName.startsWithIgnoreCase (T("http:"))
|
||||
|| fileName.startsWithIgnoreCase (T("https:"))
|
||||
|| fileName.startsWithIgnoreCase (T("ftp:"))
|
||||
|| fileName.startsWithIgnoreCase (T("file:")))
|
||||
{
|
||||
CFStringRef urlString = PlatformUtilities::juceStringToCFString (fileName);
|
||||
|
||||
if (urlString != 0)
|
||||
{
|
||||
CFURLRef url = CFURLCreateWithString (kCFAllocatorDefault,
|
||||
urlString, 0);
|
||||
CFRelease (urlString);
|
||||
|
||||
if (url != 0)
|
||||
{
|
||||
ok = (LSOpenCFURLRef (url, 0) == noErr);
|
||||
CFRelease (url);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
FSRef ref;
|
||||
if (PlatformUtilities::makeFSRefFromPath (&ref, fileName))
|
||||
{
|
||||
if (juce_isDirectory (fileName) && parameters.isNotEmpty())
|
||||
{
|
||||
// if we're launching a bundled app with a document..
|
||||
StringArray docs;
|
||||
docs.addTokens (parameters, true);
|
||||
FSRef* docRefs = new FSRef [docs.size()];
|
||||
|
||||
for (int i = 0; i < docs.size(); ++i)
|
||||
PlatformUtilities::makeFSRefFromPath (docRefs + i, docs[i]);
|
||||
|
||||
LSLaunchFSRefSpec ors;
|
||||
ors.appRef = &ref;
|
||||
ors.numDocs = docs.size();
|
||||
ors.itemRefs = docRefs;
|
||||
ors.passThruParams = 0;
|
||||
ors.launchFlags = kLSLaunchDefaults;
|
||||
ors.asyncRefCon = 0;
|
||||
|
||||
FSRef actual;
|
||||
ok = (LSOpenFromRefSpec (&ors, &actual) == noErr);
|
||||
|
||||
delete docRefs;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (parameters.isNotEmpty())
|
||||
ok = juce_launchExecutable (T("\"") + fileName + T("\" ") + parameters);
|
||||
else
|
||||
ok = (LSOpenFSRef (&ref, 0) == noErr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
bool PlatformUtilities::makeFSSpecFromPath (FSSpec* fs, const String& path)
|
||||
{
|
||||
FSRef ref;
|
||||
|
||||
return makeFSRefFromPath (&ref, path)
|
||||
&& FSGetCatalogInfo (&ref, kFSCatInfoNone, 0, 0, fs, 0) == noErr;
|
||||
}
|
||||
|
||||
bool PlatformUtilities::makeFSRefFromPath (FSRef* destFSRef, const String& path)
|
||||
{
|
||||
return FSPathMakeRef ((const UInt8*) path.toUTF8(), destFSRef, 0) == noErr;
|
||||
}
|
||||
|
||||
const String PlatformUtilities::makePathFromFSRef (FSRef* file)
|
||||
{
|
||||
uint8 path [2048];
|
||||
zeromem (path, sizeof (path));
|
||||
|
||||
String result;
|
||||
|
||||
if (FSRefMakePath (file, (UInt8*) path, sizeof (path) - 1) == noErr)
|
||||
result = String::fromUTF8 (path);
|
||||
|
||||
return PlatformUtilities::convertToPrecomposedUnicode (result);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
OSType PlatformUtilities::getTypeOfFile (const String& filename)
|
||||
{
|
||||
FSRef fs;
|
||||
if (makeFSRefFromPath (&fs, filename))
|
||||
{
|
||||
LSItemInfoRecord info;
|
||||
|
||||
if (LSCopyItemInfoForRef (&fs, kLSRequestTypeCreator, &info) == noErr)
|
||||
return info.filetype;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool PlatformUtilities::isBundle (const String& filename)
|
||||
{
|
||||
FSRef fs;
|
||||
if (makeFSRefFromPath (&fs, filename))
|
||||
{
|
||||
LSItemInfoRecord info;
|
||||
|
||||
if (LSCopyItemInfoForRef (&fs, kLSItemInfoIsPackage, &info) == noErr)
|
||||
return (info.flags & kLSItemInfoIsPackage) != 0;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
END_JUCE_NAMESPACE
|
||||
|
|
@ -59,6 +59,7 @@ using namespace JUCE_NAMESPACE;
|
|||
- (void) applicationWillUnhide: (NSNotification*) aNotification;
|
||||
- (void) customEvent: (id) data;
|
||||
- (void) performCallback: (id) info;
|
||||
- (void) dummyMethod;
|
||||
@end
|
||||
|
||||
@implementation JuceAppDelegate
|
||||
|
|
@ -171,6 +172,8 @@ using namespace JUCE_NAMESPACE;
|
|||
}
|
||||
}
|
||||
|
||||
- (void) dummyMethod {} // (used as a way of running a dummy thread)
|
||||
|
||||
@end
|
||||
|
||||
BEGIN_JUCE_NAMESPACE
|
||||
|
|
@ -207,7 +210,7 @@ bool MessageManager::runDispatchLoopUntil (int millisecondsToRunFor)
|
|||
const ScopedAutoReleasePool pool;
|
||||
|
||||
[[NSRunLoop currentRunLoop] runMode: NSDefaultRunLoopMode
|
||||
beforeDate: endDate];
|
||||
beforeDate: endDate];
|
||||
|
||||
NSEvent* e = [NSApp nextEventMatchingMask: NSAnyEventMask
|
||||
untilDate: endDate
|
||||
|
|
@ -225,6 +228,13 @@ void MessageManager::doPlatformSpecificInitialisation()
|
|||
if (juceAppDelegate == 0)
|
||||
juceAppDelegate = [[JuceAppDelegate alloc] init];
|
||||
|
||||
// This launches a dummy thread, which forces Cocoa to initialise NSThreads
|
||||
// correctly (needed prior to 10.5)
|
||||
if (! [NSThread isMultiThreaded])
|
||||
[NSThread detachNewThreadSelector: @selector (dummyMethod)
|
||||
toTarget: juceAppDelegate
|
||||
withObject: nil];
|
||||
|
||||
initialiseMainMenu();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -425,16 +425,16 @@ static void updateModifiers (NSEvent* e)
|
|||
int m = currentModifiers & ~(ModifierKeys::shiftModifier | ModifierKeys::ctrlModifier
|
||||
| ModifierKeys::altModifier | ModifierKeys::commandModifier);
|
||||
|
||||
if ((e.modifierFlags & NSShiftKeyMask) != 0)
|
||||
if (([e modifierFlags] & NSShiftKeyMask) != 0)
|
||||
m |= ModifierKeys::shiftModifier;
|
||||
|
||||
if ((e.modifierFlags & NSControlKeyMask) != 0)
|
||||
if (([e modifierFlags] & NSControlKeyMask) != 0)
|
||||
m |= ModifierKeys::ctrlModifier;
|
||||
|
||||
if ((e.modifierFlags & NSAlternateKeyMask) != 0)
|
||||
if (([e modifierFlags] & NSAlternateKeyMask) != 0)
|
||||
m |= ModifierKeys::altModifier;
|
||||
|
||||
if ((e.modifierFlags & NSCommandKeyMask) != 0)
|
||||
if (([e modifierFlags] & NSCommandKeyMask) != 0)
|
||||
m |= ModifierKeys::commandModifier;
|
||||
|
||||
currentModifiers = m;
|
||||
|
|
@ -557,7 +557,7 @@ static int getModifierForButtonNumber (const int num) throw()
|
|||
updateKeysDown (ev, true);
|
||||
used = owner->handleKeyEvent (ev, true);
|
||||
|
||||
if ((ev.modifierFlags & NSCommandKeyMask) != 0)
|
||||
if (([ev modifierFlags] & NSCommandKeyMask) != 0)
|
||||
{
|
||||
// for command keys, the key-up event is thrown away, so simulate one..
|
||||
updateKeysDown (ev, false);
|
||||
|
|
|
|||
|
|
@ -1,202 +0,0 @@
|
|||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library - "Jules' Utility Class Extensions"
|
||||
Copyright 2004-7 by Raw Material Software ltd.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
JUCE can be redistributed and/or modified under the terms of the
|
||||
GNU General Public License, as published by the Free Software Foundation;
|
||||
either version 2 of the License, or (at your option) any later version.
|
||||
|
||||
JUCE is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with JUCE; if not, visit www.gnu.org/licenses or write to the
|
||||
Free Software Foundation, Inc., 59 Temple Place, Suite 330,
|
||||
Boston, MA 02111-1307 USA
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
If you'd like to release a closed-source product which uses JUCE, commercial
|
||||
licenses are also available: visit www.rawmaterialsoftware.com/juce for
|
||||
more information.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#include "../../../src/juce_core/basics/juce_StandardHeader.h"
|
||||
#include <pthread.h>
|
||||
#include <sched.h>
|
||||
#include <sys/file.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/sysctl.h>
|
||||
|
||||
BEGIN_JUCE_NAMESPACE
|
||||
|
||||
#include "../../../src/juce_core/threads/juce_CriticalSection.h"
|
||||
#include "../../../src/juce_core/threads/juce_WaitableEvent.h"
|
||||
#include "../../../src/juce_core/threads/juce_Thread.h"
|
||||
#include "../../../src/juce_core/threads/juce_Process.h"
|
||||
#include "../../../src/juce_core/misc/juce_PlatformUtilities.h"
|
||||
#include "../../../src/juce_core/io/files/juce_File.h"
|
||||
|
||||
//==============================================================================
|
||||
/*
|
||||
Note that a lot of methods that you'd expect to find in this file actually
|
||||
live in juce_posix_SharedCode.h!
|
||||
*/
|
||||
|
||||
//==============================================================================
|
||||
void JUCE_API juce_threadEntryPoint (void*);
|
||||
|
||||
void* threadEntryProc (void* userData) throw()
|
||||
{
|
||||
juce_threadEntryPoint (userData);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void* juce_createThread (void* userData) throw()
|
||||
{
|
||||
pthread_t handle = 0;
|
||||
|
||||
if (pthread_create (&handle, 0, threadEntryProc, userData) == 0)
|
||||
{
|
||||
pthread_detach (handle);
|
||||
return (void*) handle;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void juce_killThread (void* handle) throw()
|
||||
{
|
||||
if (handle != 0)
|
||||
pthread_cancel ((pthread_t) handle);
|
||||
}
|
||||
|
||||
void juce_setCurrentThreadName (const String& /*name*/) throw()
|
||||
{
|
||||
}
|
||||
|
||||
int Thread::getCurrentThreadId() throw()
|
||||
{
|
||||
return (int) pthread_self();
|
||||
}
|
||||
|
||||
void juce_setThreadPriority (void* handle, int priority) throw()
|
||||
{
|
||||
if (handle == 0)
|
||||
handle = (void*) pthread_self();
|
||||
|
||||
struct sched_param param;
|
||||
int policy;
|
||||
pthread_getschedparam ((pthread_t) handle, &policy, ¶m);
|
||||
param.sched_priority = jlimit (1, 127, 1 + (priority * 126) / 11);
|
||||
pthread_setschedparam ((pthread_t) handle, policy, ¶m);
|
||||
}
|
||||
|
||||
void Thread::yield() throw()
|
||||
{
|
||||
sched_yield();
|
||||
}
|
||||
|
||||
void Thread::setCurrentThreadAffinityMask (const uint32 affinityMask) throw()
|
||||
{
|
||||
// xxx
|
||||
jassertfalse
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
bool JUCE_CALLTYPE juce_isRunningUnderDebugger() throw()
|
||||
{
|
||||
static char testResult = 0;
|
||||
|
||||
if (testResult == 0)
|
||||
{
|
||||
struct kinfo_proc info;
|
||||
int m[] = { CTL_KERN, KERN_PROC, KERN_PROC_PID, getpid() };
|
||||
size_t sz = sizeof (info);
|
||||
sysctl (m, 4, &info, &sz, 0, 0);
|
||||
testResult = ((info.kp_proc.p_flag & P_TRACED) != 0) ? 1 : -1;
|
||||
}
|
||||
|
||||
return testResult > 0;
|
||||
}
|
||||
|
||||
bool JUCE_CALLTYPE Process::isRunningUnderDebugger() throw()
|
||||
{
|
||||
return juce_isRunningUnderDebugger();
|
||||
}
|
||||
|
||||
void Process::raisePrivilege()
|
||||
{
|
||||
jassertfalse
|
||||
}
|
||||
|
||||
void Process::lowerPrivilege()
|
||||
{
|
||||
jassertfalse
|
||||
}
|
||||
|
||||
void Process::terminate()
|
||||
{
|
||||
exit (0);
|
||||
}
|
||||
|
||||
void Process::setPriority (ProcessPriority p)
|
||||
{
|
||||
// xxx
|
||||
}
|
||||
|
||||
void* Process::loadDynamicLibrary (const String& name)
|
||||
{
|
||||
// xxx needs to use bundles
|
||||
|
||||
FSSpec fs;
|
||||
if (PlatformUtilities::makeFSSpecFromPath (&fs, name))
|
||||
{
|
||||
CFragConnectionID connID;
|
||||
Ptr mainPtr;
|
||||
Str255 errorMessage;
|
||||
Str63 nm;
|
||||
PlatformUtilities::copyToStr63 (nm, name);
|
||||
|
||||
const OSErr err = GetDiskFragment (&fs, 0, kCFragGoesToEOF, nm, kReferenceCFrag, &connID, &mainPtr, errorMessage);
|
||||
if (err == noErr)
|
||||
return (void*)connID;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Process::freeDynamicLibrary (void* handle)
|
||||
{
|
||||
if (handle != 0)
|
||||
CloseConnection ((CFragConnectionID*)&handle);
|
||||
}
|
||||
|
||||
void* Process::getProcedureEntryPoint (void* h, const String& procedureName)
|
||||
{
|
||||
if (h != 0)
|
||||
{
|
||||
CFragSymbolClass cl;
|
||||
Ptr ptr;
|
||||
Str255 name;
|
||||
PlatformUtilities::copyToStr255 (name, procedureName);
|
||||
|
||||
if (FindSymbol ((CFragConnectionID) h, name, &ptr, &cl) == noErr)
|
||||
{
|
||||
return ptr;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
END_JUCE_NAMESPACE
|
||||
|
|
@ -264390,16 +264390,16 @@ static void updateModifiers (NSEvent* e)
|
|||
int m = currentModifiers & ~(ModifierKeys::shiftModifier | ModifierKeys::ctrlModifier
|
||||
| ModifierKeys::altModifier | ModifierKeys::commandModifier);
|
||||
|
||||
if ((e.modifierFlags & NSShiftKeyMask) != 0)
|
||||
if (([e modifierFlags] & NSShiftKeyMask) != 0)
|
||||
m |= ModifierKeys::shiftModifier;
|
||||
|
||||
if ((e.modifierFlags & NSControlKeyMask) != 0)
|
||||
if (([e modifierFlags] & NSControlKeyMask) != 0)
|
||||
m |= ModifierKeys::ctrlModifier;
|
||||
|
||||
if ((e.modifierFlags & NSAlternateKeyMask) != 0)
|
||||
if (([e modifierFlags] & NSAlternateKeyMask) != 0)
|
||||
m |= ModifierKeys::altModifier;
|
||||
|
||||
if ((e.modifierFlags & NSCommandKeyMask) != 0)
|
||||
if (([e modifierFlags] & NSCommandKeyMask) != 0)
|
||||
m |= ModifierKeys::commandModifier;
|
||||
|
||||
currentModifiers = m;
|
||||
|
|
@ -264521,7 +264521,7 @@ static int getModifierForButtonNumber (const int num) throw()
|
|||
updateKeysDown (ev, true);
|
||||
used = owner->handleKeyEvent (ev, true);
|
||||
|
||||
if ((ev.modifierFlags & NSCommandKeyMask) != 0)
|
||||
if (([ev modifierFlags] & NSCommandKeyMask) != 0)
|
||||
{
|
||||
// for command keys, the key-up event is thrown away, so simulate one..
|
||||
updateKeysDown (ev, false);
|
||||
|
|
@ -267636,6 +267636,7 @@ using namespace JUCE_NAMESPACE;
|
|||
- (void) applicationWillUnhide: (NSNotification*) aNotification;
|
||||
- (void) customEvent: (id) data;
|
||||
- (void) performCallback: (id) info;
|
||||
- (void) dummyMethod;
|
||||
@end
|
||||
|
||||
@implementation JuceAppDelegate
|
||||
|
|
@ -267748,6 +267749,8 @@ using namespace JUCE_NAMESPACE;
|
|||
}
|
||||
}
|
||||
|
||||
- (void) dummyMethod {} // (used as a way of running a dummy thread)
|
||||
|
||||
@end
|
||||
|
||||
BEGIN_JUCE_NAMESPACE
|
||||
|
|
@ -267784,7 +267787,7 @@ bool MessageManager::runDispatchLoopUntil (int millisecondsToRunFor)
|
|||
const ScopedAutoReleasePool pool;
|
||||
|
||||
[[NSRunLoop currentRunLoop] runMode: NSDefaultRunLoopMode
|
||||
beforeDate: endDate];
|
||||
beforeDate: endDate];
|
||||
|
||||
NSEvent* e = [NSApp nextEventMatchingMask: NSAnyEventMask
|
||||
untilDate: endDate
|
||||
|
|
@ -267801,6 +267804,13 @@ void MessageManager::doPlatformSpecificInitialisation()
|
|||
if (juceAppDelegate == 0)
|
||||
juceAppDelegate = [[JuceAppDelegate alloc] init];
|
||||
|
||||
// This launches a dummy thread, which forces Cocoa to initialise NSThreads
|
||||
// correctly (needed prior to 10.5)
|
||||
if (! [NSThread isMultiThreaded])
|
||||
[NSThread detachNewThreadSelector: @selector (dummyMethod)
|
||||
toTarget: juceAppDelegate
|
||||
withObject: nil];
|
||||
|
||||
initialiseMainMenu();
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue