@@ -236,7 +236,9 @@ bool AudioCDReader::isCDStillPresent() const | |||
void AudioCDReader::ejectDisk() | |||
{ | |||
JUCE_AUTORELEASEPOOL | |||
[[NSWorkspace sharedWorkspace] unmountAndEjectDeviceAtPath: juceStringToNS (volumeDir.getFullPathName())]; | |||
{ | |||
[[NSWorkspace sharedWorkspace] unmountAndEjectDeviceAtPath: juceStringToNS (volumeDir.getFullPathName())]; | |||
} | |||
} | |||
bool AudioCDReader::isTrackAudio (int trackNum) const | |||
@@ -84,225 +84,231 @@ public: | |||
dataHandle (0) | |||
{ | |||
JUCE_AUTORELEASEPOOL | |||
bufferList.calloc (256, 1); | |||
{ | |||
bufferList.calloc (256, 1); | |||
#if JUCE_WINDOWS | |||
if (InitializeQTML (0) != noErr) | |||
return; | |||
#endif | |||
#if JUCE_WINDOWS | |||
if (InitializeQTML (0) != noErr) | |||
return; | |||
#endif | |||
if (EnterMovies() != noErr) | |||
return; | |||
if (EnterMovies() != noErr) | |||
return; | |||
bool opened = juce_OpenQuickTimeMovieFromStream (input_, movie, dataHandle); | |||
bool opened = juce_OpenQuickTimeMovieFromStream (input_, movie, dataHandle); | |||
if (! opened) | |||
return; | |||
if (! opened) | |||
return; | |||
{ | |||
const int numTracks = GetMovieTrackCount (movie); | |||
int trackCount = 0; | |||
for (int i = 1; i <= numTracks; ++i) | |||
{ | |||
track = GetMovieIndTrack (movie, i); | |||
media = GetTrackMedia (track); | |||
OSType mediaType; | |||
GetMediaHandlerDescription (media, &mediaType, 0, 0); | |||
const int numTracks = GetMovieTrackCount (movie); | |||
int trackCount = 0; | |||
if (mediaType == SoundMediaType | |||
&& trackCount++ == trackNum_) | |||
for (int i = 1; i <= numTracks; ++i) | |||
{ | |||
ok = true; | |||
break; | |||
track = GetMovieIndTrack (movie, i); | |||
media = GetTrackMedia (track); | |||
OSType mediaType; | |||
GetMediaHandlerDescription (media, &mediaType, 0, 0); | |||
if (mediaType == SoundMediaType | |||
&& trackCount++ == trackNum_) | |||
{ | |||
ok = true; | |||
break; | |||
} | |||
} | |||
} | |||
} | |||
if (! ok) | |||
return; | |||
if (! ok) | |||
return; | |||
ok = false; | |||
lengthInSamples = GetMediaDecodeDuration (media); | |||
usesFloatingPointData = false; | |||
ok = false; | |||
samplesPerFrame = (int) (GetMediaDecodeDuration (media) / GetMediaSampleCount (media)); | |||
lengthInSamples = GetMediaDecodeDuration (media); | |||
usesFloatingPointData = false; | |||
trackUnitsPerFrame = GetMovieTimeScale (movie) * samplesPerFrame | |||
/ GetMediaTimeScale (media); | |||
samplesPerFrame = (int) (GetMediaDecodeDuration (media) / GetMediaSampleCount (media)); | |||
OSStatus err = MovieAudioExtractionBegin (movie, 0, &extractor); | |||
trackUnitsPerFrame = GetMovieTimeScale (movie) * samplesPerFrame | |||
/ GetMediaTimeScale (media); | |||
unsigned long output_layout_size; | |||
err = MovieAudioExtractionGetPropertyInfo (extractor, | |||
kQTPropertyClass_MovieAudioExtraction_Audio, | |||
kQTMovieAudioExtractionAudioPropertyID_AudioChannelLayout, | |||
0, &output_layout_size, 0); | |||
if (err != noErr) | |||
return; | |||
HeapBlock <AudioChannelLayout> qt_audio_channel_layout; | |||
qt_audio_channel_layout.calloc (output_layout_size, 1); | |||
err = MovieAudioExtractionGetProperty (extractor, | |||
kQTPropertyClass_MovieAudioExtraction_Audio, | |||
kQTMovieAudioExtractionAudioPropertyID_AudioChannelLayout, | |||
output_layout_size, qt_audio_channel_layout, 0); | |||
OSStatus err = MovieAudioExtractionBegin (movie, 0, &extractor); | |||
qt_audio_channel_layout[0].mChannelLayoutTag = kAudioChannelLayoutTag_Stereo; | |||
unsigned long output_layout_size; | |||
err = MovieAudioExtractionGetPropertyInfo (extractor, | |||
err = MovieAudioExtractionSetProperty (extractor, | |||
kQTPropertyClass_MovieAudioExtraction_Audio, | |||
kQTMovieAudioExtractionAudioPropertyID_AudioChannelLayout, | |||
0, &output_layout_size, 0); | |||
if (err != noErr) | |||
return; | |||
HeapBlock <AudioChannelLayout> qt_audio_channel_layout; | |||
qt_audio_channel_layout.calloc (output_layout_size, 1); | |||
err = MovieAudioExtractionGetProperty (extractor, | |||
kQTPropertyClass_MovieAudioExtraction_Audio, | |||
kQTMovieAudioExtractionAudioPropertyID_AudioChannelLayout, | |||
output_layout_size, qt_audio_channel_layout, 0); | |||
qt_audio_channel_layout[0].mChannelLayoutTag = kAudioChannelLayoutTag_Stereo; | |||
err = MovieAudioExtractionSetProperty (extractor, | |||
kQTPropertyClass_MovieAudioExtraction_Audio, | |||
kQTMovieAudioExtractionAudioPropertyID_AudioChannelLayout, | |||
output_layout_size, | |||
qt_audio_channel_layout); | |||
err = MovieAudioExtractionGetProperty (extractor, | |||
kQTPropertyClass_MovieAudioExtraction_Audio, | |||
kQTMovieAudioExtractionAudioPropertyID_AudioStreamBasicDescription, | |||
sizeof (inputStreamDesc), | |||
&inputStreamDesc, 0); | |||
if (err != noErr) | |||
return; | |||
inputStreamDesc.mFormatFlags = kAudioFormatFlagIsSignedInteger | |||
| kAudioFormatFlagIsPacked | |||
| kAudioFormatFlagsNativeEndian; | |||
inputStreamDesc.mBitsPerChannel = sizeof (SInt16) * 8; | |||
inputStreamDesc.mChannelsPerFrame = jmin ((UInt32) 2, inputStreamDesc.mChannelsPerFrame); | |||
inputStreamDesc.mBytesPerFrame = sizeof (SInt16) * inputStreamDesc.mChannelsPerFrame; | |||
inputStreamDesc.mBytesPerPacket = inputStreamDesc.mBytesPerFrame; | |||
err = MovieAudioExtractionSetProperty (extractor, | |||
kQTPropertyClass_MovieAudioExtraction_Audio, | |||
kQTMovieAudioExtractionAudioPropertyID_AudioStreamBasicDescription, | |||
sizeof (inputStreamDesc), | |||
&inputStreamDesc); | |||
if (err != noErr) | |||
return; | |||
Boolean allChannelsDiscrete = false; | |||
err = MovieAudioExtractionSetProperty (extractor, | |||
kQTPropertyClass_MovieAudioExtraction_Movie, | |||
kQTMovieAudioExtractionMoviePropertyID_AllChannelsDiscrete, | |||
sizeof (allChannelsDiscrete), | |||
&allChannelsDiscrete); | |||
if (err != noErr) | |||
return; | |||
bufferList->mNumberBuffers = 1; | |||
bufferList->mBuffers[0].mNumberChannels = inputStreamDesc.mChannelsPerFrame; | |||
bufferList->mBuffers[0].mDataByteSize = jmax ((UInt32) 4096, (UInt32) (samplesPerFrame * inputStreamDesc.mBytesPerFrame) + 16); | |||
dataBuffer.malloc (bufferList->mBuffers[0].mDataByteSize); | |||
bufferList->mBuffers[0].mData = dataBuffer; | |||
sampleRate = inputStreamDesc.mSampleRate; | |||
bitsPerSample = 16; | |||
numChannels = inputStreamDesc.mChannelsPerFrame; | |||
detachThread(); | |||
ok = true; | |||
output_layout_size, | |||
qt_audio_channel_layout); | |||
err = MovieAudioExtractionGetProperty (extractor, | |||
kQTPropertyClass_MovieAudioExtraction_Audio, | |||
kQTMovieAudioExtractionAudioPropertyID_AudioStreamBasicDescription, | |||
sizeof (inputStreamDesc), | |||
&inputStreamDesc, 0); | |||
if (err != noErr) | |||
return; | |||
inputStreamDesc.mFormatFlags = kAudioFormatFlagIsSignedInteger | |||
| kAudioFormatFlagIsPacked | |||
| kAudioFormatFlagsNativeEndian; | |||
inputStreamDesc.mBitsPerChannel = sizeof (SInt16) * 8; | |||
inputStreamDesc.mChannelsPerFrame = jmin ((UInt32) 2, inputStreamDesc.mChannelsPerFrame); | |||
inputStreamDesc.mBytesPerFrame = sizeof (SInt16) * inputStreamDesc.mChannelsPerFrame; | |||
inputStreamDesc.mBytesPerPacket = inputStreamDesc.mBytesPerFrame; | |||
err = MovieAudioExtractionSetProperty (extractor, | |||
kQTPropertyClass_MovieAudioExtraction_Audio, | |||
kQTMovieAudioExtractionAudioPropertyID_AudioStreamBasicDescription, | |||
sizeof (inputStreamDesc), | |||
&inputStreamDesc); | |||
if (err != noErr) | |||
return; | |||
Boolean allChannelsDiscrete = false; | |||
err = MovieAudioExtractionSetProperty (extractor, | |||
kQTPropertyClass_MovieAudioExtraction_Movie, | |||
kQTMovieAudioExtractionMoviePropertyID_AllChannelsDiscrete, | |||
sizeof (allChannelsDiscrete), | |||
&allChannelsDiscrete); | |||
if (err != noErr) | |||
return; | |||
bufferList->mNumberBuffers = 1; | |||
bufferList->mBuffers[0].mNumberChannels = inputStreamDesc.mChannelsPerFrame; | |||
bufferList->mBuffers[0].mDataByteSize = jmax ((UInt32) 4096, (UInt32) (samplesPerFrame * inputStreamDesc.mBytesPerFrame) + 16); | |||
dataBuffer.malloc (bufferList->mBuffers[0].mDataByteSize); | |||
bufferList->mBuffers[0].mData = dataBuffer; | |||
sampleRate = inputStreamDesc.mSampleRate; | |||
bitsPerSample = 16; | |||
numChannels = inputStreamDesc.mChannelsPerFrame; | |||
detachThread(); | |||
ok = true; | |||
} | |||
} | |||
~QTAudioReader() | |||
{ | |||
JUCE_AUTORELEASEPOOL | |||
checkThreadIsAttached(); | |||
{ | |||
checkThreadIsAttached(); | |||
if (dataHandle != nullptr) | |||
DisposeHandle (dataHandle); | |||
if (dataHandle != nullptr) | |||
DisposeHandle (dataHandle); | |||
if (extractor != nullptr) | |||
{ | |||
MovieAudioExtractionEnd (extractor); | |||
extractor = nullptr; | |||
} | |||
if (extractor != nullptr) | |||
{ | |||
MovieAudioExtractionEnd (extractor); | |||
extractor = nullptr; | |||
} | |||
DisposeMovie (movie); | |||
DisposeMovie (movie); | |||
#if JUCE_MAC | |||
ExitMoviesOnThread (); | |||
#endif | |||
#if JUCE_MAC | |||
ExitMoviesOnThread (); | |||
#endif | |||
} | |||
} | |||
bool readSamples (int** destSamples, int numDestChannels, int startOffsetInDestBuffer, | |||
int64 startSampleInFile, int numSamples) | |||
{ | |||
JUCE_AUTORELEASEPOOL | |||
checkThreadIsAttached(); | |||
bool readOk = true; | |||
while (numSamples > 0) | |||
{ | |||
if (lastSampleRead != startSampleInFile) | |||
checkThreadIsAttached(); | |||
bool readOk = true; | |||
while (numSamples > 0) | |||
{ | |||
TimeRecord time; | |||
time.scale = (TimeScale) inputStreamDesc.mSampleRate; | |||
time.base = 0; | |||
time.value.hi = 0; | |||
time.value.lo = (UInt32) startSampleInFile; | |||
if (lastSampleRead != startSampleInFile) | |||
{ | |||
TimeRecord time; | |||
time.scale = (TimeScale) inputStreamDesc.mSampleRate; | |||
time.base = 0; | |||
time.value.hi = 0; | |||
time.value.lo = (UInt32) startSampleInFile; | |||
OSStatus err = MovieAudioExtractionSetProperty (extractor, | |||
kQTPropertyClass_MovieAudioExtraction_Movie, | |||
kQTMovieAudioExtractionMoviePropertyID_CurrentTime, | |||
sizeof (time), &time); | |||
if (err != noErr) | |||
{ | |||
readOk = false; | |||
break; | |||
} | |||
} | |||
OSStatus err = MovieAudioExtractionSetProperty (extractor, | |||
kQTPropertyClass_MovieAudioExtraction_Movie, | |||
kQTMovieAudioExtractionMoviePropertyID_CurrentTime, | |||
sizeof (time), &time); | |||
int framesToDo = jmin (numSamples, (int) (bufferList->mBuffers[0].mDataByteSize / inputStreamDesc.mBytesPerFrame)); | |||
bufferList->mBuffers[0].mDataByteSize = inputStreamDesc.mBytesPerFrame * framesToDo; | |||
UInt32 outFlags = 0; | |||
UInt32 actualNumFrames = framesToDo; | |||
OSStatus err = MovieAudioExtractionFillBuffer (extractor, &actualNumFrames, bufferList, &outFlags); | |||
if (err != noErr) | |||
{ | |||
readOk = false; | |||
break; | |||
} | |||
} | |||
int framesToDo = jmin (numSamples, (int) (bufferList->mBuffers[0].mDataByteSize / inputStreamDesc.mBytesPerFrame)); | |||
bufferList->mBuffers[0].mDataByteSize = inputStreamDesc.mBytesPerFrame * framesToDo; | |||
lastSampleRead = startSampleInFile + actualNumFrames; | |||
const int samplesReceived = actualNumFrames; | |||
UInt32 outFlags = 0; | |||
UInt32 actualNumFrames = framesToDo; | |||
OSStatus err = MovieAudioExtractionFillBuffer (extractor, &actualNumFrames, bufferList, &outFlags); | |||
if (err != noErr) | |||
{ | |||
readOk = false; | |||
break; | |||
} | |||
lastSampleRead = startSampleInFile + actualNumFrames; | |||
const int samplesReceived = actualNumFrames; | |||
for (int j = numDestChannels; --j >= 0;) | |||
{ | |||
if (destSamples[j] != nullptr) | |||
for (int j = numDestChannels; --j >= 0;) | |||
{ | |||
const short* src = ((const short*) bufferList->mBuffers[0].mData) + j; | |||
for (int i = 0; i < samplesReceived; ++i) | |||
if (destSamples[j] != nullptr) | |||
{ | |||
destSamples[j][startOffsetInDestBuffer + i] = (*src << 16); | |||
src += numChannels; | |||
const short* src = ((const short*) bufferList->mBuffers[0].mData) + j; | |||
for (int i = 0; i < samplesReceived; ++i) | |||
{ | |||
destSamples[j][startOffsetInDestBuffer + i] = (*src << 16); | |||
src += numChannels; | |||
} | |||
} | |||
} | |||
} | |||
startOffsetInDestBuffer += samplesReceived; | |||
startSampleInFile += samplesReceived; | |||
numSamples -= samplesReceived; | |||
startOffsetInDestBuffer += samplesReceived; | |||
startSampleInFile += samplesReceived; | |||
numSamples -= samplesReceived; | |||
if (((outFlags & kQTMovieAudioExtractionComplete) != 0 || samplesReceived == 0) && numSamples > 0) | |||
{ | |||
for (int j = numDestChannels; --j >= 0;) | |||
if (destSamples[j] != nullptr) | |||
zeromem (destSamples[j] + startOffsetInDestBuffer, sizeof (int) * numSamples); | |||
if (((outFlags & kQTMovieAudioExtractionComplete) != 0 || samplesReceived == 0) && numSamples > 0) | |||
{ | |||
for (int j = numDestChannels; --j >= 0;) | |||
if (destSamples[j] != nullptr) | |||
zeromem (destSamples[j] + startOffsetInDestBuffer, sizeof (int) * numSamples); | |||
break; | |||
break; | |||
} | |||
} | |||
} | |||
detachThread(); | |||
return readOk; | |||
detachThread(); | |||
return readOk; | |||
} | |||
} | |||
bool ok; | |||
@@ -62,8 +62,8 @@ | |||
namespace juce | |||
{ | |||
static bool arrayContainsPlugin (const OwnedArray<PluginDescription>& list, | |||
const PluginDescription& desc) | |||
static inline bool arrayContainsPlugin (const OwnedArray<PluginDescription>& list, | |||
const PluginDescription& desc) | |||
{ | |||
for (int i = list.size(); --i >= 0;) | |||
if (list.getUnchecked(i)->isDuplicateOf (desc)) | |||
@@ -79,8 +79,16 @@ inline Type* createCopyIfNotNull (const Type* pointer) { return pointer != n | |||
JUCE_DECLARE_NON_COPYABLE (ScopedAutoReleasePool) | |||
}; | |||
/** A macro that can be used to easily declare a local ScopedAutoReleasePool object for RAII-based obj-C autoreleasing. */ | |||
/** A macro that can be used to easily declare a local ScopedAutoReleasePool | |||
object for RAII-based obj-C autoreleasing. | |||
Because this may use the @autoreleasepool syntax, you must follow the macro with | |||
a set of braces to mark the scope of the pool. | |||
*/ | |||
#if JUCE_COMPILER_SUPPORTS_ARC || DOXYGEN | |||
#define JUCE_AUTORELEASEPOOL @autoreleasepool | |||
#else | |||
#define JUCE_AUTORELEASEPOOL const juce::ScopedAutoReleasePool JUCE_JOIN_MACRO (autoReleasePool_, __LINE__); | |||
#endif | |||
#else | |||
#define JUCE_AUTORELEASEPOOL | |||
@@ -32,18 +32,20 @@ | |||
bool File::copyInternal (const File& dest) const | |||
{ | |||
JUCE_AUTORELEASEPOOL | |||
NSFileManager* fm = [NSFileManager defaultManager]; | |||
return [fm fileExistsAtPath: juceStringToNS (fullPath)] | |||
#if defined (MAC_OS_X_VERSION_10_6) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 | |||
&& [fm copyItemAtPath: juceStringToNS (fullPath) | |||
toPath: juceStringToNS (dest.getFullPathName()) | |||
error: nil]; | |||
#else | |||
&& [fm copyPath: juceStringToNS (fullPath) | |||
toPath: juceStringToNS (dest.getFullPathName()) | |||
handler: nil]; | |||
#endif | |||
{ | |||
NSFileManager* fm = [NSFileManager defaultManager]; | |||
return [fm fileExistsAtPath: juceStringToNS (fullPath)] | |||
#if defined (MAC_OS_X_VERSION_10_6) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 | |||
&& [fm copyItemAtPath: juceStringToNS (fullPath) | |||
toPath: juceStringToNS (dest.getFullPathName()) | |||
error: nil]; | |||
#else | |||
&& [fm copyPath: juceStringToNS (fullPath) | |||
toPath: juceStringToNS (dest.getFullPathName()) | |||
handler: nil]; | |||
#endif | |||
} | |||
} | |||
void File::findFileSystemRoots (Array<File>& destArray) | |||
@@ -75,12 +77,14 @@ namespace FileHelpers | |||
{ | |||
#if defined (MAC_OS_X_VERSION_10_6) && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_6 | |||
JUCE_AUTORELEASEPOOL | |||
NSNumber* hidden = nil; | |||
NSError* err = nil; | |||
{ | |||
NSNumber* hidden = nil; | |||
NSError* err = nil; | |||
return [[NSURL fileURLWithPath: juceStringToNS (path)] | |||
getResourceValue: &hidden forKey: NSURLIsHiddenKey error: &err] | |||
&& [hidden boolValue]; | |||
return [[NSURL fileURLWithPath: juceStringToNS (path)] | |||
getResourceValue: &hidden forKey: NSURLIsHiddenKey error: &err] | |||
&& [hidden boolValue]; | |||
} | |||
#elif JUCE_IOS | |||
return File (path).getFileName().startsWithChar ('.'); | |||
#else | |||
@@ -143,17 +147,19 @@ bool File::isOnRemovableDrive() const | |||
return false; // xxx is this possible? | |||
#else | |||
JUCE_AUTORELEASEPOOL | |||
BOOL removable = false; | |||
{ | |||
BOOL removable = false; | |||
[[NSWorkspace sharedWorkspace] | |||
getFileSystemInfoForPath: juceStringToNS (getFullPathName()) | |||
isRemovable: &removable | |||
isWritable: nil | |||
isUnmountable: nil | |||
description: nil | |||
type: nil]; | |||
[[NSWorkspace sharedWorkspace] | |||
getFileSystemInfoForPath: juceStringToNS (getFullPathName()) | |||
isRemovable: &removable | |||
isWritable: nil | |||
isUnmountable: nil | |||
description: nil | |||
type: nil]; | |||
return removable; | |||
return removable; | |||
} | |||
#endif | |||
} | |||
@@ -169,82 +175,84 @@ int juce_argc = 0; | |||
File File::getSpecialLocation (const SpecialLocationType type) | |||
{ | |||
JUCE_AUTORELEASEPOOL | |||
String resultPath; | |||
switch (type) | |||
{ | |||
case userHomeDirectory: resultPath = nsStringToJuce (NSHomeDirectory()); break; | |||
#if JUCE_IOS | |||
case userDocumentsDirectory: resultPath = FileHelpers::getIOSSystemLocation (NSDocumentDirectory); break; | |||
case userDesktopDirectory: resultPath = FileHelpers::getIOSSystemLocation (NSDesktopDirectory); break; | |||
String resultPath; | |||
case tempDirectory: | |||
switch (type) | |||
{ | |||
File tmp (FileHelpers::getIOSSystemLocation (NSCachesDirectory)); | |||
tmp = tmp.getChildFile (juce_getExecutableFile().getFileNameWithoutExtension()); | |||
tmp.createDirectory(); | |||
return tmp.getFullPathName(); | |||
} | |||
case userHomeDirectory: resultPath = nsStringToJuce (NSHomeDirectory()); break; | |||
#else | |||
case userDocumentsDirectory: resultPath = "~/Documents"; break; | |||
case userDesktopDirectory: resultPath = "~/Desktop"; break; | |||
#if JUCE_IOS | |||
case userDocumentsDirectory: resultPath = FileHelpers::getIOSSystemLocation (NSDocumentDirectory); break; | |||
case userDesktopDirectory: resultPath = FileHelpers::getIOSSystemLocation (NSDesktopDirectory); break; | |||
case tempDirectory: | |||
{ | |||
File tmp ("~/Library/Caches/" + juce_getExecutableFile().getFileNameWithoutExtension()); | |||
tmp.createDirectory(); | |||
return tmp.getFullPathName(); | |||
} | |||
#endif | |||
case userMusicDirectory: resultPath = "~/Music"; break; | |||
case userMoviesDirectory: resultPath = "~/Movies"; break; | |||
case userPicturesDirectory: resultPath = "~/Pictures"; break; | |||
case userApplicationDataDirectory: resultPath = "~/Library"; break; | |||
case commonApplicationDataDirectory: resultPath = "/Library"; break; | |||
case globalApplicationsDirectory: resultPath = "/Applications"; break; | |||
case invokedExecutableFile: | |||
if (juce_argv != nullptr && juce_argc > 0) | |||
return File (CharPointer_UTF8 (juce_argv[0])); | |||
// deliberate fall-through... | |||
case currentExecutableFile: | |||
return juce_getExecutableFile(); | |||
case currentApplicationFile: | |||
{ | |||
const File exe (juce_getExecutableFile()); | |||
const File parent (exe.getParentDirectory()); | |||
case tempDirectory: | |||
{ | |||
File tmp (FileHelpers::getIOSSystemLocation (NSCachesDirectory)); | |||
tmp = tmp.getChildFile (juce_getExecutableFile().getFileNameWithoutExtension()); | |||
tmp.createDirectory(); | |||
return tmp.getFullPathName(); | |||
} | |||
#if JUCE_IOS | |||
return parent; | |||
#else | |||
return parent.getFullPathName().endsWithIgnoreCase ("Contents/MacOS") | |||
? parent.getParentDirectory().getParentDirectory() | |||
: exe; | |||
case userDocumentsDirectory: resultPath = "~/Documents"; break; | |||
case userDesktopDirectory: resultPath = "~/Desktop"; break; | |||
case tempDirectory: | |||
{ | |||
File tmp ("~/Library/Caches/" + juce_getExecutableFile().getFileNameWithoutExtension()); | |||
tmp.createDirectory(); | |||
return tmp.getFullPathName(); | |||
} | |||
#endif | |||
case userMusicDirectory: resultPath = "~/Music"; break; | |||
case userMoviesDirectory: resultPath = "~/Movies"; break; | |||
case userPicturesDirectory: resultPath = "~/Pictures"; break; | |||
case userApplicationDataDirectory: resultPath = "~/Library"; break; | |||
case commonApplicationDataDirectory: resultPath = "/Library"; break; | |||
case globalApplicationsDirectory: resultPath = "/Applications"; break; | |||
case invokedExecutableFile: | |||
if (juce_argv != nullptr && juce_argc > 0) | |||
return File (CharPointer_UTF8 (juce_argv[0])); | |||
// deliberate fall-through... | |||
case currentExecutableFile: | |||
return juce_getExecutableFile(); | |||
case currentApplicationFile: | |||
{ | |||
const File exe (juce_getExecutableFile()); | |||
const File parent (exe.getParentDirectory()); | |||
#if JUCE_IOS | |||
return parent; | |||
#else | |||
return parent.getFullPathName().endsWithIgnoreCase ("Contents/MacOS") | |||
? parent.getParentDirectory().getParentDirectory() | |||
: exe; | |||
#endif | |||
} | |||
case hostApplicationPath: | |||
{ | |||
unsigned int size = 8192; | |||
HeapBlock<char> buffer; | |||
buffer.calloc (size + 8); | |||
_NSGetExecutablePath (buffer.getData(), &size); | |||
return String::fromUTF8 (buffer, (int) size); | |||
} | |||
default: | |||
jassertfalse; // unknown type? | |||
break; | |||
} | |||
case hostApplicationPath: | |||
{ | |||
unsigned int size = 8192; | |||
HeapBlock<char> buffer; | |||
buffer.calloc (size + 8); | |||
_NSGetExecutablePath (buffer.getData(), &size); | |||
return String::fromUTF8 (buffer, (int) size); | |||
} | |||
default: | |||
jassertfalse; // unknown type? | |||
break; | |||
if (resultPath.isNotEmpty()) | |||
return File (resultPath.convertToPrecomposedUnicode()); | |||
} | |||
if (resultPath.isNotEmpty()) | |||
return File (resultPath.convertToPrecomposedUnicode()); | |||
return File::nonexistent; | |||
} | |||
@@ -252,24 +260,14 @@ File File::getSpecialLocation (const SpecialLocationType type) | |||
String File::getVersion() const | |||
{ | |||
JUCE_AUTORELEASEPOOL | |||
String result; | |||
NSBundle* bundle = [NSBundle bundleWithPath: juceStringToNS (getFullPathName())]; | |||
if (bundle != nil) | |||
{ | |||
NSDictionary* info = [bundle infoDictionary]; | |||
if (info != nil) | |||
{ | |||
NSString* name = [info valueForKey: nsStringLiteral ("CFBundleShortVersionString")]; | |||
if (name != nil) | |||
result = nsStringToJuce (name); | |||
} | |||
if (NSBundle* bundle = [NSBundle bundleWithPath: juceStringToNS (getFullPathName())]) | |||
if (NSDictionary* info = [bundle infoDictionary]) | |||
if (NSString* name = [info valueForKey: nsStringLiteral ("CFBundleShortVersionString")]) | |||
return nsStringToJuce (name); | |||
} | |||
return result; | |||
return String::empty; | |||
} | |||
//============================================================================== | |||
@@ -298,15 +296,16 @@ bool File::moveToTrash() const | |||
return deleteFile(); //xxx is there a trashcan on the iOS? | |||
#else | |||
JUCE_AUTORELEASEPOOL | |||
NSString* p = juceStringToNS (getFullPathName()); | |||
return [[NSWorkspace sharedWorkspace] | |||
performFileOperation: NSWorkspaceRecycleOperation | |||
source: [p stringByDeletingLastPathComponent] | |||
destination: nsEmptyString() | |||
files: [NSArray arrayWithObject: [p lastPathComponent]] | |||
tag: nil ]; | |||
{ | |||
NSString* p = juceStringToNS (getFullPathName()); | |||
return [[NSWorkspace sharedWorkspace] | |||
performFileOperation: NSWorkspaceRecycleOperation | |||
source: [p stringByDeletingLastPathComponent] | |||
destination: nsEmptyString() | |||
files: [NSArray arrayWithObject: [p lastPathComponent]] | |||
tag: nil ]; | |||
} | |||
#endif | |||
} | |||
@@ -320,8 +319,9 @@ public: | |||
enumerator (nil) | |||
{ | |||
JUCE_AUTORELEASEPOOL | |||
enumerator = [[[NSFileManager defaultManager] enumeratorAtPath: juceStringToNS (directory.getFullPathName())] retain]; | |||
{ | |||
enumerator = [[[NSFileManager defaultManager] enumeratorAtPath: juceStringToNS (directory.getFullPathName())] retain]; | |||
} | |||
} | |||
~Pimpl() | |||
@@ -334,30 +334,32 @@ public: | |||
Time* const modTime, Time* const creationTime, bool* const isReadOnly) | |||
{ | |||
JUCE_AUTORELEASEPOOL | |||
const char* wildcardUTF8 = nullptr; | |||
for (;;) | |||
{ | |||
NSString* file; | |||
if (enumerator == nil || (file = [enumerator nextObject]) == nil) | |||
return false; | |||
const char* wildcardUTF8 = nullptr; | |||
[enumerator skipDescendents]; | |||
filenameFound = nsStringToJuce (file); | |||
for (;;) | |||
{ | |||
NSString* file; | |||
if (enumerator == nil || (file = [enumerator nextObject]) == nil) | |||
return false; | |||
if (wildcardUTF8 == nullptr) | |||
wildcardUTF8 = wildCard.toUTF8(); | |||
[enumerator skipDescendents]; | |||
filenameFound = nsStringToJuce (file); | |||
if (fnmatch (wildcardUTF8, filenameFound.toUTF8(), FNM_CASEFOLD) != 0) | |||
continue; | |||
if (wildcardUTF8 == nullptr) | |||
wildcardUTF8 = wildCard.toUTF8(); | |||
const String fullPath (parentDir + filenameFound); | |||
updateStatInfoForFile (fullPath, isDir, fileSize, modTime, creationTime, isReadOnly); | |||
if (fnmatch (wildcardUTF8, filenameFound.toUTF8(), FNM_CASEFOLD) != 0) | |||
continue; | |||
if (isHidden != nullptr) | |||
*isHidden = FileHelpers::isHiddenFile (fullPath); | |||
const String fullPath (parentDir + filenameFound); | |||
updateStatInfoForFile (fullPath, isDir, fileSize, modTime, creationTime, isReadOnly); | |||
return true; | |||
if (isHidden != nullptr) | |||
*isHidden = FileHelpers::isHiddenFile (fullPath); | |||
return true; | |||
} | |||
} | |||
} | |||
@@ -392,37 +394,38 @@ bool Process::openDocument (const String& fileName, const String& parameters) | |||
return [[UIApplication sharedApplication] openURL: [NSURL URLWithString: juceStringToNS (fileName)]]; | |||
#else | |||
JUCE_AUTORELEASEPOOL | |||
if (parameters.isEmpty()) | |||
{ | |||
return [[NSWorkspace sharedWorkspace] openFile: juceStringToNS (fileName)] | |||
|| [[NSWorkspace sharedWorkspace] openURL: [NSURL URLWithString: juceStringToNS (fileName)]]; | |||
} | |||
if (parameters.isEmpty()) | |||
{ | |||
return [[NSWorkspace sharedWorkspace] openFile: juceStringToNS (fileName)] | |||
|| [[NSWorkspace sharedWorkspace] openURL: [NSURL URLWithString: juceStringToNS (fileName)]]; | |||
} | |||
bool ok = false; | |||
const File file (fileName); | |||
bool ok = false; | |||
const File file (fileName); | |||
if (file.isBundle()) | |||
{ | |||
NSMutableArray* urls = [NSMutableArray array]; | |||
StringArray docs; | |||
docs.addTokens (parameters, true); | |||
for (int i = 0; i < docs.size(); ++i) | |||
[urls addObject: juceStringToNS (docs[i])]; | |||
ok = [[NSWorkspace sharedWorkspace] openURLs: urls | |||
withAppBundleIdentifier: [[NSBundle bundleWithPath: juceStringToNS (fileName)] bundleIdentifier] | |||
options: 0 | |||
additionalEventParamDescriptor: nil | |||
launchIdentifiers: nil]; | |||
} | |||
else if (file.exists()) | |||
{ | |||
ok = FileHelpers::launchExecutable ("\"" + fileName + "\" " + parameters); | |||
} | |||
if (file.isBundle()) | |||
{ | |||
NSMutableArray* urls = [NSMutableArray array]; | |||
StringArray docs; | |||
docs.addTokens (parameters, true); | |||
for (int i = 0; i < docs.size(); ++i) | |||
[urls addObject: juceStringToNS (docs[i])]; | |||
ok = [[NSWorkspace sharedWorkspace] openURLs: urls | |||
withAppBundleIdentifier: [[NSBundle bundleWithPath: juceStringToNS (fileName)] bundleIdentifier] | |||
options: 0 | |||
additionalEventParamDescriptor: nil | |||
launchIdentifiers: nil]; | |||
} | |||
else if (file.exists()) | |||
{ | |||
ok = FileHelpers::launchExecutable ("\"" + fileName + "\" " + parameters); | |||
} | |||
return ok; | |||
return ok; | |||
} | |||
#endif | |||
} | |||
@@ -440,15 +443,16 @@ void File::revealToUser() const | |||
OSType File::getMacOSType() const | |||
{ | |||
JUCE_AUTORELEASEPOOL | |||
{ | |||
#if JUCE_IOS || (defined (MAC_OS_X_VERSION_10_5) && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5) | |||
NSDictionary* fileDict = [[NSFileManager defaultManager] attributesOfItemAtPath: juceStringToNS (getFullPathName()) error: nil]; | |||
#else | |||
// (the cast here avoids a deprecation warning) | |||
NSDictionary* fileDict = [((id) [NSFileManager defaultManager]) fileAttributesAtPath: juceStringToNS (getFullPathName()) traverseLink: NO]; | |||
#endif | |||
#if JUCE_IOS || (defined (MAC_OS_X_VERSION_10_5) && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5) | |||
NSDictionary* fileDict = [[NSFileManager defaultManager] attributesOfItemAtPath: juceStringToNS (getFullPathName()) error: nil]; | |||
#else | |||
// (the cast here avoids a deprecation warning) | |||
NSDictionary* fileDict = [((id) [NSFileManager defaultManager]) fileAttributesAtPath: juceStringToNS (getFullPathName()) traverseLink: NO]; | |||
#endif | |||
return [fileDict fileHFSTypeCode]; | |||
return [fileDict fileHFSTypeCode]; | |||
} | |||
} | |||
bool File::isBundle() const | |||
@@ -457,7 +461,9 @@ bool File::isBundle() const | |||
return false; // xxx can't find a sensible way to do this without trying to open the bundle.. | |||
#else | |||
JUCE_AUTORELEASEPOOL | |||
return [[NSWorkspace sharedWorkspace] isFilePackageAtPath: juceStringToNS (getFullPathName())]; | |||
{ | |||
return [[NSWorkspace sharedWorkspace] isFilePackageAtPath: juceStringToNS (getFullPathName())]; | |||
} | |||
#endif | |||
} | |||
@@ -61,39 +61,40 @@ bool Process::openEmailWithAttachments (const String& targetEmailAddress, | |||
return false; | |||
#else | |||
JUCE_AUTORELEASEPOOL | |||
String script; | |||
script << "tell application \"Mail\"\r\n" | |||
"set newMessage to make new outgoing message with properties {subject:\"" | |||
<< emailSubject.replace ("\"", "\\\"") | |||
<< "\", content:\"" | |||
<< bodyText.replace ("\"", "\\\"") | |||
<< "\" & return & return}\r\n" | |||
"tell newMessage\r\n" | |||
"set visible to true\r\n" | |||
"set sender to \"sdfsdfsdfewf\"\r\n" | |||
"make new to recipient at end of to recipients with properties {address:\"" | |||
<< targetEmailAddress | |||
<< "\"}\r\n"; | |||
for (int i = 0; i < filesToAttach.size(); ++i) | |||
{ | |||
script << "tell content\r\n" | |||
"make new attachment with properties {file name:\"" | |||
<< filesToAttach[i].replace ("\"", "\\\"") | |||
<< "\"} at after the last paragraph\r\n" | |||
"end tell\r\n"; | |||
} | |||
String script; | |||
script << "tell application \"Mail\"\r\n" | |||
"set newMessage to make new outgoing message with properties {subject:\"" | |||
<< emailSubject.replace ("\"", "\\\"") | |||
<< "\", content:\"" | |||
<< bodyText.replace ("\"", "\\\"") | |||
<< "\" & return & return}\r\n" | |||
"tell newMessage\r\n" | |||
"set visible to true\r\n" | |||
"set sender to \"sdfsdfsdfewf\"\r\n" | |||
"make new to recipient at end of to recipients with properties {address:\"" | |||
<< targetEmailAddress | |||
<< "\"}\r\n"; | |||
for (int i = 0; i < filesToAttach.size(); ++i) | |||
{ | |||
script << "tell content\r\n" | |||
"make new attachment with properties {file name:\"" | |||
<< filesToAttach[i].replace ("\"", "\\\"") | |||
<< "\"} at after the last paragraph\r\n" | |||
"end tell\r\n"; | |||
} | |||
script << "end tell\r\n" | |||
"end tell\r\n"; | |||
script << "end tell\r\n" | |||
"end tell\r\n"; | |||
NSAppleScript* s = [[NSAppleScript alloc] initWithSource: juceStringToNS (script)]; | |||
NSDictionary* error = nil; | |||
const bool ok = [s executeAndReturnError: &error] != nil; | |||
[s release]; | |||
NSAppleScript* s = [[NSAppleScript alloc] initWithSource: juceStringToNS (script)]; | |||
NSDictionary* error = nil; | |||
const bool ok = [s executeAndReturnError: &error] != nil; | |||
[s release]; | |||
return ok; | |||
return ok; | |||
} | |||
#endif | |||
} | |||
@@ -229,7 +230,9 @@ public: | |||
while (! threadShouldExit()) | |||
{ | |||
JUCE_AUTORELEASEPOOL | |||
[[NSRunLoop currentRunLoop] runUntilDate: [NSDate dateWithTimeIntervalSinceNow: 0.01]]; | |||
{ | |||
[[NSRunLoop currentRunLoop] runUntilDate: [NSDate dateWithTimeIntervalSinceNow: 0.01]]; | |||
} | |||
} | |||
} | |||
@@ -305,16 +308,18 @@ public: | |||
finished (false), isPost (isPost_), timeOutMs (timeOutMs_) | |||
{ | |||
JUCE_AUTORELEASEPOOL | |||
createConnection (progressCallback, progressCallbackContext); | |||
if (responseHeaders != nullptr && connection != nullptr && connection->headers != nil) | |||
{ | |||
NSEnumerator* enumerator = [connection->headers keyEnumerator]; | |||
NSString* key; | |||
createConnection (progressCallback, progressCallbackContext); | |||
if (responseHeaders != nullptr && connection != nullptr && connection->headers != nil) | |||
{ | |||
NSEnumerator* enumerator = [connection->headers keyEnumerator]; | |||
NSString* key; | |||
while ((key = [enumerator nextObject]) != nil) | |||
responseHeaders->set (nsStringToJuce (key), | |||
nsStringToJuce ((NSString*) [connection->headers objectForKey: key])); | |||
while ((key = [enumerator nextObject]) != nil) | |||
responseHeaders->set (nsStringToJuce (key), | |||
nsStringToJuce ((NSString*) [connection->headers objectForKey: key])); | |||
} | |||
} | |||
} | |||
@@ -332,14 +337,15 @@ public: | |||
return 0; | |||
JUCE_AUTORELEASEPOOL | |||
{ | |||
const int bytesRead = connection->read (static_cast <char*> (buffer), bytesToRead); | |||
position += bytesRead; | |||
const int bytesRead = connection->read (static_cast <char*> (buffer), bytesToRead); | |||
position += bytesRead; | |||
if (bytesRead == 0) | |||
finished = true; | |||
if (bytesRead == 0) | |||
finished = true; | |||
return bytesRead; | |||
return bytesRead; | |||
} | |||
} | |||
bool setPosition (int64 wantedPos) | |||
@@ -46,7 +46,9 @@ String String::convertToPrecomposedUnicode() const | |||
{ | |||
#if JUCE_IOS | |||
JUCE_AUTORELEASEPOOL | |||
return nsStringToJuce ([juceStringToNS (*this) precomposedStringWithCanonicalMapping]); | |||
{ | |||
return nsStringToJuce ([juceStringToNS (*this) precomposedStringWithCanonicalMapping]); | |||
} | |||
#else | |||
UnicodeMapping map; | |||
@@ -110,10 +110,12 @@ static RLimitInitialiser rLimitInitialiser; | |||
static String getOSXVersion() | |||
{ | |||
JUCE_AUTORELEASEPOOL | |||
NSDictionary* dict = [NSDictionary dictionaryWithContentsOfFile: | |||
nsStringLiteral ("/System/Library/CoreServices/SystemVersion.plist")]; | |||
{ | |||
NSDictionary* dict = [NSDictionary dictionaryWithContentsOfFile: | |||
nsStringLiteral ("/System/Library/CoreServices/SystemVersion.plist")]; | |||
return nsStringToJuce ([dict objectForKey: nsStringLiteral ("ProductVersion")]); | |||
return nsStringToJuce ([dict objectForKey: nsStringLiteral ("ProductVersion")]); | |||
} | |||
} | |||
#endif | |||
@@ -824,18 +824,20 @@ extern "C" void* threadEntryProc (void*); | |||
extern "C" void* threadEntryProc (void* userData) | |||
{ | |||
JUCE_AUTORELEASEPOOL | |||
#if JUCE_ANDROID | |||
struct AndroidThreadScope | |||
{ | |||
AndroidThreadScope() { threadLocalJNIEnvHolder.attach(); } | |||
~AndroidThreadScope() { threadLocalJNIEnvHolder.detach(); } | |||
}; | |||
#if JUCE_ANDROID | |||
struct AndroidThreadScope | |||
{ | |||
AndroidThreadScope() { threadLocalJNIEnvHolder.attach(); } | |||
~AndroidThreadScope() { threadLocalJNIEnvHolder.detach(); } | |||
}; | |||
const AndroidThreadScope androidEnv; | |||
#endif | |||
const AndroidThreadScope androidEnv; | |||
#endif | |||
juce_threadEntryPoint (userData); | |||
} | |||
juce_threadEntryPoint (userData); | |||
return nullptr; | |||
} | |||
@@ -874,7 +876,9 @@ void Thread::setCurrentThreadName (const String& name) | |||
{ | |||
#if JUCE_IOS || (JUCE_MAC && defined (MAC_OS_X_VERSION_10_5) && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5) | |||
JUCE_AUTORELEASEPOOL | |||
[[NSThread currentThread] setName: juceStringToNS (name)]; | |||
{ | |||
[[NSThread currentThread] setName: juceStringToNS (name)]; | |||
} | |||
#elif JUCE_LINUX | |||
prctl (PR_SET_NAME, name.toUTF8().getAddress(), 0, 0, 0); | |||
#endif | |||
@@ -304,6 +304,8 @@ namespace juce | |||
#if __has_feature (cxx_rvalue_references) | |||
#define JUCE_COMPILER_SUPPORTS_MOVE_SEMANTICS 1 | |||
#endif | |||
#define JUCE_COMPILER_SUPPORTS_ARC 1 | |||
#endif | |||
#if defined (_MSC_VER) && _MSC_VER >= 1600 | |||
@@ -42,14 +42,15 @@ JUCEApplicationBase::~JUCEApplicationBase() | |||
void JUCEApplicationBase::appWillTerminateByForce() | |||
{ | |||
JUCE_AUTORELEASEPOOL | |||
{ | |||
const ScopedPointer<JUCEApplicationBase> app (appInstance); | |||
{ | |||
const ScopedPointer<JUCEApplicationBase> app (appInstance); | |||
if (app != nullptr) | |||
app->shutdownApp(); | |||
} | |||
if (app != nullptr) | |||
app->shutdownApp(); | |||
} | |||
DeletedAtShutdown::deleteAll(); | |||
MessageManager::deleteInstance(); | |||
DeletedAtShutdown::deleteAll(); | |||
MessageManager::deleteInstance(); | |||
} | |||
} |
@@ -326,13 +326,17 @@ JUCE_API void JUCE_CALLTYPE initialiseJuce_GUI(); | |||
JUCE_API void JUCE_CALLTYPE initialiseJuce_GUI() | |||
{ | |||
JUCE_AUTORELEASEPOOL | |||
MessageManager::getInstance(); | |||
{ | |||
MessageManager::getInstance(); | |||
} | |||
} | |||
JUCE_API void JUCE_CALLTYPE shutdownJuce_GUI(); | |||
JUCE_API void JUCE_CALLTYPE shutdownJuce_GUI() | |||
{ | |||
JUCE_AUTORELEASEPOOL | |||
DeletedAtShutdown::deleteAll(); | |||
MessageManager::deleteInstance(); | |||
{ | |||
DeletedAtShutdown::deleteAll(); | |||
MessageManager::deleteInstance(); | |||
} | |||
} |
@@ -38,23 +38,26 @@ void MessageManager::stopDispatchLoop() | |||
bool MessageManager::runDispatchLoopUntil (int millisecondsToRunFor) | |||
{ | |||
JUCE_AUTORELEASEPOOL | |||
jassert (isThisTheMessageThread()); // must only be called by the message thread | |||
{ | |||
jassert (isThisTheMessageThread()); // must only be called by the message thread | |||
uint32 endTime = Time::getMillisecondCounter() + millisecondsToRunFor; | |||
NSDate* endDate = [NSDate dateWithTimeIntervalSinceNow: millisecondsToRunFor * 0.001]; | |||
uint32 endTime = Time::getMillisecondCounter() + millisecondsToRunFor; | |||
NSDate* endDate = [NSDate dateWithTimeIntervalSinceNow: millisecondsToRunFor * 0.001]; | |||
while (! quitMessagePosted) | |||
{ | |||
JUCE_AUTORELEASEPOOL | |||
while (! quitMessagePosted) | |||
{ | |||
JUCE_AUTORELEASEPOOL | |||
{ | |||
[[NSRunLoop currentRunLoop] runMode: NSDefaultRunLoopMode | |||
beforeDate: endDate]; | |||
[[NSRunLoop currentRunLoop] runMode: NSDefaultRunLoopMode | |||
beforeDate: endDate]; | |||
if (millisecondsToRunFor >= 0 && Time::getMillisecondCounter() >= endTime) | |||
break; | |||
} | |||
} | |||
if (millisecondsToRunFor >= 0 && Time::getMillisecondCounter() >= endTime) | |||
break; | |||
return ! quitMessagePosted; | |||
} | |||
return ! quitMessagePosted; | |||
} | |||
//============================================================================== | |||
@@ -208,31 +208,32 @@ void MessageManager::runDispatchLoop() | |||
if (! quitMessagePosted) // check that the quit message wasn't already posted.. | |||
{ | |||
JUCE_AUTORELEASEPOOL | |||
// must only be called by the message thread! | |||
jassert (isThisTheMessageThread()); | |||
#if JUCE_PROJUCER_LIVE_BUILD | |||
runDispatchLoopUntil (std::numeric_limits<int>::max()); | |||
#else | |||
#if JUCE_CATCH_UNHANDLED_EXCEPTIONS | |||
@try | |||
{ | |||
// must only be called by the message thread! | |||
jassert (isThisTheMessageThread()); | |||
#if JUCE_PROJUCER_LIVE_BUILD | |||
runDispatchLoopUntil (std::numeric_limits<int>::max()); | |||
#else | |||
#if JUCE_CATCH_UNHANDLED_EXCEPTIONS | |||
@try | |||
{ | |||
[NSApp run]; | |||
} | |||
@catch (NSException* e) | |||
{ | |||
// An AppKit exception will kill the app, but at least this provides a chance to log it., | |||
std::runtime_error ex (std::string ("NSException: ") + [[e name] UTF8String] + ", Reason:" + [[e reason] UTF8String]); | |||
JUCEApplication::sendUnhandledException (&ex, __FILE__, __LINE__); | |||
} | |||
@finally | |||
{ | |||
} | |||
#else | |||
[NSApp run]; | |||
#endif | |||
#endif | |||
} | |||
@catch (NSException* e) | |||
{ | |||
// An AppKit exception will kill the app, but at least this provides a chance to log it., | |||
std::runtime_error ex (std::string ("NSException: ") + [[e name] UTF8String] + ", Reason:" + [[e reason] UTF8String]); | |||
JUCEApplication::sendUnhandledException (&ex, __FILE__, __LINE__); | |||
} | |||
@finally | |||
{ | |||
} | |||
#else | |||
[NSApp run]; | |||
#endif | |||
#endif | |||
} | |||
} | |||
@@ -257,19 +258,20 @@ bool MessageManager::runDispatchLoopUntil (int millisecondsToRunFor) | |||
while (! quitMessagePosted) | |||
{ | |||
JUCE_AUTORELEASEPOOL | |||
{ | |||
CFRunLoopRunInMode (kCFRunLoopDefaultMode, 0.001, true); | |||
CFRunLoopRunInMode (kCFRunLoopDefaultMode, 0.001, true); | |||
NSEvent* e = [NSApp nextEventMatchingMask: NSAnyEventMask | |||
untilDate: [NSDate dateWithTimeIntervalSinceNow: 0.001] | |||
inMode: NSDefaultRunLoopMode | |||
dequeue: YES]; | |||
NSEvent* e = [NSApp nextEventMatchingMask: NSAnyEventMask | |||
untilDate: [NSDate dateWithTimeIntervalSinceNow: 0.001] | |||
inMode: NSDefaultRunLoopMode | |||
dequeue: YES]; | |||
if (e != nil && (isEventBlockedByModalComps == nullptr || ! (*isEventBlockedByModalComps) (e))) | |||
[NSApp sendEvent: e]; | |||
if (e != nil && (isEventBlockedByModalComps == nullptr || ! (*isEventBlockedByModalComps) (e))) | |||
[NSApp sendEvent: e]; | |||
if (Time::getMillisecondCounter() >= endTime) | |||
break; | |||
if (Time::getMillisecondCounter() >= endTime) | |||
break; | |||
} | |||
} | |||
return ! quitMessagePosted; | |||
@@ -281,7 +283,9 @@ void initialiseNSApplication(); | |||
void initialiseNSApplication() | |||
{ | |||
JUCE_AUTORELEASEPOOL | |||
[NSApplication sharedApplication]; | |||
{ | |||
[NSApplication sharedApplication]; | |||
} | |||
} | |||
static AppDelegate* appDelegate = nullptr; | |||
@@ -75,12 +75,13 @@ private: | |||
return false; | |||
JUCE_AUTORELEASEPOOL | |||
JUCE_TRY | |||
{ | |||
nextMessage->messageCallback(); | |||
JUCE_TRY | |||
{ | |||
nextMessage->messageCallback(); | |||
} | |||
JUCE_CATCH_EXCEPTION | |||
} | |||
JUCE_CATCH_EXCEPTION | |||
return true; | |||
} | |||
@@ -787,51 +787,55 @@ Image juce_loadWithCoreImage (InputStream& input) | |||
MemoryBlock data; | |||
input.readIntoMemoryBlock (data, -1); | |||
#if JUCE_IOS | |||
#if JUCE_IOS | |||
JUCE_AUTORELEASEPOOL | |||
if (UIImage* uiImage = [UIImage imageWithData: [NSData dataWithBytesNoCopy: data.getData() | |||
length: data.getSize() | |||
freeWhenDone: NO]]) | |||
#endif | |||
{ | |||
CGImageRef loadedImage = uiImage.CGImage; | |||
#else | |||
CGDataProviderRef provider = CGDataProviderCreateWithData (0, data.getData(), data.getSize(), 0); | |||
CGImageSourceRef imageSource = CGImageSourceCreateWithDataProvider (provider, 0); | |||
CGDataProviderRelease (provider); | |||
#if JUCE_IOS | |||
if (UIImage* uiImage = [UIImage imageWithData: [NSData dataWithBytesNoCopy: data.getData() | |||
length: data.getSize() | |||
freeWhenDone: NO]]) | |||
{ | |||
CGImageRef loadedImage = uiImage.CGImage; | |||
if (imageSource != 0) | |||
{ | |||
CGImageRef loadedImage = CGImageSourceCreateImageAtIndex (imageSource, 0, 0); | |||
CFRelease (imageSource); | |||
#endif | |||
#else | |||
CGDataProviderRef provider = CGDataProviderCreateWithData (0, data.getData(), data.getSize(), 0); | |||
CGImageSourceRef imageSource = CGImageSourceCreateWithDataProvider (provider, 0); | |||
CGDataProviderRelease (provider); | |||
if (loadedImage != 0) | |||
if (imageSource != 0) | |||
{ | |||
CGImageAlphaInfo alphaInfo = CGImageGetAlphaInfo (loadedImage); | |||
const bool hasAlphaChan = (alphaInfo != kCGImageAlphaNone | |||
&& alphaInfo != kCGImageAlphaNoneSkipLast | |||
&& alphaInfo != kCGImageAlphaNoneSkipFirst); | |||
Image image (NativeImageType().create (Image::ARGB, // (CoreImage doesn't work with 24-bit images) | |||
(int) CGImageGetWidth (loadedImage), | |||
(int) CGImageGetHeight (loadedImage), | |||
hasAlphaChan)); | |||
CoreGraphicsImage* const cgImage = dynamic_cast<CoreGraphicsImage*> (image.getPixelData()); | |||
jassert (cgImage != nullptr); // if USE_COREGRAPHICS_RENDERING is set, the CoreGraphicsImage class should have been used. | |||
CGContextDrawImage (cgImage->context, convertToCGRect (image.getBounds()), loadedImage); | |||
CGContextFlush (cgImage->context); | |||
#if ! JUCE_IOS | |||
CFRelease (loadedImage); | |||
#endif | |||
// Because it's impossible to create a truly 24-bit CG image, this flag allows a user | |||
// to find out whether the file they just loaded the image from had an alpha channel or not. | |||
image.getProperties()->set ("originalImageHadAlpha", hasAlphaChan); | |||
return image; | |||
CGImageRef loadedImage = CGImageSourceCreateImageAtIndex (imageSource, 0, 0); | |||
CFRelease (imageSource); | |||
#endif | |||
if (loadedImage != 0) | |||
{ | |||
CGImageAlphaInfo alphaInfo = CGImageGetAlphaInfo (loadedImage); | |||
const bool hasAlphaChan = (alphaInfo != kCGImageAlphaNone | |||
&& alphaInfo != kCGImageAlphaNoneSkipLast | |||
&& alphaInfo != kCGImageAlphaNoneSkipFirst); | |||
Image image (NativeImageType().create (Image::ARGB, // (CoreImage doesn't work with 24-bit images) | |||
(int) CGImageGetWidth (loadedImage), | |||
(int) CGImageGetHeight (loadedImage), | |||
hasAlphaChan)); | |||
CoreGraphicsImage* const cgImage = dynamic_cast<CoreGraphicsImage*> (image.getPixelData()); | |||
jassert (cgImage != nullptr); // if USE_COREGRAPHICS_RENDERING is set, the CoreGraphicsImage class should have been used. | |||
CGContextDrawImage (cgImage->context, convertToCGRect (image.getBounds()), loadedImage); | |||
CGContextFlush (cgImage->context); | |||
#if ! JUCE_IOS | |||
CFRelease (loadedImage); | |||
#endif | |||
// Because it's impossible to create a truly 24-bit CG image, this flag allows a user | |||
// to find out whether the file they just loaded the image from had an alpha channel or not. | |||
image.getProperties()->set ("originalImageHadAlpha", hasAlphaChan); | |||
return image; | |||
} | |||
} | |||
} | |||
@@ -713,44 +713,46 @@ public: | |||
: Typeface (font.getTypefaceName(), font.getTypefaceStyle()) | |||
{ | |||
JUCE_AUTORELEASEPOOL | |||
renderingTransform = CGAffineTransformIdentity; | |||
{ | |||
renderingTransform = CGAffineTransformIdentity; | |||
NSDictionary* nsDict = [NSDictionary dictionaryWithObjectsAndKeys: | |||
juceStringToNS (name), NSFontFamilyAttribute, | |||
juceStringToNS (style), NSFontFaceAttribute, nil]; | |||
NSDictionary* nsDict = [NSDictionary dictionaryWithObjectsAndKeys: | |||
juceStringToNS (name), NSFontFamilyAttribute, | |||
juceStringToNS (style), NSFontFaceAttribute, nil]; | |||
NSFontDescriptor* nsFontDesc = [NSFontDescriptor fontDescriptorWithFontAttributes: nsDict]; | |||
nsFont = [NSFont fontWithDescriptor: nsFontDesc size: referenceFontSize]; | |||
NSFontDescriptor* nsFontDesc = [NSFontDescriptor fontDescriptorWithFontAttributes: nsDict]; | |||
nsFont = [NSFont fontWithDescriptor: nsFontDesc size: referenceFontSize]; | |||
[nsFont retain]; | |||
[nsFont retain]; | |||
#if SUPPORT_ONLY_10_4_FONTS | |||
initWithATSFont(); | |||
#else | |||
#if SUPPORT_10_4_FONTS | |||
if (NEW_CGFONT_FUNCTIONS_UNAVAILABLE) | |||
{ | |||
#if SUPPORT_ONLY_10_4_FONTS | |||
initWithATSFont(); | |||
} | |||
else | |||
#endif | |||
{ | |||
fontRef = CGFontCreateWithFontName ((CFStringRef) [nsFont fontName]); | |||
#else | |||
#if SUPPORT_10_4_FONTS | |||
if (NEW_CGFONT_FUNCTIONS_UNAVAILABLE) | |||
{ | |||
initWithATSFont(); | |||
} | |||
else | |||
#endif | |||
{ | |||
fontRef = CGFontCreateWithFontName ((CFStringRef) [nsFont fontName]); | |||
const float absAscent = std::abs ((float) CGFontGetAscent (fontRef)); | |||
const float totalHeight = absAscent + std::abs ((float) CGFontGetDescent (fontRef)); | |||
const float absAscent = std::abs ((float) CGFontGetAscent (fontRef)); | |||
const float totalHeight = absAscent + std::abs ((float) CGFontGetDescent (fontRef)); | |||
ascent = absAscent / totalHeight; | |||
unitsToHeightScaleFactor = 1.0f / totalHeight; | |||
ascent = absAscent / totalHeight; | |||
unitsToHeightScaleFactor = 1.0f / totalHeight; | |||
const float nsFontAscent = std::abs ([nsFont ascender]); | |||
const float nsFontDescent = std::abs ([nsFont descender]); | |||
const float nsFontAscent = std::abs ([nsFont ascender]); | |||
const float nsFontDescent = std::abs ([nsFont descender]); | |||
fontHeightToPointsFactor = referenceFontSize / (nsFontAscent + nsFontDescent); | |||
} | |||
#endif | |||
fontHeightToPointsFactor = referenceFontSize / (nsFontAscent + nsFontDescent); | |||
} | |||
#endif | |||
pathTransform = AffineTransform::identity.scale (unitsToHeightScaleFactor); | |||
pathTransform = AffineTransform::identity.scale (unitsToHeightScaleFactor); | |||
} | |||
} | |||
~OSXTypeface() | |||
@@ -910,28 +912,29 @@ public: | |||
jassert (path.isEmpty()); | |||
JUCE_AUTORELEASEPOOL | |||
NSBezierPath* bez = [NSBezierPath bezierPath]; | |||
[bez moveToPoint: NSMakePoint (0, 0)]; | |||
[bez appendBezierPathWithGlyph: (NSGlyph) glyphNumber | |||
inFont: nsFont]; | |||
for (int i = 0; i < [bez elementCount]; ++i) | |||
{ | |||
NSPoint p[3]; | |||
switch ([bez elementAtIndex: i associatedPoints: p]) | |||
NSBezierPath* bez = [NSBezierPath bezierPath]; | |||
[bez moveToPoint: NSMakePoint (0, 0)]; | |||
[bez appendBezierPathWithGlyph: (NSGlyph) glyphNumber | |||
inFont: nsFont]; | |||
for (int i = 0; i < [bez elementCount]; ++i) | |||
{ | |||
case NSMoveToBezierPathElement: path.startNewSubPath ((float) p[0].x, (float) -p[0].y); break; | |||
case NSLineToBezierPathElement: path.lineTo ((float) p[0].x, (float) -p[0].y); break; | |||
case NSCurveToBezierPathElement: path.cubicTo ((float) p[0].x, (float) -p[0].y, | |||
(float) p[1].x, (float) -p[1].y, | |||
(float) p[2].x, (float) -p[2].y); break; | |||
case NSClosePathBezierPathElement: path.closeSubPath(); break; | |||
default: jassertfalse; break; | |||
NSPoint p[3]; | |||
switch ([bez elementAtIndex: i associatedPoints: p]) | |||
{ | |||
case NSMoveToBezierPathElement: path.startNewSubPath ((float) p[0].x, (float) -p[0].y); break; | |||
case NSLineToBezierPathElement: path.lineTo ((float) p[0].x, (float) -p[0].y); break; | |||
case NSCurveToBezierPathElement: path.cubicTo ((float) p[0].x, (float) -p[0].y, | |||
(float) p[1].x, (float) -p[1].y, | |||
(float) p[2].x, (float) -p[2].y); break; | |||
case NSClosePathBezierPathElement: path.closeSubPath(); break; | |||
default: jassertfalse; break; | |||
} | |||
} | |||
} | |||
path.applyTransform (pathTransform); | |||
path.applyTransform (pathTransform); | |||
} | |||
return true; | |||
#endif | |||
} | |||
@@ -1084,18 +1087,21 @@ private: | |||
StringArray Font::findAllTypefaceNames() | |||
{ | |||
StringArray names; | |||
JUCE_AUTORELEASEPOOL | |||
{ | |||
#if JUCE_IOS | |||
NSArray* fonts = [UIFont familyNames]; | |||
#else | |||
NSArray* fonts = [[NSFontManager sharedFontManager] availableFontFamilies]; | |||
#endif | |||
#if JUCE_IOS | |||
NSArray* fonts = [UIFont familyNames]; | |||
#else | |||
NSArray* fonts = [[NSFontManager sharedFontManager] availableFontFamilies]; | |||
#endif | |||
for (unsigned int i = 0; i < [fonts count]; ++i) | |||
names.add (nsStringToJuce ((NSString*) [fonts objectAtIndex: i])); | |||
for (unsigned int i = 0; i < [fonts count]; ++i) | |||
names.add (nsStringToJuce ((NSString*) [fonts objectAtIndex: i])); | |||
names.sort (true); | |||
} | |||
names.sort (true); | |||
return names; | |||
} | |||
@@ -1105,14 +1111,16 @@ StringArray Font::findAllTypefaceStyles (const String& family) | |||
return findAllTypefaceStyles (FontStyleHelpers::getConcreteFamilyNameFromPlaceholder (family)); | |||
StringArray results; | |||
JUCE_AUTORELEASEPOOL | |||
NSArray* styles = [[NSFontManager sharedFontManager] availableMembersOfFontFamily: juceStringToNS (family)]; | |||
for (unsigned int i = 0; i < [styles count]; ++i) | |||
JUCE_AUTORELEASEPOOL | |||
{ | |||
NSArray* style = [styles objectAtIndex: i]; | |||
results.add (nsStringToJuce ((NSString*) [style objectAtIndex: 1])); | |||
NSArray* styles = [[NSFontManager sharedFontManager] availableMembersOfFontFamily: juceStringToNS (family)]; | |||
for (unsigned int i = 0; i < [styles count]; ++i) | |||
{ | |||
NSArray* style = [styles objectAtIndex: i]; | |||
results.add (nsStringToJuce ((NSString*) [style objectAtIndex: 1])); | |||
} | |||
} | |||
return results; | |||
@@ -283,19 +283,20 @@ String JUCEApplication::getCommandLineParameters() | |||
int JUCEApplication::main (int argc, const char* argv[]) | |||
{ | |||
JUCE_AUTORELEASEPOOL | |||
{ | |||
juce_argc = argc; | |||
juce_argv = argv; | |||
juce_argc = argc; | |||
juce_argv = argv; | |||
#if JUCE_MAC | |||
initialiseNSApplication(); | |||
#endif | |||
#if JUCE_MAC | |||
initialiseNSApplication(); | |||
#endif | |||
#if JUCE_IOS | |||
return juce_iOSMain (argc, argv); | |||
#else | |||
return JUCEApplication::main(); | |||
#endif | |||
#if JUCE_IOS | |||
return juce_iOSMain (argc, argv); | |||
#else | |||
return JUCEApplication::main(); | |||
#endif | |||
} | |||
} | |||
#endif | |||
@@ -131,10 +131,12 @@ public: | |||
int getResult() | |||
{ | |||
jassert (callback == nullptr); | |||
JUCE_AUTORELEASEPOOL | |||
while (! alert.hidden && alert.superview != nil) | |||
[[NSRunLoop mainRunLoop] runUntilDate: [NSDate dateWithTimeIntervalSinceNow: 0.01]]; | |||
JUCE_AUTORELEASEPOOL | |||
{ | |||
while (! alert.hidden && alert.superview != nil) | |||
[[NSRunLoop mainRunLoop] runUntilDate: [NSDate dateWithTimeIntervalSinceNow: 0.01]]; | |||
} | |||
return result; | |||
} | |||
@@ -181,8 +183,10 @@ void JUCE_CALLTYPE NativeMessageBox::showMessageBox (AlertWindow::AlertIconType | |||
Component* associatedComponent) | |||
{ | |||
JUCE_AUTORELEASEPOOL | |||
iOSMessageBox mb (title, message, @"OK", nil, nil, nullptr, false); | |||
(void) mb.getResult(); | |||
{ | |||
iOSMessageBox mb (title, message, @"OK", nil, nil, nullptr, false); | |||
(void) mb.getResult(); | |||
} | |||
} | |||
void JUCE_CALLTYPE NativeMessageBox::showMessageBoxAsync (AlertWindow::AlertIconType iconType, | |||
@@ -302,18 +306,19 @@ Desktop::DisplayOrientation Desktop::getCurrentOrientation() const | |||
void Desktop::Displays::findDisplays() | |||
{ | |||
JUCE_AUTORELEASEPOOL | |||
{ | |||
UIScreen* s = [UIScreen mainScreen]; | |||
UIScreen* s = [UIScreen mainScreen]; | |||
Display d; | |||
d.userArea = UIViewComponentPeer::realScreenPosToRotated (convertToRectInt ([s applicationFrame])); | |||
d.totalArea = UIViewComponentPeer::realScreenPosToRotated (convertToRectInt ([s bounds])); | |||
d.isMain = true; | |||
Display d; | |||
d.userArea = UIViewComponentPeer::realScreenPosToRotated (convertToRectInt ([s applicationFrame])); | |||
d.totalArea = UIViewComponentPeer::realScreenPosToRotated (convertToRectInt ([s bounds])); | |||
d.isMain = true; | |||
if ([s respondsToSelector: @selector (scale)]) | |||
d.scale = s.scale; | |||
else | |||
d.scale = 1.0; | |||
if ([s respondsToSelector: @selector (scale)]) | |||
d.scale = s.scale; | |||
else | |||
d.scale = 1.0; | |||
displays.add (d); | |||
displays.add (d); | |||
} | |||
} |
@@ -117,83 +117,84 @@ void FileChooser::showPlatformDialog (Array<File>& results, | |||
FilePreviewComponent* /*extraInfoComponent*/) | |||
{ | |||
JUCE_AUTORELEASEPOOL | |||
{ | |||
ScopedPointer<TemporaryMainMenuWithStandardCommands> tempMenu; | |||
if (JUCEApplication::isStandaloneApp()) | |||
tempMenu = new TemporaryMainMenuWithStandardCommands(); | |||
ScopedPointer<TemporaryMainMenuWithStandardCommands> tempMenu; | |||
if (JUCEApplication::isStandaloneApp()) | |||
tempMenu = new TemporaryMainMenuWithStandardCommands(); | |||
StringArray* filters = new StringArray(); | |||
filters->addTokens (filter.replaceCharacters (",:", ";;"), ";", String::empty); | |||
filters->trim(); | |||
filters->removeEmptyStrings(); | |||
StringArray* filters = new StringArray(); | |||
filters->addTokens (filter.replaceCharacters (",:", ";;"), ";", String::empty); | |||
filters->trim(); | |||
filters->removeEmptyStrings(); | |||
#if defined (MAC_OS_X_VERSION_10_6) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 | |||
typedef NSObject<NSOpenSavePanelDelegate> DelegateType; | |||
#else | |||
typedef NSObject DelegateType; | |||
#endif | |||
#if defined (MAC_OS_X_VERSION_10_6) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 | |||
typedef NSObject<NSOpenSavePanelDelegate> DelegateType; | |||
#else | |||
typedef NSObject DelegateType; | |||
#endif | |||
static FileChooserDelegateClass cls; | |||
DelegateType* delegate = (DelegateType*) [[cls.createInstance() init] autorelease]; | |||
FileChooserDelegateClass::setFilters (delegate, filters); | |||
static FileChooserDelegateClass cls; | |||
DelegateType* delegate = (DelegateType*) [[cls.createInstance() init] autorelease]; | |||
FileChooserDelegateClass::setFilters (delegate, filters); | |||
NSSavePanel* panel = isSaveDialogue ? [NSSavePanel savePanel] | |||
: [NSOpenPanel openPanel]; | |||
NSSavePanel* panel = isSaveDialogue ? [NSSavePanel savePanel] | |||
: [NSOpenPanel openPanel]; | |||
[panel setTitle: juceStringToNS (title)]; | |||
[panel setAllowedFileTypes: createAllowedTypesArray (*filters)]; | |||
[panel setTitle: juceStringToNS (title)]; | |||
[panel setAllowedFileTypes: createAllowedTypesArray (*filters)]; | |||
if (! isSaveDialogue) | |||
{ | |||
NSOpenPanel* openPanel = (NSOpenPanel*) panel; | |||
[openPanel setCanChooseDirectories: selectsDirectory]; | |||
[openPanel setCanChooseFiles: selectsFiles]; | |||
[openPanel setAllowsMultipleSelection: selectMultipleFiles]; | |||
[openPanel setResolvesAliases: YES]; | |||
} | |||
if (! isSaveDialogue) | |||
{ | |||
NSOpenPanel* openPanel = (NSOpenPanel*) panel; | |||
[openPanel setCanChooseDirectories: selectsDirectory]; | |||
[openPanel setCanChooseFiles: selectsFiles]; | |||
[openPanel setAllowsMultipleSelection: selectMultipleFiles]; | |||
[openPanel setResolvesAliases: YES]; | |||
} | |||
[panel setDelegate: delegate]; | |||
[panel setDelegate: delegate]; | |||
if (isSaveDialogue || selectsDirectory) | |||
[panel setCanCreateDirectories: YES]; | |||
if (isSaveDialogue || selectsDirectory) | |||
[panel setCanCreateDirectories: YES]; | |||
String directory, filename; | |||
String directory, filename; | |||
if (currentFileOrDirectory.isDirectory()) | |||
{ | |||
directory = currentFileOrDirectory.getFullPathName(); | |||
} | |||
else | |||
{ | |||
directory = currentFileOrDirectory.getParentDirectory().getFullPathName(); | |||
filename = currentFileOrDirectory.getFileName(); | |||
} | |||
#if defined (MAC_OS_X_VERSION_10_6) && (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_6) | |||
[panel setDirectoryURL: [NSURL fileURLWithPath: juceStringToNS (directory)]]; | |||
[panel setNameFieldStringValue: juceStringToNS (filename)]; | |||
if ([panel runModal] == NSOKButton) | |||
#else | |||
if ([panel runModalForDirectory: juceStringToNS (directory) | |||
file: juceStringToNS (filename)] == NSOKButton) | |||
#endif | |||
{ | |||
if (isSaveDialogue) | |||
if (currentFileOrDirectory.isDirectory()) | |||
{ | |||
results.add (File (nsStringToJuce ([[panel URL] path]))); | |||
directory = currentFileOrDirectory.getFullPathName(); | |||
} | |||
else | |||
{ | |||
NSOpenPanel* openPanel = (NSOpenPanel*) panel; | |||
NSArray* urls = [openPanel URLs]; | |||
directory = currentFileOrDirectory.getParentDirectory().getFullPathName(); | |||
filename = currentFileOrDirectory.getFileName(); | |||
} | |||
#if defined (MAC_OS_X_VERSION_10_6) && (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_6) | |||
[panel setDirectoryURL: [NSURL fileURLWithPath: juceStringToNS (directory)]]; | |||
[panel setNameFieldStringValue: juceStringToNS (filename)]; | |||
for (unsigned int i = 0; i < [urls count]; ++i) | |||
results.add (File (nsStringToJuce ([[urls objectAtIndex: i] path]))); | |||
if ([panel runModal] == NSOKButton) | |||
#else | |||
if ([panel runModalForDirectory: juceStringToNS (directory) | |||
file: juceStringToNS (filename)] == NSOKButton) | |||
#endif | |||
{ | |||
if (isSaveDialogue) | |||
{ | |||
results.add (File (nsStringToJuce ([[panel URL] path]))); | |||
} | |||
else | |||
{ | |||
NSOpenPanel* openPanel = (NSOpenPanel*) panel; | |||
NSArray* urls = [openPanel URLs]; | |||
for (unsigned int i = 0; i < [urls count]; ++i) | |||
results.add (File (nsStringToJuce ([[urls objectAtIndex: i] path]))); | |||
} | |||
} | |||
} | |||
[panel setDelegate: nil]; | |||
[panel setDelegate: nil]; | |||
} | |||
} | |||
bool FileChooser::isPlatformDialogAvailable() | |||
@@ -220,8 +221,6 @@ void FileChooser::showPlatformDialog (Array<File>& results, | |||
bool selectMultipleFiles, | |||
FilePreviewComponent* extraInfoComponent) | |||
{ | |||
JUCE_AUTORELEASEPOOL | |||
jassertfalse; //there's no such thing in iOS | |||
} | |||
@@ -658,20 +658,21 @@ namespace MainMenuHelpers | |||
if (JUCEApplication* app = JUCEApplication::getInstance()) | |||
{ | |||
JUCE_AUTORELEASEPOOL | |||
{ | |||
NSMenu* mainMenu = [[NSMenu alloc] initWithTitle: nsStringLiteral ("MainMenu")]; | |||
NSMenuItem* item = [mainMenu addItemWithTitle: nsStringLiteral ("Apple") action: nil keyEquivalent: nsEmptyString()]; | |||
NSMenu* mainMenu = [[NSMenu alloc] initWithTitle: nsStringLiteral ("MainMenu")]; | |||
NSMenuItem* item = [mainMenu addItemWithTitle: nsStringLiteral ("Apple") action: nil keyEquivalent: nsEmptyString()]; | |||
NSMenu* appMenu = [[NSMenu alloc] initWithTitle: nsStringLiteral ("Apple")]; | |||
NSMenu* appMenu = [[NSMenu alloc] initWithTitle: nsStringLiteral ("Apple")]; | |||
[NSApp performSelector: @selector (setAppleMenu:) withObject: appMenu]; | |||
[mainMenu setSubmenu: appMenu forItem: item]; | |||
[NSApp performSelector: @selector (setAppleMenu:) withObject: appMenu]; | |||
[mainMenu setSubmenu: appMenu forItem: item]; | |||
[NSApp setMainMenu: mainMenu]; | |||
MainMenuHelpers::createStandardAppMenu (appMenu, app->getApplicationName(), extraItems); | |||
[NSApp setMainMenu: mainMenu]; | |||
MainMenuHelpers::createStandardAppMenu (appMenu, app->getApplicationName(), extraItems); | |||
[appMenu release]; | |||
[mainMenu release]; | |||
[appMenu release]; | |||
[mainMenu release]; | |||
} | |||
} | |||
} | |||
} | |||
@@ -683,21 +684,22 @@ void MenuBarModel::setMacMainMenu (MenuBarModel* newMenuBarModel, | |||
if (getMacMainMenu() != newMenuBarModel) | |||
{ | |||
JUCE_AUTORELEASEPOOL | |||
if (newMenuBarModel == nullptr) | |||
{ | |||
delete JuceMainMenuHandler::instance; | |||
jassert (JuceMainMenuHandler::instance == nullptr); // should be zeroed in the destructor | |||
jassert (extraAppleMenuItems == nullptr); // you can't specify some extra items without also supplying a model | |||
if (newMenuBarModel == nullptr) | |||
{ | |||
delete JuceMainMenuHandler::instance; | |||
jassert (JuceMainMenuHandler::instance == nullptr); // should be zeroed in the destructor | |||
jassert (extraAppleMenuItems == nullptr); // you can't specify some extra items without also supplying a model | |||
extraAppleMenuItems = nullptr; | |||
} | |||
else | |||
{ | |||
if (JuceMainMenuHandler::instance == nullptr) | |||
JuceMainMenuHandler::instance = new JuceMainMenuHandler(); | |||
extraAppleMenuItems = nullptr; | |||
} | |||
else | |||
{ | |||
if (JuceMainMenuHandler::instance == nullptr) | |||
JuceMainMenuHandler::instance = new JuceMainMenuHandler(); | |||
JuceMainMenuHandler::instance->setMenu (newMenuBarModel, extraAppleMenuItems, recentItemsMenuName); | |||
JuceMainMenuHandler::instance->setMenu (newMenuBarModel, extraAppleMenuItems, recentItemsMenuName); | |||
} | |||
} | |||
} | |||
@@ -31,22 +31,23 @@ namespace MouseCursorHelpers | |||
static NSImage* createNSImage (const Image& image) | |||
{ | |||
JUCE_AUTORELEASEPOOL | |||
{ | |||
NSImage* im = [[NSImage alloc] init]; | |||
[im setSize: NSMakeSize (image.getWidth(), image.getHeight())]; | |||
[im lockFocus]; | |||
NSImage* im = [[NSImage alloc] init]; | |||
[im setSize: NSMakeSize (image.getWidth(), image.getHeight())]; | |||
[im lockFocus]; | |||
CGColorSpaceRef colourSpace = CGColorSpaceCreateDeviceRGB(); | |||
CGImageRef imageRef = juce_createCoreGraphicsImage (image, false, colourSpace, false); | |||
CGColorSpaceRelease (colourSpace); | |||
CGColorSpaceRef colourSpace = CGColorSpaceCreateDeviceRGB(); | |||
CGImageRef imageRef = juce_createCoreGraphicsImage (image, false, colourSpace, false); | |||
CGColorSpaceRelease (colourSpace); | |||
CGContextRef cg = (CGContextRef) [[NSGraphicsContext currentContext] graphicsPort]; | |||
CGContextDrawImage (cg, convertToCGRect (image.getBounds()), imageRef); | |||
CGContextRef cg = (CGContextRef) [[NSGraphicsContext currentContext] graphicsPort]; | |||
CGContextDrawImage (cg, convertToCGRect (image.getBounds()), imageRef); | |||
CGImageRelease (imageRef); | |||
[im unlockFocus]; | |||
CGImageRelease (imageRef); | |||
[im unlockFocus]; | |||
return im; | |||
return im; | |||
} | |||
} | |||
static void* fromWebKitFile (const char* filename, float hx, float hy) | |||
@@ -78,46 +79,48 @@ void* CustomMouseCursorInfo::create() const | |||
void* MouseCursor::createStandardMouseCursor (MouseCursor::StandardCursorType type) | |||
{ | |||
JUCE_AUTORELEASEPOOL | |||
NSCursor* c = nil; | |||
switch (type) | |||
{ | |||
case NormalCursor: | |||
case ParentCursor: c = [NSCursor arrowCursor]; break; | |||
case NoCursor: return CustomMouseCursorInfo (Image (Image::ARGB, 8, 8, true), 0, 0).create(); | |||
case DraggingHandCursor: c = [NSCursor openHandCursor]; break; | |||
case WaitCursor: c = [NSCursor arrowCursor]; break; // avoid this on the mac, let the OS provide the beachball | |||
case IBeamCursor: c = [NSCursor IBeamCursor]; break; | |||
case PointingHandCursor: c = [NSCursor pointingHandCursor]; break; | |||
case LeftRightResizeCursor: c = [NSCursor resizeLeftRightCursor]; break; | |||
case LeftEdgeResizeCursor: c = [NSCursor resizeLeftCursor]; break; | |||
case RightEdgeResizeCursor: c = [NSCursor resizeRightCursor]; break; | |||
case CrosshairCursor: c = [NSCursor crosshairCursor]; break; | |||
case CopyingCursor: return MouseCursorHelpers::fromWebKitFile ("copyCursor.png", 0, 0); | |||
case UpDownResizeCursor: | |||
case TopEdgeResizeCursor: | |||
case BottomEdgeResizeCursor: | |||
return MouseCursorHelpers::fromWebKitFile ("northSouthResizeCursor.png", 0.5f, 0.5f); | |||
case TopLeftCornerResizeCursor: | |||
case BottomRightCornerResizeCursor: | |||
return MouseCursorHelpers::fromWebKitFile ("northWestSouthEastResizeCursor.png", 0.5f, 0.5f); | |||
case TopRightCornerResizeCursor: | |||
case BottomLeftCornerResizeCursor: | |||
return MouseCursorHelpers::fromWebKitFile ("northEastSouthWestResizeCursor.png", 0.5f, 0.5f); | |||
case UpDownLeftRightResizeCursor: | |||
return MouseCursorHelpers::fromWebKitFile ("moveCursor.png", 0.5f, 0.5f); | |||
default: | |||
jassertfalse; | |||
break; | |||
NSCursor* c = nil; | |||
switch (type) | |||
{ | |||
case NormalCursor: | |||
case ParentCursor: c = [NSCursor arrowCursor]; break; | |||
case NoCursor: return CustomMouseCursorInfo (Image (Image::ARGB, 8, 8, true), 0, 0).create(); | |||
case DraggingHandCursor: c = [NSCursor openHandCursor]; break; | |||
case WaitCursor: c = [NSCursor arrowCursor]; break; // avoid this on the mac, let the OS provide the beachball | |||
case IBeamCursor: c = [NSCursor IBeamCursor]; break; | |||
case PointingHandCursor: c = [NSCursor pointingHandCursor]; break; | |||
case LeftRightResizeCursor: c = [NSCursor resizeLeftRightCursor]; break; | |||
case LeftEdgeResizeCursor: c = [NSCursor resizeLeftCursor]; break; | |||
case RightEdgeResizeCursor: c = [NSCursor resizeRightCursor]; break; | |||
case CrosshairCursor: c = [NSCursor crosshairCursor]; break; | |||
case CopyingCursor: return MouseCursorHelpers::fromWebKitFile ("copyCursor.png", 0, 0); | |||
case UpDownResizeCursor: | |||
case TopEdgeResizeCursor: | |||
case BottomEdgeResizeCursor: | |||
return MouseCursorHelpers::fromWebKitFile ("northSouthResizeCursor.png", 0.5f, 0.5f); | |||
case TopLeftCornerResizeCursor: | |||
case BottomRightCornerResizeCursor: | |||
return MouseCursorHelpers::fromWebKitFile ("northWestSouthEastResizeCursor.png", 0.5f, 0.5f); | |||
case TopRightCornerResizeCursor: | |||
case BottomLeftCornerResizeCursor: | |||
return MouseCursorHelpers::fromWebKitFile ("northEastSouthWestResizeCursor.png", 0.5f, 0.5f); | |||
case UpDownLeftRightResizeCursor: | |||
return MouseCursorHelpers::fromWebKitFile ("moveCursor.png", 0.5f, 0.5f); | |||
default: | |||
jassertfalse; | |||
break; | |||
} | |||
[c retain]; | |||
return c; | |||
} | |||
[c retain]; | |||
return c; | |||
} | |||
void MouseCursor::deleteMouseCursor (void* const cursorHandle, const bool /*isStandard*/) | |||
@@ -199,9 +199,10 @@ public: | |||
void setTitle (const String& title) | |||
{ | |||
JUCE_AUTORELEASEPOOL | |||
if (! isSharedWindow) | |||
[window setTitle: juceStringToNS (title)]; | |||
{ | |||
if (! isSharedWindow) | |||
[window setTitle: juceStringToNS (title)]; | |||
} | |||
} | |||
bool setDocumentEditedStatus (bool edited) | |||
@@ -163,35 +163,36 @@ bool DragAndDropContainer::performExternalDragDropOfFiles (const StringArray& fi | |||
} | |||
JUCE_AUTORELEASEPOOL | |||
NSView* view = (NSView*) sourceComp->getWindowHandle(); | |||
if (view == nil) | |||
return false; | |||
NSPasteboard* pboard = [NSPasteboard pasteboardWithName: NSDragPboard]; | |||
[pboard declareTypes: [NSArray arrayWithObject: NSFilenamesPboardType] | |||
owner: nil]; | |||
NSMutableArray* filesArray = [NSMutableArray arrayWithCapacity: 4]; | |||
for (int i = 0; i < files.size(); ++i) | |||
[filesArray addObject: juceStringToNS (files[i])]; | |||
[pboard setPropertyList: filesArray | |||
forType: NSFilenamesPboardType]; | |||
NSPoint dragPosition = [view convertPoint: [[[view window] currentEvent] locationInWindow] | |||
fromView: nil]; | |||
dragPosition.x -= 16; | |||
dragPosition.y -= 16; | |||
[view dragImage: [[NSWorkspace sharedWorkspace] iconForFile: juceStringToNS (files[0])] | |||
at: dragPosition | |||
offset: NSMakeSize (0, 0) | |||
event: [[view window] currentEvent] | |||
pasteboard: pboard | |||
source: view | |||
slideBack: YES]; | |||
{ | |||
NSView* view = (NSView*) sourceComp->getWindowHandle(); | |||
if (view == nil) | |||
return false; | |||
NSPasteboard* pboard = [NSPasteboard pasteboardWithName: NSDragPboard]; | |||
[pboard declareTypes: [NSArray arrayWithObject: NSFilenamesPboardType] | |||
owner: nil]; | |||
NSMutableArray* filesArray = [NSMutableArray arrayWithCapacity: 4]; | |||
for (int i = 0; i < files.size(); ++i) | |||
[filesArray addObject: juceStringToNS (files[i])]; | |||
[pboard setPropertyList: filesArray | |||
forType: NSFilenamesPboardType]; | |||
NSPoint dragPosition = [view convertPoint: [[[view window] currentEvent] locationInWindow] | |||
fromView: nil]; | |||
dragPosition.x -= 16; | |||
dragPosition.y -= 16; | |||
[view dragImage: [[NSWorkspace sharedWorkspace] iconForFile: juceStringToNS (files[0])] | |||
at: dragPosition | |||
offset: NSMakeSize (0, 0) | |||
event: [[view window] currentEvent] | |||
pasteboard: pboard | |||
source: view | |||
slideBack: YES]; | |||
} | |||
return true; | |||
} | |||
@@ -211,8 +212,10 @@ bool Desktop::canUseSemiTransparentWindows() noexcept | |||
Point<int> MouseInputSource::getCurrentMousePosition() | |||
{ | |||
JUCE_AUTORELEASEPOOL | |||
const NSPoint p ([NSEvent mouseLocation]); | |||
return Point<int> (roundToInt (p.x), roundToInt ([[[NSScreen screens] objectAtIndex: 0] frame].size.height - p.y)); | |||
{ | |||
const NSPoint p ([NSEvent mouseLocation]); | |||
return Point<int> (roundToInt (p.x), roundToInt ([[[NSScreen screens] objectAtIndex: 0] frame].size.height - p.y)); | |||
} | |||
} | |||
void Desktop::setMousePosition (const Point<int>& newPosition) | |||
@@ -349,29 +352,30 @@ static Rectangle<int> convertDisplayRect (NSRect r, CGFloat mainScreenBottom) | |||
void Desktop::Displays::findDisplays() | |||
{ | |||
JUCE_AUTORELEASEPOOL | |||
{ | |||
DisplaySettingsChangeCallback::getInstance(); | |||
DisplaySettingsChangeCallback::getInstance(); | |||
NSArray* screens = [NSScreen screens]; | |||
const CGFloat mainScreenBottom = [[screens objectAtIndex: 0] frame].size.height; | |||
NSArray* screens = [NSScreen screens]; | |||
const CGFloat mainScreenBottom = [[screens objectAtIndex: 0] frame].size.height; | |||
for (unsigned int i = 0; i < [screens count]; ++i) | |||
{ | |||
NSScreen* s = (NSScreen*) [screens objectAtIndex: i]; | |||
for (unsigned int i = 0; i < [screens count]; ++i) | |||
{ | |||
NSScreen* s = (NSScreen*) [screens objectAtIndex: i]; | |||
Display d; | |||
d.userArea = convertDisplayRect ([s visibleFrame], mainScreenBottom); | |||
d.totalArea = convertDisplayRect ([s frame], mainScreenBottom); | |||
d.isMain = (i == 0); | |||
Display d; | |||
d.userArea = convertDisplayRect ([s visibleFrame], mainScreenBottom); | |||
d.totalArea = convertDisplayRect ([s frame], mainScreenBottom); | |||
d.isMain = (i == 0); | |||
#if defined (MAC_OS_X_VERSION_10_7) && (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7) | |||
if ([s respondsToSelector: @selector (backingScaleFactor)]) | |||
d.scale = s.backingScaleFactor; | |||
else | |||
#endif | |||
d.scale = 1.0; | |||
#if defined (MAC_OS_X_VERSION_10_7) && (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7) | |||
if ([s respondsToSelector: @selector (backingScaleFactor)]) | |||
d.scale = s.backingScaleFactor; | |||
else | |||
#endif | |||
d.scale = 1.0; | |||
displays.add (d); | |||
displays.add (d); | |||
} | |||
} | |||
} | |||
@@ -397,22 +401,23 @@ bool juce_areThereAnyAlwaysOnTopWindows() | |||
Image juce_createIconForFile (const File& file) | |||
{ | |||
JUCE_AUTORELEASEPOOL | |||
{ | |||
NSImage* image = [[NSWorkspace sharedWorkspace] iconForFile: juceStringToNS (file.getFullPathName())]; | |||
NSImage* image = [[NSWorkspace sharedWorkspace] iconForFile: juceStringToNS (file.getFullPathName())]; | |||
Image result (Image::ARGB, (int) [image size].width, (int) [image size].height, true); | |||
Image result (Image::ARGB, (int) [image size].width, (int) [image size].height, true); | |||
[NSGraphicsContext saveGraphicsState]; | |||
[NSGraphicsContext setCurrentContext: [NSGraphicsContext graphicsContextWithGraphicsPort: juce_getImageContext (result) flipped: false]]; | |||
[NSGraphicsContext saveGraphicsState]; | |||
[NSGraphicsContext setCurrentContext: [NSGraphicsContext graphicsContextWithGraphicsPort: juce_getImageContext (result) flipped: false]]; | |||
[image drawAtPoint: NSMakePoint (0, 0) | |||
fromRect: NSMakeRect (0, 0, [image size].width, [image size].height) | |||
operation: NSCompositeSourceOver fraction: 1.0f]; | |||
[image drawAtPoint: NSMakePoint (0, 0) | |||
fromRect: NSMakeRect (0, 0, [image size].width, [image size].height) | |||
operation: NSCompositeSourceOver fraction: 1.0f]; | |||
[[NSGraphicsContext currentContext] flushGraphics]; | |||
[NSGraphicsContext restoreGraphicsState]; | |||
[[NSGraphicsContext currentContext] flushGraphics]; | |||
[NSGraphicsContext restoreGraphicsState]; | |||
return result; | |||
return result; | |||
} | |||
} | |||
//============================================================================== | |||
@@ -137,9 +137,10 @@ void RecentlyOpenedFilesList::registerRecentFileNatively (const File& file) | |||
{ | |||
#if JUCE_MAC | |||
JUCE_AUTORELEASEPOOL | |||
[[NSDocumentController sharedDocumentController] | |||
noteNewRecentDocumentURL: [NSURL fileURLWithPath: juceStringToNS (file.getFullPathName())]]; | |||
{ | |||
[[NSDocumentController sharedDocumentController] | |||
noteNewRecentDocumentURL: [NSURL fileURLWithPath: juceStringToNS (file.getFullPathName())]]; | |||
} | |||
#else | |||
(void) file; | |||
#endif | |||
@@ -52,38 +52,40 @@ public: | |||
swapFrames (0), useDepthBuffer (pixelFormat.depthBufferBits > 0) | |||
{ | |||
JUCE_AUTORELEASEPOOL | |||
ComponentPeer* const peer = component.getPeer(); | |||
jassert (peer != nullptr); | |||
{ | |||
ComponentPeer* const peer = component.getPeer(); | |||
jassert (peer != nullptr); | |||
const Rectangle<int> bounds (peer->getComponent().getLocalArea (&component, component.getLocalBounds())); | |||
lastWidth = bounds.getWidth(); | |||
lastHeight = bounds.getHeight(); | |||
const Rectangle<int> bounds (peer->getComponent().getLocalArea (&component, component.getLocalBounds())); | |||
lastWidth = bounds.getWidth(); | |||
lastHeight = bounds.getHeight(); | |||
view = [[JuceGLView alloc] initWithFrame: convertToCGRect (bounds)]; | |||
view.opaque = YES; | |||
view.hidden = NO; | |||
view.backgroundColor = [UIColor blackColor]; | |||
view.userInteractionEnabled = NO; | |||
view = [[JuceGLView alloc] initWithFrame: convertToCGRect (bounds)]; | |||
view.opaque = YES; | |||
view.hidden = NO; | |||
view.backgroundColor = [UIColor blackColor]; | |||
view.userInteractionEnabled = NO; | |||
glLayer = (CAEAGLLayer*) [view layer]; | |||
glLayer.contentsScale = Desktop::getInstance().getDisplays().getMainDisplay().scale; | |||
glLayer = (CAEAGLLayer*) [view layer]; | |||
glLayer.contentsScale = Desktop::getInstance().getDisplays().getMainDisplay().scale; | |||
[((UIView*) peer->getNativeHandle()) addSubview: view]; | |||
[((UIView*) peer->getNativeHandle()) addSubview: view]; | |||
context = [EAGLContext alloc]; | |||
context = [EAGLContext alloc]; | |||
const NSUInteger type = kEAGLRenderingAPIOpenGLES2; | |||
const NSUInteger type = kEAGLRenderingAPIOpenGLES2; | |||
if (contextToShareWith != nullptr) | |||
[context initWithAPI: type sharegroup: [(EAGLContext*) contextToShareWith sharegroup]]; | |||
else | |||
[context initWithAPI: type]; | |||
if (contextToShareWith != nullptr) | |||
[context initWithAPI: type sharegroup: [(EAGLContext*) contextToShareWith sharegroup]]; | |||
else | |||
[context initWithAPI: type]; | |||
// I'd prefer to put this stuff in the initialiseOnRenderThread() call, but doing | |||
// so causes myserious timing-related failures. | |||
[EAGLContext setCurrentContext: context]; | |||
createGLBuffers(); | |||
deactivateCurrentContext(); | |||
// I'd prefer to put this stuff in the initialiseOnRenderThread() call, but doing | |||
// so causes myserious timing-related failures. | |||
[EAGLContext setCurrentContext: context]; | |||
createGLBuffers(); | |||
deactivateCurrentContext(); | |||
} | |||
} | |||
~NativeContext() | |||