| @@ -236,7 +236,9 @@ bool AudioCDReader::isCDStillPresent() const | |||||
| void AudioCDReader::ejectDisk() | void AudioCDReader::ejectDisk() | ||||
| { | { | ||||
| JUCE_AUTORELEASEPOOL | JUCE_AUTORELEASEPOOL | ||||
| [[NSWorkspace sharedWorkspace] unmountAndEjectDeviceAtPath: juceStringToNS (volumeDir.getFullPathName())]; | |||||
| { | |||||
| [[NSWorkspace sharedWorkspace] unmountAndEjectDeviceAtPath: juceStringToNS (volumeDir.getFullPathName())]; | |||||
| } | |||||
| } | } | ||||
| bool AudioCDReader::isTrackAudio (int trackNum) const | bool AudioCDReader::isTrackAudio (int trackNum) const | ||||
| @@ -84,225 +84,231 @@ public: | |||||
| dataHandle (0) | dataHandle (0) | ||||
| { | { | ||||
| JUCE_AUTORELEASEPOOL | 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, | kQTPropertyClass_MovieAudioExtraction_Audio, | ||||
| kQTMovieAudioExtractionAudioPropertyID_AudioChannelLayout, | 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() | ~QTAudioReader() | ||||
| { | { | ||||
| JUCE_AUTORELEASEPOOL | 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, | bool readSamples (int** destSamples, int numDestChannels, int startOffsetInDestBuffer, | ||||
| int64 startSampleInFile, int numSamples) | int64 startSampleInFile, int numSamples) | ||||
| { | { | ||||
| JUCE_AUTORELEASEPOOL | 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) | if (err != noErr) | ||||
| { | { | ||||
| readOk = false; | readOk = false; | ||||
| break; | 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; | bool ok; | ||||
| @@ -62,8 +62,8 @@ | |||||
| namespace juce | 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;) | for (int i = list.size(); --i >= 0;) | ||||
| if (list.getUnchecked(i)->isDuplicateOf (desc)) | if (list.getUnchecked(i)->isDuplicateOf (desc)) | ||||
| @@ -79,8 +79,16 @@ inline Type* createCopyIfNotNull (const Type* pointer) { return pointer != n | |||||
| JUCE_DECLARE_NON_COPYABLE (ScopedAutoReleasePool) | 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__); | #define JUCE_AUTORELEASEPOOL const juce::ScopedAutoReleasePool JUCE_JOIN_MACRO (autoReleasePool_, __LINE__); | ||||
| #endif | |||||
| #else | #else | ||||
| #define JUCE_AUTORELEASEPOOL | #define JUCE_AUTORELEASEPOOL | ||||
| @@ -32,18 +32,20 @@ | |||||
| bool File::copyInternal (const File& dest) const | bool File::copyInternal (const File& dest) const | ||||
| { | { | ||||
| JUCE_AUTORELEASEPOOL | 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) | 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 | #if defined (MAC_OS_X_VERSION_10_6) && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_6 | ||||
| JUCE_AUTORELEASEPOOL | 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 | #elif JUCE_IOS | ||||
| return File (path).getFileName().startsWithChar ('.'); | return File (path).getFileName().startsWithChar ('.'); | ||||
| #else | #else | ||||
| @@ -143,17 +147,19 @@ bool File::isOnRemovableDrive() const | |||||
| return false; // xxx is this possible? | return false; // xxx is this possible? | ||||
| #else | #else | ||||
| JUCE_AUTORELEASEPOOL | 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 | #endif | ||||
| } | } | ||||
| @@ -169,82 +175,84 @@ int juce_argc = 0; | |||||
| File File::getSpecialLocation (const SpecialLocationType type) | File File::getSpecialLocation (const SpecialLocationType type) | ||||
| { | { | ||||
| JUCE_AUTORELEASEPOOL | 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 | #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 | #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; | return File::nonexistent; | ||||
| } | } | ||||
| @@ -252,24 +260,14 @@ File File::getSpecialLocation (const SpecialLocationType type) | |||||
| String File::getVersion() const | String File::getVersion() const | ||||
| { | { | ||||
| JUCE_AUTORELEASEPOOL | 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? | return deleteFile(); //xxx is there a trashcan on the iOS? | ||||
| #else | #else | ||||
| JUCE_AUTORELEASEPOOL | 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 | #endif | ||||
| } | } | ||||
| @@ -320,8 +319,9 @@ public: | |||||
| enumerator (nil) | enumerator (nil) | ||||
| { | { | ||||
| JUCE_AUTORELEASEPOOL | JUCE_AUTORELEASEPOOL | ||||
| enumerator = [[[NSFileManager defaultManager] enumeratorAtPath: juceStringToNS (directory.getFullPathName())] retain]; | |||||
| { | |||||
| enumerator = [[[NSFileManager defaultManager] enumeratorAtPath: juceStringToNS (directory.getFullPathName())] retain]; | |||||
| } | |||||
| } | } | ||||
| ~Pimpl() | ~Pimpl() | ||||
| @@ -334,30 +334,32 @@ public: | |||||
| Time* const modTime, Time* const creationTime, bool* const isReadOnly) | Time* const modTime, Time* const creationTime, bool* const isReadOnly) | ||||
| { | { | ||||
| JUCE_AUTORELEASEPOOL | 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)]]; | return [[UIApplication sharedApplication] openURL: [NSURL URLWithString: juceStringToNS (fileName)]]; | ||||
| #else | #else | ||||
| JUCE_AUTORELEASEPOOL | 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 | #endif | ||||
| } | } | ||||
| @@ -440,15 +443,16 @@ void File::revealToUser() const | |||||
| OSType File::getMacOSType() const | OSType File::getMacOSType() const | ||||
| { | { | ||||
| JUCE_AUTORELEASEPOOL | 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 | 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.. | return false; // xxx can't find a sensible way to do this without trying to open the bundle.. | ||||
| #else | #else | ||||
| JUCE_AUTORELEASEPOOL | JUCE_AUTORELEASEPOOL | ||||
| return [[NSWorkspace sharedWorkspace] isFilePackageAtPath: juceStringToNS (getFullPathName())]; | |||||
| { | |||||
| return [[NSWorkspace sharedWorkspace] isFilePackageAtPath: juceStringToNS (getFullPathName())]; | |||||
| } | |||||
| #endif | #endif | ||||
| } | } | ||||
| @@ -61,39 +61,40 @@ bool Process::openEmailWithAttachments (const String& targetEmailAddress, | |||||
| return false; | return false; | ||||
| #else | #else | ||||
| JUCE_AUTORELEASEPOOL | 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 | #endif | ||||
| } | } | ||||
| @@ -229,7 +230,9 @@ public: | |||||
| while (! threadShouldExit()) | while (! threadShouldExit()) | ||||
| { | { | ||||
| JUCE_AUTORELEASEPOOL | 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_) | finished (false), isPost (isPost_), timeOutMs (timeOutMs_) | ||||
| { | { | ||||
| JUCE_AUTORELEASEPOOL | 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; | return 0; | ||||
| JUCE_AUTORELEASEPOOL | 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) | bool setPosition (int64 wantedPos) | ||||
| @@ -46,7 +46,9 @@ String String::convertToPrecomposedUnicode() const | |||||
| { | { | ||||
| #if JUCE_IOS | #if JUCE_IOS | ||||
| JUCE_AUTORELEASEPOOL | JUCE_AUTORELEASEPOOL | ||||
| return nsStringToJuce ([juceStringToNS (*this) precomposedStringWithCanonicalMapping]); | |||||
| { | |||||
| return nsStringToJuce ([juceStringToNS (*this) precomposedStringWithCanonicalMapping]); | |||||
| } | |||||
| #else | #else | ||||
| UnicodeMapping map; | UnicodeMapping map; | ||||
| @@ -110,10 +110,12 @@ static RLimitInitialiser rLimitInitialiser; | |||||
| static String getOSXVersion() | static String getOSXVersion() | ||||
| { | { | ||||
| JUCE_AUTORELEASEPOOL | 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 | #endif | ||||
| @@ -824,18 +824,20 @@ extern "C" void* threadEntryProc (void*); | |||||
| extern "C" void* threadEntryProc (void* userData) | extern "C" void* threadEntryProc (void* userData) | ||||
| { | { | ||||
| JUCE_AUTORELEASEPOOL | 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; | 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) | #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 | JUCE_AUTORELEASEPOOL | ||||
| [[NSThread currentThread] setName: juceStringToNS (name)]; | |||||
| { | |||||
| [[NSThread currentThread] setName: juceStringToNS (name)]; | |||||
| } | |||||
| #elif JUCE_LINUX | #elif JUCE_LINUX | ||||
| prctl (PR_SET_NAME, name.toUTF8().getAddress(), 0, 0, 0); | prctl (PR_SET_NAME, name.toUTF8().getAddress(), 0, 0, 0); | ||||
| #endif | #endif | ||||
| @@ -304,6 +304,8 @@ namespace juce | |||||
| #if __has_feature (cxx_rvalue_references) | #if __has_feature (cxx_rvalue_references) | ||||
| #define JUCE_COMPILER_SUPPORTS_MOVE_SEMANTICS 1 | #define JUCE_COMPILER_SUPPORTS_MOVE_SEMANTICS 1 | ||||
| #endif | #endif | ||||
| #define JUCE_COMPILER_SUPPORTS_ARC 1 | |||||
| #endif | #endif | ||||
| #if defined (_MSC_VER) && _MSC_VER >= 1600 | #if defined (_MSC_VER) && _MSC_VER >= 1600 | ||||
| @@ -42,14 +42,15 @@ JUCEApplicationBase::~JUCEApplicationBase() | |||||
| void JUCEApplicationBase::appWillTerminateByForce() | void JUCEApplicationBase::appWillTerminateByForce() | ||||
| { | { | ||||
| JUCE_AUTORELEASEPOOL | 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_API void JUCE_CALLTYPE initialiseJuce_GUI() | ||||
| { | { | ||||
| JUCE_AUTORELEASEPOOL | JUCE_AUTORELEASEPOOL | ||||
| MessageManager::getInstance(); | |||||
| { | |||||
| MessageManager::getInstance(); | |||||
| } | |||||
| } | } | ||||
| JUCE_API void JUCE_CALLTYPE shutdownJuce_GUI(); | JUCE_API void JUCE_CALLTYPE shutdownJuce_GUI(); | ||||
| JUCE_API void JUCE_CALLTYPE shutdownJuce_GUI() | JUCE_API void JUCE_CALLTYPE shutdownJuce_GUI() | ||||
| { | { | ||||
| JUCE_AUTORELEASEPOOL | JUCE_AUTORELEASEPOOL | ||||
| DeletedAtShutdown::deleteAll(); | |||||
| MessageManager::deleteInstance(); | |||||
| { | |||||
| DeletedAtShutdown::deleteAll(); | |||||
| MessageManager::deleteInstance(); | |||||
| } | |||||
| } | } | ||||
| @@ -38,23 +38,26 @@ void MessageManager::stopDispatchLoop() | |||||
| bool MessageManager::runDispatchLoopUntil (int millisecondsToRunFor) | bool MessageManager::runDispatchLoopUntil (int millisecondsToRunFor) | ||||
| { | { | ||||
| JUCE_AUTORELEASEPOOL | 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.. | if (! quitMessagePosted) // check that the quit message wasn't already posted.. | ||||
| { | { | ||||
| JUCE_AUTORELEASEPOOL | 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]; | [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) | while (! quitMessagePosted) | ||||
| { | { | ||||
| JUCE_AUTORELEASEPOOL | 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; | return ! quitMessagePosted; | ||||
| @@ -281,7 +283,9 @@ void initialiseNSApplication(); | |||||
| void initialiseNSApplication() | void initialiseNSApplication() | ||||
| { | { | ||||
| JUCE_AUTORELEASEPOOL | JUCE_AUTORELEASEPOOL | ||||
| [NSApplication sharedApplication]; | |||||
| { | |||||
| [NSApplication sharedApplication]; | |||||
| } | |||||
| } | } | ||||
| static AppDelegate* appDelegate = nullptr; | static AppDelegate* appDelegate = nullptr; | ||||
| @@ -75,12 +75,13 @@ private: | |||||
| return false; | return false; | ||||
| JUCE_AUTORELEASEPOOL | JUCE_AUTORELEASEPOOL | ||||
| JUCE_TRY | |||||
| { | { | ||||
| nextMessage->messageCallback(); | |||||
| JUCE_TRY | |||||
| { | |||||
| nextMessage->messageCallback(); | |||||
| } | |||||
| JUCE_CATCH_EXCEPTION | |||||
| } | } | ||||
| JUCE_CATCH_EXCEPTION | |||||
| return true; | return true; | ||||
| } | } | ||||
| @@ -787,51 +787,55 @@ Image juce_loadWithCoreImage (InputStream& input) | |||||
| MemoryBlock data; | MemoryBlock data; | ||||
| input.readIntoMemoryBlock (data, -1); | input.readIntoMemoryBlock (data, -1); | ||||
| #if JUCE_IOS | |||||
| #if JUCE_IOS | |||||
| JUCE_AUTORELEASEPOOL | 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()) | : Typeface (font.getTypefaceName(), font.getTypefaceStyle()) | ||||
| { | { | ||||
| JUCE_AUTORELEASEPOOL | 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(); | 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() | ~OSXTypeface() | ||||
| @@ -910,28 +912,29 @@ public: | |||||
| jassert (path.isEmpty()); | jassert (path.isEmpty()); | ||||
| JUCE_AUTORELEASEPOOL | 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; | return true; | ||||
| #endif | #endif | ||||
| } | } | ||||
| @@ -1084,18 +1087,21 @@ private: | |||||
| StringArray Font::findAllTypefaceNames() | StringArray Font::findAllTypefaceNames() | ||||
| { | { | ||||
| StringArray names; | StringArray names; | ||||
| JUCE_AUTORELEASEPOOL | 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; | return names; | ||||
| } | } | ||||
| @@ -1105,14 +1111,16 @@ StringArray Font::findAllTypefaceStyles (const String& family) | |||||
| return findAllTypefaceStyles (FontStyleHelpers::getConcreteFamilyNameFromPlaceholder (family)); | return findAllTypefaceStyles (FontStyleHelpers::getConcreteFamilyNameFromPlaceholder (family)); | ||||
| StringArray results; | 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; | return results; | ||||
| @@ -283,19 +283,20 @@ String JUCEApplication::getCommandLineParameters() | |||||
| int JUCEApplication::main (int argc, const char* argv[]) | int JUCEApplication::main (int argc, const char* argv[]) | ||||
| { | { | ||||
| JUCE_AUTORELEASEPOOL | 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 | #endif | ||||
| @@ -131,10 +131,12 @@ public: | |||||
| int getResult() | int getResult() | ||||
| { | { | ||||
| jassert (callback == nullptr); | 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; | return result; | ||||
| } | } | ||||
| @@ -181,8 +183,10 @@ void JUCE_CALLTYPE NativeMessageBox::showMessageBox (AlertWindow::AlertIconType | |||||
| Component* associatedComponent) | Component* associatedComponent) | ||||
| { | { | ||||
| JUCE_AUTORELEASEPOOL | 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, | void JUCE_CALLTYPE NativeMessageBox::showMessageBoxAsync (AlertWindow::AlertIconType iconType, | ||||
| @@ -302,18 +306,19 @@ Desktop::DisplayOrientation Desktop::getCurrentOrientation() const | |||||
| void Desktop::Displays::findDisplays() | void Desktop::Displays::findDisplays() | ||||
| { | { | ||||
| JUCE_AUTORELEASEPOOL | 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*/) | FilePreviewComponent* /*extraInfoComponent*/) | ||||
| { | { | ||||
| JUCE_AUTORELEASEPOOL | 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 | 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() | bool FileChooser::isPlatformDialogAvailable() | ||||
| @@ -220,8 +221,6 @@ void FileChooser::showPlatformDialog (Array<File>& results, | |||||
| bool selectMultipleFiles, | bool selectMultipleFiles, | ||||
| FilePreviewComponent* extraInfoComponent) | FilePreviewComponent* extraInfoComponent) | ||||
| { | { | ||||
| JUCE_AUTORELEASEPOOL | |||||
| jassertfalse; //there's no such thing in iOS | jassertfalse; //there's no such thing in iOS | ||||
| } | } | ||||
| @@ -658,20 +658,21 @@ namespace MainMenuHelpers | |||||
| if (JUCEApplication* app = JUCEApplication::getInstance()) | if (JUCEApplication* app = JUCEApplication::getInstance()) | ||||
| { | { | ||||
| JUCE_AUTORELEASEPOOL | 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) | if (getMacMainMenu() != newMenuBarModel) | ||||
| { | { | ||||
| JUCE_AUTORELEASEPOOL | 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) | static NSImage* createNSImage (const Image& image) | ||||
| { | { | ||||
| JUCE_AUTORELEASEPOOL | 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) | static void* fromWebKitFile (const char* filename, float hx, float hy) | ||||
| @@ -78,46 +79,48 @@ void* CustomMouseCursorInfo::create() const | |||||
| void* MouseCursor::createStandardMouseCursor (MouseCursor::StandardCursorType type) | void* MouseCursor::createStandardMouseCursor (MouseCursor::StandardCursorType type) | ||||
| { | { | ||||
| JUCE_AUTORELEASEPOOL | 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*/) | void MouseCursor::deleteMouseCursor (void* const cursorHandle, const bool /*isStandard*/) | ||||
| @@ -199,9 +199,10 @@ public: | |||||
| void setTitle (const String& title) | void setTitle (const String& title) | ||||
| { | { | ||||
| JUCE_AUTORELEASEPOOL | JUCE_AUTORELEASEPOOL | ||||
| if (! isSharedWindow) | |||||
| [window setTitle: juceStringToNS (title)]; | |||||
| { | |||||
| if (! isSharedWindow) | |||||
| [window setTitle: juceStringToNS (title)]; | |||||
| } | |||||
| } | } | ||||
| bool setDocumentEditedStatus (bool edited) | bool setDocumentEditedStatus (bool edited) | ||||
| @@ -163,35 +163,36 @@ bool DragAndDropContainer::performExternalDragDropOfFiles (const StringArray& fi | |||||
| } | } | ||||
| JUCE_AUTORELEASEPOOL | 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; | return true; | ||||
| } | } | ||||
| @@ -211,8 +212,10 @@ bool Desktop::canUseSemiTransparentWindows() noexcept | |||||
| Point<int> MouseInputSource::getCurrentMousePosition() | Point<int> MouseInputSource::getCurrentMousePosition() | ||||
| { | { | ||||
| JUCE_AUTORELEASEPOOL | 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) | void Desktop::setMousePosition (const Point<int>& newPosition) | ||||
| @@ -349,29 +352,30 @@ static Rectangle<int> convertDisplayRect (NSRect r, CGFloat mainScreenBottom) | |||||
| void Desktop::Displays::findDisplays() | void Desktop::Displays::findDisplays() | ||||
| { | { | ||||
| JUCE_AUTORELEASEPOOL | 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) | Image juce_createIconForFile (const File& file) | ||||
| { | { | ||||
| JUCE_AUTORELEASEPOOL | 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 | #if JUCE_MAC | ||||
| JUCE_AUTORELEASEPOOL | JUCE_AUTORELEASEPOOL | ||||
| [[NSDocumentController sharedDocumentController] | |||||
| noteNewRecentDocumentURL: [NSURL fileURLWithPath: juceStringToNS (file.getFullPathName())]]; | |||||
| { | |||||
| [[NSDocumentController sharedDocumentController] | |||||
| noteNewRecentDocumentURL: [NSURL fileURLWithPath: juceStringToNS (file.getFullPathName())]]; | |||||
| } | |||||
| #else | #else | ||||
| (void) file; | (void) file; | ||||
| #endif | #endif | ||||
| @@ -52,38 +52,40 @@ public: | |||||
| swapFrames (0), useDepthBuffer (pixelFormat.depthBufferBits > 0) | swapFrames (0), useDepthBuffer (pixelFormat.depthBufferBits > 0) | ||||
| { | { | ||||
| JUCE_AUTORELEASEPOOL | 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() | ~NativeContext() | ||||