From b5ff396bd4cabc02114f90b2e45614655102cf58 Mon Sep 17 00:00:00 2001 From: Jonathan Thomas Date: Wed, 2 Sep 2015 18:09:07 -0500 Subject: [PATCH] Updating JUCE Audio modules to newest version (this will break a few things) --- .../buffers/juce_AudioDataConverters.cpp | 34 +- .../buffers/juce_AudioDataConverters.h | 46 +- .../buffers/juce_AudioSampleBuffer.cpp | 19 +- .../buffers/juce_AudioSampleBuffer.h | 2 +- .../buffers/juce_FloatVectorOperations.cpp | 429 ++++- .../buffers/juce_FloatVectorOperations.h | 74 +- .../juce_audio_basics/effects/juce_Decibels.h | 2 +- .../effects/juce_IIRFilter.cpp | 8 +- .../effects/juce_IIRFilter.h | 2 +- .../effects/juce_LagrangeInterpolator.cpp | 12 +- .../effects/juce_LagrangeInterpolator.h | 2 +- .../juce_audio_basics/effects/juce_Reverb.h | 137 +- .../juce_audio_basics/juce_audio_basics.cpp | 8 +- .../juce_audio_basics/juce_audio_basics.h | 6 +- .../juce_audio_basics/juce_audio_basics.mm | 2 +- .../juce_audio_basics/juce_module_info | 2 +- .../midi/juce_MidiBuffer.cpp | 14 +- .../juce_audio_basics/midi/juce_MidiBuffer.h | 12 +- .../juce_audio_basics/midi/juce_MidiFile.cpp | 2 +- .../juce_audio_basics/midi/juce_MidiFile.h | 2 +- .../midi/juce_MidiKeyboardState.cpp | 4 +- .../midi/juce_MidiKeyboardState.h | 2 +- .../midi/juce_MidiMessage.cpp | 12 +- .../juce_audio_basics/midi/juce_MidiMessage.h | 2 +- .../midi/juce_MidiMessageSequence.cpp | 40 +- .../midi/juce_MidiMessageSequence.h | 4 +- .../sources/juce_AudioSource.h | 2 +- .../sources/juce_BufferingAudioSource.cpp | 2 +- .../sources/juce_BufferingAudioSource.h | 2 +- .../juce_ChannelRemappingAudioSource.cpp | 2 +- .../juce_ChannelRemappingAudioSource.h | 2 +- .../sources/juce_IIRFilterAudioSource.cpp | 2 +- .../sources/juce_IIRFilterAudioSource.h | 2 +- .../sources/juce_MixerAudioSource.cpp | 2 +- .../sources/juce_MixerAudioSource.h | 2 +- .../sources/juce_PositionableAudioSource.h | 2 +- .../sources/juce_ResamplingAudioSource.cpp | 38 +- .../sources/juce_ResamplingAudioSource.h | 5 +- .../sources/juce_ReverbAudioSource.cpp | 2 +- .../sources/juce_ReverbAudioSource.h | 2 +- .../sources/juce_ToneGeneratorAudioSource.cpp | 2 +- .../sources/juce_ToneGeneratorAudioSource.h | 2 +- .../synthesisers/juce_Synthesiser.cpp | 268 ++- .../synthesisers/juce_Synthesiser.h | 150 +- .../audio_cd/juce_AudioCDBurner.h | 2 +- .../audio_cd/juce_AudioCDReader.cpp | 2 +- .../audio_cd/juce_AudioCDReader.h | 2 +- .../audio_io/juce_AudioDeviceManager.cpp | 36 +- .../audio_io/juce_AudioDeviceManager.h | 3 +- .../audio_io/juce_AudioIODevice.cpp | 2 +- .../audio_io/juce_AudioIODevice.h | 2 +- .../audio_io/juce_AudioIODeviceType.cpp | 4 +- .../audio_io/juce_AudioIODeviceType.h | 4 +- .../audio_io/juce_SystemAudioVolume.h | 2 +- .../juce_audio_devices/juce_audio_devices.cpp | 4 +- .../juce_audio_devices/juce_audio_devices.h | 15 +- .../juce_audio_devices/juce_audio_devices.mm | 2 +- .../juce_audio_devices/juce_module_info | 2 +- .../midi_io/juce_MidiInput.h | 16 +- .../midi_io/juce_MidiMessageCollector.cpp | 2 +- .../midi_io/juce_MidiMessageCollector.h | 2 +- .../midi_io/juce_MidiOutput.cpp | 2 +- .../midi_io/juce_MidiOutput.h | 31 +- .../native/juce_MidiDataConcatenator.h | 2 +- .../native/juce_android_Audio.cpp | 2 +- .../native/juce_android_Midi.cpp | 2 +- .../native/juce_android_OpenSL.cpp | 22 +- .../native/juce_ios_Audio.cpp | 8 +- .../native/juce_linux_ALSA.cpp | 94 +- .../native/juce_linux_AudioCDReader.cpp | 2 +- .../native/juce_linux_JackAudio.cpp | 2 +- .../native/juce_linux_Midi.cpp | 31 +- .../native/juce_mac_AudioCDBurner.mm | 2 +- .../native/juce_mac_AudioCDReader.mm | 2 +- .../native/juce_mac_CoreAudio.cpp | 16 +- .../native/juce_mac_CoreMidi.cpp | 72 +- .../native/juce_win32_ASIO.cpp | 118 +- .../native/juce_win32_AudioCDBurner.cpp | 2 +- .../native/juce_win32_AudioCDReader.cpp | 2 +- .../native/juce_win32_DirectSound.cpp | 4 +- .../native/juce_win32_Midi.cpp | 2 +- .../native/juce_win32_WASAPI.cpp | 484 ++++-- .../sources/juce_AudioSourcePlayer.cpp | 2 +- .../sources/juce_AudioSourcePlayer.h | 2 +- .../sources/juce_AudioTransportSource.cpp | 6 +- .../sources/juce_AudioTransportSource.h | 2 +- .../juce_audio_formats/codecs/flac/all.h | 2 +- .../juce_audio_formats/codecs/flac/alloc.h | 4 +- .../juce_audio_formats/codecs/flac/assert.h | 2 +- .../juce_audio_formats/codecs/flac/callback.h | 2 +- .../juce_audio_formats/codecs/flac/compat.h | 35 +- .../juce_audio_formats/codecs/flac/endswap.h | 30 +- .../juce_audio_formats/codecs/flac/export.h | 6 +- .../juce_audio_formats/codecs/flac/format.h | 6 +- .../codecs/flac/libFLAC/bitmath.c | 5 +- .../codecs/flac/libFLAC/bitreader.c | 16 +- .../codecs/flac/libFLAC/bitwriter.c | 36 +- .../codecs/flac/libFLAC/cpu.c | 637 +++---- .../codecs/flac/libFLAC/crc.c | 4 +- .../codecs/flac/libFLAC/fixed.c | 19 +- .../codecs/flac/libFLAC/float.c | 4 +- .../codecs/flac/libFLAC/format.c | 11 +- .../codecs/flac/libFLAC/include/private/all.h | 2 +- .../flac/libFLAC/include/private/bitmath.h | 81 +- .../flac/libFLAC/include/private/bitreader.h | 13 +- .../flac/libFLAC/include/private/bitwriter.h | 2 +- .../codecs/flac/libFLAC/include/private/cpu.h | 52 +- .../codecs/flac/libFLAC/include/private/crc.h | 4 +- .../flac/libFLAC/include/private/fixed.h | 19 +- .../flac/libFLAC/include/private/float.h | 2 +- .../flac/libFLAC/include/private/format.h | 2 +- .../codecs/flac/libFLAC/include/private/lpc.h | 43 +- .../codecs/flac/libFLAC/include/private/md5.h | 8 +- .../flac/libFLAC/include/private/memory.h | 2 +- .../flac/libFLAC/include/private/metadata.h | 2 +- .../include/private/stream_encoder_framing.h | 2 +- .../flac/libFLAC/include/private/window.h | 4 +- .../flac/libFLAC/include/protected/all.h | 2 +- .../include/protected/stream_decoder.h | 3 +- .../include/protected/stream_encoder.h | 9 +- .../codecs/flac/libFLAC/lpc_flac.c | 30 +- .../codecs/flac/libFLAC/md5.c | 311 ++-- .../codecs/flac/libFLAC/memory.c | 29 +- .../codecs/flac/libFLAC/stream_decoder.c | 229 +-- .../codecs/flac/libFLAC/stream_encoder.c | 299 +++- .../flac/libFLAC/stream_encoder_framing.c | 4 +- .../codecs/flac/libFLAC/window_flac.c | 81 +- .../juce_audio_formats/codecs/flac/metadata.h | 4 +- .../juce_audio_formats/codecs/flac/ordinals.h | 2 +- .../codecs/flac/stream_decoder.h | 2 +- .../codecs/flac/stream_encoder.h | 69 +- .../codecs/juce_AiffAudioFormat.cpp | 192 ++- .../codecs/juce_AiffAudioFormat.h | 2 +- .../codecs/juce_CoreAudioFormat.cpp | 2 +- .../codecs/juce_CoreAudioFormat.h | 2 +- .../codecs/juce_FlacAudioFormat.cpp | 2 +- .../codecs/juce_FlacAudioFormat.h | 2 +- .../codecs/juce_LAMEEncoderAudioFormat.cpp | 10 +- .../codecs/juce_LAMEEncoderAudioFormat.h | 2 +- .../codecs/juce_MP3AudioFormat.cpp | 29 +- .../codecs/juce_MP3AudioFormat.h | 6 +- .../codecs/juce_OggVorbisAudioFormat.cpp | 2 +- .../codecs/juce_OggVorbisAudioFormat.h | 2 +- .../codecs/juce_QuickTimeAudioFormat.cpp | 12 +- .../codecs/juce_QuickTimeAudioFormat.h | 2 +- .../codecs/juce_WavAudioFormat.cpp | 278 +++- .../codecs/juce_WavAudioFormat.h | 5 +- .../codecs/juce_WindowsMediaAudioFormat.cpp | 2 +- .../codecs/juce_WindowsMediaAudioFormat.h | 2 +- .../oggvorbis/libvorbis-1.3.2/lib/floor1.c | 2 +- .../format/juce_AudioFormat.cpp | 2 +- .../format/juce_AudioFormat.h | 4 +- .../format/juce_AudioFormatManager.cpp | 2 +- .../format/juce_AudioFormatManager.h | 2 +- .../format/juce_AudioFormatReader.cpp | 145 +- .../format/juce_AudioFormatReader.h | 36 +- .../format/juce_AudioFormatReaderSource.cpp | 2 +- .../format/juce_AudioFormatReaderSource.h | 6 +- .../format/juce_AudioFormatWriter.cpp | 32 +- .../format/juce_AudioFormatWriter.h | 23 +- .../format/juce_AudioSubsectionReader.cpp | 13 +- .../format/juce_AudioSubsectionReader.h | 5 +- .../juce_BufferingAudioFormatReader.cpp | 5 +- .../format/juce_BufferingAudioFormatReader.h | 2 +- .../juce_MemoryMappedAudioFormatReader.h | 14 +- .../juce_audio_formats/juce_audio_formats.cpp | 2 +- .../juce_audio_formats/juce_audio_formats.h | 6 +- .../juce_audio_formats/juce_audio_formats.mm | 2 +- .../juce_audio_formats/juce_module_info | 2 +- .../sampler/juce_Sampler.cpp | 14 +- .../juce_audio_formats/sampler/juce_Sampler.h | 10 +- .../format/juce_AudioPluginFormat.cpp | 2 +- .../format/juce_AudioPluginFormat.h | 2 +- .../format/juce_AudioPluginFormatManager.cpp | 2 +- .../format/juce_AudioPluginFormatManager.h | 2 +- .../format_types/juce_AudioUnitPluginFormat.h | 2 +- .../juce_AudioUnitPluginFormat.mm | 129 +- .../format_types/juce_LADSPAPluginFormat.cpp | 6 +- .../format_types/juce_LADSPAPluginFormat.h | 2 +- .../format_types/juce_VST3Common.h | 6 +- .../format_types/juce_VST3Headers.h | 2 +- .../format_types/juce_VST3PluginFormat.cpp | 252 +-- .../format_types/juce_VST3PluginFormat.h | 2 +- .../format_types/juce_VSTMidiEventList.h | 4 +- .../format_types/juce_VSTPluginFormat.cpp | 532 +++--- .../format_types/juce_VSTPluginFormat.h | 2 +- .../juce_audio_processors.cpp | 36 +- .../juce_audio_processors.h | 3 +- .../juce_audio_processors.mm | 2 +- .../juce_audio_processors/juce_module_info | 2 +- .../processors/juce_AudioPlayHead.h | 12 +- .../processors/juce_AudioPluginInstance.h | 2 +- .../processors/juce_AudioProcessor.cpp | 197 ++- .../processors/juce_AudioProcessor.h | 117 +- .../processors/juce_AudioProcessorEditor.cpp | 16 +- .../processors/juce_AudioProcessorEditor.h | 46 +- .../processors/juce_AudioProcessorGraph.cpp | 255 ++- .../processors/juce_AudioProcessorGraph.h | 123 +- .../processors/juce_AudioProcessorListener.h | 2 +- .../juce_GenericAudioProcessorEditor.cpp | 4 +- .../juce_GenericAudioProcessorEditor.h | 2 +- .../processors/juce_PluginDescription.cpp | 20 +- .../processors/juce_PluginDescription.h | 12 +- .../scanning/juce_KnownPluginList.cpp | 10 +- .../scanning/juce_KnownPluginList.h | 2 +- .../scanning/juce_PluginDirectoryScanner.cpp | 2 +- .../scanning/juce_PluginDirectoryScanner.h | 2 +- .../scanning/juce_PluginListComponent.cpp | 55 +- .../scanning/juce_PluginListComponent.h | 24 +- .../containers/juce_AbstractFifo.cpp | 2 +- .../juce_core/containers/juce_AbstractFifo.h | 4 +- .../modules/juce_core/containers/juce_Array.h | 44 +- .../containers/juce_ArrayAllocationBase.h | 2 +- .../containers/juce_DynamicObject.cpp | 4 +- .../juce_core/containers/juce_DynamicObject.h | 4 +- .../containers/juce_ElementComparator.h | 2 +- .../juce_core/containers/juce_HashMap.h | 2 +- .../containers/juce_LinkedListPointer.h | 2 +- .../containers/juce_NamedValueSet.cpp | 19 +- .../juce_core/containers/juce_NamedValueSet.h | 12 +- .../juce_core/containers/juce_OwnedArray.h | 4 +- .../juce_core/containers/juce_PropertySet.cpp | 2 +- .../juce_core/containers/juce_PropertySet.h | 2 +- .../containers/juce_ReferenceCountedArray.h | 37 +- .../containers/juce_ScopedValueSetter.h | 2 +- .../juce_core/containers/juce_SortedSet.h | 2 +- .../juce_core/containers/juce_SparseSet.h | 2 +- .../juce_core/containers/juce_Variant.cpp | 32 +- .../juce_core/containers/juce_Variant.h | 23 +- .../files/juce_DirectoryIterator.cpp | 111 +- .../juce_core/files/juce_DirectoryIterator.h | 2 +- .../modules/juce_core/files/juce_File.cpp | 14 +- .../modules/juce_core/files/juce_File.h | 18 +- .../juce_core/files/juce_FileFilter.cpp | 2 +- .../modules/juce_core/files/juce_FileFilter.h | 2 +- .../juce_core/files/juce_FileInputStream.cpp | 4 +- .../juce_core/files/juce_FileInputStream.h | 2 +- .../juce_core/files/juce_FileOutputStream.cpp | 10 +- .../juce_core/files/juce_FileOutputStream.h | 2 +- .../juce_core/files/juce_FileSearchPath.cpp | 2 +- .../juce_core/files/juce_FileSearchPath.h | 2 +- .../juce_core/files/juce_MemoryMappedFile.h | 2 +- .../juce_core/files/juce_TemporaryFile.cpp | 2 +- .../juce_core/files/juce_TemporaryFile.h | 2 +- .../files/juce_WildcardFileFilter.cpp | 55 +- .../juce_core/files/juce_WildcardFileFilter.h | 6 +- .../juce_core/javascript/juce_JSON.cpp | 4 +- .../modules/juce_core/javascript/juce_JSON.h | 2 +- .../juce_core/javascript/juce_Javascript.cpp | 82 +- .../juce_core/javascript/juce_Javascript.h | 13 +- .../modules/juce_core/juce_core.cpp | 19 +- JuceLibraryCode/modules/juce_core/juce_core.h | 32 +- .../modules/juce_core/juce_core.mm | 2 +- .../modules/juce_core/juce_module_info | 2 +- .../juce_core/logging/juce_FileLogger.cpp | 14 +- .../juce_core/logging/juce_FileLogger.h | 10 +- .../modules/juce_core/logging/juce_Logger.cpp | 2 +- .../modules/juce_core/logging/juce_Logger.h | 2 +- .../juce_core/maths/juce_BigInteger.cpp | 53 +- .../modules/juce_core/maths/juce_BigInteger.h | 2 +- .../juce_core/maths/juce_Expression.cpp | 8 +- .../modules/juce_core/maths/juce_Expression.h | 2 +- .../juce_core/maths/juce_MathsFunctions.h | 117 +- .../modules/juce_core/maths/juce_Random.cpp | 2 +- .../modules/juce_core/maths/juce_Random.h | 2 +- .../modules/juce_core/maths/juce_Range.h | 9 +- .../modules/juce_core/memory/juce_Atomic.h | 4 +- .../modules/juce_core/memory/juce_ByteOrder.h | 56 +- .../memory/juce_ContainerDeletePolicy.h | 12 +- .../modules/juce_core/memory/juce_HeapBlock.h | 28 +- .../memory/juce_LeakedObjectDetector.h | 2 +- .../modules/juce_core/memory/juce_Memory.h | 24 +- .../juce_core/memory/juce_MemoryBlock.cpp | 10 +- .../juce_core/memory/juce_MemoryBlock.h | 2 +- .../memory/juce_OptionalScopedPointer.h | 2 +- .../memory/juce_ReferenceCountedObject.h | 4 +- .../juce_core/memory/juce_ScopedPointer.h | 10 +- .../memory/juce_SharedResourcePointer.h | 30 +- .../modules/juce_core/memory/juce_Singleton.h | 4 +- .../juce_core/memory/juce_WeakReference.h | 6 +- .../modules/juce_core/misc/juce_Result.cpp | 2 +- .../modules/juce_core/misc/juce_Result.h | 2 +- .../modules/juce_core/misc/juce_Uuid.cpp | 2 +- .../modules/juce_core/misc/juce_Uuid.h | 2 +- .../juce_core/misc/juce_WindowsRegistry.h | 2 +- .../native/java/JuceAppActivity.java | 258 ++- .../native/juce_BasicNativeHeaders.h | 2 +- .../juce_core/native/juce_android_Files.cpp | 2 +- .../native/juce_android_JNIHelpers.h | 50 +- .../juce_core/native/juce_android_Misc.cpp | 2 +- .../juce_core/native/juce_android_Network.cpp | 9 +- .../native/juce_android_SystemStats.cpp | 4 +- .../juce_core/native/juce_android_Threads.cpp | 2 +- .../native/juce_linux_CommonFile.cpp | 6 +- .../juce_core/native/juce_linux_Files.cpp | 5 +- .../juce_core/native/juce_linux_Network.cpp | 195 ++- .../native/juce_linux_SystemStats.cpp | 29 +- .../juce_core/native/juce_linux_Threads.cpp | 31 +- .../juce_core/native/juce_mac_Files.mm | 2 +- .../juce_core/native/juce_mac_Network.mm | 60 +- .../juce_core/native/juce_mac_Strings.mm | 20 +- .../juce_core/native/juce_mac_SystemStats.mm | 4 +- .../juce_core/native/juce_mac_Threads.mm | 2 +- .../juce_core/native/juce_osx_ObjCHelpers.h | 23 +- .../juce_core/native/juce_posix_NamedPipe.cpp | 2 +- .../juce_core/native/juce_posix_SharedCode.h | 116 +- .../juce_core/native/juce_win32_ComSmartPtr.h | 2 +- .../juce_core/native/juce_win32_Files.cpp | 54 +- .../juce_core/native/juce_win32_Network.cpp | 76 +- .../juce_core/native/juce_win32_Registry.cpp | 2 +- .../native/juce_win32_SystemStats.cpp | 48 +- .../juce_core/native/juce_win32_Threads.cpp | 4 +- .../juce_core/network/juce_IPAddress.cpp | 4 +- .../juce_core/network/juce_IPAddress.h | 2 +- .../juce_core/network/juce_MACAddress.cpp | 2 +- .../juce_core/network/juce_MACAddress.h | 2 +- .../juce_core/network/juce_NamedPipe.cpp | 2 +- .../juce_core/network/juce_NamedPipe.h | 2 +- .../modules/juce_core/network/juce_Socket.cpp | 427 +++-- .../modules/juce_core/network/juce_Socket.h | 120 +- .../modules/juce_core/network/juce_URL.cpp | 28 +- .../modules/juce_core/network/juce_URL.h | 28 +- .../streams/juce_BufferedInputStream.cpp | 2 +- .../streams/juce_BufferedInputStream.h | 2 +- .../streams/juce_FileInputSource.cpp | 2 +- .../juce_core/streams/juce_FileInputSource.h | 2 +- .../juce_core/streams/juce_InputSource.h | 2 +- .../juce_core/streams/juce_InputStream.cpp | 6 +- .../juce_core/streams/juce_InputStream.h | 8 +- .../streams/juce_MemoryInputStream.cpp | 6 +- .../streams/juce_MemoryInputStream.h | 2 +- .../streams/juce_MemoryOutputStream.cpp | 14 +- .../streams/juce_MemoryOutputStream.h | 8 +- .../juce_core/streams/juce_OutputStream.cpp | 6 +- .../juce_core/streams/juce_OutputStream.h | 4 +- .../streams/juce_SubregionStream.cpp | 2 +- .../juce_core/streams/juce_SubregionStream.h | 2 +- .../juce_core/system/juce_PlatformDefs.h | 136 +- .../juce_core/system/juce_StandardHeader.h | 17 +- .../juce_core/system/juce_SystemStats.cpp | 11 +- .../juce_core/system/juce_SystemStats.h | 46 +- .../juce_core/system/juce_TargetPlatform.h | 6 +- .../juce_core/text/juce_CharPointer_ASCII.h | 8 +- .../juce_core/text/juce_CharPointer_UTF16.h | 8 +- .../juce_core/text/juce_CharPointer_UTF32.h | 2 +- .../juce_core/text/juce_CharPointer_UTF8.h | 14 +- .../text/juce_CharacterFunctions.cpp | 18 +- .../juce_core/text/juce_CharacterFunctions.h | 2 +- .../juce_core/text/juce_Identifier.cpp | 29 +- .../modules/juce_core/text/juce_Identifier.h | 16 +- .../juce_core/text/juce_LocalisedStrings.cpp | 2 +- .../juce_core/text/juce_LocalisedStrings.h | 2 +- .../modules/juce_core/text/juce_NewLine.h | 2 +- .../modules/juce_core/text/juce_String.cpp | 149 +- .../modules/juce_core/text/juce_String.h | 28 +- .../juce_core/text/juce_StringArray.cpp | 29 +- .../modules/juce_core/text/juce_StringArray.h | 23 +- .../juce_core/text/juce_StringPairArray.cpp | 2 +- .../juce_core/text/juce_StringPairArray.h | 2 +- .../juce_core/text/juce_StringPool.cpp | 2 +- .../modules/juce_core/text/juce_StringPool.h | 4 +- .../modules/juce_core/text/juce_StringRef.h | 2 +- .../modules/juce_core/text/juce_TextDiff.cpp | 2 +- .../modules/juce_core/text/juce_TextDiff.h | 2 +- .../juce_core/threads/juce_ChildProcess.cpp | 2 +- .../juce_core/threads/juce_ChildProcess.h | 2 +- .../juce_core/threads/juce_CriticalSection.h | 2 +- .../juce_core/threads/juce_DynamicLibrary.h | 2 +- .../threads/juce_HighResolutionTimer.cpp | 2 +- .../threads/juce_HighResolutionTimer.h | 2 +- .../juce_core/threads/juce_InterProcessLock.h | 2 +- .../modules/juce_core/threads/juce_Process.h | 2 +- .../juce_core/threads/juce_ReadWriteLock.cpp | 2 +- .../juce_core/threads/juce_ReadWriteLock.h | 2 +- .../juce_core/threads/juce_ScopedLock.h | 2 +- .../juce_core/threads/juce_ScopedReadLock.h | 2 +- .../juce_core/threads/juce_ScopedWriteLock.h | 2 +- .../modules/juce_core/threads/juce_SpinLock.h | 2 +- .../modules/juce_core/threads/juce_Thread.cpp | 2 +- .../modules/juce_core/threads/juce_Thread.h | 4 +- .../juce_core/threads/juce_ThreadLocalValue.h | 2 +- .../juce_core/threads/juce_ThreadPool.cpp | 2 +- .../juce_core/threads/juce_ThreadPool.h | 2 +- .../threads/juce_TimeSliceThread.cpp | 2 +- .../juce_core/threads/juce_TimeSliceThread.h | 2 +- .../juce_core/threads/juce_WaitableEvent.h | 2 +- .../time/juce_PerformanceCounter.cpp | 2 +- .../juce_core/time/juce_PerformanceCounter.h | 2 +- .../juce_core/time/juce_RelativeTime.cpp | 2 +- .../juce_core/time/juce_RelativeTime.h | 2 +- .../modules/juce_core/time/juce_Time.cpp | 61 +- .../modules/juce_core/time/juce_Time.h | 34 +- .../juce_core/unit_tests/juce_UnitTest.cpp | 2 +- .../juce_core/unit_tests/juce_UnitTest.h | 2 +- .../juce_core/xml/juce_XmlDocument.cpp | 27 +- .../modules/juce_core/xml/juce_XmlDocument.h | 6 +- .../modules/juce_core/xml/juce_XmlElement.cpp | 6 +- .../modules/juce_core/xml/juce_XmlElement.h | 17 +- .../zip/juce_GZIPCompressorOutputStream.cpp | 2 +- .../zip/juce_GZIPCompressorOutputStream.h | 4 +- .../zip/juce_GZIPDecompressorInputStream.cpp | 37 +- .../zip/juce_GZIPDecompressorInputStream.h | 22 +- .../modules/juce_core/zip/juce_ZipFile.cpp | 23 +- .../modules/juce_core/zip/juce_ZipFile.h | 28 +- .../modules/juce_core/zip/zlib/trees.c | 32 +- .../juce_ApplicationProperties.cpp | 2 +- .../juce_ApplicationProperties.h | 2 +- .../app_properties/juce_PropertiesFile.cpp | 2 +- .../app_properties/juce_PropertiesFile.h | 4 +- .../juce_data_structures.cpp | 3 +- .../juce_data_structures.h | 3 +- .../juce_data_structures.mm | 2 +- .../juce_data_structures/juce_module_info | 2 +- .../undomanager/juce_UndoManager.cpp | 60 +- .../undomanager/juce_UndoManager.h | 54 +- .../undomanager/juce_UndoableAction.h | 2 +- .../values/juce_Value.cpp | 43 +- .../juce_data_structures/values/juce_Value.h | 13 +- .../values/juce_ValueTree.cpp | 203 ++- .../values/juce_ValueTree.h | 46 +- .../broadcasters/juce_ActionBroadcaster.cpp | 11 +- .../broadcasters/juce_ActionBroadcaster.h | 2 +- .../broadcasters/juce_ActionListener.h | 2 +- .../broadcasters/juce_AsyncUpdater.cpp | 6 +- .../broadcasters/juce_AsyncUpdater.h | 2 +- .../broadcasters/juce_ChangeBroadcaster.cpp | 2 +- .../broadcasters/juce_ChangeBroadcaster.h | 2 +- .../broadcasters/juce_ChangeListener.h | 2 +- .../broadcasters/juce_ListenerList.h | 2 +- .../juce_ConnectedChildProcess.cpp | 27 +- .../interprocess/juce_ConnectedChildProcess.h | 18 +- .../juce_InterprocessConnection.cpp | 46 +- .../juce_InterprocessConnection.h | 3 +- .../juce_InterprocessConnectionServer.cpp | 2 +- .../juce_InterprocessConnectionServer.h | 2 +- .../modules/juce_events/juce_events.cpp | 2 +- .../modules/juce_events/juce_events.h | 3 +- .../modules/juce_events/juce_events.mm | 2 +- .../modules/juce_events/juce_module_info | 2 +- .../messages/juce_ApplicationBase.cpp | 15 +- .../messages/juce_ApplicationBase.h | 13 +- .../messages/juce_CallbackMessage.h | 2 +- .../messages/juce_DeletedAtShutdown.cpp | 2 +- .../messages/juce_DeletedAtShutdown.h | 2 +- .../messages/juce_Initialisation.h | 18 +- .../juce_events/messages/juce_Message.h | 2 +- .../messages/juce_MessageListener.cpp | 2 +- .../messages/juce_MessageListener.h | 2 +- .../messages/juce_MessageManager.cpp | 69 +- .../messages/juce_MessageManager.h | 11 +- .../messages/juce_NotificationType.h | 2 +- .../juce_events/native/juce_ScopedXLock.h | 2 +- .../native/juce_android_Messaging.cpp | 4 +- .../native/juce_ios_MessageManager.mm | 14 +- .../native/juce_linux_Messaging.cpp | 26 +- .../native/juce_mac_MessageManager.mm | 110 +- .../native/juce_osx_MessageQueue.h | 2 +- .../native/juce_win32_HiddenMessageWindow.h | 3 +- .../native/juce_win32_Messaging.cpp | 46 +- .../juce_events/timers/juce_MultiTimer.cpp | 2 +- .../juce_events/timers/juce_MultiTimer.h | 2 +- .../modules/juce_events/timers/juce_Timer.cpp | 94 +- .../modules/juce_events/timers/juce_Timer.h | 31 +- .../juce_graphics/colour/juce_Colour.cpp | 41 +- .../juce_graphics/colour/juce_Colour.h | 15 +- .../colour/juce_ColourGradient.cpp | 14 +- .../colour/juce_ColourGradient.h | 2 +- .../juce_graphics/colour/juce_Colours.cpp | 2 +- .../juce_graphics/colour/juce_Colours.h | 2 +- .../juce_graphics/colour/juce_FillType.cpp | 2 +- .../juce_graphics/colour/juce_FillType.h | 2 +- .../juce_graphics/colour/juce_PixelFormats.h | 464 ++++-- .../contexts/juce_GraphicsContext.cpp | 8 +- .../contexts/juce_GraphicsContext.h | 24 +- .../contexts/juce_LowLevelGraphicsContext.h | 2 +- ...uce_LowLevelGraphicsPostScriptRenderer.cpp | 10 +- .../juce_LowLevelGraphicsPostScriptRenderer.h | 2 +- .../juce_LowLevelGraphicsSoftwareRenderer.cpp | 2 +- .../juce_LowLevelGraphicsSoftwareRenderer.h | 2 +- .../effects/juce_DropShadowEffect.cpp | 20 +- .../effects/juce_DropShadowEffect.h | 2 +- .../juce_graphics/effects/juce_GlowEffect.cpp | 2 +- .../juce_graphics/effects/juce_GlowEffect.h | 2 +- .../effects/juce_ImageEffectFilter.h | 2 +- .../fonts/juce_AttributedString.cpp | 2 +- .../fonts/juce_AttributedString.h | 2 +- .../fonts/juce_CustomTypeface.cpp | 2 +- .../juce_graphics/fonts/juce_CustomTypeface.h | 2 +- .../modules/juce_graphics/fonts/juce_Font.cpp | 14 +- .../modules/juce_graphics/fonts/juce_Font.h | 22 +- .../fonts/juce_GlyphArrangement.cpp | 419 +++-- .../fonts/juce_GlyphArrangement.h | 32 +- .../juce_graphics/fonts/juce_TextLayout.cpp | 155 +- .../juce_graphics/fonts/juce_TextLayout.h | 37 +- .../juce_graphics/fonts/juce_Typeface.cpp | 2 +- .../juce_graphics/fonts/juce_Typeface.h | 2 +- .../geometry/juce_AffineTransform.cpp | 14 +- .../geometry/juce_AffineTransform.h | 29 +- .../juce_graphics/geometry/juce_BorderSize.h | 2 +- .../juce_graphics/geometry/juce_EdgeTable.cpp | 2 +- .../juce_graphics/geometry/juce_EdgeTable.h | 2 +- .../juce_graphics/geometry/juce_Line.h | 28 +- .../juce_graphics/geometry/juce_Path.cpp | 45 +- .../juce_graphics/geometry/juce_Path.h | 44 +- .../geometry/juce_PathIterator.cpp | 2 +- .../geometry/juce_PathIterator.h | 2 +- .../geometry/juce_PathStrokeType.cpp | 2 +- .../geometry/juce_PathStrokeType.h | 2 +- .../juce_graphics/geometry/juce_Point.h | 8 +- .../juce_graphics/geometry/juce_Rectangle.h | 124 +- .../geometry/juce_RectangleList.h | 27 +- .../image_formats/jpglib/jinclude.h | 13 +- .../image_formats/juce_GIFLoader.cpp | 2 +- .../image_formats/juce_JPEGLoader.cpp | 2 +- .../image_formats/juce_PNGLoader.cpp | 9 +- .../image_formats/pnglib/pngread.c | 2 +- .../juce_graphics/images/juce_Image.cpp | 29 +- .../modules/juce_graphics/images/juce_Image.h | 13 +- .../juce_graphics/images/juce_ImageCache.cpp | 6 +- .../juce_graphics/images/juce_ImageCache.h | 2 +- .../images/juce_ImageConvolutionKernel.cpp | 2 +- .../images/juce_ImageConvolutionKernel.h | 2 +- .../images/juce_ImageFileFormat.cpp | 2 +- .../images/juce_ImageFileFormat.h | 2 +- .../modules/juce_graphics/juce_graphics.cpp | 12 +- .../modules/juce_graphics/juce_graphics.h | 2 +- .../modules/juce_graphics/juce_graphics.mm | 2 +- .../modules/juce_graphics/juce_module_info | 2 +- .../native/juce_RenderingHelpers.h | 49 +- .../native/juce_android_Fonts.cpp | 56 +- .../native/juce_android_GraphicsContext.cpp | 2 +- .../native/juce_freetype_Fonts.cpp | 18 +- .../juce_graphics/native/juce_linux_Fonts.cpp | 2 +- .../native/juce_mac_CoreGraphicsContext.h | 18 +- .../native/juce_mac_CoreGraphicsContext.mm | 141 +- .../native/juce_mac_CoreGraphicsHelpers.h | 10 +- .../juce_graphics/native/juce_mac_Fonts.mm | 4 +- .../juce_win32_Direct2DGraphicsContext.cpp | 2 +- .../juce_win32_DirectWriteTypeLayout.cpp | 62 +- .../native/juce_win32_DirectWriteTypeface.cpp | 32 +- .../juce_graphics/native/juce_win32_Fonts.cpp | 6 +- .../placement/juce_Justification.h | 2 +- .../placement/juce_RectanglePlacement.cpp | 2 +- .../placement/juce_RectanglePlacement.h | 2 +- .../application/juce_Application.cpp | 2 +- .../application/juce_Application.h | 20 +- .../buttons/juce_ArrowButton.cpp | 2 +- .../buttons/juce_ArrowButton.h | 2 +- .../juce_gui_basics/buttons/juce_Button.cpp | 14 +- .../juce_gui_basics/buttons/juce_Button.h | 12 +- .../buttons/juce_DrawableButton.cpp | 61 +- .../buttons/juce_DrawableButton.h | 9 +- .../buttons/juce_HyperlinkButton.cpp | 2 +- .../buttons/juce_HyperlinkButton.h | 2 +- .../buttons/juce_ImageButton.cpp | 2 +- .../buttons/juce_ImageButton.h | 2 +- .../buttons/juce_ShapeButton.cpp | 2 +- .../buttons/juce_ShapeButton.h | 2 +- .../buttons/juce_TextButton.cpp | 5 +- .../juce_gui_basics/buttons/juce_TextButton.h | 4 +- .../buttons/juce_ToggleButton.cpp | 2 +- .../buttons/juce_ToggleButton.h | 2 +- .../buttons/juce_ToolbarButton.cpp | 2 +- .../buttons/juce_ToolbarButton.h | 2 +- .../commands/juce_ApplicationCommandID.h | 2 +- .../commands/juce_ApplicationCommandInfo.cpp | 2 +- .../commands/juce_ApplicationCommandInfo.h | 2 +- .../juce_ApplicationCommandManager.cpp | 41 +- .../commands/juce_ApplicationCommandManager.h | 5 +- .../juce_ApplicationCommandTarget.cpp | 2 +- .../commands/juce_ApplicationCommandTarget.h | 2 +- .../commands/juce_KeyPressMappingSet.cpp | 4 +- .../commands/juce_KeyPressMappingSet.h | 2 +- .../components/juce_CachedComponentImage.h | 2 +- .../components/juce_Component.cpp | 231 ++- .../components/juce_Component.h | 177 +- .../components/juce_ComponentListener.cpp | 2 +- .../components/juce_ComponentListener.h | 2 +- .../components/juce_Desktop.cpp | 34 +- .../juce_gui_basics/components/juce_Desktop.h | 8 +- .../components/juce_ModalComponentManager.cpp | 4 +- .../components/juce_ModalComponentManager.h | 8 +- .../drawables/juce_Drawable.cpp | 2 +- .../juce_gui_basics/drawables/juce_Drawable.h | 9 +- .../drawables/juce_DrawableComposite.cpp | 2 +- .../drawables/juce_DrawableComposite.h | 10 +- .../drawables/juce_DrawableImage.cpp | 3 +- .../drawables/juce_DrawableImage.h | 2 +- .../drawables/juce_DrawablePath.cpp | 8 +- .../drawables/juce_DrawablePath.h | 2 +- .../drawables/juce_DrawableRectangle.cpp | 2 +- .../drawables/juce_DrawableRectangle.h | 2 +- .../drawables/juce_DrawableShape.cpp | 8 +- .../drawables/juce_DrawableShape.h | 2 +- .../drawables/juce_DrawableText.cpp | 2 +- .../drawables/juce_DrawableText.h | 2 +- .../drawables/juce_SVGParser.cpp | 251 +-- ...juce_DirectoryContentsDisplayComponent.cpp | 2 +- .../juce_DirectoryContentsDisplayComponent.h | 2 +- .../juce_DirectoryContentsList.cpp | 7 +- .../filebrowser/juce_DirectoryContentsList.h | 2 +- .../filebrowser/juce_FileBrowserComponent.cpp | 13 +- .../filebrowser/juce_FileBrowserComponent.h | 27 +- .../filebrowser/juce_FileBrowserListener.h | 2 +- .../filebrowser/juce_FileChooser.cpp | 4 +- .../filebrowser/juce_FileChooser.h | 2 +- .../filebrowser/juce_FileChooserDialogBox.cpp | 2 +- .../filebrowser/juce_FileChooserDialogBox.h | 2 +- .../filebrowser/juce_FileListComponent.cpp | 2 +- .../filebrowser/juce_FileListComponent.h | 14 +- .../filebrowser/juce_FilePreviewComponent.h | 2 +- .../juce_FileSearchPathListComponent.cpp | 4 +- .../juce_FileSearchPathListComponent.h | 2 +- .../filebrowser/juce_FileTreeComponent.cpp | 2 +- .../filebrowser/juce_FileTreeComponent.h | 2 +- .../filebrowser/juce_FilenameComponent.cpp | 9 +- .../filebrowser/juce_FilenameComponent.h | 5 +- .../juce_ImagePreviewComponent.cpp | 2 +- .../filebrowser/juce_ImagePreviewComponent.h | 2 +- .../juce_gui_basics/juce_gui_basics.cpp | 15 +- .../modules/juce_gui_basics/juce_gui_basics.h | 14 +- .../juce_gui_basics/juce_gui_basics.mm | 2 +- .../modules/juce_gui_basics/juce_module_info | 2 +- .../keyboard/juce_CaretComponent.cpp | 2 +- .../keyboard/juce_CaretComponent.h | 2 +- .../keyboard/juce_KeyListener.cpp | 2 +- .../keyboard/juce_KeyListener.h | 2 +- .../keyboard/juce_KeyPress.cpp | 2 +- .../juce_gui_basics/keyboard/juce_KeyPress.h | 2 +- .../keyboard/juce_KeyboardFocusTraverser.cpp | 2 +- .../keyboard/juce_KeyboardFocusTraverser.h | 2 +- .../keyboard/juce_ModifierKeys.cpp | 2 +- .../keyboard/juce_ModifierKeys.h | 2 +- .../keyboard/juce_SystemClipboard.h | 2 +- .../keyboard/juce_TextEditorKeyMapper.h | 15 +- .../keyboard/juce_TextInputTarget.h | 3 +- .../layout/juce_AnimatedPosition.h | 8 +- .../layout/juce_AnimatedPositionBehaviours.h | 2 +- .../layout/juce_ComponentAnimator.cpp | 38 +- .../layout/juce_ComponentAnimator.h | 6 +- .../juce_ComponentBoundsConstrainer.cpp | 2 +- .../layout/juce_ComponentBoundsConstrainer.h | 2 +- .../layout/juce_ComponentBuilder.cpp | 8 +- .../layout/juce_ComponentBuilder.h | 8 +- .../layout/juce_ComponentMovementWatcher.cpp | 2 +- .../layout/juce_ComponentMovementWatcher.h | 2 +- .../layout/juce_ConcertinaPanel.cpp | 7 +- .../layout/juce_ConcertinaPanel.h | 7 +- .../layout/juce_GroupComponent.cpp | 2 +- .../layout/juce_GroupComponent.h | 2 +- .../layout/juce_MultiDocumentPanel.cpp | 2 +- .../layout/juce_MultiDocumentPanel.h | 2 +- .../layout/juce_ResizableBorderComponent.cpp | 2 +- .../layout/juce_ResizableBorderComponent.h | 2 +- .../layout/juce_ResizableCornerComponent.cpp | 2 +- .../layout/juce_ResizableCornerComponent.h | 2 +- .../layout/juce_ResizableEdgeComponent.cpp | 2 +- .../layout/juce_ResizableEdgeComponent.h | 2 +- .../juce_gui_basics/layout/juce_ScrollBar.cpp | 17 +- .../juce_gui_basics/layout/juce_ScrollBar.h | 5 +- .../layout/juce_StretchableLayoutManager.cpp | 2 +- .../layout/juce_StretchableLayoutManager.h | 2 +- .../juce_StretchableLayoutResizerBar.cpp | 2 +- .../layout/juce_StretchableLayoutResizerBar.h | 2 +- .../layout/juce_StretchableObjectResizer.cpp | 2 +- .../layout/juce_StretchableObjectResizer.h | 2 +- .../layout/juce_TabbedButtonBar.cpp | 6 +- .../layout/juce_TabbedButtonBar.h | 4 +- .../layout/juce_TabbedComponent.cpp | 2 +- .../layout/juce_TabbedComponent.h | 2 +- .../juce_gui_basics/layout/juce_Viewport.cpp | 61 +- .../juce_gui_basics/layout/juce_Viewport.h | 6 +- .../lookandfeel/juce_LookAndFeel.cpp | 2 +- .../lookandfeel/juce_LookAndFeel.h | 2 +- .../lookandfeel/juce_LookAndFeel_V1.cpp | 2 +- .../lookandfeel/juce_LookAndFeel_V1.h | 2 +- .../lookandfeel/juce_LookAndFeel_V2.cpp | 114 +- .../lookandfeel/juce_LookAndFeel_V2.h | 24 +- .../lookandfeel/juce_LookAndFeel_V3.cpp | 2 +- .../lookandfeel/juce_LookAndFeel_V3.h | 2 +- .../menus/juce_MenuBarComponent.cpp | 32 +- .../menus/juce_MenuBarComponent.h | 13 +- .../menus/juce_MenuBarModel.cpp | 2 +- .../juce_gui_basics/menus/juce_MenuBarModel.h | 16 +- .../juce_gui_basics/menus/juce_PopupMenu.cpp | 22 +- .../juce_gui_basics/menus/juce_PopupMenu.h | 5 +- .../misc/juce_BubbleComponent.cpp | 2 +- .../misc/juce_BubbleComponent.h | 2 +- .../misc/juce_DropShadower.cpp | 2 +- .../juce_gui_basics/misc/juce_DropShadower.h | 2 +- .../mouse/juce_ComponentDragger.cpp | 4 +- .../mouse/juce_ComponentDragger.h | 2 +- .../mouse/juce_DragAndDropContainer.cpp | 72 +- .../mouse/juce_DragAndDropContainer.h | 11 +- .../mouse/juce_DragAndDropTarget.h | 2 +- .../mouse/juce_FileDragAndDropTarget.h | 2 +- .../mouse/juce_LassoComponent.h | 2 +- .../mouse/juce_MouseCursor.cpp | 4 +- .../juce_gui_basics/mouse/juce_MouseCursor.h | 6 +- .../juce_gui_basics/mouse/juce_MouseEvent.cpp | 38 +- .../juce_gui_basics/mouse/juce_MouseEvent.h | 40 +- .../mouse/juce_MouseInactivityDetector.cpp | 13 +- .../mouse/juce_MouseInactivityDetector.h | 11 +- .../mouse/juce_MouseInputSource.cpp | 182 +- .../mouse/juce_MouseInputSource.h | 18 +- .../mouse/juce_MouseListener.cpp | 2 +- .../mouse/juce_MouseListener.h | 2 +- .../mouse/juce_SelectedItemSet.h | 4 +- .../mouse/juce_TextDragAndDropTarget.h | 2 +- .../mouse/juce_TooltipClient.h | 2 +- .../native/juce_MultiTouchMapper.h | 2 +- .../native/juce_android_FileChooser.cpp | 2 +- .../native/juce_android_Windowing.cpp | 82 +- .../native/juce_ios_UIViewComponentPeer.mm | 157 +- .../native/juce_ios_Windowing.mm | 41 +- .../native/juce_linux_Clipboard.cpp | 233 +-- .../native/juce_linux_FileChooser.cpp | 203 ++- .../native/juce_linux_Windowing.cpp | 1471 +++++++++++++---- .../native/juce_mac_FileChooser.mm | 64 +- .../native/juce_mac_MainMenu.mm | 2 +- .../native/juce_mac_MouseCursor.mm | 81 +- .../native/juce_mac_NSViewComponentPeer.mm | 166 +- .../native/juce_mac_Windowing.mm | 146 +- .../native/juce_win32_DragAndDrop.cpp | 2 +- .../native/juce_win32_FileChooser.cpp | 6 +- .../native/juce_win32_Windowing.cpp | 234 ++- .../positioning/juce_MarkerList.cpp | 2 +- .../positioning/juce_MarkerList.h | 2 +- .../positioning/juce_RelativeCoordinate.cpp | 2 +- .../positioning/juce_RelativeCoordinate.h | 37 +- .../juce_RelativeCoordinatePositioner.cpp | 2 +- .../juce_RelativeCoordinatePositioner.h | 2 +- .../juce_RelativeParallelogram.cpp | 2 +- .../positioning/juce_RelativeParallelogram.h | 2 +- .../positioning/juce_RelativePoint.cpp | 2 +- .../positioning/juce_RelativePoint.h | 2 +- .../positioning/juce_RelativePointPath.cpp | 2 +- .../positioning/juce_RelativePointPath.h | 2 +- .../positioning/juce_RelativeRectangle.cpp | 10 +- .../positioning/juce_RelativeRectangle.h | 9 +- .../juce_BooleanPropertyComponent.cpp | 4 +- .../juce_BooleanPropertyComponent.h | 20 +- .../juce_ButtonPropertyComponent.cpp | 2 +- .../properties/juce_ButtonPropertyComponent.h | 2 +- .../juce_ChoicePropertyComponent.cpp | 2 +- .../properties/juce_ChoicePropertyComponent.h | 10 +- .../properties/juce_PropertyComponent.cpp | 2 +- .../properties/juce_PropertyComponent.h | 4 +- .../properties/juce_PropertyPanel.cpp | 150 +- .../properties/juce_PropertyPanel.h | 22 +- .../juce_SliderPropertyComponent.cpp | 2 +- .../properties/juce_SliderPropertyComponent.h | 6 +- .../properties/juce_TextPropertyComponent.cpp | 2 +- .../properties/juce_TextPropertyComponent.h | 2 +- .../juce_gui_basics/widgets/juce_ComboBox.cpp | 100 +- .../juce_gui_basics/widgets/juce_ComboBox.h | 32 +- .../widgets/juce_ImageComponent.cpp | 2 +- .../widgets/juce_ImageComponent.h | 2 +- .../juce_gui_basics/widgets/juce_Label.cpp | 38 +- .../juce_gui_basics/widgets/juce_Label.h | 32 +- .../juce_gui_basics/widgets/juce_ListBox.cpp | 87 +- .../juce_gui_basics/widgets/juce_ListBox.h | 59 +- .../widgets/juce_ProgressBar.cpp | 2 +- .../widgets/juce_ProgressBar.h | 2 +- .../juce_gui_basics/widgets/juce_Slider.cpp | 277 ++-- .../juce_gui_basics/widgets/juce_Slider.h | 46 +- .../widgets/juce_TableHeaderComponent.cpp | 2 +- .../widgets/juce_TableHeaderComponent.h | 9 +- .../widgets/juce_TableListBox.cpp | 46 +- .../widgets/juce_TableListBox.h | 56 +- .../widgets/juce_TextEditor.cpp | 17 +- .../juce_gui_basics/widgets/juce_TextEditor.h | 17 +- .../juce_gui_basics/widgets/juce_Toolbar.cpp | 30 +- .../juce_gui_basics/widgets/juce_Toolbar.h | 8 +- .../widgets/juce_ToolbarItemComponent.cpp | 2 +- .../widgets/juce_ToolbarItemComponent.h | 2 +- .../widgets/juce_ToolbarItemFactory.h | 2 +- .../widgets/juce_ToolbarItemPalette.cpp | 2 +- .../widgets/juce_ToolbarItemPalette.h | 2 +- .../juce_gui_basics/widgets/juce_TreeView.cpp | 33 +- .../juce_gui_basics/widgets/juce_TreeView.h | 18 +- .../windows/juce_AlertWindow.cpp | 39 +- .../windows/juce_AlertWindow.h | 13 +- .../windows/juce_CallOutBox.cpp | 16 +- .../juce_gui_basics/windows/juce_CallOutBox.h | 14 +- .../windows/juce_ComponentPeer.cpp | 56 +- .../windows/juce_ComponentPeer.h | 22 +- .../windows/juce_DialogWindow.cpp | 2 +- .../windows/juce_DialogWindow.h | 16 +- .../windows/juce_DocumentWindow.cpp | 2 +- .../windows/juce_DocumentWindow.h | 4 +- .../windows/juce_NativeMessageBox.h | 2 +- .../windows/juce_ResizableWindow.cpp | 44 +- .../windows/juce_ResizableWindow.h | 20 +- .../windows/juce_ThreadWithProgressWindow.cpp | 2 +- .../windows/juce_ThreadWithProgressWindow.h | 2 +- .../windows/juce_TooltipWindow.cpp | 81 +- .../windows/juce_TooltipWindow.h | 30 +- .../windows/juce_TopLevelWindow.cpp | 4 +- .../windows/juce_TopLevelWindow.h | 6 +- .../juce_CPlusPlusCodeTokeniser.cpp | 2 +- .../code_editor/juce_CPlusPlusCodeTokeniser.h | 2 +- .../juce_CPlusPlusCodeTokeniserFunctions.h | 102 +- .../code_editor/juce_CodeDocument.cpp | 20 +- .../code_editor/juce_CodeDocument.h | 2 +- .../code_editor/juce_CodeEditorComponent.cpp | 24 +- .../code_editor/juce_CodeEditorComponent.h | 2 +- .../code_editor/juce_CodeTokeniser.h | 2 +- .../code_editor/juce_LuaCodeTokeniser.cpp | 2 +- .../code_editor/juce_LuaCodeTokeniser.h | 2 +- .../code_editor/juce_XMLCodeTokeniser.cpp | 2 +- .../code_editor/juce_XMLCodeTokeniser.h | 2 +- .../documents/juce_FileBasedDocument.cpp | 2 +- .../documents/juce_FileBasedDocument.h | 2 +- .../embedding/juce_ActiveXControlComponent.h | 2 +- .../embedding/juce_NSViewComponent.h | 2 +- .../embedding/juce_UIViewComponent.h | 2 +- .../modules/juce_gui_extra/juce_gui_extra.cpp | 9 +- .../modules/juce_gui_extra/juce_gui_extra.h | 3 +- .../modules/juce_gui_extra/juce_gui_extra.mm | 2 +- .../modules/juce_gui_extra/juce_module_info | 2 +- .../juce_gui_extra/misc/juce_AppleRemote.h | 2 +- .../misc/juce_BubbleMessageComponent.cpp | 2 +- .../misc/juce_BubbleMessageComponent.h | 2 +- .../misc/juce_ColourSelector.cpp | 2 +- .../juce_gui_extra/misc/juce_ColourSelector.h | 6 +- .../misc/juce_KeyMappingEditorComponent.cpp | 6 +- .../misc/juce_KeyMappingEditorComponent.h | 4 +- .../misc/juce_LiveConstantEditor.cpp | 68 +- .../misc/juce_LiveConstantEditor.h | 15 +- .../misc/juce_PreferencesPanel.cpp | 2 +- .../misc/juce_PreferencesPanel.h | 2 +- .../misc/juce_RecentlyOpenedFilesList.cpp | 2 +- .../misc/juce_RecentlyOpenedFilesList.h | 2 +- .../juce_gui_extra/misc/juce_SplashScreen.cpp | 2 +- .../juce_gui_extra/misc/juce_SplashScreen.h | 2 +- .../misc/juce_SystemTrayIconComponent.cpp | 2 +- .../misc/juce_SystemTrayIconComponent.h | 2 +- .../misc/juce_WebBrowserComponent.h | 10 +- .../juce_android_WebBrowserComponent.cpp | 6 +- .../native/juce_ios_UIViewComponent.mm | 2 +- .../native/juce_linux_SystemTrayIcon.cpp | 6 +- .../native/juce_linux_WebBrowserComponent.cpp | 6 +- .../native/juce_mac_AppleRemote.mm | 2 +- .../juce_mac_CarbonViewWrapperComponent.h | 2 +- .../native/juce_mac_NSViewComponent.mm | 9 +- .../native/juce_mac_SystemTrayIcon.cpp | 45 +- .../native/juce_mac_WebBrowserComponent.mm | 126 +- .../native/juce_win32_ActiveXComponent.cpp | 4 +- .../native/juce_win32_SystemTrayIcon.cpp | 6 +- .../native/juce_win32_WebBrowserComponent.cpp | 57 +- 851 files changed, 13485 insertions(+), 7821 deletions(-) diff --git a/JuceLibraryCode/modules/juce_audio_basics/buffers/juce_AudioDataConverters.cpp b/JuceLibraryCode/modules/juce_audio_basics/buffers/juce_AudioDataConverters.cpp index 95d228e..a2a033e 100644 --- a/JuceLibraryCode/modules/juce_audio_basics/buffers/juce_AudioDataConverters.cpp +++ b/JuceLibraryCode/modules/juce_audio_basics/buffers/juce_AudioDataConverters.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -25,7 +25,7 @@ void AudioDataConverters::convertFloatToInt16LE (const float* source, void* dest, int numSamples, const int destBytesPerSample) { const double maxVal = (double) 0x7fff; - char* intData = static_cast (dest); + char* intData = static_cast (dest); if (dest != (void*) source || destBytesPerSample <= 4) { @@ -50,7 +50,7 @@ void AudioDataConverters::convertFloatToInt16LE (const float* source, void* dest void AudioDataConverters::convertFloatToInt16BE (const float* source, void* dest, int numSamples, const int destBytesPerSample) { const double maxVal = (double) 0x7fff; - char* intData = static_cast (dest); + char* intData = static_cast (dest); if (dest != (void*) source || destBytesPerSample <= 4) { @@ -75,7 +75,7 @@ void AudioDataConverters::convertFloatToInt16BE (const float* source, void* dest void AudioDataConverters::convertFloatToInt24LE (const float* source, void* dest, int numSamples, const int destBytesPerSample) { const double maxVal = (double) 0x7fffff; - char* intData = static_cast (dest); + char* intData = static_cast (dest); if (dest != (void*) source || destBytesPerSample <= 4) { @@ -100,7 +100,7 @@ void AudioDataConverters::convertFloatToInt24LE (const float* source, void* dest void AudioDataConverters::convertFloatToInt24BE (const float* source, void* dest, int numSamples, const int destBytesPerSample) { const double maxVal = (double) 0x7fffff; - char* intData = static_cast (dest); + char* intData = static_cast (dest); if (dest != (void*) source || destBytesPerSample <= 4) { @@ -125,7 +125,7 @@ void AudioDataConverters::convertFloatToInt24BE (const float* source, void* dest void AudioDataConverters::convertFloatToInt32LE (const float* source, void* dest, int numSamples, const int destBytesPerSample) { const double maxVal = (double) 0x7fffffff; - char* intData = static_cast (dest); + char* intData = static_cast (dest); if (dest != (void*) source || destBytesPerSample <= 4) { @@ -150,7 +150,7 @@ void AudioDataConverters::convertFloatToInt32LE (const float* source, void* dest void AudioDataConverters::convertFloatToInt32BE (const float* source, void* dest, int numSamples, const int destBytesPerSample) { const double maxVal = (double) 0x7fffffff; - char* intData = static_cast (dest); + char* intData = static_cast (dest); if (dest != (void*) source || destBytesPerSample <= 4) { @@ -176,7 +176,7 @@ void AudioDataConverters::convertFloatToFloat32LE (const float* source, void* de { jassert (dest != (void*) source || destBytesPerSample <= 4); // This op can't be performed on in-place data! - char* d = static_cast (dest); + char* d = static_cast (dest); for (int i = 0; i < numSamples; ++i) { @@ -194,7 +194,7 @@ void AudioDataConverters::convertFloatToFloat32BE (const float* source, void* de { jassert (dest != (void*) source || destBytesPerSample <= 4); // This op can't be performed on in-place data! - char* d = static_cast (dest); + char* d = static_cast (dest); for (int i = 0; i < numSamples; ++i) { @@ -212,7 +212,7 @@ void AudioDataConverters::convertFloatToFloat32BE (const float* source, void* de void AudioDataConverters::convertInt16LEToFloat (const void* const source, float* const dest, int numSamples, const int srcBytesPerSample) { const float scale = 1.0f / 0x7fff; - const char* intData = static_cast (source); + const char* intData = static_cast (source); if (source != (void*) dest || srcBytesPerSample >= 4) { @@ -237,7 +237,7 @@ void AudioDataConverters::convertInt16LEToFloat (const void* const source, float void AudioDataConverters::convertInt16BEToFloat (const void* const source, float* const dest, int numSamples, const int srcBytesPerSample) { const float scale = 1.0f / 0x7fff; - const char* intData = static_cast (source); + const char* intData = static_cast (source); if (source != (void*) dest || srcBytesPerSample >= 4) { @@ -262,7 +262,7 @@ void AudioDataConverters::convertInt16BEToFloat (const void* const source, float void AudioDataConverters::convertInt24LEToFloat (const void* const source, float* const dest, int numSamples, const int srcBytesPerSample) { const float scale = 1.0f / 0x7fffff; - const char* intData = static_cast (source); + const char* intData = static_cast (source); if (source != (void*) dest || srcBytesPerSample >= 4) { @@ -287,7 +287,7 @@ void AudioDataConverters::convertInt24LEToFloat (const void* const source, float void AudioDataConverters::convertInt24BEToFloat (const void* const source, float* const dest, int numSamples, const int srcBytesPerSample) { const float scale = 1.0f / 0x7fffff; - const char* intData = static_cast (source); + const char* intData = static_cast (source); if (source != (void*) dest || srcBytesPerSample >= 4) { @@ -312,7 +312,7 @@ void AudioDataConverters::convertInt24BEToFloat (const void* const source, float void AudioDataConverters::convertInt32LEToFloat (const void* const source, float* const dest, int numSamples, const int srcBytesPerSample) { const float scale = 1.0f / 0x7fffffff; - const char* intData = static_cast (source); + const char* intData = static_cast (source); if (source != (void*) dest || srcBytesPerSample >= 4) { @@ -337,7 +337,7 @@ void AudioDataConverters::convertInt32LEToFloat (const void* const source, float void AudioDataConverters::convertInt32BEToFloat (const void* const source, float* const dest, int numSamples, const int srcBytesPerSample) { const float scale = 1.0f / 0x7fffffff; - const char* intData = static_cast (source); + const char* intData = static_cast (source); if (source != (void*) dest || srcBytesPerSample >= 4) { @@ -361,7 +361,7 @@ void AudioDataConverters::convertInt32BEToFloat (const void* const source, float void AudioDataConverters::convertFloat32LEToFloat (const void* const source, float* const dest, int numSamples, const int srcBytesPerSample) { - const char* s = static_cast (source); + const char* s = static_cast (source); for (int i = 0; i < numSamples; ++i) { @@ -378,7 +378,7 @@ void AudioDataConverters::convertFloat32LEToFloat (const void* const source, flo void AudioDataConverters::convertFloat32BEToFloat (const void* const source, float* const dest, int numSamples, const int srcBytesPerSample) { - const char* s = static_cast (source); + const char* s = static_cast (source); for (int i = 0; i < numSamples; ++i) { diff --git a/JuceLibraryCode/modules/juce_audio_basics/buffers/juce_AudioDataConverters.h b/JuceLibraryCode/modules/juce_audio_basics/buffers/juce_AudioDataConverters.h index b3f49a6..e11c6c1 100644 --- a/JuceLibraryCode/modules/juce_audio_basics/buffers/juce_AudioDataConverters.h +++ b/JuceLibraryCode/modules/juce_audio_basics/buffers/juce_AudioDataConverters.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -487,13 +487,10 @@ public: } /** Scans a block of data, returning the lowest and highest levels as floats */ - void findMinAndMax (size_t numSamples, float& minValue, float& maxValue) const noexcept + Range findMinAndMax (size_t numSamples) const noexcept { if (numSamples == 0) - { - minValue = maxValue = 0; - return; - } + return Range(); Pointer dest (*this); @@ -512,27 +509,32 @@ public: if (v < mn) mn = v; } - minValue = mn; - maxValue = mx; + return Range (mn, mx); } - else + + int32 mn = dest.getAsInt32(); + dest.advance(); + int32 mx = mn; + + while (--numSamples > 0) { - int32 mn = dest.getAsInt32(); + const int v = dest.getAsInt32(); dest.advance(); - int32 mx = mn; - while (--numSamples > 0) - { - const int v = dest.getAsInt32(); - dest.advance(); - - if (mx < v) mx = v; - if (v < mn) mn = v; - } - - minValue = mn * (float) (1.0 / (1.0 + Int32::maxValue)); - maxValue = mx * (float) (1.0 / (1.0 + Int32::maxValue)); + if (mx < v) mx = v; + if (v < mn) mn = v; } + + return Range (mn * (float) (1.0 / (1.0 + Int32::maxValue)), + mx * (float) (1.0 / (1.0 + Int32::maxValue))); + } + + /** Scans a block of data, returning the lowest and highest levels as floats */ + void findMinAndMax (size_t numSamples, float& minValue, float& maxValue) const noexcept + { + Range r (findMinAndMax (numSamples)); + minValue = r.getStart(); + maxValue = r.getEnd(); } /** Returns true if the pointer is using a floating-point format. */ diff --git a/JuceLibraryCode/modules/juce_audio_basics/buffers/juce_AudioSampleBuffer.cpp b/JuceLibraryCode/modules/juce_audio_basics/buffers/juce_AudioSampleBuffer.cpp index 72d7f0d..e9fd6e0 100644 --- a/JuceLibraryCode/modules/juce_audio_basics/buffers/juce_AudioSampleBuffer.cpp +++ b/JuceLibraryCode/modules/juce_audio_basics/buffers/juce_AudioSampleBuffer.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -91,7 +91,7 @@ AudioSampleBuffer::AudioSampleBuffer (float* const* dataToReferTo, allocatedBytes (0) { jassert (dataToReferTo != nullptr); - jassert (numChans >= 0); + jassert (numChans >= 0 && numSamples >= 0); allocateChannels (dataToReferTo, 0); } @@ -105,7 +105,7 @@ AudioSampleBuffer::AudioSampleBuffer (float* const* dataToReferTo, isClear (false) { jassert (dataToReferTo != nullptr); - jassert (numChans >= 0); + jassert (numChans >= 0 && startSample >= 0 && numSamples >= 0); allocateChannels (dataToReferTo, startSample); } @@ -114,10 +114,13 @@ void AudioSampleBuffer::setDataToReferTo (float** dataToReferTo, const int newNumSamples) noexcept { jassert (dataToReferTo != nullptr); - jassert (newNumChannels >= 0); + jassert (newNumChannels >= 0 && newNumSamples >= 0); - allocatedBytes = 0; - allocatedData.free(); + if (allocatedBytes != 0) + { + allocatedBytes = 0; + allocatedData.free(); + } numChannels = newNumChannels; size = newNumSamples; @@ -128,6 +131,8 @@ void AudioSampleBuffer::setDataToReferTo (float** dataToReferTo, void AudioSampleBuffer::allocateChannels (float* const* const dataToReferTo, int offset) { + jassert (offset >= 0); + // (try to avoid doing a malloc here, as that'll blow up things like Pro-Tools) if (numChannels < (int) numElementsInArray (preallocatedChannelSpace)) { @@ -163,6 +168,8 @@ AudioSampleBuffer& AudioSampleBuffer::operator= (const AudioSampleBuffer& other) } else { + isClear = false; + for (int i = 0; i < numChannels; ++i) FloatVectorOperations::copy (channels[i], other.channels[i], size); } diff --git a/JuceLibraryCode/modules/juce_audio_basics/buffers/juce_AudioSampleBuffer.h b/JuceLibraryCode/modules/juce_audio_basics/buffers/juce_AudioSampleBuffer.h index 8b9a72c..12e2de8 100644 --- a/JuceLibraryCode/modules/juce_audio_basics/buffers/juce_AudioSampleBuffer.h +++ b/JuceLibraryCode/modules/juce_audio_basics/buffers/juce_AudioSampleBuffer.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_audio_basics/buffers/juce_FloatVectorOperations.cpp b/JuceLibraryCode/modules/juce_audio_basics/buffers/juce_FloatVectorOperations.cpp index a232ec9..971ff65 100644 --- a/JuceLibraryCode/modules/juce_audio_basics/buffers/juce_FloatVectorOperations.cpp +++ b/JuceLibraryCode/modules/juce_audio_basics/buffers/juce_FloatVectorOperations.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -24,8 +24,9 @@ namespace FloatVectorHelpers { - #define JUCE_INCREMENT_SRC_DEST dest += (16 / sizeof (*dest)); src += (16 / sizeof (*dest)); - #define JUCE_INCREMENT_DEST dest += (16 / sizeof (*dest)); + #define JUCE_INCREMENT_SRC_DEST dest += (16 / sizeof (*dest)); src += (16 / sizeof (*dest)); + #define JUCE_INCREMENT_SRC1_SRC2_DEST dest += (16 / sizeof (*dest)); src1 += (16 / sizeof (*dest)); src2 += (16 / sizeof (*dest)); + #define JUCE_INCREMENT_DEST dest += (16 / sizeof (*dest)); #if JUCE_USE_SSE_INTRINSICS static bool sse2Present = false; @@ -48,8 +49,13 @@ namespace FloatVectorHelpers { typedef float Type; typedef __m128 ParallelType; + typedef __m128 IntegerType; enum { numParallel = 4 }; + // Integer and parallel types are the same for SSE. On neon they have different types + static forcedinline IntegerType toint (ParallelType v) noexcept { return v; } + static forcedinline ParallelType toflt (IntegerType v) noexcept { return v; } + static forcedinline ParallelType load1 (Type v) noexcept { return _mm_load1_ps (&v); } static forcedinline ParallelType loadA (const Type* v) noexcept { return _mm_load_ps (v); } static forcedinline ParallelType loadU (const Type* v) noexcept { return _mm_loadu_ps (v); } @@ -62,6 +68,11 @@ namespace FloatVectorHelpers static forcedinline ParallelType max (ParallelType a, ParallelType b) noexcept { return _mm_max_ps (a, b); } static forcedinline ParallelType min (ParallelType a, ParallelType b) noexcept { return _mm_min_ps (a, b); } + static forcedinline ParallelType bit_and (ParallelType a, ParallelType b) noexcept { return _mm_and_ps (a, b); } + static forcedinline ParallelType bit_not (ParallelType a, ParallelType b) noexcept { return _mm_andnot_ps (a, b); } + static forcedinline ParallelType bit_or (ParallelType a, ParallelType b) noexcept { return _mm_or_ps (a, b); } + static forcedinline ParallelType bit_xor (ParallelType a, ParallelType b) noexcept { return _mm_xor_ps (a, b); } + static forcedinline Type max (ParallelType a) noexcept { Type v[numParallel]; storeU (v, a); return jmax (v[0], v[1], v[2], v[3]); } static forcedinline Type min (ParallelType a) noexcept { Type v[numParallel]; storeU (v, a); return jmin (v[0], v[1], v[2], v[3]); } }; @@ -70,8 +81,13 @@ namespace FloatVectorHelpers { typedef double Type; typedef __m128d ParallelType; + typedef __m128d IntegerType; enum { numParallel = 2 }; + // Integer and parallel types are the same for SSE. On neon they have different types + static forcedinline IntegerType toint (ParallelType v) noexcept { return v; } + static forcedinline ParallelType toflt (IntegerType v) noexcept { return v; } + static forcedinline ParallelType load1 (Type v) noexcept { return _mm_load1_pd (&v); } static forcedinline ParallelType loadA (const Type* v) noexcept { return _mm_load_pd (v); } static forcedinline ParallelType loadU (const Type* v) noexcept { return _mm_loadu_pd (v); } @@ -84,10 +100,17 @@ namespace FloatVectorHelpers static forcedinline ParallelType max (ParallelType a, ParallelType b) noexcept { return _mm_max_pd (a, b); } static forcedinline ParallelType min (ParallelType a, ParallelType b) noexcept { return _mm_min_pd (a, b); } + static forcedinline ParallelType bit_and (ParallelType a, ParallelType b) noexcept { return _mm_and_pd (a, b); } + static forcedinline ParallelType bit_not (ParallelType a, ParallelType b) noexcept { return _mm_andnot_pd (a, b); } + static forcedinline ParallelType bit_or (ParallelType a, ParallelType b) noexcept { return _mm_or_pd (a, b); } + static forcedinline ParallelType bit_xor (ParallelType a, ParallelType b) noexcept { return _mm_xor_pd (a, b); } + static forcedinline Type max (ParallelType a) noexcept { Type v[numParallel]; storeU (v, a); return jmax (v[0], v[1]); } static forcedinline Type min (ParallelType a) noexcept { Type v[numParallel]; storeU (v, a); return jmin (v[0], v[1]); } }; + + #define JUCE_BEGIN_VEC_OP \ typedef FloatVectorHelpers::ModeType::Mode Mode; \ if (FloatVectorHelpers::isSSE2Available()) \ @@ -122,6 +145,69 @@ namespace FloatVectorHelpers } \ JUCE_FINISH_VEC_OP (normalOp) + #define JUCE_PERFORM_VEC_OP_SRC1_SRC2_DEST(normalOp, vecOp, locals, increment, setupOp) \ + JUCE_BEGIN_VEC_OP \ + setupOp \ + if (FloatVectorHelpers::isAligned (dest)) \ + { \ + if (FloatVectorHelpers::isAligned (src1)) \ + { \ + if (FloatVectorHelpers::isAligned (src2)) JUCE_VEC_LOOP_TWO_SOURCES (vecOp, Mode::loadA, Mode::loadA, Mode::storeA, locals, increment) \ + else JUCE_VEC_LOOP_TWO_SOURCES (vecOp, Mode::loadA, Mode::loadU, Mode::storeA, locals, increment) \ + } \ + else \ + { \ + if (FloatVectorHelpers::isAligned (src2)) JUCE_VEC_LOOP_TWO_SOURCES (vecOp, Mode::loadU, Mode::loadA, Mode::storeA, locals, increment) \ + else JUCE_VEC_LOOP_TWO_SOURCES (vecOp, Mode::loadU, Mode::loadU, Mode::storeA, locals, increment) \ + } \ + } \ + else \ + { \ + if (FloatVectorHelpers::isAligned (src1)) \ + { \ + if (FloatVectorHelpers::isAligned (src2)) JUCE_VEC_LOOP_TWO_SOURCES (vecOp, Mode::loadA, Mode::loadA, Mode::storeU, locals, increment) \ + else JUCE_VEC_LOOP_TWO_SOURCES (vecOp, Mode::loadA, Mode::loadU, Mode::storeU, locals, increment) \ + } \ + else \ + { \ + if (FloatVectorHelpers::isAligned (src2)) JUCE_VEC_LOOP_TWO_SOURCES (vecOp, Mode::loadU, Mode::loadA, Mode::storeU, locals, increment) \ + else JUCE_VEC_LOOP_TWO_SOURCES (vecOp, Mode::loadU, Mode::loadU, Mode::storeU, locals, increment) \ + } \ + } \ + JUCE_FINISH_VEC_OP (normalOp) + + #define JUCE_PERFORM_VEC_OP_SRC1_SRC2_DEST_DEST(normalOp, vecOp, locals, increment, setupOp) \ + JUCE_BEGIN_VEC_OP \ + setupOp \ + if (FloatVectorHelpers::isAligned (dest)) \ + { \ + if (FloatVectorHelpers::isAligned (src1)) \ + { \ + if (FloatVectorHelpers::isAligned (src2)) JUCE_VEC_LOOP_TWO_SOURCES_WITH_DEST_LOAD (vecOp, Mode::loadA, Mode::loadA, Mode::loadA, Mode::storeA, locals, increment) \ + else JUCE_VEC_LOOP_TWO_SOURCES_WITH_DEST_LOAD (vecOp, Mode::loadA, Mode::loadU, Mode::loadA, Mode::storeA, locals, increment) \ + } \ + else \ + { \ + if (FloatVectorHelpers::isAligned (src2)) JUCE_VEC_LOOP_TWO_SOURCES_WITH_DEST_LOAD (vecOp, Mode::loadU, Mode::loadA, Mode::loadA, Mode::storeA, locals, increment) \ + else JUCE_VEC_LOOP_TWO_SOURCES_WITH_DEST_LOAD (vecOp, Mode::loadU, Mode::loadU, Mode::loadA, Mode::storeA, locals, increment) \ + } \ + } \ + else \ + { \ + if (FloatVectorHelpers::isAligned (src1)) \ + { \ + if (FloatVectorHelpers::isAligned (src2)) JUCE_VEC_LOOP_TWO_SOURCES_WITH_DEST_LOAD (vecOp, Mode::loadA, Mode::loadA, Mode::loadU, Mode::storeU, locals, increment) \ + else JUCE_VEC_LOOP_TWO_SOURCES_WITH_DEST_LOAD (vecOp, Mode::loadA, Mode::loadU, Mode::loadU, Mode::storeU, locals, increment) \ + } \ + else \ + { \ + if (FloatVectorHelpers::isAligned (src2)) JUCE_VEC_LOOP_TWO_SOURCES_WITH_DEST_LOAD (vecOp, Mode::loadU, Mode::loadA, Mode::loadU, Mode::storeU, locals, increment) \ + else JUCE_VEC_LOOP_TWO_SOURCES_WITH_DEST_LOAD (vecOp, Mode::loadU, Mode::loadU, Mode::loadU, Mode::storeU, locals, increment) \ + } \ + } \ + JUCE_FINISH_VEC_OP (normalOp) + + //============================================================================== #elif JUCE_USE_ARM_NEON @@ -129,8 +215,12 @@ namespace FloatVectorHelpers { typedef float Type; typedef float32x4_t ParallelType; + typedef uint32x4_t IntegerType; enum { numParallel = 4 }; + static forcedinline IntegerType toint (ParallelType v) noexcept { union { ParallelType f; IntegerType i; } u; u.f = v; return u.i; } + static forcedinline ParallelType toflt (IntegerType v) noexcept { union { ParallelType f; IntegerType i; } u; u.i = v; return u.f; } + static forcedinline ParallelType load1 (Type v) noexcept { return vld1q_dup_f32 (&v); } static forcedinline ParallelType loadA (const Type* v) noexcept { return vld1q_f32 (v); } static forcedinline ParallelType loadU (const Type* v) noexcept { return vld1q_f32 (v); } @@ -143,6 +233,11 @@ namespace FloatVectorHelpers static forcedinline ParallelType max (ParallelType a, ParallelType b) noexcept { return vmaxq_f32 (a, b); } static forcedinline ParallelType min (ParallelType a, ParallelType b) noexcept { return vminq_f32 (a, b); } + static forcedinline ParallelType bit_and (ParallelType a, ParallelType b) noexcept { return toflt (vandq_u32 (toint (a), toint (b))); } + static forcedinline ParallelType bit_not (ParallelType a, ParallelType b) noexcept { return toflt (vbicq_u32 (toint (a), toint (b))); } + static forcedinline ParallelType bit_or (ParallelType a, ParallelType b) noexcept { return toflt (vorrq_u32 (toint (a), toint (b))); } + static forcedinline ParallelType bit_xor (ParallelType a, ParallelType b) noexcept { return toflt (veorq_u32 (toint (a), toint (b))); } + static forcedinline Type max (ParallelType a) noexcept { Type v[numParallel]; storeU (v, a); return jmax (v[0], v[1], v[2], v[3]); } static forcedinline Type min (ParallelType a) noexcept { Type v[numParallel]; storeU (v, a); return jmin (v[0], v[1], v[2], v[3]); } }; @@ -151,8 +246,12 @@ namespace FloatVectorHelpers { typedef double Type; typedef double ParallelType; + typedef uint64 IntegerType; enum { numParallel = 1 }; + static forcedinline IntegerType toint (ParallelType v) noexcept { union { ParallelType f; IntegerType i; } u; u.f = v; return u.i; } + static forcedinline ParallelType toflt (IntegerType v) noexcept { union { ParallelType f; IntegerType i; } u; u.i = v; return u.f; } + static forcedinline ParallelType load1 (Type v) noexcept { return v; } static forcedinline ParallelType loadA (const Type* v) noexcept { return *v; } static forcedinline ParallelType loadU (const Type* v) noexcept { return *v; } @@ -165,6 +264,11 @@ namespace FloatVectorHelpers static forcedinline ParallelType max (ParallelType a, ParallelType b) noexcept { return jmax (a, b); } static forcedinline ParallelType min (ParallelType a, ParallelType b) noexcept { return jmin (a, b); } + static forcedinline ParallelType bit_and (ParallelType a, ParallelType b) noexcept { return toflt (toint (a) & toint (b)); } + static forcedinline ParallelType bit_not (ParallelType a, ParallelType b) noexcept { return toflt ((~toint (a)) & toint (b)); } + static forcedinline ParallelType bit_or (ParallelType a, ParallelType b) noexcept { return toflt (toint (a) | toint (b)); } + static forcedinline ParallelType bit_xor (ParallelType a, ParallelType b) noexcept { return toflt (toint (a) ^ toint (b)); } + static forcedinline Type max (ParallelType a) noexcept { return a; } static forcedinline Type min (ParallelType a) noexcept { return a; } }; @@ -193,6 +297,19 @@ namespace FloatVectorHelpers JUCE_VEC_LOOP (vecOp, Mode::loadU, Mode::loadU, Mode::storeU, locals, increment) \ JUCE_FINISH_VEC_OP (normalOp) + #define JUCE_PERFORM_VEC_OP_SRC1_SRC2_DEST(normalOp, vecOp, locals, increment, setupOp) \ + JUCE_BEGIN_VEC_OP \ + setupOp \ + JUCE_VEC_LOOP_TWO_SOURCES (vecOp, Mode::loadU, Mode::loadU, Mode::storeU, locals, increment) \ + JUCE_FINISH_VEC_OP (normalOp) + + #define JUCE_PERFORM_VEC_OP_SRC1_SRC2_DEST_DEST(normalOp, vecOp, locals, increment, setupOp) \ + JUCE_BEGIN_VEC_OP \ + setupOp \ + JUCE_VEC_LOOP_TWO_SOURCES_WITH_DEST_LOAD (vecOp, Mode::loadU, Mode::loadU, Mode::loadU, Mode::storeU, locals, increment) \ + JUCE_FINISH_VEC_OP (normalOp) + + //============================================================================== #else #define JUCE_PERFORM_VEC_OP_DEST(normalOp, vecOp, locals, setupOp) \ @@ -201,6 +318,12 @@ namespace FloatVectorHelpers #define JUCE_PERFORM_VEC_OP_SRC_DEST(normalOp, vecOp, locals, increment, setupOp) \ for (int i = 0; i < num; ++i) normalOp; + #define JUCE_PERFORM_VEC_OP_SRC1_SRC2_DEST(normalOp, vecOp, locals, increment, setupOp) \ + for (int i = 0; i < num; ++i) normalOp; + + #define JUCE_PERFORM_VEC_OP_SRC1_SRC2_DEST_DEST(normalOp, vecOp, locals, increment, setupOp) \ + for (int i = 0; i < num; ++i) normalOp; + #endif //============================================================================== @@ -212,10 +335,28 @@ namespace FloatVectorHelpers increment; \ } + #define JUCE_VEC_LOOP_TWO_SOURCES(vecOp, src1Load, src2Load, dstStore, locals, increment) \ + for (int i = 0; i < numLongOps; ++i) \ + { \ + locals (src1Load, src2Load); \ + dstStore (dest, vecOp); \ + increment; \ + } + + #define JUCE_VEC_LOOP_TWO_SOURCES_WITH_DEST_LOAD(vecOp, src1Load, src2Load, dstLoad, dstStore, locals, increment) \ + for (int i = 0; i < numLongOps; ++i) \ + { \ + locals (src1Load, src2Load, dstLoad); \ + dstStore (dest, vecOp); \ + increment; \ + } + #define JUCE_LOAD_NONE(srcLoad, dstLoad) - #define JUCE_LOAD_DEST(srcLoad, dstLoad) const Mode::ParallelType d = dstLoad (dest); - #define JUCE_LOAD_SRC(srcLoad, dstLoad) const Mode::ParallelType s = srcLoad (src); - #define JUCE_LOAD_SRC_DEST(srcLoad, dstLoad) const Mode::ParallelType d = dstLoad (dest), s = srcLoad (src); + #define JUCE_LOAD_DEST(srcLoad, dstLoad) const Mode::ParallelType d = dstLoad (dest); + #define JUCE_LOAD_SRC(srcLoad, dstLoad) const Mode::ParallelType s = srcLoad (src); + #define JUCE_LOAD_SRC1_SRC2(src1Load, src2Load) const Mode::ParallelType s1 = src1Load (src1), s2 = src2Load (src2); + #define JUCE_LOAD_SRC1_SRC2_DEST(src1Load, src2Load, dstLoad) const Mode::ParallelType d = dstLoad (dest), s1 = src1Load (src1), s2 = src2Load (src2); + #define JUCE_LOAD_SRC_DEST(srcLoad, dstLoad) const Mode::ParallelType d = dstLoad (dest), s = srcLoad (src); #if JUCE_USE_SSE_INTRINSICS || JUCE_USE_ARM_NEON template struct ModeType { typedef BasicOps32 Mode; }; @@ -366,7 +507,7 @@ void JUCE_CALLTYPE FloatVectorOperations::clear (float* dest, int num) noexcept #if JUCE_USE_VDSP_FRAMEWORK vDSP_vclr (dest, 1, (size_t) num); #else - zeromem (dest, num * sizeof (float)); + zeromem (dest, (size_t) num * sizeof (float)); #endif } @@ -375,7 +516,7 @@ void JUCE_CALLTYPE FloatVectorOperations::clear (double* dest, int num) noexcept #if JUCE_USE_VDSP_FRAMEWORK vDSP_vclrD (dest, 1, (size_t) num); #else - zeromem (dest, num * sizeof (double)); + zeromem (dest, (size_t) num * sizeof (double)); #endif } @@ -412,7 +553,7 @@ void JUCE_CALLTYPE FloatVectorOperations::copy (double* dest, const double* src, void JUCE_CALLTYPE FloatVectorOperations::copyWithMultiply (float* dest, const float* src, float multiplier, int num) noexcept { #if JUCE_USE_VDSP_FRAMEWORK - vDSP_vsmul (src, 1, &multiplier, dest, 1, num); + vDSP_vsmul (src, 1, &multiplier, dest, 1, (vDSP_Length) num); #else JUCE_PERFORM_VEC_OP_SRC_DEST (dest[i] = src[i] * multiplier, Mode::mul (mult, s), JUCE_LOAD_SRC, JUCE_INCREMENT_SRC_DEST, @@ -423,7 +564,7 @@ void JUCE_CALLTYPE FloatVectorOperations::copyWithMultiply (float* dest, const f void JUCE_CALLTYPE FloatVectorOperations::copyWithMultiply (double* dest, const double* src, double multiplier, int num) noexcept { #if JUCE_USE_VDSP_FRAMEWORK - vDSP_vsmulD (src, 1, &multiplier, dest, 1, num); + vDSP_vsmulD (src, 1, &multiplier, dest, 1, (vDSP_Length) num); #else JUCE_PERFORM_VEC_OP_SRC_DEST (dest[i] = src[i] * multiplier, Mode::mul (mult, s), JUCE_LOAD_SRC, JUCE_INCREMENT_SRC_DEST, @@ -433,8 +574,12 @@ void JUCE_CALLTYPE FloatVectorOperations::copyWithMultiply (double* dest, const void JUCE_CALLTYPE FloatVectorOperations::add (float* dest, float amount, int num) noexcept { + #if JUCE_USE_VDSP_FRAMEWORK + vDSP_vsadd (dest, 1, &amount, dest, 1, (vDSP_Length) num); + #else JUCE_PERFORM_VEC_OP_DEST (dest[i] += amount, Mode::add (d, amountToAdd), JUCE_LOAD_DEST, const Mode::ParallelType amountToAdd = Mode::load1 (amount);) + #endif } void JUCE_CALLTYPE FloatVectorOperations::add (double* dest, double amount, int num) noexcept @@ -443,10 +588,32 @@ void JUCE_CALLTYPE FloatVectorOperations::add (double* dest, double amount, int const Mode::ParallelType amountToAdd = Mode::load1 (amount);) } +void JUCE_CALLTYPE FloatVectorOperations::add (float* dest, float* src, float amount, int num) noexcept +{ + #if JUCE_USE_VDSP_FRAMEWORK + vDSP_vsadd (src, 1, &amount, dest, 1, (vDSP_Length) num); + #else + JUCE_PERFORM_VEC_OP_SRC_DEST (dest[i] = src[i] + amount, Mode::add (am, s), + JUCE_LOAD_SRC, JUCE_INCREMENT_SRC_DEST, + const Mode::ParallelType am = Mode::load1 (amount);) + #endif +} + +void JUCE_CALLTYPE FloatVectorOperations::add (double* dest, double* src, double amount, int num) noexcept +{ + #if JUCE_USE_VDSP_FRAMEWORK + vDSP_vsaddD (src, 1, &amount, dest, 1, (vDSP_Length) num); + #else + JUCE_PERFORM_VEC_OP_SRC_DEST (dest[i] = src[i] + amount, Mode::add (am, s), + JUCE_LOAD_SRC, JUCE_INCREMENT_SRC_DEST, + const Mode::ParallelType am = Mode::load1 (amount);) + #endif +} + void JUCE_CALLTYPE FloatVectorOperations::add (float* dest, const float* src, int num) noexcept { #if JUCE_USE_VDSP_FRAMEWORK - vDSP_vadd (src, 1, dest, 1, dest, 1, num); + vDSP_vadd (src, 1, dest, 1, dest, 1, (vDSP_Length) num); #else JUCE_PERFORM_VEC_OP_SRC_DEST (dest[i] += src[i], Mode::add (d, s), JUCE_LOAD_SRC_DEST, JUCE_INCREMENT_SRC_DEST, ) #endif @@ -455,16 +622,34 @@ void JUCE_CALLTYPE FloatVectorOperations::add (float* dest, const float* src, in void JUCE_CALLTYPE FloatVectorOperations::add (double* dest, const double* src, int num) noexcept { #if JUCE_USE_VDSP_FRAMEWORK - vDSP_vaddD (src, 1, dest, 1, dest, 1, num); + vDSP_vaddD (src, 1, dest, 1, dest, 1, (vDSP_Length) num); #else JUCE_PERFORM_VEC_OP_SRC_DEST (dest[i] += src[i], Mode::add (d, s), JUCE_LOAD_SRC_DEST, JUCE_INCREMENT_SRC_DEST, ) #endif } +void JUCE_CALLTYPE FloatVectorOperations::add (float* dest, const float* src1, const float* src2, int num) noexcept +{ + #if JUCE_USE_VDSP_FRAMEWORK + vDSP_vadd (src1, 1, src2, 1, dest, 1, (vDSP_Length) num); + #else + JUCE_PERFORM_VEC_OP_SRC1_SRC2_DEST (dest[i] = src1[i] + src2[i], Mode::add (s1, s2), JUCE_LOAD_SRC1_SRC2, JUCE_INCREMENT_SRC1_SRC2_DEST, ) + #endif +} + +void JUCE_CALLTYPE FloatVectorOperations::add (double* dest, const double* src1, const double* src2, int num) noexcept +{ + #if JUCE_USE_VDSP_FRAMEWORK + vDSP_vaddD (src1, 1, src2, 1, dest, 1, (vDSP_Length) num); + #else + JUCE_PERFORM_VEC_OP_SRC1_SRC2_DEST (dest[i] = src1[i] + src2[i], Mode::add (s1, s2), JUCE_LOAD_SRC1_SRC2, JUCE_INCREMENT_SRC1_SRC2_DEST, ) + #endif +} + void JUCE_CALLTYPE FloatVectorOperations::subtract (float* dest, const float* src, int num) noexcept { #if JUCE_USE_VDSP_FRAMEWORK - vDSP_vsub (src, 1, dest, 1, dest, 1, num); + vDSP_vsub (src, 1, dest, 1, dest, 1, (vDSP_Length) num); #else JUCE_PERFORM_VEC_OP_SRC_DEST (dest[i] -= src[i], Mode::sub (d, s), JUCE_LOAD_SRC_DEST, JUCE_INCREMENT_SRC_DEST, ) #endif @@ -473,17 +658,39 @@ void JUCE_CALLTYPE FloatVectorOperations::subtract (float* dest, const float* sr void JUCE_CALLTYPE FloatVectorOperations::subtract (double* dest, const double* src, int num) noexcept { #if JUCE_USE_VDSP_FRAMEWORK - vDSP_vsubD (src, 1, dest, 1, dest, 1, num); + vDSP_vsubD (src, 1, dest, 1, dest, 1, (vDSP_Length) num); #else JUCE_PERFORM_VEC_OP_SRC_DEST (dest[i] -= src[i], Mode::sub (d, s), JUCE_LOAD_SRC_DEST, JUCE_INCREMENT_SRC_DEST, ) #endif } +void JUCE_CALLTYPE FloatVectorOperations::subtract (float* dest, const float* src1, const float* src2, int num) noexcept +{ + #if JUCE_USE_VDSP_FRAMEWORK + vDSP_vsub (src2, 1, src1, 1, dest, 1, (vDSP_Length) num); + #else + JUCE_PERFORM_VEC_OP_SRC1_SRC2_DEST (dest[i] = src1[i] - src2[i], Mode::sub (s1, s2), JUCE_LOAD_SRC1_SRC2, JUCE_INCREMENT_SRC1_SRC2_DEST, ) + #endif +} + +void JUCE_CALLTYPE FloatVectorOperations::subtract (double* dest, const double* src1, const double* src2, int num) noexcept +{ + #if JUCE_USE_VDSP_FRAMEWORK + vDSP_vsubD (src2, 1, src1, 1, dest, 1, (vDSP_Length) num); + #else + JUCE_PERFORM_VEC_OP_SRC1_SRC2_DEST (dest[i] = src1[i] - src2[i], Mode::sub (s1, s2), JUCE_LOAD_SRC1_SRC2, JUCE_INCREMENT_SRC1_SRC2_DEST, ) + #endif +} + void JUCE_CALLTYPE FloatVectorOperations::addWithMultiply (float* dest, const float* src, float multiplier, int num) noexcept { + #if JUCE_USE_VDSP_FRAMEWORK + vDSP_vsma (src, 1, &multiplier, dest, 1, dest, 1, (vDSP_Length) num); + #else JUCE_PERFORM_VEC_OP_SRC_DEST (dest[i] += src[i] * multiplier, Mode::add (d, Mode::mul (mult, s)), JUCE_LOAD_SRC_DEST, JUCE_INCREMENT_SRC_DEST, const Mode::ParallelType mult = Mode::load1 (multiplier);) + #endif } void JUCE_CALLTYPE FloatVectorOperations::addWithMultiply (double* dest, const double* src, double multiplier, int num) noexcept @@ -493,10 +700,32 @@ void JUCE_CALLTYPE FloatVectorOperations::addWithMultiply (double* dest, const d const Mode::ParallelType mult = Mode::load1 (multiplier);) } +void JUCE_CALLTYPE FloatVectorOperations::addWithMultiply (float* dest, const float* src1, const float* src2, int num) noexcept +{ + #if JUCE_USE_VDSP_FRAMEWORK + vDSP_vma ((float*) src1, 1, (float*) src2, 1, dest, 1, dest, 1, (vDSP_Length) num); + #else + JUCE_PERFORM_VEC_OP_SRC1_SRC2_DEST_DEST (dest[i] += src1[i] * src2[i], Mode::add (d, Mode::mul (s1, s2)), + JUCE_LOAD_SRC1_SRC2_DEST, + JUCE_INCREMENT_SRC1_SRC2_DEST, ) + #endif +} + +void JUCE_CALLTYPE FloatVectorOperations::addWithMultiply (double* dest, const double* src1, const double* src2, int num) noexcept +{ + #if JUCE_USE_VDSP_FRAMEWORK + vDSP_vmaD ((double*) src1, 1, (double*) src2, 1, dest, 1, dest, 1, (vDSP_Length) num); + #else + JUCE_PERFORM_VEC_OP_SRC1_SRC2_DEST_DEST (dest[i] += src1[i] * src2[i], Mode::add (d, Mode::mul (s1, s2)), + JUCE_LOAD_SRC1_SRC2_DEST, + JUCE_INCREMENT_SRC1_SRC2_DEST, ) + #endif +} + void JUCE_CALLTYPE FloatVectorOperations::multiply (float* dest, const float* src, int num) noexcept { #if JUCE_USE_VDSP_FRAMEWORK - vDSP_vmul (src, 1, dest, 1, dest, 1, num); + vDSP_vmul (src, 1, dest, 1, dest, 1, (vDSP_Length) num); #else JUCE_PERFORM_VEC_OP_SRC_DEST (dest[i] *= src[i], Mode::mul (d, s), JUCE_LOAD_SRC_DEST, JUCE_INCREMENT_SRC_DEST, ) #endif @@ -505,16 +734,34 @@ void JUCE_CALLTYPE FloatVectorOperations::multiply (float* dest, const float* sr void JUCE_CALLTYPE FloatVectorOperations::multiply (double* dest, const double* src, int num) noexcept { #if JUCE_USE_VDSP_FRAMEWORK - vDSP_vmulD (src, 1, dest, 1, dest, 1, num); + vDSP_vmulD (src, 1, dest, 1, dest, 1, (vDSP_Length) num); #else JUCE_PERFORM_VEC_OP_SRC_DEST (dest[i] *= src[i], Mode::mul (d, s), JUCE_LOAD_SRC_DEST, JUCE_INCREMENT_SRC_DEST, ) #endif } +void JUCE_CALLTYPE FloatVectorOperations::multiply (float* dest, const float* src1, const float* src2, int num) noexcept +{ + #if JUCE_USE_VDSP_FRAMEWORK + vDSP_vmul (src1, 1, src2, 1, dest, 1, (vDSP_Length) num); + #else + JUCE_PERFORM_VEC_OP_SRC1_SRC2_DEST (dest[i] = src1[i] * src2[i], Mode::mul (s1, s2), JUCE_LOAD_SRC1_SRC2, JUCE_INCREMENT_SRC1_SRC2_DEST, ) + #endif +} + +void JUCE_CALLTYPE FloatVectorOperations::multiply (double* dest, const double* src1, const double* src2, int num) noexcept +{ + #if JUCE_USE_VDSP_FRAMEWORK + vDSP_vmulD (src1, 1, src2, 1, dest, 1, (vDSP_Length) num); + #else + JUCE_PERFORM_VEC_OP_SRC1_SRC2_DEST (dest[i] = src1[i] * src2[i], Mode::mul (s1, s2), JUCE_LOAD_SRC1_SRC2, JUCE_INCREMENT_SRC1_SRC2_DEST, ) + #endif +} + void JUCE_CALLTYPE FloatVectorOperations::multiply (float* dest, float multiplier, int num) noexcept { #if JUCE_USE_VDSP_FRAMEWORK - vDSP_vsmul (dest, 1, &multiplier, dest, 1, num); + vDSP_vsmul (dest, 1, &multiplier, dest, 1, (vDSP_Length) num); #else JUCE_PERFORM_VEC_OP_DEST (dest[i] *= multiplier, Mode::mul (d, mult), JUCE_LOAD_DEST, const Mode::ParallelType mult = Mode::load1 (multiplier);) @@ -524,13 +771,27 @@ void JUCE_CALLTYPE FloatVectorOperations::multiply (float* dest, float multiplie void JUCE_CALLTYPE FloatVectorOperations::multiply (double* dest, double multiplier, int num) noexcept { #if JUCE_USE_VDSP_FRAMEWORK - vDSP_vsmulD (dest, 1, &multiplier, dest, 1, num); + vDSP_vsmulD (dest, 1, &multiplier, dest, 1, (vDSP_Length) num); #else JUCE_PERFORM_VEC_OP_DEST (dest[i] *= multiplier, Mode::mul (d, mult), JUCE_LOAD_DEST, const Mode::ParallelType mult = Mode::load1 (multiplier);) #endif } +void JUCE_CALLTYPE FloatVectorOperations::multiply (float* dest, const float* src, float multiplier, int num) noexcept +{ + JUCE_PERFORM_VEC_OP_SRC_DEST (dest[i] = src[i] * multiplier, Mode::mul (mult, s), + JUCE_LOAD_SRC, JUCE_INCREMENT_SRC_DEST, + const Mode::ParallelType mult = Mode::load1 (multiplier);) +} + +void JUCE_CALLTYPE FloatVectorOperations::multiply (double* dest, const double* src, double multiplier, int num) noexcept +{ + JUCE_PERFORM_VEC_OP_SRC_DEST (dest[i] = src[i] * multiplier, Mode::mul (mult, s), + JUCE_LOAD_SRC, JUCE_INCREMENT_SRC_DEST, + const Mode::ParallelType mult = Mode::load1 (multiplier);) +} + void FloatVectorOperations::negate (float* dest, const float* src, int num) noexcept { #if JUCE_USE_VDSP_FRAMEWORK @@ -549,6 +810,33 @@ void FloatVectorOperations::negate (double* dest, const double* src, int num) no #endif } +void FloatVectorOperations::abs (float* dest, const float* src, int num) noexcept +{ + #if JUCE_USE_VDSP_FRAMEWORK + vDSP_vabs ((float*) src, 1, dest, 1, (vDSP_Length) num); + #else + union {float f; uint32 i;} signMask; + signMask.i = 0x7fffffffUL; + JUCE_PERFORM_VEC_OP_SRC_DEST (dest[i] = fabsf (src[i]), Mode::bit_and (s, mask), + JUCE_LOAD_SRC, JUCE_INCREMENT_SRC_DEST, + const Mode::ParallelType mask = Mode::load1 (signMask.f);) + #endif +} + +void FloatVectorOperations::abs (double* dest, const double* src, int num) noexcept +{ + #if JUCE_USE_VDSP_FRAMEWORK + vDSP_vabsD ((double*) src, 1, dest, 1, (vDSP_Length) num); + #else + union {double d; uint64 i;} signMask; + signMask.i = 0x7fffffffffffffffULL; + + JUCE_PERFORM_VEC_OP_SRC_DEST (dest[i] = fabs (src[i]), Mode::bit_and (s, mask), + JUCE_LOAD_SRC, JUCE_INCREMENT_SRC_DEST, + const Mode::ParallelType mask = Mode::load1 (signMask.d);) + #endif +} + void JUCE_CALLTYPE FloatVectorOperations::convertFixedToFloat (float* dest, const int* src, float multiplier, int num) noexcept { #if JUCE_USE_ARM_NEON @@ -563,6 +851,96 @@ void JUCE_CALLTYPE FloatVectorOperations::convertFixedToFloat (float* dest, cons #endif } +void JUCE_CALLTYPE FloatVectorOperations::min (float* dest, const float* src, float comp, int num) noexcept +{ + JUCE_PERFORM_VEC_OP_SRC_DEST (dest[i] = jmin (src[i], comp), Mode::min (s, cmp), + JUCE_LOAD_SRC, JUCE_INCREMENT_SRC_DEST, + const Mode::ParallelType cmp = Mode::load1 (comp);) +} + +void JUCE_CALLTYPE FloatVectorOperations::min (double* dest, const double* src, double comp, int num) noexcept +{ + JUCE_PERFORM_VEC_OP_SRC_DEST (dest[i] = jmin (src[i], comp), Mode::min (s, cmp), + JUCE_LOAD_SRC, JUCE_INCREMENT_SRC_DEST, + const Mode::ParallelType cmp = Mode::load1 (comp);) +} + +void JUCE_CALLTYPE FloatVectorOperations::min (float* dest, const float* src1, const float* src2, int num) noexcept +{ + #if JUCE_USE_VDSP_FRAMEWORK + vDSP_vmin ((float*) src1, 1, (float*) src2, 1, dest, 1, (vDSP_Length) num); + #else + JUCE_PERFORM_VEC_OP_SRC1_SRC2_DEST (dest[i] = jmin (src1[i], src2[i]), Mode::min (s1, s2), JUCE_LOAD_SRC1_SRC2, JUCE_INCREMENT_SRC1_SRC2_DEST, ) + #endif +} + +void JUCE_CALLTYPE FloatVectorOperations::min (double* dest, const double* src1, const double* src2, int num) noexcept +{ + #if JUCE_USE_VDSP_FRAMEWORK + vDSP_vminD ((double*) src1, 1, (double*) src2, 1, dest, 1, (vDSP_Length) num); + #else + JUCE_PERFORM_VEC_OP_SRC1_SRC2_DEST (dest[i] = jmin (src1[i], src2[i]), Mode::min (s1, s2), JUCE_LOAD_SRC1_SRC2, JUCE_INCREMENT_SRC1_SRC2_DEST, ) + #endif +} + +void JUCE_CALLTYPE FloatVectorOperations::max (float* dest, const float* src, float comp, int num) noexcept +{ + JUCE_PERFORM_VEC_OP_SRC_DEST (dest[i] = jmax (src[i], comp), Mode::max (s, cmp), + JUCE_LOAD_SRC, JUCE_INCREMENT_SRC_DEST, + const Mode::ParallelType cmp = Mode::load1 (comp);) +} + +void JUCE_CALLTYPE FloatVectorOperations::max (double* dest, const double* src, double comp, int num) noexcept +{ + JUCE_PERFORM_VEC_OP_SRC_DEST (dest[i] = jmax (src[i], comp), Mode::max (s, cmp), + JUCE_LOAD_SRC, JUCE_INCREMENT_SRC_DEST, + const Mode::ParallelType cmp = Mode::load1 (comp);) +} + +void JUCE_CALLTYPE FloatVectorOperations::max (float* dest, const float* src1, const float* src2, int num) noexcept +{ + #if JUCE_USE_VDSP_FRAMEWORK + vDSP_vmax ((float*) src1, 1, (float*) src2, 1, dest, 1, (vDSP_Length) num); + #else + JUCE_PERFORM_VEC_OP_SRC1_SRC2_DEST (dest[i] = jmax (src1[i], src2[i]), Mode::max (s1, s2), JUCE_LOAD_SRC1_SRC2, JUCE_INCREMENT_SRC1_SRC2_DEST, ) + #endif +} + +void JUCE_CALLTYPE FloatVectorOperations::max (double* dest, const double* src1, const double* src2, int num) noexcept +{ + #if JUCE_USE_VDSP_FRAMEWORK + vDSP_vmaxD ((double*) src1, 1, (double*) src2, 1, dest, 1, (vDSP_Length) num); + #else + JUCE_PERFORM_VEC_OP_SRC1_SRC2_DEST (dest[i] = jmax (src1[i], src2[i]), Mode::max (s1, s2), JUCE_LOAD_SRC1_SRC2, JUCE_INCREMENT_SRC1_SRC2_DEST, ) + #endif +} + +void JUCE_CALLTYPE FloatVectorOperations::clip (float* dest, const float* src, float low, float high, int num) noexcept +{ + jassert(high >= low); + + #if JUCE_USE_VDSP_FRAMEWORK + vDSP_vclip ((float*) src, 1, &low, &high, dest, 1, (vDSP_Length) num); + #else + JUCE_PERFORM_VEC_OP_SRC_DEST (dest[i] = jmax (jmin (src[i], high), low), Mode::max (Mode::min (s, hi), lo), + JUCE_LOAD_SRC, JUCE_INCREMENT_SRC_DEST, + const Mode::ParallelType lo = Mode::load1 (low); const Mode::ParallelType hi = Mode::load1 (high);) + #endif +} + +void JUCE_CALLTYPE FloatVectorOperations::clip (double* dest, const double* src, double low, double high, int num) noexcept +{ + jassert(high >= low); + + #if JUCE_USE_VDSP_FRAMEWORK + vDSP_vclipD ((double*) src, 1, &low, &high, dest, 1, (vDSP_Length) num); + #else + JUCE_PERFORM_VEC_OP_SRC_DEST (dest[i] = jmax (jmin (src[i], high), low), Mode::max (Mode::min (s, hi), lo), + JUCE_LOAD_SRC, JUCE_INCREMENT_SRC_DEST, + const Mode::ParallelType lo = Mode::load1 (low); const Mode::ParallelType hi = Mode::load1 (high);) + #endif +} + Range JUCE_CALLTYPE FloatVectorOperations::findMinAndMax (const float* src, int num) noexcept { #if JUCE_USE_SSE_INTRINSICS || JUCE_USE_ARM_NEON @@ -643,8 +1021,8 @@ public: const int range = random.nextBool() ? 500 : 10; const int num = random.nextInt (range) + 1; - HeapBlock buffer1 (num + 16), buffer2 (num + 16); - HeapBlock buffer3 (num + 16); + HeapBlock buffer1 ((size_t) num + 16), buffer2 ((size_t) num + 16); + HeapBlock buffer3 ((size_t) num + 16); #if JUCE_ARM ValueType* const data1 = buffer1; @@ -702,8 +1080,19 @@ public: FloatVectorOperations::subtract (data1, data2, num); u.expect (areAllValuesEqual (data1, num, (ValueType) 512)); + FloatVectorOperations::abs (data1, data2, num); + u.expect (areAllValuesEqual (data1, num, (ValueType) 256)); + + FloatVectorOperations::abs (data2, data1, num); + u.expect (areAllValuesEqual (data2, num, (ValueType) 256)); + fillRandomly (random, int1, num); doConversionTest (u, data1, data2, int1, num); + + FloatVectorOperations::fill (data1, (ValueType) 2, num); + FloatVectorOperations::fill (data2, (ValueType) 3, num); + FloatVectorOperations::addWithMultiply (data1, data1, data2, num); + u.expect (areAllValuesEqual (data1, num, (ValueType) 8)); } static void doConversionTest (UnitTest& u, float* data1, float* data2, int* const int1, int num) diff --git a/JuceLibraryCode/modules/juce_audio_basics/buffers/juce_FloatVectorOperations.h b/JuceLibraryCode/modules/juce_audio_basics/buffers/juce_FloatVectorOperations.h index 54821d2..0c85e60 100644 --- a/JuceLibraryCode/modules/juce_audio_basics/buffers/juce_FloatVectorOperations.h +++ b/JuceLibraryCode/modules/juce_audio_basics/buffers/juce_FloatVectorOperations.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -65,45 +65,117 @@ public: /** Adds a fixed value to the destination values. */ static void JUCE_CALLTYPE add (double* dest, double amountToAdd, int numValues) noexcept; + /** Adds a fixed value to each source value and stores it in the destination array. */ + static void JUCE_CALLTYPE add (float* dest, float* src, float amount, int numValues) noexcept; + + /** Adds a fixed value to each source value and stores it in the destination array. */ + static void JUCE_CALLTYPE add (double* dest, double* src, double amount, int numValues) noexcept; + /** Adds the source values to the destination values. */ static void JUCE_CALLTYPE add (float* dest, const float* src, int numValues) noexcept; /** Adds the source values to the destination values. */ static void JUCE_CALLTYPE add (double* dest, const double* src, int numValues) noexcept; + /** Adds each source1 value to the corresponding source2 value and stores the result in the destination array. */ + static void JUCE_CALLTYPE add (float* dest, const float* src1, const float* src2, int num) noexcept; + + /** Adds each source1 value to the corresponding source2 value and stores the result in the destination array. */ + static void JUCE_CALLTYPE add (double* dest, const double* src1, const double* src2, int num) noexcept; + /** Subtracts the source values from the destination values. */ static void JUCE_CALLTYPE subtract (float* dest, const float* src, int numValues) noexcept; /** Subtracts the source values from the destination values. */ static void JUCE_CALLTYPE subtract (double* dest, const double* src, int numValues) noexcept; + /** Subtracts each source2 value from the corresponding source1 value and stores the result in the destination array. */ + static void JUCE_CALLTYPE subtract (float* dest, const float* src1, const float* src2, int num) noexcept; + + /** Subtracts each source2 value from the corresponding source1 value and stores the result in the destination array. */ + static void JUCE_CALLTYPE subtract (double* dest, const double* src1, const double* src2, int num) noexcept; + /** Multiplies each source value by the given multiplier, then adds it to the destination value. */ static void JUCE_CALLTYPE addWithMultiply (float* dest, const float* src, float multiplier, int numValues) noexcept; /** Multiplies each source value by the given multiplier, then adds it to the destination value. */ static void JUCE_CALLTYPE addWithMultiply (double* dest, const double* src, double multiplier, int numValues) noexcept; + /** Multiplies each source1 value by the corresponding source2 value, then adds it to the destination value. */ + static void JUCE_CALLTYPE addWithMultiply (float* dest, const float* src1, const float* src2, int num) noexcept; + + /** Multiplies each source1 value by the corresponding source2 value, then adds it to the destination value. */ + static void JUCE_CALLTYPE addWithMultiply (double* dest, const double* src1, const double* src2, int num) noexcept; + /** Multiplies the destination values by the source values. */ static void JUCE_CALLTYPE multiply (float* dest, const float* src, int numValues) noexcept; /** Multiplies the destination values by the source values. */ static void JUCE_CALLTYPE multiply (double* dest, const double* src, int numValues) noexcept; + /** Multiplies each source1 value by the correspinding source2 value, then stores it in the destination array. */ + static void JUCE_CALLTYPE multiply (float* dest, const float* src1, const float* src2, int numValues) noexcept; + + /** Multiplies each source1 value by the correspinding source2 value, then stores it in the destination array. */ + static void JUCE_CALLTYPE multiply (double* dest, const double* src1, const double* src2, int numValues) noexcept; + /** Multiplies each of the destination values by a fixed multiplier. */ static void JUCE_CALLTYPE multiply (float* dest, float multiplier, int numValues) noexcept; /** Multiplies each of the destination values by a fixed multiplier. */ static void JUCE_CALLTYPE multiply (double* dest, double multiplier, int numValues) noexcept; + /** Multiplies each of the source values by a fixed multiplier and stores the result in the destination array. */ + static void JUCE_CALLTYPE multiply (float* dest, const float* src, float multiplier, int num) noexcept; + + /** Multiplies each of the source values by a fixed multiplier and stores the result in the destination array. */ + static void JUCE_CALLTYPE multiply (double* dest, const double* src, double multiplier, int num) noexcept; + /** Copies a source vector to a destination, negating each value. */ static void JUCE_CALLTYPE negate (float* dest, const float* src, int numValues) noexcept; /** Copies a source vector to a destination, negating each value. */ static void JUCE_CALLTYPE negate (double* dest, const double* src, int numValues) noexcept; + /** Copies a source vector to a destination, taking the absolute of each value. */ + static void JUCE_CALLTYPE abs (float* dest, const float* src, int numValues) noexcept; + + /** Copies a source vector to a destination, taking the absolute of each value. */ + static void JUCE_CALLTYPE abs (double* dest, const double* src, int numValues) noexcept; + /** Converts a stream of integers to floats, multiplying each one by the given multiplier. */ static void JUCE_CALLTYPE convertFixedToFloat (float* dest, const int* src, float multiplier, int numValues) noexcept; + /** Each element of dest will be the minimum of the corresponding element of the source array and the given comp value. */ + static void JUCE_CALLTYPE min (float* dest, const float* src, float comp, int num) noexcept; + + /** Each element of dest will be the minimum of the corresponding element of the source array and the given comp value. */ + static void JUCE_CALLTYPE min (double* dest, const double* src, double comp, int num) noexcept; + + /** Each element of dest will be the minimum of the corresponding source1 and source2 values. */ + static void JUCE_CALLTYPE min (float* dest, const float* src1, const float* src2, int num) noexcept; + + /** Each element of dest will be the minimum of the corresponding source1 and source2 values. */ + static void JUCE_CALLTYPE min (double* dest, const double* src1, const double* src2, int num) noexcept; + + /** Each element of dest will be the maximum of the corresponding element of the source array and the given comp value. */ + static void JUCE_CALLTYPE max (float* dest, const float* src, float comp, int num) noexcept; + + /** Each element of dest will be the maximum of the corresponding element of the source array and the given comp value. */ + static void JUCE_CALLTYPE max (double* dest, const double* src, double comp, int num) noexcept; + + /** Each element of dest will be the maximum of the corresponding source1 and source2 values. */ + static void JUCE_CALLTYPE max (float* dest, const float* src1, const float* src2, int num) noexcept; + + /** Each element of dest will be the maximum of the corresponding source1 and source2 values. */ + static void JUCE_CALLTYPE max (double* dest, const double* src1, const double* src2, int num) noexcept; + + /** Each element of dest is calculated by hard clipping the corresponding src element so that it is in the range specified by the arguments low and high. */ + static void JUCE_CALLTYPE clip (float* dest, const float* src, float low, float high, int num) noexcept; + + /** Each element of dest is calculated by hard clipping the corresponding src element so that it is in the range specified by the arguments low and high. */ + static void JUCE_CALLTYPE clip (double* dest, const double* src, double low, double high, int num) noexcept; + /** Finds the miniumum and maximum values in the given array. */ static Range JUCE_CALLTYPE findMinAndMax (const float* src, int numValues) noexcept; diff --git a/JuceLibraryCode/modules/juce_audio_basics/effects/juce_Decibels.h b/JuceLibraryCode/modules/juce_audio_basics/effects/juce_Decibels.h index c63746c..6e039e3 100644 --- a/JuceLibraryCode/modules/juce_audio_basics/effects/juce_Decibels.h +++ b/JuceLibraryCode/modules/juce_audio_basics/effects/juce_Decibels.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_audio_basics/effects/juce_IIRFilter.cpp b/JuceLibraryCode/modules/juce_audio_basics/effects/juce_IIRFilter.cpp index 908a69e..836c0f6 100644 --- a/JuceLibraryCode/modules/juce_audio_basics/effects/juce_IIRFilter.cpp +++ b/JuceLibraryCode/modules/juce_audio_basics/effects/juce_IIRFilter.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -23,7 +23,7 @@ */ #if JUCE_INTEL - #define JUCE_SNAP_TO_ZERO(n) if (! (n < -1.0e-8 || n > 1.0e-8)) n = 0; + #define JUCE_SNAP_TO_ZERO(n) if (! (n < -1.0e-8f || n > 1.0e-8f)) n = 0; #else #define JUCE_SNAP_TO_ZERO(n) #endif @@ -64,7 +64,7 @@ IIRCoefficients IIRCoefficients::makeLowPass (const double sampleRate, { jassert (sampleRate > 0); - const double n = 1.0 / tan (double_Pi * frequency / sampleRate); + const double n = 1.0 / std::tan (double_Pi * frequency / sampleRate); const double nSquared = n * n; const double c1 = 1.0 / (1.0 + std::sqrt (2.0) * n + nSquared); @@ -79,7 +79,7 @@ IIRCoefficients IIRCoefficients::makeLowPass (const double sampleRate, IIRCoefficients IIRCoefficients::makeHighPass (const double sampleRate, const double frequency) noexcept { - const double n = tan (double_Pi * frequency / sampleRate); + const double n = std::tan (double_Pi * frequency / sampleRate); const double nSquared = n * n; const double c1 = 1.0 / (1.0 + std::sqrt (2.0) * n + nSquared); diff --git a/JuceLibraryCode/modules/juce_audio_basics/effects/juce_IIRFilter.h b/JuceLibraryCode/modules/juce_audio_basics/effects/juce_IIRFilter.h index 8269cf5..03deee7 100644 --- a/JuceLibraryCode/modules/juce_audio_basics/effects/juce_IIRFilter.h +++ b/JuceLibraryCode/modules/juce_audio_basics/effects/juce_IIRFilter.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_audio_basics/effects/juce_LagrangeInterpolator.cpp b/JuceLibraryCode/modules/juce_audio_basics/effects/juce_LagrangeInterpolator.cpp index 7bab3a5..aa4eccc 100644 --- a/JuceLibraryCode/modules/juce_audio_basics/effects/juce_LagrangeInterpolator.cpp +++ b/JuceLibraryCode/modules/juce_audio_basics/effects/juce_LagrangeInterpolator.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -87,7 +87,10 @@ int LagrangeInterpolator::process (const double actualRatio, const float* in, if (numOut >= 4) { - memcpy (lastInputSamples, in + (numOut - 4), 4 * sizeof (float)); + const float* end = in + numOut; + + for (int i = 0; i < 4; ++i) + lastInputSamples[i] = *--end; } else { @@ -152,7 +155,10 @@ int LagrangeInterpolator::processAdding (const double actualRatio, const float* if (numOut >= 4) { - memcpy (lastInputSamples, in + (numOut - 4), 4 * sizeof (float)); + const float* end = in + numOut; + + for (int i = 0; i < 4; ++i) + lastInputSamples[i] = *--end; } else { diff --git a/JuceLibraryCode/modules/juce_audio_basics/effects/juce_LagrangeInterpolator.h b/JuceLibraryCode/modules/juce_audio_basics/effects/juce_LagrangeInterpolator.h index caa4802..c3f7fd2 100644 --- a/JuceLibraryCode/modules/juce_audio_basics/effects/juce_LagrangeInterpolator.h +++ b/JuceLibraryCode/modules/juce_audio_basics/effects/juce_LagrangeInterpolator.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_audio_basics/effects/juce_Reverb.h b/JuceLibraryCode/modules/juce_audio_basics/effects/juce_Reverb.h index 53457a6..4dcc0fc 100644 --- a/JuceLibraryCode/modules/juce_audio_basics/effects/juce_Reverb.h +++ b/JuceLibraryCode/modules/juce_audio_basics/effects/juce_Reverb.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -82,12 +82,13 @@ public: const float dryScaleFactor = 2.0f; const float wet = newParams.wetLevel * wetScaleFactor; - wet1 = wet * (newParams.width * 0.5f + 0.5f); - wet2 = wet * (1.0f - newParams.width) * 0.5f; - dry = newParams.dryLevel * dryScaleFactor; + dryGain.setValue (newParams.dryLevel * dryScaleFactor); + wetGain1.setValue (0.5f * wet * (1.0f + newParams.width)); + wetGain2.setValue (0.5f * wet * (1.0f - newParams.width)); + gain = isFrozen (newParams.freezeMode) ? 0.0f : 0.015f; parameters = newParams; - shouldUpdateDamping = true; + updateDamping(); } //============================================================================== @@ -115,7 +116,12 @@ public: allPass[1][i].setSize ((intSampleRate * (allPassTunings[i] + stereoSpread)) / 44100); } - shouldUpdateDamping = true; + const double smoothTime = 0.01; + damping .reset (sampleRate, smoothTime); + feedback.reset (sampleRate, smoothTime); + dryGain .reset (sampleRate, smoothTime); + wetGain1.reset (sampleRate, smoothTime); + wetGain2.reset (sampleRate, smoothTime); } /** Clears the reverb's buffers. */ @@ -137,18 +143,18 @@ public: { jassert (left != nullptr && right != nullptr); - if (shouldUpdateDamping) - updateDamping(); - for (int i = 0; i < numSamples; ++i) { const float input = (left[i] + right[i]) * gain; float outL = 0, outR = 0; + const float damp = damping.getNextValue(); + const float feedbck = feedback.getNextValue(); + for (int j = 0; j < numCombs; ++j) // accumulate the comb filters in parallel { - outL += comb[0][j].process (input); - outR += comb[1][j].process (input); + outL += comb[0][j].process (input, damp, feedbck); + outR += comb[1][j].process (input, damp, feedbck); } for (int j = 0; j < numAllPasses; ++j) // run the allpass filters in series @@ -157,6 +163,10 @@ public: outR = allPass[1][j].process (outR); } + const float dry = dryGain.getNextValue(); + const float wet1 = wetGain1.getNextValue(); + const float wet2 = wetGain2.getNextValue(); + left[i] = outL * wet1 + outR * wet2 + left[i] * dry; right[i] = outR * wet1 + outL * wet2 + right[i] * dry; } @@ -167,32 +177,30 @@ public: { jassert (samples != nullptr); - if (shouldUpdateDamping) - updateDamping(); - for (int i = 0; i < numSamples; ++i) { const float input = samples[i] * gain; float output = 0; + const float damp = damping.getNextValue(); + const float feedbck = feedback.getNextValue(); + for (int j = 0; j < numCombs; ++j) // accumulate the comb filters in parallel - output += comb[0][j].process (input); + output += comb[0][j].process (input, damp, feedbck); for (int j = 0; j < numAllPasses; ++j) // run the allpass filters in series output = allPass[0][j].process (output); + const float dry = dryGain.getNextValue(); + const float wet1 = wetGain1.getNextValue(); + samples[i] = output * wet1 + samples[i] * dry; } } private: //============================================================================== - Parameters parameters; - - volatile bool shouldUpdateDamping; - float gain, wet1, wet2, dry; - - inline static bool isFrozen (const float freezeMode) noexcept { return freezeMode >= 0.5f; } + static bool isFrozen (const float freezeMode) noexcept { return freezeMode >= 0.5f; } void updateDamping() noexcept { @@ -200,8 +208,6 @@ private: const float roomOffset = 0.7f; const float dampScaleFactor = 0.4f; - shouldUpdateDamping = false; - if (isFrozen (parameters.freezeMode)) setDamping (0.0f, 1.0f); else @@ -211,19 +217,15 @@ private: void setDamping (const float dampingToUse, const float roomSizeToUse) noexcept { - for (int j = 0; j < numChannels; ++j) - for (int i = numCombs; --i >= 0;) - comb[j][i].setFeedbackAndDamp (roomSizeToUse, dampingToUse); + damping.setValue (dampingToUse); + feedback.setValue (roomSizeToUse); } //============================================================================== class CombFilter { public: - CombFilter() noexcept - : bufferSize (0), bufferIndex (0), - feedback (0), last (0), damp1 (0), damp2 (0) - {} + CombFilter() noexcept : bufferSize (0), bufferIndex (0), last (0) {} void setSize (const int size) { @@ -243,22 +245,15 @@ private: buffer.clear ((size_t) bufferSize); } - void setFeedbackAndDamp (const float f, const float d) noexcept + float process (const float input, const float damp, const float feedbackLevel) noexcept { - damp1 = d; - damp2 = 1.0f - d; - feedback = f; - } - - inline float process (const float input) noexcept - { - const float output = buffer [bufferIndex]; - last = (output * damp2) + (last * damp1); + const float output = buffer[bufferIndex]; + last = (output * (1.0f - damp)) + (last * damp); JUCE_UNDENORMALISE (last); - float temp = input + (last * feedback); + float temp = input + (last * feedbackLevel); JUCE_UNDENORMALISE (temp); - buffer [bufferIndex] = temp; + buffer[bufferIndex] = temp; bufferIndex = (bufferIndex + 1) % bufferSize; return output; } @@ -266,7 +261,7 @@ private: private: HeapBlock buffer; int bufferSize, bufferIndex; - float feedback, last, damp1, damp2; + float last; JUCE_DECLARE_NON_COPYABLE (CombFilter) }; @@ -294,7 +289,7 @@ private: buffer.clear ((size_t) bufferSize); } - inline float process (const float input) noexcept + float process (const float input) noexcept { const float bufferedValue = buffer [bufferIndex]; float temp = input + (bufferedValue * 0.5f); @@ -311,11 +306,65 @@ private: JUCE_DECLARE_NON_COPYABLE (AllPassFilter) }; + //============================================================================== + class LinearSmoothedValue + { + public: + LinearSmoothedValue() noexcept + : currentValue (0), target (0), step (0), countdown (0), stepsToTarget (0) + { + } + + void reset (double sampleRate, double fadeLengthSeconds) noexcept + { + jassert (sampleRate > 0 && fadeLengthSeconds >= 0); + stepsToTarget = (int) std::floor (fadeLengthSeconds * sampleRate); + currentValue = target; + countdown = 0; + } + + void setValue (float newValue) noexcept + { + if (target != newValue) + { + target = newValue; + countdown = stepsToTarget; + + if (countdown <= 0) + currentValue = target; + else + step = (target - currentValue) / (float) countdown; + } + } + + float getNextValue() noexcept + { + if (countdown <= 0) + return target; + + --countdown; + currentValue += step; + return currentValue; + } + + private: + float currentValue, target, step; + int countdown, stepsToTarget; + + JUCE_DECLARE_NON_COPYABLE (LinearSmoothedValue) + }; + + //============================================================================== enum { numCombs = 8, numAllPasses = 4, numChannels = 2 }; + Parameters parameters; + float gain; + CombFilter comb [numChannels][numCombs]; AllPassFilter allPass [numChannels][numAllPasses]; + LinearSmoothedValue damping, feedback, dryGain, wetGain1, wetGain2; + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Reverb) }; diff --git a/JuceLibraryCode/modules/juce_audio_basics/juce_audio_basics.cpp b/JuceLibraryCode/modules/juce_audio_basics/juce_audio_basics.cpp index dcd53cd..05673cc 100644 --- a/JuceLibraryCode/modules/juce_audio_basics/juce_audio_basics.cpp +++ b/JuceLibraryCode/modules/juce_audio_basics/juce_audio_basics.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -57,13 +57,18 @@ #endif #if (JUCE_MAC || JUCE_IOS) && JUCE_USE_VDSP_FRAMEWORK + #define Point CarbonDummyPointName // (workaround to avoid definition of "Point" by old Carbon headers) #include + #undef Point #else #undef JUCE_USE_VDSP_FRAMEWORK #endif #if __ARM_NEON__ && ! (JUCE_USE_VDSP_FRAMEWORK || defined (JUCE_USE_ARM_NEON)) #define JUCE_USE_ARM_NEON 1 +#endif + +#if JUCE_USE_ARM_NEON #include #endif @@ -75,6 +80,7 @@ namespace juce #include "buffers/juce_FloatVectorOperations.cpp" #include "effects/juce_IIRFilter.cpp" #include "effects/juce_LagrangeInterpolator.cpp" +#include "effects/juce_FFT.cpp" #include "midi/juce_MidiBuffer.cpp" #include "midi/juce_MidiFile.cpp" #include "midi/juce_MidiKeyboardState.cpp" diff --git a/JuceLibraryCode/modules/juce_audio_basics/juce_audio_basics.h b/JuceLibraryCode/modules/juce_audio_basics/juce_audio_basics.h index 70c5432..bffa1ef 100644 --- a/JuceLibraryCode/modules/juce_audio_basics/juce_audio_basics.h +++ b/JuceLibraryCode/modules/juce_audio_basics/juce_audio_basics.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -31,12 +31,16 @@ namespace juce { +#undef Complex // apparently some C libraries actually define these symbols (!) +#undef Factor + #include "buffers/juce_AudioDataConverters.h" #include "buffers/juce_AudioSampleBuffer.h" #include "buffers/juce_FloatVectorOperations.h" #include "effects/juce_Decibels.h" #include "effects/juce_IIRFilter.h" #include "effects/juce_LagrangeInterpolator.h" +#include "effects/juce_FFT.h" #include "effects/juce_Reverb.h" #include "midi/juce_MidiMessage.h" #include "midi/juce_MidiBuffer.h" diff --git a/JuceLibraryCode/modules/juce_audio_basics/juce_audio_basics.mm b/JuceLibraryCode/modules/juce_audio_basics/juce_audio_basics.mm index 54083fd..33bccab 100644 --- a/JuceLibraryCode/modules/juce_audio_basics/juce_audio_basics.mm +++ b/JuceLibraryCode/modules/juce_audio_basics/juce_audio_basics.mm @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_audio_basics/juce_module_info b/JuceLibraryCode/modules/juce_audio_basics/juce_module_info index 79340c9..6621745 100644 --- a/JuceLibraryCode/modules/juce_audio_basics/juce_module_info +++ b/JuceLibraryCode/modules/juce_audio_basics/juce_module_info @@ -1,7 +1,7 @@ { "id": "juce_audio_basics", "name": "JUCE audio and midi data classes", - "version": "3.0.6", + "version": "3.2.0", "description": "Classes for audio buffer manipulation, midi message handling, synthesis, etc", "website": "http://www.juce.com/juce", "license": "GPL/Commercial", diff --git a/JuceLibraryCode/modules/juce_audio_basics/midi/juce_MidiBuffer.cpp b/JuceLibraryCode/modules/juce_audio_basics/midi/juce_MidiBuffer.cpp index 0a6a1f9..4fc1eb7 100644 --- a/JuceLibraryCode/modules/juce_audio_basics/midi/juce_MidiBuffer.cpp +++ b/JuceLibraryCode/modules/juce_audio_basics/midi/juce_MidiBuffer.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -26,12 +26,12 @@ namespace MidiBufferHelpers { inline int getEventTime (const void* const d) noexcept { - return *static_cast (d); + return readUnaligned (d); } inline uint16 getEventDataSize (const void* const d) noexcept { - return *reinterpret_cast (static_cast (d) + sizeof (int32)); + return readUnaligned (static_cast (d) + sizeof (int32)); } inline uint16 getEventTotalSize (const void* const d) noexcept @@ -124,8 +124,8 @@ void MidiBuffer::addEvent (const void* const newData, const int maxBytes, const data.insertMultiple (offset, 0, (int) newItemSize); uint8* const d = data.begin() + offset; - *reinterpret_cast (d) = sampleNumber; - *reinterpret_cast (d + 4) = (uint16) numBytes; + writeUnaligned (d, sampleNumber); + writeUnaligned (d + 4, static_cast (numBytes)); memcpy (d + 6, newData, (size_t) numBytes); } } @@ -210,7 +210,7 @@ bool MidiBuffer::Iterator::getNextEvent (const uint8* &midiData, int& numBytes, const int itemSize = MidiBufferHelpers::getEventDataSize (data); numBytes = itemSize; midiData = data + sizeof (int32) + sizeof (uint16); - data += sizeof (int32) + sizeof (uint16) + itemSize; + data += sizeof (int32) + sizeof (uint16) + (size_t) itemSize; return true; } @@ -223,7 +223,7 @@ bool MidiBuffer::Iterator::getNextEvent (MidiMessage& result, int& samplePositio samplePosition = MidiBufferHelpers::getEventTime (data); const int itemSize = MidiBufferHelpers::getEventDataSize (data); result = MidiMessage (data + sizeof (int32) + sizeof (uint16), itemSize, samplePosition); - data += sizeof (int32) + sizeof (uint16) + itemSize; + data += sizeof (int32) + sizeof (uint16) + (size_t) itemSize; return true; } diff --git a/JuceLibraryCode/modules/juce_audio_basics/midi/juce_MidiBuffer.h b/JuceLibraryCode/modules/juce_audio_basics/midi/juce_MidiBuffer.h index 7dfc458..d93ab52 100644 --- a/JuceLibraryCode/modules/juce_audio_basics/midi/juce_MidiBuffer.h +++ b/JuceLibraryCode/modules/juce_audio_basics/midi/juce_MidiBuffer.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -186,9 +186,10 @@ public: /** Retrieves a copy of the next event from the buffer. - @param result on return, this will be the message (the MidiMessage's timestamp - is not set) - @param samplePosition on return, this will be the position of the event + @param result on return, this will be the message. The MidiMessage's timestamp + is set to the same value as samplePosition. + @param samplePosition on return, this will be the position of the event, as a + sample index in the buffer @returns true if an event was found, or false if the iterator has reached the end of the buffer */ @@ -203,7 +204,8 @@ public: temporarily until the MidiBuffer is altered. @param numBytesOfMidiData on return, this is the number of bytes of data used by the midi message - @param samplePosition on return, this will be the position of the event + @param samplePosition on return, this will be the position of the event, as a + sample index in the buffer @returns true if an event was found, or false if the iterator has reached the end of the buffer */ diff --git a/JuceLibraryCode/modules/juce_audio_basics/midi/juce_MidiFile.cpp b/JuceLibraryCode/modules/juce_audio_basics/midi/juce_MidiFile.cpp index e798cc0..e24443b 100644 --- a/JuceLibraryCode/modules/juce_audio_basics/midi/juce_MidiFile.cpp +++ b/JuceLibraryCode/modules/juce_audio_basics/midi/juce_MidiFile.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_audio_basics/midi/juce_MidiFile.h b/JuceLibraryCode/modules/juce_audio_basics/midi/juce_MidiFile.h index 2a69937..7f98fc3 100644 --- a/JuceLibraryCode/modules/juce_audio_basics/midi/juce_MidiFile.h +++ b/JuceLibraryCode/modules/juce_audio_basics/midi/juce_MidiFile.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_audio_basics/midi/juce_MidiKeyboardState.cpp b/JuceLibraryCode/modules/juce_audio_basics/midi/juce_MidiKeyboardState.cpp index a40262b..287a4fa 100644 --- a/JuceLibraryCode/modules/juce_audio_basics/midi/juce_MidiKeyboardState.cpp +++ b/JuceLibraryCode/modules/juce_audio_basics/midi/juce_MidiKeyboardState.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -145,7 +145,7 @@ void MidiKeyboardState::processNextMidiBuffer (MidiBuffer& buffer, const bool injectIndirectEvents) { MidiBuffer::Iterator i (buffer); - MidiMessage message (0xf4, 0.0); + MidiMessage message; int time; const ScopedLock sl (lock); diff --git a/JuceLibraryCode/modules/juce_audio_basics/midi/juce_MidiKeyboardState.h b/JuceLibraryCode/modules/juce_audio_basics/midi/juce_MidiKeyboardState.h index 885b7d8..520dfec 100644 --- a/JuceLibraryCode/modules/juce_audio_basics/midi/juce_MidiKeyboardState.h +++ b/JuceLibraryCode/modules/juce_audio_basics/midi/juce_MidiKeyboardState.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_audio_basics/midi/juce_MidiMessage.cpp b/JuceLibraryCode/modules/juce_audio_basics/midi/juce_MidiMessage.cpp index 18733a3..5638afe 100644 --- a/JuceLibraryCode/modules/juce_audio_basics/midi/juce_MidiMessage.cpp +++ b/JuceLibraryCode/modules/juce_audio_basics/midi/juce_MidiMessage.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -129,7 +129,7 @@ MidiMessage::MidiMessage (const MidiMessage& other) { if (other.allocatedData != nullptr) { - allocatedData.malloc (size); + allocatedData.malloc ((size_t) size); memcpy (allocatedData, other.allocatedData, (size_t) size); } else @@ -143,7 +143,7 @@ MidiMessage::MidiMessage (const MidiMessage& other, const double newTimeStamp) { if (other.allocatedData != nullptr) { - allocatedData.malloc (size); + allocatedData.malloc ((size_t) size); memcpy (allocatedData, other.allocatedData, (size_t) size); } else @@ -255,7 +255,7 @@ MidiMessage& MidiMessage::operator= (const MidiMessage& other) if (other.allocatedData != nullptr) { - allocatedData.malloc (size); + allocatedData.malloc ((size_t) size); memcpy (allocatedData, other.allocatedData, (size_t) size); } else @@ -297,7 +297,7 @@ uint8* MidiMessage::allocateSpace (int bytes) { if (bytes > 4) { - allocatedData.malloc (bytes); + allocatedData.malloc ((size_t) bytes); return allocatedData; } @@ -661,7 +661,7 @@ String MidiMessage::getTextFromTextMetaEvent() const MidiMessage MidiMessage::textMetaEvent (int type, StringRef text) { - jassert (type > 0 && type < 16) + jassert (type > 0 && type < 16); MidiMessage result; diff --git a/JuceLibraryCode/modules/juce_audio_basics/midi/juce_MidiMessage.h b/JuceLibraryCode/modules/juce_audio_basics/midi/juce_MidiMessage.h index 9002aa0..6d59c59 100644 --- a/JuceLibraryCode/modules/juce_audio_basics/midi/juce_MidiMessage.h +++ b/JuceLibraryCode/modules/juce_audio_basics/midi/juce_MidiMessage.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_audio_basics/midi/juce_MidiMessageSequence.cpp b/JuceLibraryCode/modules/juce_audio_basics/midi/juce_MidiMessageSequence.cpp index 94a6b9b..dcac30e 100644 --- a/JuceLibraryCode/modules/juce_audio_basics/midi/juce_MidiMessageSequence.cpp +++ b/JuceLibraryCode/modules/juce_audio_basics/midi/juce_MidiMessageSequence.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -276,14 +276,11 @@ void MidiMessageSequence::deleteSysExMessages() } //============================================================================== -void MidiMessageSequence::createControllerUpdatesForTime (const int channelNumber, - const double time, - OwnedArray& dest) +void MidiMessageSequence::createControllerUpdatesForTime (const int channelNumber, const double time, Array& dest) { bool doneProg = false; bool donePitchWheel = false; - Array doneControllers; - doneControllers.ensureStorageAllocated (32); + bool doneControllers[128] = { 0 }; for (int i = list.size(); --i >= 0;) { @@ -291,28 +288,25 @@ void MidiMessageSequence::createControllerUpdatesForTime (const int channelNumbe if (mm.isForChannel (channelNumber) && mm.getTimeStamp() <= time) { - if (mm.isProgramChange()) + if (mm.isProgramChange() && ! doneProg) { - if (! doneProg) - { - dest.add (new MidiMessage (mm, 0.0)); - doneProg = true; - } + doneProg = true; + dest.add (MidiMessage (mm, 0.0)); + } + else if (mm.isPitchWheel() && ! donePitchWheel) + { + donePitchWheel = true; + dest.add (MidiMessage (mm, 0.0)); } else if (mm.isController()) { - if (! doneControllers.contains (mm.getControllerNumber())) + const int controllerNumber = mm.getControllerNumber(); + jassert (isPositiveAndBelow (controllerNumber, 128)); + + if (! doneControllers[controllerNumber]) { - dest.add (new MidiMessage (mm, 0.0)); - doneControllers.add (mm.getControllerNumber()); - } - } - else if (mm.isPitchWheel()) - { - if (! donePitchWheel) - { - dest.add (new MidiMessage (mm, 0.0)); - donePitchWheel = true; + doneControllers[controllerNumber] = true; + dest.add (MidiMessage (mm, 0.0)); } } } diff --git a/JuceLibraryCode/modules/juce_audio_basics/midi/juce_MidiMessageSequence.h b/JuceLibraryCode/modules/juce_audio_basics/midi/juce_MidiMessageSequence.h index b62940c..5d2f977 100644 --- a/JuceLibraryCode/modules/juce_audio_basics/midi/juce_MidiMessageSequence.h +++ b/JuceLibraryCode/modules/juce_audio_basics/midi/juce_MidiMessageSequence.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -247,7 +247,7 @@ public: state at the required time. */ void createControllerUpdatesForTime (int channelNumber, double time, - OwnedArray& resultMessages); + Array& resultMessages); //============================================================================== /** Swaps this sequence with another one. */ diff --git a/JuceLibraryCode/modules/juce_audio_basics/sources/juce_AudioSource.h b/JuceLibraryCode/modules/juce_audio_basics/sources/juce_AudioSource.h index cfbd59f..9708530 100644 --- a/JuceLibraryCode/modules/juce_audio_basics/sources/juce_AudioSource.h +++ b/JuceLibraryCode/modules/juce_audio_basics/sources/juce_AudioSource.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_audio_basics/sources/juce_BufferingAudioSource.cpp b/JuceLibraryCode/modules/juce_audio_basics/sources/juce_BufferingAudioSource.cpp index 21dc173..c47cc5e 100644 --- a/JuceLibraryCode/modules/juce_audio_basics/sources/juce_BufferingAudioSource.cpp +++ b/JuceLibraryCode/modules/juce_audio_basics/sources/juce_BufferingAudioSource.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_audio_basics/sources/juce_BufferingAudioSource.h b/JuceLibraryCode/modules/juce_audio_basics/sources/juce_BufferingAudioSource.h index b0ab4d2..4d507d7 100644 --- a/JuceLibraryCode/modules/juce_audio_basics/sources/juce_BufferingAudioSource.h +++ b/JuceLibraryCode/modules/juce_audio_basics/sources/juce_BufferingAudioSource.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_audio_basics/sources/juce_ChannelRemappingAudioSource.cpp b/JuceLibraryCode/modules/juce_audio_basics/sources/juce_ChannelRemappingAudioSource.cpp index 7e0a58c..ac06074 100644 --- a/JuceLibraryCode/modules/juce_audio_basics/sources/juce_ChannelRemappingAudioSource.cpp +++ b/JuceLibraryCode/modules/juce_audio_basics/sources/juce_ChannelRemappingAudioSource.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_audio_basics/sources/juce_ChannelRemappingAudioSource.h b/JuceLibraryCode/modules/juce_audio_basics/sources/juce_ChannelRemappingAudioSource.h index 483fe99..1c44aa4 100644 --- a/JuceLibraryCode/modules/juce_audio_basics/sources/juce_ChannelRemappingAudioSource.h +++ b/JuceLibraryCode/modules/juce_audio_basics/sources/juce_ChannelRemappingAudioSource.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_audio_basics/sources/juce_IIRFilterAudioSource.cpp b/JuceLibraryCode/modules/juce_audio_basics/sources/juce_IIRFilterAudioSource.cpp index 08e87f0..4305a39 100644 --- a/JuceLibraryCode/modules/juce_audio_basics/sources/juce_IIRFilterAudioSource.cpp +++ b/JuceLibraryCode/modules/juce_audio_basics/sources/juce_IIRFilterAudioSource.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_audio_basics/sources/juce_IIRFilterAudioSource.h b/JuceLibraryCode/modules/juce_audio_basics/sources/juce_IIRFilterAudioSource.h index 40844c5..ef3da93 100644 --- a/JuceLibraryCode/modules/juce_audio_basics/sources/juce_IIRFilterAudioSource.h +++ b/JuceLibraryCode/modules/juce_audio_basics/sources/juce_IIRFilterAudioSource.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_audio_basics/sources/juce_MixerAudioSource.cpp b/JuceLibraryCode/modules/juce_audio_basics/sources/juce_MixerAudioSource.cpp index 60ae191..14a3f87 100644 --- a/JuceLibraryCode/modules/juce_audio_basics/sources/juce_MixerAudioSource.cpp +++ b/JuceLibraryCode/modules/juce_audio_basics/sources/juce_MixerAudioSource.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_audio_basics/sources/juce_MixerAudioSource.h b/JuceLibraryCode/modules/juce_audio_basics/sources/juce_MixerAudioSource.h index f581ac3..98269c5 100644 --- a/JuceLibraryCode/modules/juce_audio_basics/sources/juce_MixerAudioSource.h +++ b/JuceLibraryCode/modules/juce_audio_basics/sources/juce_MixerAudioSource.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_audio_basics/sources/juce_PositionableAudioSource.h b/JuceLibraryCode/modules/juce_audio_basics/sources/juce_PositionableAudioSource.h index 2213722..2084f0b 100644 --- a/JuceLibraryCode/modules/juce_audio_basics/sources/juce_PositionableAudioSource.h +++ b/JuceLibraryCode/modules/juce_audio_basics/sources/juce_PositionableAudioSource.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_audio_basics/sources/juce_ResamplingAudioSource.cpp b/JuceLibraryCode/modules/juce_audio_basics/sources/juce_ResamplingAudioSource.cpp index 52fc730..d4b68e3 100644 --- a/JuceLibraryCode/modules/juce_audio_basics/sources/juce_ResamplingAudioSource.cpp +++ b/JuceLibraryCode/modules/juce_audio_basics/sources/juce_ResamplingAudioSource.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -24,14 +24,14 @@ ResamplingAudioSource::ResamplingAudioSource (AudioSource* const inputSource, const bool deleteInputWhenDeleted, - const int numChannels_) + const int channels) : input (inputSource, deleteInputWhenDeleted), ratio (1.0), lastRatio (1.0), bufferPos (0), sampsInBuffer (0), subSampleOffset (0), - numChannels (numChannels_) + numChannels (channels) { jassert (input != nullptr); zeromem (coefficients, sizeof (coefficients)); @@ -47,23 +47,29 @@ void ResamplingAudioSource::setResamplingRatio (const double samplesInPerOutputS ratio = jmax (0.0, samplesInPerOutputSample); } -void ResamplingAudioSource::prepareToPlay (int samplesPerBlockExpected, - double sampleRate) +void ResamplingAudioSource::prepareToPlay (int samplesPerBlockExpected, double sampleRate) { const SpinLock::ScopedLockType sl (ratioLock); - input->prepareToPlay (samplesPerBlockExpected, sampleRate); + const int scaledBlockSize = roundToInt (samplesPerBlockExpected * ratio); + input->prepareToPlay (scaledBlockSize, sampleRate * ratio); - buffer.setSize (numChannels, roundToInt (samplesPerBlockExpected * ratio) + 32); - buffer.clear(); - sampsInBuffer = 0; - bufferPos = 0; - subSampleOffset = 0.0; + buffer.setSize (numChannels, scaledBlockSize + 32); filterStates.calloc ((size_t) numChannels); srcBuffers.calloc ((size_t) numChannels); destBuffers.calloc ((size_t) numChannels); createLowPass (ratio); + + flushBuffers(); +} + +void ResamplingAudioSource::flushBuffers() +{ + buffer.clear(); + bufferPos = 0; + sampsInBuffer = 0; + subSampleOffset = 0.0; resetFilters(); } @@ -88,7 +94,7 @@ void ResamplingAudioSource::getNextAudioBlock (const AudioSourceChannelInfo& inf lastRatio = localRatio; } - const int sampsNeeded = roundToInt (info.numSamples * localRatio) + 2; + const int sampsNeeded = roundToInt (info.numSamples * localRatio) + 3; int bufferSize = buffer.getNumSamples(); @@ -133,8 +139,11 @@ void ResamplingAudioSource::getNextAudioBlock (const AudioSourceChannelInfo& inf } int nextPos = (bufferPos + 1) % bufferSize; + for (int m = info.numSamples; --m >= 0;) { + jassert (sampsInBuffer > 0 && nextPos != endOfBufferPos); + const float alpha = (float) subSampleOffset; for (int channel = 0; channel < channelsToProcess; ++channel) @@ -143,8 +152,6 @@ void ResamplingAudioSource::getNextAudioBlock (const AudioSourceChannelInfo& inf subSampleOffset += localRatio; - jassert (sampsInBuffer > 0); - while (subSampleOffset >= 1.0) { if (++bufferPos >= bufferSize) @@ -225,7 +232,8 @@ void ResamplingAudioSource::setFilterCoefficients (double c1, double c2, double void ResamplingAudioSource::resetFilters() { - filterStates.clear ((size_t) numChannels); + if (filterStates != nullptr) + filterStates.clear ((size_t) numChannels); } void ResamplingAudioSource::applyFilter (float* samples, int num, FilterState& fs) diff --git a/JuceLibraryCode/modules/juce_audio_basics/sources/juce_ResamplingAudioSource.h b/JuceLibraryCode/modules/juce_audio_basics/sources/juce_ResamplingAudioSource.h index 20886e6..09491cb 100644 --- a/JuceLibraryCode/modules/juce_audio_basics/sources/juce_ResamplingAudioSource.h +++ b/JuceLibraryCode/modules/juce_audio_basics/sources/juce_ResamplingAudioSource.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -66,6 +66,9 @@ public: */ double getResamplingRatio() const noexcept { return ratio; } + /** Clears any buffers and filters that the resampler is using. */ + void flushBuffers(); + //============================================================================== void prepareToPlay (int samplesPerBlockExpected, double sampleRate) override; void releaseResources() override; diff --git a/JuceLibraryCode/modules/juce_audio_basics/sources/juce_ReverbAudioSource.cpp b/JuceLibraryCode/modules/juce_audio_basics/sources/juce_ReverbAudioSource.cpp index d630075..4701855 100644 --- a/JuceLibraryCode/modules/juce_audio_basics/sources/juce_ReverbAudioSource.cpp +++ b/JuceLibraryCode/modules/juce_audio_basics/sources/juce_ReverbAudioSource.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_audio_basics/sources/juce_ReverbAudioSource.h b/JuceLibraryCode/modules/juce_audio_basics/sources/juce_ReverbAudioSource.h index 6b90e18..547a44e 100644 --- a/JuceLibraryCode/modules/juce_audio_basics/sources/juce_ReverbAudioSource.h +++ b/JuceLibraryCode/modules/juce_audio_basics/sources/juce_ReverbAudioSource.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_audio_basics/sources/juce_ToneGeneratorAudioSource.cpp b/JuceLibraryCode/modules/juce_audio_basics/sources/juce_ToneGeneratorAudioSource.cpp index a0e04ef..05ec255 100644 --- a/JuceLibraryCode/modules/juce_audio_basics/sources/juce_ToneGeneratorAudioSource.cpp +++ b/JuceLibraryCode/modules/juce_audio_basics/sources/juce_ToneGeneratorAudioSource.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_audio_basics/sources/juce_ToneGeneratorAudioSource.h b/JuceLibraryCode/modules/juce_audio_basics/sources/juce_ToneGeneratorAudioSource.h index 5d09ad8..c45143d 100644 --- a/JuceLibraryCode/modules/juce_audio_basics/sources/juce_ToneGeneratorAudioSource.h +++ b/JuceLibraryCode/modules/juce_audio_basics/sources/juce_ToneGeneratorAudioSource.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_audio_basics/synthesisers/juce_Synthesiser.cpp b/JuceLibraryCode/modules/juce_audio_basics/synthesisers/juce_Synthesiser.cpp index 7a72d00..16ef359 100644 --- a/JuceLibraryCode/modules/juce_audio_basics/synthesisers/juce_Synthesiser.cpp +++ b/JuceLibraryCode/modules/juce_audio_basics/synthesisers/juce_Synthesiser.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -29,8 +29,10 @@ SynthesiserSound::~SynthesiserSound() {} SynthesiserVoice::SynthesiserVoice() : currentSampleRate (44100.0), currentlyPlayingNote (-1), + currentPlayingMidiChannel (0), noteOnTime (0), keyIsDown (false), + sustainPedalDown (false), sostenutoPedalDown (false) { } @@ -41,8 +43,7 @@ SynthesiserVoice::~SynthesiserVoice() bool SynthesiserVoice::isPlayingChannel (const int midiChannel) const { - return currentlyPlayingSound != nullptr - && currentlyPlayingSound->appliesToChannel (midiChannel); + return currentPlayingMidiChannel == midiChannel; } void SynthesiserVoice::setCurrentPlaybackSampleRate (const double newRate) @@ -50,13 +51,20 @@ void SynthesiserVoice::setCurrentPlaybackSampleRate (const double newRate) currentSampleRate = newRate; } +bool SynthesiserVoice::isVoiceActive() const +{ + return getCurrentlyPlayingNote() >= 0; +} + void SynthesiserVoice::clearCurrentNote() { currentlyPlayingNote = -1; currentlyPlayingSound = nullptr; + currentPlayingMidiChannel = 0; } void SynthesiserVoice::aftertouchChanged (int) {} +void SynthesiserVoice::channelPressureChanged (int) {} bool SynthesiserVoice::wasStartedBefore (const SynthesiserVoice& other) const noexcept { @@ -67,6 +75,7 @@ bool SynthesiserVoice::wasStartedBefore (const SynthesiserVoice& other) const no Synthesiser::Synthesiser() : sampleRate (0), lastNoteOnCounter (0), + minimumSubBlockSize (32), shouldStealNotes (true) { for (int i = 0; i < numElementsInArray (lastPitchWheelValues); ++i) @@ -125,6 +134,12 @@ void Synthesiser::setNoteStealingEnabled (const bool shouldSteal) shouldStealNotes = shouldSteal; } +void Synthesiser::setMinimumRenderingSubdivisionSize (int numSamples) noexcept +{ + jassert (numSamples > 0); // it wouldn't make much sense for this to be less than 1 + minimumSubBlockSize = numSamples; +} + //============================================================================== void Synthesiser::setCurrentPlaybackSampleRate (const double newRate) { @@ -147,64 +162,90 @@ void Synthesiser::renderNextBlock (AudioSampleBuffer& outputBuffer, const MidiBu // must set the sample rate before using this! jassert (sampleRate != 0); - const ScopedLock sl (lock); - MidiBuffer::Iterator midiIterator (midiData); midiIterator.setNextSamplePosition (startSample); - MidiMessage m (0xf4, 0.0); + + int midiEventPos; + MidiMessage m; + + const ScopedLock sl (lock); while (numSamples > 0) { - int midiEventPos; - const bool useEvent = midiIterator.getNextEvent (m, midiEventPos) - && midiEventPos < startSample + numSamples; - - const int numThisTime = useEvent ? midiEventPos - startSample - : numSamples; - - if (numThisTime > 0) + if (! midiIterator.getNextEvent (m, midiEventPos)) { - for (int i = voices.size(); --i >= 0;) - voices.getUnchecked (i)->renderNextBlock (outputBuffer, startSample, numThisTime); + renderVoices (outputBuffer, startSample, numSamples); + return; } - if (useEvent) - handleMidiEvent (m); + const int samplesToNextMidiMessage = midiEventPos - startSample; - startSample += numThisTime; - numSamples -= numThisTime; + if (samplesToNextMidiMessage >= numSamples) + { + renderVoices (outputBuffer, startSample, numSamples); + handleMidiEvent (m); + break; + } + + if (samplesToNextMidiMessage < minimumSubBlockSize) + { + handleMidiEvent (m); + continue; + } + + renderVoices (outputBuffer, startSample, samplesToNextMidiMessage); + handleMidiEvent (m); + startSample += samplesToNextMidiMessage; + numSamples -= samplesToNextMidiMessage; } + + while (midiIterator.getNextEvent (m, midiEventPos)) + handleMidiEvent (m); +} + +void Synthesiser::renderVoices (AudioSampleBuffer& buffer, int startSample, int numSamples) +{ + for (int i = voices.size(); --i >= 0;) + voices.getUnchecked (i)->renderNextBlock (buffer, startSample, numSamples); } void Synthesiser::handleMidiEvent (const MidiMessage& m) { + const int channel = m.getChannel(); + if (m.isNoteOn()) { - noteOn (m.getChannel(), m.getNoteNumber(), m.getFloatVelocity()); + noteOn (channel, m.getNoteNumber(), m.getFloatVelocity()); } else if (m.isNoteOff()) { - noteOff (m.getChannel(), m.getNoteNumber(), true); + noteOff (channel, m.getNoteNumber(), m.getFloatVelocity(), true); } else if (m.isAllNotesOff() || m.isAllSoundOff()) { - allNotesOff (m.getChannel(), true); + allNotesOff (channel, true); } else if (m.isPitchWheel()) { - const int channel = m.getChannel(); const int wheelPos = m.getPitchWheelValue(); lastPitchWheelValues [channel - 1] = wheelPos; - handlePitchWheel (channel, wheelPos); } else if (m.isAftertouch()) { - handleAftertouch (m.getChannel(), m.getNoteNumber(), m.getAfterTouchValue()); + handleAftertouch (channel, m.getNoteNumber(), m.getAfterTouchValue()); + } + else if (m.isChannelPressure()) + { + handleChannelPressure (channel, m.getChannelPressureValue()); } else if (m.isController()) { - handleController (m.getChannel(), m.getControllerNumber(), m.getControllerValue()); + handleController (channel, m.getControllerNumber(), m.getControllerValue()); + } + else if (m.isProgramChange()) + { + handleProgramChange (channel, m.getProgramChangeNumber()); } } @@ -230,10 +271,10 @@ void Synthesiser::noteOn (const int midiChannel, if (voice->getCurrentlyPlayingNote() == midiNoteNumber && voice->isPlayingChannel (midiChannel)) - stopVoice (voice, true); + stopVoice (voice, 1.0f, true); } - startVoice (findFreeVoice (sound, shouldStealNotes), + startVoice (findFreeVoice (sound, midiChannel, midiNoteNumber, shouldStealNotes), sound, midiChannel, midiNoteNumber, velocity); } } @@ -248,24 +289,26 @@ void Synthesiser::startVoice (SynthesiserVoice* const voice, if (voice != nullptr && sound != nullptr) { if (voice->currentlyPlayingSound != nullptr) - voice->stopNote (false); - - voice->startNote (midiNoteNumber, velocity, sound, - lastPitchWheelValues [midiChannel - 1]); + voice->stopNote (0.0f, false); voice->currentlyPlayingNote = midiNoteNumber; + voice->currentPlayingMidiChannel = midiChannel; voice->noteOnTime = ++lastNoteOnCounter; voice->currentlyPlayingSound = sound; voice->keyIsDown = true; voice->sostenutoPedalDown = false; + voice->sustainPedalDown = sustainPedalsDown[midiChannel]; + + voice->startNote (midiNoteNumber, velocity, sound, + lastPitchWheelValues [midiChannel - 1]); } } -void Synthesiser::stopVoice (SynthesiserVoice* voice, const bool allowTailOff) +void Synthesiser::stopVoice (SynthesiserVoice* voice, float velocity, const bool allowTailOff) { jassert (voice != nullptr); - voice->stopNote (allowTailOff); + voice->stopNote (velocity, allowTailOff); // the subclass MUST call clearCurrentNote() if it's not tailing off! RTFM for stopNote()! jassert (allowTailOff || (voice->getCurrentlyPlayingNote() < 0 && voice->getCurrentlyPlayingSound() == 0)); @@ -273,6 +316,7 @@ void Synthesiser::stopVoice (SynthesiserVoice* voice, const bool allowTailOff) void Synthesiser::noteOff (const int midiChannel, const int midiNoteNumber, + const float velocity, const bool allowTailOff) { const ScopedLock sl (lock); @@ -281,17 +325,20 @@ void Synthesiser::noteOff (const int midiChannel, { SynthesiserVoice* const voice = voices.getUnchecked (i); - if (voice->getCurrentlyPlayingNote() == midiNoteNumber) + if (voice->getCurrentlyPlayingNote() == midiNoteNumber + && voice->isPlayingChannel (midiChannel)) { if (SynthesiserSound* const sound = voice->getCurrentlyPlayingSound()) { if (sound->appliesToNote (midiNoteNumber) && sound->appliesToChannel (midiChannel)) { + jassert (! voice->keyIsDown || voice->sustainPedalDown == sustainPedalsDown [midiChannel]); + voice->keyIsDown = false; - if (! (sustainPedalsDown [midiChannel] || voice->sostenutoPedalDown)) - stopVoice (voice, allowTailOff); + if (! (voice->sustainPedalDown || voice->sostenutoPedalDown)) + stopVoice (voice, velocity, allowTailOff); } } } @@ -307,7 +354,7 @@ void Synthesiser::allNotesOff (const int midiChannel, const bool allowTailOff) SynthesiserVoice* const voice = voices.getUnchecked (i); if (midiChannel <= 0 || voice->isPlayingChannel (midiChannel)) - voice->stopNote (allowTailOff); + voice->stopNote (1.0f, allowTailOff); } sustainPedalsDown.clear(); @@ -363,6 +410,19 @@ void Synthesiser::handleAftertouch (int midiChannel, int midiNoteNumber, int aft } } +void Synthesiser::handleChannelPressure (int midiChannel, int channelPressureValue) +{ + const ScopedLock sl (lock); + + for (int i = voices.size(); --i >= 0;) + { + SynthesiserVoice* const voice = voices.getUnchecked (i); + + if (midiChannel <= 0 || voice->isPlayingChannel (midiChannel)) + voice->channelPressureChanged (channelPressureValue); + } +} + void Synthesiser::handleSustainPedal (int midiChannel, bool isDown) { jassert (midiChannel > 0 && midiChannel <= 16); @@ -371,6 +431,14 @@ void Synthesiser::handleSustainPedal (int midiChannel, bool isDown) if (isDown) { sustainPedalsDown.setBit (midiChannel); + + for (int i = voices.size(); --i >= 0;) + { + SynthesiserVoice* const voice = voices.getUnchecked (i); + + if (voice->isPlayingChannel (midiChannel) && voice->isKeyDown()) + voice->sustainPedalDown = true; + } } else { @@ -378,8 +446,13 @@ void Synthesiser::handleSustainPedal (int midiChannel, bool isDown) { SynthesiserVoice* const voice = voices.getUnchecked (i); - if (voice->isPlayingChannel (midiChannel) && ! voice->keyIsDown) - stopVoice (voice, true); + if (voice->isPlayingChannel (midiChannel)) + { + voice->sustainPedalDown = false; + + if (! voice->isKeyDown()) + stopVoice (voice, 1.0f, true); + } } sustainPedalsDown.clearBit (midiChannel); @@ -400,7 +473,7 @@ void Synthesiser::handleSostenutoPedal (int midiChannel, bool isDown) if (isDown) voice->sostenutoPedalDown = true; else if (voice->sostenutoPedalDown) - stopVoice (voice, true); + stopVoice (voice, 1.0f, true); } } } @@ -411,8 +484,16 @@ void Synthesiser::handleSoftPedal (int midiChannel, bool /*isDown*/) jassert (midiChannel > 0 && midiChannel <= 16); } +void Synthesiser::handleProgramChange (int midiChannel, int programNumber) +{ + (void) midiChannel; (void) programNumber; + jassert (midiChannel > 0 && midiChannel <= 16); +} + //============================================================================== -SynthesiserVoice* Synthesiser::findFreeVoice (SynthesiserSound* soundToPlay, const bool stealIfNoneAvailable) const +SynthesiserVoice* Synthesiser::findFreeVoice (SynthesiserSound* soundToPlay, + int midiChannel, int midiNoteNumber, + const bool stealIfNoneAvailable) const { const ScopedLock sl (lock); @@ -420,30 +501,111 @@ SynthesiserVoice* Synthesiser::findFreeVoice (SynthesiserSound* soundToPlay, con { SynthesiserVoice* const voice = voices.getUnchecked (i); - if (voice->getCurrentlyPlayingNote() < 0 && voice->canPlaySound (soundToPlay)) + if ((! voice->isVoiceActive()) && voice->canPlaySound (soundToPlay)) return voice; } if (stealIfNoneAvailable) - return findVoiceToSteal (soundToPlay); + return findVoiceToSteal (soundToPlay, midiChannel, midiNoteNumber); return nullptr; } -SynthesiserVoice* Synthesiser::findVoiceToSteal (SynthesiserSound* soundToPlay) const +struct VoiceAgeSorter { - // currently this just steals the one that's been playing the longest, but could be made a bit smarter.. - SynthesiserVoice* oldest = nullptr; + static int compareElements (SynthesiserVoice* v1, SynthesiserVoice* v2) noexcept + { + return v1->wasStartedBefore (*v2) ? -1 : (v2->wasStartedBefore (*v1) ? 1 : 0); + } +}; + +SynthesiserVoice* Synthesiser::findVoiceToSteal (SynthesiserSound* soundToPlay, + int /*midiChannel*/, int midiNoteNumber) const +{ + // This voice-stealing algorithm applies the following heuristics: + // - Re-use the oldest notes first + // - Protect the lowest & topmost notes, even if sustained, but not if they've been released. + + // These are the voices we want to protect (ie: only steal if unavoidable) + SynthesiserVoice* low = nullptr; // Lowest sounding note, might be sustained, but NOT in release phase + SynthesiserVoice* top = nullptr; // Highest sounding note, might be sustained, but NOT in release phase + + // this is a list of voices we can steal, sorted by how long they've been running + Array usableVoices; + usableVoices.ensureStorageAllocated (voices.size()); for (int i = 0; i < voices.size(); ++i) { SynthesiserVoice* const voice = voices.getUnchecked (i); - if (voice->canPlaySound (soundToPlay) - && (oldest == nullptr || voice->wasStartedBefore (*oldest))) - oldest = voice; + if (voice->canPlaySound (soundToPlay)) + { + jassert (voice->isVoiceActive()); // We wouldn't be here otherwise + + VoiceAgeSorter sorter; + usableVoices.addSorted (sorter, voice); + + if (! voice->isPlayingButReleased()) // Don't protect released notes + { + const int note = voice->getCurrentlyPlayingNote(); + + if (low == nullptr || note < low->getCurrentlyPlayingNote()) + low = voice; + + if (top == nullptr || note > top->getCurrentlyPlayingNote()) + top = voice; + } + } } - jassert (oldest != nullptr); - return oldest; + // Eliminate pathological cases (ie: only 1 note playing): we always give precedence to the lowest note(s) + if (top == low) + top = nullptr; + + const int numUsableVoices = usableVoices.size(); + + // The oldest note that's playing with the target pitch is ideal.. + for (int i = 0; i < numUsableVoices; ++i) + { + SynthesiserVoice* const voice = usableVoices.getUnchecked (i); + + if (voice->getCurrentlyPlayingNote() == midiNoteNumber) + return voice; + } + + // Oldest voice that has been released (no finger on it and not held by sustain pedal) + for (int i = 0; i < numUsableVoices; ++i) + { + SynthesiserVoice* const voice = usableVoices.getUnchecked (i); + + if (voice != low && voice != top && voice->isPlayingButReleased()) + return voice; + } + + // Oldest voice that doesn't have a finger on it: + for (int i = 0; i < numUsableVoices; ++i) + { + SynthesiserVoice* const voice = usableVoices.getUnchecked (i); + + if (voice != low && voice != top && ! voice->isKeyDown()) + return voice; + } + + // Oldest voice that isn't protected + for (int i = 0; i < numUsableVoices; ++i) + { + SynthesiserVoice* const voice = usableVoices.getUnchecked (i); + + if (voice != low && voice != top) + return voice; + } + + // We've only got "protected" voices now: lowest note takes priority + jassert (low != nullptr); + + // Duophonic synth: give priority to the bass note: + if (top != nullptr) + return top; + + return low; } diff --git a/JuceLibraryCode/modules/juce_audio_basics/synthesisers/juce_Synthesiser.h b/JuceLibraryCode/modules/juce_audio_basics/synthesisers/juce_Synthesiser.h index e765697..7052b00 100644 --- a/JuceLibraryCode/modules/juce_audio_basics/synthesisers/juce_Synthesiser.h +++ b/JuceLibraryCode/modules/juce_audio_basics/synthesisers/juce_Synthesiser.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -55,14 +55,14 @@ public: The Synthesiser will use this information when deciding which sounds to trigger for a given note. */ - virtual bool appliesToNote (const int midiNoteNumber) = 0; + virtual bool appliesToNote (int midiNoteNumber) = 0; /** Returns true if the sound should be triggered by midi events on a given channel. The Synthesiser will use this information when deciding which sounds to trigger for a given note. */ - virtual bool appliesToChannel (const int midiChannel) = 0; + virtual bool appliesToChannel (int midiChannel) = 0; /** The class is reference-counted, so this is a handy pointer class for it. */ typedef ReferenceCountedObjectPtr Ptr; @@ -127,6 +127,8 @@ public: This will be called during the rendering callback, so must be fast and thread-safe. + The velocity indicates how quickly the note was released - 0 is slowly, 1 is quickly. + If allowTailOff is false or the voice doesn't want to tail-off, then it must stop all sound immediately, and must call clearCurrentNote() to reset the state of this voice and allow the synth to reassign it another sound. @@ -136,7 +138,13 @@ public: finishes playing (during the rendering callback), it must make sure that it calls clearCurrentNote(). */ - virtual void stopNote (bool allowTailOff) = 0; + virtual void stopNote (float velocity, bool allowTailOff) = 0; + + /** Returns true if this voice is currently busy playing a sound. + By default this just checks the getCurrentlyPlayingNote() value, but can + be overridden for more advanced checking. + */ + virtual bool isVoiceActive() const; /** Called to let the voice know that the pitch wheel has been moved. This will be called during the rendering callback, so must be fast and thread-safe. @@ -153,6 +161,11 @@ public: */ virtual void aftertouchChanged (int newAftertouchValue); + /** Called to let the voice know that the channel pressure has changed. + This will be called during the rendering callback, so must be fast and thread-safe. + */ + virtual void channelPressureChanged (int newChannelPressureValue); + //============================================================================== /** Renders the next block of data for this voice. @@ -173,13 +186,6 @@ public: int startSample, int numSamples) = 0; - /** Returns true if the voice is currently playing a sound which is mapped to the given - midi channel. - - If it's not currently playing, this will return false. - */ - bool isPlayingChannel (int midiChannel) const; - /** Changes the voice's reference sample rate. The rate is set so that subclasses know the output rate and can set their pitch @@ -188,7 +194,19 @@ public: This method is called by the synth, and subclasses can access the current rate with the currentSampleRate member. */ - void setCurrentPlaybackSampleRate (double newRate); + virtual void setCurrentPlaybackSampleRate (double newRate); + + /** Returns true if the voice is currently playing a sound which is mapped to the given + midi channel. + + If it's not currently playing, this will return false. + */ + virtual bool isPlayingChannel (int midiChannel) const; + + /** Returns the current target sample rate at which rendering is being done. + Subclasses may need to know this so that they can pitch things correctly. + */ + double getSampleRate() const noexcept { return currentSampleRate; } /** Returns true if the key that triggered this voice is still held down. Note that the voice may still be playing after the key was released (e.g because the @@ -196,20 +214,22 @@ public: */ bool isKeyDown() const noexcept { return keyIsDown; } + /** Returns true if the sustain pedal is currently active for this voice. */ + bool isSustainPedalDown() const noexcept { return sustainPedalDown; } + /** Returns true if the sostenuto pedal is currently active for this voice. */ bool isSostenutoPedalDown() const noexcept { return sostenutoPedalDown; } + /** Returns true if a voice is sounding in its release phase **/ + bool isPlayingButReleased() const noexcept + { + return isVoiceActive() && ! (isKeyDown() || isSostenutoPedalDown() || isSustainPedalDown()); + } + /** Returns true if this voice started playing its current note before the other voice did. */ bool wasStartedBefore (const SynthesiserVoice& other) const noexcept; protected: - //============================================================================== - /** Returns the current target sample rate at which rendering is being done. - - This is available for subclasses so they can pitch things correctly. - */ - double getSampleRate() const { return currentSampleRate; } - /** Resets the state of this voice after a sound has finished playing. The subclass must call this when it finishes playing a note and becomes available @@ -230,10 +250,15 @@ private: friend class Synthesiser; double currentSampleRate; - int currentlyPlayingNote; + int currentlyPlayingNote, currentPlayingMidiChannel; uint32 noteOnTime; SynthesiserSound::Ptr currentlyPlayingSound; - bool keyIsDown, sostenutoPedalDown; + bool keyIsDown, sustainPedalDown, sostenutoPedalDown; + + #if JUCE_CATCH_DEPRECATED_CODE_MISUSE + // Note the new parameters for this method. + virtual int stopNote (bool) { return 0; } + #endif JUCE_LEAK_DETECTOR (SynthesiserVoice) }; @@ -268,8 +293,7 @@ class JUCE_API Synthesiser public: //============================================================================== /** Creates a new synthesiser. - - You'll need to add some sounds and voices before it'll make any sound.. + You'll need to add some sounds and voices before it'll make any sound. */ Synthesiser(); @@ -365,6 +389,7 @@ public: */ virtual void noteOff (int midiChannel, int midiNoteNumber, + float velocity, bool allowTailOff); /** Turns off all notes. @@ -429,6 +454,20 @@ public: */ virtual void handleAftertouch (int midiChannel, int midiNoteNumber, int aftertouchValue); + /** Sends a channel pressure message. + + This will send a channel pressure message to any voices that are playing sounds on + the given midi channel. + + This method will be called automatically according to the midi data passed into + renderNextBlock(), but may be called explicitly too. + + @param midiChannel the midi channel, from 1 to 16 inclusive + @param channelPressureValue the pressure value, between 0 and 127, as returned + by MidiMessage::getChannelPressureValue() + */ + virtual void handleChannelPressure (int midiChannel, int channelPressureValue); + /** Handles a sustain pedal event. */ virtual void handleSustainPedal (int midiChannel, bool isDown); @@ -438,13 +477,20 @@ public: /** Can be overridden to handle soft pedal events. */ virtual void handleSoftPedal (int midiChannel, bool isDown); + /** Can be overridden to handle an incoming program change message. + The base class implementation of this has no effect, but you may want to make your + own synth react to program changes. + */ + virtual void handleProgramChange (int midiChannel, + int programNumber); + //============================================================================== /** Tells the synthesiser what the sample rate is for the audio it's being used to render. This value is propagated to the voices so that they can use it to render the correct pitches. */ - void setCurrentPlaybackSampleRate (double sampleRate); + virtual void setCurrentPlaybackSampleRate (double sampleRate); /** Creates the next block of audio output. @@ -463,6 +509,27 @@ public: int startSample, int numSamples); + /** Returns the current target sample rate at which rendering is being done. + Subclasses may need to know this so that they can pitch things correctly. + */ + double getSampleRate() const noexcept { return sampleRate; } + + /** Sets a minimum limit on the size to which audio sub-blocks will be divided when rendering. + + When rendering, the audio blocks that are passed into renderNextBlock() will be split up + into smaller blocks that lie between all the incoming midi messages, and it is these smaller + sub-blocks that are rendered with multiple calls to renderVoices(). + + Obviously in a pathological case where there are midi messages on every sample, then + renderVoices() could be called once per sample and lead to poor performance, so this + setting allows you to set a lower limit on the block size. + + The default setting is 32, which means that midi messages are accurate to about < 1ms + accuracy, which is probably fine for most purposes, but you may want to increase or + decrease this value for your synth. + */ + void setMinimumRenderingSubdivisionSize (int numSamples) noexcept; + protected: //============================================================================== /** This is used to control access to the rendering callback and the note trigger methods. */ @@ -474,21 +541,34 @@ protected: /** The last pitch-wheel values for each midi channel. */ int lastPitchWheelValues [16]; - /** Searches through the voices to find one that's not currently playing, and which - can play the given sound. + /** Renders the voices for the given range. + By default this just calls renderNextBlock() on each voice, but you may need + to override it to handle custom cases. + */ + virtual void renderVoices (AudioSampleBuffer& outputAudio, + int startSample, int numSamples); + + /** Searches through the voices to find one that's not currently playing, and + which can play the given sound. Returns nullptr if all voices are busy and stealing isn't enabled. - This can be overridden to implement custom voice-stealing algorithms. + To implement a custom note-stealing algorithm, you can either override this + method, or (preferably) override findVoiceToSteal(). */ virtual SynthesiserVoice* findFreeVoice (SynthesiserSound* soundToPlay, - const bool stealIfNoneAvailable) const; + int midiChannel, + int midiNoteNumber, + bool stealIfNoneAvailable) const; /** Chooses a voice that is most suitable for being re-used. - The default method returns the one that has been playing for the longest, but - you may want to override this and do something more cunning instead. + The default method will attempt to find the oldest voice that isn't the + bottom or top note being played. If that's not suitable for your synth, + you can override this method and do something more cunning instead. */ - virtual SynthesiserVoice* findVoiceToSteal (SynthesiserSound* soundToPlay) const; + virtual SynthesiserVoice* findVoiceToSteal (SynthesiserSound* soundToPlay, + int midiChannel, + int midiNoteNumber) const; /** Starts a specified voice playing a particular sound. @@ -508,14 +588,18 @@ private: //============================================================================== double sampleRate; uint32 lastNoteOnCounter; + int minimumSubBlockSize; bool shouldStealNotes; BigInteger sustainPedalsDown; - void stopVoice (SynthesiserVoice*, bool allowTailOff); + void stopVoice (SynthesiserVoice*, float velocity, bool allowTailOff); #if JUCE_CATCH_DEPRECATED_CODE_MISUSE - // Note the new parameters for this method. + // Note the new parameters for these methods. virtual int findFreeVoice (const bool) const { return 0; } + virtual int noteOff (int, int, int) { return 0; } + virtual int findFreeVoice (SynthesiserSound*, const bool) { return 0; } + virtual int findVoiceToSteal (SynthesiserSound*) const { return 0; } #endif JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Synthesiser) diff --git a/JuceLibraryCode/modules/juce_audio_devices/audio_cd/juce_AudioCDBurner.h b/JuceLibraryCode/modules/juce_audio_devices/audio_cd/juce_AudioCDBurner.h index 88b1ef2..fae2cd0 100644 --- a/JuceLibraryCode/modules/juce_audio_devices/audio_cd/juce_AudioCDBurner.h +++ b/JuceLibraryCode/modules/juce_audio_devices/audio_cd/juce_AudioCDBurner.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_audio_devices/audio_cd/juce_AudioCDReader.cpp b/JuceLibraryCode/modules/juce_audio_devices/audio_cd/juce_AudioCDReader.cpp index ca9c5b0..b9d7987 100644 --- a/JuceLibraryCode/modules/juce_audio_devices/audio_cd/juce_AudioCDReader.cpp +++ b/JuceLibraryCode/modules/juce_audio_devices/audio_cd/juce_AudioCDReader.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_audio_devices/audio_cd/juce_AudioCDReader.h b/JuceLibraryCode/modules/juce_audio_devices/audio_cd/juce_AudioCDReader.h index 0e868db..bcf0f48 100644 --- a/JuceLibraryCode/modules/juce_audio_devices/audio_cd/juce_AudioCDReader.h +++ b/JuceLibraryCode/modules/juce_audio_devices/audio_cd/juce_AudioCDReader.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_audio_devices/audio_io/juce_AudioDeviceManager.cpp b/JuceLibraryCode/modules/juce_audio_devices/audio_io/juce_AudioDeviceManager.cpp index fad5eea..25451fe 100644 --- a/JuceLibraryCode/modules/juce_audio_devices/audio_io/juce_AudioDeviceManager.cpp +++ b/JuceLibraryCode/modules/juce_audio_devices/audio_io/juce_AudioDeviceManager.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -92,7 +92,6 @@ AudioDeviceManager::AudioDeviceManager() : numInputChansNeeded (0), numOutputChansNeeded (2), listNeedsScanning (true), - useInputNames (false), inputLevel (0), testSoundPosition (0), cpuUsageMs (0), @@ -154,7 +153,8 @@ static void addIfNotNull (OwnedArray& list, AudioIODeviceType void AudioDeviceManager::createAudioDeviceTypes (OwnedArray& list) { - addIfNotNull (list, AudioIODeviceType::createAudioIODeviceType_WASAPI()); + addIfNotNull (list, AudioIODeviceType::createAudioIODeviceType_WASAPI (false)); + addIfNotNull (list, AudioIODeviceType::createAudioIODeviceType_WASAPI (true)); addIfNotNull (list, AudioIODeviceType::createAudioIODeviceType_DirectSound()); addIfNotNull (list, AudioIODeviceType::createAudioIODeviceType_ASIO()); addIfNotNull (list, AudioIODeviceType::createAudioIODeviceType_CoreAudio()); @@ -177,6 +177,17 @@ void AudioDeviceManager::addAudioDeviceType (AudioIODeviceType* newDeviceType) } } +static bool deviceListContains (AudioIODeviceType* type, bool isInput, const String& name) +{ + StringArray devices (type->getDeviceNames (isInput)); + + for (int i = devices.size(); --i >= 0;) + if (devices[i].trim().equalsIgnoreCase (name.trim())) + return true; + + return false; +} + //============================================================================== String AudioDeviceManager::initialise (const int numInputChannelsNeeded, const int numOutputChannelsNeeded, @@ -363,8 +374,8 @@ AudioIODeviceType* AudioDeviceManager::findType (const String& inputName, const { AudioIODeviceType* const type = availableDeviceTypes.getUnchecked(i); - if ((inputName.isNotEmpty() && type->getDeviceNames (true).contains (inputName, true)) - || (outputName.isNotEmpty() && type->getDeviceNames (false).contains (outputName, true))) + if ((inputName.isNotEmpty() && deviceListContains (type, true, inputName)) + || (outputName.isNotEmpty() && deviceListContains (type, false, outputName))) { return type; } @@ -458,17 +469,11 @@ String AudioDeviceManager::setAudioDeviceSetup (const AudioDeviceSetup& newSetup deleteCurrentDevice(); scanDevicesIfNeeded(); - if (newOutputDeviceName.isNotEmpty() - && ! type->getDeviceNames (false).contains (newOutputDeviceName)) - { + if (newOutputDeviceName.isNotEmpty() && ! deviceListContains (type, false, newOutputDeviceName)) return "No such device: " + newOutputDeviceName; - } - if (newInputDeviceName.isNotEmpty() - && ! type->getDeviceNames (true).contains (newInputDeviceName)) - { + if (newInputDeviceName.isNotEmpty() && ! deviceListContains (type, true, newInputDeviceName)) return "No such device: " + newInputDeviceName; - } currentAudioDevice = type->createDevice (newOutputDeviceName, newInputDeviceName); @@ -546,6 +551,11 @@ double AudioDeviceManager::chooseBestSampleRate (double rate) const const Array rates (currentAudioDevice->getAvailableSampleRates()); + if (rate > 0 && rates.contains (rate)) + return rate; + + rate = currentAudioDevice->getCurrentSampleRate(); + if (rate > 0 && rates.contains (rate)) return rate; diff --git a/JuceLibraryCode/modules/juce_audio_devices/audio_io/juce_AudioDeviceManager.h b/JuceLibraryCode/modules/juce_audio_devices/audio_io/juce_AudioDeviceManager.h index f1e483f..978ed35 100644 --- a/JuceLibraryCode/modules/juce_audio_devices/audio_io/juce_AudioDeviceManager.h +++ b/JuceLibraryCode/modules/juce_audio_devices/audio_io/juce_AudioDeviceManager.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -450,7 +450,6 @@ private: BigInteger inputChannels, outputChannels; ScopedPointer lastExplicitSettings; mutable bool listNeedsScanning; - bool useInputNames; Atomic inputLevelMeasurementEnabledCount; double inputLevel; ScopedPointer testSound; diff --git a/JuceLibraryCode/modules/juce_audio_devices/audio_io/juce_AudioIODevice.cpp b/JuceLibraryCode/modules/juce_audio_devices/audio_io/juce_AudioIODevice.cpp index 95221ba..990550e 100644 --- a/JuceLibraryCode/modules/juce_audio_devices/audio_io/juce_AudioIODevice.cpp +++ b/JuceLibraryCode/modules/juce_audio_devices/audio_io/juce_AudioIODevice.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_audio_devices/audio_io/juce_AudioIODevice.h b/JuceLibraryCode/modules/juce_audio_devices/audio_io/juce_AudioIODevice.h index 8ce41d0..921c57d 100644 --- a/JuceLibraryCode/modules/juce_audio_devices/audio_io/juce_AudioIODevice.h +++ b/JuceLibraryCode/modules/juce_audio_devices/audio_io/juce_AudioIODevice.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_audio_devices/audio_io/juce_AudioIODeviceType.cpp b/JuceLibraryCode/modules/juce_audio_devices/audio_io/juce_AudioIODeviceType.cpp index 80026e7..0df87eb 100644 --- a/JuceLibraryCode/modules/juce_audio_devices/audio_io/juce_AudioIODeviceType.cpp +++ b/JuceLibraryCode/modules/juce_audio_devices/audio_io/juce_AudioIODeviceType.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -50,7 +50,7 @@ AudioIODeviceType* AudioIODeviceType::createAudioIODeviceType_iOSAudio() #endif #if ! (JUCE_WINDOWS && JUCE_WASAPI) -AudioIODeviceType* AudioIODeviceType::createAudioIODeviceType_WASAPI() { return nullptr; } +AudioIODeviceType* AudioIODeviceType::createAudioIODeviceType_WASAPI (bool) { return nullptr; } #endif #if ! (JUCE_WINDOWS && JUCE_DIRECTSOUND) diff --git a/JuceLibraryCode/modules/juce_audio_devices/audio_io/juce_AudioIODeviceType.h b/JuceLibraryCode/modules/juce_audio_devices/audio_io/juce_AudioIODeviceType.h index d6cd99a..73b8afc 100644 --- a/JuceLibraryCode/modules/juce_audio_devices/audio_io/juce_AudioIODeviceType.h +++ b/JuceLibraryCode/modules/juce_audio_devices/audio_io/juce_AudioIODeviceType.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -151,7 +151,7 @@ public: /** Creates an iOS device type if it's available on this platform, or returns null. */ static AudioIODeviceType* createAudioIODeviceType_iOSAudio(); /** Creates a WASAPI device type if it's available on this platform, or returns null. */ - static AudioIODeviceType* createAudioIODeviceType_WASAPI(); + static AudioIODeviceType* createAudioIODeviceType_WASAPI (bool exclusiveMode); /** Creates a DirectSound device type if it's available on this platform, or returns null. */ static AudioIODeviceType* createAudioIODeviceType_DirectSound(); /** Creates an ASIO device type if it's available on this platform, or returns null. */ diff --git a/JuceLibraryCode/modules/juce_audio_devices/audio_io/juce_SystemAudioVolume.h b/JuceLibraryCode/modules/juce_audio_devices/audio_io/juce_SystemAudioVolume.h index 689e1f2..5088976 100644 --- a/JuceLibraryCode/modules/juce_audio_devices/audio_io/juce_SystemAudioVolume.h +++ b/JuceLibraryCode/modules/juce_audio_devices/audio_io/juce_SystemAudioVolume.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_audio_devices/juce_audio_devices.cpp b/JuceLibraryCode/modules/juce_audio_devices/juce_audio_devices.cpp index a9733db..2bc3c6a 100644 --- a/JuceLibraryCode/modules/juce_audio_devices/juce_audio_devices.cpp +++ b/JuceLibraryCode/modules/juce_audio_devices/juce_audio_devices.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -72,7 +72,7 @@ This means that anyone who wants to use JUCE's ASIO abilities will have to: 1) Agree to Steinberg's licensing terms and download the ASIO SDK - (see www.steinberg.net/Steinberg/Developers.asp). + (see http://www.steinberg.net/en/company/developers.html). 2) Enable this code with a global definition #define JUCE_ASIO 1. diff --git a/JuceLibraryCode/modules/juce_audio_devices/juce_audio_devices.h b/JuceLibraryCode/modules/juce_audio_devices/juce_audio_devices.h index 12343d1..249f6b2 100644 --- a/JuceLibraryCode/modules/juce_audio_devices/juce_audio_devices.h +++ b/JuceLibraryCode/modules/juce_audio_devices/juce_audio_devices.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -43,12 +43,21 @@ #endif /** Config: JUCE_WASAPI - Enables WASAPI audio devices (Windows Vista and above). + Enables WASAPI audio devices (Windows Vista and above). See also the + JUCE_WASAPI_EXCLUSIVE flag. */ #ifndef JUCE_WASAPI - #define JUCE_WASAPI 0 + #define JUCE_WASAPI 1 #endif +/** Config: JUCE_WASAPI_EXCLUSIVE + Enables WASAPI audio devices in exclusive mode (Windows Vista and above). +*/ +#ifndef JUCE_WASAPI_EXCLUSIVE + #define JUCE_WASAPI_EXCLUSIVE 0 +#endif + + /** Config: JUCE_DIRECTSOUND Enables DirectSound audio (MS Windows only). */ diff --git a/JuceLibraryCode/modules/juce_audio_devices/juce_audio_devices.mm b/JuceLibraryCode/modules/juce_audio_devices/juce_audio_devices.mm index a135119..b49480d 100644 --- a/JuceLibraryCode/modules/juce_audio_devices/juce_audio_devices.mm +++ b/JuceLibraryCode/modules/juce_audio_devices/juce_audio_devices.mm @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_audio_devices/juce_module_info b/JuceLibraryCode/modules/juce_audio_devices/juce_module_info index c1f01b6..add21aa 100644 --- a/JuceLibraryCode/modules/juce_audio_devices/juce_module_info +++ b/JuceLibraryCode/modules/juce_audio_devices/juce_module_info @@ -1,7 +1,7 @@ { "id": "juce_audio_devices", "name": "JUCE audio and midi I/O device classes", - "version": "3.0.6", + "version": "3.2.0", "description": "Classes to play and record from audio and midi i/o devices.", "website": "http://www.juce.com/juce", "license": "GPL/Commercial", diff --git a/JuceLibraryCode/modules/juce_audio_devices/midi_io/juce_MidiInput.h b/JuceLibraryCode/modules/juce_audio_devices/midi_io/juce_MidiInput.h index 6308020..0c5a5b6 100644 --- a/JuceLibraryCode/modules/juce_audio_devices/midi_io/juce_MidiInput.h +++ b/JuceLibraryCode/modules/juce_audio_devices/midi_io/juce_MidiInput.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -139,7 +139,7 @@ public: //============================================================================== /** Destructor. */ - virtual ~MidiInput(); + ~MidiInput(); /** Returns the name of this device. */ const String& getName() const noexcept { return name; } @@ -158,23 +158,21 @@ public: @see stop */ - virtual void start(); + void start(); /** Stops the device running. - @see start */ - virtual void stop(); + void stop(); -protected: +private: //============================================================================== String name; void* internal; - explicit MidiInput (const String& name); + // The input objects are created with the openDevice() method. + explicit MidiInput (const String&); -private: - //============================================================================== JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MidiInput) }; diff --git a/JuceLibraryCode/modules/juce_audio_devices/midi_io/juce_MidiMessageCollector.cpp b/JuceLibraryCode/modules/juce_audio_devices/midi_io/juce_MidiMessageCollector.cpp index 28e81c0..f4b9525 100644 --- a/JuceLibraryCode/modules/juce_audio_devices/midi_io/juce_MidiMessageCollector.cpp +++ b/JuceLibraryCode/modules/juce_audio_devices/midi_io/juce_MidiMessageCollector.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_audio_devices/midi_io/juce_MidiMessageCollector.h b/JuceLibraryCode/modules/juce_audio_devices/midi_io/juce_MidiMessageCollector.h index 5b16737..c77401a 100644 --- a/JuceLibraryCode/modules/juce_audio_devices/midi_io/juce_MidiMessageCollector.h +++ b/JuceLibraryCode/modules/juce_audio_devices/midi_io/juce_MidiMessageCollector.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_audio_devices/midi_io/juce_MidiOutput.cpp b/JuceLibraryCode/modules/juce_audio_devices/midi_io/juce_MidiOutput.cpp index 0af7d1b..984c9ad 100644 --- a/JuceLibraryCode/modules/juce_audio_devices/midi_io/juce_MidiOutput.cpp +++ b/JuceLibraryCode/modules/juce_audio_devices/midi_io/juce_MidiOutput.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_audio_devices/midi_io/juce_MidiOutput.h b/JuceLibraryCode/modules/juce_audio_devices/midi_io/juce_MidiOutput.h index c668f8a..c908263 100644 --- a/JuceLibraryCode/modules/juce_audio_devices/midi_io/juce_MidiOutput.h +++ b/JuceLibraryCode/modules/juce_audio_devices/midi_io/juce_MidiOutput.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -82,13 +82,12 @@ public: //============================================================================== /** Destructor. */ - virtual ~MidiOutput(); + ~MidiOutput(); /** Makes this device output a midi message. - @see MidiMessage */ - virtual void sendMessageNow (const MidiMessage& message); + void sendMessageNow (const MidiMessage& message); //============================================================================== /** This lets you supply a block of messages that will be sent out at some point @@ -100,7 +99,7 @@ public: This will only work if you've already started the thread with startBackgroundThread(). - A time is supplied, at which the block of messages should be sent. This time uses + A time is specified, at which the block of messages should be sent. This time uses the same time base as Time::getMillisecondCounter(), and must be in the future. The samplesPerSecondForBuffer parameter indicates the number of samples per second @@ -108,38 +107,34 @@ public: samplesPerSecondForBuffer value is needed to convert this sample position to a real time. */ - virtual void sendBlockOfMessages (const MidiBuffer& buffer, - double millisecondCounterToStartAt, - double samplesPerSecondForBuffer); + void sendBlockOfMessages (const MidiBuffer& buffer, + double millisecondCounterToStartAt, + double samplesPerSecondForBuffer); - /** Gets rid of any midi messages that had been added by sendBlockOfMessages(). - */ - virtual void clearAllPendingMessages(); + /** Gets rid of any midi messages that had been added by sendBlockOfMessages(). */ + void clearAllPendingMessages(); /** Starts up a background thread so that the device can send blocks of data. - Call this to get the device ready, before using sendBlockOfMessages(). */ - virtual void startBackgroundThread(); + void startBackgroundThread(); /** Stops the background thread, and clears any pending midi events. - @see startBackgroundThread */ - virtual void stopBackgroundThread(); + void stopBackgroundThread(); -protected: +private: //============================================================================== void* internal; CriticalSection lock; struct PendingMessage; PendingMessage* firstMessage; - MidiOutput(); + MidiOutput(); // These objects are created with the openDevice() method. void run() override; -private: JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MidiOutput) }; diff --git a/JuceLibraryCode/modules/juce_audio_devices/native/juce_MidiDataConcatenator.h b/JuceLibraryCode/modules/juce_audio_devices/native/juce_MidiDataConcatenator.h index 4dc70b9..0cefb83 100644 --- a/JuceLibraryCode/modules/juce_audio_devices/native/juce_MidiDataConcatenator.h +++ b/JuceLibraryCode/modules/juce_audio_devices/native/juce_MidiDataConcatenator.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_audio_devices/native/juce_android_Audio.cpp b/JuceLibraryCode/modules/juce_audio_devices/native/juce_android_Audio.cpp index 80711da..d32f5cf 100644 --- a/JuceLibraryCode/modules/juce_audio_devices/native/juce_android_Audio.cpp +++ b/JuceLibraryCode/modules/juce_audio_devices/native/juce_android_Audio.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_audio_devices/native/juce_android_Midi.cpp b/JuceLibraryCode/modules/juce_audio_devices/native/juce_android_Midi.cpp index 88eeae6..59ddf3e 100644 --- a/JuceLibraryCode/modules/juce_audio_devices/native/juce_android_Midi.cpp +++ b/JuceLibraryCode/modules/juce_audio_devices/native/juce_android_Midi.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_audio_devices/native/juce_android_OpenSL.cpp b/JuceLibraryCode/modules/juce_audio_devices/native/juce_android_OpenSL.cpp index e02951d..f4c09bb 100644 --- a/JuceLibraryCode/modules/juce_audio_devices/native/juce_android_OpenSL.cpp +++ b/JuceLibraryCode/modules/juce_audio_devices/native/juce_android_OpenSL.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -47,13 +47,13 @@ public: // this is a total guess about how to calculate the latency, but seems to vaguely agree // with the devices I've tested.. YMMV - inputLatency = ((javaDevice.minBufferSizeIn * 2) / 3); - outputLatency = ((javaDevice.minBufferSizeOut * 2) / 3); + inputLatency = (javaDevice.minBufferSizeIn * 2) / 3; + outputLatency = (javaDevice.minBufferSizeOut * 2) / 3; - const int longestLatency = jmax (inputLatency, outputLatency); - const int totalLatency = inputLatency + outputLatency; - inputLatency = ((longestLatency * inputLatency) / totalLatency) & ~15; - outputLatency = ((longestLatency * outputLatency) / totalLatency) & ~15; + const int64 longestLatency = jmax (inputLatency, outputLatency); + const int64 totalLatency = inputLatency + outputLatency; + inputLatency = (int) ((longestLatency * inputLatency) / totalLatency) & ~15; + outputLatency = (int) ((longestLatency * outputLatency) / totalLatency) & ~15; } ~OpenSLAudioIODevice() @@ -341,8 +341,8 @@ private: SLDataFormat_PCM pcmFormat = { SL_DATAFORMAT_PCM, - numChannels, - sampleRate * 1000, // (sample rate units are millihertz) + (SLuint32) numChannels, + (SLuint32) (sampleRate * 1000), // (sample rate units are millihertz) SL_PCMSAMPLEFORMAT_FIXED_16, SL_PCMSAMPLEFORMAT_FIXED_16, SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT, @@ -450,8 +450,8 @@ private: SLDataFormat_PCM pcmFormat = { SL_DATAFORMAT_PCM, - numChannels, - sampleRate * 1000, // (sample rate units are millihertz) + (SLuint32) numChannels, + (SLuint32) (sampleRate * 1000), // (sample rate units are millihertz) SL_PCMSAMPLEFORMAT_FIXED_16, SL_PCMSAMPLEFORMAT_FIXED_16, (numChannels == 1) ? SL_SPEAKER_FRONT_CENTER : (SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT), diff --git a/JuceLibraryCode/modules/juce_audio_devices/native/juce_ios_Audio.cpp b/JuceLibraryCode/modules/juce_audio_devices/native/juce_ios_Audio.cpp index b7d1611..16dba0c 100644 --- a/JuceLibraryCode/modules/juce_audio_devices/native/juce_ios_Audio.cpp +++ b/JuceLibraryCode/modules/juce_audio_devices/native/juce_ios_Audio.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -536,9 +536,9 @@ private: return AudioSessionGetProperty (propID, &valueSize, &result); } - static bool setSessionUInt32Property (AudioSessionPropertyID propID, UInt32 v) noexcept { AudioSessionSetProperty (propID, sizeof (v), &v) == kAudioSessionNoError; } - static bool setSessionFloat32Property (AudioSessionPropertyID propID, Float32 v) noexcept { AudioSessionSetProperty (propID, sizeof (v), &v) == kAudioSessionNoError; } - static bool setSessionFloat64Property (AudioSessionPropertyID propID, Float64 v) noexcept { AudioSessionSetProperty (propID, sizeof (v), &v) == kAudioSessionNoError; } + static bool setSessionUInt32Property (AudioSessionPropertyID propID, UInt32 v) noexcept { return AudioSessionSetProperty (propID, sizeof (v), &v) == kAudioSessionNoError; } + static bool setSessionFloat32Property (AudioSessionPropertyID propID, Float32 v) noexcept { return AudioSessionSetProperty (propID, sizeof (v), &v) == kAudioSessionNoError; } + static bool setSessionFloat64Property (AudioSessionPropertyID propID, Float64 v) noexcept { return AudioSessionSetProperty (propID, sizeof (v), &v) == kAudioSessionNoError; } JUCE_DECLARE_NON_COPYABLE (iOSAudioIODevice) }; diff --git a/JuceLibraryCode/modules/juce_audio_devices/native/juce_linux_ALSA.cpp b/JuceLibraryCode/modules/juce_audio_devices/native/juce_linux_ALSA.cpp index 9bc7ecf..85fb8c5 100644 --- a/JuceLibraryCode/modules/juce_audio_devices/native/juce_linux_ALSA.cpp +++ b/JuceLibraryCode/modules/juce_audio_devices/native/juce_linux_ALSA.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -30,7 +30,7 @@ namespace #endif #if JUCE_ALSA_LOGGING - #define JUCE_ALSA_LOG(dbgtext) { juce::String tempDbgBuf ("ALSA: "); tempDbgBuf << dbgtext; Logger::writeToLog (tempDbgBuf); DBG (tempDbgBuf) } + #define JUCE_ALSA_LOG(dbgtext) { juce::String tempDbgBuf ("ALSA: "); tempDbgBuf << dbgtext; Logger::writeToLog (tempDbgBuf); DBG (tempDbgBuf); } #define JUCE_CHECKED_RESULT(x) (logErrorMessage (x, __LINE__)) static int logErrorMessage (int err, int lineNum) @@ -41,7 +41,7 @@ namespace return err; } #else - #define JUCE_ALSA_LOG(x) + #define JUCE_ALSA_LOG(x) {} #define JUCE_CHECKED_RESULT(x) (x) #endif @@ -57,7 +57,7 @@ static void getDeviceSampleRates (snd_pcm_t* handle, Array& rates) for (int i = 0; ratesToTry[i] != 0; ++i) { if (snd_pcm_hw_params_any (handle, hwParams) >= 0 - && snd_pcm_hw_params_test_rate (handle, hwParams, ratesToTry[i], 0) == 0) + && snd_pcm_hw_params_test_rate (handle, hwParams, (unsigned int) ratesToTry[i], 0) == 0) { rates.addIfNotAlreadyThere ((double) ratesToTry[i]); } @@ -149,7 +149,7 @@ class ALSADevice { public: ALSADevice (const String& devID, bool forInput) - : handle (0), + : handle (nullptr), bitDepth (16), numChannelsRunning (0), latency (0), @@ -183,16 +183,16 @@ public: void closeNow() { - if (handle != 0) + if (handle != nullptr) { snd_pcm_close (handle); - handle = 0; + handle = nullptr; } } bool setParameters (unsigned int sampleRate, int numChannels, int bufferSize) { - if (handle == 0) + if (handle == nullptr) return false; JUCE_ALSA_LOG ("ALSADevice::setParameters(" << deviceID << ", " @@ -257,10 +257,10 @@ public: int dir = 0; unsigned int periods = 4; - snd_pcm_uframes_t samplesPerPeriod = bufferSize; + snd_pcm_uframes_t samplesPerPeriod = (snd_pcm_uframes_t) bufferSize; if (JUCE_ALSA_FAILED (snd_pcm_hw_params_set_rate_near (handle, hwParams, &sampleRate, 0)) - || JUCE_ALSA_FAILED (snd_pcm_hw_params_set_channels (handle, hwParams, numChannels)) + || JUCE_ALSA_FAILED (snd_pcm_hw_params_set_channels (handle, hwParams, (unsigned int ) numChannels)) || JUCE_ALSA_FAILED (snd_pcm_hw_params_set_periods_near (handle, hwParams, &periods, &dir)) || JUCE_ALSA_FAILED (snd_pcm_hw_params_set_period_size_near (handle, hwParams, &samplesPerPeriod, &dir)) || JUCE_ALSA_FAILED (snd_pcm_hw_params (handle, hwParams))) @@ -274,7 +274,7 @@ public: || JUCE_ALSA_FAILED (snd_pcm_hw_params_get_periods (hwParams, &periods, &dir))) latency = 0; else - latency = frames * (periods - 1); // (this is the method JACK uses to guess the latency..) + latency = (int) frames * ((int) periods - 1); // (this is the method JACK uses to guess the latency..) JUCE_ALSA_LOG ("frames: " << (int) frames << ", periods: " << (int) periods << ", samplesPerPeriod: " << (int) samplesPerPeriod); @@ -316,22 +316,22 @@ public: if (isInterleaved) { - scratch.ensureSize (sizeof (float) * numSamples * numChannelsRunning, false); + scratch.ensureSize ((size_t) ((int) sizeof (float) * numSamples * numChannelsRunning), false); for (int i = 0; i < numChannelsRunning; ++i) converter->convertSamples (scratch.getData(), i, data[i], 0, numSamples); - numDone = snd_pcm_writei (handle, scratch.getData(), numSamples); + numDone = snd_pcm_writei (handle, scratch.getData(), (snd_pcm_uframes_t) numSamples); } else { for (int i = 0; i < numChannelsRunning; ++i) converter->convertSamples (data[i], data[i], numSamples); - numDone = snd_pcm_writen (handle, (void**) data, numSamples); + numDone = snd_pcm_writen (handle, (void**) data, (snd_pcm_uframes_t) numSamples); } - if (numDone < 0 && JUCE_ALSA_FAILED (snd_pcm_recover (handle, numDone, 1 /* silent */))) + if (numDone < 0 && JUCE_ALSA_FAILED (snd_pcm_recover (handle, (int) numDone, 1 /* silent */))) return false; if (numDone < numSamples) @@ -347,12 +347,12 @@ public: if (isInterleaved) { - scratch.ensureSize (sizeof (float) * numSamples * numChannelsRunning, false); + scratch.ensureSize ((size_t) ((int) sizeof (float) * numSamples * numChannelsRunning), false); scratch.fillWith (0); // (not clearing this data causes warnings in valgrind) - snd_pcm_sframes_t num = snd_pcm_readi (handle, scratch.getData(), numSamples); + snd_pcm_sframes_t num = snd_pcm_readi (handle, scratch.getData(), (snd_pcm_uframes_t) numSamples); - if (num < 0 && JUCE_ALSA_FAILED (snd_pcm_recover (handle, num, 1 /* silent */))) + if (num < 0 && JUCE_ALSA_FAILED (snd_pcm_recover (handle, (int) num, 1 /* silent */))) return false; if (num < numSamples) @@ -363,9 +363,9 @@ public: } else { - snd_pcm_sframes_t num = snd_pcm_readn (handle, (void**) data, numSamples); + snd_pcm_sframes_t num = snd_pcm_readn (handle, (void**) data, (snd_pcm_uframes_t) numSamples); - if (num < 0 && JUCE_ALSA_FAILED (snd_pcm_recover (handle, num, 1 /* silent */))) + if (num < 0 && JUCE_ALSA_FAILED (snd_pcm_recover (handle, (int) num, 1 /* silent */))) return false; if (num < numSamples) @@ -486,14 +486,17 @@ public: sampleRate = newSampleRate; bufferSize = newBufferSize; - inputChannelBuffer.setSize (jmax ((int) minChansIn, inputChannels.getHighestBit()) + 1, bufferSize); + int maxInputsRequested = inputChannels.getHighestBit() + 1; + maxInputsRequested = jmax ((int) minChansIn, jmin ((int) maxChansIn, maxInputsRequested)); + + inputChannelBuffer.setSize (maxInputsRequested, bufferSize); inputChannelBuffer.clear(); inputChannelDataForCallback.clear(); currentInputChans.clear(); if (inputChannels.getHighestBit() >= 0) { - for (int i = 0; i <= jmax (inputChannels.getHighestBit(), (int) minChansIn); ++i) + for (int i = 0; i < maxInputsRequested; ++i) { if (inputChannels[i]) { @@ -503,16 +506,19 @@ public: } } - ensureMinimumNumBitsSet (outputChannels, minChansOut); + ensureMinimumNumBitsSet (outputChannels, (int) minChansOut); - outputChannelBuffer.setSize (jmax ((int) minChansOut, outputChannels.getHighestBit()) + 1, bufferSize); + int maxOutputsRequested = outputChannels.getHighestBit() + 1; + maxOutputsRequested = jmax ((int) minChansOut, jmin ((int) maxChansOut, maxOutputsRequested)); + + outputChannelBuffer.setSize (maxOutputsRequested, bufferSize); outputChannelBuffer.clear(); outputChannelDataForCallback.clear(); currentOutputChans.clear(); if (outputChannels.getHighestBit() >= 0) { - for (int i = 0; i <= jmax (outputChannels.getHighestBit(), (int) minChansOut); ++i) + for (int i = 0; i < maxOutputsRequested; ++i) { if (outputChannels[i]) { @@ -557,7 +563,7 @@ public: return; } - ensureMinimumNumBitsSet (currentInputChans, minChansIn); + ensureMinimumNumBitsSet (currentInputChans, (int) minChansIn); if (! inputDevice->setParameters ((unsigned int) sampleRate, jlimit ((int) minChansIn, (int) maxChansIn, currentInputChans.getHighestBit() + 1), @@ -644,8 +650,21 @@ public: { while (! threadShouldExit()) { - if (inputDevice != nullptr && inputDevice->handle) + if (inputDevice != nullptr && inputDevice->handle != nullptr) { + if (outputDevice == nullptr || outputDevice->handle == nullptr) + { + JUCE_ALSA_FAILED (snd_pcm_wait (inputDevice->handle, 2000)); + + if (threadShouldExit()) + break; + + snd_pcm_sframes_t avail = snd_pcm_avail_update (inputDevice->handle); + + if (avail < 0) + JUCE_ALSA_FAILED (snd_pcm_recover (inputDevice->handle, (int) avail, 0)); + } + audioIoInProgress = true; if (! inputDevice->readFromInputDevice (inputChannelBuffer, bufferSize)) @@ -675,11 +694,11 @@ public: else { for (int i = 0; i < outputChannelDataForCallback.size(); ++i) - zeromem (outputChannelDataForCallback[i], sizeof (float) * bufferSize); + zeromem (outputChannelDataForCallback[i], sizeof (float) * (size_t) bufferSize); } } - if (outputDevice != nullptr && outputDevice->handle) + if (outputDevice != nullptr && outputDevice->handle != nullptr) { JUCE_ALSA_FAILED (snd_pcm_wait (outputDevice->handle, 2000)); @@ -689,7 +708,7 @@ public: snd_pcm_sframes_t avail = snd_pcm_avail_update (outputDevice->handle); if (avail < 0) - JUCE_ALSA_FAILED (snd_pcm_recover (outputDevice->handle, avail, 0)); + JUCE_ALSA_FAILED (snd_pcm_recover (outputDevice->handle, (int) avail, 0)); audioIoInProgress = true; @@ -702,6 +721,7 @@ public: audioIoInProgress = false; } } + audioIoInProgress = false; } @@ -782,10 +802,10 @@ class ALSAAudioIODevice : public AudioIODevice { public: ALSAAudioIODevice (const String& deviceName, - const String& typeName, + const String& deviceTypeName, const String& inputDeviceID, const String& outputDeviceID) - : AudioIODevice (deviceName, typeName), + : AudioIODevice (deviceName, deviceTypeName), inputId (inputDeviceID), outputId (outputDeviceID), isOpen_ (false), @@ -910,8 +930,8 @@ private: class ALSAAudioIODeviceType : public AudioIODeviceType { public: - ALSAAudioIODeviceType (bool onlySoundcards, const String &typeName) - : AudioIODeviceType (typeName), + ALSAAudioIODeviceType (bool onlySoundcards, const String &deviceTypeName) + : AudioIODeviceType (deviceTypeName), hasScanned (false), listOnlySoundcards (onlySoundcards) { @@ -1078,9 +1098,9 @@ private: if (snd_ctl_pcm_next_device (handle, &device) < 0 || device < 0) break; - snd_pcm_info_set_device (pcmInfo, device); + snd_pcm_info_set_device (pcmInfo, (unsigned int) device); - for (int subDevice = 0, nbSubDevice = 1; subDevice < nbSubDevice; ++subDevice) + for (unsigned int subDevice = 0, nbSubDevice = 1; subDevice < nbSubDevice; ++subDevice) { snd_pcm_info_set_subdevice (pcmInfo, subDevice); snd_pcm_info_set_stream (pcmInfo, SND_PCM_STREAM_CAPTURE); @@ -1104,7 +1124,7 @@ private: } else { - id << "hw:" << cardId << "," << device << "," << subDevice; + id << "hw:" << cardId << "," << device << "," << (int) subDevice; name << cardName << ", " << snd_pcm_info_get_name (pcmInfo) << " {" << snd_pcm_info_get_subdevice_name (pcmInfo) << "}"; } diff --git a/JuceLibraryCode/modules/juce_audio_devices/native/juce_linux_AudioCDReader.cpp b/JuceLibraryCode/modules/juce_audio_devices/native/juce_linux_AudioCDReader.cpp index a645333..938486b 100644 --- a/JuceLibraryCode/modules/juce_audio_devices/native/juce_linux_AudioCDReader.cpp +++ b/JuceLibraryCode/modules/juce_audio_devices/native/juce_linux_AudioCDReader.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_audio_devices/native/juce_linux_JackAudio.cpp b/JuceLibraryCode/modules/juce_audio_devices/native/juce_linux_JackAudio.cpp index 38ad64d..ac9846f 100644 --- a/JuceLibraryCode/modules/juce_audio_devices/native/juce_linux_JackAudio.cpp +++ b/JuceLibraryCode/modules/juce_audio_devices/native/juce_linux_JackAudio.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_audio_devices/native/juce_linux_Midi.cpp b/JuceLibraryCode/modules/juce_audio_devices/native/juce_linux_Midi.cpp index a6799f3..821a538 100644 --- a/JuceLibraryCode/modules/juce_audio_devices/native/juce_linux_Midi.cpp +++ b/JuceLibraryCode/modules/juce_audio_devices/native/juce_linux_Midi.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -133,14 +133,14 @@ private: if (snd_midi_event_new (maxEventSize, &midiParser) >= 0) { const int numPfds = snd_seq_poll_descriptors_count (seqHandle, POLLIN); - HeapBlock pfd (numPfds); - snd_seq_poll_descriptors (seqHandle, pfd, numPfds, POLLIN); + HeapBlock pfd ((size_t) numPfds); + snd_seq_poll_descriptors (seqHandle, pfd, (unsigned int) numPfds, POLLIN); HeapBlock buffer (maxEventSize); while (! threadShouldExit()) { - if (poll (pfd, numPfds, 100) > 0) // there was a "500" here which is a bit long when we exit the program and have to wait for a timeout on this poll call + if (poll (pfd, (nfds_t) numPfds, 100) > 0) // there was a "500" here which is a bit long when we exit the program and have to wait for a timeout on this poll call { if (threadShouldExit()) break; @@ -154,14 +154,14 @@ private: if (snd_seq_event_input (seqHandle, &inputEvent) >= 0) { // xxx what about SYSEXes that are too big for the buffer? - const int numBytes = snd_midi_event_decode (midiParser, buffer, + const long numBytes = snd_midi_event_decode (midiParser, buffer, maxEventSize, inputEvent); snd_midi_event_reset_decode (midiParser); if (numBytes > 0) { - const MidiMessage message ((const uint8*) buffer, numBytes, + const MidiMessage message ((const uint8*) buffer, (int) numBytes, Time::getMillisecondCounter() * 0.001); client.handleIncomingMidiMessage (message, inputEvent->dest.port); @@ -410,7 +410,7 @@ public: maxEventSize (16 * 1024) { jassert (port.isValid() && midiOutput != nullptr); - snd_midi_event_new (maxEventSize, &midiParser); + snd_midi_event_new ((size_t) maxEventSize, &midiParser); } ~MidiOutputDevice() @@ -419,13 +419,13 @@ public: port.deletePort(); } - void sendMessageNow (const MidiMessage& message) + bool sendMessageNow (const MidiMessage& message) { if (message.getRawDataSize() > maxEventSize) { maxEventSize = message.getRawDataSize(); snd_midi_event_free (midiParser); - snd_midi_event_new (maxEventSize, &midiParser); + snd_midi_event_new ((size_t) maxEventSize, &midiParser); } snd_seq_event_t event; @@ -435,12 +435,17 @@ public: const uint8* data = message.getRawData(); snd_seq_t* seqHandle = port.client->get(); + bool success = true; while (numBytes > 0) { const long numSent = snd_midi_event_encode (midiParser, data, numBytes, &event); + if (numSent <= 0) + { + success = numSent == 0; break; + } numBytes -= numSent; data += numSent; @@ -449,11 +454,15 @@ public: snd_seq_ev_set_subs (&event); snd_seq_ev_set_direct (&event); - snd_seq_event_output (seqHandle, &event); + if (snd_seq_event_output_direct (seqHandle, &event) < 0) + { + success = false; + break; + } } - snd_seq_drain_output (seqHandle); snd_midi_event_reset_encode (midiParser); + return success; } private: diff --git a/JuceLibraryCode/modules/juce_audio_devices/native/juce_mac_AudioCDBurner.mm b/JuceLibraryCode/modules/juce_audio_devices/native/juce_mac_AudioCDBurner.mm index 8dd7bfa..3489a80 100644 --- a/JuceLibraryCode/modules/juce_audio_devices/native/juce_mac_AudioCDBurner.mm +++ b/JuceLibraryCode/modules/juce_audio_devices/native/juce_mac_AudioCDBurner.mm @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_audio_devices/native/juce_mac_AudioCDReader.mm b/JuceLibraryCode/modules/juce_audio_devices/native/juce_mac_AudioCDReader.mm index 447c98b..8d87fac 100644 --- a/JuceLibraryCode/modules/juce_audio_devices/native/juce_mac_AudioCDReader.mm +++ b/JuceLibraryCode/modules/juce_audio_devices/native/juce_mac_AudioCDReader.mm @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_audio_devices/native/juce_mac_CoreAudio.cpp b/JuceLibraryCode/modules/juce_audio_devices/native/juce_mac_CoreAudio.cpp index e51dd7c..02c7a5d 100644 --- a/JuceLibraryCode/modules/juce_audio_devices/native/juce_mac_CoreAudio.cpp +++ b/JuceLibraryCode/modules/juce_audio_devices/native/juce_mac_CoreAudio.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -233,7 +233,7 @@ public: size = sizeof (nameNSString); pa.mSelector = kAudioObjectPropertyElementName; - pa.mElement = chanNum + 1; + pa.mElement = (AudioObjectPropertyElement) chanNum + 1; if (AudioObjectGetPropertyData (deviceID, &pa, 0, nullptr, &size, &nameNSString) == noErr) { @@ -277,7 +277,7 @@ public: if (OK (AudioObjectGetPropertyData (deviceID, &pa, 0, nullptr, &size, ranges))) { - static const double possibleRates[] = { 44100.0, 48000.0, 88200.0, 96000.0, 176400.0, 192000.0 }; + static const double possibleRates[] = { 44100.0, 48000.0, 88200.0, 96000.0, 176400.0, 192000.0, 384000.0 }; for (int i = 0; i < numElementsInArray (possibleRates); ++i) { @@ -394,7 +394,7 @@ public: if (OK (AudioObjectGetPropertyData (deviceID, &pa, 0, nullptr, &size, &sr))) sampleRate = sr; - UInt32 framesPerBuf = bufferSize; + UInt32 framesPerBuf = (UInt32) bufferSize; size = sizeof (framesPerBuf); pa.mSelector = kAudioDevicePropertyBufferFrameSize; AudioObjectGetPropertyData (deviceID, &pa, 0, nullptr, &size, &framesPerBuf); @@ -543,7 +543,7 @@ public: // set sample rate AudioObjectPropertyAddress pa; pa.mSelector = kAudioDevicePropertyNominalSampleRate; - pa.mScope = kAudioObjectPropertyScopeWildcard; + pa.mScope = kAudioObjectPropertyScopeGlobal; pa.mElement = kAudioObjectPropertyElementMaster; Float64 sr = newSampleRate; @@ -1067,6 +1067,12 @@ public: jassert (! isOpen()); jassert (! device->isOpen()); devices.add (new DeviceWrapper (*this, device, useInputs, useOutputs)); + + if (currentSampleRate == 0) + currentSampleRate = device->getCurrentSampleRate(); + + if (currentBufferSize == 0) + currentBufferSize = device->getCurrentBufferSizeSamples(); } Array getDevices() const diff --git a/JuceLibraryCode/modules/juce_audio_devices/native/juce_mac_CoreMidi.cpp b/JuceLibraryCode/modules/juce_audio_devices/native/juce_mac_CoreMidi.cpp index 5f8b3d5..a16674c 100644 --- a/JuceLibraryCode/modules/juce_audio_devices/native/juce_mac_CoreMidi.cpp +++ b/JuceLibraryCode/modules/juce_audio_devices/native/juce_mac_CoreMidi.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -45,6 +45,14 @@ namespace CoreMidiHelpers #define CHECK_ERROR(a) CoreMidiHelpers::checkError (a, __LINE__) //============================================================================== + struct ScopedCFString + { + ScopedCFString() noexcept : cfString (nullptr) {} + ~ScopedCFString() noexcept { if (cfString != nullptr) CFRelease (cfString); } + + CFStringRef cfString; + }; + static String getMidiObjectName (MIDIObjectRef entity) { String result; @@ -116,7 +124,7 @@ namespace CoreMidiHelpers if (numConnections > 0) { - const SInt32* pid = reinterpret_cast (CFDataGetBytePtr (connections)); + const SInt32* pid = reinterpret_cast (CFDataGetBytePtr (connections)); for (int i = 0; i < numConnections; ++i, ++pid) { @@ -133,7 +141,7 @@ namespace CoreMidiHelpers || connObjectType == kMIDIObjectType_ExternalDestination) { // Connected to an external device's endpoint (10.3 and later). - s = getEndpointName (static_cast (connObject), true); + s = getEndpointName (static_cast (connObject), true); } else { @@ -208,9 +216,9 @@ namespace CoreMidiHelpers // correctly when called from the message thread! jassert (MessageManager::getInstance()->isThisTheMessageThread()); - CFStringRef name = getGlobalMidiClientName().toCFString(); - CHECK_ERROR (MIDIClientCreate (name, &globalSystemChangeCallback, nullptr, &globalMidiClient)); - CFRelease (name); + CoreMidiHelpers::ScopedCFString name; + name.cfString = getGlobalMidiClientName().toCFString(); + CHECK_ERROR (MIDIClientCreate (name.cfString, &globalSystemChangeCallback, nullptr, &globalMidiClient)); } return globalMidiClient; @@ -220,12 +228,12 @@ namespace CoreMidiHelpers class MidiPortAndEndpoint { public: - MidiPortAndEndpoint (MIDIPortRef p, MIDIEndpointRef ep) + MidiPortAndEndpoint (MIDIPortRef p, MIDIEndpointRef ep) noexcept : port (p), endPoint (ep) { } - ~MidiPortAndEndpoint() + ~MidiPortAndEndpoint() noexcept { if (port != 0) MIDIPortDispose (port); @@ -234,7 +242,7 @@ namespace CoreMidiHelpers MIDIEndpointDispose (endPoint); } - void send (const MIDIPacketList* const packets) + void send (const MIDIPacketList* const packets) noexcept { if (port != 0) MIDISend (port, endPoint, packets); @@ -302,7 +310,7 @@ namespace CoreMidiHelpers static void midiInputProc (const MIDIPacketList* pktlist, void* readProcRefCon, void* /*srcConnRefCon*/) { - static_cast (readProcRefCon)->handlePackets (pktlist); + static_cast (readProcRefCon)->handlePackets (pktlist); } } @@ -318,19 +326,18 @@ MidiOutput* MidiOutput::openDevice (int index) { MIDIEndpointRef endPoint = MIDIGetDestination ((ItemCount) index); - CFStringRef pname; - if (CHECK_ERROR (MIDIObjectGetStringProperty (endPoint, kMIDIPropertyName, &pname))) + CoreMidiHelpers::ScopedCFString pname; + + if (CHECK_ERROR (MIDIObjectGetStringProperty (endPoint, kMIDIPropertyName, &pname.cfString))) { MIDIClientRef client = CoreMidiHelpers::getGlobalMidiClient(); MIDIPortRef port; - if (client != 0 && CHECK_ERROR (MIDIOutputPortCreate (client, pname, &port))) + if (client != 0 && CHECK_ERROR (MIDIOutputPortCreate (client, pname.cfString, &port))) { mo = new MidiOutput(); mo->internal = new CoreMidiHelpers::MidiPortAndEndpoint (port, endPoint); } - - CFRelease (pname); } } @@ -339,20 +346,20 @@ MidiOutput* MidiOutput::openDevice (int index) MidiOutput* MidiOutput::createNewDevice (const String& deviceName) { - MidiOutput* mo = nullptr; MIDIClientRef client = CoreMidiHelpers::getGlobalMidiClient(); - MIDIEndpointRef endPoint; - CFStringRef name = deviceName.toCFString(); - if (client != 0 && CHECK_ERROR (MIDISourceCreate (client, name, &endPoint))) + CoreMidiHelpers::ScopedCFString name; + name.cfString = deviceName.toCFString(); + + if (client != 0 && CHECK_ERROR (MIDISourceCreate (client, name.cfString, &endPoint))) { - mo = new MidiOutput(); + MidiOutput* mo = new MidiOutput(); mo->internal = new CoreMidiHelpers::MidiPortAndEndpoint (0, endPoint); + return mo; } - CFRelease (name); - return mo; + return nullptr; } MidiOutput::~MidiOutput() @@ -370,7 +377,7 @@ void MidiOutput::sendMessageNow (const MidiMessage& message) const MIDITimeStamp timeStamp = AudioGetCurrentHostTime(); #endif - HeapBlock allocatedPackets; + HeapBlock allocatedPackets; MIDIPacketList stackPacket; MIDIPacketList* packetToSend = &stackPacket; const size_t dataSize = (size_t) message.getRawDataSize(); @@ -436,16 +443,16 @@ MidiInput* MidiInput::openDevice (int index, MidiInputCallback* callback) { if (MIDIEndpointRef endPoint = MIDIGetSource ((ItemCount) index)) { - CFStringRef name; + ScopedCFString name; - if (CHECK_ERROR (MIDIObjectGetStringProperty (endPoint, kMIDIPropertyName, &name))) + if (CHECK_ERROR (MIDIObjectGetStringProperty (endPoint, kMIDIPropertyName, &name.cfString))) { if (MIDIClientRef client = getGlobalMidiClient()) { MIDIPortRef port; - ScopedPointer mpc (new MidiPortAndCallback (*callback)); + ScopedPointer mpc (new MidiPortAndCallback (*callback)); - if (CHECK_ERROR (MIDIInputPortCreate (client, name, midiInputProc, mpc, &port))) + if (CHECK_ERROR (MIDIInputPortCreate (client, name.cfString, midiInputProc, mpc, &port))) { if (CHECK_ERROR (MIDIPortConnectSource (port, endPoint, nullptr))) { @@ -465,8 +472,6 @@ MidiInput* MidiInput::openDevice (int index, MidiInputCallback* callback) } } } - - CFRelease (name); } } @@ -482,13 +487,14 @@ MidiInput* MidiInput::createNewDevice (const String& deviceName, MidiInputCallba if (MIDIClientRef client = getGlobalMidiClient()) { - ScopedPointer mpc (new MidiPortAndCallback (*callback)); + ScopedPointer mpc (new MidiPortAndCallback (*callback)); mpc->active = false; MIDIEndpointRef endPoint; - CFStringRef name = deviceName.toCFString(); + ScopedCFString name; + name.cfString = deviceName.toCFString(); - if (CHECK_ERROR (MIDIDestinationCreate (client, name, midiInputProc, mpc, &endPoint))) + if (CHECK_ERROR (MIDIDestinationCreate (client, name.cfString, midiInputProc, mpc, &endPoint))) { mpc->portAndEndpoint = new MidiPortAndEndpoint (0, endPoint); @@ -499,8 +505,6 @@ MidiInput* MidiInput::createNewDevice (const String& deviceName, MidiInputCallba const ScopedLock sl (callbackLock); activeCallbacks.add (mpc.release()); } - - CFRelease (name); } return mi; diff --git a/JuceLibraryCode/modules/juce_audio_devices/native/juce_win32_ASIO.cpp b/JuceLibraryCode/modules/juce_audio_devices/native/juce_win32_ASIO.cpp index 1b520dd..a44ce7d 100644 --- a/JuceLibraryCode/modules/juce_audio_devices/native/juce_win32_ASIO.cpp +++ b/JuceLibraryCode/modules/juce_audio_devices/native/juce_win32_ASIO.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -123,9 +123,9 @@ struct ASIOSampleFormat { switch (bitDepth) { - case 16: convertInt16ToFloat (static_cast (src), dst, byteStride, samps, littleEndian); break; - case 24: convertInt24ToFloat (static_cast (src), dst, byteStride, samps, littleEndian); break; - case 32: convertInt32ToFloat (static_cast (src), dst, byteStride, samps, littleEndian); break; + case 16: convertInt16ToFloat (static_cast (src), dst, byteStride, samps, littleEndian); break; + case 24: convertInt24ToFloat (static_cast (src), dst, byteStride, samps, littleEndian); break; + case 32: convertInt32ToFloat (static_cast (src), dst, byteStride, samps, littleEndian); break; default: jassertfalse; break; } } @@ -141,9 +141,9 @@ struct ASIOSampleFormat { switch (bitDepth) { - case 16: convertFloatToInt16 (src, static_cast (dst), byteStride, samps, littleEndian); break; - case 24: convertFloatToInt24 (src, static_cast (dst), byteStride, samps, littleEndian); break; - case 32: convertFloatToInt32 (src, static_cast (dst), byteStride, samps, littleEndian); break; + case 16: convertFloatToInt16 (src, static_cast (dst), byteStride, samps, littleEndian); break; + case 24: convertFloatToInt24 (src, static_cast (dst), byteStride, samps, littleEndian); break; + case 32: convertFloatToInt32 (src, static_cast (dst), byteStride, samps, littleEndian); break; default: jassertfalse; break; } } @@ -300,7 +300,7 @@ private: //============================================================================== class ASIOAudioIODevice; -static ASIOAudioIODevice* volatile currentASIODev[3] = { 0 }; +static ASIOAudioIODevice* volatile currentASIODev[16] = { 0 }; extern HWND juce_messageWindowHandle; @@ -365,7 +365,7 @@ public: void updateSampleRates() { // find a list of sample rates.. - const int possibleSampleRates[] = { 44100, 48000, 88200, 96000, 176400, 192000 }; + const int possibleSampleRates[] = { 44100, 48000, 88200, 96000, 176400, 192000, 352800, 384000 }; Array newRates; if (asioObject != nullptr) @@ -438,8 +438,6 @@ public: currentBlockSizeSamples = bufferSizeSamples; currentChansOut.clear(); currentChansIn.clear(); - inBuffers.clear (totalNumInputChans + 1); - outBuffers.clear (totalNumOutputChans + 1); updateSampleRates(); @@ -458,6 +456,13 @@ public: setSampleRate (sampleRate); + // (need to get this again in case a sample rate change affected the channel count) + err = asioObject->getChannels (&totalNumInputChans, &totalNumOutputChans); + jassert (err == ASE_OK); + + inBuffers.calloc (totalNumInputChans + 8); + outBuffers.calloc (totalNumOutputChans + 8); + if (needToReset) { JUCE_ASIO_LOG (" Resetting"); @@ -1320,7 +1325,7 @@ private: inputFormat[i].convertToFloat (infos[i].buffers[bi], inBuffers[i], samps); } - currentCallback->audioDeviceIOCallback (const_cast (inBuffers.getData()), numActiveInputChans, + currentCallback->audioDeviceIOCallback (const_cast (inBuffers.getData()), numActiveInputChans, outBuffers, numActiveOutputChans, samps); for (int i = 0; i < numActiveOutputChans; ++i) @@ -1340,6 +1345,29 @@ private: asioObject->outputReady(); } + long asioMessagesCallback (long selector, long value) + { + switch (selector) + { + case kAsioSelectorSupported: + if (value == kAsioResetRequest || value == kAsioEngineVersion || value == kAsioResyncRequest + || value == kAsioLatenciesChanged || value == kAsioSupportsInputMonitor) + return 1; + break; + + case kAsioBufferSizeChange: JUCE_ASIO_LOG ("kAsioBufferSizeChange"); resetRequest(); return 1; + case kAsioResetRequest: JUCE_ASIO_LOG ("kAsioResetRequest"); resetRequest(); return 1; + case kAsioResyncRequest: JUCE_ASIO_LOG ("kAsioResyncRequest"); resetRequest(); return 1; + case kAsioLatenciesChanged: JUCE_ASIO_LOG ("kAsioLatenciesChanged"); return 1; + case kAsioEngineVersion: return 2; + + case kAsioSupportsTimeInfo: + case kAsioSupportsTimeCode: return 0; + } + + return 0; + } + //============================================================================== template struct ASIOCallbackFunctions @@ -1360,56 +1388,43 @@ private: static long JUCE_ASIOCALLBACK asioMessagesCallback (long selector, long value, void*, double*) { - switch (selector) - { - case kAsioSelectorSupported: - if (value == kAsioResetRequest || value == kAsioEngineVersion || value == kAsioResyncRequest - || value == kAsioLatenciesChanged || value == kAsioSupportsInputMonitor) - return 1; - break; - - case kAsioBufferSizeChange: JUCE_ASIO_LOG ("kAsioBufferSizeChange"); return sendResetRequest (deviceIndex); - case kAsioResetRequest: JUCE_ASIO_LOG ("kAsioResetRequest"); return sendResetRequest (deviceIndex); - case kAsioResyncRequest: JUCE_ASIO_LOG ("kAsioResyncRequest"); return sendResetRequest (deviceIndex); - case kAsioLatenciesChanged: JUCE_ASIO_LOG ("kAsioLatenciesChanged"); return 1; - case kAsioEngineVersion: return 2; - - case kAsioSupportsTimeInfo: - case kAsioSupportsTimeCode: - return 0; - } - - return 0; + return currentASIODev[deviceIndex] != nullptr + ? currentASIODev[deviceIndex]->asioMessagesCallback (selector, value) + : 0; } static void JUCE_ASIOCALLBACK sampleRateChangedCallback (ASIOSampleRate) { - sendResetRequest (deviceIndex); + if (currentASIODev[deviceIndex] != nullptr) + currentASIODev[deviceIndex]->resetRequest(); } - static long sendResetRequest (int index) + static void setCallbacks (ASIOCallbacks& callbacks) noexcept { - if (currentASIODev[index] != nullptr) - currentASIODev[index]->resetRequest(); - - return 1; + callbacks.bufferSwitch = &bufferSwitchCallback; + callbacks.asioMessage = &asioMessagesCallback; + callbacks.bufferSwitchTimeInfo = &bufferSwitchTimeInfoCallback; + callbacks.sampleRateDidChange = &sampleRateChangedCallback; } - static void setCallbacks (ASIOCallbacks& callbacks) + static void setCallbacksForDevice (ASIOCallbacks& callbacks, ASIOAudioIODevice* device) noexcept { - callbacks.bufferSwitch = &bufferSwitchCallback; - callbacks.asioMessage = &asioMessagesCallback; - callbacks.bufferSwitchTimeInfo = &bufferSwitchTimeInfoCallback; - callbacks.sampleRateDidChange = &sampleRateChangedCallback; + if (currentASIODev[deviceIndex] == device) + setCallbacks (callbacks); + else + ASIOCallbackFunctions::setCallbacksForDevice (callbacks, device); } }; - void setCallbackFunctions() + template <> + struct ASIOCallbackFunctions { - if (currentASIODev[0] == this) ASIOCallbackFunctions<0>::setCallbacks (callbacks); - else if (currentASIODev[1] == this) ASIOCallbackFunctions<1>::setCallbacks (callbacks); - else if (currentASIODev[2] == this) ASIOCallbackFunctions<2>::setCallbacks (callbacks); - else jassertfalse; + static void setCallbacksForDevice (ASIOCallbacks&, ASIOAudioIODevice*) noexcept {} + }; + + void setCallbackFunctions() noexcept + { + ASIOCallbackFunctions<0>::setCallbacksForDevice (callbacks, this); } JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ASIOAudioIODevice) @@ -1503,15 +1518,16 @@ public: jassert (inputDeviceName == outputDeviceName || outputDeviceName.isEmpty() || inputDeviceName.isEmpty()); jassert (hasScanned); // need to call scanForDevices() before doing this - const int index = deviceNames.indexOf (outputDeviceName.isNotEmpty() ? outputDeviceName - : inputDeviceName); + const String deviceName (outputDeviceName.isNotEmpty() ? outputDeviceName + : inputDeviceName); + const int index = deviceNames.indexOf (deviceName); if (index >= 0) { const int freeSlot = findFreeSlot(); if (freeSlot >= 0) - return new ASIOAudioIODevice (this, outputDeviceName, + return new ASIOAudioIODevice (this, deviceName, classIds.getReference (index), freeSlot); } diff --git a/JuceLibraryCode/modules/juce_audio_devices/native/juce_win32_AudioCDBurner.cpp b/JuceLibraryCode/modules/juce_audio_devices/native/juce_win32_AudioCDBurner.cpp index 3c3befb..03a3c32 100644 --- a/JuceLibraryCode/modules/juce_audio_devices/native/juce_win32_AudioCDBurner.cpp +++ b/JuceLibraryCode/modules/juce_audio_devices/native/juce_win32_AudioCDBurner.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_audio_devices/native/juce_win32_AudioCDReader.cpp b/JuceLibraryCode/modules/juce_audio_devices/native/juce_win32_AudioCDReader.cpp index 064ca91..fe9076a 100644 --- a/JuceLibraryCode/modules/juce_audio_devices/native/juce_win32_AudioCDReader.cpp +++ b/JuceLibraryCode/modules/juce_audio_devices/native/juce_win32_AudioCDReader.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_audio_devices/native/juce_win32_DirectSound.cpp b/JuceLibraryCode/modules/juce_audio_devices/native/juce_win32_DirectSound.cpp index 9c43a1d..18159bd 100644 --- a/JuceLibraryCode/modules/juce_audio_devices/native/juce_win32_DirectSound.cpp +++ b/JuceLibraryCode/modules/juce_audio_devices/native/juce_win32_DirectSound.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -1255,7 +1255,7 @@ private: DSoundDeviceList deviceList; bool hasScanned; - void systemDeviceChanged() + void systemDeviceChanged() override { DSoundDeviceList newList; newList.scan(); diff --git a/JuceLibraryCode/modules/juce_audio_devices/native/juce_win32_Midi.cpp b/JuceLibraryCode/modules/juce_audio_devices/native/juce_win32_Midi.cpp index 2737b1e..abab612 100644 --- a/JuceLibraryCode/modules/juce_audio_devices/native/juce_win32_Midi.cpp +++ b/JuceLibraryCode/modules/juce_audio_devices/native/juce_win32_Midi.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_audio_devices/native/juce_win32_WASAPI.cpp b/JuceLibraryCode/modules/juce_audio_devices/native/juce_win32_WASAPI.cpp index 98e276c..acff84b 100644 --- a/JuceLibraryCode/modules/juce_audio_devices/native/juce_win32_WASAPI.cpp +++ b/JuceLibraryCode/modules/juce_audio_devices/native/juce_win32_WASAPI.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -33,8 +33,8 @@ namespace WasapiClasses void logFailure (HRESULT hr) { (void) hr; - jassert (hr != 0x800401f0); // If you hit this, it means you're trying to call from - // a thread which hasn't been initialised with CoInitialize(). + jassert (hr != (HRESULT) 0x800401f0); // If you hit this, it means you're trying to call from + // a thread which hasn't been initialised with CoInitialize(). #if JUCE_WASAPI_LOGGING if (FAILED (hr)) @@ -45,6 +45,7 @@ void logFailure (HRESULT hr) { case E_POINTER: m = "E_POINTER"; break; case E_INVALIDARG: m = "E_INVALIDARG"; break; + case E_NOINTERFACE: m = "E_NOINTERFACE"; break; #define JUCE_WASAPI_ERR(desc, n) \ case MAKE_HRESULT(1, 0x889, n): m = #desc; break; @@ -126,7 +127,11 @@ enum EDataFlow eAll = (eCapture + 1) }; -enum { DEVICE_STATE_ACTIVE = 1 }; +enum +{ + DEVICE_STATE_ACTIVE = 1, + AUDCLNT_BUFFERFLAGS_SILENT = 2 +}; JUCE_IUNKNOWNCLASS (IPropertyStore, "886d8eeb-8cf2-4446-8d02-cdba1dbdcf99") { @@ -328,6 +333,11 @@ int refTimeToSamples (const REFERENCE_TIME& t, const double sampleRate) noexcept return roundToInt (sampleRate * ((double) t) * 0.0000001); } +REFERENCE_TIME samplesToRefTime (const int numSamples, const double sampleRate) noexcept +{ + return (REFERENCE_TIME) ((numSamples * 10000.0 * 1000.0 / sampleRate) + 0.5); +} + void copyWavFormat (WAVEFORMATEXTENSIBLE& dest, const WAVEFORMATEX* const src) noexcept { memcpy (&dest, src, src->wFormatTag == WAVE_FORMAT_EXTENSIBLE ? sizeof (WAVEFORMATEXTENSIBLE) @@ -348,9 +358,12 @@ public: defaultBufferSize (0), latencySamples (0), useExclusiveMode (exclusiveMode), + actualBufferSize (0), + bytesPerSample (0), + bytesPerFrame (0), sampleRateHasChanged (false) { - clientEvent = CreateEvent (0, false, false, _T("JuceWASAPI")); + clientEvent = CreateEvent (nullptr, false, false, nullptr); ComSmartPtr tempClient (createClient()); if (tempClient == nullptr) @@ -376,16 +389,24 @@ public: rates.addUsingDefaultSort (defaultSampleRate); - static const int ratesToTest[] = { 44100, 48000, 88200, 96000, 176400, 192000 }; + if (useExclusiveMode + && findSupportedFormat (tempClient, defaultSampleRate, format.dwChannelMask, format)) + { + // Got a format that is supported by the device so we can ask what sample rates are supported (in whatever format) + } + + static const int ratesToTest[] = { 44100, 48000, 88200, 96000, 176400, 192000, 352800, 384000 }; for (int i = 0; i < numElementsInArray (ratesToTest); ++i) { - if (ratesToTest[i] == defaultSampleRate) + if (rates.contains (ratesToTest[i])) continue; - format.Format.nSamplesPerSec = (DWORD) ratesToTest[i]; + format.Format.nSamplesPerSec = (DWORD) ratesToTest[i]; + format.Format.nAvgBytesPerSec = (DWORD) (format.Format.nSamplesPerSec * format.Format.nChannels * format.Format.wBitsPerSample / 8); - if (SUCCEEDED (tempClient->IsFormatSupported (useExclusiveMode ? AUDCLNT_SHAREMODE_EXCLUSIVE : AUDCLNT_SHAREMODE_SHARED, + if (SUCCEEDED (tempClient->IsFormatSupported (useExclusiveMode ? AUDCLNT_SHAREMODE_EXCLUSIVE + : AUDCLNT_SHAREMODE_SHARED, (WAVEFORMATEX*) &format, 0))) if (! rates.contains (ratesToTest[i])) rates.addUsingDefaultSort (ratesToTest[i]); @@ -400,7 +421,7 @@ public: bool isOk() const noexcept { return defaultBufferSize > 0 && defaultSampleRate > 0; } - bool openClient (const double newSampleRate, const BigInteger& newChannels) + bool openClient (const double newSampleRate, const BigInteger& newChannels, const int bufferSizeSamples) { sampleRate = newSampleRate; channels = newChannels; @@ -413,8 +434,7 @@ public: client = createClient(); if (client != nullptr - && (tryInitialisingWithFormat (true, 4) || tryInitialisingWithFormat (false, 4) - || tryInitialisingWithFormat (false, 3) || tryInitialisingWithFormat (false, 2))) + && tryInitialisingWithBufferSize (bufferSizeSamples)) { sampleRateHasChanged = false; @@ -465,7 +485,7 @@ public: BigInteger channels; Array channelMaps; UINT32 actualBufferSize; - int bytesPerSample; + int bytesPerSample, bytesPerFrame; bool sampleRateHasChanged; virtual void updateFormat (bool isFloat) = 0; @@ -536,12 +556,19 @@ private: return client; } - bool tryInitialisingWithFormat (const bool useFloat, const int bytesPerSampleToTry) + struct AudioSampleFormat + { + bool useFloat; + int bitsPerSampleToTry; + int bytesPerSampleContainer; + }; + + bool tryFormat (const AudioSampleFormat sampleFormat, IAudioClient* clientToUse, double sampleRate, + DWORD mixFormatChannelMask, WAVEFORMATEXTENSIBLE& format) const { - WAVEFORMATEXTENSIBLE format; zerostruct (format); - if (numChannels <= 2 && bytesPerSampleToTry <= 2) + if (numChannels <= 2 && sampleFormat.bitsPerSampleToTry <= 16) { format.Format.wFormatTag = WAVE_FORMAT_PCM; } @@ -553,45 +580,97 @@ private: format.Format.nSamplesPerSec = (DWORD) sampleRate; format.Format.nChannels = (WORD) numChannels; - format.Format.wBitsPerSample = (WORD) (8 * bytesPerSampleToTry); - format.Format.nAvgBytesPerSec = (DWORD) (format.Format.nSamplesPerSec * numChannels * bytesPerSampleToTry); - format.Format.nBlockAlign = (WORD) (numChannels * bytesPerSampleToTry); - format.SubFormat = useFloat ? KSDATAFORMAT_SUBTYPE_IEEE_FLOAT : KSDATAFORMAT_SUBTYPE_PCM; - format.Samples.wValidBitsPerSample = format.Format.wBitsPerSample; + format.Format.wBitsPerSample = (WORD) (8 * sampleFormat.bytesPerSampleContainer); + format.Samples.wValidBitsPerSample = (WORD) (sampleFormat.bitsPerSampleToTry); + format.Format.nBlockAlign = (WORD) (format.Format.nChannels * format.Format.wBitsPerSample / 8); + format.Format.nAvgBytesPerSec = (DWORD) (format.Format.nSamplesPerSec * format.Format.nBlockAlign); + format.SubFormat = sampleFormat.useFloat ? KSDATAFORMAT_SUBTYPE_IEEE_FLOAT : KSDATAFORMAT_SUBTYPE_PCM; format.dwChannelMask = mixFormatChannelMask; WAVEFORMATEXTENSIBLE* nearestFormat = nullptr; - HRESULT hr = client->IsFormatSupported (useExclusiveMode ? AUDCLNT_SHAREMODE_EXCLUSIVE - : AUDCLNT_SHAREMODE_SHARED, - (WAVEFORMATEX*) &format, - useExclusiveMode ? nullptr : (WAVEFORMATEX**) &nearestFormat); + HRESULT hr = clientToUse->IsFormatSupported (useExclusiveMode ? AUDCLNT_SHAREMODE_EXCLUSIVE + : AUDCLNT_SHAREMODE_SHARED, + (WAVEFORMATEX*) &format, + useExclusiveMode ? nullptr : (WAVEFORMATEX**) &nearestFormat); logFailure (hr); if (hr == S_FALSE && format.Format.nSamplesPerSec == nearestFormat->Format.nSamplesPerSec) { - copyWavFormat (format, (WAVEFORMATEX*) nearestFormat); + copyWavFormat (format, (const WAVEFORMATEX*) nearestFormat); hr = S_OK; } CoTaskMemFree (nearestFormat); + return check (hr); + } + + bool findSupportedFormat (IAudioClient* clientToUse, double sampleRate, + DWORD mixFormatChannelMask, WAVEFORMATEXTENSIBLE& format) const + { + static const AudioSampleFormat formats[] = + { + { true, 32, 4 }, + { false, 32, 4 }, + { false, 24, 4 }, + { false, 24, 3 }, + { false, 20, 4 }, + { false, 20, 3 }, + { false, 16, 2 } + }; + + for (int i = 0; i < numElementsInArray (formats); ++i) + if (tryFormat (formats[i], clientToUse, sampleRate, mixFormatChannelMask, format)) + return true; + + return false; + } + + bool tryInitialisingWithBufferSize (const int bufferSizeSamples) + { + WAVEFORMATEXTENSIBLE format; + + if (findSupportedFormat (client, sampleRate, mixFormatChannelMask, format)) + { + REFERENCE_TIME defaultPeriod = 0, minPeriod = 0; - REFERENCE_TIME defaultPeriod = 0, minPeriod = 0; - if (useExclusiveMode) check (client->GetDevicePeriod (&defaultPeriod, &minPeriod)); - GUID session; - if (hr == S_OK - && check (client->Initialize (useExclusiveMode ? AUDCLNT_SHAREMODE_EXCLUSIVE : AUDCLNT_SHAREMODE_SHARED, - 0x40000 /*AUDCLNT_STREAMFLAGS_EVENTCALLBACK*/, - defaultPeriod, defaultPeriod, (WAVEFORMATEX*) &format, &session))) - { - actualNumChannels = format.Format.nChannels; - const bool isFloat = format.Format.wFormatTag == WAVE_FORMAT_EXTENSIBLE && format.SubFormat == KSDATAFORMAT_SUBTYPE_IEEE_FLOAT; - bytesPerSample = format.Format.wBitsPerSample / 8; + if (useExclusiveMode && bufferSizeSamples > 0) + defaultPeriod = jmax (minPeriod, samplesToRefTime (bufferSizeSamples, format.Format.nSamplesPerSec)); - updateFormat (isFloat); - return true; + for (;;) + { + GUID session; + HRESULT hr = client->Initialize (useExclusiveMode ? AUDCLNT_SHAREMODE_EXCLUSIVE : AUDCLNT_SHAREMODE_SHARED, + 0x40000 /*AUDCLNT_STREAMFLAGS_EVENTCALLBACK*/, + defaultPeriod, useExclusiveMode ? defaultPeriod : 0, (WAVEFORMATEX*) &format, &session); + + if (check (hr)) + { + actualNumChannels = format.Format.nChannels; + const bool isFloat = format.Format.wFormatTag == WAVE_FORMAT_EXTENSIBLE && format.SubFormat == KSDATAFORMAT_SUBTYPE_IEEE_FLOAT; + bytesPerSample = format.Format.wBitsPerSample / 8; + bytesPerFrame = format.Format.nBlockAlign; + + updateFormat (isFloat); + return true; + } + + // Handle the "alignment dance" : http://msdn.microsoft.com/en-us/library/windows/desktop/dd370875(v=vs.85).aspx (see Remarks) + if (hr != MAKE_HRESULT (1, 0x889, 0x19)) // AUDCLNT_E_BUFFER_SIZE_NOT_ALIGNED + break; + + UINT32 numFrames = 0; + if (! check (client->GetBufferSize (&numFrames))) + break; + + // Recreate client + client = nullptr; + client = createClient(); + + defaultPeriod = samplesToRefTime (numFrames, format.Format.nSamplesPerSec); + } } return false; @@ -615,12 +694,9 @@ public: close(); } - bool open (const double newSampleRate, const BigInteger& newChannels) + bool open (const double newSampleRate, const BigInteger& newChannels, int bufferSizeSamples) { - reservoirSize = 0; - reservoirCapacity = 16384; - reservoir.setSize (actualNumChannels * reservoirCapacity * sizeof (float)); - return openClient (newSampleRate, newChannels) + return openClient (newSampleRate, newChannels, bufferSizeSamples) && (numChannels == 0 || check (client->GetService (__uuidof (IAudioCaptureClient), (void**) captureClient.resetAndGetPointerAddress()))); } @@ -630,88 +706,129 @@ public: closeClient(); captureClient = nullptr; reservoir.reset(); + reservoirReadPos = reservoirWritePos = 0; } template - void updateFormatWithType (SourceType*) + void updateFormatWithType (SourceType*) noexcept { typedef AudioData::Pointer NativeType; converter = new AudioData::ConverterInstance, NativeType> (actualNumChannels, 1); } - void updateFormat (bool isFloat) + void updateFormat (bool isFloat) override { - if (isFloat) updateFormatWithType ((AudioData::Float32*) 0); - else if (bytesPerSample == 4) updateFormatWithType ((AudioData::Int32*) 0); - else if (bytesPerSample == 3) updateFormatWithType ((AudioData::Int24*) 0); - else updateFormatWithType ((AudioData::Int16*) 0); + if (isFloat) updateFormatWithType ((AudioData::Float32*) nullptr); + else if (bytesPerSample == 4) updateFormatWithType ((AudioData::Int32*) nullptr); + else if (bytesPerSample == 3) updateFormatWithType ((AudioData::Int24*) nullptr); + else updateFormatWithType ((AudioData::Int16*) nullptr); } - void copyBuffers (float** destBuffers, int numDestBuffers, int bufferSize, Thread& thread) + bool start (const int userBufferSize) + { + reservoirSize = actualBufferSize + userBufferSize; + reservoirMask = nextPowerOfTwo (reservoirSize) - 1; + reservoir.setSize ((reservoirMask + 1) * bytesPerFrame, true); + reservoirReadPos = reservoirWritePos = 0; + + if (! check (client->Start())) + return false; + + purgeInputBuffers(); + return true; + } + + void purgeInputBuffers() + { + uint8* inputData; + UINT32 numSamplesAvailable; + DWORD flags; + + while (captureClient->GetBuffer (&inputData, &numSamplesAvailable, &flags, nullptr, nullptr) + != MAKE_HRESULT (0, 0x889, 0x1) /* AUDCLNT_S_BUFFER_EMPTY */) + captureClient->ReleaseBuffer (numSamplesAvailable); + } + + int getNumSamplesInReservoir() const noexcept { return reservoirWritePos - reservoirReadPos; } + + void handleDeviceBuffer() { if (numChannels <= 0) return; - int offset = 0; + uint8* inputData; + UINT32 numSamplesAvailable; + DWORD flags; + + while (check (captureClient->GetBuffer (&inputData, &numSamplesAvailable, &flags, nullptr, nullptr)) && numSamplesAvailable > 0) + { + int samplesLeft = (int) numSamplesAvailable; + + while (samplesLeft > 0) + { + const int localWrite = reservoirWritePos & reservoirMask; + const int samplesToDo = jmin (samplesLeft, reservoirMask + 1 - localWrite); + const int samplesToDoBytes = samplesToDo * bytesPerFrame; + + void* reservoirPtr = addBytesToPointer (reservoir.getData(), localWrite * bytesPerFrame); + + if ((flags & AUDCLNT_BUFFERFLAGS_SILENT) != 0) + zeromem (reservoirPtr, samplesToDoBytes); + else + memcpy (reservoirPtr, inputData, samplesToDoBytes); + + reservoirWritePos += samplesToDo; + inputData += samplesToDoBytes; + samplesLeft -= samplesToDo; + } + + if (getNumSamplesInReservoir() > reservoirSize) + reservoirReadPos = reservoirWritePos - reservoirSize; + + captureClient->ReleaseBuffer (numSamplesAvailable); + } + } + + void copyBuffersFromReservoir (float** destBuffers, int numDestBuffers, int bufferSize) + { + if ((numChannels <= 0 && bufferSize == 0) || reservoir.getSize() == 0) + return; + + int offset = jmax (0, bufferSize - getNumSamplesInReservoir()); + + if (offset > 0) + { + for (int i = 0; i < numDestBuffers; ++i) + zeromem (destBuffers[i], offset * sizeof (float)); + + bufferSize -= offset; + reservoirReadPos -= offset / 2; + } while (bufferSize > 0) { - if (reservoirSize > 0) // There's stuff in the reservoir, so use that... - { - const int samplesToDo = jmin (bufferSize, (int) reservoirSize); + const int localRead = reservoirReadPos & reservoirMask; - for (int i = 0; i < numDestBuffers; ++i) - converter->convertSamples (destBuffers[i] + offset, 0, reservoir.getData(), channelMaps.getUnchecked(i), samplesToDo); + const int samplesToDo = jmin (bufferSize, getNumSamplesInReservoir(), reservoirMask + 1 - localRead); + if (samplesToDo <= 0) + break; - bufferSize -= samplesToDo; - offset += samplesToDo; - reservoirSize = 0; - } - else - { - UINT32 packetLength = 0; - if (! check (captureClient->GetNextPacketSize (&packetLength))) - break; + const int reservoirOffset = localRead * bytesPerFrame; - if (packetLength == 0) - { - if (thread.threadShouldExit() - || WaitForSingleObject (clientEvent, 1000) == WAIT_TIMEOUT) - break; + for (int i = 0; i < numDestBuffers; ++i) + converter->convertSamples (destBuffers[i] + offset, 0, addBytesToPointer (reservoir.getData(), reservoirOffset), channelMaps.getUnchecked(i), samplesToDo); - continue; - } - - uint8* inputData; - UINT32 numSamplesAvailable; - DWORD flags; - - if (check (captureClient->GetBuffer (&inputData, &numSamplesAvailable, &flags, 0, 0))) - { - const int samplesToDo = jmin (bufferSize, (int) numSamplesAvailable); - - for (int i = 0; i < numDestBuffers; ++i) - converter->convertSamples (destBuffers[i] + offset, 0, inputData, channelMaps.getUnchecked(i), samplesToDo); - - bufferSize -= samplesToDo; - offset += samplesToDo; - - if (samplesToDo < (int) numSamplesAvailable) - { - reservoirSize = jmin ((int) (numSamplesAvailable - samplesToDo), reservoirCapacity); - memcpy ((uint8*) reservoir.getData(), inputData + bytesPerSample * actualNumChannels * samplesToDo, - (size_t) (bytesPerSample * actualNumChannels * reservoirSize)); - } - - captureClient->ReleaseBuffer (numSamplesAvailable); - } - } + bufferSize -= samplesToDo; + offset += samplesToDo; + reservoirReadPos += samplesToDo; } } ComSmartPtr captureClient; MemoryBlock reservoir; - int reservoirSize, reservoirCapacity; + int reservoirSize, reservoirMask; + volatile int reservoirReadPos, reservoirWritePos; + ScopedPointer converter; private: @@ -732,10 +849,11 @@ public: close(); } - bool open (const double newSampleRate, const BigInteger& newChannels) + bool open (const double newSampleRate, const BigInteger& newChannels, int bufferSizeSamples) { - return openClient (newSampleRate, newChannels) - && (numChannels == 0 || check (client->GetService (__uuidof (IAudioRenderClient), (void**) renderClient.resetAndGetPointerAddress()))); + return openClient (newSampleRate, newChannels, bufferSizeSamples) + && (numChannels == 0 || check (client->GetService (__uuidof (IAudioRenderClient), + (void**) renderClient.resetAndGetPointerAddress()))); } void close() @@ -751,15 +869,42 @@ public: converter = new AudioData::ConverterInstance > (1, actualNumChannels); } - void updateFormat (bool isFloat) + void updateFormat (bool isFloat) override { - if (isFloat) updateFormatWithType ((AudioData::Float32*) 0); - else if (bytesPerSample == 4) updateFormatWithType ((AudioData::Int32*) 0); - else if (bytesPerSample == 3) updateFormatWithType ((AudioData::Int24*) 0); - else updateFormatWithType ((AudioData::Int16*) 0); + if (isFloat) updateFormatWithType ((AudioData::Float32*) nullptr); + else if (bytesPerSample == 4) updateFormatWithType ((AudioData::Int32*) nullptr); + else if (bytesPerSample == 3) updateFormatWithType ((AudioData::Int24*) nullptr); + else updateFormatWithType ((AudioData::Int16*) nullptr); } - void copyBuffers (const float** const srcBuffers, const int numSrcBuffers, int bufferSize, Thread& thread) + bool start() + { + int samplesToDo = getNumSamplesAvailableToCopy(); + uint8* outputData; + + if (check (renderClient->GetBuffer (samplesToDo, &outputData))) + renderClient->ReleaseBuffer (samplesToDo, AUDCLNT_BUFFERFLAGS_SILENT); + + return check (client->Start()); + } + + int getNumSamplesAvailableToCopy() const + { + if (numChannels <= 0) + return 0; + + if (! useExclusiveMode) + { + UINT32 padding = 0; + if (check (client->GetCurrentPadding (&padding))) + return actualBufferSize - (int) padding; + } + + return actualBufferSize; + } + + void copyBuffers (const float** const srcBuffers, const int numSrcBuffers, int bufferSize, + WASAPIInputDevice* inputDevice, Thread& thread) { if (numChannels <= 0) return; @@ -768,22 +913,25 @@ public: while (bufferSize > 0) { - UINT32 padding = 0; - if (! check (client->GetCurrentPadding (&padding))) - return; + // This is needed in order not to drop any input data if the output device endpoint buffer was full + if ((! useExclusiveMode) && inputDevice != nullptr + && WaitForSingleObject (inputDevice->clientEvent, 0) == WAIT_OBJECT_0) + inputDevice->handleDeviceBuffer(); - int samplesToDo = useExclusiveMode ? bufferSize - : jmin ((int) (actualBufferSize - padding), bufferSize); + int samplesToDo = jmin (getNumSamplesAvailableToCopy(), bufferSize); - if (samplesToDo <= 0) + if (samplesToDo == 0) { - if (thread.threadShouldExit() - || WaitForSingleObject (clientEvent, 1000) == WAIT_TIMEOUT) - break; + // This can ONLY occur in non-exclusive mode + if (! thread.threadShouldExit() && WaitForSingleObject (clientEvent, 1000) == WAIT_OBJECT_0) + continue; - continue; + break; } + if (useExclusiveMode && WaitForSingleObject (clientEvent, 1000) == WAIT_TIMEOUT) + break; + uint8* outputData = nullptr; if (check (renderClient->GetBuffer ((UINT32) samplesToDo, &outputData))) { @@ -791,10 +939,10 @@ public: converter->convertSamples (outputData, channelMaps.getUnchecked(i), srcBuffers[i] + offset, 0, samplesToDo); renderClient->ReleaseBuffer ((UINT32) samplesToDo, 0); - - offset += samplesToDo; - bufferSize -= samplesToDo; } + + bufferSize -= samplesToDo; + offset += samplesToDo; } } @@ -812,13 +960,14 @@ class WASAPIAudioIODevice : public AudioIODevice, { public: WASAPIAudioIODevice (const String& deviceName, - const String& outputDeviceId_, - const String& inputDeviceId_, + const String& typeName, + const String& outputDeviceID, + const String& inputDeviceID, const bool exclusiveMode) - : AudioIODevice (deviceName, "Windows Audio"), + : AudioIODevice (deviceName, typeName), Thread ("Juce WASAPI"), - outputDeviceId (outputDeviceId_), - inputDeviceId (inputDeviceId_), + outputDeviceId (outputDeviceID), + inputDeviceId (inputDeviceID), useExclusiveMode (exclusiveMode), isOpen_ (false), isStarted (false), @@ -932,19 +1081,33 @@ public: lastKnownInputChannels = inputChannels; lastKnownOutputChannels = outputChannels; - if (inputDevice != nullptr && ! inputDevice->open (currentSampleRate, inputChannels)) + if (inputDevice != nullptr && ! inputDevice->open (currentSampleRate, inputChannels, bufferSizeSamples)) { lastError = TRANS("Couldn't open the input device!"); return lastError; } - if (outputDevice != nullptr && ! outputDevice->open (currentSampleRate, outputChannels)) + if (outputDevice != nullptr && ! outputDevice->open (currentSampleRate, outputChannels, bufferSizeSamples)) { close(); lastError = TRANS("Couldn't open the output device!"); return lastError; } + if (useExclusiveMode) + { + // This is to make sure that the callback uses actualBufferSize in case of exclusive mode + if (inputDevice != nullptr && outputDevice != nullptr && inputDevice->actualBufferSize != outputDevice->actualBufferSize) + { + close(); + lastError = TRANS("Couldn't open the output device (buffer size mismatch)"); + return lastError; + } + + currentBufferSizeSamples = outputDevice != nullptr ? outputDevice->actualBufferSize + : inputDevice->actualBufferSize; + } + if (inputDevice != nullptr) ResetEvent (inputDevice->clientEvent); if (outputDevice != nullptr) ResetEvent (outputDevice->clientEvent); @@ -955,7 +1118,7 @@ public: { latencyIn = (int) (inputDevice->latencySamples + currentBufferSizeSamples); - if (! check (inputDevice->client->Start())) + if (! inputDevice->start (currentBufferSizeSamples)) { close(); lastError = TRANS("Couldn't start the input device!"); @@ -967,7 +1130,7 @@ public: { latencyOut = (int) (outputDevice->latencySamples + currentBufferSizeSamples); - if (! check (outputDevice->client->Start())) + if (! outputDevice->start()) { close(); lastError = TRANS("Couldn't start the output device!"); @@ -1056,34 +1219,48 @@ public: const int bufferSize = currentBufferSizeSamples; const int numInputBuffers = getActiveInputChannels().countNumberOfSetBits(); const int numOutputBuffers = getActiveOutputChannels().countNumberOfSetBits(); - bool sampleRateChanged = false; + bool sampleRateHasChanged = false; AudioSampleBuffer ins (jmax (1, numInputBuffers), bufferSize + 32); AudioSampleBuffer outs (jmax (1, numOutputBuffers), bufferSize + 32); float** const inputBuffers = ins.getArrayOfWritePointers(); float** const outputBuffers = outs.getArrayOfWritePointers(); ins.clear(); + outs.clear(); while (! threadShouldExit()) { if (inputDevice != nullptr) { - inputDevice->copyBuffers (inputBuffers, numInputBuffers, bufferSize, *this); + if (outputDevice == nullptr) + { + if (WaitForSingleObject (inputDevice->clientEvent, 1000) == WAIT_TIMEOUT) + break; - if (threadShouldExit()) - break; + inputDevice->handleDeviceBuffer(); + + if (inputDevice->getNumSamplesInReservoir() < bufferSize) + continue; + } + else + { + if (useExclusiveMode && WaitForSingleObject (inputDevice->clientEvent, 0) == WAIT_OBJECT_0) + inputDevice->handleDeviceBuffer(); + } + + inputDevice->copyBuffersFromReservoir (inputBuffers, numInputBuffers, bufferSize); if (inputDevice->sampleRateHasChanged) { - sampleRateChanged = true; + sampleRateHasChanged = true; sampleRateChangedByOutput = false; } } { - const ScopedLock sl (startStopLock); + const ScopedTryLock sl (startStopLock); - if (isStarted) + if (sl.isLocked() && isStarted) callback->audioDeviceIOCallback (const_cast (inputBuffers), numInputBuffers, outputBuffers, numOutputBuffers, bufferSize); else @@ -1092,16 +1269,18 @@ public: if (outputDevice != nullptr) { - outputDevice->copyBuffers (const_cast (outputBuffers), numOutputBuffers, bufferSize, *this); + // Note that this function is handed the input device so it can check for the event and make sure + // the input reservoir is filled up correctly even when bufferSize > device actualBufferSize + outputDevice->copyBuffers (const_cast (outputBuffers), numOutputBuffers, bufferSize, inputDevice, *this); if (outputDevice->sampleRateHasChanged) { - sampleRateChanged = true; + sampleRateHasChanged = true; sampleRateChangedByOutput = true; } } - if (sampleRateChanged) + if (sampleRateHasChanged) { triggerAsyncUpdate(); break; // Quit the thread... will restart it later! @@ -1208,9 +1387,10 @@ class WASAPIAudioIODeviceType : public AudioIODeviceType, private DeviceChangeDetector { public: - WASAPIAudioIODeviceType() - : AudioIODeviceType ("Windows Audio"), + WASAPIAudioIODeviceType (bool exclusive) + : AudioIODeviceType (exclusive ? "Windows Audio (Exclusive Mode)" : "Windows Audio"), DeviceChangeDetector (L"Windows Audio"), + exclusiveMode (exclusive), hasScanned (false) { } @@ -1267,7 +1447,6 @@ public: { jassert (hasScanned); // need to call scanForDevices() before doing this - const bool useExclusiveMode = false; ScopedPointer device; const int outputIndex = outputDeviceNames.indexOf (outputDeviceName); @@ -1277,9 +1456,10 @@ public: { device = new WASAPIAudioIODevice (outputDeviceName.isNotEmpty() ? outputDeviceName : inputDeviceName, + getTypeName(), outputDeviceIds [outputIndex], inputDeviceIds [inputIndex], - useExclusiveMode); + exclusiveMode); if (! device->initialise()) device = nullptr; @@ -1293,7 +1473,7 @@ public: StringArray inputDeviceNames, inputDeviceIds; private: - bool hasScanned; + bool exclusiveMode, hasScanned; ComSmartPtr enumerator; //============================================================================== @@ -1418,7 +1598,7 @@ private: } //============================================================================== - void systemDeviceChanged() + void systemDeviceChanged() override { StringArray newOutNames, newInNames, newOutIds, newInIds; scan (newOutNames, newInNames, newOutIds, newInIds); @@ -1493,12 +1673,16 @@ struct MMDeviceMasterVolume } //============================================================================== -AudioIODeviceType* AudioIODeviceType::createAudioIODeviceType_WASAPI() +AudioIODeviceType* AudioIODeviceType::createAudioIODeviceType_WASAPI (bool exclusiveMode) { - if (SystemStats::getOperatingSystemType() >= SystemStats::WinVista) - return new WasapiClasses::WASAPIAudioIODeviceType(); + #if ! JUCE_WASAPI_EXCLUSIVE + if (exclusiveMode) + return nullptr; + #endif - return nullptr; + return SystemStats::getOperatingSystemType() >= SystemStats::WinVista + ? new WasapiClasses::WASAPIAudioIODeviceType (exclusiveMode) + : nullptr; } //============================================================================== diff --git a/JuceLibraryCode/modules/juce_audio_devices/sources/juce_AudioSourcePlayer.cpp b/JuceLibraryCode/modules/juce_audio_devices/sources/juce_AudioSourcePlayer.cpp index c351795..2e231d7 100644 --- a/JuceLibraryCode/modules/juce_audio_devices/sources/juce_AudioSourcePlayer.cpp +++ b/JuceLibraryCode/modules/juce_audio_devices/sources/juce_AudioSourcePlayer.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_audio_devices/sources/juce_AudioSourcePlayer.h b/JuceLibraryCode/modules/juce_audio_devices/sources/juce_AudioSourcePlayer.h index 0a3751c..02e4449 100644 --- a/JuceLibraryCode/modules/juce_audio_devices/sources/juce_AudioSourcePlayer.h +++ b/JuceLibraryCode/modules/juce_audio_devices/sources/juce_AudioSourcePlayer.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_audio_devices/sources/juce_AudioTransportSource.cpp b/JuceLibraryCode/modules/juce_audio_devices/sources/juce_AudioTransportSource.cpp index e923b46..9e013ef 100644 --- a/JuceLibraryCode/modules/juce_audio_devices/sources/juce_AudioTransportSource.cpp +++ b/JuceLibraryCode/modules/juce_audio_devices/sources/juce_AudioTransportSource.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -182,6 +182,10 @@ void AudioTransportSource::setNextReadPosition (int64 newPosition) newPosition = (int64) (newPosition * sourceSampleRate / sampleRate); positionableSource->setNextReadPosition (newPosition); + + if (resamplerSource != nullptr) + resamplerSource->flushBuffers(); + inputStreamEOF = false; } } diff --git a/JuceLibraryCode/modules/juce_audio_devices/sources/juce_AudioTransportSource.h b/JuceLibraryCode/modules/juce_audio_devices/sources/juce_AudioTransportSource.h index e60dee0..d964d92 100644 --- a/JuceLibraryCode/modules/juce_audio_devices/sources/juce_AudioTransportSource.h +++ b/JuceLibraryCode/modules/juce_audio_devices/sources/juce_AudioTransportSource.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/all.h b/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/all.h index cc01e05..c7f3032 100644 --- a/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/all.h +++ b/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/all.h @@ -1,6 +1,6 @@ /* libFLAC - Free Lossless Audio Codec library * Copyright (C) 2000-2009 Josh Coalson - * Copyright (C) 2011-2013 Xiph.Org Foundation + * Copyright (C) 2011-2014 Xiph.Org Foundation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/alloc.h b/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/alloc.h index 83595ac..3aab81c 100644 --- a/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/alloc.h +++ b/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/alloc.h @@ -1,6 +1,6 @@ /* alloc - Convenience routines for safely allocating memory * Copyright (C) 2007-2009 Josh Coalson - * Copyright (C) 2011-2013 Xiph.Org Foundation + * Copyright (C) 2011-2014 Xiph.Org Foundation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -33,7 +33,7 @@ #ifndef FLAC__SHARE__ALLOC_H #define FLAC__SHARE__ALLOC_H -#if HAVE_CONFIG_H +#ifdef HAVE_CONFIG_H # include #endif diff --git a/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/assert.h b/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/assert.h index fab30f7..f02aeac 100644 --- a/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/assert.h +++ b/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/assert.h @@ -1,6 +1,6 @@ /* libFLAC - Free Lossless Audio Codec library * Copyright (C) 2001-2009 Josh Coalson - * Copyright (C) 2011-2013 Xiph.Org Foundation + * Copyright (C) 2011-2014 Xiph.Org Foundation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/callback.h b/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/callback.h index 5f58552..9928843 100644 --- a/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/callback.h +++ b/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/callback.h @@ -1,6 +1,6 @@ /* libFLAC - Free Lossless Audio Codec library * Copyright (C) 2004-2009 Josh Coalson - * Copyright (C) 2011-2013 Xiph.Org Foundation + * Copyright (C) 2011-2014 Xiph.Org Foundation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/compat.h b/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/compat.h index 6c436cc..a3dc7c7 100644 --- a/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/compat.h +++ b/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/compat.h @@ -1,5 +1,5 @@ /* libFLAC - Free Lossless Audio Codec library - * Copyright (C) 2012 Xiph.org Foundation + * Copyright (C) 2012-2014 Xiph.org Foundation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -73,23 +73,25 @@ #endif #if defined(_MSC_VER) -#if _MSC_VER < 1500 -/* Visual Studio 2008 has restrict. */ -#define restrict __restrict -#endif #define inline __inline #endif -/* adjust for compilers that can't understand using LLU suffix for uint64_t literals */ -#ifdef _MSC_VER -#define FLAC__U64L(x) x +#if defined __INTEL_COMPILER || (defined _MSC_VER && defined _WIN64) +/* MSVS generates VERY slow 32-bit code with __restrict */ +#define flac_restrict __restrict +#elif defined __GNUC__ +#define flac_restrict __restrict__ #else -#define FLAC__U64L(x) x##LLU +#define flac_restrict #endif +#define FLAC__U64L(x) x##ULL + #if defined _MSC_VER || defined __BORLANDC__ || defined __MINGW32__ +#define FLAC__STRCASECMP stricmp #define FLAC__STRNCASECMP strnicmp #else +#define FLAC__STRCASECMP strcasecmp #define FLAC__STRNCASECMP strncasecmp #endif @@ -139,6 +141,7 @@ #ifdef _WIN32 /* All char* strings are in UTF-8 format. Added to support Unicode files on Windows */ +#include "win_utf8_io.h" #define flac_printf printf_utf8 #define flac_fprintf fprintf_utf8 @@ -160,12 +163,7 @@ #define flac_utime utime #define flac_unlink unlink #define flac_rename rename - -#ifdef _WIN32 -#define flac_stat _stat64 -#else #define flac_stat stat -#endif #endif @@ -177,8 +175,14 @@ #define flac_fstat fstat #endif +#ifndef M_LN2 +#define M_LN2 0.69314718055994530942 +#endif +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif -/* FLAC needs to compile and work correctly on systems with a norrmal ISO C99 +/* FLAC needs to compile and work correctly on systems with a normal ISO C99 * snprintf as well as Microsoft Visual Studio which has an non-standards * conformant snprint_s function. * @@ -188,6 +192,7 @@ extern "C" { #endif int flac_snprintf(char *str, size_t size, const char *fmt, ...); +int flac_vsnprintf(char *str, size_t size, const char *fmt, va_list va); #ifdef __cplusplus }; #endif diff --git a/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/endswap.h b/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/endswap.h index 2e09404..b2a7e85 100644 --- a/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/endswap.h +++ b/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/endswap.h @@ -1,5 +1,5 @@ /* libFLAC - Free Lossless Audio Codec library - * Copyright (C) 2012 Xiph.org Foundation + * Copyright (C) 2012-2014 Xiph.org Foundation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -33,20 +33,46 @@ #if HAVE_BSWAP32 /* GCC and Clang */ +/* GCC prior to 4.8 didn't provide bswap16 on x86_64 */ +#if ! HAVE_BSWAP16 +static inline unsigned short __builtin_bswap16(unsigned short a) +{ + return (a<<8)|(a>>8); +} +#endif + +#define ENDSWAP_16(x) (__builtin_bswap16 (x)) #define ENDSWAP_32(x) (__builtin_bswap32 (x)) #elif defined _MSC_VER /* Windows. Apparently in . */ +#define ENDSWAP_16(x) (_byteswap_ushort (x)) #define ENDSWAP_32(x) (_byteswap_ulong (x)) #elif defined HAVE_BYTESWAP_H /* Linux */ #include +#define ENDSWAP_16(x) (bswap_16 (x)) #define ENDSWAP_32(x) (bswap_32 (x)) #else -#define ENDSWAP_32(x) ((((x) >> 24) & 0xFF) + (((x) >> 8) & 0xFF00) + (((x) & 0xFF00) << 8) + (((x) & 0xFF) << 24)) +#define ENDSWAP_16(x) ((((x) >> 8) & 0xFF) | (((x) & 0xFF) << 8)) +#define ENDSWAP_32(x) ((((x) >> 24) & 0xFF) | (((x) >> 8) & 0xFF00) | (((x) & 0xFF00) << 8) | (((x) & 0xFF) << 24)) + +#endif + + +/* Host to little-endian byte swapping. */ +#if CPU_IS_BIG_ENDIAN + +#define H2LE_16(x) ENDSWAP_16 (x) +#define H2LE_32(x) ENDSWAP_32 (x) + +#else + +#define H2LE_16(x) (x) +#define H2LE_32(x) (x) #endif diff --git a/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/export.h b/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/export.h index d7ca735..30f018b 100644 --- a/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/export.h +++ b/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/export.h @@ -1,6 +1,6 @@ /* libFLAC - Free Lossless Audio Codec library * Copyright (C) 2000-2009 Josh Coalson - * Copyright (C) 2011-2013 Xiph.Org Foundation + * Copyright (C) 2011-2014 Xiph.Org Foundation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -61,9 +61,9 @@ #elif defined(_MSC_VER) #ifdef FLAC_API_EXPORTS -#define FLAC_API _declspec(dllexport) +#define FLAC_API __declspec(dllexport) #else -#define FLAC_API _declspec(dllimport) +#define FLAC_API __declspec(dllimport) #endif #elif defined(FLAC__USE_VISIBILITY_ATTR) diff --git a/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/format.h b/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/format.h index ecebe80..a151b67 100644 --- a/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/format.h +++ b/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/format.h @@ -1,6 +1,6 @@ /* libFLAC - Free Lossless Audio Codec library * Copyright (C) 2000-2009 Josh Coalson - * Copyright (C) 2011-2013 Xiph.Org Foundation + * Copyright (C) 2011-2014 Xiph.Org Foundation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -509,9 +509,11 @@ typedef enum { FLAC__METADATA_TYPE_PICTURE = 6, /**< PICTURE block */ - FLAC__METADATA_TYPE_UNDEFINED = 7 + FLAC__METADATA_TYPE_UNDEFINED = 7, /**< marker to denote beginning of undefined type range; this number will increase as new metadata types are added */ + FLAC__MAX_METADATA_TYPE = FLAC__MAX_METADATA_TYPE_CODE, + /**< No type will ever be greater than this. There is not enough room in the protocol block. */ } FLAC__MetadataType; /** Maps a FLAC__MetadataType to a C string. diff --git a/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/bitmath.c b/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/bitmath.c index 3ea040e..e011f84 100644 --- a/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/bitmath.c +++ b/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/bitmath.c @@ -1,6 +1,6 @@ /* libFLAC - Free Lossless Audio Codec library * Copyright (C) 2001-2009 Josh Coalson - * Copyright (C) 2011-2013 Xiph.Org Foundation + * Copyright (C) 2011-2014 Xiph.Org Foundation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -30,12 +30,11 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#if HAVE_CONFIG_H +#ifdef HAVE_CONFIG_H # include #endif #include "include/private/bitmath.h" -#include "../assert.h" /* An example of what FLAC__bitmath_silog2() computes: * diff --git a/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/bitreader.c b/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/bitreader.c index 3fc7e1d..a4632e3 100644 --- a/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/bitreader.c +++ b/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/bitreader.c @@ -1,6 +1,6 @@ /* libFLAC - Free Lossless Audio Codec library * Copyright (C) 2000-2009 Josh Coalson - * Copyright (C) 2011-2013 Xiph.Org Foundation + * Copyright (C) 2011-2014 Xiph.Org Foundation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -30,7 +30,7 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#if HAVE_CONFIG_H +#ifdef HAVE_CONFIG_H # include #endif @@ -73,7 +73,6 @@ */ static const unsigned FLAC__BITREADER_DEFAULT_CAPACITY = 65536u / FLAC__BITS_PER_WORD; /* in words */ -/* WATCHOUT: assembly routines rely on the order in which these fields are declared */ struct FLAC__BitReader { /* any partially-consumed word at the head will stay right-justified as bits are consumed from the left */ /* any incomplete word at the tail will be left-justified, and bytes from the read callback are added on the right */ @@ -87,7 +86,6 @@ struct FLAC__BitReader { unsigned crc16_align; /* the number of bits in the current consumed word that should not be CRC'd */ FLAC__BitReaderReadCallback read_callback; void *client_data; - FLAC__CPUInfo cpu_info; }; static inline void crc16_update_word_(FLAC__BitReader *br, uint32_t word) @@ -119,8 +117,7 @@ static inline void crc16_update_word_(FLAC__BitReader *br, uint32_t word) br->crc16_align = 0; } -/* would be static except it needs to be called by asm routines */ -FLAC__bool bitreader_read_from_client_(FLAC__BitReader *br) +static FLAC__bool bitreader_read_from_client_(FLAC__BitReader *br) { unsigned start, end; size_t bytes; @@ -231,7 +228,7 @@ void FLAC__bitreader_delete(FLAC__BitReader *br) * ***********************************************************************/ -FLAC__bool FLAC__bitreader_init(FLAC__BitReader *br, FLAC__CPUInfo cpu, FLAC__BitReaderReadCallback rcb, void *cd) +FLAC__bool FLAC__bitreader_init(FLAC__BitReader *br, FLAC__BitReaderReadCallback rcb, void *cd) { FLAC__ASSERT(0 != br); @@ -243,7 +240,6 @@ FLAC__bool FLAC__bitreader_init(FLAC__BitReader *br, FLAC__CPUInfo cpu, FLAC__Bi return false; br->read_callback = rcb; br->client_data = cd; - br->cpu_info = cpu; return true; } @@ -1048,9 +1044,9 @@ FLAC__bool FLAC__bitreader_read_utf8_uint64(FLAC__BitReader *br, FLAC__uint64 *v return true; } -/* These functions a declared inline in this file but are also callable as +/* These functions are declared inline in this file but are also callable as * externs from elsewhere. - * According to the C99 sepc, section 6.7.4, simply providing a function + * According to the C99 spec, section 6.7.4, simply providing a function * prototype in a header file without 'inline' and making the function inline * in this file should be sufficient. * Unfortunately, the Microsoft VS compiler doesn't pick them up externally. To diff --git a/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/bitwriter.c b/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/bitwriter.c index 9ac9ee5..565fbcd 100644 --- a/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/bitwriter.c +++ b/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/bitwriter.c @@ -1,6 +1,6 @@ /* libFLAC - Free Lossless Audio Codec library * Copyright (C) 2000-2009 Josh Coalson - * Copyright (C) 2011-2013 Xiph.Org Foundation + * Copyright (C) 2011-2014 Xiph.Org Foundation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -30,7 +30,7 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#if HAVE_CONFIG_H +#ifdef HAVE_CONFIG_H # include #endif @@ -47,8 +47,7 @@ /* WATCHOUT: if you change this you must also change the following #defines down to SWAP_BE_WORD_TO_HOST below to match */ /* WATCHOUT: there are a few places where the code will not work unless uint32_t is >= 32 bits wide */ #define FLAC__BYTES_PER_WORD 4 -#undef FLAC__BITS_PER_WORD -#define FLAC__BITS_PER_WORD 32 +#define FLAC__BITS_PER_WORD (8 * FLAC__BYTES_PER_WORD) #define FLAC__WORD_ALL_ONES ((FLAC__uint32)0xffffffff) /* SWAP_BE_WORD_TO_HOST swaps bytes in a uint32_t (which is always big-endian) if necessary to match host byte order */ #if WORDS_BIGENDIAN @@ -524,28 +523,6 @@ FLAC__bool FLAC__bitwriter_write_rice_signed_block(FLAC__BitWriter *bw, const FL msbits = uval >> parameter; -#if 0 /* OPT: can remove this special case if it doesn't make up for the extra compare (doesn't make a statistically significant difference with msvc or gcc/x86) */ - if(bw->bits && bw->bits + msbits + lsbits <= FLAC__BITS_PER_WORD) { /* i.e. if the whole thing fits in the current uint32_t */ - /* ^^^ if bw->bits is 0 then we may have filled the buffer and have no free uint32_t to work in */ - bw->bits = bw->bits + msbits + lsbits; - uval |= mask1; /* set stop bit */ - uval &= mask2; /* mask off unused top bits */ - /* NOT: bw->accum <<= msbits + lsbits because msbits+lsbits could be 32, then the shift would be a NOP */ - bw->accum <<= msbits; - bw->accum <<= lsbits; - bw->accum |= uval; - if(bw->bits == FLAC__BITS_PER_WORD) { - bw->buffer[bw->words++] = SWAP_BE_WORD_TO_HOST(bw->accum); - bw->bits = 0; - /* burying the capacity check down here means we have to grow the buffer a little if there are more vals to do */ - if(bw->capacity <= bw->words && nvals > 1 && !bitwriter_grow_(bw, 1)) { - FLAC__ASSERT(bw->capacity == bw->words); - return false; - } - } - } - else { -#elif 1 /*@@@@@@ OPT: try this version with MSVC6 to see if better, not much difference for gcc-4 */ if(bw->bits && bw->bits + msbits + lsbits < FLAC__BITS_PER_WORD) { /* i.e. if the whole thing fits in the current uint32_t */ /* ^^^ if bw->bits is 0 then we may have filled the buffer and have no free uint32_t to work in */ bw->bits = bw->bits + msbits + lsbits; @@ -555,7 +532,6 @@ FLAC__bool FLAC__bitwriter_write_rice_signed_block(FLAC__BitWriter *bw, const FL bw->accum |= uval; } else { -#endif /* slightly pessimistic size check but faster than "<= bw->words + (bw->bits+msbits+lsbits+FLAC__BITS_PER_WORD-1)/FLAC__BITS_PER_WORD" */ /* OPT: pessimism may cause flurry of false calls to grow_ which eat up all savings before it */ if(bw->capacity <= bw->words + bw->bits + msbits + 1/*lsbits always fit in 1 uint32_t*/ && !bitwriter_grow_(bw, msbits+lsbits)) @@ -610,9 +586,7 @@ break1: bw->buffer[bw->words++] = SWAP_BE_WORD_TO_HOST(bw->accum); bw->accum = uval; } -#if 1 } -#endif vals++; nvals--; } @@ -853,9 +827,9 @@ FLAC__bool FLAC__bitwriter_zero_pad_to_byte_boundary(FLAC__BitWriter *bw) return true; } -/* These functions a declared inline in this file but are also callable as +/* These functions are declared inline in this file but are also callable as * externs from elsewhere. - * According to the C99 sepc, section 6.7.4, simply providing a function + * According to the C99 spec, section 6.7.4, simply providing a function * prototype in a header file without 'inline' and making the function inline * in this file should be sufficient. * Unfortunately, the Microsoft VS compiler doesn't pick them up externally. To diff --git a/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/cpu.c b/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/cpu.c index e352c95..46db9e3 100644 --- a/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/cpu.c +++ b/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/cpu.c @@ -1,6 +1,6 @@ /* libFLAC - Free Lossless Audio Codec library * Copyright (C) 2001-2009 Josh Coalson - * Copyright (C) 2011-2013 Xiph.Org Foundation + * Copyright (C) 2011-2014 Xiph.Org Foundation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -30,47 +30,47 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#if HAVE_CONFIG_H +#ifdef HAVE_CONFIG_H # include #endif #include "include/private/cpu.h" -#include -#include + +#if 0 + #include + #include + #include +#endif #if defined FLAC__CPU_IA32 # include -#elif defined FLAC__CPU_PPC -# if !defined FLAC__NO_ASM -# if defined FLAC__SYS_DARWIN -# include -# include -# include -# include -# include -# ifndef CPU_SUBTYPE_POWERPC_970 -# define CPU_SUBTYPE_POWERPC_970 ((cpu_subtype_t) 100) -# endif -# else /* FLAC__SYS_DARWIN */ -# include -# include - -static sigjmp_buf jmpbuf; -static volatile sig_atomic_t canjump = 0; - -static void sigill_handler (int sig) +static void disable_sse(FLAC__CPUInfo *info) { - if (!canjump) { - signal (sig, SIG_DFL); - raise (sig); - } - canjump = 0; - siglongjmp (jmpbuf, 1); + info->ia32.sse = false; + info->ia32.sse2 = false; + info->ia32.sse3 = false; + info->ia32.ssse3 = false; + info->ia32.sse41 = false; + info->ia32.sse42 = false; } -# endif /* FLAC__SYS_DARWIN */ -# endif /* FLAC__NO_ASM */ -#endif /* FLAC__CPU_PPC */ + +static void disable_avx(FLAC__CPUInfo *info) +{ + info->ia32.avx = false; + info->ia32.avx2 = false; + info->ia32.fma = false; +} + +#elif defined FLAC__CPU_X86_64 + +static void disable_avx(FLAC__CPUInfo *info) +{ + info->x86.avx = false; + info->x86.avx2 = false; + info->x86.fma = false; +} +#endif #if defined (__NetBSD__) || defined(__OpenBSD__) #include @@ -87,25 +87,34 @@ static void sigill_handler (int sig) /* how to get sysctlbyname()? */ #endif +#ifdef FLAC__CPU_IA32 /* these are flags in EDX of CPUID AX=00000001 */ static const unsigned FLAC__CPUINFO_IA32_CPUID_CMOV = 0x00008000; static const unsigned FLAC__CPUINFO_IA32_CPUID_MMX = 0x00800000; static const unsigned FLAC__CPUINFO_IA32_CPUID_FXSR = 0x01000000; static const unsigned FLAC__CPUINFO_IA32_CPUID_SSE = 0x02000000; static const unsigned FLAC__CPUINFO_IA32_CPUID_SSE2 = 0x04000000; +#endif + /* these are flags in ECX of CPUID AX=00000001 */ static const unsigned FLAC__CPUINFO_IA32_CPUID_SSE3 = 0x00000001; static const unsigned FLAC__CPUINFO_IA32_CPUID_SSSE3 = 0x00000200; -/* these are flags in EDX of CPUID AX=80000001 */ -static const unsigned FLAC__CPUINFO_IA32_CPUID_EXTENDED_AMD_3DNOW = 0x80000000; -static const unsigned FLAC__CPUINFO_IA32_CPUID_EXTENDED_AMD_EXT3DNOW = 0x40000000; -static const unsigned FLAC__CPUINFO_IA32_CPUID_EXTENDED_AMD_EXTMMX = 0x00400000; +static const unsigned FLAC__CPUINFO_IA32_CPUID_SSE41 = 0x00080000; +static const unsigned FLAC__CPUINFO_IA32_CPUID_SSE42 = 0x00100000; +#if defined FLAC__AVX_SUPPORTED +/* these are flags in ECX of CPUID AX=00000001 */ +static const unsigned FLAC__CPUINFO_IA32_CPUID_OSXSAVE = 0x08000000; +static const unsigned FLAC__CPUINFO_IA32_CPUID_AVX = 0x10000000; +static const unsigned FLAC__CPUINFO_IA32_CPUID_FMA = 0x00001000; +/* these are flags in EBX of CPUID AX=00000007 */ +static const unsigned FLAC__CPUINFO_IA32_CPUID_AVX2 = 0x00000020; +#endif /* * Extra stuff needed for detection of OS support for SSE on IA-32 */ -#if defined(FLAC__CPU_IA32) && !defined FLAC__NO_ASM && defined FLAC__HAS_NASM && !defined FLAC__NO_SSE_OS && !defined FLAC__SSE_OS +#if defined(FLAC__CPU_IA32) && !defined FLAC__NO_ASM && (defined FLAC__HAS_NASM || defined FLAC__HAS_X86INTRIN) && !defined FLAC__NO_SSE_OS && !defined FLAC__SSE_OS # if defined(__linux__) /* * If the OS doesn't support SSE, we will get here with a SIGILL. We @@ -120,35 +129,14 @@ static const unsigned FLAC__CPUINFO_IA32_CPUID_EXTENDED_AMD_EXTMMX = 0x00400000; * 6 bytes extra in case our estimate is wrong * 12 bytes puts us in the NOP "landing zone" */ -# undef USE_OBSOLETE_SIGCONTEXT_FLAVOR /* #define this to use the older signal handler method */ -# ifdef USE_OBSOLETE_SIGCONTEXT_FLAVOR - static void sigill_handler_sse_os(int signal, struct sigcontext sc) - { - (void)signal; - sc.eip += 3 + 3 + 6; - } -# else # include static void sigill_handler_sse_os(int signal, siginfo_t *si, void *uc) { (void)signal, (void)si; ((ucontext_t*)uc)->uc_mcontext.gregs[14/*REG_EIP*/] += 3 + 3 + 6; } -# endif # elif defined(_MSC_VER) # include -# define USE_TRY_CATCH_FLAVOR /* sigill_handler flavor resulted in several crash reports on win32 */ -# ifdef USE_TRY_CATCH_FLAVOR -# else - LONG CALLBACK sigill_handler_sse_os(EXCEPTION_POINTERS *ep) - { - if(ep->ExceptionRecord->ExceptionCode == EXCEPTION_ILLEGAL_INSTRUCTION) { - ep->ContextRecord->Eip += 3 + 3 + 6; - return EXCEPTION_CONTINUE_EXECUTION; - } - return EXCEPTION_CONTINUE_SEARCH; - } -# endif # endif #endif @@ -159,261 +147,344 @@ void FLAC__cpu_info(FLAC__CPUInfo *info) * IA32-specific */ #ifdef FLAC__CPU_IA32 + FLAC__bool ia32_fxsr = false; + FLAC__bool ia32_osxsave = false; + (void) ia32_fxsr; (void) ia32_osxsave; /* to avoid warnings about unused variables */ + memset(info, 0, sizeof(*info)); info->type = FLAC__CPUINFO_TYPE_IA32; -#if !defined FLAC__NO_ASM && defined FLAC__HAS_NASM +#if !defined FLAC__NO_ASM && (defined FLAC__HAS_NASM || defined FLAC__HAS_X86INTRIN) info->use_asm = true; /* we assume a minimum of 80386 with FLAC__CPU_IA32 */ - info->data.ia32.cpuid = FLAC__cpu_have_cpuid_asm_ia32()? true : false; - info->data.ia32.bswap = info->data.ia32.cpuid; /* CPUID => BSWAP since it came after */ - info->data.ia32.cmov = false; - info->data.ia32.mmx = false; - info->data.ia32.fxsr = false; - info->data.ia32.sse = false; - info->data.ia32.sse2 = false; - info->data.ia32.sse3 = false; - info->data.ia32.ssse3 = false; - info->data.ia32._3dnow = false; - info->data.ia32.ext3dnow = false; - info->data.ia32.extmmx = false; - if(info->data.ia32.cpuid) { - /* http://www.sandpile.org/ia32/cpuid.htm */ - FLAC__uint32 flags_edx, flags_ecx; - FLAC__cpu_info_asm_ia32(&flags_edx, &flags_ecx); - info->data.ia32.cmov = (flags_edx & FLAC__CPUINFO_IA32_CPUID_CMOV )? true : false; - info->data.ia32.mmx = (flags_edx & FLAC__CPUINFO_IA32_CPUID_MMX )? true : false; - info->data.ia32.fxsr = (flags_edx & FLAC__CPUINFO_IA32_CPUID_FXSR )? true : false; - info->data.ia32.sse = (flags_edx & FLAC__CPUINFO_IA32_CPUID_SSE )? true : false; - info->data.ia32.sse2 = (flags_edx & FLAC__CPUINFO_IA32_CPUID_SSE2 )? true : false; - info->data.ia32.sse3 = (flags_ecx & FLAC__CPUINFO_IA32_CPUID_SSE3 )? true : false; - info->data.ia32.ssse3 = (flags_ecx & FLAC__CPUINFO_IA32_CPUID_SSSE3)? true : false; - -#ifdef FLAC__USE_3DNOW - flags_edx = FLAC__cpu_info_extended_amd_asm_ia32(); - info->data.ia32._3dnow = (flags_edx & FLAC__CPUINFO_IA32_CPUID_EXTENDED_AMD_3DNOW )? true : false; - info->data.ia32.ext3dnow = (flags_edx & FLAC__CPUINFO_IA32_CPUID_EXTENDED_AMD_EXT3DNOW)? true : false; - info->data.ia32.extmmx = (flags_edx & FLAC__CPUINFO_IA32_CPUID_EXTENDED_AMD_EXTMMX )? true : false; +#ifdef FLAC__HAS_X86INTRIN + if(!FLAC__cpu_have_cpuid_x86()) + return; #else - info->data.ia32._3dnow = info->data.ia32.ext3dnow = info->data.ia32.extmmx = false; + if(!FLAC__cpu_have_cpuid_asm_ia32()) + return; #endif + { + /* http://www.sandpile.org/x86/cpuid.htm */ +#ifdef FLAC__HAS_X86INTRIN + FLAC__uint32 flags_eax, flags_ebx, flags_ecx, flags_edx; + FLAC__cpu_info_x86(1, &flags_eax, &flags_ebx, &flags_ecx, &flags_edx); +#else + FLAC__uint32 flags_ecx, flags_edx; + FLAC__cpu_info_asm_ia32(&flags_edx, &flags_ecx); +#endif + info->ia32.cmov = (flags_edx & FLAC__CPUINFO_IA32_CPUID_CMOV )? true : false; + info->ia32.mmx = (flags_edx & FLAC__CPUINFO_IA32_CPUID_MMX )? true : false; + ia32_fxsr = (flags_edx & FLAC__CPUINFO_IA32_CPUID_FXSR )? true : false; + info->ia32.sse = (flags_edx & FLAC__CPUINFO_IA32_CPUID_SSE )? true : false; + info->ia32.sse2 = (flags_edx & FLAC__CPUINFO_IA32_CPUID_SSE2 )? true : false; + info->ia32.sse3 = (flags_ecx & FLAC__CPUINFO_IA32_CPUID_SSE3 )? true : false; + info->ia32.ssse3 = (flags_ecx & FLAC__CPUINFO_IA32_CPUID_SSSE3)? true : false; + info->ia32.sse41 = (flags_ecx & FLAC__CPUINFO_IA32_CPUID_SSE41)? true : false; + info->ia32.sse42 = (flags_ecx & FLAC__CPUINFO_IA32_CPUID_SSE42)? true : false; +#if defined FLAC__HAS_X86INTRIN && defined FLAC__AVX_SUPPORTED + ia32_osxsave = (flags_ecx & FLAC__CPUINFO_IA32_CPUID_OSXSAVE)? true : false; + info->ia32.avx = (flags_ecx & FLAC__CPUINFO_IA32_CPUID_AVX )? true : false; + info->ia32.fma = (flags_ecx & FLAC__CPUINFO_IA32_CPUID_FMA )? true : false; + FLAC__cpu_info_x86(7, &flags_eax, &flags_ebx, &flags_ecx, &flags_edx); + info->ia32.avx2 = (flags_ebx & FLAC__CPUINFO_IA32_CPUID_AVX2 )? true : false; +#endif + } #ifdef DEBUG - fprintf(stderr, "CPU info (IA-32):\n"); - fprintf(stderr, " CPUID ...... %c\n", info->data.ia32.cpuid ? 'Y' : 'n'); - fprintf(stderr, " BSWAP ...... %c\n", info->data.ia32.bswap ? 'Y' : 'n'); - fprintf(stderr, " CMOV ....... %c\n", info->data.ia32.cmov ? 'Y' : 'n'); - fprintf(stderr, " MMX ........ %c\n", info->data.ia32.mmx ? 'Y' : 'n'); - fprintf(stderr, " FXSR ....... %c\n", info->data.ia32.fxsr ? 'Y' : 'n'); - fprintf(stderr, " SSE ........ %c\n", info->data.ia32.sse ? 'Y' : 'n'); - fprintf(stderr, " SSE2 ....... %c\n", info->data.ia32.sse2 ? 'Y' : 'n'); - fprintf(stderr, " SSE3 ....... %c\n", info->data.ia32.sse3 ? 'Y' : 'n'); - fprintf(stderr, " SSSE3 ...... %c\n", info->data.ia32.ssse3 ? 'Y' : 'n'); - fprintf(stderr, " 3DNow! ..... %c\n", info->data.ia32._3dnow ? 'Y' : 'n'); - fprintf(stderr, " 3DNow!-ext . %c\n", info->data.ia32.ext3dnow? 'Y' : 'n'); - fprintf(stderr, " 3DNow!-MMX . %c\n", info->data.ia32.extmmx ? 'Y' : 'n'); + fprintf(stderr, "CPU info (IA-32):\n"); + fprintf(stderr, " CMOV ....... %c\n", info->ia32.cmov ? 'Y' : 'n'); + fprintf(stderr, " MMX ........ %c\n", info->ia32.mmx ? 'Y' : 'n'); + fprintf(stderr, " SSE ........ %c\n", info->ia32.sse ? 'Y' : 'n'); + fprintf(stderr, " SSE2 ....... %c\n", info->ia32.sse2 ? 'Y' : 'n'); + fprintf(stderr, " SSE3 ....... %c\n", info->ia32.sse3 ? 'Y' : 'n'); + fprintf(stderr, " SSSE3 ...... %c\n", info->ia32.ssse3 ? 'Y' : 'n'); + fprintf(stderr, " SSE41 ...... %c\n", info->ia32.sse41 ? 'Y' : 'n'); + fprintf(stderr, " SSE42 ...... %c\n", info->ia32.sse42 ? 'Y' : 'n'); +# if defined FLAC__HAS_X86INTRIN && defined FLAC__AVX_SUPPORTED + fprintf(stderr, " AVX ........ %c\n", info->ia32.avx ? 'Y' : 'n'); + fprintf(stderr, " FMA ........ %c\n", info->ia32.fma ? 'Y' : 'n'); + fprintf(stderr, " AVX2 ....... %c\n", info->ia32.avx2 ? 'Y' : 'n'); +# endif #endif - /* - * now have to check for OS support of SSE/SSE2 - */ - if(info->data.ia32.fxsr || info->data.ia32.sse || info->data.ia32.sse2) { + /* + * now have to check for OS support of SSE instructions + */ + if(info->ia32.sse) { #if defined FLAC__NO_SSE_OS - /* assume user knows better than us; turn it off */ - info->data.ia32.fxsr = info->data.ia32.sse = info->data.ia32.sse2 = info->data.ia32.sse3 = info->data.ia32.ssse3 = false; + /* assume user knows better than us; turn it off */ + disable_sse(info); #elif defined FLAC__SSE_OS - /* assume user knows better than us; leave as detected above */ + /* assume user knows better than us; leave as detected above */ #elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__) || defined(__APPLE__) - int sse = 0; - size_t len; - /* at least one of these must work: */ - len = sizeof(sse); sse = sse || (sysctlbyname("hw.instruction_sse", &sse, &len, NULL, 0) == 0 && sse); - len = sizeof(sse); sse = sse || (sysctlbyname("hw.optional.sse" , &sse, &len, NULL, 0) == 0 && sse); /* __APPLE__ ? */ - if(!sse) - info->data.ia32.fxsr = info->data.ia32.sse = info->data.ia32.sse2 = info->data.ia32.sse3 = info->data.ia32.ssse3 = false; + int sse = 0; + size_t len; + /* at least one of these must work: */ + len = sizeof(sse); sse = sse || (sysctlbyname("hw.instruction_sse", &sse, &len, NULL, 0) == 0 && sse); + len = sizeof(sse); sse = sse || (sysctlbyname("hw.optional.sse" , &sse, &len, NULL, 0) == 0 && sse); /* __APPLE__ ? */ + if(!sse) + disable_sse(info); #elif defined(__NetBSD__) || defined (__OpenBSD__) # if __NetBSD_Version__ >= 105250000 || (defined __OpenBSD__) - int val = 0, mib[2] = { CTL_MACHDEP, CPU_SSE }; - size_t len = sizeof(val); - if(sysctl(mib, 2, &val, &len, NULL, 0) < 0 || !val) - info->data.ia32.fxsr = info->data.ia32.sse = info->data.ia32.sse2 = info->data.ia32.sse3 = info->data.ia32.ssse3 = false; - else { /* double-check SSE2 */ - mib[1] = CPU_SSE2; - len = sizeof(val); - if(sysctl(mib, 2, &val, &len, NULL, 0) < 0 || !val) - info->data.ia32.sse2 = info->data.ia32.sse3 = info->data.ia32.ssse3 = false; + int val = 0, mib[2] = { CTL_MACHDEP, CPU_SSE }; + size_t len = sizeof(val); + if(sysctl(mib, 2, &val, &len, NULL, 0) < 0 || !val) + disable_sse(info); + else { /* double-check SSE2 */ + mib[1] = CPU_SSE2; + len = sizeof(val); + if(sysctl(mib, 2, &val, &len, NULL, 0) < 0 || !val) { + disable_sse(info); + info->ia32.sse = true; } + } # else - info->data.ia32.fxsr = info->data.ia32.sse = info->data.ia32.sse2 = info->data.ia32.sse3 = info->data.ia32.ssse3 = false; + disable_sse(info); # endif #elif defined(__linux__) - int sse = 0; - struct sigaction sigill_save; -#ifdef USE_OBSOLETE_SIGCONTEXT_FLAVOR - if(0 == sigaction(SIGILL, NULL, &sigill_save) && signal(SIGILL, (void (*)(int))sigill_handler_sse_os) != SIG_ERR) -#else - struct sigaction sigill_sse; - sigill_sse.sa_sigaction = sigill_handler_sse_os; - __sigemptyset(&sigill_sse.sa_mask); - sigill_sse.sa_flags = SA_SIGINFO | SA_RESETHAND; /* SA_RESETHAND just in case our SIGILL return jump breaks, so we don't get stuck in a loop */ - if(0 == sigaction(SIGILL, &sigill_sse, &sigill_save)) -#endif - { - /* http://www.ibiblio.org/gferg/ldp/GCC-Inline-Assembly-HOWTO.html */ - /* see sigill_handler_sse_os() for an explanation of the following: */ - asm volatile ( - "xorl %0,%0\n\t" /* for some reason, still need to do this to clear 'sse' var */ - "xorps %%xmm0,%%xmm0\n\t" /* will cause SIGILL if unsupported by OS */ - "incl %0\n\t" /* SIGILL handler will jump over this */ - /* landing zone */ - "nop\n\t" /* SIGILL jump lands here if "inc" is 9 bytes */ - "nop\n\t" - "nop\n\t" - "nop\n\t" - "nop\n\t" - "nop\n\t" - "nop\n\t" /* SIGILL jump lands here if "inc" is 3 bytes (expected) */ - "nop\n\t" - "nop" /* SIGILL jump lands here if "inc" is 1 byte */ - : "=r"(sse) - : "r"(sse) - ); - - sigaction(SIGILL, &sigill_save, NULL); - } - - if(!sse) - info->data.ia32.fxsr = info->data.ia32.sse = info->data.ia32.sse2 = info->data.ia32.sse3 = info->data.ia32.ssse3 = false; -#elif defined(_MSC_VER) -# ifdef USE_TRY_CATCH_FLAVOR - _try { - __asm { -# if _MSC_VER <= 1200 - /* VC6 assembler doesn't know SSE, have to emit bytecode instead */ - _emit 0x0F - _emit 0x57 - _emit 0xC0 -# else - xorps xmm0,xmm0 -# endif - } - } - _except(EXCEPTION_EXECUTE_HANDLER) { - if (_exception_code() == STATUS_ILLEGAL_INSTRUCTION) - info->data.ia32.fxsr = info->data.ia32.sse = info->data.ia32.sse2 = info->data.ia32.sse3 = info->data.ia32.ssse3 = false; - } -# else - int sse = 0; - LPTOP_LEVEL_EXCEPTION_FILTER save = SetUnhandledExceptionFilter(sigill_handler_sse_os); - /* see GCC version above for explanation */ - /* http://msdn2.microsoft.com/en-us/library/4ks26t93.aspx */ - /* http://www.codeproject.com/cpp/gccasm.asp */ - /* http://www.hick.org/~mmiller/msvc_inline_asm.html */ - __asm { -# if _MSC_VER <= 1200 - /* VC6 assembler doesn't know SSE, have to emit bytecode instead */ - _emit 0x0F - _emit 0x57 - _emit 0xC0 -# else - xorps xmm0,xmm0 -# endif - inc sse - nop - nop - nop - nop - nop - nop - nop - nop - nop - } - SetUnhandledExceptionFilter(save); - if(!sse) - info->data.ia32.fxsr = info->data.ia32.sse = info->data.ia32.sse2 = info->data.ia32.sse3 = info->data.ia32.ssse3 = false; -# endif -#else - /* no way to test, disable to be safe */ - info->data.ia32.fxsr = info->data.ia32.sse = info->data.ia32.sse2 = info->data.ia32.sse3 = info->data.ia32.ssse3 = false; -#endif -#ifdef DEBUG - fprintf(stderr, " SSE OS sup . %c\n", info->data.ia32.sse ? 'Y' : 'n'); -#endif - - } - } -#else - info->use_asm = false; -#endif - -/* - * PPC-specific - */ -#elif defined FLAC__CPU_PPC - info->type = FLAC__CPUINFO_TYPE_PPC; -# if !defined FLAC__NO_ASM - info->use_asm = true; -# ifdef FLAC__USE_ALTIVEC -# if defined FLAC__SYS_DARWIN - { - int val = 0, mib[2] = { CTL_HW, HW_VECTORUNIT }; - size_t len = sizeof(val); - info->data.ppc.altivec = !(sysctl(mib, 2, &val, &len, NULL, 0) || !val); - } - { - host_basic_info_data_t hostInfo; - mach_msg_type_number_t infoCount; - - infoCount = HOST_BASIC_INFO_COUNT; - host_info(mach_host_self(), HOST_BASIC_INFO, (host_info_t)&hostInfo, &infoCount); - - info->data.ppc.ppc64 = (hostInfo.cpu_type == CPU_TYPE_POWERPC) && (hostInfo.cpu_subtype == CPU_SUBTYPE_POWERPC_970); - } -# else /* FLAC__USE_ALTIVEC && !FLAC__SYS_DARWIN */ - { - /* no Darwin, do it the brute-force way */ - /* @@@@@@ this is not thread-safe; replace with SSE OS method above or remove */ - info->data.ppc.altivec = 0; - info->data.ppc.ppc64 = 0; - - signal (SIGILL, sigill_handler); - canjump = 0; - if (!sigsetjmp (jmpbuf, 1)) { - canjump = 1; - + int sse = 0; + struct sigaction sigill_save; + struct sigaction sigill_sse; + sigill_sse.sa_sigaction = sigill_handler_sse_os; + __sigemptyset(&sigill_sse.sa_mask); + sigill_sse.sa_flags = SA_SIGINFO | SA_RESETHAND; /* SA_RESETHAND just in case our SIGILL return jump breaks, so we don't get stuck in a loop */ + if(0 == sigaction(SIGILL, &sigill_sse, &sigill_save)) + { + /* http://www.ibiblio.org/gferg/ldp/GCC-Inline-Assembly-HOWTO.html */ + /* see sigill_handler_sse_os() for an explanation of the following: */ asm volatile ( - "mtspr 256, %0\n\t" - "vand %%v0, %%v0, %%v0" - : - : "r" (-1) + "xorps %%xmm0,%%xmm0\n\t" /* will cause SIGILL if unsupported by OS */ + "incl %0\n\t" /* SIGILL handler will jump over this */ + /* landing zone */ + "nop\n\t" /* SIGILL jump lands here if "inc" is 9 bytes */ + "nop\n\t" + "nop\n\t" + "nop\n\t" + "nop\n\t" + "nop\n\t" + "nop\n\t" /* SIGILL jump lands here if "inc" is 3 bytes (expected) */ + "nop\n\t" + "nop" /* SIGILL jump lands here if "inc" is 1 byte */ + : "=r"(sse) + : "0"(sse) ); - info->data.ppc.altivec = 1; + sigaction(SIGILL, &sigill_save, NULL); } - canjump = 0; - if (!sigsetjmp (jmpbuf, 1)) { - int x = 0; - canjump = 1; - /* PPC64 hardware implements the cntlzd instruction */ - asm volatile ("cntlzd %0, %1" : "=r" (x) : "r" (x) ); - - info->data.ppc.ppc64 = 1; + if(!sse) + disable_sse(info); +#elif defined(_MSC_VER) + __try { + __asm { + xorps xmm0,xmm0 + } } - signal (SIGILL, SIG_DFL); /*@@@@@@ should save and restore old signal */ + __except(EXCEPTION_EXECUTE_HANDLER) { + if (_exception_code() == STATUS_ILLEGAL_INSTRUCTION) + disable_sse(info); + } +#elif defined(__GNUC__) /* MinGW goes here */ + int sse = 0; + /* Based on the idea described in Agner Fog's manual "Optimizing subroutines in assembly language" */ + /* In theory, not guaranteed to detect lack of OS SSE support on some future Intel CPUs, but in practice works (see the aforementioned manual) */ + if (ia32_fxsr) { + struct { + FLAC__uint32 buff[128]; + } __attribute__((aligned(16))) fxsr; + FLAC__uint32 old_val, new_val; + + asm volatile ("fxsave %0" : "=m" (fxsr) : "m" (fxsr)); + old_val = fxsr.buff[50]; + fxsr.buff[50] ^= 0x0013c0de; /* change value in the buffer */ + asm volatile ("fxrstor %0" : "=m" (fxsr) : "m" (fxsr)); /* try to change SSE register */ + fxsr.buff[50] = old_val; /* restore old value in the buffer */ + asm volatile ("fxsave %0 " : "=m" (fxsr) : "m" (fxsr)); /* old value will be overwritten if SSE register was changed */ + new_val = fxsr.buff[50]; /* == old_val if FXRSTOR didn't change SSE register and (old_val ^ 0x0013c0de) otherwise */ + fxsr.buff[50] = old_val; /* again restore old value in the buffer */ + asm volatile ("fxrstor %0" : "=m" (fxsr) : "m" (fxsr)); /* restore old values of registers */ + + if ((old_val^new_val) == 0x0013c0de) + sse = 1; + } + if(!sse) + disable_sse(info); +#else + /* no way to test, disable to be safe */ + disable_sse(info); +#endif +#ifdef DEBUG + fprintf(stderr, " SSE OS sup . %c\n", info->ia32.sse ? 'Y' : 'n'); +#endif } -# endif -# else /* !FLAC__USE_ALTIVEC */ - info->data.ppc.altivec = 0; - info->data.ppc.ppc64 = 0; -# endif -# else + else /* info->ia32.sse == false */ + disable_sse(info); + + /* + * now have to check for OS support of AVX instructions + */ + if(info->ia32.avx && ia32_osxsave) { + FLAC__uint32 ecr = FLAC__cpu_xgetbv_x86(); + if ((ecr & 0x6) != 0x6) + disable_avx(info); +#ifdef DEBUG + fprintf(stderr, " AVX OS sup . %c\n", info->ia32.avx ? 'Y' : 'n'); +#endif + } + else /* no OS AVX support*/ + disable_avx(info); +#else info->use_asm = false; -# endif +#endif /* - * unknown CPI + * x86-64-specific + */ +#elif defined FLAC__CPU_X86_64 + FLAC__bool x86_osxsave = false; + (void) x86_osxsave; /* to avoid warnings about unused variables */ + memset(info, 0, sizeof(*info)); + info->type = FLAC__CPUINFO_TYPE_X86_64; +#if !defined FLAC__NO_ASM && defined FLAC__HAS_X86INTRIN + info->use_asm = true; + { + /* http://www.sandpile.org/x86/cpuid.htm */ + FLAC__uint32 flags_eax, flags_ebx, flags_ecx, flags_edx; + FLAC__cpu_info_x86(1, &flags_eax, &flags_ebx, &flags_ecx, &flags_edx); + info->x86.sse3 = (flags_ecx & FLAC__CPUINFO_IA32_CPUID_SSE3 )? true : false; + info->x86.ssse3 = (flags_ecx & FLAC__CPUINFO_IA32_CPUID_SSSE3)? true : false; + info->x86.sse41 = (flags_ecx & FLAC__CPUINFO_IA32_CPUID_SSE41)? true : false; + info->x86.sse42 = (flags_ecx & FLAC__CPUINFO_IA32_CPUID_SSE42)? true : false; +#if defined FLAC__AVX_SUPPORTED + x86_osxsave = (flags_ecx & FLAC__CPUINFO_IA32_CPUID_OSXSAVE)? true : false; + info->x86.avx = (flags_ecx & FLAC__CPUINFO_IA32_CPUID_AVX )? true : false; + info->x86.fma = (flags_ecx & FLAC__CPUINFO_IA32_CPUID_FMA )? true : false; + FLAC__cpu_info_x86(7, &flags_eax, &flags_ebx, &flags_ecx, &flags_edx); + info->x86.avx2 = (flags_ebx & FLAC__CPUINFO_IA32_CPUID_AVX2 )? true : false; +#endif + } +#ifdef DEBUG + fprintf(stderr, "CPU info (x86-64):\n"); + fprintf(stderr, " SSE3 ....... %c\n", info->x86.sse3 ? 'Y' : 'n'); + fprintf(stderr, " SSSE3 ...... %c\n", info->x86.ssse3 ? 'Y' : 'n'); + fprintf(stderr, " SSE41 ...... %c\n", info->x86.sse41 ? 'Y' : 'n'); + fprintf(stderr, " SSE42 ...... %c\n", info->x86.sse42 ? 'Y' : 'n'); +# if defined FLAC__AVX_SUPPORTED + fprintf(stderr, " AVX ........ %c\n", info->x86.avx ? 'Y' : 'n'); + fprintf(stderr, " FMA ........ %c\n", info->x86.fma ? 'Y' : 'n'); + fprintf(stderr, " AVX2 ....... %c\n", info->x86.avx2 ? 'Y' : 'n'); +# endif +#endif + + /* + * now have to check for OS support of AVX instructions + */ + if(info->x86.avx && x86_osxsave) { + FLAC__uint32 ecr = FLAC__cpu_xgetbv_x86(); + if ((ecr & 0x6) != 0x6) + disable_avx(info); +#ifdef DEBUG + fprintf(stderr, " AVX OS sup . %c\n", info->x86.avx ? 'Y' : 'n'); +#endif + } + else /* no OS AVX support*/ + disable_avx(info); +#else + info->use_asm = false; +#endif + +/* + * unknown CPU */ #else info->type = FLAC__CPUINFO_TYPE_UNKNOWN; info->use_asm = false; #endif } + +#if (defined FLAC__CPU_IA32 || defined FLAC__CPU_X86_64) && defined FLAC__HAS_X86INTRIN + +#if defined _MSC_VER +#include /* for __cpuid() and _xgetbv() */ +#elif defined __GNUC__ && defined HAVE_CPUID_H +#include /* for __get_cpuid() and __get_cpuid_max() */ +#endif + +FLAC__uint32 FLAC__cpu_have_cpuid_x86(void) +{ +#ifdef FLAC__CPU_X86_64 + return 1; +#else +# if defined _MSC_VER || defined __INTEL_COMPILER /* Do they support CPUs w/o CPUID support (or OSes that work on those CPUs)? */ + FLAC__uint32 flags1, flags2; + __asm { + pushfd + pushfd + pop eax + mov flags1, eax + xor eax, 0x200000 + push eax + popfd + pushfd + pop eax + mov flags2, eax + popfd + } + if (((flags1^flags2) & 0x200000) != 0) + return 1; + else + return 0; +# elif defined __GNUC__ && defined HAVE_CPUID_H + if (__get_cpuid_max(0, 0) != 0) + return 1; + else + return 0; +# else + return 0; +# endif +#endif +} + +void FLAC__cpu_info_x86(FLAC__uint32 level, FLAC__uint32 *eax, FLAC__uint32 *ebx, FLAC__uint32 *ecx, FLAC__uint32 *edx) +{ + (void) level; + +#if defined _MSC_VER || defined __INTEL_COMPILER + int cpuinfo[4]; + int ext = level & 0x80000000; + __cpuid(cpuinfo, ext); + if((unsigned)cpuinfo[0] < level) { + *eax = *ebx = *ecx = *edx = 0; + return; + } +#if defined FLAC__AVX_SUPPORTED + __cpuidex(cpuinfo, level, 0); /* for AVX2 detection */ +#else + __cpuid(cpuinfo, level); /* some old compilers don't support __cpuidex */ +#endif + *eax = cpuinfo[0]; *ebx = cpuinfo[1]; *ecx = cpuinfo[2]; *edx = cpuinfo[3]; +#elif defined __GNUC__ && defined HAVE_CPUID_H + FLAC__uint32 ext = level & 0x80000000; + __cpuid(ext, *eax, *ebx, *ecx, *edx); + if (*eax < level) { + *eax = *ebx = *ecx = *edx = 0; + return; + } + __cpuid_count(level, 0, *eax, *ebx, *ecx, *edx); +#else + *eax = *ebx = *ecx = *edx = 0; +#endif +} + +FLAC__uint32 FLAC__cpu_xgetbv_x86(void) +{ +#if (defined _MSC_VER || defined __INTEL_COMPILER) && defined FLAC__AVX_SUPPORTED + return (FLAC__uint32)_xgetbv(0); +#elif defined __GNUC__ + FLAC__uint32 lo, hi; + asm volatile (".byte 0x0f, 0x01, 0xd0" : "=a"(lo), "=d"(hi) : "c" (0)); + return lo; +#else + return 0; +#endif +} + +#endif /* (FLAC__CPU_IA32 || FLAC__CPU_X86_64) && FLAC__HAS_X86INTRIN */ diff --git a/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/crc.c b/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/crc.c index 225b26d..f58e7be 100644 --- a/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/crc.c +++ b/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/crc.c @@ -1,6 +1,6 @@ /* libFLAC - Free Lossless Audio Codec library * Copyright (C) 2000-2009 Josh Coalson - * Copyright (C) 2011-2013 Xiph.Org Foundation + * Copyright (C) 2011-2014 Xiph.Org Foundation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -30,7 +30,7 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#if HAVE_CONFIG_H +#ifdef HAVE_CONFIG_H # include #endif diff --git a/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/fixed.c b/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/fixed.c index f8ebeda..78a9ec0 100644 --- a/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/fixed.c +++ b/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/fixed.c @@ -1,6 +1,6 @@ /* libFLAC - Free Lossless Audio Codec library * Copyright (C) 2000-2009 Josh Coalson - * Copyright (C) 2011-2013 Xiph.Org Foundation + * Copyright (C) 2011-2014 Xiph.Org Foundation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -30,21 +30,17 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#if HAVE_CONFIG_H +#ifdef HAVE_CONFIG_H # include #endif #include #include +#include "../compat.h" #include "include/private/bitmath.h" #include "include/private/fixed.h" #include "../assert.h" -#ifndef M_LN2 -/* math.h in VC++ doesn't seem to have this (how Microsoft is that?) */ -#define M_LN2 0.69314718055994530942 -#endif - #ifdef local_abs #undef local_abs #endif @@ -320,20 +316,11 @@ unsigned FLAC__fixed_compute_best_predictor_wide(const FLAC__int32 data[], unsig FLAC__ASSERT(data_len > 0 || total_error_3 == 0); FLAC__ASSERT(data_len > 0 || total_error_4 == 0); #ifndef FLAC__INTEGER_ONLY_LIBRARY -#if defined _MSC_VER || defined __MINGW32__ - /* with MSVC you have to spoon feed it the casting */ - residual_bits_per_sample[0] = (FLAC__float)((total_error_0 > 0) ? log(M_LN2 * (FLAC__double)(FLAC__int64)total_error_0 / (FLAC__double)data_len) / M_LN2 : 0.0); - residual_bits_per_sample[1] = (FLAC__float)((total_error_1 > 0) ? log(M_LN2 * (FLAC__double)(FLAC__int64)total_error_1 / (FLAC__double)data_len) / M_LN2 : 0.0); - residual_bits_per_sample[2] = (FLAC__float)((total_error_2 > 0) ? log(M_LN2 * (FLAC__double)(FLAC__int64)total_error_2 / (FLAC__double)data_len) / M_LN2 : 0.0); - residual_bits_per_sample[3] = (FLAC__float)((total_error_3 > 0) ? log(M_LN2 * (FLAC__double)(FLAC__int64)total_error_3 / (FLAC__double)data_len) / M_LN2 : 0.0); - residual_bits_per_sample[4] = (FLAC__float)((total_error_4 > 0) ? log(M_LN2 * (FLAC__double)(FLAC__int64)total_error_4 / (FLAC__double)data_len) / M_LN2 : 0.0); -#else residual_bits_per_sample[0] = (FLAC__float)((total_error_0 > 0) ? log(M_LN2 * (FLAC__double)total_error_0 / (FLAC__double)data_len) / M_LN2 : 0.0); residual_bits_per_sample[1] = (FLAC__float)((total_error_1 > 0) ? log(M_LN2 * (FLAC__double)total_error_1 / (FLAC__double)data_len) / M_LN2 : 0.0); residual_bits_per_sample[2] = (FLAC__float)((total_error_2 > 0) ? log(M_LN2 * (FLAC__double)total_error_2 / (FLAC__double)data_len) / M_LN2 : 0.0); residual_bits_per_sample[3] = (FLAC__float)((total_error_3 > 0) ? log(M_LN2 * (FLAC__double)total_error_3 / (FLAC__double)data_len) / M_LN2 : 0.0); residual_bits_per_sample[4] = (FLAC__float)((total_error_4 > 0) ? log(M_LN2 * (FLAC__double)total_error_4 / (FLAC__double)data_len) / M_LN2 : 0.0); -#endif #else residual_bits_per_sample[0] = (total_error_0 > 0) ? local__compute_rbps_wide_integerized(total_error_0, data_len) : 0; residual_bits_per_sample[1] = (total_error_1 > 0) ? local__compute_rbps_wide_integerized(total_error_1, data_len) : 0; diff --git a/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/float.c b/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/float.c index ae10407..1c16a2b 100644 --- a/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/float.c +++ b/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/float.c @@ -1,6 +1,6 @@ /* libFLAC - Free Lossless Audio Codec library * Copyright (C) 2004-2009 Josh Coalson - * Copyright (C) 2011-2013 Xiph.Org Foundation + * Copyright (C) 2011-2014 Xiph.Org Foundation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -30,7 +30,7 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#if HAVE_CONFIG_H +#ifdef HAVE_CONFIG_H # include #endif diff --git a/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/format.c b/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/format.c index 1f37de9..eb8f56f 100644 --- a/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/format.c +++ b/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/format.c @@ -1,6 +1,6 @@ /* libFLAC - Free Lossless Audio Codec library * Copyright (C) 2000-2009 Josh Coalson - * Copyright (C) 2011-2013 Xiph.Org Foundation + * Copyright (C) 2011-2014 Xiph.Org Foundation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -30,7 +30,7 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#if HAVE_CONFIG_H +#ifdef HAVE_CONFIG_H # include #endif @@ -45,12 +45,7 @@ /* VERSION should come from configure */ FLAC_API const char *FLAC__VERSION_STRING = VERSION; -#if defined _MSC_VER || defined __BORLANDC__ || defined __MINW32__ -/* yet one more hack because of MSVC6: */ -FLAC_API const char *FLAC__VENDOR_STRING = "reference libFLAC 1.3.0 20130526"; -#else -FLAC_API const char *FLAC__VENDOR_STRING = "reference libFLAC " VERSION " 20130526"; -#endif +FLAC_API const char *FLAC__VENDOR_STRING = "reference libFLAC " VERSION " 20141125"; FLAC_API const FLAC__byte FLAC__STREAM_SYNC_STRING[4] = { 'f','L','a','C' }; FLAC_API const unsigned FLAC__STREAM_SYNC = 0x664C6143; diff --git a/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/include/private/all.h b/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/include/private/all.h index 2925309..a526071 100644 --- a/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/include/private/all.h +++ b/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/include/private/all.h @@ -1,6 +1,6 @@ /* libFLAC - Free Lossless Audio Codec library * Copyright (C) 2000-2009 Josh Coalson - * Copyright (C) 2011-2013 Xiph.Org Foundation + * Copyright (C) 2011-2014 Xiph.Org Foundation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/include/private/bitmath.h b/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/include/private/bitmath.h index 371bd48..9ca9ec3 100644 --- a/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/include/private/bitmath.h +++ b/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/include/private/bitmath.h @@ -1,6 +1,6 @@ /* libFLAC - Free Lossless Audio Codec library * Copyright (C) 2001-2009 Josh Coalson - * Copyright (C) 2011-2013 Xiph.Org Foundation + * Copyright (C) 2011-2014 Xiph.Org Foundation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -34,6 +34,7 @@ #define FLAC__PRIVATE__BITMATH_H #include "../../../ordinals.h" +#include "../../../assert.h" /* for CHAR_BIT */ #include @@ -74,16 +75,19 @@ static inline unsigned int FLAC__clz_soft_uint32(unsigned int word) static inline unsigned int FLAC__clz_uint32(FLAC__uint32 v) { /* Never used with input 0 */ + FLAC__ASSERT(v > 0); #if defined(__INTEL_COMPILER) return _bit_scan_reverse(v) ^ 31U; #elif defined(__GNUC__) && (__GNUC__ >= 4 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)) /* This will translate either to (bsr ^ 31U), clz , ctlz, cntlz, lzcnt depending on - * -march= setting or to a software rutine in exotic machines. */ + * -march= setting or to a software routine in exotic machines. */ return __builtin_clz(v); #elif defined(_MSC_VER) && (_MSC_VER >= 1400) - FLAC__uint32 idx; - _BitScanReverse((DWORD*) &idx, v); - return idx ^ 31U; + { + unsigned long idx; + _BitScanReverse(&idx, v); + return idx ^ 31U; + } #else return FLAC__clz_soft_uint32(v); #endif @@ -99,7 +103,7 @@ static inline unsigned int FLAC__clz2_uint32(FLAC__uint32 v) /* An example of what FLAC__bitmath_ilog2() computes: * - * ilog2( 0) = undefined + * ilog2( 0) = assertion failure * ilog2( 1) = 0 * ilog2( 2) = 1 * ilog2( 3) = 1 @@ -122,45 +126,56 @@ static inline unsigned int FLAC__clz2_uint32(FLAC__uint32 v) static inline unsigned FLAC__bitmath_ilog2(FLAC__uint32 v) { + FLAC__ASSERT(v > 0); +#if defined(__INTEL_COMPILER) + return _bit_scan_reverse(v); +#elif defined(_MSC_VER) && (_MSC_VER >= 1400) + { + unsigned long idx; + _BitScanReverse(&idx, v); + return idx; + } +#else return sizeof(FLAC__uint32) * CHAR_BIT - 1 - FLAC__clz_uint32(v); +#endif } -#ifdef FLAC__INTEGER_ONLY_LIBRARY /*Unused otherwise */ +#ifdef FLAC__INTEGER_ONLY_LIBRARY /* Unused otherwise */ static inline unsigned FLAC__bitmath_ilog2_wide(FLAC__uint64 v) { - if (v == 0) - return 0; + FLAC__ASSERT(v > 0); #if defined(__GNUC__) && (__GNUC__ >= 4 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)) return sizeof(FLAC__uint64) * CHAR_BIT - 1 - __builtin_clzll(v); -/* Sorry, only supported in win64/Itanium.. */ -#elif (defined(_MSC_VER) && (_MSC_VER >= 1400)) && (defined(_M_IA64) || defined(_WIN64)) - FLAC__uint64 idx; - _BitScanReverse64(&idx, v); - return idx ^ 63U; +/* Sorry, only supported in x64/Itanium.. and both have fast FPU which makes integer-only encoder pointless */ +#elif (defined(_MSC_VER) && (_MSC_VER >= 1400)) && (defined(_M_IA64) || defined(_M_X64)) + { + unsigned long idx; + _BitScanReverse64(&idx, v); + return idx; + } #else -/* Brain-damaged compilers will use the fastest possible way that is, +/* Brain-damaged compilers will use the fastest possible way that is, de Bruijn sequences (http://supertech.csail.mit.edu/papers/debruijn.pdf) - (C) Timothy B. Terriberry (tterribe@xiph.org) 2001-2009 LGPL (v2 or later). + (C) Timothy B. Terriberry (tterribe@xiph.org) 2001-2009 CC0 (Public domain). */ - static const unsigned char DEBRUIJN_IDX64[64]={ - 0, 1, 2, 7, 3,13, 8,19, 4,25,14,28, 9,34,20,40, - 5,17,26,38,15,46,29,48,10,31,35,54,21,50,41,57, - 63, 6,12,18,24,27,33,39,16,37,45,47,30,53,49,56, - 62,11,23,32,36,44,52,55,61,22,43,51,60,42,59,58 - }; - int ret; - ret= v>0; - v|= v>>1; - v|= v>>2; - v|= v>>4; - v|= v>>8; - v|= v>>16; - v|= v>>32; - v= (v>>1)+1; - ret+=DEBRUIJN_IDX64[v*0x218A392CD3D5DBF>>58&0x3F]; - return ret; + { + static const unsigned char DEBRUIJN_IDX64[64]={ + 0, 1, 2, 7, 3,13, 8,19, 4,25,14,28, 9,34,20,40, + 5,17,26,38,15,46,29,48,10,31,35,54,21,50,41,57, + 63, 6,12,18,24,27,33,39,16,37,45,47,30,53,49,56, + 62,11,23,32,36,44,52,55,61,22,43,51,60,42,59,58 + }; + v|= v>>1; + v|= v>>2; + v|= v>>4; + v|= v>>8; + v|= v>>16; + v|= v>>32; + v= (v>>1)+1; + return DEBRUIJN_IDX64[v*0x218A392CD3D5DBF>>58&0x3F]; + } #endif } #endif diff --git a/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/include/private/bitreader.h b/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/include/private/bitreader.h index 4d9668f..83f8361 100644 --- a/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/include/private/bitreader.h +++ b/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/include/private/bitreader.h @@ -1,6 +1,6 @@ /* libFLAC - Free Lossless Audio Codec library * Copyright (C) 2000-2009 Josh Coalson - * Copyright (C) 2011-2013 Xiph.Org Foundation + * Copyright (C) 2011-2014 Xiph.Org Foundation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -50,7 +50,7 @@ typedef FLAC__bool (*FLAC__BitReaderReadCallback)(FLAC__byte buffer[], size_t *b */ FLAC__BitReader *FLAC__bitreader_new(void); void FLAC__bitreader_delete(FLAC__BitReader *br); -FLAC__bool FLAC__bitreader_init(FLAC__BitReader *br, FLAC__CPUInfo cpu, FLAC__BitReaderReadCallback rcb, void *cd); +FLAC__bool FLAC__bitreader_init(FLAC__BitReader *br, FLAC__BitReaderReadCallback rcb, void *cd); void FLAC__bitreader_free(FLAC__BitReader *br); /* does not 'free(br)' */ FLAC__bool FLAC__bitreader_clear(FLAC__BitReader *br); void FLAC__bitreader_dump(const FLAC__BitReader *br, FILE *out); @@ -82,19 +82,10 @@ FLAC__bool FLAC__bitreader_read_byte_block_aligned_no_crc(FLAC__BitReader *br, F FLAC__bool FLAC__bitreader_read_unary_unsigned(FLAC__BitReader *br, unsigned *val); FLAC__bool FLAC__bitreader_read_rice_signed(FLAC__BitReader *br, int *val, unsigned parameter); FLAC__bool FLAC__bitreader_read_rice_signed_block(FLAC__BitReader *br, int vals[], unsigned nvals, unsigned parameter); -#ifndef FLAC__NO_ASM -# ifdef FLAC__CPU_IA32 -# ifdef FLAC__HAS_NASM -FLAC__bool FLAC__bitreader_read_rice_signed_block_asm_ia32_bswap(FLAC__BitReader *br, int vals[], unsigned nvals, unsigned parameter); -# endif -# endif -#endif #if 0 /* UNUSED */ FLAC__bool FLAC__bitreader_read_golomb_signed(FLAC__BitReader *br, int *val, unsigned parameter); FLAC__bool FLAC__bitreader_read_golomb_unsigned(FLAC__BitReader *br, unsigned *val, unsigned parameter); #endif FLAC__bool FLAC__bitreader_read_utf8_uint32(FLAC__BitReader *br, FLAC__uint32 *val, FLAC__byte *raw, unsigned *rawlen); FLAC__bool FLAC__bitreader_read_utf8_uint64(FLAC__BitReader *br, FLAC__uint64 *val, FLAC__byte *raw, unsigned *rawlen); - -FLAC__bool bitreader_read_from_client_(FLAC__BitReader *br); #endif diff --git a/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/include/private/bitwriter.h b/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/include/private/bitwriter.h index b1ff5e6..1e23efe 100644 --- a/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/include/private/bitwriter.h +++ b/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/include/private/bitwriter.h @@ -1,6 +1,6 @@ /* libFLAC - Free Lossless Audio Codec library * Copyright (C) 2000-2009 Josh Coalson - * Copyright (C) 2011-2013 Xiph.Org Foundation + * Copyright (C) 2011-2014 Xiph.Org Foundation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/include/private/cpu.h b/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/include/private/cpu.h index 930d678..655800e 100644 --- a/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/include/private/cpu.h +++ b/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/include/private/cpu.h @@ -1,6 +1,6 @@ /* libFLAC - Free Lossless Audio Codec library * Copyright (C) 2001-2009 Josh Coalson - * Copyright (C) 2011-2013 Xiph.Org Foundation + * Copyright (C) 2011-2014 Xiph.Org Foundation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -41,49 +41,59 @@ typedef enum { FLAC__CPUINFO_TYPE_IA32, - FLAC__CPUINFO_TYPE_PPC, + FLAC__CPUINFO_TYPE_X86_64, FLAC__CPUINFO_TYPE_UNKNOWN } FLAC__CPUInfo_Type; +#if defined FLAC__CPU_IA32 typedef struct { - FLAC__bool cpuid; - FLAC__bool bswap; FLAC__bool cmov; FLAC__bool mmx; - FLAC__bool fxsr; FLAC__bool sse; FLAC__bool sse2; + FLAC__bool sse3; FLAC__bool ssse3; - FLAC__bool _3dnow; - FLAC__bool ext3dnow; - FLAC__bool extmmx; + FLAC__bool sse41; + FLAC__bool sse42; + FLAC__bool avx; + FLAC__bool avx2; + FLAC__bool fma; } FLAC__CPUInfo_IA32; - +#elif defined FLAC__CPU_X86_64 typedef struct { - FLAC__bool altivec; - FLAC__bool ppc64; -} FLAC__CPUInfo_PPC; + FLAC__bool sse3; + FLAC__bool ssse3; + FLAC__bool sse41; + FLAC__bool sse42; + FLAC__bool avx; + FLAC__bool avx2; + FLAC__bool fma; +} FLAC__CPUInfo_x86; +#endif typedef struct { FLAC__bool use_asm; FLAC__CPUInfo_Type type; - union { - FLAC__CPUInfo_IA32 ia32; - FLAC__CPUInfo_PPC ppc; - } data; +#if defined FLAC__CPU_IA32 + FLAC__CPUInfo_IA32 ia32; +#elif defined FLAC__CPU_X86_64 + FLAC__CPUInfo_x86 x86; +#endif } FLAC__CPUInfo; void FLAC__cpu_info(FLAC__CPUInfo *info); #ifndef FLAC__NO_ASM -#ifdef FLAC__CPU_IA32 -#ifdef FLAC__HAS_NASM +# if defined FLAC__CPU_IA32 && defined FLAC__HAS_NASM FLAC__uint32 FLAC__cpu_have_cpuid_asm_ia32(void); void FLAC__cpu_info_asm_ia32(FLAC__uint32 *flags_edx, FLAC__uint32 *flags_ecx); -FLAC__uint32 FLAC__cpu_info_extended_amd_asm_ia32(void); -#endif -#endif +# endif +# if (defined FLAC__CPU_IA32 || defined FLAC__CPU_X86_64) && defined FLAC__HAS_X86INTRIN +FLAC__uint32 FLAC__cpu_have_cpuid_x86(void); +void FLAC__cpu_info_x86(FLAC__uint32 level, FLAC__uint32 *eax, FLAC__uint32 *ebx, FLAC__uint32 *ecx, FLAC__uint32 *edx); +FLAC__uint32 FLAC__cpu_xgetbv_x86(void); +# endif #endif #endif diff --git a/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/include/private/crc.h b/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/include/private/crc.h index 6284783..8ebe5c8 100644 --- a/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/include/private/crc.h +++ b/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/include/private/crc.h @@ -1,6 +1,6 @@ /* libFLAC - Free Lossless Audio Codec library * Copyright (C) 2000-2009 Josh Coalson - * Copyright (C) 2011-2013 Xiph.Org Foundation + * Copyright (C) 2011-2014 Xiph.Org Foundation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -51,7 +51,7 @@ FLAC__uint8 FLAC__crc8(const FLAC__byte *data, unsigned len); */ extern unsigned const FLAC__crc16_table[256]; -#define FLAC__CRC16_UPDATE(data, crc) (((((crc)<<8) & 0xffff) ^ FLAC__crc16_table[((crc)>>8) ^ (data)])) +#define FLAC__CRC16_UPDATE(data, crc) ((((crc)<<8) & 0xffff) ^ FLAC__crc16_table[((crc)>>8) ^ (data)]) /* this alternate may be faster on some systems/compilers */ #if 0 #define FLAC__CRC16_UPDATE(data, crc) ((((crc)<<8) ^ FLAC__crc16_table[((crc)>>8) ^ (data)]) & 0xffff) diff --git a/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/include/private/fixed.h b/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/include/private/fixed.h index 0123bed..e4c044b 100644 --- a/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/include/private/fixed.h +++ b/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/include/private/fixed.h @@ -1,6 +1,6 @@ /* libFLAC - Free Lossless Audio Codec library * Copyright (C) 2000-2009 Josh Coalson - * Copyright (C) 2011-2013 Xiph.Org Foundation + * Copyright (C) 2011-2014 Xiph.Org Foundation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -37,6 +37,7 @@ #include #endif +#include "cpu.h" #include "float.h" #include "../../../format.h" @@ -54,14 +55,22 @@ */ #ifndef FLAC__INTEGER_ONLY_LIBRARY unsigned FLAC__fixed_compute_best_predictor(const FLAC__int32 data[], unsigned data_len, FLAC__float residual_bits_per_sample[FLAC__MAX_FIXED_ORDER+1]); +unsigned FLAC__fixed_compute_best_predictor_wide(const FLAC__int32 data[], unsigned data_len, FLAC__float residual_bits_per_sample[FLAC__MAX_FIXED_ORDER+1]); # ifndef FLAC__NO_ASM -# ifdef FLAC__CPU_IA32 -# ifdef FLAC__HAS_NASM -unsigned FLAC__fixed_compute_best_predictor_asm_ia32_mmx_cmov(const FLAC__int32 data[], unsigned data_len, FLAC__float residual_bits_per_sample[FLAC__MAX_FIXED_ORDER+1]); +# if (defined FLAC__CPU_IA32 || defined FLAC__CPU_X86_64) && defined FLAC__HAS_X86INTRIN +# ifdef FLAC__SSE2_SUPPORTED +unsigned FLAC__fixed_compute_best_predictor_intrin_sse2(const FLAC__int32 data[], unsigned data_len, FLAC__float residual_bits_per_sample[FLAC__MAX_FIXED_ORDER + 1]); +unsigned FLAC__fixed_compute_best_predictor_wide_intrin_sse2(const FLAC__int32 data[], unsigned data_len, FLAC__float residual_bits_per_sample[FLAC__MAX_FIXED_ORDER + 1]); +# endif +# ifdef FLAC__SSSE3_SUPPORTED +unsigned FLAC__fixed_compute_best_predictor_intrin_ssse3(const FLAC__int32 data[], unsigned data_len, FLAC__float residual_bits_per_sample[FLAC__MAX_FIXED_ORDER+1]); +unsigned FLAC__fixed_compute_best_predictor_wide_intrin_ssse3(const FLAC__int32 data[], unsigned data_len, FLAC__float residual_bits_per_sample[FLAC__MAX_FIXED_ORDER + 1]); # endif # endif +# if defined FLAC__CPU_IA32 && defined FLAC__HAS_NASM +unsigned FLAC__fixed_compute_best_predictor_asm_ia32_mmx_cmov(const FLAC__int32 data[], unsigned data_len, FLAC__float residual_bits_per_sample[FLAC__MAX_FIXED_ORDER+1]); +# endif # endif -unsigned FLAC__fixed_compute_best_predictor_wide(const FLAC__int32 data[], unsigned data_len, FLAC__float residual_bits_per_sample[FLAC__MAX_FIXED_ORDER+1]); #else unsigned FLAC__fixed_compute_best_predictor(const FLAC__int32 data[], unsigned data_len, FLAC__fixedpoint residual_bits_per_sample[FLAC__MAX_FIXED_ORDER+1]); unsigned FLAC__fixed_compute_best_predictor_wide(const FLAC__int32 data[], unsigned data_len, FLAC__fixedpoint residual_bits_per_sample[FLAC__MAX_FIXED_ORDER+1]); diff --git a/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/include/private/float.h b/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/include/private/float.h index 74d17ed..af09336 100644 --- a/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/include/private/float.h +++ b/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/include/private/float.h @@ -1,6 +1,6 @@ /* libFLAC - Free Lossless Audio Codec library * Copyright (C) 2004-2009 Josh Coalson - * Copyright (C) 2011-2013 Xiph.Org Foundation + * Copyright (C) 2011-2014 Xiph.Org Foundation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/include/private/format.h b/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/include/private/format.h index 996c7e9..87fb9e1 100644 --- a/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/include/private/format.h +++ b/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/include/private/format.h @@ -1,6 +1,6 @@ /* libFLAC - Free Lossless Audio Codec library * Copyright (C) 2000-2009 Josh Coalson - * Copyright (C) 2011-2013 Xiph.Org Foundation + * Copyright (C) 2011-2014 Xiph.Org Foundation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/include/private/lpc.h b/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/include/private/lpc.h index d639e25..d97c26b 100644 --- a/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/include/private/lpc.h +++ b/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/include/private/lpc.h @@ -1,6 +1,6 @@ /* libFLAC - Free Lossless Audio Codec library * Copyright (C) 2000-2009 Josh Coalson - * Copyright (C) 2011-2013 Xiph.Org Foundation + * Copyright (C) 2011-2014 Xiph.Org Foundation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -37,6 +37,7 @@ #include #endif +#include "cpu.h" #include "float.h" #include "../../../format.h" @@ -75,7 +76,15 @@ void FLAC__lpc_compute_autocorrelation_asm_ia32(const FLAC__real data[], unsigne void FLAC__lpc_compute_autocorrelation_asm_ia32_sse_lag_4(const FLAC__real data[], unsigned data_len, unsigned lag, FLAC__real autoc[]); void FLAC__lpc_compute_autocorrelation_asm_ia32_sse_lag_8(const FLAC__real data[], unsigned data_len, unsigned lag, FLAC__real autoc[]); void FLAC__lpc_compute_autocorrelation_asm_ia32_sse_lag_12(const FLAC__real data[], unsigned data_len, unsigned lag, FLAC__real autoc[]); -void FLAC__lpc_compute_autocorrelation_asm_ia32_3dnow(const FLAC__real data[], unsigned data_len, unsigned lag, FLAC__real autoc[]); +void FLAC__lpc_compute_autocorrelation_asm_ia32_sse_lag_16(const FLAC__real data[], unsigned data_len, unsigned lag, FLAC__real autoc[]); +# endif +# endif +# if (defined FLAC__CPU_IA32 || defined FLAC__CPU_X86_64) && defined FLAC__HAS_X86INTRIN +# ifdef FLAC__SSE_SUPPORTED +void FLAC__lpc_compute_autocorrelation_intrin_sse_lag_4(const FLAC__real data[], unsigned data_len, unsigned lag, FLAC__real autoc[]); +void FLAC__lpc_compute_autocorrelation_intrin_sse_lag_8(const FLAC__real data[], unsigned data_len, unsigned lag, FLAC__real autoc[]); +void FLAC__lpc_compute_autocorrelation_intrin_sse_lag_12(const FLAC__real data[], unsigned data_len, unsigned lag, FLAC__real autoc[]); +void FLAC__lpc_compute_autocorrelation_intrin_sse_lag_16(const FLAC__real data[], unsigned data_len, unsigned lag, FLAC__real autoc[]); # endif # endif #endif @@ -145,6 +154,22 @@ void FLAC__lpc_compute_residual_from_qlp_coefficients_wide(const FLAC__int32 *da # ifdef FLAC__HAS_NASM void FLAC__lpc_compute_residual_from_qlp_coefficients_asm_ia32(const FLAC__int32 *data, unsigned data_len, const FLAC__int32 qlp_coeff[], unsigned order, int lp_quantization, FLAC__int32 residual[]); void FLAC__lpc_compute_residual_from_qlp_coefficients_asm_ia32_mmx(const FLAC__int32 *data, unsigned data_len, const FLAC__int32 qlp_coeff[], unsigned order, int lp_quantization, FLAC__int32 residual[]); +void FLAC__lpc_compute_residual_from_qlp_coefficients_wide_asm_ia32(const FLAC__int32 *data, unsigned data_len, const FLAC__int32 qlp_coeff[], unsigned order, int lp_quantization, FLAC__int32 residual[]); +# endif +# endif +# if (defined FLAC__CPU_IA32 || defined FLAC__CPU_X86_64) && defined FLAC__HAS_X86INTRIN +# ifdef FLAC__SSE2_SUPPORTED +void FLAC__lpc_compute_residual_from_qlp_coefficients_16_intrin_sse2(const FLAC__int32 *data, unsigned data_len, const FLAC__int32 qlp_coeff[], unsigned order, int lp_quantization, FLAC__int32 residual[]); +void FLAC__lpc_compute_residual_from_qlp_coefficients_intrin_sse2(const FLAC__int32 *data, unsigned data_len, const FLAC__int32 qlp_coeff[], unsigned order, int lp_quantization, FLAC__int32 residual[]); +# endif +# ifdef FLAC__SSE4_1_SUPPORTED +void FLAC__lpc_compute_residual_from_qlp_coefficients_intrin_sse41(const FLAC__int32 *data, unsigned data_len, const FLAC__int32 qlp_coeff[], unsigned order, int lp_quantization, FLAC__int32 residual[]); +void FLAC__lpc_compute_residual_from_qlp_coefficients_wide_intrin_sse41(const FLAC__int32 *data, unsigned data_len, const FLAC__int32 qlp_coeff[], unsigned order, int lp_quantization, FLAC__int32 residual[]); +# endif +# ifdef FLAC__AVX2_SUPPORTED +void FLAC__lpc_compute_residual_from_qlp_coefficients_16_intrin_avx2(const FLAC__int32 *data, unsigned data_len, const FLAC__int32 qlp_coeff[], unsigned order, int lp_quantization, FLAC__int32 residual[]); +void FLAC__lpc_compute_residual_from_qlp_coefficients_intrin_avx2(const FLAC__int32 *data, unsigned data_len, const FLAC__int32 qlp_coeff[], unsigned order, int lp_quantization, FLAC__int32 residual[]); +void FLAC__lpc_compute_residual_from_qlp_coefficients_wide_intrin_avx2(const FLAC__int32 *data, unsigned data_len, const FLAC__int32 qlp_coeff[], unsigned order, int lp_quantization, FLAC__int32 residual[]); # endif # endif #endif @@ -173,11 +198,17 @@ void FLAC__lpc_restore_signal_wide(const FLAC__int32 residual[], unsigned data_l # ifdef FLAC__HAS_NASM void FLAC__lpc_restore_signal_asm_ia32(const FLAC__int32 residual[], unsigned data_len, const FLAC__int32 qlp_coeff[], unsigned order, int lp_quantization, FLAC__int32 data[]); void FLAC__lpc_restore_signal_asm_ia32_mmx(const FLAC__int32 residual[], unsigned data_len, const FLAC__int32 qlp_coeff[], unsigned order, int lp_quantization, FLAC__int32 data[]); +void FLAC__lpc_restore_signal_wide_asm_ia32(const FLAC__int32 residual[], unsigned data_len, const FLAC__int32 qlp_coeff[], unsigned order, int lp_quantization, FLAC__int32 data[]); # endif /* FLAC__HAS_NASM */ -# elif defined FLAC__CPU_PPC -void FLAC__lpc_restore_signal_asm_ppc_altivec_16(const FLAC__int32 residual[], unsigned data_len, const FLAC__int32 qlp_coeff[], unsigned order, int lp_quantization, FLAC__int32 data[]); -void FLAC__lpc_restore_signal_asm_ppc_altivec_16_order8(const FLAC__int32 residual[], unsigned data_len, const FLAC__int32 qlp_coeff[], unsigned order, int lp_quantization, FLAC__int32 data[]); -# endif/* FLAC__CPU_IA32 || FLAC__CPU_PPC */ +# endif /* FLAC__CPU_IA32 */ +# if (defined FLAC__CPU_IA32 || defined FLAC__CPU_X86_64) && defined FLAC__HAS_X86INTRIN +# ifdef FLAC__SSE2_SUPPORTED +void FLAC__lpc_restore_signal_16_intrin_sse2(const FLAC__int32 residual[], unsigned data_len, const FLAC__int32 qlp_coeff[], unsigned order, int lp_quantization, FLAC__int32 data[]); +# endif +# ifdef FLAC__SSE4_1_SUPPORTED +void FLAC__lpc_restore_signal_wide_intrin_sse41(const FLAC__int32 residual[], unsigned data_len, const FLAC__int32 qlp_coeff[], unsigned order, int lp_quantization, FLAC__int32 data[]); +# endif +# endif #endif /* FLAC__NO_ASM */ #ifndef FLAC__INTEGER_ONLY_LIBRARY diff --git a/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/include/private/md5.h b/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/include/private/md5.h index 2cf5c5d..b1324a9 100644 --- a/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/include/private/md5.h +++ b/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/include/private/md5.h @@ -28,11 +28,17 @@ #include "../../../ordinals.h" +typedef union { + FLAC__byte *p8; + FLAC__int16 *p16; + FLAC__int32 *p32; +} FLAC__multibyte; + typedef struct { FLAC__uint32 in[16]; FLAC__uint32 buf[4]; FLAC__uint32 bytes[2]; - FLAC__byte *internal_buf; + FLAC__multibyte internal_buf; size_t capacity; } FLAC__MD5Context; diff --git a/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/include/private/memory.h b/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/include/private/memory.h index d6651c6..c387ea6 100644 --- a/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/include/private/memory.h +++ b/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/include/private/memory.h @@ -1,6 +1,6 @@ /* libFLAC - Free Lossless Audio Codec library * Copyright (C) 2001-2009 Josh Coalson - * Copyright (C) 2011-2013 Xiph.Org Foundation + * Copyright (C) 2011-2014 Xiph.Org Foundation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/include/private/metadata.h b/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/include/private/metadata.h index a29050e..29c73e0 100644 --- a/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/include/private/metadata.h +++ b/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/include/private/metadata.h @@ -1,6 +1,6 @@ /* libFLAC - Free Lossless Audio Codec library * Copyright (C) 2002-2009 Josh Coalson - * Copyright (C) 2011-2013 Xiph.Org Foundation + * Copyright (C) 2011-2014 Xiph.Org Foundation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/include/private/stream_encoder_framing.h b/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/include/private/stream_encoder_framing.h index 51bf8c3..eaa9958 100644 --- a/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/include/private/stream_encoder_framing.h +++ b/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/include/private/stream_encoder_framing.h @@ -1,6 +1,6 @@ /* libFLAC - Free Lossless Audio Codec library * Copyright (C) 2000-2009 Josh Coalson - * Copyright (C) 2011-2013 Xiph.Org Foundation + * Copyright (C) 2011-2014 Xiph.Org Foundation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/include/private/window.h b/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/include/private/window.h index 8acec39..8464d22 100644 --- a/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/include/private/window.h +++ b/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/include/private/window.h @@ -1,6 +1,6 @@ /* libFLAC - Free Lossless Audio Codec library * Copyright (C) 2006-2009 Josh Coalson - * Copyright (C) 2011-2013 Xiph.Org Foundation + * Copyright (C) 2011-2014 Xiph.Org Foundation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -65,6 +65,8 @@ void FLAC__window_nuttall(FLAC__real *window, const FLAC__int32 L); void FLAC__window_rectangle(FLAC__real *window, const FLAC__int32 L); void FLAC__window_triangle(FLAC__real *window, const FLAC__int32 L); void FLAC__window_tukey(FLAC__real *window, const FLAC__int32 L, const FLAC__real p); +void FLAC__window_partial_tukey(FLAC__real *window, const FLAC__int32 L, const FLAC__real p, const FLAC__real start, const FLAC__real end); +void FLAC__window_punchout_tukey(FLAC__real *window, const FLAC__int32 L, const FLAC__real p, const FLAC__real start, const FLAC__real end); void FLAC__window_welch(FLAC__real *window, const FLAC__int32 L); #endif /* !defined FLAC__INTEGER_ONLY_LIBRARY */ diff --git a/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/include/protected/all.h b/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/include/protected/all.h index 057cd73..b852c2b 100644 --- a/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/include/protected/all.h +++ b/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/include/protected/all.h @@ -1,6 +1,6 @@ /* libFLAC - Free Lossless Audio Codec library * Copyright (C) 2001-2009 Josh Coalson - * Copyright (C) 2011-2013 Xiph.Org Foundation + * Copyright (C) 2011-2014 Xiph.Org Foundation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/include/protected/stream_decoder.h b/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/include/protected/stream_decoder.h index 0d5813f..d8a3e61 100644 --- a/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/include/protected/stream_decoder.h +++ b/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/include/protected/stream_decoder.h @@ -1,6 +1,6 @@ /* libFLAC - Free Lossless Audio Codec library * Copyright (C) 2000-2009 Josh Coalson - * Copyright (C) 2011-2013 Xiph.Org Foundation + * Copyright (C) 2011-2014 Xiph.Org Foundation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -40,6 +40,7 @@ typedef struct FLAC__StreamDecoderProtected { FLAC__StreamDecoderState state; + FLAC__StreamDecoderInitStatus initstate; unsigned channels; FLAC__ChannelAssignment channel_assignment; unsigned bits_per_sample; diff --git a/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/include/protected/stream_encoder.h b/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/include/protected/stream_encoder.h index 2c632f9..bd0cf25 100644 --- a/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/include/protected/stream_encoder.h +++ b/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/include/protected/stream_encoder.h @@ -1,6 +1,6 @@ /* libFLAC - Free Lossless Audio Codec library * Copyright (C) 2001-2009 Josh Coalson - * Copyright (C) 2011-2013 Xiph.Org Foundation + * Copyright (C) 2011-2014 Xiph.Org Foundation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -59,6 +59,8 @@ typedef enum { FLAC__APODIZATION_RECTANGLE, FLAC__APODIZATION_TRIANGLE, FLAC__APODIZATION_TUKEY, + FLAC__APODIZATION_PARTIAL_TUKEY, + FLAC__APODIZATION_PUNCHOUT_TUKEY, FLAC__APODIZATION_WELCH } FLAC__ApodizationFunction; @@ -71,6 +73,11 @@ typedef struct { struct { FLAC__real p; } tukey; + struct { + FLAC__real p; + FLAC__real start; + FLAC__real end; + } multiple_tukey; } parameters; } FLAC__ApodizationSpecification; diff --git a/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/lpc_flac.c b/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/lpc_flac.c index 5741e7c..87e2321 100644 --- a/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/lpc_flac.c +++ b/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/lpc_flac.c @@ -1,6 +1,6 @@ /* libFLAC - Free Lossless Audio Codec library * Copyright (C) 2000-2009 Josh Coalson - * Copyright (C) 2011-2013 Xiph.Org Foundation + * Copyright (C) 2011-2014 Xiph.Org Foundation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -30,7 +30,7 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#if HAVE_CONFIG_H +#ifdef HAVE_CONFIG_H # include #endif @@ -50,11 +50,6 @@ #ifndef FLAC__INTEGER_ONLY_LIBRARY -#ifndef M_LN2 -/* math.h in VC++ doesn't seem to have this (how Microsoft is that?) */ -#define M_LN2 0.69314718055994530942 -#endif - #if !defined(HAVE_LROUND) #if defined(_MSC_VER) #include @@ -65,7 +60,7 @@ static inline long int lround(double x) { return (long)(x + copysign (0.5, x)); } -//If this fails, we are in the precence of a mid 90's compiler..move along... +/* If this fails, we are in the presence of a mid 90's compiler, move along... */ #endif void FLAC__lpc_window_data(const FLAC__int32 in[], const FLAC__real window[], FLAC__real out[], unsigned data_len) @@ -160,7 +155,7 @@ void FLAC__lpc_compute_lp_coefficients(const FLAC__real autoc[], unsigned *max_o lp_coeff[i][j] = (FLAC__real)(-lpc[j]); /* negate FIR filter coeff to get predictor coeff */ error[i] = err; - /* see SF bug #1601812 http://sourceforge.net/tracker/index.php?func=detail&aid=1601812&group_id=13478&atid=113478 */ + /* see SF bug https://sourceforge.net/p/flac/bugs/234/ */ if(err == 0.0) { *max_order = i+1; return; @@ -264,7 +259,12 @@ int FLAC__lpc_quantize_coefficients(const FLAC__real lp_coeff[], unsigned order, return 0; } -void FLAC__lpc_compute_residual_from_qlp_coefficients(const FLAC__int32 *data, unsigned data_len, const FLAC__int32 qlp_coeff[], unsigned order, int lp_quantization, FLAC__int32 residual[]) +#if defined(_MSC_VER) +// silence MSVC warnings about __restrict modifier +#pragma warning ( disable : 4028 ) +#endif + +void FLAC__lpc_compute_residual_from_qlp_coefficients(const FLAC__int32 * flac_restrict data, unsigned data_len, const FLAC__int32 * flac_restrict qlp_coeff, unsigned order, int lp_quantization, FLAC__int32 * flac_restrict residual) #if defined(FLAC__OVERFLOW_DETECT) || !defined(FLAC__LPC_UNROLLED_FILTER_LOOPS) { FLAC__int64 sumo; @@ -524,7 +524,7 @@ void FLAC__lpc_compute_residual_from_qlp_coefficients(const FLAC__int32 *data, u } #endif -void FLAC__lpc_compute_residual_from_qlp_coefficients_wide(const FLAC__int32 *data, unsigned data_len, const FLAC__int32 qlp_coeff[], unsigned order, int lp_quantization, FLAC__int32 residual[]) +void FLAC__lpc_compute_residual_from_qlp_coefficients_wide(const FLAC__int32 * flac_restrict data, unsigned data_len, const FLAC__int32 * flac_restrict qlp_coeff, unsigned order, int lp_quantization, FLAC__int32 * flac_restrict residual) #if defined(FLAC__OVERFLOW_DETECT) || !defined(FLAC__LPC_UNROLLED_FILTER_LOOPS) { unsigned i, j; @@ -780,7 +780,7 @@ void FLAC__lpc_compute_residual_from_qlp_coefficients_wide(const FLAC__int32 *da #endif /* !defined FLAC__INTEGER_ONLY_LIBRARY */ -void FLAC__lpc_restore_signal(const FLAC__int32 residual[], unsigned data_len, const FLAC__int32 qlp_coeff[], unsigned order, int lp_quantization, FLAC__int32 data[]) +void FLAC__lpc_restore_signal(const FLAC__int32 * flac_restrict residual, unsigned data_len, const FLAC__int32 * flac_restrict qlp_coeff, unsigned order, int lp_quantization, FLAC__int32 * flac_restrict data) #if defined(FLAC__OVERFLOW_DETECT) || !defined(FLAC__LPC_UNROLLED_FILTER_LOOPS) { FLAC__int64 sumo; @@ -1041,7 +1041,7 @@ void FLAC__lpc_restore_signal(const FLAC__int32 residual[], unsigned data_len, c } #endif -void FLAC__lpc_restore_signal_wide(const FLAC__int32 residual[], unsigned data_len, const FLAC__int32 qlp_coeff[], unsigned order, int lp_quantization, FLAC__int32 data[]) +void FLAC__lpc_restore_signal_wide(const FLAC__int32 * flac_restrict residual, unsigned data_len, const FLAC__int32 * flac_restrict qlp_coeff, unsigned order, int lp_quantization, FLAC__int32 * flac_restrict data) #if defined(FLAC__OVERFLOW_DETECT) || !defined(FLAC__LPC_UNROLLED_FILTER_LOOPS) { unsigned i, j; @@ -1295,6 +1295,10 @@ void FLAC__lpc_restore_signal_wide(const FLAC__int32 residual[], unsigned data_l } #endif +#if defined(_MSC_VER) +#pragma warning ( default : 4028 ) +#endif + #ifndef FLAC__INTEGER_ONLY_LIBRARY FLAC__double FLAC__lpc_compute_expected_bits_per_residual_sample(FLAC__double lpc_error, unsigned total_samples) diff --git a/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/md5.c b/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/md5.c index c448b87..d41f6a8 100644 --- a/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/md5.c +++ b/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/md5.c @@ -1,4 +1,4 @@ -#if HAVE_CONFIG_H +#ifdef HAVE_CONFIG_H # include #endif @@ -7,6 +7,7 @@ #include "include/private/md5.h" #include "../alloc.h" +#include "../endswap.h" /* * This code implements the MD5 message-digest algorithm. @@ -223,7 +224,7 @@ void FLAC__MD5Init(FLAC__MD5Context *ctx) ctx->bytes[0] = 0; ctx->bytes[1] = 0; - ctx->internal_buf = 0; + ctx->internal_buf.p8= 0; ctx->capacity = 0; } @@ -259,9 +260,9 @@ void FLAC__MD5Final(FLAC__byte digest[16], FLAC__MD5Context *ctx) byteSwap(ctx->buf, 4); memcpy(digest, ctx->buf, 16); - if(0 != ctx->internal_buf) { - free(ctx->internal_buf); - ctx->internal_buf = 0; + if (0 != ctx->internal_buf.p8) { + free(ctx->internal_buf.p8); + ctx->internal_buf.p8= 0; ctx->capacity = 0; } memset(ctx, 0, sizeof(*ctx)); /* In case it's sensitive */ @@ -270,58 +271,124 @@ void FLAC__MD5Final(FLAC__byte digest[16], FLAC__MD5Context *ctx) /* * Convert the incoming audio signal to a byte stream */ -static void format_input_(FLAC__byte *buf, const FLAC__int32 * const signal[], unsigned channels, unsigned samples, unsigned bytes_per_sample) +static void format_input_(FLAC__multibyte *mbuf, const FLAC__int32 * const signal[], unsigned channels, unsigned samples, unsigned bytes_per_sample) { + FLAC__byte *buf_ = mbuf->p8; + FLAC__int16 *buf16 = mbuf->p16; + FLAC__int32 *buf32 = mbuf->p32; + FLAC__int32 a_word; unsigned channel, sample; - register FLAC__int32 a_word; - register FLAC__byte *buf_ = buf; -#if WORDS_BIGENDIAN -#else - if(channels == 2 && bytes_per_sample == 2) { - FLAC__int16 *buf1_ = ((FLAC__int16*)buf_) + 1; - memcpy(buf_, signal[0], sizeof(FLAC__int32) * samples); - for(sample = 0; sample < samples; sample++, buf1_+=2) - *buf1_ = (FLAC__int16)signal[1][sample]; - } - else if(channels == 1 && bytes_per_sample == 2) { - FLAC__int16 *buf1_ = (FLAC__int16*)buf_; - for(sample = 0; sample < samples; sample++) - *buf1_++ = (FLAC__int16)signal[0][sample]; - } - else -#endif - if(bytes_per_sample == 2) { - if(channels == 2) { - for(sample = 0; sample < samples; sample++) { + /* Storage in the output buffer, buf, is little endian. */ + +#define BYTES_CHANNEL_SELECTOR(bytes, channels) (bytes * 100 + channels) + + /* First do the most commonly used combinations. */ + switch (BYTES_CHANNEL_SELECTOR (bytes_per_sample, channels)) { + /* One byte per sample. */ + case (BYTES_CHANNEL_SELECTOR (1, 1)): + for (sample = 0; sample < samples; sample++) + *buf_++ = signal[0][sample]; + return; + + case (BYTES_CHANNEL_SELECTOR (1, 2)): + for (sample = 0; sample < samples; sample++) { + *buf_++ = signal[0][sample]; + *buf_++ = signal[1][sample]; + } + return; + + case (BYTES_CHANNEL_SELECTOR (1, 4)): + for (sample = 0; sample < samples; sample++) { + *buf_++ = signal[0][sample]; + *buf_++ = signal[1][sample]; + *buf_++ = signal[2][sample]; + *buf_++ = signal[3][sample]; + } + return; + + case (BYTES_CHANNEL_SELECTOR (1, 6)): + for (sample = 0; sample < samples; sample++) { + *buf_++ = signal[0][sample]; + *buf_++ = signal[1][sample]; + *buf_++ = signal[2][sample]; + *buf_++ = signal[3][sample]; + *buf_++ = signal[4][sample]; + *buf_++ = signal[5][sample]; + } + return; + + case (BYTES_CHANNEL_SELECTOR (1, 8)): + for (sample = 0; sample < samples; sample++) { + *buf_++ = signal[0][sample]; + *buf_++ = signal[1][sample]; + *buf_++ = signal[2][sample]; + *buf_++ = signal[3][sample]; + *buf_++ = signal[4][sample]; + *buf_++ = signal[5][sample]; + *buf_++ = signal[6][sample]; + *buf_++ = signal[7][sample]; + } + return; + + /* Two bytes per sample. */ + case (BYTES_CHANNEL_SELECTOR (2, 1)): + for (sample = 0; sample < samples; sample++) + *buf16++ = H2LE_16(signal[0][sample]); + return; + + case (BYTES_CHANNEL_SELECTOR (2, 2)): + for (sample = 0; sample < samples; sample++) { + *buf16++ = H2LE_16(signal[0][sample]); + *buf16++ = H2LE_16(signal[1][sample]); + } + return; + + case (BYTES_CHANNEL_SELECTOR (2, 4)): + for (sample = 0; sample < samples; sample++) { + *buf16++ = H2LE_16(signal[0][sample]); + *buf16++ = H2LE_16(signal[1][sample]); + *buf16++ = H2LE_16(signal[2][sample]); + *buf16++ = H2LE_16(signal[3][sample]); + } + return; + + case (BYTES_CHANNEL_SELECTOR (2, 6)): + for (sample = 0; sample < samples; sample++) { + *buf16++ = H2LE_16(signal[0][sample]); + *buf16++ = H2LE_16(signal[1][sample]); + *buf16++ = H2LE_16(signal[2][sample]); + *buf16++ = H2LE_16(signal[3][sample]); + *buf16++ = H2LE_16(signal[4][sample]); + *buf16++ = H2LE_16(signal[5][sample]); + } + return; + + case (BYTES_CHANNEL_SELECTOR (2, 8)): + for (sample = 0; sample < samples; sample++) { + *buf16++ = H2LE_16(signal[0][sample]); + *buf16++ = H2LE_16(signal[1][sample]); + *buf16++ = H2LE_16(signal[2][sample]); + *buf16++ = H2LE_16(signal[3][sample]); + *buf16++ = H2LE_16(signal[4][sample]); + *buf16++ = H2LE_16(signal[5][sample]); + *buf16++ = H2LE_16(signal[6][sample]); + *buf16++ = H2LE_16(signal[7][sample]); + } + return; + + /* Three bytes per sample. */ + case (BYTES_CHANNEL_SELECTOR (3, 1)): + for (sample = 0; sample < samples; sample++) { a_word = signal[0][sample]; *buf_++ = (FLAC__byte)a_word; a_word >>= 8; - *buf_++ = (FLAC__byte)a_word; - a_word = signal[1][sample]; *buf_++ = (FLAC__byte)a_word; a_word >>= 8; *buf_++ = (FLAC__byte)a_word; } - } - else if(channels == 1) { - for(sample = 0; sample < samples; sample++) { - a_word = signal[0][sample]; - *buf_++ = (FLAC__byte)a_word; a_word >>= 8; - *buf_++ = (FLAC__byte)a_word; - } - } - else { - for(sample = 0; sample < samples; sample++) { - for(channel = 0; channel < channels; channel++) { - a_word = signal[channel][sample]; - *buf_++ = (FLAC__byte)a_word; a_word >>= 8; - *buf_++ = (FLAC__byte)a_word; - } - } - } - } - else if(bytes_per_sample == 3) { - if(channels == 2) { - for(sample = 0; sample < samples; sample++) { + return; + + case (BYTES_CHANNEL_SELECTOR (3, 2)): + for (sample = 0; sample < samples; sample++) { a_word = signal[0][sample]; *buf_++ = (FLAC__byte)a_word; a_word >>= 8; *buf_++ = (FLAC__byte)a_word; a_word >>= 8; @@ -331,60 +398,90 @@ static void format_input_(FLAC__byte *buf, const FLAC__int32 * const signal[], u *buf_++ = (FLAC__byte)a_word; a_word >>= 8; *buf_++ = (FLAC__byte)a_word; } - } - else if(channels == 1) { - for(sample = 0; sample < samples; sample++) { - a_word = signal[0][sample]; - *buf_++ = (FLAC__byte)a_word; a_word >>= 8; - *buf_++ = (FLAC__byte)a_word; a_word >>= 8; - *buf_++ = (FLAC__byte)a_word; + return; + + /* Four bytes per sample. */ + case (BYTES_CHANNEL_SELECTOR (4, 1)): + for (sample = 0; sample < samples; sample++) + *buf32++ = H2LE_32(signal[0][sample]); + return; + + case (BYTES_CHANNEL_SELECTOR (4, 2)): + for (sample = 0; sample < samples; sample++) { + *buf32++ = H2LE_32(signal[0][sample]); + *buf32++ = H2LE_32(signal[1][sample]); } - } - else { - for(sample = 0; sample < samples; sample++) { - for(channel = 0; channel < channels; channel++) { + return; + + case (BYTES_CHANNEL_SELECTOR (4, 4)): + for (sample = 0; sample < samples; sample++) { + *buf32++ = H2LE_32(signal[0][sample]); + *buf32++ = H2LE_32(signal[1][sample]); + *buf32++ = H2LE_32(signal[2][sample]); + *buf32++ = H2LE_32(signal[3][sample]); + } + return; + + case (BYTES_CHANNEL_SELECTOR (4, 6)): + for (sample = 0; sample < samples; sample++) { + *buf32++ = H2LE_32(signal[0][sample]); + *buf32++ = H2LE_32(signal[1][sample]); + *buf32++ = H2LE_32(signal[2][sample]); + *buf32++ = H2LE_32(signal[3][sample]); + *buf32++ = H2LE_32(signal[4][sample]); + *buf32++ = H2LE_32(signal[5][sample]); + } + return; + + case (BYTES_CHANNEL_SELECTOR (4, 8)): + for (sample = 0; sample < samples; sample++) { + *buf32++ = H2LE_32(signal[0][sample]); + *buf32++ = H2LE_32(signal[1][sample]); + *buf32++ = H2LE_32(signal[2][sample]); + *buf32++ = H2LE_32(signal[3][sample]); + *buf32++ = H2LE_32(signal[4][sample]); + *buf32++ = H2LE_32(signal[5][sample]); + *buf32++ = H2LE_32(signal[6][sample]); + *buf32++ = H2LE_32(signal[7][sample]); + } + return; + + default: + break; + } + + /* General version. */ + switch (bytes_per_sample) { + case 1: + for (sample = 0; sample < samples; sample++) + for (channel = 0; channel < channels; channel++) + *buf_++ = signal[channel][sample]; + return; + + case 2: + for (sample = 0; sample < samples; sample++) + for (channel = 0; channel < channels; channel++) + *buf16++ = H2LE_16(signal[channel][sample]); + return; + + case 3: + for (sample = 0; sample < samples; sample++) + for (channel = 0; channel < channels; channel++) { a_word = signal[channel][sample]; *buf_++ = (FLAC__byte)a_word; a_word >>= 8; *buf_++ = (FLAC__byte)a_word; a_word >>= 8; *buf_++ = (FLAC__byte)a_word; } - } - } - } - else if(bytes_per_sample == 1) { - if(channels == 2) { - for(sample = 0; sample < samples; sample++) { - a_word = signal[0][sample]; - *buf_++ = (FLAC__byte)a_word; - a_word = signal[1][sample]; - *buf_++ = (FLAC__byte)a_word; - } - } - else if(channels == 1) { - for(sample = 0; sample < samples; sample++) { - a_word = signal[0][sample]; - *buf_++ = (FLAC__byte)a_word; - } - } - else { - for(sample = 0; sample < samples; sample++) { - for(channel = 0; channel < channels; channel++) { - a_word = signal[channel][sample]; - *buf_++ = (FLAC__byte)a_word; - } - } - } - } - else { /* bytes_per_sample == 4, maybe optimize more later */ - for(sample = 0; sample < samples; sample++) { - for(channel = 0; channel < channels; channel++) { - a_word = signal[channel][sample]; - *buf_++ = (FLAC__byte)a_word; a_word >>= 8; - *buf_++ = (FLAC__byte)a_word; a_word >>= 8; - *buf_++ = (FLAC__byte)a_word; a_word >>= 8; - *buf_++ = (FLAC__byte)a_word; - } - } + return; + + case 4: + for (sample = 0; sample < samples; sample++) + for (channel = 0; channel < channels; channel++) + *buf32++ = H2LE_32(signal[channel][sample]); + return; + + default: + break; } } @@ -396,26 +493,26 @@ FLAC__bool FLAC__MD5Accumulate(FLAC__MD5Context *ctx, const FLAC__int32 * const const size_t bytes_needed = (size_t)channels * (size_t)samples * (size_t)bytes_per_sample; /* overflow check */ - if((size_t)channels > SIZE_MAX / (size_t)bytes_per_sample) + if ((size_t)channels > SIZE_MAX / (size_t)bytes_per_sample) return false; - if((size_t)channels * (size_t)bytes_per_sample > SIZE_MAX / (size_t)samples) + if ((size_t)channels * (size_t)bytes_per_sample > SIZE_MAX / (size_t)samples) return false; - if(ctx->capacity < bytes_needed) { - FLAC__byte *tmp = (FLAC__byte*) realloc(ctx->internal_buf, bytes_needed); - if(0 == tmp) { - free(ctx->internal_buf); - if(0 == (ctx->internal_buf = (FLAC__byte*) safe_malloc_(bytes_needed))) + if (ctx->capacity < bytes_needed) { + FLAC__byte *tmp = (FLAC__byte*) realloc(ctx->internal_buf.p8, bytes_needed); + if (0 == tmp) { + free(ctx->internal_buf.p8); + if (0 == (ctx->internal_buf.p8= (FLAC__byte*) safe_malloc_(bytes_needed))) return false; } else - ctx->internal_buf = tmp; + ctx->internal_buf.p8= tmp; ctx->capacity = bytes_needed; } - format_input_(ctx->internal_buf, signal, channels, samples, bytes_per_sample); + format_input_(&ctx->internal_buf, signal, channels, samples, bytes_per_sample); - FLAC__MD5Update(ctx, ctx->internal_buf, bytes_needed); + FLAC__MD5Update(ctx, ctx->internal_buf.p8, bytes_needed); return true; } diff --git a/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/memory.c b/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/memory.c index dd972e0..fb125f1 100644 --- a/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/memory.c +++ b/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/memory.c @@ -1,6 +1,6 @@ /* libFLAC - Free Lossless Audio Codec library * Copyright (C) 2001-2009 Josh Coalson - * Copyright (C) 2011-2013 Xiph.Org Foundation + * Copyright (C) 2011-2014 Xiph.Org Foundation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -30,10 +30,14 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#if HAVE_CONFIG_H +#ifdef HAVE_CONFIG_H # include #endif +#ifdef HAVE_STDINT_H +#include +#endif + #include "include/private/memory.h" #include "../assert.h" #include "../alloc.h" @@ -46,25 +50,8 @@ void *FLAC__memory_alloc_aligned(size_t bytes, void **aligned_address) #ifdef FLAC__ALIGN_MALLOC_DATA /* align on 32-byte (256-bit) boundary */ - x = safe_malloc_add_2op_(bytes, /*+*/31); -#ifdef SIZEOF_VOIDP -#if SIZEOF_VOIDP == 4 - /* could do *aligned_address = x + ((unsigned) (32 - (((unsigned)x) & 31))) & 31; */ - *aligned_address = (void*)(((unsigned)x + 31) & -32); -#elif SIZEOF_VOIDP == 8 - *aligned_address = (void*)(((FLAC__uint64)x + 31) & (FLAC__uint64)(-((FLAC__int64)32))); -#else -# error Unsupported sizeof(void*) -#endif -#else - /* there's got to be a better way to do this right for all archs */ - if(sizeof(void*) == sizeof(unsigned)) - *aligned_address = (void*)(((unsigned)x + 31) & -32); - else if(sizeof(void*) == sizeof(FLAC__uint64)) - *aligned_address = (void*)(((FLAC__uint64)x + 31) & (FLAC__uint64)(-((FLAC__int64)32))); - else - return 0; -#endif + x = safe_malloc_add_2op_(bytes, /*+*/31L); + *aligned_address = (void*)(((uintptr_t)x + 31L) & -32L); #else x = safe_malloc_(bytes); *aligned_address = x; diff --git a/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/stream_decoder.c b/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/stream_decoder.c index 04e1766..d6a7973 100644 --- a/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/stream_decoder.c +++ b/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/stream_decoder.c @@ -1,6 +1,6 @@ /* libFLAC - Free Lossless Audio Codec library * Copyright (C) 2000-2009 Josh Coalson - * Copyright (C) 2011-2013 Xiph.Org Foundation + * Copyright (C) 2011-2014 Xiph.Org Foundation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -30,7 +30,7 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#if HAVE_CONFIG_H +#ifdef HAVE_CONFIG_H # include #endif @@ -70,7 +70,7 @@ FLAC_API int FLAC_API_SUPPORTS_OGG_FLAC = * ***********************************************************************/ -static FLAC__byte ID3V2_TAG_[3] = { 'I', 'D', '3' }; +static const FLAC__byte ID3V2_TAG_[3] = { 'I', 'D', '3' }; /*********************************************************************** * @@ -86,7 +86,7 @@ static FLAC__bool find_metadata_(FLAC__StreamDecoder *decoder); static FLAC__bool read_metadata_(FLAC__StreamDecoder *decoder); static FLAC__bool read_metadata_streaminfo_(FLAC__StreamDecoder *decoder, FLAC__bool is_last, unsigned length); static FLAC__bool read_metadata_seektable_(FLAC__StreamDecoder *decoder, FLAC__bool is_last, unsigned length); -static FLAC__bool read_metadata_vorbiscomment_(FLAC__StreamDecoder *decoder, FLAC__StreamMetadata_VorbisComment *obj); +static FLAC__bool read_metadata_vorbiscomment_(FLAC__StreamDecoder *decoder, FLAC__StreamMetadata_VorbisComment *obj, unsigned length); static FLAC__bool read_metadata_cuesheet_(FLAC__StreamDecoder *decoder, FLAC__StreamMetadata_CueSheet *obj); static FLAC__bool read_metadata_picture_(FLAC__StreamDecoder *decoder, FLAC__StreamMetadata_Picture *obj); static FLAC__bool skip_id3v2_tag_(FLAC__StreamDecoder *decoder); @@ -141,9 +141,6 @@ typedef struct FLAC__StreamDecoderPrivate { void (*local_lpc_restore_signal_64bit)(const FLAC__int32 residual[], unsigned data_len, const FLAC__int32 qlp_coeff[], unsigned order, int lp_quantization, FLAC__int32 data[]); /* for use when the signal is <= 16 bits-per-sample, or <= 15 bits-per-sample on a side channel (which requires 1 extra bit): */ void (*local_lpc_restore_signal_16bit)(const FLAC__int32 residual[], unsigned data_len, const FLAC__int32 qlp_coeff[], unsigned order, int lp_quantization, FLAC__int32 data[]); - /* for use when the signal is <= 16 bits-per-sample, or <= 15 bits-per-sample on a side channel (which requires 1 extra bit), AND order <= 8: */ - void (*local_lpc_restore_signal_16bit_order8)(const FLAC__int32 residual[], unsigned data_len, const FLAC__int32 qlp_coeff[], unsigned order, int lp_quantization, FLAC__int32 data[]); - FLAC__bool (*local_bitreader_read_rice_signed_block)(FLAC__BitReader *br, int vals[], unsigned nvals, unsigned parameter); void *client_data; FILE *file; /* only used if FLAC__stream_decoder_init_file()/FLAC__stream_decoder_init_file() called, else NULL */ FLAC__BitReader *input; @@ -380,7 +377,7 @@ static FLAC__StreamDecoderInitStatus init_stream_internal_( #if FLAC__HAS_OGG decoder->private_->is_ogg = is_ogg; if(is_ogg && !FLAC__ogg_decoder_aspect_init(&decoder->protected_->ogg_decoder_aspect)) - return decoder->protected_->state = FLAC__STREAM_DECODER_OGG_ERROR; + return decoder->protected_->initstate = FLAC__STREAM_DECODER_INIT_STATUS_ERROR_OPENING_FILE; #endif /* @@ -391,42 +388,44 @@ static FLAC__StreamDecoderInitStatus init_stream_internal_( decoder->private_->local_lpc_restore_signal = FLAC__lpc_restore_signal; decoder->private_->local_lpc_restore_signal_64bit = FLAC__lpc_restore_signal_wide; decoder->private_->local_lpc_restore_signal_16bit = FLAC__lpc_restore_signal; - decoder->private_->local_lpc_restore_signal_16bit_order8 = FLAC__lpc_restore_signal; - decoder->private_->local_bitreader_read_rice_signed_block = FLAC__bitreader_read_rice_signed_block; /* now override with asm where appropriate */ #ifndef FLAC__NO_ASM if(decoder->private_->cpuinfo.use_asm) { #ifdef FLAC__CPU_IA32 FLAC__ASSERT(decoder->private_->cpuinfo.type == FLAC__CPUINFO_TYPE_IA32); #ifdef FLAC__HAS_NASM -#if 1 /*@@@@@@ OPT: not clearly faster, needs more testing */ - if(decoder->private_->cpuinfo.data.ia32.bswap) - decoder->private_->local_bitreader_read_rice_signed_block = FLAC__bitreader_read_rice_signed_block_asm_ia32_bswap; -#endif - if(decoder->private_->cpuinfo.data.ia32.mmx) { + decoder->private_->local_lpc_restore_signal_64bit = FLAC__lpc_restore_signal_wide_asm_ia32; /* OPT_IA32: was really necessary for GCC < 4.9 */ + if(decoder->private_->cpuinfo.ia32.mmx) { decoder->private_->local_lpc_restore_signal = FLAC__lpc_restore_signal_asm_ia32; decoder->private_->local_lpc_restore_signal_16bit = FLAC__lpc_restore_signal_asm_ia32_mmx; - decoder->private_->local_lpc_restore_signal_16bit_order8 = FLAC__lpc_restore_signal_asm_ia32_mmx; } else { decoder->private_->local_lpc_restore_signal = FLAC__lpc_restore_signal_asm_ia32; decoder->private_->local_lpc_restore_signal_16bit = FLAC__lpc_restore_signal_asm_ia32; - decoder->private_->local_lpc_restore_signal_16bit_order8 = FLAC__lpc_restore_signal_asm_ia32; } #endif -#elif defined FLAC__CPU_PPC - FLAC__ASSERT(decoder->private_->cpuinfo.type == FLAC__CPUINFO_TYPE_PPC); - if(decoder->private_->cpuinfo.data.ppc.altivec) { - decoder->private_->local_lpc_restore_signal_16bit = FLAC__lpc_restore_signal_asm_ppc_altivec_16; - decoder->private_->local_lpc_restore_signal_16bit_order8 = FLAC__lpc_restore_signal_asm_ppc_altivec_16_order8; +#ifdef FLAC__HAS_X86INTRIN +# if defined FLAC__SSE2_SUPPORTED && !defined FLAC__HAS_NASM /* OPT_SSE: not better than MMX asm */ + if(decoder->private_->cpuinfo.ia32.sse2) { + decoder->private_->local_lpc_restore_signal_16bit = FLAC__lpc_restore_signal_16_intrin_sse2; } +# endif +# if defined FLAC__SSE4_1_SUPPORTED + if(decoder->private_->cpuinfo.ia32.sse41) { + decoder->private_->local_lpc_restore_signal_64bit = FLAC__lpc_restore_signal_wide_intrin_sse41; + } +# endif +#endif +#elif defined FLAC__CPU_X86_64 + FLAC__ASSERT(decoder->private_->cpuinfo.type == FLAC__CPUINFO_TYPE_X86_64); + /* No useful SSE optimizations yet */ #endif } #endif /* from here on, errors are fatal */ - if(!FLAC__bitreader_init(decoder->private_->input, decoder->private_->cpuinfo, read_callback_, decoder)) { + if(!FLAC__bitreader_init(decoder->private_->input, read_callback_, decoder)) { decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR; return FLAC__STREAM_DECODER_INIT_STATUS_MEMORY_ALLOCATION_ERROR; } @@ -528,10 +527,10 @@ static FLAC__StreamDecoderInitStatus init_FILE_internal_( FLAC__ASSERT(0 != file); if(decoder->protected_->state != FLAC__STREAM_DECODER_UNINITIALIZED) - return (FLAC__StreamDecoderInitStatus) (decoder->protected_->state = (FLAC__StreamDecoderState) FLAC__STREAM_DECODER_INIT_STATUS_ALREADY_INITIALIZED); + return decoder->protected_->initstate = FLAC__STREAM_DECODER_INIT_STATUS_ALREADY_INITIALIZED; if(0 == write_callback || 0 == error_callback) - return (FLAC__StreamDecoderInitStatus) (decoder->protected_->state = (FLAC__StreamDecoderState) FLAC__STREAM_DECODER_INIT_STATUS_INVALID_CALLBACKS); + return decoder->protected_->initstate = FLAC__STREAM_DECODER_INIT_STATUS_INVALID_CALLBACKS; /* * To make sure that our file does not go unclosed after an error, we @@ -602,10 +601,10 @@ static FLAC__StreamDecoderInitStatus init_file_internal_( * in FLAC__stream_decoder_init_FILE() before the FILE* is assigned. */ if(decoder->protected_->state != FLAC__STREAM_DECODER_UNINITIALIZED) - return (FLAC__StreamDecoderInitStatus) (decoder->protected_->state = (FLAC__StreamDecoderState) FLAC__STREAM_DECODER_INIT_STATUS_ALREADY_INITIALIZED); + return decoder->protected_->initstate = FLAC__STREAM_DECODER_INIT_STATUS_ALREADY_INITIALIZED; if(0 == write_callback || 0 == error_callback) - return (FLAC__StreamDecoderInitStatus) (decoder->protected_->state = (FLAC__StreamDecoderState) FLAC__STREAM_DECODER_INIT_STATUS_INVALID_CALLBACKS); + return decoder->protected_->initstate = FLAC__STREAM_DECODER_INIT_STATUS_INVALID_CALLBACKS; file = filename? flac_fopen(filename, "rb") : stdin; @@ -652,7 +651,7 @@ FLAC_API FLAC__bool FLAC__stream_decoder_finish(FLAC__StreamDecoder *decoder) if(decoder->protected_->state == FLAC__STREAM_DECODER_UNINITIALIZED) return true; - /* see the comment in FLAC__seekable_stream_decoder_reset() as to why we + /* see the comment in FLAC__stream_decoder_reset() as to why we * always call FLAC__MD5Final() */ FLAC__MD5Final(decoder->private_->computed_md5sum, &decoder->private_->md5context); @@ -1316,9 +1315,6 @@ FLAC__bool allocate_output_(FLAC__StreamDecoder *decoder, unsigned size, unsigne memset(tmp, 0, sizeof(FLAC__int32)*4); decoder->private_->output[i] = tmp + 4; - /* WATCHOUT: - * minimum of quadword alignment for PPC vector optimizations is REQUIRED: - */ if(!FLAC__memory_alloc_aligned_int32_array(size, &decoder->private_->residual_unaligned[i], &decoder->private_->residual[i])) { decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR; return false; @@ -1368,6 +1364,10 @@ FLAC__bool find_metadata_(FLAC__StreamDecoder *decoder) id_ = 0; continue; } + + if(id_ >= 3) + return false; + if(x == ID3V2_TAG_[id_]) { id_++; i = 0; @@ -1446,6 +1446,7 @@ FLAC__bool read_metadata_(FLAC__StreamDecoder *decoder) unsigned real_length = length; FLAC__StreamMetadata block; + memset(&block, 0, sizeof(block)); block.is_last = is_last; block.type = (FLAC__MetadataType)type; block.length = length; @@ -1470,36 +1471,37 @@ FLAC__bool read_metadata_(FLAC__StreamDecoder *decoder) return false; /* read_callback_ sets the state for us */ } else { + FLAC__bool ok = true; switch(type) { case FLAC__METADATA_TYPE_PADDING: /* skip the padding bytes */ if(!FLAC__bitreader_skip_byte_block_aligned_no_crc(decoder->private_->input, real_length)) - return false; /* read_callback_ sets the state for us */ + ok = false; /* read_callback_ sets the state for us */ break; case FLAC__METADATA_TYPE_APPLICATION: /* remember, we read the ID already */ if(real_length > 0) { if(0 == (block.data.application.data = (FLAC__byte*) malloc(real_length))) { decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR; - return false; + ok = false; } - if(!FLAC__bitreader_read_byte_block_aligned_no_crc(decoder->private_->input, block.data.application.data, real_length)) - return false; /* read_callback_ sets the state for us */ + else if(!FLAC__bitreader_read_byte_block_aligned_no_crc(decoder->private_->input, block.data.application.data, real_length)) + ok = false; /* read_callback_ sets the state for us */ } else block.data.application.data = 0; break; case FLAC__METADATA_TYPE_VORBIS_COMMENT: - if(!read_metadata_vorbiscomment_(decoder, &block.data.vorbis_comment)) - return false; + if(!read_metadata_vorbiscomment_(decoder, &block.data.vorbis_comment, real_length)) + ok = false; break; case FLAC__METADATA_TYPE_CUESHEET: if(!read_metadata_cuesheet_(decoder, &block.data.cue_sheet)) - return false; + ok = false; break; case FLAC__METADATA_TYPE_PICTURE: if(!read_metadata_picture_(decoder, &block.data.picture)) - return false; + ok = false; break; case FLAC__METADATA_TYPE_STREAMINFO: case FLAC__METADATA_TYPE_SEEKTABLE: @@ -1509,16 +1511,16 @@ FLAC__bool read_metadata_(FLAC__StreamDecoder *decoder) if(real_length > 0) { if(0 == (block.data.unknown.data = (FLAC__byte*) malloc(real_length))) { decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR; - return false; + ok = false; } - if(!FLAC__bitreader_read_byte_block_aligned_no_crc(decoder->private_->input, block.data.unknown.data, real_length)) - return false; /* read_callback_ sets the state for us */ + else if(!FLAC__bitreader_read_byte_block_aligned_no_crc(decoder->private_->input, block.data.unknown.data, real_length)) + ok = false; /* read_callback_ sets the state for us */ } else block.data.unknown.data = 0; break; } - if(!decoder->private_->is_seeking && decoder->private_->metadata_callback) + if(ok && !decoder->private_->is_seeking && decoder->private_->metadata_callback) decoder->private_->metadata_callback(decoder, &block, decoder->private_->client_data); /* now we have to free any malloc()ed data in the block */ @@ -1563,6 +1565,9 @@ FLAC__bool read_metadata_(FLAC__StreamDecoder *decoder) free(block.data.unknown.data); break; } + + if(!ok) /* anything that unsets "ok" should also make sure decoder->protected_->state is updated */ + return false; } } @@ -1689,58 +1694,88 @@ FLAC__bool read_metadata_seektable_(FLAC__StreamDecoder *decoder, FLAC__bool is_ return true; } -FLAC__bool read_metadata_vorbiscomment_(FLAC__StreamDecoder *decoder, FLAC__StreamMetadata_VorbisComment *obj) +FLAC__bool read_metadata_vorbiscomment_(FLAC__StreamDecoder *decoder, FLAC__StreamMetadata_VorbisComment *obj, unsigned length) { FLAC__uint32 i; FLAC__ASSERT(FLAC__bitreader_is_consumed_byte_aligned(decoder->private_->input)); /* read vendor string */ - FLAC__ASSERT(FLAC__STREAM_METADATA_VORBIS_COMMENT_ENTRY_LENGTH_LEN == 32); - if(!FLAC__bitreader_read_uint32_little_endian(decoder->private_->input, &obj->vendor_string.length)) - return false; /* read_callback_ sets the state for us */ - if(obj->vendor_string.length > 0) { - if(0 == (obj->vendor_string.entry = (FLAC__byte*) safe_malloc_add_2op_(obj->vendor_string.length, /*+*/1))) { - decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR; - return false; - } - if(!FLAC__bitreader_read_byte_block_aligned_no_crc(decoder->private_->input, obj->vendor_string.entry, obj->vendor_string.length)) + if (length >= 8) { + length -= 8; /* vendor string length + num comments entries alone take 8 bytes */ + FLAC__ASSERT(FLAC__STREAM_METADATA_VORBIS_COMMENT_ENTRY_LENGTH_LEN == 32); + if (!FLAC__bitreader_read_uint32_little_endian(decoder->private_->input, &obj->vendor_string.length)) return false; /* read_callback_ sets the state for us */ - obj->vendor_string.entry[obj->vendor_string.length] = '\0'; - } - else - obj->vendor_string.entry = 0; - - /* read num comments */ - FLAC__ASSERT(FLAC__STREAM_METADATA_VORBIS_COMMENT_NUM_COMMENTS_LEN == 32); - if(!FLAC__bitreader_read_uint32_little_endian(decoder->private_->input, &obj->num_comments)) - return false; /* read_callback_ sets the state for us */ - - /* read comments */ - if(obj->num_comments > 0) { - if(0 == (obj->comments = (FLAC__StreamMetadata_VorbisComment_Entry*) safe_malloc_mul_2op_p(obj->num_comments, /*times*/sizeof(FLAC__StreamMetadata_VorbisComment_Entry)))) { - decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR; - return false; - } - for(i = 0; i < obj->num_comments; i++) { - FLAC__ASSERT(FLAC__STREAM_METADATA_VORBIS_COMMENT_ENTRY_LENGTH_LEN == 32); - if(!FLAC__bitreader_read_uint32_little_endian(decoder->private_->input, &obj->comments[i].length)) - return false; /* read_callback_ sets the state for us */ - if(obj->comments[i].length > 0) { - if(0 == (obj->comments[i].entry = (FLAC__byte*) safe_malloc_add_2op_(obj->comments[i].length, /*+*/1))) { - decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR; - return false; - } - if(!FLAC__bitreader_read_byte_block_aligned_no_crc(decoder->private_->input, obj->comments[i].entry, obj->comments[i].length)) - return false; /* read_callback_ sets the state for us */ - obj->comments[i].entry[obj->comments[i].length] = '\0'; + if (obj->vendor_string.length > 0) { + if (length < obj->vendor_string.length) { + obj->vendor_string.length = 0; + obj->vendor_string.entry = 0; + goto skip; } else - obj->comments[i].entry = 0; + length -= obj->vendor_string.length; + if (0 == (obj->vendor_string.entry = (FLAC__byte*) safe_malloc_add_2op_(obj->vendor_string.length, /*+*/1))) { + decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR; + return false; + } + if (!FLAC__bitreader_read_byte_block_aligned_no_crc(decoder->private_->input, obj->vendor_string.entry, obj->vendor_string.length)) + return false; /* read_callback_ sets the state for us */ + obj->vendor_string.entry[obj->vendor_string.length] = '\0'; } + else + obj->vendor_string.entry = 0; + + /* read num comments */ + FLAC__ASSERT(FLAC__STREAM_METADATA_VORBIS_COMMENT_NUM_COMMENTS_LEN == 32); + if (!FLAC__bitreader_read_uint32_little_endian(decoder->private_->input, &obj->num_comments)) + return false; /* read_callback_ sets the state for us */ + + /* read comments */ + if (obj->num_comments > 0) { + if (0 == (obj->comments = (FLAC__StreamMetadata_VorbisComment_Entry*) safe_malloc_mul_2op_p(obj->num_comments, /*times*/sizeof(FLAC__StreamMetadata_VorbisComment_Entry)))) { + decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR; + return false; + } + for (i = 0; i < obj->num_comments; i++) { + FLAC__ASSERT(FLAC__STREAM_METADATA_VORBIS_COMMENT_ENTRY_LENGTH_LEN == 32); + if (length < 4) { + obj->num_comments = i; + goto skip; + } + else + length -= 4; + if (!FLAC__bitreader_read_uint32_little_endian(decoder->private_->input, &obj->comments[i].length)) + return false; /* read_callback_ sets the state for us */ + if (obj->comments[i].length > 0) { + if (length < obj->comments[i].length) { + obj->comments[i].length = 0; + obj->comments[i].entry = 0; + obj->num_comments = i; + goto skip; + } + else + length -= obj->comments[i].length; + if (0 == (obj->comments[i].entry = (FLAC__byte*) safe_malloc_add_2op_(obj->comments[i].length, /*+*/1))) { + decoder->protected_->state = FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR; + return false; + } + if (!FLAC__bitreader_read_byte_block_aligned_no_crc(decoder->private_->input, obj->comments[i].entry, obj->comments[i].length)) + return false; /* read_callback_ sets the state for us */ + obj->comments[i].entry[obj->comments[i].length] = '\0'; + } + else + obj->comments[i].entry = 0; + } + } + else + obj->comments = 0; } - else { - obj->comments = 0; + + skip: + if (length > 0) { + /* This will only happen on files with invalid data in comments */ + if(!FLAC__bitreader_skip_byte_block_aligned_no_crc(decoder->private_->input, length)) + return false; /* read_callback_ sets the state for us */ } return true; @@ -2655,12 +2690,8 @@ FLAC__bool read_subframe_lpc_(FLAC__StreamDecoder *decoder, unsigned channel, un if( (FLAC__uint64)order * ((((FLAC__uint64)1)<qlp_coeff_precision)-1) < (((FLAC__uint64)-1) << 32) ) */ if(bps + subframe->qlp_coeff_precision + FLAC__bitmath_ilog2(order) <= 32) - if(bps <= 16 && subframe->qlp_coeff_precision <= 16) { - if(order <= 8) - decoder->private_->local_lpc_restore_signal_16bit_order8(decoder->private_->residual[channel], decoder->private_->frame.header.blocksize-order, subframe->qlp_coeff, order, subframe->quantization_level, decoder->private_->output[channel]+order); - else - decoder->private_->local_lpc_restore_signal_16bit(decoder->private_->residual[channel], decoder->private_->frame.header.blocksize-order, subframe->qlp_coeff, order, subframe->quantization_level, decoder->private_->output[channel]+order); - } + if(bps <= 16 && subframe->qlp_coeff_precision <= 16) + decoder->private_->local_lpc_restore_signal_16bit(decoder->private_->residual[channel], decoder->private_->frame.header.blocksize-order, subframe->qlp_coeff, order, subframe->quantization_level, decoder->private_->output[channel]+order); else decoder->private_->local_lpc_restore_signal(decoder->private_->residual[channel], decoder->private_->frame.header.blocksize-order, subframe->qlp_coeff, order, subframe->quantization_level, decoder->private_->output[channel]+order); else @@ -2708,14 +2739,16 @@ FLAC__bool read_residual_partitioned_rice_(FLAC__StreamDecoder *decoder, unsigne if(decoder->private_->frame.header.blocksize < predictor_order) { send_error_to_client_(decoder, FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC); decoder->protected_->state = FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC; - return true; + /* We have received a potentially malicious bit stream. All we can do is error out to avoid a heap overflow. */ + return false; } } else { if(partition_samples < predictor_order) { send_error_to_client_(decoder, FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC); decoder->protected_->state = FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC; - return true; + /* We have received a potentially malicious bit stream. All we can do is error out to avoid a heap overflow. */ + return false; } } @@ -2732,7 +2765,7 @@ FLAC__bool read_residual_partitioned_rice_(FLAC__StreamDecoder *decoder, unsigne if(rice_parameter < pesc) { partitioned_rice_contents->raw_bits[partition] = 0; u = (partition_order == 0 || partition > 0)? partition_samples : partition_samples - predictor_order; - if(!decoder->private_->local_bitreader_read_rice_signed_block(decoder->private_->input, residual + sample, u, rice_parameter)) + if(!FLAC__bitreader_read_rice_signed_block(decoder->private_->input, residual + sample, u, rice_parameter)) return false; /* read_callback_ sets the state for us */ sample += u; } @@ -3074,12 +3107,7 @@ FLAC__bool seek_to_absolute_sample_(FLAC__StreamDecoder *decoder, FLAC__uint64 s return false; } #ifndef FLAC__INTEGER_ONLY_LIBRARY -#if defined _MSC_VER || defined __MINGW32__ - /* with VC++ you have to spoon feed it the casting */ - pos = (FLAC__int64)lower_bound + (FLAC__int64)((FLAC__double)(FLAC__int64)(target_sample - lower_bound_sample) / (FLAC__double)(FLAC__int64)(upper_bound_sample - lower_bound_sample) * (FLAC__double)(FLAC__int64)(upper_bound - lower_bound)) - approx_bytes_per_frame; -#else pos = (FLAC__int64)lower_bound + (FLAC__int64)((FLAC__double)(target_sample - lower_bound_sample) / (FLAC__double)(upper_bound_sample - lower_bound_sample) * (FLAC__double)(upper_bound - lower_bound)) - approx_bytes_per_frame; -#endif #else /* a little less accurate: */ if(upper_bound - lower_bound < 0xffffffff) @@ -3203,12 +3231,7 @@ FLAC__bool seek_to_absolute_sample_ogg_(FLAC__StreamDecoder *decoder, FLAC__uint } else { #ifndef FLAC__INTEGER_ONLY_LIBRARY -#if defined _MSC_VER || defined __MINGW32__ - /* with MSVC you have to spoon feed it the casting */ - pos = (FLAC__uint64)((FLAC__double)(FLAC__int64)(target_sample - left_sample) / (FLAC__double)(FLAC__int64)(right_sample - left_sample) * (FLAC__double)(FLAC__int64)(right_pos - left_pos)); -#else pos = (FLAC__uint64)((FLAC__double)(target_sample - left_sample) / (FLAC__double)(right_sample - left_sample) * (FLAC__double)(right_pos - left_pos)); -#endif #else /* a little less accurate: */ if ((target_sample-left_sample <= 0xffffffff) && (right_pos-left_pos <= 0xffffffff)) diff --git a/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/stream_encoder.c b/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/stream_encoder.c index 20e98da..f5eb90e 100644 --- a/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/stream_encoder.c +++ b/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/stream_encoder.c @@ -1,6 +1,6 @@ /* libFLAC - Free Lossless Audio Codec library * Copyright (C) 2000-2009 Josh Coalson - * Copyright (C) 2011-2013 Xiph.Org Foundation + * Copyright (C) 2011-2014 Xiph.Org Foundation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -30,7 +30,7 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#if HAVE_CONFIG_H +#ifdef HAVE_CONFIG_H # include #endif @@ -55,10 +55,10 @@ #include "include/private/ogg_helper.h" #include "include/private/ogg_mapping.h" #endif +#include "include/private/stream_encoder.h" #include "include/private/stream_encoder_framing.h" #include "include/private/window.h" #include "../alloc.h" -#include "../compat.h" /* Exact Rice codeword length calculation is off by default. The simple @@ -103,16 +103,18 @@ static struct CompressionLevels { unsigned min_residual_partition_order; unsigned max_residual_partition_order; unsigned rice_parameter_search_dist; + const char *apodization; } compression_levels_[] = { - { false, false, 0, 0, false, false, false, 0, 3, 0 }, - { true , true , 0, 0, false, false, false, 0, 3, 0 }, - { true , false, 0, 0, false, false, false, 0, 3, 0 }, - { false, false, 6, 0, false, false, false, 0, 4, 0 }, - { true , true , 8, 0, false, false, false, 0, 4, 0 }, - { true , false, 8, 0, false, false, false, 0, 5, 0 }, - { true , false, 8, 0, false, false, false, 0, 6, 0 }, - { true , false, 8, 0, false, false, true , 0, 6, 0 }, - { true , false, 12, 0, false, false, true , 0, 6, 0 } + { false, false, 0, 0, false, false, false, 0, 3, 0, "tukey(5e-1)" }, + { true , true , 0, 0, false, false, false, 0, 3, 0, "tukey(5e-1)" }, + { true , false, 0, 0, false, false, false, 0, 3, 0, "tukey(5e-1)" }, + { false, false, 6, 0, false, false, false, 0, 4, 0, "tukey(5e-1)" }, + { true , true , 8, 0, false, false, false, 0, 4, 0, "tukey(5e-1)" }, + { true , false, 8, 0, false, false, false, 0, 5, 0, "tukey(5e-1)" }, + { true , false, 8, 0, false, false, false, 0, 6, 0, "tukey(5e-1);partial_tukey(2)" }, + { true , false, 12, 0, false, false, false, 0, 6, 0, "tukey(5e-1);partial_tukey(2)" }, + { true , false, 12, 0, false, false, false, 0, 6, 0, "tukey(5e-1);partial_tukey(2);punchout_tukey(3)" } + /* here we use locale-independent 5e-1 instead of 0.5 or 0,5 */ }; @@ -342,10 +344,13 @@ typedef struct FLAC__StreamEncoderPrivate { unsigned current_frame_number; FLAC__MD5Context md5context; FLAC__CPUInfo cpuinfo; + void (*local_precompute_partition_info_sums)(const FLAC__int32 residual[], FLAC__uint64 abs_residual_partition_sums[], unsigned residual_samples, unsigned predictor_order, unsigned min_partition_order, unsigned max_partition_order, unsigned bps); #ifndef FLAC__INTEGER_ONLY_LIBRARY unsigned (*local_fixed_compute_best_predictor)(const FLAC__int32 data[], unsigned data_len, FLAC__float residual_bits_per_sample[FLAC__MAX_FIXED_ORDER+1]); + unsigned (*local_fixed_compute_best_predictor_wide)(const FLAC__int32 data[], unsigned data_len, FLAC__float residual_bits_per_sample[FLAC__MAX_FIXED_ORDER+1]); #else unsigned (*local_fixed_compute_best_predictor)(const FLAC__int32 data[], unsigned data_len, FLAC__fixedpoint residual_bits_per_sample[FLAC__MAX_FIXED_ORDER+1]); + unsigned (*local_fixed_compute_best_predictor_wide)(const FLAC__int32 data[], unsigned data_len, FLAC__fixedpoint residual_bits_per_sample[FLAC__MAX_FIXED_ORDER+1]); #endif #ifndef FLAC__INTEGER_ONLY_LIBRARY void (*local_lpc_compute_autocorrelation)(const FLAC__real data[], unsigned data_len, unsigned lag, FLAC__real autoc[]); @@ -873,7 +878,9 @@ static FLAC__StreamEncoderInitStatus init_stream_internal_( #ifndef FLAC__INTEGER_ONLY_LIBRARY encoder->private_->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation; #endif + encoder->private_->local_precompute_partition_info_sums = precompute_partition_info_sums_; encoder->private_->local_fixed_compute_best_predictor = FLAC__fixed_compute_best_predictor; + encoder->private_->local_fixed_compute_best_predictor_wide = FLAC__fixed_compute_best_predictor_wide; #ifndef FLAC__INTEGER_ONLY_LIBRARY encoder->private_->local_lpc_compute_residual_from_qlp_coefficients = FLAC__lpc_compute_residual_from_qlp_coefficients; encoder->private_->local_lpc_compute_residual_from_qlp_coefficients_64bit = FLAC__lpc_compute_residual_from_qlp_coefficients_wide; @@ -886,21 +893,23 @@ static FLAC__StreamEncoderInitStatus init_stream_internal_( # ifdef FLAC__CPU_IA32 FLAC__ASSERT(encoder->private_->cpuinfo.type == FLAC__CPUINFO_TYPE_IA32); # ifdef FLAC__HAS_NASM - if(encoder->private_->cpuinfo.data.ia32.sse) { + if(encoder->private_->cpuinfo.ia32.sse) { if(encoder->protected_->max_lpc_order < 4) encoder->private_->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation_asm_ia32_sse_lag_4; else if(encoder->protected_->max_lpc_order < 8) encoder->private_->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation_asm_ia32_sse_lag_8; else if(encoder->protected_->max_lpc_order < 12) encoder->private_->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation_asm_ia32_sse_lag_12; + else if(encoder->protected_->max_lpc_order < 16) + encoder->private_->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation_asm_ia32_sse_lag_16; else encoder->private_->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation_asm_ia32; } - else if(encoder->private_->cpuinfo.data.ia32._3dnow) - encoder->private_->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation_asm_ia32_3dnow; else encoder->private_->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation_asm_ia32; - if(encoder->private_->cpuinfo.data.ia32.mmx) { + + encoder->private_->local_lpc_compute_residual_from_qlp_coefficients_64bit = FLAC__lpc_compute_residual_from_qlp_coefficients_wide_asm_ia32; /* OPT_IA32: was really necessary for GCC < 4.9 */ + if(encoder->private_->cpuinfo.ia32.mmx) { encoder->private_->local_lpc_compute_residual_from_qlp_coefficients = FLAC__lpc_compute_residual_from_qlp_coefficients_asm_ia32; encoder->private_->local_lpc_compute_residual_from_qlp_coefficients_16bit = FLAC__lpc_compute_residual_from_qlp_coefficients_asm_ia32_mmx; } @@ -908,16 +917,137 @@ static FLAC__StreamEncoderInitStatus init_stream_internal_( encoder->private_->local_lpc_compute_residual_from_qlp_coefficients = FLAC__lpc_compute_residual_from_qlp_coefficients_asm_ia32; encoder->private_->local_lpc_compute_residual_from_qlp_coefficients_16bit = FLAC__lpc_compute_residual_from_qlp_coefficients_asm_ia32; } - if(encoder->private_->cpuinfo.data.ia32.mmx && encoder->private_->cpuinfo.data.ia32.cmov) + + if(encoder->private_->cpuinfo.ia32.mmx && encoder->private_->cpuinfo.ia32.cmov) encoder->private_->local_fixed_compute_best_predictor = FLAC__fixed_compute_best_predictor_asm_ia32_mmx_cmov; # endif /* FLAC__HAS_NASM */ -# endif /* FLAC__CPU_IA32 */ +# ifdef FLAC__HAS_X86INTRIN +# if defined FLAC__SSE_SUPPORTED + if(encoder->private_->cpuinfo.ia32.sse) { + if(encoder->protected_->max_lpc_order < 4) + encoder->private_->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation_intrin_sse_lag_4; + else if(encoder->protected_->max_lpc_order < 8) + encoder->private_->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation_intrin_sse_lag_8; + else if(encoder->protected_->max_lpc_order < 12) + encoder->private_->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation_intrin_sse_lag_12; + else if(encoder->protected_->max_lpc_order < 16) + encoder->private_->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation_intrin_sse_lag_16; + else + encoder->private_->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation; + } +# endif + +# ifdef FLAC__SSE2_SUPPORTED + if(encoder->private_->cpuinfo.ia32.sse2) { + encoder->private_->local_lpc_compute_residual_from_qlp_coefficients = FLAC__lpc_compute_residual_from_qlp_coefficients_intrin_sse2; + encoder->private_->local_lpc_compute_residual_from_qlp_coefficients_16bit = FLAC__lpc_compute_residual_from_qlp_coefficients_16_intrin_sse2; + } +# endif +# ifdef FLAC__SSE4_1_SUPPORTED + if(encoder->private_->cpuinfo.ia32.sse41) { + encoder->private_->local_lpc_compute_residual_from_qlp_coefficients = FLAC__lpc_compute_residual_from_qlp_coefficients_intrin_sse41; + encoder->private_->local_lpc_compute_residual_from_qlp_coefficients_64bit = FLAC__lpc_compute_residual_from_qlp_coefficients_wide_intrin_sse41; + } +# endif +# ifdef FLAC__AVX2_SUPPORTED + if(encoder->private_->cpuinfo.ia32.avx2) { + encoder->private_->local_lpc_compute_residual_from_qlp_coefficients_16bit = FLAC__lpc_compute_residual_from_qlp_coefficients_16_intrin_avx2; + encoder->private_->local_lpc_compute_residual_from_qlp_coefficients = FLAC__lpc_compute_residual_from_qlp_coefficients_intrin_avx2; + encoder->private_->local_lpc_compute_residual_from_qlp_coefficients_64bit = FLAC__lpc_compute_residual_from_qlp_coefficients_wide_intrin_avx2; + } +# endif + +# ifdef FLAC__SSE2_SUPPORTED + if (encoder->private_->cpuinfo.ia32.sse2) { + encoder->private_->local_fixed_compute_best_predictor = FLAC__fixed_compute_best_predictor_intrin_sse2; + encoder->private_->local_fixed_compute_best_predictor_wide = FLAC__fixed_compute_best_predictor_wide_intrin_sse2; + } +# endif +# ifdef FLAC__SSSE3_SUPPORTED + if (encoder->private_->cpuinfo.ia32.ssse3) { + encoder->private_->local_fixed_compute_best_predictor = FLAC__fixed_compute_best_predictor_intrin_ssse3; + encoder->private_->local_fixed_compute_best_predictor_wide = FLAC__fixed_compute_best_predictor_wide_intrin_ssse3; + } +# endif +# endif /* FLAC__HAS_X86INTRIN */ +# elif defined FLAC__CPU_X86_64 + FLAC__ASSERT(encoder->private_->cpuinfo.type == FLAC__CPUINFO_TYPE_X86_64); +# ifdef FLAC__HAS_X86INTRIN +# ifdef FLAC__SSE_SUPPORTED + if(encoder->protected_->max_lpc_order < 4) + encoder->private_->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation_intrin_sse_lag_4; + else if(encoder->protected_->max_lpc_order < 8) + encoder->private_->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation_intrin_sse_lag_8; + else if(encoder->protected_->max_lpc_order < 12) + encoder->private_->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation_intrin_sse_lag_12; + else if(encoder->protected_->max_lpc_order < 16) + encoder->private_->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation_intrin_sse_lag_16; +# endif + +# ifdef FLAC__SSE2_SUPPORTED + encoder->private_->local_lpc_compute_residual_from_qlp_coefficients_16bit = FLAC__lpc_compute_residual_from_qlp_coefficients_16_intrin_sse2; +# endif +# ifdef FLAC__SSE4_1_SUPPORTED + if(encoder->private_->cpuinfo.x86.sse41) { + encoder->private_->local_lpc_compute_residual_from_qlp_coefficients = FLAC__lpc_compute_residual_from_qlp_coefficients_intrin_sse41; + } +# endif +# ifdef FLAC__AVX2_SUPPORTED + if(encoder->private_->cpuinfo.x86.avx2) { + encoder->private_->local_lpc_compute_residual_from_qlp_coefficients_16bit = FLAC__lpc_compute_residual_from_qlp_coefficients_16_intrin_avx2; + encoder->private_->local_lpc_compute_residual_from_qlp_coefficients = FLAC__lpc_compute_residual_from_qlp_coefficients_intrin_avx2; + encoder->private_->local_lpc_compute_residual_from_qlp_coefficients_64bit = FLAC__lpc_compute_residual_from_qlp_coefficients_wide_intrin_avx2; + } +# endif + +# ifdef FLAC__SSE2_SUPPORTED + encoder->private_->local_fixed_compute_best_predictor = FLAC__fixed_compute_best_predictor_intrin_sse2; + encoder->private_->local_fixed_compute_best_predictor_wide = FLAC__fixed_compute_best_predictor_wide_intrin_sse2; +# endif +# ifdef FLAC__SSSE3_SUPPORTED + if (encoder->private_->cpuinfo.x86.ssse3) { + encoder->private_->local_fixed_compute_best_predictor = FLAC__fixed_compute_best_predictor_intrin_ssse3; + encoder->private_->local_fixed_compute_best_predictor_wide = FLAC__fixed_compute_best_predictor_wide_intrin_ssse3; + } +# endif +# endif /* FLAC__HAS_X86INTRIN */ +# endif /* FLAC__CPU_... */ } # endif /* !FLAC__NO_ASM */ #endif /* !FLAC__INTEGER_ONLY_LIBRARY */ +#if !defined FLAC__NO_ASM && defined FLAC__HAS_X86INTRIN + if(encoder->private_->cpuinfo.use_asm) { +# if defined FLAC__CPU_IA32 +# ifdef FLAC__SSE2_SUPPORTED + if(encoder->private_->cpuinfo.ia32.sse2) + encoder->private_->local_precompute_partition_info_sums = FLAC__precompute_partition_info_sums_intrin_sse2; +# endif +# ifdef FLAC__SSSE3_SUPPORTED + if(encoder->private_->cpuinfo.ia32.ssse3) + encoder->private_->local_precompute_partition_info_sums = FLAC__precompute_partition_info_sums_intrin_ssse3; +# endif +# ifdef FLAC__AVX2_SUPPORTED + if(encoder->private_->cpuinfo.ia32.avx2) + encoder->private_->local_precompute_partition_info_sums = FLAC__precompute_partition_info_sums_intrin_avx2; +# endif +# elif defined FLAC__CPU_X86_64 +# ifdef FLAC__SSE2_SUPPORTED + encoder->private_->local_precompute_partition_info_sums = FLAC__precompute_partition_info_sums_intrin_sse2; +# endif +# ifdef FLAC__SSSE3_SUPPORTED + if(encoder->private_->cpuinfo.x86.ssse3) + encoder->private_->local_precompute_partition_info_sums = FLAC__precompute_partition_info_sums_intrin_ssse3; +# endif +# ifdef FLAC__AVX2_SUPPORTED + if(encoder->private_->cpuinfo.x86.avx2) + encoder->private_->local_precompute_partition_info_sums = FLAC__precompute_partition_info_sums_intrin_avx2; +# endif +# endif /* FLAC__CPU_... */ + } +#endif /* !FLAC__NO_ASM && FLAC__HAS_X86INTRIN */ /* finally override based on wide-ness if necessary */ if(encoder->private_->use_wide_by_block) { - encoder->private_->local_fixed_compute_best_predictor = FLAC__fixed_compute_best_predictor_wide; + encoder->private_->local_fixed_compute_best_predictor = encoder->private_->local_fixed_compute_best_predictor_wide; } /* set state to OK; from here on, errors are fatal and we'll override the state then */ @@ -1152,7 +1282,7 @@ static FLAC__StreamEncoderInitStatus init_FILE_internal_( FLAC__StreamEncoder *encoder, FILE *file, FLAC__StreamEncoderProgressCallback progress_callback, - void * /*client_data*/, + void *client_data, FLAC__bool is_ogg ) { @@ -1178,6 +1308,13 @@ static FLAC__StreamEncoderInitStatus init_FILE_internal_( if(file == stdout) file = get_binary_stdout_(); /* just to be safe */ +#ifdef _WIN32 + /* + * Windows can suffer quite badly from disk fragmentation. This can be + * reduced significantly by setting the output buffer size to be 10MB. + */ + setvbuf(file, NULL, _IOFBF, 10*1024*1024); +#endif encoder->private_->file = file; encoder->private_->progress_callback = progress_callback; @@ -1447,11 +1584,10 @@ FLAC_API FLAC__bool FLAC__stream_encoder_set_compression_level(FLAC__StreamEncod ok &= FLAC__stream_encoder_set_do_mid_side_stereo (encoder, compression_levels_[value].do_mid_side_stereo); ok &= FLAC__stream_encoder_set_loose_mid_side_stereo (encoder, compression_levels_[value].loose_mid_side_stereo); #ifndef FLAC__INTEGER_ONLY_LIBRARY -#if 0 - /* was: */ +#if 1 ok &= FLAC__stream_encoder_set_apodization (encoder, compression_levels_[value].apodization); - /* but it's too hard to specify the string in a locale-specific way */ #else + /* equivalent to -A tukey(0.5) */ encoder->protected_->num_apodizations = 1; encoder->protected_->apodizations[0].type = FLAC__APODIZATION_TUKEY; encoder->protected_->apodizations[0].parameters.tukey.p = 0.5; @@ -1555,6 +1691,48 @@ FLAC_API FLAC__bool FLAC__stream_encoder_set_apodization(FLAC__StreamEncoder *en encoder->protected_->apodizations[encoder->protected_->num_apodizations++].type = FLAC__APODIZATION_TUKEY; } } + else if(n>15 && 0 == strncmp("partial_tukey(" , specification, 14)) { + FLAC__int32 tukey_parts = (FLAC__int32)strtod(specification+14, 0); + const char *si_1 = strchr(specification, '/'); + FLAC__real overlap = si_1?flac_min((FLAC__real)strtod(si_1+1, 0),0.99f):0.1f; + FLAC__real overlap_units = 1.0f/(1.0f - overlap) - 1.0f; + const char *si_2 = strchr((si_1?(si_1+1):specification), '/'); + FLAC__real tukey_p = si_2?(FLAC__real)strtod(si_2+1, 0):0.2f; + + if (tukey_parts <= 1) { + encoder->protected_->apodizations[encoder->protected_->num_apodizations].parameters.tukey.p = tukey_p; + encoder->protected_->apodizations[encoder->protected_->num_apodizations++].type = FLAC__APODIZATION_TUKEY; + }else if (encoder->protected_->num_apodizations + tukey_parts < 32){ + FLAC__int32 m; + for(m = 0; m < tukey_parts; m++){ + encoder->protected_->apodizations[encoder->protected_->num_apodizations].parameters.multiple_tukey.p = tukey_p; + encoder->protected_->apodizations[encoder->protected_->num_apodizations].parameters.multiple_tukey.start = m/(tukey_parts+overlap_units); + encoder->protected_->apodizations[encoder->protected_->num_apodizations].parameters.multiple_tukey.end = (m+1+overlap_units)/(tukey_parts+overlap_units); + encoder->protected_->apodizations[encoder->protected_->num_apodizations++].type = FLAC__APODIZATION_PARTIAL_TUKEY; + } + } + } + else if(n>16 && 0 == strncmp("punchout_tukey(" , specification, 15)) { + FLAC__int32 tukey_parts = (FLAC__int32)strtod(specification+15, 0); + const char *si_1 = strchr(specification, '/'); + FLAC__real overlap = si_1?flac_min((FLAC__real)strtod(si_1+1, 0),0.99f):0.2f; + FLAC__real overlap_units = 1.0f/(1.0f - overlap) - 1.0f; + const char *si_2 = strchr((si_1?(si_1+1):specification), '/'); + FLAC__real tukey_p = si_2?(FLAC__real)strtod(si_2+1, 0):0.2f; + + if (tukey_parts <= 1) { + encoder->protected_->apodizations[encoder->protected_->num_apodizations].parameters.tukey.p = tukey_p; + encoder->protected_->apodizations[encoder->protected_->num_apodizations++].type = FLAC__APODIZATION_TUKEY; + }else if (encoder->protected_->num_apodizations + tukey_parts < 32){ + FLAC__int32 m; + for(m = 0; m < tukey_parts; m++){ + encoder->protected_->apodizations[encoder->protected_->num_apodizations].parameters.multiple_tukey.p = tukey_p; + encoder->protected_->apodizations[encoder->protected_->num_apodizations].parameters.multiple_tukey.start = m/(tukey_parts+overlap_units); + encoder->protected_->apodizations[encoder->protected_->num_apodizations].parameters.multiple_tukey.end = (m+1+overlap_units)/(tukey_parts+overlap_units); + encoder->protected_->apodizations[encoder->protected_->num_apodizations++].type = FLAC__APODIZATION_PUNCHOUT_TUKEY; + } + } + } else if(n==5 && 0 == strncmp("welch" , specification, n)) encoder->protected_->apodizations[encoder->protected_->num_apodizations++].type = FLAC__APODIZATION_WELCH; if (encoder->protected_->num_apodizations == 32) @@ -2236,8 +2414,8 @@ FLAC__bool resize_buffers_(FLAC__StreamEncoder *encoder, unsigned new_blocksize) ok = true; - /* WATCHOUT: FLAC__lpc_compute_residual_from_qlp_coefficients_asm_ia32_mmx() - * requires that the input arrays (in our case the integer signals) + /* WATCHOUT: FLAC__lpc_compute_residual_from_qlp_coefficients_asm_ia32_mmx() and ..._intrin_sse2() + * require that the input arrays (in our case the integer signals) * have a buffer of up to 3 zeroes in front (at negative indices) for * alignment purposes; we use 4 in front to keep the data well-aligned. */ @@ -2334,6 +2512,12 @@ FLAC__bool resize_buffers_(FLAC__StreamEncoder *encoder, unsigned new_blocksize) case FLAC__APODIZATION_TUKEY: FLAC__window_tukey(encoder->private_->window[i], new_blocksize, encoder->protected_->apodizations[i].parameters.tukey.p); break; + case FLAC__APODIZATION_PARTIAL_TUKEY: + FLAC__window_partial_tukey(encoder->private_->window[i], new_blocksize, encoder->protected_->apodizations[i].parameters.multiple_tukey.p, encoder->protected_->apodizations[i].parameters.multiple_tukey.start, encoder->protected_->apodizations[i].parameters.multiple_tukey.end); + break; + case FLAC__APODIZATION_PUNCHOUT_TUKEY: + FLAC__window_punchout_tukey(encoder->private_->window[i], new_blocksize, encoder->protected_->apodizations[i].parameters.multiple_tukey.p, encoder->protected_->apodizations[i].parameters.multiple_tukey.start, encoder->protected_->apodizations[i].parameters.multiple_tukey.end); + break; case FLAC__APODIZATION_WELCH: FLAC__window_welch(encoder->private_->window[i], new_blocksize); break; @@ -3165,7 +3349,7 @@ FLAC__bool process_subframe_( #endif #ifndef FLAC__INTEGER_ONLY_LIBRARY FLAC__double lpc_residual_bits_per_sample; - FLAC__real autoc[FLAC__MAX_LPC_ORDER+1]; /* WATCHOUT: the size is important even though encoder->protected_->max_lpc_order might be less; some asm routines need all the space */ + FLAC__real autoc[FLAC__MAX_LPC_ORDER+1]; /* WATCHOUT: the size is important even though encoder->protected_->max_lpc_order might be less; some asm and x86 intrinsic routines need all the space */ FLAC__double lpc_error[FLAC__MAX_LPC_ORDER]; unsigned min_lpc_order, max_lpc_order, lpc_order; unsigned min_qlp_coeff_precision, max_qlp_coeff_precision, qlp_coeff_precision; @@ -3318,9 +3502,9 @@ FLAC__bool process_subframe_( } if(encoder->protected_->do_qlp_coeff_prec_search) { min_qlp_coeff_precision = FLAC__MIN_QLP_COEFF_PRECISION; - /* try to ensure a 32-bit datapath throughout for 16bps(+1bps for side channel) or less */ - if(subframe_bps <= 17) { - max_qlp_coeff_precision = flac_min(32 - subframe_bps - lpc_order, FLAC__MAX_QLP_COEFF_PRECISION); + /* try to keep qlp coeff precision such that only 32-bit math is required for decode of <=16bps streams */ + if(subframe_bps <= 16) { + max_qlp_coeff_precision = flac_min(32 - subframe_bps - FLAC__bitmath_ilog2(lpc_order), FLAC__MAX_QLP_COEFF_PRECISION); max_qlp_coeff_precision = flac_max(max_qlp_coeff_precision, min_qlp_coeff_precision); } else @@ -3556,7 +3740,7 @@ unsigned evaluate_lpc_subframe_( FLAC__EntropyCodingMethod_PartitionedRiceContents *partitioned_rice_contents ) { - FLAC__int32 qlp_coeff[FLAC__MAX_LPC_ORDER]; + FLAC__int32 qlp_coeff[FLAC__MAX_LPC_ORDER]; /* WATCHOUT: the size is important; some x86 intrinsic routines need more than lpc order elements */ unsigned i, residual_bits, estimate; int quantization, ret; const unsigned residual_samples = blocksize - order; @@ -3671,7 +3855,7 @@ unsigned find_best_partition_order_( max_partition_order = FLAC__format_get_max_rice_partition_order_from_blocksize_limited_max_and_predictor_order(max_partition_order, blocksize, predictor_order); min_partition_order = flac_min(min_partition_order, max_partition_order); - precompute_partition_info_sums_(residual, abs_residual_partition_sums, residual_samples, predictor_order, min_partition_order, max_partition_order, bps); + private_->local_precompute_partition_info_sums(residual, abs_residual_partition_sums, residual_samples, predictor_order, min_partition_order, max_partition_order, bps); if(do_escape_coding) precompute_partition_info_escapes_(residual, raw_bits_per_partition, residual_samples, predictor_order, min_partition_order, max_partition_order); @@ -3743,17 +3927,6 @@ unsigned find_best_partition_order_( return best_residual_bits; } -#if defined(FLAC__CPU_IA32) && !defined FLAC__NO_ASM && defined FLAC__HAS_NASM -extern void precompute_partition_info_sums_32bit_asm_ia32_( - const FLAC__int32 residual[], - FLAC__uint64 abs_residual_partition_sums[], - unsigned blocksize, - unsigned predictor_order, - unsigned min_partition_order, - unsigned max_partition_order -); -#endif - void precompute_partition_info_sums_( const FLAC__int32 residual[], FLAC__uint64 abs_residual_partition_sums[], @@ -3769,21 +3942,12 @@ void precompute_partition_info_sums_( FLAC__ASSERT(default_partition_samples > predictor_order); -#if defined(FLAC__CPU_IA32) && !defined FLAC__NO_ASM && defined FLAC__HAS_NASM - /* slightly pessimistic but still catches all common cases */ - /* WATCHOUT: "+ bps" is an assumption that the average residual magnitude will not be more than "bps" bits */ - if(FLAC__bitmath_ilog2(default_partition_samples) + bps < 32) { - precompute_partition_info_sums_32bit_asm_ia32_(residual, abs_residual_partition_sums, residual_samples + predictor_order, predictor_order, min_partition_order, max_partition_order); - return; - } -#endif - /* first do max_partition_order */ { unsigned partition, residual_sample, end = (unsigned)(-(int)predictor_order); - /* slightly pessimistic but still catches all common cases */ - /* WATCHOUT: "+ bps" is an assumption that the average residual magnitude will not be more than "bps" bits */ - if(FLAC__bitmath_ilog2(default_partition_samples) + bps < 32) { + /* WATCHOUT: "+ bps + FLAC__MAX_EXTRA_RESIDUAL_BPS" is the maximum + * assumed size of the average residual magnitude */ + if(FLAC__bitmath_ilog2(default_partition_samples) + bps + FLAC__MAX_EXTRA_RESIDUAL_BPS < 32) { FLAC__uint32 abs_residual_partition_sum; for(partition = residual_sample = 0; partition < partitions; partition++) { @@ -4027,8 +4191,35 @@ FLAC__bool set_partitioned_rice_( * in the partition, so the actual mean is * mean/partition_samples */ +#if 0 /* old simple code */ for(rice_parameter = 0, k = partition_samples; k < mean; rice_parameter++, k <<= 1) ; +#else +#if defined FLAC__CPU_X86_64 /* and other 64-bit arch, too */ + if(mean <= 0x80000000/512) { /* 512: more or less optimal for both 16- and 24-bit input */ +#else + if(mean <= 0x80000000/8) { /* 32-bit arch: use 32-bit math if possible */ +#endif + FLAC__uint32 k2, mean2 = (FLAC__uint32) mean; + rice_parameter = 0; k2 = partition_samples; + while(k2*8 < mean2) { /* requires: mean <= (2^31)/8 */ + rice_parameter += 4; k2 <<= 4; /* tuned for 16-bit input */ + } + while(k2 < mean2) { /* requires: mean <= 2^31 */ + rice_parameter++; k2 <<= 1; + } + } + else { + rice_parameter = 0; k = partition_samples; + if(mean <= FLAC__U64L(0x8000000000000000)/128) /* usually mean is _much_ smaller than this value */ + while(k*128 < mean) { /* requires: mean <= (2^63)/128 */ + rice_parameter += 8; k <<= 8; /* tuned for 24-bit input */ + } + while(k < mean) { /* requires: mean <= 2^63 */ + rice_parameter++; k <<= 1; + } + } +#endif if(rice_parameter >= rice_parameter_limit) { #ifdef DEBUG_VERBOSE fprintf(stderr, "clipping rice_parameter (%u -> %u) @6\n", rice_parameter, rice_parameter_limit - 1); diff --git a/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/stream_encoder_framing.c b/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/stream_encoder_framing.c index 41efca5..6d57006 100644 --- a/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/stream_encoder_framing.c +++ b/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/stream_encoder_framing.c @@ -1,6 +1,6 @@ /* libFLAC - Free Lossless Audio Codec library * Copyright (C) 2000-2009 Josh Coalson - * Copyright (C) 2011-2013 Xiph.Org Foundation + * Copyright (C) 2011-2014 Xiph.Org Foundation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -30,7 +30,7 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#if HAVE_CONFIG_H +#ifdef HAVE_CONFIG_H # include #endif diff --git a/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/window_flac.c b/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/window_flac.c index c99d5b4..dc341a6 100644 --- a/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/window_flac.c +++ b/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/window_flac.c @@ -1,6 +1,6 @@ /* libFLAC - Free Lossless Audio Codec library * Copyright (C) 2006-2009 Josh Coalson - * Copyright (C) 2011-2013 Xiph.Org Foundation + * Copyright (C) 2011-2014 Xiph.Org Foundation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -30,7 +30,7 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#if HAVE_CONFIG_H +#ifdef HAVE_CONFIG_H # include #endif @@ -41,11 +41,6 @@ #ifndef FLAC__INTEGER_ONLY_LIBRARY -#ifndef M_PI -/* math.h in VC++ doesn't seem to have this (how Microsoft is that?) */ -#define M_PI 3.14159265358979323846 -#endif - void FLAC__window_bartlett(FLAC__real *window, const FLAC__int32 L) { @@ -62,7 +57,7 @@ void FLAC__window_bartlett(FLAC__real *window, const FLAC__int32 L) for (n = 0; n <= L/2-1; n++) window[n] = 2.0f * n / (float)N; for (; n <= N; n++) - window[n] = 2.0f - 2.0f * (N-n) / (float)N; + window[n] = 2.0f - 2.0f * n / (float)N; } } @@ -72,7 +67,7 @@ void FLAC__window_bartlett_hann(FLAC__real *window, const FLAC__int32 L) FLAC__int32 n; for (n = 0; n < L; n++) - window[n] = (FLAC__real)(0.62f - 0.48f * fabs((float)n/(float)N+0.5f) + 0.38f * cos(2.0f * M_PI * ((float)n/(float)N+0.5f))); + window[n] = (FLAC__real)(0.62f - 0.48f * fabs((float)n/(float)N-0.5f) - 0.38f * cos(2.0f * M_PI * ((float)n/(float)N))); } void FLAC__window_blackman(FLAC__real *window, const FLAC__int32 L) @@ -177,16 +172,16 @@ void FLAC__window_triangle(FLAC__real *window, const FLAC__int32 L) FLAC__int32 n; if (L & 1) { - for (n = 1; n <= L+1/2; n++) + for (n = 1; n <= (L+1)/2; n++) window[n-1] = 2.0f * n / ((float)L + 1.0f); for (; n <= L; n++) - window[n-1] = - (float)(2 * (L - n + 1)) / ((float)L + 1.0f); + window[n-1] = (float)(2 * (L - n + 1)) / ((float)L + 1.0f); } else { for (n = 1; n <= L/2; n++) - window[n-1] = 2.0f * n / (float)L; + window[n-1] = 2.0f * n / ((float)L + 1.0f); for (; n <= L; n++) - window[n-1] = ((float)(2 * (L - n)) + 1.0f) / (float)L; + window[n-1] = (float)(2 * (L - n + 1)) / ((float)L + 1.0f); } } @@ -211,6 +206,66 @@ void FLAC__window_tukey(FLAC__real *window, const FLAC__int32 L, const FLAC__rea } } +void FLAC__window_partial_tukey(FLAC__real *window, const FLAC__int32 L, const FLAC__real p, const FLAC__real start, const FLAC__real end) +{ + const FLAC__int32 start_n = (FLAC__int32)(start * L); + const FLAC__int32 end_n = (FLAC__int32)(end * L); + const FLAC__int32 N = end_n - start_n; + FLAC__int32 Np, n, i; + + if (p <= 0.0f) + FLAC__window_partial_tukey(window, L, 0.05f, start, end); + else if (p >= 1.0f) + FLAC__window_partial_tukey(window, L, 0.95f, start, end); + else { + + Np = (FLAC__int32)(p / 2.0f * N); + + for (n = 0; n < start_n && n < L; n++) + window[n] = 0.0f; + for (i = 1; n < (start_n+Np) && n < L; n++, i++) + window[n] = (FLAC__real)(0.5f - 0.5f * cos(M_PI * i / Np)); + for (; n < (end_n-Np) && n < L; n++) + window[n] = 1.0f; + for (i = Np; n < end_n && n < L; n++, i--) + window[n] = (FLAC__real)(0.5f - 0.5f * cos(M_PI * i / Np)); + for (; n < L; n++) + window[n] = 0.0f; + } +} + +void FLAC__window_punchout_tukey(FLAC__real *window, const FLAC__int32 L, const FLAC__real p, const FLAC__real start, const FLAC__real end) +{ + const FLAC__int32 start_n = (FLAC__int32)(start * L); + const FLAC__int32 end_n = (FLAC__int32)(end * L); + FLAC__int32 Ns, Ne, n, i; + + if (p <= 0.0f) + FLAC__window_punchout_tukey(window, L, 0.05f, start, end); + else if (p >= 1.0f) + FLAC__window_punchout_tukey(window, L, 0.95f, start, end); + else { + + Ns = (FLAC__int32)(p / 2.0f * start_n); + Ne = (FLAC__int32)(p / 2.0f * (L - end_n)); + + for (n = 0, i = 1; n < Ns && n < L; n++, i++) + window[n] = (FLAC__real)(0.5f - 0.5f * cos(M_PI * i / Ns)); + for (; n < start_n-Ns && n < L; n++) + window[n] = 1.0f; + for (i = Ns; n < start_n && n < L; n++, i--) + window[n] = (FLAC__real)(0.5f - 0.5f * cos(M_PI * i / Ns)); + for (; n < end_n && n < L; n++) + window[n] = 0.0f; + for (i = 1; n < end_n+Ne && n < L; n++, i++) + window[n] = (FLAC__real)(0.5f - 0.5f * cos(M_PI * i / Ne)); + for (; n < L - (Ne) && n < L; n++) + window[n] = 1.0f; + for (i = Ne; n < L; n++, i--) + window[n] = (FLAC__real)(0.5f - 0.5f * cos(M_PI * i / Ne)); + } +} + void FLAC__window_welch(FLAC__real *window, const FLAC__int32 L) { const FLAC__int32 N = L - 1; diff --git a/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/metadata.h b/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/metadata.h index 18bf6d1..02cfc32 100644 --- a/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/metadata.h +++ b/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/metadata.h @@ -1,6 +1,6 @@ /* libFLAC - Free Lossless Audio Codec library * Copyright (C) 2001-2009 Josh Coalson - * Copyright (C) 2011-2013 Xiph.Org Foundation + * Copyright (C) 2011-2014 Xiph.Org Foundation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -500,7 +500,7 @@ FLAC_API FLAC__MetadataType FLAC__metadata_simple_iterator_get_block_type(const * \retval unsigned * The length of the metadata block at the current iterator position. * The is same length as that in the - * metadata block header, + * metadata block header, * i.e. the length of the metadata body that follows the header. */ FLAC_API unsigned FLAC__metadata_simple_iterator_get_block_length(const FLAC__Metadata_SimpleIterator *iterator); diff --git a/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/ordinals.h b/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/ordinals.h index c9466c5..0bab9c2 100644 --- a/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/ordinals.h +++ b/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/ordinals.h @@ -1,6 +1,6 @@ /* libFLAC - Free Lossless Audio Codec library * Copyright (C) 2000-2009 Josh Coalson - * Copyright (C) 2011-2013 Xiph.Org Foundation + * Copyright (C) 2011-2014 Xiph.Org Foundation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/stream_decoder.h b/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/stream_decoder.h index be402c8..50cd754 100644 --- a/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/stream_decoder.h +++ b/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/stream_decoder.h @@ -1,6 +1,6 @@ /* libFLAC - Free Lossless Audio Codec library * Copyright (C) 2000-2009 Josh Coalson - * Copyright (C) 2011-2013 Xiph.Org Foundation + * Copyright (C) 2011-2014 Xiph.Org Foundation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/stream_encoder.h b/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/stream_encoder.h index f0fcab5..646efb7 100644 --- a/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/stream_encoder.h +++ b/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/stream_encoder.h @@ -1,6 +1,6 @@ /* libFLAC - Free Lossless Audio Codec library * Copyright (C) 2000-2009 Josh Coalson - * Copyright (C) 2011-2013 Xiph.Org Foundation + * Copyright (C) 2011-2014 Xiph.Org Foundation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -830,28 +830,28 @@ FLAC_API FLAC__bool FLAC__stream_encoder_set_sample_rate(FLAC__StreamEncoder *en * The actual values set for each level are: * * - * + * + * + * + * + * + * + * + * + * + * + * * - * - * - * - * - * - * - * - * - * + * + * + * + * + * + * + * + * + * *
level - * do mid-side stereo - * loose mid-side stereo - * apodization - * max lpc order - * qlp coeff precision - * qlp coeff prec search - * escape coding - * exhaustive model search - * min residual partition order - * max residual partition order - * rice parameter search dist + * leveldo mid-side stereoloose mid-side stereoapodizationmax lpc orderqlp coeff precisionqlp coeff prec searchescape codingexhaustive model searchmin residual partition ordermax residual partition orderrice parameter search dist
0 false false tukey(0.5) 0 0 false false false 0 3 0
1 true true tukey(0.5) 0 0 false false false 0 3 0
2 true false tukey(0.5) 0 0 false false false 0 3 0
3 false false tukey(0.5) 6 0 false false false 0 4 0
4 true true tukey(0.5) 8 0 false false false 0 4 0
5 true false tukey(0.5) 8 0 false false false 0 5 0
6 true false tukey(0.5) 8 0 false false false 0 6 0
7 true false tukey(0.5) 8 0 false false true 0 6 0
8 true false tukey(0.5) 12 0 false false true 0 6 0
0 false false tukey(0.5) 0 0 false false false 0 3 0
1 true true tukey(0.5) 0 0 false false false 0 3 0
2 true false tukey(0.5) 0 0 false false false 0 3 0
3 false false tukey(0.5) 6 0 false false false 0 4 0
4 true true tukey(0.5) 8 0 false false false 0 4 0
5 true false tukey(0.5) 8 0 false false false 0 5 0
6 true false tukey(0.5);partial_tukey(2) 8 0 false false false 0 6 0
7 true false tukey(0.5);partial_tukey(2) 12 0 false false false 0 6 0
8 true false tukey(0.5);partial_tukey(2);punchout_tukey(3) 12 0 false false false 0 6 0
* * \default \c 5 @@ -920,7 +920,8 @@ FLAC_API FLAC__bool FLAC__stream_encoder_set_loose_mid_side_stereo(FLAC__StreamE * The available functions are \c bartlett, \c bartlett_hann, * \c blackman, \c blackman_harris_4term_92db, \c connes, \c flattop, * \c gauss(STDDEV), \c hamming, \c hann, \c kaiser_bessel, \c nuttall, - * \c rectangle, \c triangle, \c tukey(P), \c welch. + * \c rectangle, \c triangle, \c tukey(P), \c partial_tukey(n[/ov[/P]]), + * \c punchout_tukey(n[/ov[/P]]), \c welch. * * For \c gauss(STDDEV), STDDEV specifies the standard deviation * (0 (mb.getData()); - - while (bytesLeft > 0) - { - const String tag (CharPointer_UTF8 (data), - CharPointer_UTF8 (data + bytesLeft)); - - if (tag.isNotEmpty()) - tagsArray.add (data); - - const int numBytesInTag = genres.contains (tag) ? 118 : 50; - data += numBytesInTag; - bytesLeft -= numBytesInTag; + return CharacterFunctions::isLetterOrDigit (d[0]) && CharacterFunctions::isUpperCase (d[0]) + && CharacterFunctions::isLetterOrDigit (d[1]) && CharacterFunctions::isLowerCase (d[1]) + && CharacterFunctions::isLetterOrDigit (d[2]) && CharacterFunctions::isLowerCase (d[2]); } - return tagsArray.joinIntoString (";"); + static bool isAppleGenre (const String& tag) noexcept + { + static const char* appleGenres[] = + { + "Rock/Blues", + "Electronic/Dance", + "Jazz", + "Urban", + "World/Ethnic", + "Cinematic/New Age", + "Orchestral", + "Country/Folk", + "Experimental", + "Other Genre" + }; + + for (int i = 0; i < numElementsInArray (appleGenres); ++i) + if (tag == appleGenres[i]) + return true; + + return false; + } + + static String read (InputStream& input, const uint32 length) + { + MemoryBlock mb; + input.skipNextBytes (4); + input.readIntoMemoryBlock (mb, (ssize_t) length - 4); + + StringArray tagsArray; + + const char* data = static_cast (mb.getData()); + const char* dataEnd = data + mb.getSize(); + + while (data < dataEnd) + { + bool isGenre = false; + + if (isValidTag (data)) + { + const String tag = String (CharPointer_UTF8 (data), CharPointer_UTF8 (dataEnd)); + isGenre = isAppleGenre (tag); + tagsArray.add (tag); + } + + data += isGenre ? 118 : 50; + + if (data[0] == 0) + { + if (data + 52 < dataEnd && isValidTag (data + 50)) data += 50; + else if (data + 120 < dataEnd && isValidTag (data + 118)) data += 118; + else if (data + 170 < dataEnd && isValidTag (data + 168)) data += 168; + } + } + + return tagsArray.joinIntoString (";"); + } } //============================================================================== @@ -316,10 +341,10 @@ namespace AiffFileHelpers out.writeByte ((char) labelLength + 1); out.write (label.toUTF8(), labelLength); out.writeByte (0); - } - if ((out.getDataSize() & 1) != 0) - out.writeByte (0); + if ((out.getDataSize() & 1) != 0) + out.writeByte (0); + } } } } @@ -518,7 +543,7 @@ public: else if (type == chunkName ("cate")) { metadataValues.set (AiffAudioFormat::appleTag, - AiffFileHelpers::readCATEChunk (*input, length));; + AiffFileHelpers::CATEChunk::read (*input, length)); } else if ((hasGotVer && hasGotData && hasGotType) || chunkEnd < input->getPosition() @@ -821,12 +846,54 @@ public: return true; } - void readMaxLevels (int64 startSampleInFile, int64 numSamples, - float& min0, float& max0, float& min1, float& max1) + void getSample (int64 sample, float* result) const noexcept override + { + const int num = (int) numChannels; + + if (map == nullptr || ! mappedSection.contains (sample)) + { + jassertfalse; // you must make sure that the window contains all the samples you're going to attempt to read. + + zeromem (result, sizeof (float) * (size_t) num); + return; + } + + float** dest = &result; + const void* source = sampleToPointer (sample); + + if (littleEndian) + { + switch (bitsPerSample) + { + case 8: ReadHelper::read (dest, 0, 1, source, 1, num); break; + case 16: ReadHelper::read (dest, 0, 1, source, 1, num); break; + case 24: ReadHelper::read (dest, 0, 1, source, 1, num); break; + case 32: if (usesFloatingPointData) ReadHelper::read (dest, 0, 1, source, 1, num); + else ReadHelper::read (dest, 0, 1, source, 1, num); break; + default: jassertfalse; break; + } + } + else + { + switch (bitsPerSample) + { + case 8: ReadHelper::read (dest, 0, 1, source, 1, num); break; + case 16: ReadHelper::read (dest, 0, 1, source, 1, num); break; + case 24: ReadHelper::read (dest, 0, 1, source, 1, num); break; + case 32: if (usesFloatingPointData) ReadHelper::read (dest, 0, 1, source, 1, num); + else ReadHelper::read (dest, 0, 1, source, 1, num); break; + default: jassertfalse; break; + } + } + } + + void readMaxLevels (int64 startSampleInFile, int64 numSamples, Range* results, int numChannelsToRead) override { if (numSamples <= 0) { - min0 = max0 = min1 = max1 = 0; + for (int i = 0; i < numChannelsToRead; ++i) + results[i] = Range(); + return; } @@ -834,17 +901,19 @@ public: { jassertfalse; // you must make sure that the window contains all the samples you're going to attempt to read. - min0 = max0 = min1 = max1 = 0; + for (int i = 0; i < numChannelsToRead; ++i) + results[i] = Range(); + return; } switch (bitsPerSample) { - case 8: scanMinAndMax (startSampleInFile, numSamples, min0, max0, min1, max1); break; - case 16: scanMinAndMax (startSampleInFile, numSamples, min0, max0, min1, max1); break; - case 24: scanMinAndMax (startSampleInFile, numSamples, min0, max0, min1, max1); break; - case 32: if (usesFloatingPointData) scanMinAndMax (startSampleInFile, numSamples, min0, max0, min1, max1); - else scanMinAndMax (startSampleInFile, numSamples, min0, max0, min1, max1); break; + case 8: scanMinAndMax (startSampleInFile, numSamples, results, numChannelsToRead); break; + case 16: scanMinAndMax (startSampleInFile, numSamples, results, numChannelsToRead); break; + case 24: scanMinAndMax (startSampleInFile, numSamples, results, numChannelsToRead); break; + case 32: if (usesFloatingPointData) scanMinAndMax (startSampleInFile, numSamples, results, numChannelsToRead); + else scanMinAndMax (startSampleInFile, numSamples, results, numChannelsToRead); break; default: jassertfalse; break; } } @@ -853,24 +922,17 @@ private: const bool littleEndian; template - void scanMinAndMax (int64 startSampleInFile, int64 numSamples, - float& min0, float& max0, float& min1, float& max1) const noexcept + void scanMinAndMax (int64 startSampleInFile, int64 numSamples, Range* results, int numChannelsToRead) const noexcept { - scanMinAndMax2 (0, startSampleInFile, numSamples, min0, max0); - - if (numChannels > 1) - scanMinAndMax2 (1, startSampleInFile, numSamples, min1, max1); - else - min1 = max1 = 0; + for (int i = 0; i < numChannelsToRead; ++i) + results[i] = scanMinAndMaxForChannel (i, startSampleInFile, numSamples); } template - void scanMinAndMax2 (int channel, int64 startSampleInFile, int64 numSamples, float& mn, float& mx) const noexcept + Range scanMinAndMaxForChannel (int channel, int64 startSampleInFile, int64 numSamples) const noexcept { - if (littleEndian) - scanMinAndMaxInterleaved (channel, startSampleInFile, numSamples, mn, mx); - else - scanMinAndMaxInterleaved (channel, startSampleInFile, numSamples, mn, mx); + return littleEndian ? scanMinAndMaxInterleaved (channel, startSampleInFile, numSamples) + : scanMinAndMaxInterleaved (channel, startSampleInFile, numSamples); } JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MemoryMappedAiffReader) diff --git a/JuceLibraryCode/modules/juce_audio_formats/codecs/juce_AiffAudioFormat.h b/JuceLibraryCode/modules/juce_audio_formats/codecs/juce_AiffAudioFormat.h index 01d1484..fe475e3 100644 --- a/JuceLibraryCode/modules/juce_audio_formats/codecs/juce_AiffAudioFormat.h +++ b/JuceLibraryCode/modules/juce_audio_formats/codecs/juce_AiffAudioFormat.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_audio_formats/codecs/juce_CoreAudioFormat.cpp b/JuceLibraryCode/modules/juce_audio_formats/codecs/juce_CoreAudioFormat.cpp index 6d3aafa..9b4d556 100644 --- a/JuceLibraryCode/modules/juce_audio_formats/codecs/juce_CoreAudioFormat.cpp +++ b/JuceLibraryCode/modules/juce_audio_formats/codecs/juce_CoreAudioFormat.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_audio_formats/codecs/juce_CoreAudioFormat.h b/JuceLibraryCode/modules/juce_audio_formats/codecs/juce_CoreAudioFormat.h index 60bace4..8ae56fc 100644 --- a/JuceLibraryCode/modules/juce_audio_formats/codecs/juce_CoreAudioFormat.h +++ b/JuceLibraryCode/modules/juce_audio_formats/codecs/juce_CoreAudioFormat.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_audio_formats/codecs/juce_FlacAudioFormat.cpp b/JuceLibraryCode/modules/juce_audio_formats/codecs/juce_FlacAudioFormat.cpp index 58fdd8f..34e6a3b 100644 --- a/JuceLibraryCode/modules/juce_audio_formats/codecs/juce_FlacAudioFormat.cpp +++ b/JuceLibraryCode/modules/juce_audio_formats/codecs/juce_FlacAudioFormat.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_audio_formats/codecs/juce_FlacAudioFormat.h b/JuceLibraryCode/modules/juce_audio_formats/codecs/juce_FlacAudioFormat.h index 20bf094..68f1628 100644 --- a/JuceLibraryCode/modules/juce_audio_formats/codecs/juce_FlacAudioFormat.h +++ b/JuceLibraryCode/modules/juce_audio_formats/codecs/juce_FlacAudioFormat.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_audio_formats/codecs/juce_LAMEEncoderAudioFormat.cpp b/JuceLibraryCode/modules/juce_audio_formats/codecs/juce_LAMEEncoderAudioFormat.cpp index 5d30d44..c7468fb 100644 --- a/JuceLibraryCode/modules/juce_audio_formats/codecs/juce_LAMEEncoderAudioFormat.cpp +++ b/JuceLibraryCode/modules/juce_audio_formats/codecs/juce_LAMEEncoderAudioFormat.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -30,9 +30,9 @@ public: Writer (OutputStream* destStream, const String& formatName, const File& appFile, int vbr, int cbr, double sampleRate, unsigned int numberOfChannels, - unsigned int bitsPerSample, const StringPairArray& metadata) + int bitsPerSample, const StringPairArray& metadata) : AudioFormatWriter (destStream, formatName, sampleRate, - numberOfChannels, bitsPerSample), + numberOfChannels, (unsigned int) bitsPerSample), vbrLevel (vbr), cbrBitrate (cbr), tempWav (".wav") { @@ -165,13 +165,13 @@ bool LAMEEncoderAudioFormat::canHandleFile (const File&) Array LAMEEncoderAudioFormat::getPossibleSampleRates() { const int rates[] = { 32000, 44100, 48000, 0 }; - return Array (rates); + return Array (rates); } Array LAMEEncoderAudioFormat::getPossibleBitDepths() { const int depths[] = { 16, 0 }; - return Array (depths); + return Array (depths); } bool LAMEEncoderAudioFormat::canDoStereo() { return true; } diff --git a/JuceLibraryCode/modules/juce_audio_formats/codecs/juce_LAMEEncoderAudioFormat.h b/JuceLibraryCode/modules/juce_audio_formats/codecs/juce_LAMEEncoderAudioFormat.h index 92e581b..77e6be6 100644 --- a/JuceLibraryCode/modules/juce_audio_formats/codecs/juce_LAMEEncoderAudioFormat.h +++ b/JuceLibraryCode/modules/juce_audio_formats/codecs/juce_LAMEEncoderAudioFormat.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_audio_formats/codecs/juce_MP3AudioFormat.cpp b/JuceLibraryCode/modules/juce_audio_formats/codecs/juce_MP3AudioFormat.cpp index 219c93f..cf6fad6 100644 --- a/JuceLibraryCode/modules/juce_audio_formats/codecs/juce_MP3AudioFormat.cpp +++ b/JuceLibraryCode/modules/juce_audio_formats/codecs/juce_MP3AudioFormat.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -25,8 +25,8 @@ /* IMPORTANT DISCLAIMER: By choosing to enable the JUCE_USE_MP3AUDIOFORMAT flag and to compile this MP3 code into your software, you do so AT YOUR OWN RISK! By doing so, - you are agreeing that Raw Material Software is in no way responsible for any patent, - copyright, or other legal issues that you may suffer as a result. + you are agreeing that ROLI Ltd. is in no way responsible for any patent, copyright, + or other legal issues that you may suffer as a result. The code in juce_MP3AudioFormat.cpp is NOT guaranteed to be free from infringements of 3rd-party intellectual property. If you wish to use it, please seek your own independent advice about the @@ -426,9 +426,8 @@ struct VBRTagData if (flags & 4) { - if (toc != nullptr) - for (int i = 0; i < 100; ++i) - toc[i] = data[i]; + for (int i = 0; i < 100; ++i) + toc[i] = data[i]; data += 100; } @@ -607,7 +606,7 @@ private: float* costab = cosTables[i]; for (int k = 0; k < kr; ++k) - costab[k] = (float) (1.0 / (2.0 * cos (double_Pi * (k * 2 + 1) / divv))); + costab[k] = (float) (1.0 / (2.0 * std::cos (double_Pi * (k * 2 + 1) / divv))); } for (i = 0, j = 0; i < 256; ++i, ++j, table += 32) @@ -692,23 +691,23 @@ private: for (i = 0; i < 18; ++i) { - win[0][i] = win[1][i] = (float) (0.5 * sin (double_Pi / 72.0 * (2 * i + 1)) / cos (double_Pi * (2 * i + 19) / 72.0)); - win[0][i + 18] = win[3][i + 18] = (float) (0.5 * sin (double_Pi / 72.0 * (2 * (i + 18) + 1)) / cos (double_Pi * (2 * (i + 18) + 19) / 72.0)); + win[0][i] = win[1][i] = (float) (0.5 * std::sin (double_Pi / 72.0 * (2 * i + 1)) / std::cos (double_Pi * (2 * i + 19) / 72.0)); + win[0][i + 18] = win[3][i + 18] = (float) (0.5 * std::sin (double_Pi / 72.0 * (2 * (i + 18) + 1)) / std::cos (double_Pi * (2 * (i + 18) + 19) / 72.0)); } const double piOver72 = double_Pi; for (i = 0; i < 6; ++i) { - win[1][i + 18] = (float) (0.5 / cos (piOver72 * (2 * (i + 18) + 19))); - win[3][i + 12] = (float) (0.5 / cos (piOver72 * (2 * (i + 12) + 19))); - win[1][i + 24] = (float) (0.5 * sin (double_Pi / 24.0 * (2 * i + 13)) / cos (piOver72 * (2 * (i + 24) + 19))); + win[1][i + 18] = (float) (0.5 / std::cos (piOver72 * (2 * (i + 18) + 19))); + win[3][i + 12] = (float) (0.5 / std::cos (piOver72 * (2 * (i + 12) + 19))); + win[1][i + 24] = (float) (0.5 * std::sin (double_Pi / 24.0 * (2 * i + 13)) / std::cos (piOver72 * (2 * (i + 24) + 19))); win[1][i + 30] = win[3][i] = 0; - win[3][i + 6] = (float) (0.5 * sin (double_Pi / 24.0 * (2 * i + 1)) / cos (piOver72 * (2 * (i + 6) + 19))); + win[3][i + 6] = (float) (0.5 * std::sin (double_Pi / 24.0 * (2 * i + 1)) / std::cos (piOver72 * (2 * (i + 6) + 19))); } for (i = 0; i < 12; ++i) - win[2][i] = (float) (0.5 * sin (double_Pi / 24.0 * (2 * i + 1)) / cos (double_Pi * (2 * i + 7) / 24.0)); + win[2][i] = (float) (0.5 * std::sin (double_Pi / 24.0 * (2 * i + 1)) / std::cos (double_Pi * (2 * i + 7) / 24.0)); for (j = 0; j < 4; ++j) { @@ -721,7 +720,7 @@ private: for (i = 0; i < 16; ++i) { - const double t = tan (i * double_Pi / 12.0); + const double t = std::tan (i * double_Pi / 12.0); tan1_1[i] = (float) (t / (1.0 + t)); tan2_1[i] = (float) (1.0 / (1.0 + t)); tan1_2[i] = (float) (sqrt2 * t / (1.0 + t)); diff --git a/JuceLibraryCode/modules/juce_audio_formats/codecs/juce_MP3AudioFormat.h b/JuceLibraryCode/modules/juce_audio_formats/codecs/juce_MP3AudioFormat.h index e89c05d..d3cd792 100644 --- a/JuceLibraryCode/modules/juce_audio_formats/codecs/juce_MP3AudioFormat.h +++ b/JuceLibraryCode/modules/juce_audio_formats/codecs/juce_MP3AudioFormat.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -30,8 +30,8 @@ IMPORTANT DISCLAIMER: By choosing to enable the JUCE_USE_MP3AUDIOFORMAT flag and to compile the MP3 code into your software, you do so AT YOUR OWN RISK! By doing so, - you are agreeing that Raw Material Software is in no way responsible for any patent, - copyright, or other legal issues that you may suffer as a result. + you are agreeing that ROLI Ltd. is in no way responsible for any patent, copyright, + or other legal issues that you may suffer as a result. The code in juce_MP3AudioFormat.cpp is NOT guaranteed to be free from infringements of 3rd-party intellectual property. If you wish to use it, please seek your own independent advice about the diff --git a/JuceLibraryCode/modules/juce_audio_formats/codecs/juce_OggVorbisAudioFormat.cpp b/JuceLibraryCode/modules/juce_audio_formats/codecs/juce_OggVorbisAudioFormat.cpp index 7cc12a4..924f8e4 100644 --- a/JuceLibraryCode/modules/juce_audio_formats/codecs/juce_OggVorbisAudioFormat.cpp +++ b/JuceLibraryCode/modules/juce_audio_formats/codecs/juce_OggVorbisAudioFormat.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_audio_formats/codecs/juce_OggVorbisAudioFormat.h b/JuceLibraryCode/modules/juce_audio_formats/codecs/juce_OggVorbisAudioFormat.h index 03bc3fb..9d575e0 100644 --- a/JuceLibraryCode/modules/juce_audio_formats/codecs/juce_OggVorbisAudioFormat.h +++ b/JuceLibraryCode/modules/juce_audio_formats/codecs/juce_OggVorbisAudioFormat.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_audio_formats/codecs/juce_QuickTimeAudioFormat.cpp b/JuceLibraryCode/modules/juce_audio_formats/codecs/juce_QuickTimeAudioFormat.cpp index 17a06da..b87c05d 100644 --- a/JuceLibraryCode/modules/juce_audio_formats/codecs/juce_QuickTimeAudioFormat.cpp +++ b/JuceLibraryCode/modules/juce_audio_formats/codecs/juce_QuickTimeAudioFormat.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -194,7 +194,7 @@ public: bufferList->mNumberBuffers = 1; bufferList->mBuffers[0].mNumberChannels = inputStreamDesc.mChannelsPerFrame; - bufferList->mBuffers[0].mDataByteSize = jmax ((UInt32) 4096, (UInt32) (samplesPerFrame * inputStreamDesc.mBytesPerFrame) + 16); + bufferList->mBuffers[0].mDataByteSize = jmax ((UInt32) 4096, (UInt32) (samplesPerFrame * (int) inputStreamDesc.mBytesPerFrame) + 16); dataBuffer.malloc (bufferList->mBuffers[0].mDataByteSize); bufferList->mBuffers[0].mData = dataBuffer; @@ -262,10 +262,10 @@ public: } int framesToDo = jmin (numSamples, (int) (bufferList->mBuffers[0].mDataByteSize / inputStreamDesc.mBytesPerFrame)); - bufferList->mBuffers[0].mDataByteSize = inputStreamDesc.mBytesPerFrame * framesToDo; + bufferList->mBuffers[0].mDataByteSize = inputStreamDesc.mBytesPerFrame * (UInt32) framesToDo; UInt32 outFlags = 0; - UInt32 actualNumFrames = framesToDo; + UInt32 actualNumFrames = (UInt32) framesToDo; OSStatus err = MovieAudioExtractionFillBuffer (extractor, &actualNumFrames, bufferList, &outFlags); if (err != noErr) { @@ -274,7 +274,7 @@ public: } lastSampleRead = startSampleInFile + actualNumFrames; - const int samplesReceived = actualNumFrames; + const int samplesReceived = (int) actualNumFrames; for (int j = numDestChannels; --j >= 0;) { @@ -298,7 +298,7 @@ public: { for (int j = numDestChannels; --j >= 0;) if (destSamples[j] != nullptr) - zeromem (destSamples[j] + startOffsetInDestBuffer, sizeof (int) * numSamples); + zeromem (destSamples[j] + startOffsetInDestBuffer, sizeof (int) * (size_t) numSamples); break; } diff --git a/JuceLibraryCode/modules/juce_audio_formats/codecs/juce_QuickTimeAudioFormat.h b/JuceLibraryCode/modules/juce_audio_formats/codecs/juce_QuickTimeAudioFormat.h index 6ef6a4e..a7cd60b 100644 --- a/JuceLibraryCode/modules/juce_audio_formats/codecs/juce_QuickTimeAudioFormat.h +++ b/JuceLibraryCode/modules/juce_audio_formats/codecs/juce_QuickTimeAudioFormat.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_audio_formats/codecs/juce_WavAudioFormat.cpp b/JuceLibraryCode/modules/juce_audio_formats/codecs/juce_WavAudioFormat.cpp index 058ff73..24ad58c 100644 --- a/JuceLibraryCode/modules/juce_audio_formats/codecs/juce_WavAudioFormat.cpp +++ b/JuceLibraryCode/modules/juce_audio_formats/codecs/juce_WavAudioFormat.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -65,6 +65,7 @@ const char* const WavAudioFormat::acidNumerator = "acid numerator"; const char* const WavAudioFormat::acidTempo = "acid tempo"; const char* const WavAudioFormat::ISRC = "ISRC"; +const char* const WavAudioFormat::tracktionLoopInfo = "tracktion loop info"; //============================================================================== namespace WavFileHelpers @@ -471,6 +472,46 @@ namespace WavFileHelpers } } + //============================================================================== + namespace ListInfoChunk + { + static bool writeValue (const StringPairArray& values, MemoryOutputStream& out, const char* paramName) + { + const String value (values.getValue (paramName, String())); + + if (value.isEmpty()) + return false; + + const int valueLength = (int) value.getNumBytesAsUTF8() + 1; + const int chunkLength = valueLength + (valueLength & 1); + + out.writeInt (chunkName (paramName)); + out.writeInt (chunkLength); + out.write (value.toUTF8(), (size_t) valueLength); + + if ((out.getDataSize() & 1) != 0) + out.writeByte (0); + + return true; + } + + static MemoryBlock createFrom (const StringPairArray& values) + { + static const char* params[] = { "INAM", "IART", "IPRD", "IPRT", "ISFT", + "ISRC", "IGNR", "ICMT", "ICOP", "ICRD" }; + + MemoryOutputStream out; + out.writeInt (chunkName ("INFO")); + bool anyParamsDefined = false; + + for (int i = 0; i < numElementsInArray (params); ++i) + if (writeValue (values, out, params[i])) + anyParamsDefined = true; + + return anyParamsDefined ? out.getMemoryBlock() : MemoryBlock(); + } + } + //============================================================================== struct AcidChunk { @@ -481,6 +522,38 @@ namespace WavFileHelpers input.read (this, (int) jmin (sizeof (*this), length)); } + AcidChunk (const StringPairArray& values) + { + zerostruct (*this); + + flags = getFlagIfPresent (values, WavAudioFormat::acidOneShot, 0x01) + | getFlagIfPresent (values, WavAudioFormat::acidRootSet, 0x02) + | getFlagIfPresent (values, WavAudioFormat::acidStretch, 0x04) + | getFlagIfPresent (values, WavAudioFormat::acidDiskBased, 0x08) + | getFlagIfPresent (values, WavAudioFormat::acidizerFlag, 0x10); + + if (values[WavAudioFormat::acidRootSet].getIntValue() != 0) + rootNote = ByteOrder::swapIfBigEndian ((uint16) values[WavAudioFormat::acidRootNote].getIntValue()); + + numBeats = ByteOrder::swapIfBigEndian ((uint32) values[WavAudioFormat::acidBeats].getIntValue()); + meterDenominator = ByteOrder::swapIfBigEndian ((uint16) values[WavAudioFormat::acidDenominator].getIntValue()); + meterNumerator = ByteOrder::swapIfBigEndian ((uint16) values[WavAudioFormat::acidNumerator].getIntValue()); + + if (values.containsKey (WavAudioFormat::acidTempo)) + tempo = swapFloatByteOrder (values[WavAudioFormat::acidTempo].getFloatValue()); + } + + static MemoryBlock createFrom (const StringPairArray& values) + { + return AcidChunk (values).toMemoryBlock(); + } + + MemoryBlock toMemoryBlock() const + { + return (flags != 0 || rootNote != 0 || numBeats != 0 || meterDenominator != 0 || meterNumerator != 0) + ? MemoryBlock (this, sizeof (*this)) : MemoryBlock(); + } + void addToMetadata (StringPairArray& values) const { setBoolFlag (values, WavAudioFormat::acidOneShot, 0x01); @@ -490,30 +563,67 @@ namespace WavFileHelpers setBoolFlag (values, WavAudioFormat::acidizerFlag, 0x10); if (flags & 0x02) // root note set - values.set (WavAudioFormat::acidRootNote, String (rootNote)); + values.set (WavAudioFormat::acidRootNote, String (ByteOrder::swapIfBigEndian (rootNote))); - values.set (WavAudioFormat::acidBeats, String (numBeats)); - values.set (WavAudioFormat::acidDenominator, String (meterDenominator)); - values.set (WavAudioFormat::acidNumerator, String (meterNumerator)); - values.set (WavAudioFormat::acidTempo, String (tempo)); + values.set (WavAudioFormat::acidBeats, String (ByteOrder::swapIfBigEndian (numBeats))); + values.set (WavAudioFormat::acidDenominator, String (ByteOrder::swapIfBigEndian (meterDenominator))); + values.set (WavAudioFormat::acidNumerator, String (ByteOrder::swapIfBigEndian (meterNumerator))); + values.set (WavAudioFormat::acidTempo, String (swapFloatByteOrder (tempo))); } - void setBoolFlag (StringPairArray& values, const char* name, int32 mask) const + void setBoolFlag (StringPairArray& values, const char* name, uint32 mask) const { - values.set (name, (flags & mask) ? "1" : "0"); + values.set (name, (flags & ByteOrder::swapIfBigEndian (mask)) ? "1" : "0"); } - int32 flags; - int16 rootNote; - int16 reserved1; + static uint32 getFlagIfPresent (const StringPairArray& values, const char* name, uint32 flag) + { + return values[name].getIntValue() != 0 ? ByteOrder::swapIfBigEndian (flag) : 0; + } + + static float swapFloatByteOrder (const float x) noexcept + { + #ifdef JUCE_BIG_ENDIAN + union { uint32 asInt; float asFloat; } n; + n.asFloat = x; + n.asInt = ByteOrder::swap (n.asInt); + return n.asFloat; + #else + return x; + #endif + } + + uint32 flags; + uint16 rootNote; + uint16 reserved1; float reserved2; - int32 numBeats; - int16 meterDenominator; - int16 meterNumerator; + uint32 numBeats; + uint16 meterDenominator; + uint16 meterNumerator; float tempo; } JUCE_PACKED; + //============================================================================== + struct TracktionChunk + { + static MemoryBlock createFrom (const StringPairArray& values) + { + MemoryOutputStream out; + const String s (values[WavAudioFormat::tracktionLoopInfo]); + + if (s.isNotEmpty()) + { + out.writeString (s); + + if ((out.getDataSize() & 1) != 0) + out.writeByte (0); + } + + return out.getMemoryBlock(); + } + }; + //============================================================================== namespace AXMLChunk { @@ -816,6 +926,12 @@ public: { AcidChunk (*input, length).addToMetadata (metadataValues); } + else if (chunkType == chunkName ("Trkn")) + { + MemoryBlock tracktion; + input->readIntoMemoryBlock (tracktion, (ssize_t) length); + metadataValues.set (WavAudioFormat::tracktionLoopInfo, tracktion.toString()); + } else if (chunkEnd <= input->getPosition()) { break; @@ -913,12 +1029,15 @@ public: // key should be removed (or set to "WAV") once this has been done jassert (metadataValues.getValue ("MetaDataSource", "None") != "AIFF"); - bwavChunk = BWAVChunk::createFrom (metadataValues); - axmlChunk = AXMLChunk::createFrom (metadataValues); - smplChunk = SMPLChunk::createFrom (metadataValues); - instChunk = InstChunk::createFrom (metadataValues); - cueChunk = CueChunk ::createFrom (metadataValues); - listChunk = ListChunk::createFrom (metadataValues); + bwavChunk = BWAVChunk::createFrom (metadataValues); + axmlChunk = AXMLChunk::createFrom (metadataValues); + smplChunk = SMPLChunk::createFrom (metadataValues); + instChunk = InstChunk::createFrom (metadataValues); + cueChunk = CueChunk ::createFrom (metadataValues); + listChunk = ListChunk::createFrom (metadataValues); + listInfoChunk = ListInfoChunk::createFrom (metadataValues); + acidChunk = AcidChunk::createFrom (metadataValues); + trckChunk = TracktionChunk::createFrom (metadataValues); } headerPosition = out->getPosition(); @@ -927,12 +1046,6 @@ public: ~WavAudioFormatWriter() { - if ((bytesWritten & 1) != 0) // pad to an even length - { - ++bytesWritten; - output->writeByte (0); - } - writeHeader(); } @@ -972,8 +1085,22 @@ public: return true; } + bool flush() override + { + const int64 lastWritePos = output->getPosition(); + writeHeader(); + + if (output->setPosition (lastWritePos)) + return true; + + // if this fails, you've given it an output stream that can't seek! It needs + // to be able to seek back to write the header + jassertfalse; + return false; + } + private: - MemoryBlock tempBlock, bwavChunk, axmlChunk, smplChunk, instChunk, cueChunk, listChunk; + MemoryBlock tempBlock, bwavChunk, axmlChunk, smplChunk, instChunk, cueChunk, listChunk, listInfoChunk, acidChunk, trckChunk; uint64 lengthInSamples, bytesWritten; int64 headerPosition; bool writeFailed; @@ -998,13 +1125,18 @@ private: void writeHeader() { - using namespace WavFileHelpers; - const bool seekedOk = output->setPosition (headerPosition); - (void) seekedOk; + if ((bytesWritten & 1) != 0) // pad to an even length + output->writeByte (0); - // if this fails, you've given it an output stream that can't seek! It needs - // to be able to seek back to write the header - jassert (seekedOk); + using namespace WavFileHelpers; + + if (headerPosition != output->getPosition() && ! output->setPosition (headerPosition)) + { + // if this fails, you've given it an output stream that can't seek! It needs to be + // able to seek back to go back and write the header after the data has been written. + jassertfalse; + return; + } const size_t bytesPerFrame = numChannels * bitsPerSample / 8; uint64 audioDataSize = bytesPerFrame * lengthInSamples; @@ -1020,6 +1152,9 @@ private: + chunkSize (instChunk) + chunkSize (cueChunk) + chunkSize (listChunk) + + chunkSize (listInfoChunk) + + chunkSize (acidChunk) + + chunkSize (trckChunk) + (8 + 28)); // (ds64 chunk) riffChunkSize += (riffChunkSize & 1); @@ -1093,12 +1228,15 @@ private: output->write (subFormat.data4, sizeof (subFormat.data4)); } - writeChunk (bwavChunk, chunkName ("bext")); - writeChunk (axmlChunk, chunkName ("axml")); - writeChunk (smplChunk, chunkName ("smpl")); - writeChunk (instChunk, chunkName ("inst"), 7); - writeChunk (cueChunk, chunkName ("cue ")); - writeChunk (listChunk, chunkName ("LIST")); + writeChunk (bwavChunk, chunkName ("bext")); + writeChunk (axmlChunk, chunkName ("axml")); + writeChunk (smplChunk, chunkName ("smpl")); + writeChunk (instChunk, chunkName ("inst"), 7); + writeChunk (cueChunk, chunkName ("cue ")); + writeChunk (listChunk, chunkName ("LIST")); + writeChunk (listInfoChunk, chunkName ("LIST")); + writeChunk (acidChunk, chunkName ("acid")); + writeChunk (trckChunk, chunkName ("Trkn")); writeChunkHeader (chunkName ("data"), isRF64 ? -1 : (int) (lengthInSamples * bytesPerFrame)); @@ -1129,8 +1267,8 @@ private: class MemoryMappedWavReader : public MemoryMappedAudioFormatReader { public: - MemoryMappedWavReader (const File& file, const WavAudioFormatReader& reader) - : MemoryMappedAudioFormatReader (file, reader, reader.dataChunkStart, + MemoryMappedWavReader (const File& wavFile, const WavAudioFormatReader& reader) + : MemoryMappedAudioFormatReader (wavFile, reader, reader.dataChunkStart, reader.dataLength, reader.bytesPerFrame) { } @@ -1153,12 +1291,39 @@ public: return true; } - void readMaxLevels (int64 startSampleInFile, int64 numSamples, - float& min0, float& max0, float& min1, float& max1) override + void getSample (int64 sample, float* result) const noexcept override + { + const int num = (int) numChannels; + + if (map == nullptr || ! mappedSection.contains (sample)) + { + jassertfalse; // you must make sure that the window contains all the samples you're going to attempt to read. + + zeromem (result, sizeof (float) * (size_t) num); + return; + } + + float** dest = &result; + const void* source = sampleToPointer (sample); + + switch (bitsPerSample) + { + case 8: ReadHelper::read (dest, 0, 1, source, 1, num); break; + case 16: ReadHelper::read (dest, 0, 1, source, 1, num); break; + case 24: ReadHelper::read (dest, 0, 1, source, 1, num); break; + case 32: if (usesFloatingPointData) ReadHelper::read (dest, 0, 1, source, 1, num); + else ReadHelper::read (dest, 0, 1, source, 1, num); break; + default: jassertfalse; break; + } + } + + void readMaxLevels (int64 startSampleInFile, int64 numSamples, Range* results, int numChannelsToRead) override { if (numSamples <= 0) { - min0 = max0 = min1 = max1 = 0; + for (int i = 0; i < numChannelsToRead; ++i) + results[i] = Range(); + return; } @@ -1166,32 +1331,29 @@ public: { jassertfalse; // you must make sure that the window contains all the samples you're going to attempt to read. - min0 = max0 = min1 = max1 = 0; + for (int i = 0; i < numChannelsToRead; ++i) + results[i] = Range(); + return; } switch (bitsPerSample) { - case 8: scanMinAndMax (startSampleInFile, numSamples, min0, max0, min1, max1); break; - case 16: scanMinAndMax (startSampleInFile, numSamples, min0, max0, min1, max1); break; - case 24: scanMinAndMax (startSampleInFile, numSamples, min0, max0, min1, max1); break; - case 32: if (usesFloatingPointData) scanMinAndMax (startSampleInFile, numSamples, min0, max0, min1, max1); - else scanMinAndMax (startSampleInFile, numSamples, min0, max0, min1, max1); break; + case 8: scanMinAndMax (startSampleInFile, numSamples, results, numChannelsToRead); break; + case 16: scanMinAndMax (startSampleInFile, numSamples, results, numChannelsToRead); break; + case 24: scanMinAndMax (startSampleInFile, numSamples, results, numChannelsToRead); break; + case 32: if (usesFloatingPointData) scanMinAndMax (startSampleInFile, numSamples, results, numChannelsToRead); + else scanMinAndMax (startSampleInFile, numSamples, results, numChannelsToRead); break; default: jassertfalse; break; } } private: template - void scanMinAndMax (int64 startSampleInFile, int64 numSamples, - float& min0, float& max0, float& min1, float& max1) const noexcept + void scanMinAndMax (int64 startSampleInFile, int64 numSamples, Range* results, int numChannelsToRead) const noexcept { - scanMinAndMaxInterleaved (0, startSampleInFile, numSamples, min0, max0); - - if (numChannels > 1) - scanMinAndMaxInterleaved (1, startSampleInFile, numSamples, min1, max1); - else - min1 = max1 = 0; + for (int i = 0; i < numChannelsToRead; ++i) + results[i] = scanMinAndMaxInterleaved (i, startSampleInFile, numSamples); } JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MemoryMappedWavReader) diff --git a/JuceLibraryCode/modules/juce_audio_formats/codecs/juce_WavAudioFormat.h b/JuceLibraryCode/modules/juce_audio_formats/codecs/juce_WavAudioFormat.h index f80695c..ff0ca94 100644 --- a/JuceLibraryCode/modules/juce_audio_formats/codecs/juce_WavAudioFormat.h +++ b/JuceLibraryCode/modules/juce_audio_formats/codecs/juce_WavAudioFormat.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -135,6 +135,9 @@ public: /** Metadata property name used when reading an ISRC code from an AXML chunk. */ static const char* const ISRC; + /** Metadata property name used when reading a WAV file with a Tracktion chunk. */ + static const char* const tracktionLoopInfo; + //============================================================================== Array getPossibleSampleRates() override; Array getPossibleBitDepths() override; diff --git a/JuceLibraryCode/modules/juce_audio_formats/codecs/juce_WindowsMediaAudioFormat.cpp b/JuceLibraryCode/modules/juce_audio_formats/codecs/juce_WindowsMediaAudioFormat.cpp index f5f5664..746ce64 100644 --- a/JuceLibraryCode/modules/juce_audio_formats/codecs/juce_WindowsMediaAudioFormat.cpp +++ b/JuceLibraryCode/modules/juce_audio_formats/codecs/juce_WindowsMediaAudioFormat.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_audio_formats/codecs/juce_WindowsMediaAudioFormat.h b/JuceLibraryCode/modules/juce_audio_formats/codecs/juce_WindowsMediaAudioFormat.h index 8c10ee1..88cd438 100644 --- a/JuceLibraryCode/modules/juce_audio_formats/codecs/juce_WindowsMediaAudioFormat.h +++ b/JuceLibraryCode/modules/juce_audio_formats/codecs/juce_WindowsMediaAudioFormat.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_audio_formats/codecs/oggvorbis/libvorbis-1.3.2/lib/floor1.c b/JuceLibraryCode/modules/juce_audio_formats/codecs/oggvorbis/libvorbis-1.3.2/lib/floor1.c index 8ea1978..644b852 100644 --- a/JuceLibraryCode/modules/juce_audio_formats/codecs/oggvorbis/libvorbis-1.3.2/lib/floor1.c +++ b/JuceLibraryCode/modules/juce_audio_formats/codecs/oggvorbis/libvorbis-1.3.2/lib/floor1.c @@ -850,7 +850,7 @@ int floor1_encode(oggpack_buffer *opb,vorbis_block *vb, /* generate the partition's first stage cascade value */ if(csubbits){ - int maxval[8]; + int maxval[8] = { 0 }; for(k=0;kclass_subbook[classx][k]; if(booknum<0){ diff --git a/JuceLibraryCode/modules/juce_audio_formats/format/juce_AudioFormat.cpp b/JuceLibraryCode/modules/juce_audio_formats/format/juce_AudioFormat.cpp index ad87176..fc3f9ff 100644 --- a/JuceLibraryCode/modules/juce_audio_formats/format/juce_AudioFormat.cpp +++ b/JuceLibraryCode/modules/juce_audio_formats/format/juce_AudioFormat.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_audio_formats/format/juce_AudioFormat.h b/JuceLibraryCode/modules/juce_audio_formats/format/juce_AudioFormat.h index 196d436..fee1e06 100644 --- a/JuceLibraryCode/modules/juce_audio_formats/format/juce_AudioFormat.h +++ b/JuceLibraryCode/modules/juce_audio_formats/format/juce_AudioFormat.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -119,7 +119,7 @@ public: should then be deleted by the caller. If the stream can't be created for some reason (e.g. the parameters passed in - here aren't suitable), this will return 0. + here aren't suitable), this will return nullptr. @param streamToWriteTo the stream that the data will go to - this will be deleted by the AudioFormatWriter object when it's no longer diff --git a/JuceLibraryCode/modules/juce_audio_formats/format/juce_AudioFormatManager.cpp b/JuceLibraryCode/modules/juce_audio_formats/format/juce_AudioFormatManager.cpp index f0196c8..c51ebcb 100644 --- a/JuceLibraryCode/modules/juce_audio_formats/format/juce_AudioFormatManager.cpp +++ b/JuceLibraryCode/modules/juce_audio_formats/format/juce_AudioFormatManager.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_audio_formats/format/juce_AudioFormatManager.h b/JuceLibraryCode/modules/juce_audio_formats/format/juce_AudioFormatManager.h index f560347..3ad9213 100644 --- a/JuceLibraryCode/modules/juce_audio_formats/format/juce_AudioFormatManager.h +++ b/JuceLibraryCode/modules/juce_audio_formats/format/juce_AudioFormatManager.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_audio_formats/format/juce_AudioFormatReader.cpp b/JuceLibraryCode/modules/juce_audio_formats/format/juce_AudioFormatReader.cpp index 501e339..498c79e 100644 --- a/JuceLibraryCode/modules/juce_audio_formats/format/juce_AudioFormatReader.cpp +++ b/JuceLibraryCode/modules/juce_audio_formats/format/juce_AudioFormatReader.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -46,6 +46,7 @@ bool AudioFormatReader::read (int* const* destSamples, { jassert (numDestChannels > 0); // you have to actually give this some channels to work with! + const size_t originalNumSamplesToRead = (size_t) numSamplesToRead; int startOffsetInDestBuffer = 0; if (startSampleInSource < 0) @@ -64,7 +65,7 @@ bool AudioFormatReader::read (int* const* destSamples, if (numSamplesToRead <= 0) return true; - if (! readSamples (const_cast (destSamples), + if (! readSamples (const_cast (destSamples), jmin ((int) numChannels, numDestChannels), startOffsetInDestBuffer, startSampleInSource, numSamplesToRead)) return false; @@ -87,13 +88,13 @@ bool AudioFormatReader::read (int* const* destSamples, if (lastFullChannel != nullptr) for (int i = (int) numChannels; i < numDestChannels; ++i) if (destSamples[i] != nullptr) - memcpy (destSamples[i], lastFullChannel, sizeof (int) * (size_t) numSamplesToRead); + memcpy (destSamples[i], lastFullChannel, sizeof (int) * originalNumSamplesToRead); } else { for (int i = (int) numChannels; i < numDestChannels; ++i) if (destSamples[i] != nullptr) - zeromem (destSamples[i], sizeof (int) * (size_t) numSamplesToRead); + zeromem (destSamples[i], sizeof (int) * originalNumSamplesToRead); } } @@ -162,7 +163,7 @@ void AudioFormatReader::read (AudioSampleBuffer* buffer, } else { - HeapBlock chans (numTargetChannels); + HeapBlock chans ((size_t) numTargetChannels + 1); readChannels (*this, chans, buffer, startSample, numSamples, readerStartSample, numTargetChannels); } @@ -173,35 +174,54 @@ void AudioFormatReader::read (AudioSampleBuffer* buffer, } } -template -static Range getChannelMinAndMax (SampleType* channel, int numSamples) noexcept +void AudioFormatReader::readMaxLevels (int64 startSampleInFile, int64 numSamples, + Range* const results, const int channelsToRead) { - return Range::findMinAndMax (channel, numSamples); -} + jassert (channelsToRead > 0 && channelsToRead <= (int) numChannels); -static Range getChannelMinAndMax (float* channel, int numSamples) noexcept -{ - return FloatVectorOperations::findMinAndMax (channel, numSamples); -} - -template -static void getStereoMinAndMax (SampleType* const* channels, const int numChannels, const int numSamples, - SampleType& lmin, SampleType& lmax, SampleType& rmin, SampleType& rmax) -{ - Range range (getChannelMinAndMax (channels[0], numSamples)); - lmax = jmax (lmax, range.getEnd()); - lmin = jmin (lmin, range.getStart()); - - if (numChannels > 1) + if (numSamples <= 0) { - range = getChannelMinAndMax (channels[1], numSamples); - rmax = jmax (rmax, range.getEnd()); - rmin = jmin (rmin, range.getStart()); + for (int i = 0; i < channelsToRead; ++i) + results[i] = Range(); + + return; } - else + + const int bufferSize = (int) jmin (numSamples, (int64) 4096); + AudioSampleBuffer tempSampleBuffer ((int) channelsToRead, bufferSize); + + float* const* const floatBuffer = tempSampleBuffer.getArrayOfWritePointers(); + int* const* intBuffer = reinterpret_cast (floatBuffer); + bool isFirstBlock = true; + + while (numSamples > 0) { - rmax = lmax; - rmin = lmin; + const int numToDo = (int) jmin (numSamples, (int64) bufferSize); + if (! read (intBuffer, channelsToRead, startSampleInFile, numToDo, false)) + break; + + for (int i = 0; i < channelsToRead; ++i) + { + Range r; + + if (usesFloatingPointData) + { + r = FloatVectorOperations::findMinAndMax (floatBuffer[i], numToDo); + } + else + { + Range intRange (Range::findMinAndMax (intBuffer[i], numToDo)); + + r = Range (intRange.getStart() / (float) std::numeric_limits::max(), + intRange.getEnd() / (float) std::numeric_limits::max()); + } + + results[i] = isFirstBlock ? r : results[i].getUnionWith (r); + } + + isFirstBlock = false; + numSamples -= numToDo; + startSampleInFile += numToDo; } } @@ -209,67 +229,22 @@ void AudioFormatReader::readMaxLevels (int64 startSampleInFile, int64 numSamples float& lowestLeft, float& highestLeft, float& lowestRight, float& highestRight) { - if (numSamples <= 0) + Range levels[2]; + + if (numChannels < 2) { - lowestLeft = 0; - lowestRight = 0; - highestLeft = 0; - highestRight = 0; - return; - } - - const int bufferSize = (int) jmin (numSamples, (int64) 4096); - AudioSampleBuffer tempSampleBuffer ((int) numChannels, bufferSize); - - float* const* const floatBuffer = tempSampleBuffer.getArrayOfWritePointers(); - int* const* intBuffer = reinterpret_cast (floatBuffer); - - if (usesFloatingPointData) - { - float lmin = 1.0e6f; - float lmax = -lmin; - float rmin = lmin; - float rmax = lmax; - - while (numSamples > 0) - { - const int numToDo = (int) jmin (numSamples, (int64) bufferSize); - if (! read (intBuffer, 2, startSampleInFile, numToDo, false)) - break; - - numSamples -= numToDo; - startSampleInFile += numToDo; - getStereoMinAndMax (floatBuffer, (int) numChannels, numToDo, lmin, lmax, rmin, rmax); - } - - lowestLeft = lmin; - highestLeft = lmax; - lowestRight = rmin; - highestRight = rmax; + readMaxLevels (startSampleInFile, numSamples, levels, (int) numChannels); + levels[1] = levels[0]; } else { - int lmax = std::numeric_limits::min(); - int lmin = std::numeric_limits::max(); - int rmax = std::numeric_limits::min(); - int rmin = std::numeric_limits::max(); - - while (numSamples > 0) - { - const int numToDo = (int) jmin (numSamples, (int64) bufferSize); - if (! read (intBuffer, 2, startSampleInFile, numToDo, false)) - break; - - numSamples -= numToDo; - startSampleInFile += numToDo; - getStereoMinAndMax (intBuffer, (int) numChannels, numToDo, lmin, lmax, rmin, rmax); - } - - lowestLeft = lmin / (float) std::numeric_limits::max(); - highestLeft = lmax / (float) std::numeric_limits::max(); - lowestRight = rmin / (float) std::numeric_limits::max(); - highestRight = rmax / (float) std::numeric_limits::max(); + readMaxLevels (startSampleInFile, numSamples, levels, 2); } + + lowestLeft = levels[0].getStart(); + highestLeft = levels[0].getEnd(); + lowestRight = levels[1].getStart(); + highestRight = levels[1].getEnd(); } int64 AudioFormatReader::searchForLevel (int64 startSample, diff --git a/JuceLibraryCode/modules/juce_audio_formats/format/juce_AudioFormatReader.h b/JuceLibraryCode/modules/juce_audio_formats/format/juce_AudioFormatReader.h index d7cdd9c..9a972cf 100644 --- a/JuceLibraryCode/modules/juce_audio_formats/format/juce_AudioFormatReader.h +++ b/JuceLibraryCode/modules/juce_audio_formats/format/juce_AudioFormatReader.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -44,7 +44,7 @@ protected: @param sourceStream the stream to read from - this will be deleted by this object when it is no longer needed. (Some specialised readers might not use this parameter and - can leave it as 0). + can leave it as nullptr). @param formatName the description that will be returned by the getFormatName() method */ @@ -121,6 +121,25 @@ public: bool useReaderLeftChan, bool useReaderRightChan); + /** Finds the highest and lowest sample levels from a section of the audio stream. + + This will read a block of samples from the stream, and measure the + highest and lowest sample levels from the channels in that section, returning + these as normalised floating-point levels. + + @param startSample the offset into the audio stream to start reading from. It's + ok for this to be beyond the start or end of the stream. + @param numSamples how many samples to read + @param results this array will be filled with Range values for each channel. + The array must contain numChannels elements. + @param numChannelsToRead the number of channels of data to scan. This must be + more than zero, but not more than the total number of channels + that the reader contains + @see read + */ + virtual void readMaxLevels (int64 startSample, int64 numSamples, + Range* results, int numChannelsToRead); + /** Finds the highest and lowest sample levels from a section of the audio stream. This will read a block of samples from the stream, and measure the @@ -138,12 +157,9 @@ public: channel (if there is one) @see read */ - virtual void readMaxLevels (int64 startSample, - int64 numSamples, - float& lowestLeft, - float& highestLeft, - float& lowestRight, - float& highestRight); + virtual void readMaxLevels (int64 startSample, int64 numSamples, + float& lowestLeft, float& highestLeft, + float& lowestRight, float& highestRight); /** Scans the source looking for a sample whose magnitude is in a specified range. @@ -231,8 +247,8 @@ protected: template struct ReadHelper { - typedef AudioData::Pointer DestType; - typedef AudioData::Pointer SourceType; + typedef AudioData::Pointer DestType; + typedef AudioData::Pointer SourceType; template static void read (TargetType* const* destData, int destOffset, int numDestChannels, diff --git a/JuceLibraryCode/modules/juce_audio_formats/format/juce_AudioFormatReaderSource.cpp b/JuceLibraryCode/modules/juce_audio_formats/format/juce_AudioFormatReaderSource.cpp index fb086ef..35ddeeb 100644 --- a/JuceLibraryCode/modules/juce_audio_formats/format/juce_AudioFormatReaderSource.cpp +++ b/JuceLibraryCode/modules/juce_audio_formats/format/juce_AudioFormatReaderSource.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_audio_formats/format/juce_AudioFormatReaderSource.h b/JuceLibraryCode/modules/juce_audio_formats/format/juce_AudioFormatReaderSource.h index d7ff5f7..c7f74bb 100644 --- a/JuceLibraryCode/modules/juce_audio_formats/format/juce_AudioFormatReaderSource.h +++ b/JuceLibraryCode/modules/juce_audio_formats/format/juce_AudioFormatReaderSource.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -58,10 +58,10 @@ public: @see isLooping */ - void setLooping (bool shouldLoop); + void setLooping (bool shouldLoop) override; /** Returns whether loop-mode is turned on or not. */ - bool isLooping() const { return looping; } + bool isLooping() const override { return looping; } /** Returns the reader that's being used. */ AudioFormatReader* getAudioFormatReader() const noexcept { return reader; } diff --git a/JuceLibraryCode/modules/juce_audio_formats/format/juce_AudioFormatWriter.cpp b/JuceLibraryCode/modules/juce_audio_formats/format/juce_AudioFormatWriter.cpp index cd1ffc9..5082070 100644 --- a/JuceLibraryCode/modules/juce_audio_formats/format/juce_AudioFormatWriter.cpp +++ b/JuceLibraryCode/modules/juce_audio_formats/format/juce_AudioFormatWriter.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -183,6 +183,11 @@ bool AudioFormatWriter::writeFromAudioSampleBuffer (const AudioSampleBuffer& sou return writeFromFloatArrays (chans, numSourceChannels, numSamples); } +bool AudioFormatWriter::flush() +{ + return false; +} + //============================================================================== class AudioFormatWriter::ThreadedWriter::Buffer : private TimeSliceClient { @@ -194,6 +199,8 @@ public: writer (w), receiver (nullptr), samplesWritten (0), + samplesPerFlush (0), + flushSampleCounter (0), isRunning (true) { timeSliceThread.addTimeSliceClient (this); @@ -266,6 +273,18 @@ public: } fifo.finishedRead (size1 + size2); + + if (samplesPerFlush > 0) + { + flushSampleCounter -= size1 + size2; + + if (flushSampleCounter <= 0) + { + flushSampleCounter = samplesPerFlush; + writer->flush(); + } + } + return 0; } @@ -279,6 +298,11 @@ public: samplesWritten = 0; } + void setFlushInterval (int numSamples) noexcept + { + samplesPerFlush = numSamples; + } + private: AbstractFifo fifo; AudioSampleBuffer buffer; @@ -287,6 +311,7 @@ private: CriticalSection thumbnailLock; IncomingDataReceiver* receiver; int64 samplesWritten; + int samplesPerFlush, flushSampleCounter; volatile bool isRunning; JUCE_DECLARE_NON_COPYABLE (Buffer) @@ -310,3 +335,8 @@ void AudioFormatWriter::ThreadedWriter::setDataReceiver (AudioFormatWriter::Thre { buffer->setDataReceiver (receiver); } + +void AudioFormatWriter::ThreadedWriter::setFlushInterval (int numSamplesPerFlush) noexcept +{ + buffer->setFlushInterval (numSamplesPerFlush); +} diff --git a/JuceLibraryCode/modules/juce_audio_formats/format/juce_AudioFormatWriter.h b/JuceLibraryCode/modules/juce_audio_formats/format/juce_AudioFormatWriter.h index ceb54da..6e85424 100644 --- a/JuceLibraryCode/modules/juce_audio_formats/format/juce_AudioFormatWriter.h +++ b/JuceLibraryCode/modules/juce_audio_formats/format/juce_AudioFormatWriter.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -91,8 +91,18 @@ public: to pass it into the method. @param numSamples the number of samples to write */ - virtual bool write (const int** samplesToWrite, - int numSamples) = 0; + virtual bool write (const int** samplesToWrite, int numSamples) = 0; + + /** Some formats may support a flush operation that makes sure the file is in a + valid state before carrying on. + If supported, this means that by calling flush periodically when writing data + to a large file, then it should still be left in a readable state if your program + crashes. + It goes without saying that this method must be called from the same thread that's + calling write()! + If the format supports flushing and the operation succeeds, this returns true. + */ + virtual bool flush(); //============================================================================== /** Reads a section of samples from an AudioFormatReader, and writes these to @@ -197,7 +207,12 @@ public: The object passed-in must not be deleted while this writer is still using it. */ - void setDataReceiver (IncomingDataReceiver* receiver); + void setDataReceiver (IncomingDataReceiver*); + + /** Sets how many samples should be written before calling the AudioFormatWriter::flush method. + Set this to 0 to disable flushing (this is the default). + */ + void setFlushInterval (int numSamplesPerFlush) noexcept; private: class Buffer; diff --git a/JuceLibraryCode/modules/juce_audio_formats/format/juce_AudioSubsectionReader.cpp b/JuceLibraryCode/modules/juce_audio_formats/format/juce_AudioSubsectionReader.cpp index bbe1ebd..9ca1724 100644 --- a/JuceLibraryCode/modules/juce_audio_formats/format/juce_AudioSubsectionReader.cpp +++ b/JuceLibraryCode/modules/juce_audio_formats/format/juce_AudioSubsectionReader.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -57,17 +57,10 @@ bool AudioSubsectionReader::readSamples (int** destSamples, int numDestChannels, startSampleInFile + startSample, numSamples); } -void AudioSubsectionReader::readMaxLevels (int64 startSampleInFile, - int64 numSamples, - float& lowestLeft, - float& highestLeft, - float& lowestRight, - float& highestRight) +void AudioSubsectionReader::readMaxLevels (int64 startSampleInFile, int64 numSamples, Range* results, int numChannelsToRead) { startSampleInFile = jmax ((int64) 0, startSampleInFile); numSamples = jmax ((int64) 0, jmin (numSamples, length - startSampleInFile)); - source->readMaxLevels (startSampleInFile + startSample, numSamples, - lowestLeft, highestLeft, - lowestRight, highestRight); + source->readMaxLevels (startSampleInFile + startSample, numSamples, results, numChannelsToRead); } diff --git a/JuceLibraryCode/modules/juce_audio_formats/format/juce_AudioSubsectionReader.h b/JuceLibraryCode/modules/juce_audio_formats/format/juce_AudioSubsectionReader.h index fb9e6a0..4293c45 100644 --- a/JuceLibraryCode/modules/juce_audio_formats/format/juce_AudioSubsectionReader.h +++ b/JuceLibraryCode/modules/juce_audio_formats/format/juce_AudioSubsectionReader.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -68,8 +68,7 @@ public: int64 startSampleInFile, int numSamples) override; void readMaxLevels (int64 startSample, int64 numSamples, - float& lowestLeft, float& highestLeft, - float& lowestRight, float& highestRight) override; + Range* results, int numChannelsToRead) override; private: diff --git a/JuceLibraryCode/modules/juce_audio_formats/format/juce_BufferingAudioFormatReader.cpp b/JuceLibraryCode/modules/juce_audio_formats/format/juce_BufferingAudioFormatReader.cpp index ecfe1d4..ca1e6d8 100644 --- a/JuceLibraryCode/modules/juce_audio_formats/format/juce_BufferingAudioFormatReader.cpp +++ b/JuceLibraryCode/modules/juce_audio_formats/format/juce_BufferingAudioFormatReader.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -28,7 +28,8 @@ BufferingAudioReader::BufferingAudioReader (AudioFormatReader* sourceReader, : AudioFormatReader (nullptr, sourceReader->getFormatName()), source (sourceReader), thread (timeSliceThread), nextReadPosition (0), - numBlocks (1 + (samplesToBuffer / samplesPerBlock)) + numBlocks (1 + (samplesToBuffer / samplesPerBlock)), + timeoutMs (0) { sampleRate = source->sampleRate; lengthInSamples = source->lengthInSamples; diff --git a/JuceLibraryCode/modules/juce_audio_formats/format/juce_BufferingAudioFormatReader.h b/JuceLibraryCode/modules/juce_audio_formats/format/juce_BufferingAudioFormatReader.h index 8f950be..a8f5955 100644 --- a/JuceLibraryCode/modules/juce_audio_formats/format/juce_BufferingAudioFormatReader.h +++ b/JuceLibraryCode/modules/juce_audio_formats/format/juce_BufferingAudioFormatReader.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_audio_formats/format/juce_MemoryMappedAudioFormatReader.h b/JuceLibraryCode/modules/juce_audio_formats/format/juce_MemoryMappedAudioFormatReader.h index 2ec6388..a63869b 100644 --- a/JuceLibraryCode/modules/juce_audio_formats/format/juce_MemoryMappedAudioFormatReader.h +++ b/JuceLibraryCode/modules/juce_audio_formats/format/juce_MemoryMappedAudioFormatReader.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -70,6 +70,12 @@ public: /** Touches the memory for the given sample, to force it to be loaded into active memory. */ void touchSample (int64 sample) const noexcept; + /** Returns the samples for all channels at a given sample position. + The result array must be large enough to hold a value for each channel + that this reader contains. + */ + virtual void getSample (int64 sampleIndex, float* result) const noexcept = 0; + /** Returns the number of bytes currently being mapped */ size_t getNumBytesUsed() const { return map != nullptr ? map->getSize() : 0; } @@ -91,12 +97,12 @@ protected: /** Used by AudioFormatReader subclasses to scan for min/max ranges in interleaved data. */ template - void scanMinAndMaxInterleaved (int channel, int64 startSampleInFile, int64 numSamples, float& mn, float& mx) const noexcept + Range scanMinAndMaxInterleaved (int channel, int64 startSampleInFile, int64 numSamples) const noexcept { typedef AudioData::Pointer SourceType; - SourceType (addBytesToPointer (sampleToPointer (startSampleInFile), ((int) bitsPerSample / 8) * channel), (int) numChannels) - .findMinAndMax ((size_t) numSamples, mn, mx); + return SourceType (addBytesToPointer (sampleToPointer (startSampleInFile), ((int) bitsPerSample / 8) * channel), (int) numChannels) + .findMinAndMax ((size_t) numSamples); } JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MemoryMappedAudioFormatReader) diff --git a/JuceLibraryCode/modules/juce_audio_formats/juce_audio_formats.cpp b/JuceLibraryCode/modules/juce_audio_formats/juce_audio_formats.cpp index b68042f..8a157b6 100644 --- a/JuceLibraryCode/modules/juce_audio_formats/juce_audio_formats.cpp +++ b/JuceLibraryCode/modules/juce_audio_formats/juce_audio_formats.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_audio_formats/juce_audio_formats.h b/JuceLibraryCode/modules/juce_audio_formats/juce_audio_formats.h index c15194e..13cc25f 100644 --- a/JuceLibraryCode/modules/juce_audio_formats/juce_audio_formats.h +++ b/JuceLibraryCode/modules/juce_audio_formats/juce_audio_formats.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -50,8 +50,8 @@ Enables the software-based MP3AudioFormat class. IMPORTANT DISCLAIMER: By choosing to enable the JUCE_USE_MP3AUDIOFORMAT flag and to compile this MP3 code into your software, you do so AT YOUR OWN RISK! By doing so, you are agreeing - that Raw Material Software is in no way responsible for any patent, copyright, or other - legal issues that you may suffer as a result. + that ROLI Ltd. is in no way responsible for any patent, copyright, or other legal issues + that you may suffer as a result. The code in juce_MP3AudioFormat.cpp is NOT guaranteed to be free from infringements of 3rd-party intellectual property. If you wish to use it, please seek your own independent advice about the diff --git a/JuceLibraryCode/modules/juce_audio_formats/juce_audio_formats.mm b/JuceLibraryCode/modules/juce_audio_formats/juce_audio_formats.mm index 9b32ae5..6f562c0 100644 --- a/JuceLibraryCode/modules/juce_audio_formats/juce_audio_formats.mm +++ b/JuceLibraryCode/modules/juce_audio_formats/juce_audio_formats.mm @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_audio_formats/juce_module_info b/JuceLibraryCode/modules/juce_audio_formats/juce_module_info index 69f5c09..78dc367 100644 --- a/JuceLibraryCode/modules/juce_audio_formats/juce_module_info +++ b/JuceLibraryCode/modules/juce_audio_formats/juce_module_info @@ -1,7 +1,7 @@ { "id": "juce_audio_formats", "name": "JUCE audio file format codecs", - "version": "3.0.6", + "version": "3.2.0", "description": "Classes for reading and writing various audio file formats.", "website": "http://www.juce.com/juce", "license": "GPL/Commercial", diff --git a/JuceLibraryCode/modules/juce_audio_formats/sampler/juce_Sampler.cpp b/JuceLibraryCode/modules/juce_audio_formats/sampler/juce_Sampler.cpp index 9dbe7b3..7440c16 100644 --- a/JuceLibraryCode/modules/juce_audio_formats/sampler/juce_Sampler.cpp +++ b/JuceLibraryCode/modules/juce_audio_formats/sampler/juce_Sampler.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -59,12 +59,12 @@ SamplerSound::~SamplerSound() { } -bool SamplerSound::appliesToNote (const int midiNoteNumber) +bool SamplerSound::appliesToNote (int midiNoteNumber) { return midiNotes [midiNoteNumber]; } -bool SamplerSound::appliesToChannel (const int /*midiChannel*/) +bool SamplerSound::appliesToChannel (int /*midiChannel*/) { return true; } @@ -119,7 +119,7 @@ void SamplerVoice::startNote (const int midiNoteNumber, if (sound->releaseSamples > 0) releaseDelta = (float) (-pitchRatio / sound->releaseSamples); else - releaseDelta = 0.0f; + releaseDelta = -1.0f; } else { @@ -127,7 +127,7 @@ void SamplerVoice::startNote (const int midiNoteNumber, } } -void SamplerVoice::stopNote (const bool allowTailOff) +void SamplerVoice::stopNote (float /*velocity*/, bool allowTailOff) { if (allowTailOff) { @@ -197,7 +197,7 @@ void SamplerVoice::renderNextBlock (AudioSampleBuffer& outputBuffer, int startSa if (attackReleaseLevel <= 0.0f) { - stopNote (false); + stopNote (0.0f, false); break; } } @@ -216,7 +216,7 @@ void SamplerVoice::renderNextBlock (AudioSampleBuffer& outputBuffer, int startSa if (sourceSamplePosition > playingSound->length) { - stopNote (false); + stopNote (0.0f, false); break; } } diff --git a/JuceLibraryCode/modules/juce_audio_formats/sampler/juce_Sampler.h b/JuceLibraryCode/modules/juce_audio_formats/sampler/juce_Sampler.h index 51133ad..74a8afc 100644 --- a/JuceLibraryCode/modules/juce_audio_formats/sampler/juce_Sampler.h +++ b/JuceLibraryCode/modules/juce_audio_formats/sampler/juce_Sampler.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -82,8 +82,8 @@ public: //============================================================================== - bool appliesToNote (const int midiNoteNumber) override; - bool appliesToChannel (const int midiChannel) override; + bool appliesToNote (int midiNoteNumber) override; + bool appliesToChannel (int midiChannel) override; private: @@ -124,9 +124,9 @@ public: bool canPlaySound (SynthesiserSound*) override; void startNote (int midiNoteNumber, float velocity, SynthesiserSound*, int pitchWheel) override; - void stopNote (bool allowTailOff) override; + void stopNote (float velocity, bool allowTailOff) override; - void pitchWheelMoved (int newValue); + void pitchWheelMoved (int newValue) override; void controllerMoved (int controllerNumber, int newValue) override; void renderNextBlock (AudioSampleBuffer&, int startSample, int numSamples) override; diff --git a/JuceLibraryCode/modules/juce_audio_processors/format/juce_AudioPluginFormat.cpp b/JuceLibraryCode/modules/juce_audio_processors/format/juce_AudioPluginFormat.cpp index cbd2542..9b534a8 100644 --- a/JuceLibraryCode/modules/juce_audio_processors/format/juce_AudioPluginFormat.cpp +++ b/JuceLibraryCode/modules/juce_audio_processors/format/juce_AudioPluginFormat.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_audio_processors/format/juce_AudioPluginFormat.h b/JuceLibraryCode/modules/juce_audio_processors/format/juce_AudioPluginFormat.h index d0af201..8f299a8 100644 --- a/JuceLibraryCode/modules/juce_audio_processors/format/juce_AudioPluginFormat.h +++ b/JuceLibraryCode/modules/juce_audio_processors/format/juce_AudioPluginFormat.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_audio_processors/format/juce_AudioPluginFormatManager.cpp b/JuceLibraryCode/modules/juce_audio_processors/format/juce_AudioPluginFormatManager.cpp index 0afa7c7..e27f128 100644 --- a/JuceLibraryCode/modules/juce_audio_processors/format/juce_AudioPluginFormatManager.cpp +++ b/JuceLibraryCode/modules/juce_audio_processors/format/juce_AudioPluginFormatManager.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_audio_processors/format/juce_AudioPluginFormatManager.h b/JuceLibraryCode/modules/juce_audio_processors/format/juce_AudioPluginFormatManager.h index a6f1607..f810f32 100644 --- a/JuceLibraryCode/modules/juce_audio_processors/format/juce_AudioPluginFormatManager.h +++ b/JuceLibraryCode/modules/juce_audio_processors/format/juce_AudioPluginFormatManager.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_audio_processors/format_types/juce_AudioUnitPluginFormat.h b/JuceLibraryCode/modules/juce_audio_processors/format_types/juce_AudioUnitPluginFormat.h index 46c2b10..b0738ed 100644 --- a/JuceLibraryCode/modules/juce_audio_processors/format_types/juce_AudioUnitPluginFormat.h +++ b/JuceLibraryCode/modules/juce_audio_processors/format_types/juce_AudioUnitPluginFormat.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_audio_processors/format_types/juce_AudioUnitPluginFormat.mm b/JuceLibraryCode/modules/juce_audio_processors/format_types/juce_AudioUnitPluginFormat.mm index a4e58b1..035220d 100644 --- a/JuceLibraryCode/modules/juce_audio_processors/format_types/juce_AudioUnitPluginFormat.mm +++ b/JuceLibraryCode/modules/juce_audio_processors/format_types/juce_AudioUnitPluginFormat.mm @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -62,7 +62,7 @@ namespace AudioUnitFormatHelpers static ThreadLocalValue insideCallback; #endif - String osTypeToString (OSType type) + String osTypeToString (OSType type) noexcept { const juce_wchar s[4] = { (juce_wchar) ((type >> 24) & 0xff), (juce_wchar) ((type >> 16) & 0xff), @@ -88,9 +88,6 @@ namespace AudioUnitFormatHelpers String createPluginIdentifier (const AudioComponentDescription& desc) { - jassert (osTypeToString ('abcd') == "abcd"); // agh, must have got the endianness wrong.. - jassert (stringToOSType ("abcd") == (OSType) 'abcd'); // ditto - String s (auIdentifierPrefix); if (desc.componentType == kAudioUnitType_MusicDevice) @@ -187,7 +184,7 @@ namespace AudioUnitFormatHelpers const char* const utf8 = fileOrIdentifier.toUTF8(); if (CFURLRef url = CFURLCreateFromFileSystemRepresentation (0, (const UInt8*) utf8, - strlen (utf8), file.isDirectory())) + (CFIndex) strlen (utf8), file.isDirectory())) { CFBundleRef bundleRef = CFBundleCreate (kCFAllocatorDefault, url); CFRelease (url); @@ -215,9 +212,11 @@ namespace AudioUnitFormatHelpers const short resFileId = CFBundleOpenBundleResourceMap (bundleRef); UseResFile (resFileId); - for (ResourceIndex i = 1; i <= Count1Resources ('thng'); ++i) + const OSType thngType = stringToOSType ("thng"); + + for (ResourceIndex i = 1; i <= Count1Resources (thngType); ++i) { - if (Handle h = Get1IndResource ('thng', i)) + if (Handle h = Get1IndResource (thngType, i)) { HLock (h); const uint32* const types = (const uint32*) *h; @@ -346,11 +345,21 @@ public: refreshParameterList(); updateNumChannels(); producesMidiMessages = canProduceMidiOutput(); - setPluginCallbacks(); - setPlayConfigDetails (numInputBusChannels * numInputBusses, - numOutputBusChannels * numOutputBusses, + setPlayConfigDetails ((int) (numInputBusChannels * numInputBusses), + (int) (numOutputBusChannels * numOutputBusses), rate, blockSize); setLatencySamples (0); + + if (parameters.size() == 0) + { + // some plugins crash if initialiseAudioUnit() is called too soon (sigh..), so we'll + // only call it here if it seems like they it's one of the awkward plugins that can + // only create their parameters after it has been initialised. + initialiseAudioUnit(); + refreshParameterList(); + } + + setPluginCallbacks(); } //============================================================================== @@ -411,7 +420,7 @@ public: UInt32 sampleRateSize = sizeof (sampleRateIn); const Float64 sr = newSampleRate; - for (int i = 0; i < numInputBusses; ++i) + for (AudioUnitElement i = 0; i < numInputBusses; ++i) { AudioUnitGetProperty (audioUnit, kAudioUnitProperty_SampleRate, kAudioUnitScope_Input, i, &sampleRateIn, &sampleRateSize); @@ -419,7 +428,7 @@ public: AudioUnitSetProperty (audioUnit, kAudioUnitProperty_SampleRate, kAudioUnitScope_Input, i, &sr, sizeof (sr)); } - for (int i = 0; i < numOutputBusses; ++i) + for (AudioUnitElement i = 0; i < numOutputBusses; ++i) { AudioUnitGetProperty (audioUnit, kAudioUnitProperty_SampleRate, kAudioUnitScope_Output, i, &sampleRateOut, &sampleRateSize); @@ -431,9 +440,9 @@ public: AudioUnitSetProperty (audioUnit, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global, 0, &frameSize, sizeof (frameSize)); - setPlayConfigDetails (numInputBusChannels * numInputBusses, - numOutputBusChannels * numOutputBusses, - newSampleRate, estimatedSamplesPerBlock); + setPlayConfigDetails ((int) (numInputBusChannels * numInputBusses), + (int) (numOutputBusChannels * numOutputBusses), + (double) newSampleRate, estimatedSamplesPerBlock); Float64 latencySecs = 0.0; UInt32 latencySize = sizeof (latencySecs); @@ -454,13 +463,13 @@ public: stream.mBitsPerChannel = 32; stream.mChannelsPerFrame = numInputBusChannels; - for (int i = 0; i < numInputBusses; ++i) + for (AudioUnitElement i = 0; i < numInputBusses; ++i) AudioUnitSetProperty (audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, i, &stream, sizeof (stream)); stream.mChannelsPerFrame = numOutputBusChannels; - for (int i = 0; i < numOutputBusses; ++i) + for (AudioUnitElement i = 0; i < numOutputBusses; ++i) AudioUnitSetProperty (audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, i, &stream, sizeof (stream)); } @@ -509,8 +518,8 @@ public: void resetBusses() { - for (int i = 0; i < numInputBusses; ++i) AudioUnitReset (audioUnit, kAudioUnitScope_Input, i); - for (int i = 0; i < numOutputBusses; ++i) AudioUnitReset (audioUnit, kAudioUnitScope_Output, i); + for (AudioUnitElement i = 0; i < numInputBusses; ++i) AudioUnitReset (audioUnit, kAudioUnitScope_Input, i); + for (AudioUnitElement i = 0; i < numOutputBusses; ++i) AudioUnitReset (audioUnit, kAudioUnitScope_Output, i); } void processBlock (AudioSampleBuffer& buffer, MidiBuffer& midiMessages) override @@ -521,17 +530,17 @@ public: { timeStamp.mHostTime = AudioGetCurrentHostTime(); - for (int i = 0; i < numOutputBusses; ++i) + for (AudioUnitElement i = 0; i < numOutputBusses; ++i) { if (AudioBufferList* const abl = getAudioBufferListForBus(i)) { abl->mNumberBuffers = numOutputBusChannels; - for (int j = 0; j < numOutputBusChannels; ++j) + for (AudioUnitElement j = 0; j < numOutputBusChannels; ++j) { abl->mBuffers[j].mNumberChannels = 1; - abl->mBuffers[j].mDataByteSize = sizeof (float) * numSamples; - abl->mBuffers[j].mData = buffer.getWritePointer (i * numOutputBusChannels + j); + abl->mBuffers[j].mDataByteSize = sizeof (float) * (size_t) numSamples; + abl->mBuffers[j].mData = buffer.getWritePointer ((int) (i * numOutputBusChannels + j)); } } } @@ -548,19 +557,19 @@ public: if (midiEventSize <= 3) MusicDeviceMIDIEvent (audioUnit, midiEventData[0], midiEventData[1], midiEventData[2], - midiEventPosition); + (UInt32) midiEventPosition); else - MusicDeviceSysEx (audioUnit, midiEventData, midiEventSize); + MusicDeviceSysEx (audioUnit, midiEventData, (UInt32) midiEventSize); } midiMessages.clear(); } - for (int i = 0; i < numOutputBusses; ++i) + for (AudioUnitElement i = 0; i < numOutputBusses; ++i) { AudioUnitRenderActionFlags flags = 0; - AudioUnitRender (audioUnit, &flags, &timeStamp, i, numSamples, getAudioBufferListForBus (i)); + AudioUnitRender (audioUnit, &flags, &timeStamp, i, (UInt32) numSamples, getAudioBufferListForBus (i)); } timeStamp.mSampleTime += numSamples; @@ -787,7 +796,7 @@ public: CFDataRef data = (CFDataRef) CFWriteStreamCopyProperty (stream, kCFStreamPropertyDataWritten); - destData.setSize (bytesWritten); + destData.setSize ((size_t) bytesWritten); destData.copyFrom (CFDataGetBytePtr (data), 0, destData.getSize()); CFRelease (data); @@ -902,7 +911,7 @@ private: HeapBlock outputBufferList; AudioTimeStamp timeStamp; AudioSampleBuffer* currentBuffer; - int numInputBusChannels, numOutputBusChannels, numInputBusses, numOutputBusses; + AudioUnitElement numInputBusChannels, numOutputBusChannels, numInputBusses, numOutputBusses; AudioUnit audioUnit; AUEventListenerRef eventListenerRef; @@ -932,7 +941,7 @@ private: info.inputProcRefCon = this; info.inputProc = renderGetInputCallback; - for (int i = 0; i < numInputBusses; ++i) + for (AudioUnitElement i = 0; i < numInputBusses; ++i) AudioUnitSetProperty (audioUnit, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, i, &info, sizeof (info)); } @@ -972,16 +981,11 @@ private: for (int i = 0; i < parameters.size(); ++i) { - const ParamInfo& p = *parameters.getUnchecked(i); - - AudioUnitParameter paramToAdd; - paramToAdd.mAudioUnit = audioUnit; - paramToAdd.mParameterID = p.paramID; - paramToAdd.mScope = kAudioUnitScope_Global; - paramToAdd.mElement = 0; - AudioUnitEvent event; - event.mArgument.mParameter = paramToAdd; + event.mArgument.mParameter.mAudioUnit = audioUnit; + event.mArgument.mParameter.mParameterID = parameters.getUnchecked(i)->paramID; + event.mArgument.mParameter.mScope = kAudioUnitScope_Global; + event.mArgument.mParameter.mElement = 0; event.mEventType = kAudioUnitEvent_ParameterValueChange; AUEventListenerAddEventType (eventListenerRef, nullptr, &event); @@ -992,6 +996,16 @@ private: event.mEventType = kAudioUnitEvent_EndParameterChangeGesture; AUEventListenerAddEventType (eventListenerRef, nullptr, &event); } + + // Add a listener for program changes + AudioUnitEvent event; + event.mArgument.mProperty.mAudioUnit = audioUnit; + event.mArgument.mProperty.mPropertyID = kAudioUnitProperty_PresentPreset; + event.mArgument.mProperty.mScope = kAudioUnitScope_Global; + event.mArgument.mProperty.mElement = 0; + + event.mEventType = kAudioUnitEvent_PropertyChange; + AUEventListenerAddEventType (eventListenerRef, nullptr, &event); } } @@ -1014,14 +1028,15 @@ private: break; case kAudioUnitEvent_BeginParameterChangeGesture: - beginParameterChangeGesture (event.mArgument.mParameter.mParameterID); + beginParameterChangeGesture ((int) event.mArgument.mParameter.mParameterID); break; case kAudioUnitEvent_EndParameterChangeGesture: - endParameterChangeGesture (event.mArgument.mParameter.mParameterID); + endParameterChangeGesture ((int) event.mArgument.mParameter.mParameterID); break; default: + sendAllParametersChangedEvents(); break; } } @@ -1047,7 +1062,7 @@ private: for (UInt32 i = 0; i < ioData->mNumberBuffers; ++i) { - const int bufferChannel = inBusNumber * numInputBusChannels + i; + const int bufferChannel = (int) (inBusNumber * numInputBusChannels + i); if (bufferChannel < currentBuffer->getNumChannels()) { @@ -1116,16 +1131,16 @@ private: if (ph != nullptr && ph->getCurrentPosition (result)) { - setIfNotNull (outTimeSig_Numerator, result.timeSigNumerator); - setIfNotNull (outTimeSig_Denominator, result.timeSigDenominator); - setIfNotNull (outDeltaSampleOffsetToNextBeat, 0); //xxx + setIfNotNull (outTimeSig_Numerator, (UInt32) result.timeSigNumerator); + setIfNotNull (outTimeSig_Denominator, (UInt32) result.timeSigDenominator); + setIfNotNull (outDeltaSampleOffsetToNextBeat, (UInt32) 0); //xxx setIfNotNull (outCurrentMeasureDownBeat, result.ppqPositionOfLastBarStart); //xxx wrong } else { - setIfNotNull (outDeltaSampleOffsetToNextBeat, 0); - setIfNotNull (outTimeSig_Numerator, 4); - setIfNotNull (outTimeSig_Denominator, 4); + setIfNotNull (outDeltaSampleOffsetToNextBeat, (UInt32) 0); + setIfNotNull (outTimeSig_Numerator, (UInt32) 4); + setIfNotNull (outTimeSig_Denominator, (UInt32) 4); setIfNotNull (outCurrentMeasureDownBeat, 0); } @@ -1211,12 +1226,12 @@ private: return offsetof (AudioBufferList, mBuffers) + (sizeof (AudioBuffer) * numOutputBusChannels); } - AudioBufferList* getAudioBufferListForBus (int busIndex) const noexcept + AudioBufferList* getAudioBufferListForBus (AudioUnitElement busIndex) const noexcept { return addBytesToPointer (outputBufferList.getData(), getAudioBufferSizeInBytes() * busIndex); } - int getElementCount (AudioUnitScope scope) const noexcept + AudioUnitElement getElementCount (AudioUnitScope scope) const noexcept { UInt32 count; UInt32 countSize = sizeof (count); @@ -1225,7 +1240,7 @@ private: || countSize == 0) count = 1; - return (int) count; + return count; } void updateNumChannels() @@ -1251,17 +1266,17 @@ private: const int outChannels = (int) supportedChannels[i].outChannels; if (inChannels < 0) - maximumNumIns = jmin (maximumNumIns, inChannels); + maximumNumIns = jmin (maximumNumIns, inChannels); else explicitNumIns = jmax (explicitNumIns, inChannels); if (outChannels < 0) - maximumNumOuts = jmin (maximumNumOuts, outChannels); + maximumNumOuts = jmin (maximumNumOuts, outChannels); else explicitNumOuts = jmax (explicitNumOuts, outChannels); } - if ((maximumNumIns == -1 && maximumNumOuts == -1) // (special meaning: any number of ins/outs, as long as they match) + if ((maximumNumIns == -1 && maximumNumOuts == -1) // (special meaning: any number of ins/outs, as long as they match) || (maximumNumIns == -2 && maximumNumOuts == -1) // (special meaning: any number of ins/outs, even if they don't match) || (maximumNumIns == -1 && maximumNumOuts == -2)) { @@ -1269,8 +1284,8 @@ private: } else { - numInputBusChannels = explicitNumIns; - numOutputBusChannels = explicitNumOuts; + numInputBusChannels = (AudioUnitElement) explicitNumIns; + numOutputBusChannels = (AudioUnitElement) explicitNumOuts; if (maximumNumIns == -1 || (maximumNumIns < 0 && explicitNumIns <= -maximumNumIns)) numInputBusChannels = 2; diff --git a/JuceLibraryCode/modules/juce_audio_processors/format_types/juce_LADSPAPluginFormat.cpp b/JuceLibraryCode/modules/juce_audio_processors/format_types/juce_LADSPAPluginFormat.cpp index 81b369a..d315b07 100644 --- a/JuceLibraryCode/modules/juce_audio_processors/format_types/juce_LADSPAPluginFormat.cpp +++ b/JuceLibraryCode/modules/juce_audio_processors/format_types/juce_LADSPAPluginFormat.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -118,8 +118,8 @@ class LADSPAPluginInstance : public AudioPluginInstance { public: LADSPAPluginInstance (const LADSPAModuleHandle::Ptr& m) - : plugin (nullptr), handle (nullptr), initialised (false), - tempBuffer (1, 1), module (m) + : module (m), plugin (nullptr), handle (nullptr), + initialised (false), tempBuffer (1, 1) { ++insideLADSPACallback; diff --git a/JuceLibraryCode/modules/juce_audio_processors/format_types/juce_LADSPAPluginFormat.h b/JuceLibraryCode/modules/juce_audio_processors/format_types/juce_LADSPAPluginFormat.h index 21d3167..15c1095 100644 --- a/JuceLibraryCode/modules/juce_audio_processors/format_types/juce_LADSPAPluginFormat.h +++ b/JuceLibraryCode/modules/juce_audio_processors/format_types/juce_LADSPAPluginFormat.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_audio_processors/format_types/juce_VST3Common.h b/JuceLibraryCode/modules/juce_audio_processors/format_types/juce_VST3Common.h index d7e66cd..0017e1c 100644 --- a/JuceLibraryCode/modules/juce_audio_processors/format_types/juce_VST3Common.h +++ b/JuceLibraryCode/modules/juce_audio_processors/format_types/juce_VST3Common.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -250,7 +250,7 @@ public: break; case Steinberg::Vst::Event::kDataEvent: - result.addEvent (MidiMessage::createSysExMessage (e.data.bytes, e.data.size), + result.addEvent (MidiMessage::createSysExMessage (e.data.bytes, (int) e.data.size), e.sampleOffset); break; @@ -300,7 +300,7 @@ public: { e.type = Steinberg::Vst::Event::kDataEvent; e.data.bytes = msg.getSysExData(); - e.data.size = msg.getSysExDataSize(); + e.data.size = (uint32) msg.getSysExDataSize(); e.data.type = Steinberg::Vst::DataEvent::kMidiSysEx; } else if (msg.isAftertouch()) diff --git a/JuceLibraryCode/modules/juce_audio_processors/format_types/juce_VST3Headers.h b/JuceLibraryCode/modules/juce_audio_processors/format_types/juce_VST3Headers.h index ffb90e8..50b8552 100644 --- a/JuceLibraryCode/modules/juce_audio_processors/format_types/juce_VST3Headers.h +++ b/JuceLibraryCode/modules/juce_audio_processors/format_types/juce_VST3Headers.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_audio_processors/format_types/juce_VST3PluginFormat.cpp b/JuceLibraryCode/modules/juce_audio_processors/format_types/juce_VST3PluginFormat.cpp index 7abe6e3..4de9ec8 100644 --- a/JuceLibraryCode/modules/juce_audio_processors/format_types/juce_VST3PluginFormat.cpp +++ b/JuceLibraryCode/modules/juce_audio_processors/format_types/juce_VST3PluginFormat.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -364,7 +364,6 @@ class VST3HostContext : public Vst::IComponentHandler, // From VST V3.0.0 public Vst::IComponentHandler3, // From VST V3.5.0 (also very well named!) public Vst::IContextMenuTarget, public Vst::IHostApplication, - public Vst::IParamValueQueue, public Vst::IUnitHandler { public: @@ -428,16 +427,11 @@ public: if (hasFlag (flags, Vst::kIoChanged)) { - double sampleRate = owner->getSampleRate(); - int numSamples = owner->getBlockSize(); + const double sampleRate = owner->getSampleRate(); + const int blockSize = owner->getBlockSize(); - if (sampleRate <= 8000.0) - sampleRate = 44100.0; - - if (numSamples <= 0) - numSamples = 1024; - - owner->prepareToPlay (owner->getSampleRate(), owner->getBlockSize()); + owner->prepareToPlay (sampleRate >= 8000 ? sampleRate : 44100.0, + blockSize > 0 ? blockSize : 1024); } if (hasFlag (flags, Vst::kLatencyChanged)) @@ -689,31 +683,6 @@ public: return kNotImplemented; } - //============================================================================== - Vst::ParamID PLUGIN_API getParameterId() override - { - jassertfalse; - return 0; - } - - Steinberg::int32 PLUGIN_API getPointCount() override - { - jassertfalse; - return 0; - } - - tresult PLUGIN_API getPoint (Steinberg::int32, Steinberg::int32&, Vst::ParamValue&) override - { - jassertfalse; - return kResultFalse; - } - - tresult PLUGIN_API addPoint (Steinberg::int32, Vst::ParamValue, Steinberg::int32&) override - { - jassertfalse; - return kResultFalse; - } - //============================================================================== tresult PLUGIN_API notifyUnitSelection (Vst::UnitID) override { @@ -741,7 +710,6 @@ public: TEST_FOR_AND_RETURN_IF_VALID (iid, Vst::IComponentHandler3) TEST_FOR_AND_RETURN_IF_VALID (iid, Vst::IContextMenuTarget) TEST_FOR_AND_RETURN_IF_VALID (iid, Vst::IHostApplication) - TEST_FOR_AND_RETURN_IF_VALID (iid, Vst::IParamValueQueue) TEST_FOR_AND_RETURN_IF_VALID (iid, Vst::IUnitHandler) TEST_FOR_COMMON_BASE_AND_RETURN_IF_VALID (iid, FUnknown, Vst::IComponentHandler) @@ -842,47 +810,26 @@ private: //============================================================================== tresult PLUGIN_API setInt (AttrID id, Steinberg::int64 value) override { - jassert (id != nullptr); - - if (! setValueForId (id, value)) - owner->messageQueue.add (ComSmartPtr (new Message (*owner, this, id, value))); - + addMessageToQueue (id, value); return kResultTrue; } tresult PLUGIN_API setFloat (AttrID id, double value) override { - jassert (id != nullptr); - - if (! setValueForId (id, value)) - owner->messageQueue.add (ComSmartPtr (new Message (*owner, this, id, value))); - + addMessageToQueue (id, value); return kResultTrue; } tresult PLUGIN_API setString (AttrID id, const Vst::TChar* string) override { - jassert (id != nullptr); - jassert (string != nullptr); - - const String text (toString (string)); - - if (! setValueForId (id, text)) - owner->messageQueue.add (ComSmartPtr (new Message (*owner, this, id, text))); - + addMessageToQueue (id, toString (string)); return kResultTrue; } tresult PLUGIN_API setBinary (AttrID id, const void* data, Steinberg::uint32 size) override { - jassert (id != nullptr); - jassert (data != nullptr && size > 0); - - MemoryBlock block (data, (size_t) size); - - if (! setValueForId (id, block)) - owner->messageQueue.add (ComSmartPtr (new Message (*owner, this, id, block))); - + jassert (size >= 0 && (data != nullptr || size == 0)); + addMessageToQueue (id, MemoryBlock (data, (size_t) size)); return kResultTrue; } @@ -891,7 +838,7 @@ private: { jassert (id != nullptr); - if (fetchValueForId (id, result)) + if (findMessageOnQueueWithID (id, result)) return kResultTrue; jassertfalse; @@ -902,7 +849,7 @@ private: { jassert (id != nullptr); - if (fetchValueForId (id, result)) + if (findMessageOnQueueWithID (id, result)) return kResultTrue; jassertfalse; @@ -914,7 +861,7 @@ private: jassert (id != nullptr); String stringToFetch; - if (fetchValueForId (id, stringToFetch)) + if (findMessageOnQueueWithID (id, stringToFetch)) { Steinberg::String str (stringToFetch.toRawUTF8()); str.copyTo (result, 0, (Steinberg::int32) jmin (length, (Steinberg::uint32) std::numeric_limits::max())); @@ -954,7 +901,7 @@ private: //============================================================================== template - bool setValueForId (AttrID id, const Type& value) + void addMessageToQueue (AttrID id, const Type& value) { jassert (id != nullptr); @@ -965,15 +912,15 @@ private: if (std::strcmp (message->getMessageID(), id) == 0) { message->value = value; - return true; + return; } } - return false; // No message found with that Id + owner->messageQueue.add (ComSmartPtr (new Message (*owner, this, id, value))); } template - bool fetchValueForId (AttrID id, Type& value) + bool findMessageOnQueueWithID (AttrID id, Type& value) { jassert (id != nullptr); @@ -1449,7 +1396,9 @@ public: ~VST3PluginWindow() { warnOnFailure (view->removed()); - getAudioProcessor()->editorBeingDeleted (this); + warnOnFailure (view->setFrame (nullptr)); + + processor.editorBeingDeleted (this); #if JUCE_MAC dummyComponent.setView (nullptr); @@ -1634,8 +1583,8 @@ public: : module (handle), numInputAudioBusses (0), numOutputAudioBusses (0), - inputParameterChanges (new ParameterChangeList()), - outputParameterChanges (new ParameterChangeList()), + inputParameterChanges (new ParamValueQueueList()), + outputParameterChanges (new ParamValueQueueList()), midiInputs (new MidiEventList()), midiOutputs (new MidiEventList()), isComponentInitialised (false), @@ -1849,6 +1798,8 @@ public: processor->process (data); MidiEventList::toMidiBuffer (midiMessages, *midiOutputs); + + inputParameterChanges->clearAllQueues(); } } @@ -1979,8 +1930,11 @@ public: { if (editController != nullptr) { - const uint32 id = getParameterInfoForIndex (parameterIndex).id; - editController->setParamNormalized (id, (double) newValue); + const uint32 paramID = getParameterInfoForIndex (parameterIndex).id; + editController->setParamNormalized (paramID, (double) newValue); + + Steinberg::int32 index; + inputParameterChanges->addParameterData (paramID, index)->addPoint (0, newValue, index); } } @@ -2055,6 +2009,115 @@ public: (void) sizeInBytes; } + //============================================================================== + // NB: this class and its subclasses must be public to avoid problems in + // DLL builds under MSVC. + class ParamValueQueueList : public Vst::IParameterChanges + { + public: + ParamValueQueueList() {} + virtual ~ParamValueQueueList() {} + + JUCE_DECLARE_VST3_COM_REF_METHODS + JUCE_DECLARE_VST3_COM_QUERY_METHODS + + Steinberg::int32 PLUGIN_API getParameterCount() override { return (Steinberg::int32) queues.size(); } + Vst::IParamValueQueue* PLUGIN_API getParameterData (Steinberg::int32 index) override { return queues[(int) index]; } + + Vst::IParamValueQueue* PLUGIN_API addParameterData (const Vst::ParamID& id, Steinberg::int32& index) override + { + for (int i = queues.size(); --i >= 0;) + { + if (queues.getUnchecked (i)->getParameterId() == id) + { + index = (Steinberg::int32) i; + return queues.getUnchecked (i); + } + } + + index = getParameterCount(); + return queues.add (new ParamValueQueue (id)); + } + + void clearAllQueues() noexcept + { + for (int i = queues.size(); --i >= 0;) + queues.getUnchecked (i)->clear(); + } + + struct ParamValueQueue : public Vst::IParamValueQueue + { + ParamValueQueue (Vst::ParamID parameterID) : paramID (parameterID) + { + points.ensureStorageAllocated (1024); + } + + virtual ~ParamValueQueue() {} + + JUCE_DECLARE_VST3_COM_REF_METHODS + JUCE_DECLARE_VST3_COM_QUERY_METHODS + + Steinberg::Vst::ParamID PLUGIN_API getParameterId() override { return paramID; } + Steinberg::int32 PLUGIN_API getPointCount() override { return (Steinberg::int32) points.size(); } + + Steinberg::tresult PLUGIN_API getPoint (Steinberg::int32 index, + Steinberg::int32& sampleOffset, + Steinberg::Vst::ParamValue& value) override + { + const ScopedLock sl (pointLock); + + if (isPositiveAndBelow ((int) index, points.size())) + { + ParamPoint e (points.getUnchecked ((int) index)); + sampleOffset = e.sampleOffset; + value = e.value; + return kResultTrue; + } + + sampleOffset = -1; + value = 0.0; + return kResultFalse; + } + + Steinberg::tresult PLUGIN_API addPoint (Steinberg::int32 sampleOffset, + Steinberg::Vst::ParamValue value, + Steinberg::int32& index) override + { + ParamPoint p = { sampleOffset, value }; + + const ScopedLock sl (pointLock); + index = (Steinberg::int32) points.size(); + points.add (p); + return kResultTrue; + } + + void clear() noexcept + { + const ScopedLock sl (pointLock); + points.clearQuick(); + } + + private: + struct ParamPoint + { + Steinberg::int32 sampleOffset; + Steinberg::Vst::ParamValue value; + }; + + Atomic refCount; + const Vst::ParamID paramID; + Array points; + CriticalSection pointLock; + + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ParamValueQueue) + }; + + Atomic refCount; + OwnedArray queues; + + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ParamValueQueueList) + }; + private: //============================================================================== VST3ModuleHandle::Ptr module; @@ -2100,7 +2163,7 @@ private: if (object->getState (&stream) == kResultTrue) { - MemoryBlock info (stream.getData(), (std::size_t) stream.getSize()); + MemoryBlock info (stream.getData(), (size_t) stream.getSize()); head.createNewChildElement (identifier)->addTextElement (info.toBase64Encoding()); } } @@ -2115,42 +2178,17 @@ private: MemoryBlock mem; if (mem.fromBase64Encoding (state->getAllSubText())) - stream = new Steinberg::MemoryStream (mem.getData(), (TSize) mem.getSize()); + { + stream = new Steinberg::MemoryStream(); + stream->setSize ((TSize) mem.getSize()); + mem.copyTo (stream->getData(), 0, mem.getSize()); + } } return stream; } - //============================================================================== - class ParameterChangeList : public Vst::IParameterChanges - { - public: - ParameterChangeList() {} - virtual ~ParameterChangeList() {} - - JUCE_DECLARE_VST3_COM_REF_METHODS - JUCE_DECLARE_VST3_COM_QUERY_METHODS - - Steinberg::int32 PLUGIN_API getParameterCount() override { return 0; } - - Vst::IParamValueQueue* PLUGIN_API getParameterData (Steinberg::int32) override - { - return nullptr; - } - - Vst::IParamValueQueue* PLUGIN_API addParameterData (const Vst::ParamID&, Steinberg::int32& index) override - { - index = 0; - return nullptr; - } - - private: - Atomic refCount; - - JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ParameterChangeList) - }; - - ComSmartPtr inputParameterChanges, outputParameterChanges; + ComSmartPtr inputParameterChanges, outputParameterChanges; ComSmartPtr midiInputs, midiOutputs; Vst::ProcessContext timingInfo; //< Only use this in processBlock()! bool isComponentInitialised, isControllerInitialised, isActive; diff --git a/JuceLibraryCode/modules/juce_audio_processors/format_types/juce_VST3PluginFormat.h b/JuceLibraryCode/modules/juce_audio_processors/format_types/juce_VST3PluginFormat.h index 308ff5a..ceabcbc 100644 --- a/JuceLibraryCode/modules/juce_audio_processors/format_types/juce_VST3PluginFormat.h +++ b/JuceLibraryCode/modules/juce_audio_processors/format_types/juce_VST3PluginFormat.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_audio_processors/format_types/juce_VSTMidiEventList.h b/JuceLibraryCode/modules/juce_audio_processors/format_types/juce_VSTMidiEventList.h index f442eab..bf7bc4b 100644 --- a/JuceLibraryCode/modules/juce_audio_processors/format_types/juce_VSTMidiEventList.h +++ b/JuceLibraryCode/modules/juce_audio_processors/format_types/juce_VSTMidiEventList.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -184,4 +184,4 @@ private: }; #endif // JUCE_VSTMIDIEVENTLIST_H_INCLUDED -#endif +#endif // JUCE_VSTMIDIEVENTLIST_H_INCLUDED diff --git a/JuceLibraryCode/modules/juce_audio_processors/format_types/juce_VSTPluginFormat.cpp b/JuceLibraryCode/modules/juce_audio_processors/format_types/juce_VSTPluginFormat.cpp index 458d59b..0a88d5c 100644 --- a/JuceLibraryCode/modules/juce_audio_processors/format_types/juce_VSTPluginFormat.cpp +++ b/JuceLibraryCode/modules/juce_audio_processors/format_types/juce_VSTPluginFormat.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -29,13 +29,6 @@ #include "../../juce_gui_extra/native/juce_mac_CarbonViewWrapperComponent.h" #endif -#if JUCE_MAC - static bool makeFSRefFromPath (FSRef* destFSRef, const String& path) - { - return FSPathMakeRef (reinterpret_cast (path.toRawUTF8()), destFSRef, 0) == noErr; - } -#endif - //============================================================================== #undef PRAGMA_ALIGN_SUPPORTED #define VST_FORCE_DEPRECATED 0 @@ -84,74 +77,75 @@ #endif //============================================================================== -const int fxbVersionNum = 1; - -struct fxProgram -{ - VstInt32 chunkMagic; // 'CcnK' - VstInt32 byteSize; // of this chunk, excl. magic + byteSize - VstInt32 fxMagic; // 'FxCk' - VstInt32 version; - VstInt32 fxID; // fx unique id - VstInt32 fxVersion; - VstInt32 numParams; - char prgName[28]; - float params[1]; // variable no. of parameters -}; - -struct fxSet -{ - VstInt32 chunkMagic; // 'CcnK' - VstInt32 byteSize; // of this chunk, excl. magic + byteSize - VstInt32 fxMagic; // 'FxBk' - VstInt32 version; - VstInt32 fxID; // fx unique id - VstInt32 fxVersion; - VstInt32 numPrograms; - char future[128]; - fxProgram programs[1]; // variable no. of programs -}; - -struct fxChunkSet -{ - VstInt32 chunkMagic; // 'CcnK' - VstInt32 byteSize; // of this chunk, excl. magic + byteSize - VstInt32 fxMagic; // 'FxCh', 'FPCh', or 'FBCh' - VstInt32 version; - VstInt32 fxID; // fx unique id - VstInt32 fxVersion; - VstInt32 numPrograms; - char future[128]; - VstInt32 chunkSize; - char chunk[8]; // variable -}; - -struct fxProgramSet -{ - VstInt32 chunkMagic; // 'CcnK' - VstInt32 byteSize; // of this chunk, excl. magic + byteSize - VstInt32 fxMagic; // 'FxCh', 'FPCh', or 'FBCh' - VstInt32 version; - VstInt32 fxID; // fx unique id - VstInt32 fxVersion; - VstInt32 numPrograms; - char name[28]; - VstInt32 chunkSize; - char chunk[8]; // variable -}; - namespace { - VstInt32 vst_swap (const VstInt32 x) noexcept + const int fxbVersionNum = 1; + + struct fxProgram { - #ifdef JUCE_LITTLE_ENDIAN - return (VstInt32) ByteOrder::swap ((uint32) x); - #else - return x; - #endif + VstInt32 chunkMagic; // 'CcnK' + VstInt32 byteSize; // of this chunk, excl. magic + byteSize + VstInt32 fxMagic; // 'FxCk' + VstInt32 version; + VstInt32 fxID; // fx unique id + VstInt32 fxVersion; + VstInt32 numParams; + char prgName[28]; + float params[1]; // variable no. of parameters + }; + + struct fxSet + { + VstInt32 chunkMagic; // 'CcnK' + VstInt32 byteSize; // of this chunk, excl. magic + byteSize + VstInt32 fxMagic; // 'FxBk' + VstInt32 version; + VstInt32 fxID; // fx unique id + VstInt32 fxVersion; + VstInt32 numPrograms; + char future[128]; + fxProgram programs[1]; // variable no. of programs + }; + + struct fxChunkSet + { + VstInt32 chunkMagic; // 'CcnK' + VstInt32 byteSize; // of this chunk, excl. magic + byteSize + VstInt32 fxMagic; // 'FxCh', 'FPCh', or 'FBCh' + VstInt32 version; + VstInt32 fxID; // fx unique id + VstInt32 fxVersion; + VstInt32 numPrograms; + char future[128]; + VstInt32 chunkSize; + char chunk[8]; // variable + }; + + struct fxProgramSet + { + VstInt32 chunkMagic; // 'CcnK' + VstInt32 byteSize; // of this chunk, excl. magic + byteSize + VstInt32 fxMagic; // 'FxCh', 'FPCh', or 'FBCh' + VstInt32 version; + VstInt32 fxID; // fx unique id + VstInt32 fxVersion; + VstInt32 numPrograms; + char name[28]; + VstInt32 chunkSize; + char chunk[8]; // variable + }; + + // Compares a magic value in either endianness. + static bool compareMagic (VstInt32 magic, const char* name) noexcept + { + return magic == (VstInt32) ByteOrder::littleEndianInt (name) + || magic == (VstInt32) ByteOrder::bigEndianInt (name); } - float vst_swapFloat (const float x) noexcept + static VstInt32 fxbName (const char* name) noexcept { return (VstInt32) ByteOrder::littleEndianInt (name); } + static VstInt32 fxbSwap (const VstInt32 x) noexcept { return (VstInt32) ByteOrder::swapIfLittleEndian ((uint32) x); } + + static float fxbSwapFloat (const float x) noexcept { #ifdef JUCE_LITTLE_ENDIAN union { uint32 asInt; float asFloat; } n; @@ -162,8 +156,12 @@ namespace return x; #endif } +} - double getVSTHostTimeNanoseconds() +//============================================================================== +namespace +{ + static double getVSTHostTimeNanoseconds() noexcept { #if JUCE_WINDOWS return timeGetTime() * 1000000.0; @@ -177,40 +175,52 @@ namespace return micro.lo * 1000.0; #endif } + + static int shellUIDToCreate = 0; + static int insideVSTCallback = 0; + + struct IdleCallRecursionPreventer + { + IdleCallRecursionPreventer() : isMessageThread (MessageManager::getInstance()->isThisTheMessageThread()) + { + if (isMessageThread) + ++insideVSTCallback; + } + + ~IdleCallRecursionPreventer() + { + if (isMessageThread) + --insideVSTCallback; + } + + const bool isMessageThread; + JUCE_DECLARE_NON_COPYABLE (IdleCallRecursionPreventer) + }; + + #if JUCE_MAC + static bool makeFSRefFromPath (FSRef* destFSRef, const String& path) + { + return FSPathMakeRef (reinterpret_cast (path.toRawUTF8()), destFSRef, 0) == noErr; + } + #endif + + #if JUCE_MAC && JUCE_PPC + static void* newCFMFromMachO (void* const machofp) noexcept + { + void* result = (void*) new char[8]; + + ((void**) result)[0] = machofp; + ((void**) result)[1] = result; + + return result; + } + #endif } //============================================================================== typedef AEffect* (VSTCALLBACK *MainCall) (audioMasterCallback); - static VstIntPtr VSTCALLBACK audioMaster (AEffect* effect, VstInt32 opcode, VstInt32 index, VstIntPtr value, void* ptr, float opt); -static int shellUIDToCreate = 0; -static int insideVSTCallback = 0; - -class IdleCallRecursionPreventer -{ -public: - IdleCallRecursionPreventer() - : isMessageThread (MessageManager::getInstance()->isThisTheMessageThread()) - { - if (isMessageThread) - ++insideVSTCallback; - } - - ~IdleCallRecursionPreventer() - { - if (isMessageThread) - --insideVSTCallback; - } - -private: - const bool isMessageThread; - - JUCE_DECLARE_NON_COPYABLE (IdleCallRecursionPreventer) -}; - -class VSTPluginWindow; - //============================================================================== // Change this to disable logging of various VST activities #ifndef VST_LOGGING @@ -223,27 +233,12 @@ class VSTPluginWindow; #define JUCE_VST_LOG(a) #endif -//============================================================================== -#if JUCE_MAC && JUCE_PPC -static void* NewCFMFromMachO (void* const machofp) noexcept -{ - void* result = (void*) new char[8]; - - ((void**) result)[0] = machofp; - ((void**) result)[1] = result; - - return result; -} -#endif - //============================================================================== #if JUCE_LINUX extern Display* display; extern XContext windowHandleXContext; -typedef void (*EventProcPtr) (XEvent* ev); - namespace { static bool xErrorTriggered = false; @@ -254,6 +249,8 @@ namespace return 0; } + typedef void (*EventProcPtr) (XEvent* ev); + static EventProcPtr getPropertyFromXWindow (Window handle, Atom atom) { XErrorHandler oldErrorHandler = XSetErrorHandler (temporaryErrorHandler); @@ -269,8 +266,7 @@ namespace XSetErrorHandler (oldErrorHandler); - return (userCount == 1 && ! xErrorTriggered) ? *reinterpret_cast (data) - : 0; + return (userCount == 1 && ! xErrorTriggered) ? *reinterpret_cast (data) : nullptr; } Window getChildWindow (Window windowToCheck) @@ -279,12 +275,7 @@ namespace Window* childWindows; unsigned int numChildren = 0; - XQueryTree (display, - windowToCheck, - &rootWindow, - &parentWindow, - &childWindows, - &numChildren); + XQueryTree (display, windowToCheck, &rootWindow, &parentWindow, &childWindows, &numChildren); if (numChildren > 0) return childWindows [0]; @@ -327,6 +318,8 @@ namespace static void translateJuceToXMouseWheelModifiers (const MouseEvent& e, const float increment, XEvent& ev) noexcept { + ignoreUnused (e); + if (increment < 0) { ev.xbutton.button = Button5; @@ -354,9 +347,9 @@ public: typedef ReferenceCountedObjectPtr Ptr; - static Array & getActiveModules() + static Array& getActiveModules() { - static Array activeModules; + static Array activeModules; return activeModules; } @@ -470,7 +463,7 @@ public: { if (HGLOBAL hGlob = LoadResource (dllModule, res)) { - const char* data = static_cast (LockResource (hGlob)); + const char* data = static_cast (LockResource (hGlob)); return String::fromUTF8 (data, SizeofResource (dllModule, res)); } } @@ -497,7 +490,7 @@ public: const char* const utf8 = file.getFullPathName().toRawUTF8(); if (CFURLRef url = CFURLCreateFromFileSystemRepresentation (0, (const UInt8*) utf8, - strlen (utf8), file.isDirectory())) + (CFIndex) strlen (utf8), file.isDirectory())) { bundleRef = CFBundleCreate (kCFAllocatorDefault, url); CFRelease (url); @@ -552,7 +545,7 @@ public: } } } -#if JUCE_PPC + #if JUCE_PPC else { FSRef fn; @@ -605,7 +598,7 @@ public: } } } -#endif + #endif return ok; } @@ -683,7 +676,7 @@ public: static void disposeMachOFromCFM (void* ptr) { - delete[] static_cast (ptr); + delete[] static_cast (ptr); } void coerceAEffectFunctionCalls (AEffect* eff) @@ -715,11 +708,11 @@ class VSTPluginInstance : public AudioPluginInstance, private AsyncUpdater { public: - VSTPluginInstance (const ModuleHandle::Ptr& module_) + VSTPluginInstance (const ModuleHandle::Ptr& mh) : effect (nullptr), - module (module_), + module (mh), usesCocoaNSView (false), - name (module_->pluginName), + name (mh->pluginName), wantsMidiMessages (false), initialised (false), isPowerOn (false), @@ -741,7 +734,7 @@ public: { static void* audioMasterCoerced = nullptr; if (audioMasterCoerced == nullptr) - audioMasterCoerced = NewCFMFromMachO ((void*) &audioMaster); + audioMasterCoerced = newCFMFromMachO ((void*) &audioMaster); effect = module->moduleMain ((audioMasterCallback) audioMasterCoerced); } @@ -803,7 +796,7 @@ public: char buffer [512] = { 0 }; dispatch (effGetEffectName, 0, 0, buffer, 0); - desc.descriptiveName = String (buffer).trim(); + desc.descriptiveName = String::fromUTF8 (buffer).trim(); if (desc.descriptiveName.isEmpty()) desc.descriptiveName = name; @@ -818,7 +811,7 @@ public: { char buffer [kVstMaxVendorStrLen + 8] = { 0 }; dispatch (effGetVendorString, 0, 0, buffer, 0); - desc.manufacturerName = buffer; + desc.manufacturerName = String::fromUTF8 (buffer); } desc.version = getVersion(); @@ -873,7 +866,7 @@ public: wantsMidiMessages = dispatch (effCanDo, 0, 0, (void*) "receiveVstMidiEvent", 0) > 0; #if JUCE_MAC && JUCE_SUPPORT_CARBON - usesCocoaNSView = (dispatch (effCanDo, 0, 0, (void*) "hasCockosViewAsConfig", 0) & 0xffff0000) == 0xbeef0000; + usesCocoaNSView = (dispatch (effCanDo, 0, 0, (void*) "hasCockosViewAsConfig", 0) & (int) 0xffff0000) == 0xbeef0000; #endif setLatencySamples (effect->initialDelay); @@ -996,27 +989,28 @@ public: if (AudioPlayHead* const playHead = getPlayHead()) { AudioPlayHead::CurrentPositionInfo position; - playHead->getCurrentPosition (position); - - vstHostTime.samplePos = (double) position.timeInSamples; - vstHostTime.tempo = position.bpm; - vstHostTime.timeSigNumerator = position.timeSigNumerator; - vstHostTime.timeSigDenominator = position.timeSigDenominator; - vstHostTime.ppqPos = position.ppqPosition; - vstHostTime.barStartPos = position.ppqPositionOfLastBarStart; - vstHostTime.flags |= kVstTempoValid | kVstTimeSigValid | kVstPpqPosValid | kVstBarsValid; - - VstInt32 newTransportFlags = 0; - if (position.isPlaying) newTransportFlags |= kVstTransportPlaying; - if (position.isRecording) newTransportFlags |= kVstTransportRecording; - - if (newTransportFlags != (vstHostTime.flags & (kVstTransportPlaying | kVstTransportRecording))) - vstHostTime.flags = (vstHostTime.flags & ~(kVstTransportPlaying | kVstTransportRecording)) | newTransportFlags | kVstTransportChanged; - else - vstHostTime.flags &= ~kVstTransportChanged; - - switch (position.frameRate) + if (playHead->getCurrentPosition (position)) { + + vstHostTime.samplePos = (double) position.timeInSamples; + vstHostTime.tempo = position.bpm; + vstHostTime.timeSigNumerator = position.timeSigNumerator; + vstHostTime.timeSigDenominator = position.timeSigDenominator; + vstHostTime.ppqPos = position.ppqPosition; + vstHostTime.barStartPos = position.ppqPositionOfLastBarStart; + vstHostTime.flags |= kVstTempoValid | kVstTimeSigValid | kVstPpqPosValid | kVstBarsValid; + + VstInt32 newTransportFlags = 0; + if (position.isPlaying) newTransportFlags |= kVstTransportPlaying; + if (position.isRecording) newTransportFlags |= kVstTransportRecording; + + if (newTransportFlags != (vstHostTime.flags & (kVstTransportPlaying | kVstTransportRecording))) + vstHostTime.flags = (vstHostTime.flags & ~(kVstTransportPlaying | kVstTransportRecording)) | newTransportFlags | kVstTransportChanged; + else + vstHostTime.flags &= ~kVstTransportChanged; + + switch (position.frameRate) + { case AudioPlayHead::fps24: setHostTimeFrameRate (0, 24.0, position.timeInSeconds); break; case AudioPlayHead::fps25: setHostTimeFrameRate (1, 25.0, position.timeInSeconds); break; case AudioPlayHead::fps2997: setHostTimeFrameRate (2, 29.97, position.timeInSeconds); break; @@ -1024,17 +1018,18 @@ public: case AudioPlayHead::fps2997drop: setHostTimeFrameRate (4, 29.97, position.timeInSeconds); break; case AudioPlayHead::fps30drop: setHostTimeFrameRate (5, 29.97, position.timeInSeconds); break; default: break; - } + } - if (position.isLooping) - { - vstHostTime.cycleStartPos = position.ppqLoopStart; - vstHostTime.cycleEndPos = position.ppqLoopEnd; - vstHostTime.flags |= kVstCyclePosValid; - } - else - { - vstHostTime.flags &= ~kVstCyclePosValid; + if (position.isLooping) + { + vstHostTime.cycleStartPos = position.ppqLoopStart; + vstHostTime.cycleEndPos = position.ppqLoopEnd; + vstHostTime.flags |= (kVstCyclePosValid | kVstTransportCycleActive); + } + else + { + vstHostTime.flags &= ~(kVstCyclePosValid | kVstTransportCycleActive); + } } } @@ -1146,8 +1141,7 @@ public: bool isValidChannel (int index, bool isInput) const { - return isInput ? (index < getNumInputChannels()) - : (index < getNumOutputChannels()); + return isPositiveAndBelow (index, isInput ? getNumInputChannels() : getNumOutputChannels()); } //============================================================================== @@ -1214,7 +1208,7 @@ public: char nm[264] = { 0 }; if (dispatch (effGetProgramNameIndexed, jlimit (0, getNumPrograms(), index), -1, nm, 0) != 0) - return String (CharPointer_UTF8 (nm)).trim(); + return String::fromUTF8 (nm).trim(); } } @@ -1238,8 +1232,8 @@ public: void getStateInformation (MemoryBlock& mb) override { saveToFXBFile (mb, true); } void getCurrentProgramStateInformation (MemoryBlock& mb) override { saveToFXBFile (mb, false); } - void setStateInformation (const void* data, int size) override { loadFromFXBFile (data, size); } - void setCurrentProgramStateInformation (const void* data, int size) override { loadFromFXBFile (data, size); } + void setStateInformation (const void* data, int size) override { loadFromFXBFile (data, (size_t) size); } + void setCurrentProgramStateInformation (const void* data, int size) override { loadFromFXBFile (data, (size_t) size); } //============================================================================== void timerCallback() override @@ -1292,7 +1286,12 @@ public: case audioMasterSizeWindow: if (AudioProcessorEditor* ed = getActiveEditor()) - ed->setSize (index, (int) value); + { + #if JUCE_LINUX + const MessageManagerLock mmLock; + #endif + ed->setSize (index, (int) value); + } return 1; @@ -1366,6 +1365,7 @@ public: "receiveVstEvents", "receiveVstMidiEvent", "supportShell", + "sizeWindow", "shellCategory" }; for (int i = 0; i < numElementsInArray (canDos); ++i) @@ -1449,20 +1449,19 @@ public: const fxSet* const set = (const fxSet*) data; - if ((vst_swap (set->chunkMagic) != 'CcnK' && vst_swap (set->chunkMagic) != 'KncC') - || vst_swap (set->version) > fxbVersionNum) + if ((! compareMagic (set->chunkMagic, "CcnK")) || fxbSwap (set->version) > fxbVersionNum) return false; - if (vst_swap (set->fxMagic) == 'FxBk') + if (compareMagic (set->fxMagic, "FxBk")) { // bank of programs - if (vst_swap (set->numPrograms) >= 0) + if (fxbSwap (set->numPrograms) >= 0) { const int oldProg = getCurrentProgram(); - const int numParams = vst_swap (((const fxProgram*) (set->programs))->numParams); - const int progLen = sizeof (fxProgram) + (numParams - 1) * sizeof (float); + const int numParams = fxbSwap (((const fxProgram*) (set->programs))->numParams); + const int progLen = (int) sizeof (fxProgram) + (numParams - 1) * (int) sizeof (float); - for (int i = 0; i < vst_swap (set->numPrograms); ++i) + for (int i = 0; i < fxbSwap (set->numPrograms); ++i) { if (i != oldProg) { @@ -1470,7 +1469,7 @@ public: if (((const char*) prog) - ((const char*) set) >= (ssize_t) dataSize) return false; - if (vst_swap (set->numPrograms) > 0) + if (fxbSwap (set->numPrograms) > 0) setCurrentProgram (i); if (! restoreProgramSettings (prog)) @@ -1478,7 +1477,7 @@ public: } } - if (vst_swap (set->numPrograms) > 0) + if (fxbSwap (set->numPrograms) > 0) setCurrentProgram (oldProg); const fxProgram* const prog = (const fxProgram*) (((const char*) (set->programs)) + oldProg * progLen); @@ -1489,38 +1488,38 @@ public: return false; } } - else if (vst_swap (set->fxMagic) == 'FxCk') + else if (compareMagic (set->fxMagic, "FxCk")) { // single program const fxProgram* const prog = (const fxProgram*) data; - if (vst_swap (prog->chunkMagic) != 'CcnK') + if (! compareMagic (prog->chunkMagic, "CcnK")) return false; changeProgramName (getCurrentProgram(), prog->prgName); - for (int i = 0; i < vst_swap (prog->numParams); ++i) - setParameter (i, vst_swapFloat (prog->params[i])); + for (int i = 0; i < fxbSwap (prog->numParams); ++i) + setParameter (i, fxbSwapFloat (prog->params[i])); } - else if (vst_swap (set->fxMagic) == 'FBCh' || vst_swap (set->fxMagic) == 'hCBF') + else if (compareMagic (set->fxMagic, "FBCh")) { // non-preset chunk const fxChunkSet* const cset = (const fxChunkSet*) data; - if (vst_swap (cset->chunkSize) + sizeof (fxChunkSet) - 8 > (unsigned int) dataSize) + if ((size_t) fxbSwap (cset->chunkSize) + sizeof (fxChunkSet) - 8 > (size_t) dataSize) return false; - setChunkData (cset->chunk, vst_swap (cset->chunkSize), false); + setChunkData (cset->chunk, fxbSwap (cset->chunkSize), false); } - else if (vst_swap (set->fxMagic) == 'FPCh' || vst_swap (set->fxMagic) == 'hCPF') + else if (compareMagic (set->fxMagic, "FPCh")) { // preset chunk const fxProgramSet* const cset = (const fxProgramSet*) data; - if (vst_swap (cset->chunkSize) + sizeof (fxProgramSet) - 8 > (unsigned int) dataSize) + if ((size_t) fxbSwap (cset->chunkSize) + sizeof (fxProgramSet) - 8 > (size_t) dataSize) return false; - setChunkData (cset->chunk, vst_swap (cset->chunkSize), true); + setChunkData (cset->chunk, fxbSwap (cset->chunkSize), true); changeProgramName (getCurrentProgram(), cset->name); } @@ -1548,14 +1547,14 @@ public: dest.setSize (totalLen, true); fxChunkSet* const set = (fxChunkSet*) dest.getData(); - set->chunkMagic = vst_swap ('CcnK'); + set->chunkMagic = fxbName ("CcnK"); set->byteSize = 0; - set->fxMagic = vst_swap ('FBCh'); - set->version = vst_swap (fxbVersionNum); - set->fxID = vst_swap (getUID()); - set->fxVersion = vst_swap (getVersionNumber()); - set->numPrograms = vst_swap (numPrograms); - set->chunkSize = vst_swap ((VstInt32) chunk.getSize()); + set->fxMagic = fxbName ("FBCh"); + set->version = fxbSwap (fxbVersionNum); + set->fxID = fxbSwap (getUID()); + set->fxVersion = fxbSwap (getVersionNumber()); + set->numPrograms = fxbSwap (numPrograms); + set->chunkSize = fxbSwap ((VstInt32) chunk.getSize()); chunk.copyTo (set->chunk, 0, chunk.getSize()); } @@ -1565,14 +1564,14 @@ public: dest.setSize (totalLen, true); fxProgramSet* const set = (fxProgramSet*) dest.getData(); - set->chunkMagic = vst_swap ('CcnK'); + set->chunkMagic = fxbName ("CcnK"); set->byteSize = 0; - set->fxMagic = vst_swap ('FPCh'); - set->version = vst_swap (fxbVersionNum); - set->fxID = vst_swap (getUID()); - set->fxVersion = vst_swap (getVersionNumber()); - set->numPrograms = vst_swap (numPrograms); - set->chunkSize = vst_swap ((VstInt32) chunk.getSize()); + set->fxMagic = fxbName ("FPCh"); + set->version = fxbSwap (fxbVersionNum); + set->fxID = fxbSwap (getUID()); + set->fxVersion = fxbSwap (getVersionNumber()); + set->numPrograms = fxbSwap (numPrograms); + set->chunkSize = fxbSwap ((VstInt32) chunk.getSize()); getCurrentProgramName().copyToUTF8 (set->name, sizeof (set->name) - 1); chunk.copyTo (set->chunk, 0, chunk.getSize()); @@ -1582,24 +1581,26 @@ public: { if (isFXB) { - const int progLen = sizeof (fxProgram) + (numParams - 1) * sizeof (float); - const int len = (sizeof (fxSet) - sizeof (fxProgram)) + progLen * jmax (1, numPrograms); + const int progLen = (int) sizeof (fxProgram) + (numParams - 1) * (int) sizeof (float); + const size_t len = (sizeof (fxSet) - sizeof (fxProgram)) + (size_t) (progLen * jmax (1, numPrograms)); dest.setSize (len, true); fxSet* const set = (fxSet*) dest.getData(); - set->chunkMagic = vst_swap ('CcnK'); + set->chunkMagic = fxbName ("CcnK"); set->byteSize = 0; - set->fxMagic = vst_swap ('FxBk'); - set->version = vst_swap (fxbVersionNum); - set->fxID = vst_swap (getUID()); - set->fxVersion = vst_swap (getVersionNumber()); - set->numPrograms = vst_swap (numPrograms); + set->fxMagic = fxbName ("FxBk"); + set->version = fxbSwap (fxbVersionNum); + set->fxID = fxbSwap (getUID()); + set->fxVersion = fxbSwap (getVersionNumber()); + set->numPrograms = fxbSwap (numPrograms); - const int oldProgram = getCurrentProgram(); MemoryBlock oldSettings; createTempParameterStore (oldSettings); - setParamsInProgramBlock ((fxProgram*) (((char*) (set->programs)) + oldProgram * progLen)); + const int oldProgram = getCurrentProgram(); + + if (oldProgram >= 0) + setParamsInProgramBlock ((fxProgram*) (((char*) (set->programs)) + oldProgram * progLen)); for (int i = 0; i < numPrograms; ++i) { @@ -1610,14 +1611,14 @@ public: } } - setCurrentProgram (oldProgram); + if (oldProgram >= 0) + setCurrentProgram (oldProgram); + restoreFromTempParameterStore (oldSettings); } else { - const int totalLen = sizeof (fxProgram) + (numParams - 1) * sizeof (float); - dest.setSize (totalLen, true); - + dest.setSize (sizeof (fxProgram) + (size_t) ((numParams - 1) * (int) sizeof (float)), true); setParamsInProgramBlock ((fxProgram*) dest.getData()); } } @@ -1632,9 +1633,9 @@ public: if (usesChunks()) { void* data = nullptr; - const VstIntPtr bytes = dispatch (effGetChunk, isPreset ? 1 : 0, 0, &data, 0.0f); + const size_t bytes = (size_t) dispatch (effGetChunk, isPreset ? 1 : 0, 0, &data, 0.0f); - if (data != nullptr && bytes <= maxSizeMB * 1024 * 1024) + if (data != nullptr && bytes <= (size_t) maxSizeMB * 1024 * 1024) { mb.setSize (bytes); mb.copyFrom (data, 0, bytes); @@ -1688,12 +1689,13 @@ private: bool restoreProgramSettings (const fxProgram* const prog) { - if (vst_swap (prog->chunkMagic) == 'CcnK' && vst_swap (prog->fxMagic) == 'FxCk') + if (compareMagic (prog->chunkMagic, "CcnK") + && compareMagic (prog->fxMagic, "FxCk")) { changeProgramName (getCurrentProgram(), prog->prgName); - for (int i = 0; i < vst_swap (prog->numParams); ++i) - setParameter (i, vst_swapFloat (prog->params[i])); + for (int i = 0; i < fxbSwap (prog->numParams); ++i) + setParameter (i, fxbSwapFloat (prog->params[i])); return true; } @@ -1742,18 +1744,18 @@ private: { const int numParams = getNumParameters(); - prog->chunkMagic = vst_swap ('CcnK'); + prog->chunkMagic = fxbName ("CcnK"); prog->byteSize = 0; - prog->fxMagic = vst_swap ('FxCk'); - prog->version = vst_swap (fxbVersionNum); - prog->fxID = vst_swap (getUID()); - prog->fxVersion = vst_swap (getVersionNumber()); - prog->numParams = vst_swap (numParams); + prog->fxMagic = fxbName ("FxCk"); + prog->version = fxbSwap (fxbVersionNum); + prog->fxID = fxbSwap (getUID()); + prog->fxVersion = fxbSwap (getVersionNumber()); + prog->numParams = fxbSwap (numParams); getCurrentProgramName().copyToUTF8 (prog->prgName, sizeof (prog->prgName) - 1); for (int i = 0; i < numParams; ++i) - prog->params[i] = vst_swapFloat (getParameter (i)); + prog->params[i] = fxbSwapFloat (getParameter (i)); } void updateStoredProgramNames() @@ -1793,7 +1795,7 @@ private: //============================================================================== void createTempParameterStore (MemoryBlock& dest) { - dest.setSize (64 + 4 * getNumParameters()); + dest.setSize (64 + 4 * (size_t) getNumParameters()); dest.fillWith (0); getCurrentProgramName().copyToUTF8 ((char*) dest.getData(), 63); @@ -1831,21 +1833,21 @@ private: String s; if (v == 0 || (int) v == -1) - v = getVersionNumber(); + v = (unsigned int) getVersionNumber(); if (v != 0) { int versionBits[32]; int n = 0; - for (int vv = v; vv != 0; vv /= 10) + for (unsigned int vv = v; vv != 0; vv /= 10) versionBits [n++] = vv % 10; if (n > 4) // if the number ends up silly, it's probably encoded as hex instead of decimal.. { n = 0; - for (int vv = v; vv != 0; vv >>= 8) + for (unsigned int vv = v; vv != 0; vv >>= 8) versionBits [n++] = vv & 255; } @@ -1895,7 +1897,8 @@ private: }; //============================================================================== -static Array activeVSTWindows; +class VSTPluginWindow; +static Array activeVSTWindows; //============================================================================== class VSTPluginWindow : public AudioProcessorEditor, @@ -1977,9 +1980,13 @@ public: #elif JUCE_LINUX if (pluginWindow != 0) { - XResizeWindow (display, pluginWindow, getWidth(), getHeight()); - XMoveWindow (display, pluginWindow, pos.getX(), pos.getY()); + XMoveResizeWindow (display, pluginWindow, + pos.getX(), pos.getY(), + (unsigned int) getWidth(), + (unsigned int) getHeight()); + XMapRaised (display, pluginWindow); + XFlush (display); } #endif @@ -2090,6 +2097,16 @@ public: plugin.dispatch (effEditIdle, 0, 0, 0, 0); reentrant = false; } + + #if JUCE_LINUX + if (pluginWindow == 0) + { + updatePluginWindowHandle(); + + if (pluginWindow != 0) + componentMovedOrResized (true, true); + } + #endif } } @@ -2233,10 +2250,11 @@ private: #pragma warning (push) #pragma warning (disable: 4244) - originalWndProc = (void*) GetWindowLongPtr (pluginHWND, GWLP_WNDPROC); - if (! pluginWantsKeys) + { + originalWndProc = (void*) GetWindowLongPtr (pluginHWND, GWLP_WNDPROC); SetWindowLongPtr (pluginHWND, GWLP_WNDPROC, (LONG_PTR) vstHookWndProc); + } #pragma warning (pop) @@ -2274,11 +2292,7 @@ private: } #elif JUCE_LINUX - pluginWindow = getChildWindow ((Window) getWindowHandle()); - - if (pluginWindow != 0) - pluginProc = (EventProcPtr) getPropertyFromXWindow (pluginWindow, - XInternAtom (display, "_XEventProc", False)); + updatePluginWindowHandle(); int w = 250, h = 150; @@ -2326,10 +2340,11 @@ private: #if JUCE_WINDOWS #pragma warning (push) #pragma warning (disable: 4244) - if (pluginHWND != 0 && IsWindow (pluginHWND)) + if (originalWndProc != 0 && pluginHWND != 0 && IsWindow (pluginHWND)) SetWindowLongPtr (pluginHWND, GWLP_WNDPROC, (LONG_PTR) originalWndProc); #pragma warning (pop) + originalWndProc = 0; pluginHWND = 0; #elif JUCE_LINUX pluginWindow = 0; @@ -2505,6 +2520,15 @@ private: sendEventToChild (ev); } } + + void updatePluginWindowHandle() + { + pluginWindow = getChildWindow ((Window) getWindowHandle()); + + if (pluginWindow != 0) + pluginProc = (EventProcPtr) getPropertyFromXWindow (pluginWindow, + XInternAtom (display, "_XEventProc", False)); + } #endif //============================================================================== @@ -2843,7 +2867,7 @@ FileSearchPath VSTPluginFormat::getDefaultLocationsToSearch() const XmlElement* VSTPluginFormat::getVSTXML (AudioPluginInstance* plugin) { - if (VSTPluginInstance* const vst = dynamic_cast (plugin)) + if (VSTPluginInstance* const vst = dynamic_cast (plugin)) if (vst->module != nullptr) return vst->module->vstXml.get(); @@ -2852,7 +2876,7 @@ const XmlElement* VSTPluginFormat::getVSTXML (AudioPluginInstance* plugin) bool VSTPluginFormat::loadFromFXBFile (AudioPluginInstance* plugin, const void* data, size_t dataSize) { - if (VSTPluginInstance* vst = dynamic_cast (plugin)) + if (VSTPluginInstance* vst = dynamic_cast (plugin)) return vst->loadFromFXBFile (data, dataSize); return false; @@ -2860,7 +2884,7 @@ bool VSTPluginFormat::loadFromFXBFile (AudioPluginInstance* plugin, const void* bool VSTPluginFormat::saveToFXBFile (AudioPluginInstance* plugin, MemoryBlock& dest, bool asFXB) { - if (VSTPluginInstance* vst = dynamic_cast (plugin)) + if (VSTPluginInstance* vst = dynamic_cast (plugin)) return vst->saveToFXBFile (dest, asFXB); return false; @@ -2868,7 +2892,7 @@ bool VSTPluginFormat::saveToFXBFile (AudioPluginInstance* plugin, MemoryBlock& d bool VSTPluginFormat::getChunkData (AudioPluginInstance* plugin, MemoryBlock& result, bool isPreset) { - if (VSTPluginInstance* vst = dynamic_cast (plugin)) + if (VSTPluginInstance* vst = dynamic_cast (plugin)) return vst->getChunkData (result, isPreset, 128); return false; @@ -2876,7 +2900,7 @@ bool VSTPluginFormat::getChunkData (AudioPluginInstance* plugin, MemoryBlock& re bool VSTPluginFormat::setChunkData (AudioPluginInstance* plugin, const void* data, int size, bool isPreset) { - if (VSTPluginInstance* vst = dynamic_cast (plugin)) + if (VSTPluginInstance* vst = dynamic_cast (plugin)) return vst->setChunkData (data, size, isPreset); return false; @@ -2886,13 +2910,13 @@ void VSTPluginFormat::setExtraFunctions (AudioPluginInstance* plugin, ExtraFunct { ScopedPointer f (functions); - if (VSTPluginInstance* vst = dynamic_cast (plugin)) + if (VSTPluginInstance* vst = dynamic_cast (plugin)) vst->extraFunctions = f; } VSTPluginFormat::VstIntPtr JUCE_CALLTYPE VSTPluginFormat::dispatcher (AudioPluginInstance* plugin, int32 opcode, int32 index, VstIntPtr value, void* ptr, float opt) { - if (VSTPluginInstance* vst = dynamic_cast (plugin)) + if (VSTPluginInstance* vst = dynamic_cast (plugin)) return vst->dispatch (opcode, index, value, ptr, opt); return 0; diff --git a/JuceLibraryCode/modules/juce_audio_processors/format_types/juce_VSTPluginFormat.h b/JuceLibraryCode/modules/juce_audio_processors/format_types/juce_VSTPluginFormat.h index 4e4b744..400d75d 100644 --- a/JuceLibraryCode/modules/juce_audio_processors/format_types/juce_VSTPluginFormat.h +++ b/JuceLibraryCode/modules/juce_audio_processors/format_types/juce_VSTPluginFormat.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_audio_processors/juce_audio_processors.cpp b/JuceLibraryCode/modules/juce_audio_processors/juce_audio_processors.cpp index 78d3387..663fb96 100644 --- a/JuceLibraryCode/modules/juce_audio_processors/juce_audio_processors.cpp +++ b/JuceLibraryCode/modules/juce_audio_processors/juce_audio_processors.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -41,8 +41,9 @@ //============================================================================== #if JUCE_MAC - #if (JUCE_PLUGINHOST_VST || JUCE_PLUGINHOST_AU) \ - || ! (defined (MAC_OS_X_VERSION_10_6) && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_6) + #if JUCE_SUPPORT_CARBON \ + && ((JUCE_PLUGINHOST_VST || JUCE_PLUGINHOST_AU) \ + || ! (defined (MAC_OS_X_VERSION_10_6) && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_6)) #define Point CarbonDummyPointName // (workaround to avoid definition of "Point" by old Carbon headers) #define Component CarbonDummyCompName #include @@ -112,27 +113,24 @@ struct AutoResizingNSViewComponentWithParent : public AutoResizingNSViewCompone setView (v); [v release]; - startTimer (100); + startTimer (30); + } + + NSView* getChildView() const + { + if (NSView* parent = (NSView*) getView()) + if ([[parent subviews] count] > 0) + return [[parent subviews] objectAtIndex: 0]; + + return nil; } void timerCallback() override { - if (NSView* parent = (NSView*) getView()) + if (NSView* child = getChildView()) { - if ([[parent subviews] count] > 0) - { - if (NSView* child = [[parent subviews] objectAtIndex: 0]) - { - NSRect f = [parent frame]; - NSSize newSize = [child frame].size; - - if (f.size.width != newSize.width || f.size.height != newSize.height) - { - f.size = newSize; - [parent setFrame: f]; - } - } - } + stopTimer(); + setView (child); } } }; diff --git a/JuceLibraryCode/modules/juce_audio_processors/juce_audio_processors.h b/JuceLibraryCode/modules/juce_audio_processors/juce_audio_processors.h index 3854d2a..5ccfe2b 100644 --- a/JuceLibraryCode/modules/juce_audio_processors/juce_audio_processors.h +++ b/JuceLibraryCode/modules/juce_audio_processors/juce_audio_processors.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -76,6 +76,7 @@ class AudioProcessor; #include "processors/juce_AudioPlayHead.h" #include "processors/juce_AudioProcessorEditor.h" #include "processors/juce_AudioProcessorListener.h" +#include "processors/juce_AudioProcessorParameter.h" #include "processors/juce_AudioProcessor.h" #include "processors/juce_PluginDescription.h" #include "processors/juce_AudioPluginInstance.h" diff --git a/JuceLibraryCode/modules/juce_audio_processors/juce_audio_processors.mm b/JuceLibraryCode/modules/juce_audio_processors/juce_audio_processors.mm index 918e848..f111409 100644 --- a/JuceLibraryCode/modules/juce_audio_processors/juce_audio_processors.mm +++ b/JuceLibraryCode/modules/juce_audio_processors/juce_audio_processors.mm @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_audio_processors/juce_module_info b/JuceLibraryCode/modules/juce_audio_processors/juce_module_info index c46eb74..11fa235 100644 --- a/JuceLibraryCode/modules/juce_audio_processors/juce_module_info +++ b/JuceLibraryCode/modules/juce_audio_processors/juce_module_info @@ -1,7 +1,7 @@ { "id": "juce_audio_processors", "name": "JUCE audio plugin hosting classes", - "version": "3.0.6", + "version": "3.2.0", "description": "Classes for loading and playing VST, AU, or internally-generated audio processors.", "website": "http://www.juce.com/juce", "license": "GPL/Commercial", diff --git a/JuceLibraryCode/modules/juce_audio_processors/processors/juce_AudioPlayHead.h b/JuceLibraryCode/modules/juce_audio_processors/processors/juce_AudioPlayHead.h index b92b802..c54e7c3 100644 --- a/JuceLibraryCode/modules/juce_audio_processors/processors/juce_AudioPlayHead.h +++ b/JuceLibraryCode/modules/juce_audio_processors/processors/juce_AudioPlayHead.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -128,10 +128,14 @@ public: //============================================================================== /** Fills-in the given structure with details about the transport's - position at the start of the current processing block. + position at the start of the current processing block. If this method returns + false then the current play head position is not available and the given + structure will be undefined. - This method must ONLY be called from within your AudioProcessor::processBlock() - method. Calling it at any other time will probably cause a nasty crash. + You can ONLY call this from your processBlock() method! Calling it at other + times will produce undefined behaviour, as the host may not have any context + in which a time would make sense, and some hosts will almost certainly have + multithreading issues if it's not called on the audio thread. */ virtual bool getCurrentPosition (CurrentPositionInfo& result) = 0; }; diff --git a/JuceLibraryCode/modules/juce_audio_processors/processors/juce_AudioPluginInstance.h b/JuceLibraryCode/modules/juce_audio_processors/processors/juce_AudioPluginInstance.h index b7c7b7d..675cab4 100644 --- a/JuceLibraryCode/modules/juce_audio_processors/processors/juce_AudioPluginInstance.h +++ b/JuceLibraryCode/modules/juce_audio_processors/processors/juce_AudioPluginInstance.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_audio_processors/processors/juce_AudioProcessor.cpp b/JuceLibraryCode/modules/juce_audio_processors/processors/juce_AudioProcessor.cpp index 86f2e81..aa4c198 100644 --- a/JuceLibraryCode/modules/juce_audio_processors/processors/juce_AudioProcessor.cpp +++ b/JuceLibraryCode/modules/juce_audio_processors/processors/juce_AudioProcessor.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -48,7 +48,7 @@ AudioProcessor::~AudioProcessor() // that it refers to is deleted.. jassert (activeEditor == nullptr); - #if JUCE_DEBUG + #if JUCE_DEBUG && ! JUCE_DISABLE_AUDIOPROCESSOR_BEGIN_END_GESTURE_CHECKING // This will fail if you've called beginParameterChangeGesture() for one // or more parameters without having made a corresponding call to endParameterChangeGesture... jassert (changingParams.countNumberOfSetBits() == 0); @@ -118,19 +118,6 @@ void AudioProcessor::setParameterNotifyingHost (const int parameterIndex, sendParamChangeMessageToListeners (parameterIndex, newValue); } -String AudioProcessor::getParameterName (int parameterIndex, int maximumStringLength) -{ - return getParameterName (parameterIndex).substring (0, maximumStringLength); -} - -String AudioProcessor::getParameterText (int parameterIndex, int maximumStringLength) -{ - return getParameterText (parameterIndex).substring (0, maximumStringLength); -} - -int AudioProcessor::getParameterNumSteps (int /*parameterIndex*/) { return 0x7fffffff; } -float AudioProcessor::getParameterDefaultValue (int /*parameterIndex*/) { return 0.0f; } - AudioProcessorListener* AudioProcessor::getListenerLocked (const int index) const noexcept { const ScopedLock sl (listenerLock); @@ -155,7 +142,7 @@ void AudioProcessor::beginParameterChangeGesture (int parameterIndex) { if (isPositiveAndBelow (parameterIndex, getNumParameters())) { - #if JUCE_DEBUG + #if JUCE_DEBUG && ! JUCE_DISABLE_AUDIOPROCESSOR_BEGIN_END_GESTURE_CHECKING // This means you've called beginParameterChangeGesture twice in succession without a matching // call to endParameterChangeGesture. That might be fine in most hosts, but better to avoid doing it. jassert (! changingParams [parameterIndex]); @@ -176,9 +163,9 @@ void AudioProcessor::endParameterChangeGesture (int parameterIndex) { if (isPositiveAndBelow (parameterIndex, getNumParameters())) { - #if JUCE_DEBUG + #if JUCE_DEBUG && ! JUCE_DISABLE_AUDIOPROCESSOR_BEGIN_END_GESTURE_CHECKING // This means you've called endParameterChangeGesture without having previously called - // endParameterChangeGesture. That might be fine in most hosts, but better to keep the + // beginParameterChangeGesture. That might be fine in most hosts, but better to keep the // calls matched correctly. jassert (changingParams [parameterIndex]); changingParams.clearBit (parameterIndex); @@ -201,10 +188,129 @@ void AudioProcessor::updateHostDisplay() l->audioProcessorChanged (this); } -String AudioProcessor::getParameterLabel (int) const { return String(); } -bool AudioProcessor::isParameterOrientationInverted (int) const { return false; } -bool AudioProcessor::isParameterAutomatable (int) const { return true; } -bool AudioProcessor::isMetaParameter (int) const { return false; } +const OwnedArray& AudioProcessor::getParameters() const noexcept +{ + return managedParameters; +} + +int AudioProcessor::getNumParameters() +{ + return managedParameters.size(); +} + +float AudioProcessor::getParameter (int index) +{ + if (AudioProcessorParameter* p = getParamChecked (index)) + return p->getValue(); + + return 0; +} + +void AudioProcessor::setParameter (int index, float newValue) +{ + if (AudioProcessorParameter* p = getParamChecked (index)) + p->setValue (newValue); +} + +float AudioProcessor::getParameterDefaultValue (int index) +{ + if (AudioProcessorParameter* p = managedParameters[index]) + return p->getDefaultValue(); + + return 0; +} + +const String AudioProcessor::getParameterName (int index) +{ + if (AudioProcessorParameter* p = getParamChecked (index)) + return p->getName (512); + + return String(); +} + +String AudioProcessor::getParameterName (int index, int maximumStringLength) +{ + if (AudioProcessorParameter* p = managedParameters[index]) + return p->getName (maximumStringLength); + + return getParameterName (index).substring (0, maximumStringLength); +} + +const String AudioProcessor::getParameterText (int index) +{ + return getParameterText (index, 1024); +} + +String AudioProcessor::getParameterText (int index, int maximumStringLength) +{ + if (AudioProcessorParameter* p = managedParameters[index]) + return p->getText (p->getValue(), maximumStringLength); + + return getParameterText (index).substring (0, maximumStringLength); +} + +int AudioProcessor::getParameterNumSteps (int index) +{ + if (AudioProcessorParameter* p = managedParameters[index]) + return p->getNumSteps(); + + return AudioProcessor::getDefaultNumParameterSteps(); +} + +int AudioProcessor::getDefaultNumParameterSteps() noexcept +{ + return 0x7fffffff; +} + +String AudioProcessor::getParameterLabel (int index) const +{ + if (AudioProcessorParameter* p = managedParameters[index]) + return p->getLabel(); + + return String(); +} + +bool AudioProcessor::isParameterAutomatable (int index) const +{ + if (AudioProcessorParameter* p = managedParameters[index]) + return p->isAutomatable(); + + return true; +} + +bool AudioProcessor::isParameterOrientationInverted (int index) const +{ + if (AudioProcessorParameter* p = managedParameters[index]) + return p->isOrientationInverted(); + + return false; +} + +bool AudioProcessor::isMetaParameter (int index) const +{ + if (AudioProcessorParameter* p = managedParameters[index]) + return p->isMetaParameter(); + + return false; +} + +AudioProcessorParameter* AudioProcessor::getParamChecked (int index) const noexcept +{ + AudioProcessorParameter* p = managedParameters[index]; + + // If you hit this, then you're either trying to access parameters that are out-of-range, + // or you're not using addParameter and the managed parameter list, but have failed + // to override some essential virtual methods and implement them appropriately. + jassert (p != nullptr); + return p; +} + +void AudioProcessor::addParameter (AudioProcessorParameter* p) +{ + p->processor = this; + p->parameterIndex = managedParameters.size(); + managedParameters.add (p); +} void AudioProcessor::suspendProcessing (const bool shouldBeSuspended) { @@ -231,9 +337,6 @@ AudioProcessorEditor* AudioProcessor::createEditorIfNeeded() AudioProcessorEditor* const ed = createEditor(); - // You must make your hasEditor() method return a consistent result! - jassert (hasEditor() == (ed != nullptr)); - if (ed != nullptr) { // you must give your editor comp a size before returning it.. @@ -243,6 +346,9 @@ AudioProcessorEditor* AudioProcessor::createEditorIfNeeded() activeEditor = ed; } + // You must make your hasEditor() method return a consistent result! + jassert (hasEditor() == (ed != nullptr)); + return ed; } @@ -295,6 +401,47 @@ XmlElement* AudioProcessor::getXmlFromBinary (const void* data, const int sizeIn void AudioProcessorListener::audioProcessorParameterChangeGestureBegin (AudioProcessor*, int) {} void AudioProcessorListener::audioProcessorParameterChangeGestureEnd (AudioProcessor*, int) {} +//============================================================================== +AudioProcessorParameter::AudioProcessorParameter() noexcept + : processor (nullptr), parameterIndex (-1) +{} + +AudioProcessorParameter::~AudioProcessorParameter() {} + +void AudioProcessorParameter::setValueNotifyingHost (float newValue) +{ + // This method can't be used until the parameter has been attached to a processor! + jassert (processor != nullptr && parameterIndex >= 0); + + return processor->setParameterNotifyingHost (parameterIndex, newValue); +} + +void AudioProcessorParameter::beginChangeGesture() +{ + // This method can't be used until the parameter has been attached to a processor! + jassert (processor != nullptr && parameterIndex >= 0); + + processor->beginParameterChangeGesture (parameterIndex); +} + +void AudioProcessorParameter::endChangeGesture() +{ + // This method can't be used until the parameter has been attached to a processor! + jassert (processor != nullptr && parameterIndex >= 0); + + processor->endParameterChangeGesture (parameterIndex); +} + +bool AudioProcessorParameter::isOrientationInverted() const { return false; } +bool AudioProcessorParameter::isAutomatable() const { return true; } +bool AudioProcessorParameter::isMetaParameter() const { return false; } +int AudioProcessorParameter::getNumSteps() const { return AudioProcessor::getDefaultNumParameterSteps(); } + +String AudioProcessorParameter::getText (float value, int /*maximumStringLength*/) const +{ + return String (value, 2); +} + //============================================================================== bool AudioPlayHead::CurrentPositionInfo::operator== (const CurrentPositionInfo& other) const noexcept { diff --git a/JuceLibraryCode/modules/juce_audio_processors/processors/juce_AudioProcessor.h b/JuceLibraryCode/modules/juce_audio_processors/processors/juce_AudioProcessor.h index cec25c0..4019149 100644 --- a/JuceLibraryCode/modules/juce_audio_processors/processors/juce_AudioProcessor.h +++ b/JuceLibraryCode/modules/juce_audio_processors/processors/juce_AudioProcessor.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -140,11 +140,17 @@ public: /** Returns the current AudioPlayHead object that should be used to find out the state and position of the playhead. - You can call this from your processBlock() method, and use the AudioPlayHead - object to get the details about the time of the start of the block currently - being processed. + You can ONLY call this from your processBlock() method! Calling it at other + times will produce undefined behaviour, as the host may not have any context + in which a time would make sense, and some hosts will almost certainly have + multithreading issues if it's not called on the audio thread. - If the host hasn't supplied a playhead object, this will return nullptr. + The AudioPlayHead object that is returned can be used to get the details about + the time of the start of the block currently being processed. But do not + store this pointer or use it outside of the current audio callback, because + the host may delete or re-use it. + + If the host can't or won't provide any time info, this will return nullptr. */ AudioPlayHead* getPlayHead() const noexcept { return playHead; } @@ -289,9 +295,9 @@ public: filter will return an empty buffer, but won't block the audio thread like it would do if you use the getCallbackLock() critical section to synchronise access. - If you're going to use this, your processBlock() method must call isSuspended() and - check whether it's suspended or not. If it is, then it should skip doing any real - processing, either emitting silence or passing the input through unchanged. + Any code that calls processBlock() should call isSuspended() before doing so, and + if the processor is suspended, it should avoid the call and emit silence or + whatever is appropriate. @see getCallbackLock */ @@ -325,7 +331,7 @@ public: /** Called by the host to tell this processor whether it's being used in a non-realtime capacity for offline rendering or bouncing. */ - void setNonRealtime (bool isNonRealtime) noexcept; + virtual void setNonRealtime (bool isNonRealtime) noexcept; //============================================================================== /** Creates the filter's UI. @@ -376,11 +382,18 @@ public: //============================================================================== /** This must return the correct value immediately after the object has been created, and mustn't change the number of parameters later. - */ - virtual int getNumParameters() = 0; - /** Returns the name of a particular parameter. */ - virtual const String getParameterName (int parameterIndex) = 0; + NOTE! This method will eventually be deprecated! It's recommended that you use the + AudioProcessorParameter class instead to manage your parameters. + */ + virtual int getNumParameters(); + + /** Returns the name of a particular parameter. + + NOTE! This method will eventually be deprecated! It's recommended that you use the + AudioProcessorParameter class instead to manage your parameters. + */ + virtual const String getParameterName (int parameterIndex); /** Called by the host to find out the value of one of the filter's parameters. @@ -389,11 +402,11 @@ public: This could be called quite frequently, so try to make your code efficient. It's also likely to be called by non-UI threads, so the code in here should be thread-aware. - */ - virtual float getParameter (int parameterIndex) = 0; - /** Returns the value of a parameter as a text string. */ - virtual const String getParameterText (int parameterIndex) = 0; + NOTE! This method will eventually be deprecated! It's recommended that you use the + AudioProcessorParameter class instead to manage your parameters. + */ + virtual float getParameter (int parameterIndex); /** Returns the name of a parameter as a text string with a preferred maximum length. If you want to provide customised short versions of your parameter names that @@ -401,38 +414,71 @@ public: devices or mixing desks) then you should implement this method. If you don't override it, the default implementation will call getParameterText(int), and truncate the result. + + NOTE! This method will eventually be deprecated! It's recommended that you use + AudioProcessorParameter::getName() instead. */ virtual String getParameterName (int parameterIndex, int maximumStringLength); + /** Returns the value of a parameter as a text string. + NOTE! This method will eventually be deprecated! It's recommended that you use + AudioProcessorParameter::getText() instead. + */ + virtual const String getParameterText (int parameterIndex); + /** Returns the value of a parameter as a text string with a preferred maximum length. If you want to provide customised short versions of your parameter values that will look better in constrained spaces (e.g. the displays on hardware controller devices or mixing desks) then you should implement this method. If you don't override it, the default implementation will call getParameterText(int), and truncate the result. + + NOTE! This method will eventually be deprecated! It's recommended that you use + AudioProcessorParameter::getText() instead. */ virtual String getParameterText (int parameterIndex, int maximumStringLength); /** Returns the number of discrete steps that this parameter can represent. - The default return value if you don't implement this method is 0x7fffffff. + The default return value if you don't implement this method is + AudioProcessor::getDefaultNumParameterSteps(). If your parameter is boolean, then you may want to make this return 2. The value that is returned may or may not be used, depending on the host. + + NOTE! This method will eventually be deprecated! It's recommended that you use + AudioProcessorParameter::getNumSteps() instead. */ virtual int getParameterNumSteps (int parameterIndex); + /** Returns the default number of steps for a parameter. + + NOTE! This method will eventually be deprecated! It's recommended that you use + AudioProcessorParameter::getNumSteps() instead. + @see getParameterNumSteps + */ + static int getDefaultNumParameterSteps() noexcept; + /** Returns the default value for the parameter. By default, this just returns 0. The value that is returned may or may not be used, depending on the host. + + NOTE! This method will eventually be deprecated! It's recommended that you use + AudioProcessorParameter::getDefaultValue() instead. */ virtual float getParameterDefaultValue (int parameterIndex); /** Some plugin types may be able to return a label string for a parameter's units. + + NOTE! This method will eventually be deprecated! It's recommended that you use + AudioProcessorParameter::getLabel() instead. */ virtual String getParameterLabel (int index) const; /** This can be overridden to tell the host that particular parameters operate in the reverse direction. (Not all plugin formats or hosts will actually use this information). + + NOTE! This method will eventually be deprecated! It's recommended that you use + AudioProcessorParameter::isOrientationInverted() instead. */ virtual bool isParameterOrientationInverted (int index) const; @@ -448,8 +494,11 @@ public: won't be able to automate your parameters properly. The value passed will be between 0 and 1.0. + + NOTE! This method will eventually be deprecated! It's recommended that you use + AudioProcessorParameter::setValue() instead. */ - virtual void setParameter (int parameterIndex, float newValue) = 0; + virtual void setParameter (int parameterIndex, float newValue); /** Your filter can call this when it needs to change one of its parameters. @@ -460,11 +509,17 @@ public: Note that to make sure the host correctly handles automation, you should call the beginParameterChangeGesture() and endParameterChangeGesture() methods to tell the host when the user has started and stopped changing the parameter. + + NOTE! This method will eventually be deprecated! It's recommended that you use + AudioProcessorParameter::setValueNotifyingHost() instead. */ void setParameterNotifyingHost (int parameterIndex, float newValue); /** Returns true if the host can automate this parameter. By default, this returns true for all parameters. + + NOTE! This method will eventually be deprecated! It's recommended that you use + AudioProcessorParameter::isAutomatable() instead. */ virtual bool isParameterAutomatable (int parameterIndex) const; @@ -472,6 +527,9 @@ public: A meta-parameter is a parameter that changes other params. It is used by some hosts (e.g. AudioUnit hosts). By default this returns false. + + NOTE! This method will eventually be deprecated! It's recommended that you use + AudioProcessorParameter::isMetaParameter() instead. */ virtual bool isMetaParameter (int parameterIndex) const; @@ -482,6 +540,9 @@ public: it may use this information to help it record automation. If you call this, it must be matched by a later call to endParameterChangeGesture(). + + NOTE! This method will eventually be deprecated! It's recommended that you use + AudioProcessorParameter::beginChangeGesture() instead. */ void beginParameterChangeGesture (int parameterIndex); @@ -491,6 +552,9 @@ public: it may use this information to help it record automation. A call to this method must follow a call to beginParameterChangeGesture(). + + NOTE! This method will eventually be deprecated! It's recommended that you use + AudioProcessorParameter::endChangeGesture() instead. */ void endParameterChangeGesture (int parameterIndex); @@ -501,6 +565,16 @@ public: */ void updateHostDisplay(); + //============================================================================== + /** Adds a parameter to the list. + The parameter object will be managed and deleted automatically by the list + when no longer needed. + */ + void addParameter (AudioProcessorParameter*); + + /** Returns the current list of parameters. */ + const OwnedArray& getParameters() const noexcept; + //============================================================================== /** Returns the number of preset programs the filter supports. @@ -657,7 +731,10 @@ private: CriticalSection callbackLock, listenerLock; String inputSpeakerArrangement, outputSpeakerArrangement; - #if JUCE_DEBUG + OwnedArray managedParameters; + AudioProcessorParameter* getParamChecked (int) const noexcept; + + #if JUCE_DEBUG && ! JUCE_DISABLE_AUDIOPROCESSOR_BEGIN_END_GESTURE_CHECKING BigInteger changingParams; #endif diff --git a/JuceLibraryCode/modules/juce_audio_processors/processors/juce_AudioProcessorEditor.cpp b/JuceLibraryCode/modules/juce_audio_processors/processors/juce_AudioProcessorEditor.cpp index a4c9d29..07f865e 100644 --- a/JuceLibraryCode/modules/juce_audio_processors/processors/juce_AudioProcessorEditor.cpp +++ b/JuceLibraryCode/modules/juce_audio_processors/processors/juce_AudioProcessorEditor.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -22,16 +22,22 @@ ============================================================================== */ -AudioProcessorEditor::AudioProcessorEditor (AudioProcessor* const p) - : owner (p) +AudioProcessorEditor::AudioProcessorEditor (AudioProcessor& p) noexcept : processor (p) +{ +} + +AudioProcessorEditor::AudioProcessorEditor (AudioProcessor* p) noexcept : processor (*p) { // the filter must be valid.. - jassert (owner != nullptr); + jassert (p != nullptr); } AudioProcessorEditor::~AudioProcessorEditor() { // if this fails, then the wrapper hasn't called editorBeingDeleted() on the // filter for some reason.. - jassert (owner->getActiveEditor() != this); + jassert (processor.getActiveEditor() != this); } + +void AudioProcessorEditor::setControlHighlight (ParameterControlHighlightInfo) {} +int AudioProcessorEditor::getControlParameterIndex (Component&) { return -1; } diff --git a/JuceLibraryCode/modules/juce_audio_processors/processors/juce_AudioProcessorEditor.h b/JuceLibraryCode/modules/juce_audio_processors/processors/juce_AudioProcessorEditor.h index 3c811a2..e043c37 100644 --- a/JuceLibraryCode/modules/juce_audio_processors/processors/juce_AudioProcessorEditor.h +++ b/JuceLibraryCode/modules/juce_audio_processors/processors/juce_AudioProcessorEditor.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -39,9 +39,11 @@ class JUCE_API AudioProcessorEditor : public Component { protected: //============================================================================== - /** Creates an editor for the specified processor. - */ - AudioProcessorEditor (AudioProcessor* owner); + /** Creates an editor for the specified processor. */ + AudioProcessorEditor (AudioProcessor&) noexcept; + + /** Creates an editor for the specified processor. */ + AudioProcessorEditor (AudioProcessor*) noexcept; public: /** Destructor. */ @@ -49,14 +51,40 @@ public: //============================================================================== - /** Returns a pointer to the processor that this editor represents. */ - AudioProcessor* getAudioProcessor() const noexcept { return owner; } + /** The AudioProcessor that this editor represents. */ + AudioProcessor& processor; + /** Returns a pointer to the processor that this editor represents. + This method is here to support legacy code, but it's easier to just use the + AudioProcessorEditor::processor member variable directly to get this object. + */ + AudioProcessor* getAudioProcessor() const noexcept { return &processor; } + + //============================================================================== + /** Used by the setParameterHighlighting() method. */ + struct ParameterControlHighlightInfo + { + int parameterIndex; + bool isHighlighted; + Colour suggestedColour; + }; + + /** Some types of plugin can call this to suggest that the control for a particular + parameter should be highlighted. + Currently only AAX plugins will call this, and implementing it is optional. + */ + virtual void setControlHighlight (ParameterControlHighlightInfo); + + /** Called by certain plug-in wrappers to find out whether a component is used + to control a parameter. + + If the given component represents a particular plugin parameter, then this + method should return the index of that parameter. If not, it should return -1. + Currently only AAX plugins will call this, and implementing it is optional. + */ + virtual int getControlParameterIndex (Component&); private: - //============================================================================== - AudioProcessor* const owner; - JUCE_DECLARE_NON_COPYABLE (AudioProcessorEditor) }; diff --git a/JuceLibraryCode/modules/juce_audio_processors/processors/juce_AudioProcessorGraph.cpp b/JuceLibraryCode/modules/juce_audio_processors/processors/juce_AudioProcessorGraph.cpp index 9ca46d2..924286d 100644 --- a/JuceLibraryCode/modules/juce_audio_processors/processors/juce_AudioProcessorGraph.cpp +++ b/JuceLibraryCode/modules/juce_audio_processors/processors/juce_AudioProcessorGraph.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -29,151 +29,129 @@ namespace GraphRenderingOps { //============================================================================== -class AudioGraphRenderingOp +struct AudioGraphRenderingOp { -public: - AudioGraphRenderingOp() {} - virtual ~AudioGraphRenderingOp() {} + AudioGraphRenderingOp() noexcept {} + virtual ~AudioGraphRenderingOp() {} virtual void perform (AudioSampleBuffer& sharedBufferChans, - const OwnedArray & sharedMidiBuffers, + const OwnedArray& sharedMidiBuffers, const int numSamples) = 0; JUCE_LEAK_DETECTOR (AudioGraphRenderingOp) }; //============================================================================== -class ClearChannelOp : public AudioGraphRenderingOp +struct ClearChannelOp : public AudioGraphRenderingOp { -public: - ClearChannelOp (const int channelNum_) - : channelNum (channelNum_) - {} + ClearChannelOp (const int channel) noexcept : channelNum (channel) {} - void perform (AudioSampleBuffer& sharedBufferChans, const OwnedArray &, const int numSamples) + void perform (AudioSampleBuffer& sharedBufferChans, const OwnedArray&, const int numSamples) { sharedBufferChans.clear (channelNum, 0, numSamples); } -private: const int channelNum; JUCE_DECLARE_NON_COPYABLE (ClearChannelOp) }; //============================================================================== -class CopyChannelOp : public AudioGraphRenderingOp +struct CopyChannelOp : public AudioGraphRenderingOp { -public: - CopyChannelOp (const int srcChannelNum_, const int dstChannelNum_) - : srcChannelNum (srcChannelNum_), - dstChannelNum (dstChannelNum_) + CopyChannelOp (const int srcChan, const int dstChan) noexcept + : srcChannelNum (srcChan), dstChannelNum (dstChan) {} - void perform (AudioSampleBuffer& sharedBufferChans, const OwnedArray &, const int numSamples) + void perform (AudioSampleBuffer& sharedBufferChans, const OwnedArray&, const int numSamples) { sharedBufferChans.copyFrom (dstChannelNum, 0, sharedBufferChans, srcChannelNum, 0, numSamples); } -private: const int srcChannelNum, dstChannelNum; JUCE_DECLARE_NON_COPYABLE (CopyChannelOp) }; //============================================================================== -class AddChannelOp : public AudioGraphRenderingOp +struct AddChannelOp : public AudioGraphRenderingOp { -public: - AddChannelOp (const int srcChannelNum_, const int dstChannelNum_) - : srcChannelNum (srcChannelNum_), - dstChannelNum (dstChannelNum_) + AddChannelOp (const int srcChan, const int dstChan) noexcept + : srcChannelNum (srcChan), dstChannelNum (dstChan) {} - void perform (AudioSampleBuffer& sharedBufferChans, const OwnedArray &, const int numSamples) + void perform (AudioSampleBuffer& sharedBufferChans, const OwnedArray&, const int numSamples) { sharedBufferChans.addFrom (dstChannelNum, 0, sharedBufferChans, srcChannelNum, 0, numSamples); } -private: const int srcChannelNum, dstChannelNum; JUCE_DECLARE_NON_COPYABLE (AddChannelOp) }; //============================================================================== -class ClearMidiBufferOp : public AudioGraphRenderingOp +struct ClearMidiBufferOp : public AudioGraphRenderingOp { -public: - ClearMidiBufferOp (const int bufferNum_) - : bufferNum (bufferNum_) - {} + ClearMidiBufferOp (const int buffer) noexcept : bufferNum (buffer) {} - void perform (AudioSampleBuffer&, const OwnedArray & sharedMidiBuffers, const int) + void perform (AudioSampleBuffer&, const OwnedArray& sharedMidiBuffers, const int) { sharedMidiBuffers.getUnchecked (bufferNum)->clear(); } -private: const int bufferNum; JUCE_DECLARE_NON_COPYABLE (ClearMidiBufferOp) }; //============================================================================== -class CopyMidiBufferOp : public AudioGraphRenderingOp +struct CopyMidiBufferOp : public AudioGraphRenderingOp { -public: - CopyMidiBufferOp (const int srcBufferNum_, const int dstBufferNum_) - : srcBufferNum (srcBufferNum_), - dstBufferNum (dstBufferNum_) + CopyMidiBufferOp (const int srcBuffer, const int dstBuffer) noexcept + : srcBufferNum (srcBuffer), dstBufferNum (dstBuffer) {} - void perform (AudioSampleBuffer&, const OwnedArray & sharedMidiBuffers, const int) + void perform (AudioSampleBuffer&, const OwnedArray& sharedMidiBuffers, const int) { *sharedMidiBuffers.getUnchecked (dstBufferNum) = *sharedMidiBuffers.getUnchecked (srcBufferNum); } -private: const int srcBufferNum, dstBufferNum; JUCE_DECLARE_NON_COPYABLE (CopyMidiBufferOp) }; //============================================================================== -class AddMidiBufferOp : public AudioGraphRenderingOp +struct AddMidiBufferOp : public AudioGraphRenderingOp { -public: - AddMidiBufferOp (const int srcBufferNum_, const int dstBufferNum_) - : srcBufferNum (srcBufferNum_), - dstBufferNum (dstBufferNum_) + AddMidiBufferOp (const int srcBuffer, const int dstBuffer) + : srcBufferNum (srcBuffer), dstBufferNum (dstBuffer) {} - void perform (AudioSampleBuffer&, const OwnedArray & sharedMidiBuffers, const int numSamples) + void perform (AudioSampleBuffer&, const OwnedArray& sharedMidiBuffers, const int numSamples) { sharedMidiBuffers.getUnchecked (dstBufferNum) ->addEvents (*sharedMidiBuffers.getUnchecked (srcBufferNum), 0, numSamples, 0); } -private: const int srcBufferNum, dstBufferNum; JUCE_DECLARE_NON_COPYABLE (AddMidiBufferOp) }; //============================================================================== -class DelayChannelOp : public AudioGraphRenderingOp +struct DelayChannelOp : public AudioGraphRenderingOp { -public: - DelayChannelOp (const int channel_, const int numSamplesDelay_) - : channel (channel_), - bufferSize (numSamplesDelay_ + 1), - readIndex (0), writeIndex (numSamplesDelay_) + DelayChannelOp (const int chan, const int delaySize) + : channel (chan), + bufferSize (delaySize + 1), + readIndex (0), writeIndex (delaySize) { buffer.calloc ((size_t) bufferSize); } - void perform (AudioSampleBuffer& sharedBufferChans, const OwnedArray &, const int numSamples) + void perform (AudioSampleBuffer& sharedBufferChans, const OwnedArray&, const int numSamples) { float* data = sharedBufferChans.getWritePointer (channel, 0); @@ -197,18 +175,17 @@ private: //============================================================================== -class ProcessBufferOp : public AudioGraphRenderingOp +struct ProcessBufferOp : public AudioGraphRenderingOp { -public: - ProcessBufferOp (const AudioProcessorGraph::Node::Ptr& node_, - const Array & audioChannelsToUse_, - const int totalChans_, - const int midiBufferToUse_) - : node (node_), - processor (node_->getProcessor()), - audioChannelsToUse (audioChannelsToUse_), - totalChans (jmax (1, totalChans_)), - midiBufferToUse (midiBufferToUse_) + ProcessBufferOp (const AudioProcessorGraph::Node::Ptr& n, + const Array& audioChannels, + const int totalNumChans, + const int midiBuffer) + : node (n), + processor (n->getProcessor()), + audioChannelsToUse (audioChannels), + totalChans (jmax (1, totalNumChans)), + midiBufferToUse (midiBuffer) { channels.calloc ((size_t) totalChans); @@ -216,7 +193,7 @@ public: audioChannelsToUse.add (0); } - void perform (AudioSampleBuffer& sharedBufferChans, const OwnedArray & sharedMidiBuffers, const int numSamples) + void perform (AudioSampleBuffer& sharedBufferChans, const OwnedArray& sharedMidiBuffers, const int numSamples) { for (int i = totalChans; --i >= 0;) channels[i] = sharedBufferChans.getWritePointer (audioChannelsToUse.getUnchecked (i), 0); @@ -232,8 +209,8 @@ public: private: Array audioChannelsToUse; HeapBlock channels; - int totalChans; - int midiBufferToUse; + const int totalChans; + const int midiBufferToUse; JUCE_DECLARE_NON_COPYABLE (ProcessBufferOp) }; @@ -242,15 +219,13 @@ private: /** Used to calculate the correct sequence of rendering ops needed, based on the best re-use of shared buffers at each stage. */ -class RenderingOpSequenceCalculator +struct RenderingOpSequenceCalculator { -public: - //============================================================================== - RenderingOpSequenceCalculator (AudioProcessorGraph& graph_, - const Array& orderedNodes_, + RenderingOpSequenceCalculator (AudioProcessorGraph& g, + const Array& nodes, Array& renderingOps) - : graph (graph_), - orderedNodes (orderedNodes_), + : graph (g), + orderedNodes (nodes), totalLatency (0) { nodeIds.add ((uint32) zeroNodeID); // first buffer is read-only zeros @@ -260,34 +235,32 @@ public: for (int i = 0; i < orderedNodes.size(); ++i) { - createRenderingOpsForNode ((AudioProcessorGraph::Node*) orderedNodes.getUnchecked(i), - renderingOps, i); - + createRenderingOpsForNode (*orderedNodes.getUnchecked(i), renderingOps, i); markAnyUnusedBuffersAsFree (i); } graph.setLatencySamples (totalLatency); } - int getNumBuffersNeeded() const { return nodeIds.size(); } - int getNumMidiBuffersNeeded() const { return midiNodeIds.size(); } + int getNumBuffersNeeded() const noexcept { return nodeIds.size(); } + int getNumMidiBuffersNeeded() const noexcept { return midiNodeIds.size(); } private: //============================================================================== AudioProcessorGraph& graph; - const Array& orderedNodes; - Array channels; - Array nodeIds, midiNodeIds; + const Array& orderedNodes; + Array channels; + Array nodeIds, midiNodeIds; enum { freeNodeID = 0xffffffff, zeroNodeID = 0xfffffffe }; - static bool isNodeBusy (uint32 nodeID) noexcept { return nodeID != freeNodeID && nodeID != zeroNodeID; } + static bool isNodeBusy (uint32 nodeID) noexcept { return nodeID != freeNodeID && nodeID != zeroNodeID; } - Array nodeDelayIDs; - Array nodeDelays; + Array nodeDelayIDs; + Array nodeDelays; int totalLatency; - int getNodeDelay (const uint32 nodeID) const { return nodeDelays [nodeDelayIDs.indexOf (nodeID)]; } + int getNodeDelay (const uint32 nodeID) const { return nodeDelays [nodeDelayIDs.indexOf (nodeID)]; } void setNodeDelay (const uint32 nodeID, const int latency) { @@ -320,30 +293,31 @@ private: } //============================================================================== - void createRenderingOpsForNode (AudioProcessorGraph::Node* const node, + void createRenderingOpsForNode (AudioProcessorGraph::Node& node, Array& renderingOps, const int ourRenderingIndex) { - const int numIns = node->getProcessor()->getNumInputChannels(); - const int numOuts = node->getProcessor()->getNumOutputChannels(); + AudioProcessor& processor = *node.getProcessor(); + const int numIns = processor.getNumInputChannels(); + const int numOuts = processor.getNumOutputChannels(); const int totalChans = jmax (numIns, numOuts); - Array audioChannelsToUse; + Array audioChannelsToUse; int midiBufferToUse = -1; - int maxLatency = getInputLatencyForNode (node->nodeId); + int maxLatency = getInputLatencyForNode (node.nodeId); for (int inputChan = 0; inputChan < numIns; ++inputChan) { // get a list of all the inputs to this node - Array sourceNodes; + Array sourceNodes; Array sourceOutputChans; for (int i = graph.getNumConnections(); --i >= 0;) { const AudioProcessorGraph::Connection* const c = graph.getConnection (i); - if (c->destNodeId == node->nodeId && c->destChannelIndex == inputChan) + if (c->destNodeId == node.nodeId && c->destChannelIndex == inputChan) { sourceNodes.add (c->sourceNodeId); sourceOutputChans.add (c->sourceChannelIndex); @@ -493,7 +467,7 @@ private: audioChannelsToUse.add (bufIndex); if (inputChan < numOuts) - markBufferAsContaining (bufIndex, node->nodeId, inputChan); + markBufferAsContaining (bufIndex, node.nodeId, inputChan); } for (int outputChan = numIns; outputChan < numOuts; ++outputChan) @@ -502,17 +476,17 @@ private: jassert (bufIndex != 0); audioChannelsToUse.add (bufIndex); - markBufferAsContaining (bufIndex, node->nodeId, outputChan); + markBufferAsContaining (bufIndex, node.nodeId, outputChan); } // Now the same thing for midi.. - Array midiSourceNodes; + Array midiSourceNodes; for (int i = graph.getNumConnections(); --i >= 0;) { const AudioProcessorGraph::Connection* const c = graph.getConnection (i); - if (c->destNodeId == node->nodeId && c->destChannelIndex == AudioProcessorGraph::midiChannelIndex) + if (c->destNodeId == node.nodeId && c->destChannelIndex == AudioProcessorGraph::midiChannelIndex) midiSourceNodes.add (c->sourceNodeId); } @@ -521,7 +495,7 @@ private: // No midi inputs.. midiBufferToUse = getFreeBuffer (true); // need to pick a buffer even if the processor doesn't use midi - if (node->getProcessor()->acceptsMidi() || node->getProcessor()->producesMidi()) + if (processor.acceptsMidi() || processor.producesMidi()) renderingOps.add (new ClearMidiBufferOp (midiBufferToUse)); } else if (midiSourceNodes.size() == 1) @@ -601,16 +575,16 @@ private: } } - if (node->getProcessor()->producesMidi()) - markBufferAsContaining (midiBufferToUse, node->nodeId, + if (processor.producesMidi()) + markBufferAsContaining (midiBufferToUse, node.nodeId, AudioProcessorGraph::midiChannelIndex); - setNodeDelay (node->nodeId, maxLatency + node->getProcessor()->getLatencySamples()); + setNodeDelay (node.nodeId, maxLatency + processor.getLatencySamples()); if (numOuts == 0) totalLatency = maxLatency; - renderingOps.add (new ProcessBufferOp (node, audioChannelsToUse, + renderingOps.add (new ProcessBufferOp (&node, audioChannelsToUse, totalChans, midiBufferToUse)); } @@ -872,18 +846,16 @@ struct ConnectionSorter } //============================================================================== -AudioProcessorGraph::Connection::Connection (const uint32 sourceNodeId_, const int sourceChannelIndex_, - const uint32 destNodeId_, const int destChannelIndex_) noexcept - : sourceNodeId (sourceNodeId_), sourceChannelIndex (sourceChannelIndex_), - destNodeId (destNodeId_), destChannelIndex (destChannelIndex_) +AudioProcessorGraph::Connection::Connection (const uint32 sourceID, const int sourceChannel, + const uint32 destID, const int destChannel) noexcept + : sourceNodeId (sourceID), sourceChannelIndex (sourceChannel), + destNodeId (destID), destChannelIndex (destChannel) { } //============================================================================== -AudioProcessorGraph::Node::Node (const uint32 nodeId_, AudioProcessor* const processor_) noexcept - : nodeId (nodeId_), - processor (processor_), - isPrepared (false) +AudioProcessorGraph::Node::Node (const uint32 nodeID, AudioProcessor* const p) noexcept + : nodeId (nodeID), processor (p), isPrepared (false) { jassert (processor != nullptr); } @@ -916,7 +888,7 @@ void AudioProcessorGraph::Node::unprepare() void AudioProcessorGraph::Node::setParentGraph (AudioProcessorGraph* const graph) const { if (AudioProcessorGraph::AudioGraphIOProcessor* const ioProc - = dynamic_cast (processor.get())) + = dynamic_cast (processor.get())) ioProc->setParentGraph (graph); } @@ -1005,7 +977,6 @@ bool AudioProcessorGraph::removeNode (const uint32 nodeId) { if (nodes.getUnchecked(i)->nodeId == nodeId) { - nodes.getUnchecked(i)->setParentGraph (nullptr); nodes.remove (i); triggerAsyncUpdate(); @@ -1213,7 +1184,7 @@ void AudioProcessorGraph::buildRenderingSequence() { MessageManagerLock mml; - Array orderedNodes; + Array orderedNodes; { const GraphRenderingOps::ConnectionLookupTable table (connections); @@ -1298,6 +1269,24 @@ void AudioProcessorGraph::reset() nodes.getUnchecked(i)->getProcessor()->reset(); } +void AudioProcessorGraph::setNonRealtime (bool isProcessingNonRealtime) noexcept +{ + const ScopedLock sl (getCallbackLock()); + + for (int i = 0; i < nodes.size(); ++i) + nodes.getUnchecked(i)->getProcessor()->setNonRealtime (isProcessingNonRealtime); +} + +void AudioProcessorGraph::setPlayHead (AudioPlayHead* audioPlayHead) +{ + const ScopedLock sl (getCallbackLock()); + + AudioProcessor::setPlayHead (audioPlayHead); + + for (int i = 0; i < nodes.size(); ++i) + nodes.getUnchecked(i)->getProcessor()->setPlayHead (audioPlayHead); +} + void AudioProcessorGraph::processBlock (AudioSampleBuffer& buffer, MidiBuffer& midiMessages) { const int numSamples = buffer.getNumSamples(); @@ -1333,20 +1322,19 @@ const String AudioProcessorGraph::getOutputChannelName (int channelIndex) const return "Output " + String (channelIndex + 1); } -bool AudioProcessorGraph::isInputChannelStereoPair (int /*index*/) const { return true; } -bool AudioProcessorGraph::isOutputChannelStereoPair (int /*index*/) const { return true; } -bool AudioProcessorGraph::silenceInProducesSilenceOut() const { return false; } -double AudioProcessorGraph::getTailLengthSeconds() const { return 0; } -bool AudioProcessorGraph::acceptsMidi() const { return true; } -bool AudioProcessorGraph::producesMidi() const { return true; } -void AudioProcessorGraph::getStateInformation (juce::MemoryBlock& /*destData*/) {} -void AudioProcessorGraph::setStateInformation (const void* /*data*/, int /*sizeInBytes*/) {} +bool AudioProcessorGraph::isInputChannelStereoPair (int) const { return true; } +bool AudioProcessorGraph::isOutputChannelStereoPair (int) const { return true; } +bool AudioProcessorGraph::silenceInProducesSilenceOut() const { return false; } +double AudioProcessorGraph::getTailLengthSeconds() const { return 0; } +bool AudioProcessorGraph::acceptsMidi() const { return true; } +bool AudioProcessorGraph::producesMidi() const { return true; } +void AudioProcessorGraph::getStateInformation (juce::MemoryBlock&) {} +void AudioProcessorGraph::setStateInformation (const void*, int) {} //============================================================================== -AudioProcessorGraph::AudioGraphIOProcessor::AudioGraphIOProcessor (const IODeviceType type_) - : type (type_), - graph (nullptr) +AudioProcessorGraph::AudioGraphIOProcessor::AudioGraphIOProcessor (const IODeviceType deviceType) + : type (deviceType), graph (nullptr) { } @@ -1374,7 +1362,7 @@ void AudioProcessorGraph::AudioGraphIOProcessor::fillInPluginDescription (Plugin d.uid = d.name.hashCode(); d.category = "I/O devices"; d.pluginFormatName = "Internal"; - d.manufacturerName = "Raw Material Software"; + d.manufacturerName = "ROLI Ltd."; d.version = "1.0"; d.isInstrument = false; @@ -1492,19 +1480,12 @@ bool AudioProcessorGraph::AudioGraphIOProcessor::isOutputChannelStereoPair (int return isInputChannelStereoPair (index); } -bool AudioProcessorGraph::AudioGraphIOProcessor::isInput() const { return type == audioInputNode || type == midiInputNode; } -bool AudioProcessorGraph::AudioGraphIOProcessor::isOutput() const { return type == audioOutputNode || type == midiOutputNode; } +bool AudioProcessorGraph::AudioGraphIOProcessor::isInput() const noexcept { return type == audioInputNode || type == midiInputNode; } +bool AudioProcessorGraph::AudioGraphIOProcessor::isOutput() const noexcept { return type == audioOutputNode || type == midiOutputNode; } bool AudioProcessorGraph::AudioGraphIOProcessor::hasEditor() const { return false; } AudioProcessorEditor* AudioProcessorGraph::AudioGraphIOProcessor::createEditor() { return nullptr; } -int AudioProcessorGraph::AudioGraphIOProcessor::getNumParameters() { return 0; } -const String AudioProcessorGraph::AudioGraphIOProcessor::getParameterName (int) { return String(); } - -float AudioProcessorGraph::AudioGraphIOProcessor::getParameter (int) { return 0.0f; } -const String AudioProcessorGraph::AudioGraphIOProcessor::getParameterText (int) { return String(); } -void AudioProcessorGraph::AudioGraphIOProcessor::setParameter (int, float) { } - int AudioProcessorGraph::AudioGraphIOProcessor::getNumPrograms() { return 0; } int AudioProcessorGraph::AudioGraphIOProcessor::getCurrentProgram() { return 0; } void AudioProcessorGraph::AudioGraphIOProcessor::setCurrentProgram (int) { } @@ -1522,7 +1503,7 @@ void AudioProcessorGraph::AudioGraphIOProcessor::setParentGraph (AudioProcessorG if (graph != nullptr) { setPlayConfigDetails (type == audioOutputNode ? graph->getNumOutputChannels() : 0, - type == audioInputNode ? graph->getNumInputChannels() : 0, + type == audioInputNode ? graph->getNumInputChannels() : 0, getSampleRate(), getBlockSize()); diff --git a/JuceLibraryCode/modules/juce_audio_processors/processors/juce_AudioProcessorGraph.h b/JuceLibraryCode/modules/juce_audio_processors/processors/juce_AudioProcessorGraph.h index d944682..5662be6 100644 --- a/JuceLibraryCode/modules/juce_audio_processors/processors/juce_AudioProcessorGraph.h +++ b/JuceLibraryCode/modules/juce_audio_processors/processors/juce_AudioProcessorGraph.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -80,7 +80,7 @@ public: //============================================================================== /** A convenient typedef for referring to a pointer to a node object. */ - typedef ReferenceCountedObjectPtr Ptr; + typedef ReferenceCountedObjectPtr Ptr; private: //============================================================================== @@ -151,13 +151,13 @@ public: void clear(); /** Returns the number of nodes in the graph. */ - int getNumNodes() const { return nodes.size(); } + int getNumNodes() const noexcept { return nodes.size(); } /** Returns a pointer to one of the nodes in the graph. This will return nullptr if the index is out of range. @see getNodeForId */ - Node* getNode (const int index) const { return nodes [index]; } + Node* getNode (const int index) const noexcept { return nodes [index]; } /** Searches the graph for a node with the given ID number and returns it. If no such node was found, this returns nullptr. @@ -289,54 +289,47 @@ public: //============================================================================== /** Returns the mode of this processor. */ - IODeviceType getType() const { return type; } + IODeviceType getType() const noexcept { return type; } /** Returns the parent graph to which this processor belongs, or nullptr if it hasn't yet been added to one. */ - AudioProcessorGraph* getParentGraph() const { return graph; } + AudioProcessorGraph* getParentGraph() const noexcept { return graph; } /** True if this is an audio or midi input. */ - bool isInput() const; + bool isInput() const noexcept; /** True if this is an audio or midi output. */ - bool isOutput() const; + bool isOutput() const noexcept; //============================================================================== AudioGraphIOProcessor (const IODeviceType type); ~AudioGraphIOProcessor(); - const String getName() const; - void fillInPluginDescription (PluginDescription&) const; + const String getName() const override; + void fillInPluginDescription (PluginDescription&) const override; + void prepareToPlay (double sampleRate, int estimatedSamplesPerBlock) override; + void releaseResources() override; + void processBlock (AudioSampleBuffer&, MidiBuffer&) override; - void prepareToPlay (double sampleRate, int estimatedSamplesPerBlock); - void releaseResources(); - void processBlock (AudioSampleBuffer&, MidiBuffer&); + const String getInputChannelName (int channelIndex) const override; + const String getOutputChannelName (int channelIndex) const override; + bool isInputChannelStereoPair (int index) const override; + bool isOutputChannelStereoPair (int index) const override; + bool silenceInProducesSilenceOut() const override; + double getTailLengthSeconds() const override; + bool acceptsMidi() const override; + bool producesMidi() const override; - const String getInputChannelName (int channelIndex) const; - const String getOutputChannelName (int channelIndex) const; - bool isInputChannelStereoPair (int index) const; - bool isOutputChannelStereoPair (int index) const; - bool silenceInProducesSilenceOut() const; - double getTailLengthSeconds() const; - bool acceptsMidi() const; - bool producesMidi() const; + bool hasEditor() const override; + AudioProcessorEditor* createEditor() override; - bool hasEditor() const; - AudioProcessorEditor* createEditor(); + int getNumPrograms() override; + int getCurrentProgram() override; + void setCurrentProgram (int) override; + const String getProgramName (int) override; + void changeProgramName (int, const String&) override; - int getNumParameters(); - const String getParameterName (int); - float getParameter (int); - const String getParameterText (int); - void setParameter (int, float); - - int getNumPrograms(); - int getCurrentProgram(); - void setCurrentProgram (int); - const String getProgramName (int); - void changeProgramName (int, const String&); - - void getStateInformation (juce::MemoryBlock& destData); - void setStateInformation (const void* data, int sizeInBytes); + void getStateInformation (juce::MemoryBlock& destData) override; + void setStateInformation (const void* data, int sizeInBytes) override; /** @internal */ void setParentGraph (AudioProcessorGraph*); @@ -349,42 +342,34 @@ public: }; //============================================================================== - // AudioProcessor methods: + const String getName() const override; + void prepareToPlay (double, int) override; + void releaseResources() override; + void processBlock (AudioSampleBuffer&, MidiBuffer&) override; - const String getName() const; + void reset() override; + void setNonRealtime (bool) noexcept override; + void setPlayHead (AudioPlayHead*) override; - void prepareToPlay (double sampleRate, int estimatedSamplesPerBlock); - void releaseResources(); - void processBlock (AudioSampleBuffer&, MidiBuffer&); - void reset(); + const String getInputChannelName (int) const override; + const String getOutputChannelName (int) const override; + bool isInputChannelStereoPair (int) const override; + bool isOutputChannelStereoPair (int) const override; - const String getInputChannelName (int channelIndex) const; - const String getOutputChannelName (int channelIndex) const; - bool isInputChannelStereoPair (int index) const; - bool isOutputChannelStereoPair (int index) const; - bool silenceInProducesSilenceOut() const; - double getTailLengthSeconds() const; + bool silenceInProducesSilenceOut() const override; + double getTailLengthSeconds() const override; + bool acceptsMidi() const override; + bool producesMidi() const override; - bool acceptsMidi() const; - bool producesMidi() const; - - bool hasEditor() const { return false; } - AudioProcessorEditor* createEditor() { return nullptr; } - - int getNumParameters() { return 0; } - const String getParameterName (int) { return String(); } - float getParameter (int) { return 0; } - const String getParameterText (int) { return String(); } - void setParameter (int, float) { } - - int getNumPrograms() { return 0; } - int getCurrentProgram() { return 0; } - void setCurrentProgram (int) { } - const String getProgramName (int) { return String(); } - void changeProgramName (int, const String&) { } - - void getStateInformation (juce::MemoryBlock&); - void setStateInformation (const void* data, int sizeInBytes); + bool hasEditor() const override { return false; } + AudioProcessorEditor* createEditor() override { return nullptr; } + int getNumPrograms() override { return 0; } + int getCurrentProgram() override { return 0; } + void setCurrentProgram (int) override { } + const String getProgramName (int) override { return String(); } + void changeProgramName (int, const String&) override { } + void getStateInformation (juce::MemoryBlock&) override; + void setStateInformation (const void* data, int sizeInBytes) override; private: //============================================================================== diff --git a/JuceLibraryCode/modules/juce_audio_processors/processors/juce_AudioProcessorListener.h b/JuceLibraryCode/modules/juce_audio_processors/processors/juce_AudioProcessorListener.h index d8ea93c..a2fe16e 100644 --- a/JuceLibraryCode/modules/juce_audio_processors/processors/juce_AudioProcessorListener.h +++ b/JuceLibraryCode/modules/juce_audio_processors/processors/juce_AudioProcessorListener.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_audio_processors/processors/juce_GenericAudioProcessorEditor.cpp b/JuceLibraryCode/modules/juce_audio_processors/processors/juce_GenericAudioProcessorEditor.cpp index c94411d..e1ba865 100644 --- a/JuceLibraryCode/modules/juce_audio_processors/processors/juce_GenericAudioProcessorEditor.cpp +++ b/JuceLibraryCode/modules/juce_audio_processors/processors/juce_GenericAudioProcessorEditor.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -67,7 +67,7 @@ public: if (paramHasChanged) { refresh(); - startTimer (1000 / 50); + startTimerHz (50); } else { diff --git a/JuceLibraryCode/modules/juce_audio_processors/processors/juce_GenericAudioProcessorEditor.h b/JuceLibraryCode/modules/juce_audio_processors/processors/juce_GenericAudioProcessorEditor.h index 1189f88..dc5d8fa 100644 --- a/JuceLibraryCode/modules/juce_audio_processors/processors/juce_GenericAudioProcessorEditor.h +++ b/JuceLibraryCode/modules/juce_audio_processors/processors/juce_GenericAudioProcessorEditor.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_audio_processors/processors/juce_PluginDescription.cpp b/JuceLibraryCode/modules/juce_audio_processors/processors/juce_PluginDescription.cpp index 8e1010f..2e647ec 100644 --- a/JuceLibraryCode/modules/juce_audio_processors/processors/juce_PluginDescription.cpp +++ b/JuceLibraryCode/modules/juce_audio_processors/processors/juce_PluginDescription.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -71,18 +71,26 @@ PluginDescription& PluginDescription::operator= (const PluginDescription& other) return *this; } -bool PluginDescription::isDuplicateOf (const PluginDescription& other) const +bool PluginDescription::isDuplicateOf (const PluginDescription& other) const noexcept { return fileOrIdentifier == other.fileOrIdentifier && uid == other.uid; } +static String getPluginDescSuffix (const PluginDescription& d) +{ + return "-" + String::toHexString (d.fileOrIdentifier.hashCode()) + + "-" + String::toHexString (d.uid); +} + +bool PluginDescription::matchesIdentifierString (const String& identifierString) const +{ + return identifierString.endsWithIgnoreCase (getPluginDescSuffix (*this)); +} + String PluginDescription::createIdentifierString() const { - return pluginFormatName - + "-" + name - + "-" + String::toHexString (fileOrIdentifier.hashCode()) - + "-" + String::toHexString (uid); + return pluginFormatName + "-" + name + getPluginDescSuffix (*this); } XmlElement* PluginDescription::createXml() const diff --git a/JuceLibraryCode/modules/juce_audio_processors/processors/juce_PluginDescription.h b/JuceLibraryCode/modules/juce_audio_processors/processors/juce_PluginDescription.h index 6361775..83effce 100644 --- a/JuceLibraryCode/modules/juce_audio_processors/processors/juce_PluginDescription.h +++ b/JuceLibraryCode/modules/juce_audio_processors/processors/juce_PluginDescription.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -107,7 +107,15 @@ public: This isn't quite as simple as them just having the same file (because of shell plug-ins). */ - bool isDuplicateOf (const PluginDescription& other) const; + bool isDuplicateOf (const PluginDescription& other) const noexcept; + + /** Return true if this description is equivalent to another one which created the + given identifier string. + + Note that this isn't quite as simple as them just calling createIdentifierString() + and comparing the strings, because the identifers can differ (thanks to shell plug-ins). + */ + bool matchesIdentifierString (const String& identifierString) const; //============================================================================== /** Returns a string that can be saved and used to uniquely identify the diff --git a/JuceLibraryCode/modules/juce_audio_processors/scanning/juce_KnownPluginList.cpp b/JuceLibraryCode/modules/juce_audio_processors/scanning/juce_KnownPluginList.cpp index afbf23e..ad37837 100644 --- a/JuceLibraryCode/modules/juce_audio_processors/scanning/juce_KnownPluginList.cpp +++ b/JuceLibraryCode/modules/juce_audio_processors/scanning/juce_KnownPluginList.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -46,7 +46,7 @@ PluginDescription* KnownPluginList::getTypeForFile (const String& fileOrIdentifi PluginDescription* KnownPluginList::getTypeForIdentifierString (const String& identifierString) const { for (int i = 0; i < types.size(); ++i) - if (types.getUnchecked(i)->createIdentifierString() == identifierString) + if (types.getUnchecked(i)->matchesIdentifierString (identifierString)) return types.getUnchecked(i); return nullptr; @@ -259,15 +259,15 @@ struct PluginSorter switch (method) { - case KnownPluginList::sortByCategory: diff = first->category.compareLexicographically (second->category); break; - case KnownPluginList::sortByManufacturer: diff = first->manufacturerName.compareLexicographically (second->manufacturerName); break; + case KnownPluginList::sortByCategory: diff = first->category.compareNatural (second->category); break; + case KnownPluginList::sortByManufacturer: diff = first->manufacturerName.compareNatural (second->manufacturerName); break; case KnownPluginList::sortByFormat: diff = first->pluginFormatName.compare (second->pluginFormatName); break; case KnownPluginList::sortByFileSystemLocation: diff = lastPathPart (first->fileOrIdentifier).compare (lastPathPart (second->fileOrIdentifier)); break; default: break; } if (diff == 0) - diff = first->name.compareLexicographically (second->name); + diff = first->name.compareNatural (second->name); return diff * direction; } diff --git a/JuceLibraryCode/modules/juce_audio_processors/scanning/juce_KnownPluginList.h b/JuceLibraryCode/modules/juce_audio_processors/scanning/juce_KnownPluginList.h index 3c8df25..d04dd89 100644 --- a/JuceLibraryCode/modules/juce_audio_processors/scanning/juce_KnownPluginList.h +++ b/JuceLibraryCode/modules/juce_audio_processors/scanning/juce_KnownPluginList.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_audio_processors/scanning/juce_PluginDirectoryScanner.cpp b/JuceLibraryCode/modules/juce_audio_processors/scanning/juce_PluginDirectoryScanner.cpp index a7beea7..805f809 100644 --- a/JuceLibraryCode/modules/juce_audio_processors/scanning/juce_PluginDirectoryScanner.cpp +++ b/JuceLibraryCode/modules/juce_audio_processors/scanning/juce_PluginDirectoryScanner.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_audio_processors/scanning/juce_PluginDirectoryScanner.h b/JuceLibraryCode/modules/juce_audio_processors/scanning/juce_PluginDirectoryScanner.h index 762e742..8087c1c 100644 --- a/JuceLibraryCode/modules/juce_audio_processors/scanning/juce_PluginDirectoryScanner.h +++ b/JuceLibraryCode/modules/juce_audio_processors/scanning/juce_PluginDirectoryScanner.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_audio_processors/scanning/juce_PluginListComponent.cpp b/JuceLibraryCode/modules/juce_audio_processors/scanning/juce_PluginListComponent.cpp index a0c2388..8ff304d 100644 --- a/JuceLibraryCode/modules/juce_audio_processors/scanning/juce_PluginListComponent.cpp +++ b/JuceLibraryCode/modules/juce_audio_processors/scanning/juce_PluginListComponent.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -85,7 +85,7 @@ public: void deleteKeyPressed (int) override { - owner.removeSelected(); + owner.removeSelectedPlugins(); } void sortOrderChanged (int newSortColumnId, bool isForwards) override @@ -102,14 +102,6 @@ public: } } - static void removePluginItem (KnownPluginList& list, int index) - { - if (index < list.getNumTypes()) - list.removeType (index); - else - list.removeFromBlacklist (list.getBlacklistedFiles() [index - list.getNumTypes()]); - } - static String getPluginDescription (const PluginDescription& desc) { StringArray items; @@ -179,6 +171,12 @@ void PluginListComponent::setOptionsButtonText (const String& newText) resized(); } +void PluginListComponent::setScanDialogText (const String& title, const String& content) +{ + dialogTitle = title; + dialogText = content; +} + void PluginListComponent::setNumberOfThreadsForScanning (int num) { numThreads = num; @@ -207,13 +205,24 @@ void PluginListComponent::updateList() table.repaint(); } -void PluginListComponent::removeSelected() +void PluginListComponent::removeSelectedPlugins() { const SparseSet selected (table.getSelectedRows()); for (int i = table.getNumRows(); --i >= 0;) if (selected.contains (i)) - TableModel::removePluginItem (list, i); + removePluginItem (i); +} + +void PluginListComponent::setTableModel (TableListBoxModel* model) +{ + table.setModel (nullptr); + tableModel = model; + table.setModel (tableModel); + + table.getHeader().reSortTable(); + table.updateContent(); + table.repaint(); } bool PluginListComponent::canShowSelectedFolder() const @@ -238,6 +247,14 @@ void PluginListComponent::removeMissingPlugins() list.removeType (i); } +void PluginListComponent::removePluginItem (int index) +{ + if (index < list.getNumTypes()) + list.removeType (index); + else + list.removeFromBlacklist (list.getBlacklistedFiles() [index - list.getNumTypes()]); +} + void PluginListComponent::optionsMenuStaticCallback (int result, PluginListComponent* pluginList) { if (pluginList != nullptr) @@ -250,7 +267,7 @@ void PluginListComponent::optionsMenuCallback (int result) { case 0: break; case 1: list.clear(); break; - case 2: removeSelected(); break; + case 2: removeSelectedPlugins(); break; case 3: showSelectedFolder(); break; case 4: removeMissingPlugins(); break; @@ -293,7 +310,7 @@ bool PluginListComponent::isInterestedInFileDrag (const StringArray& /*files*/) void PluginListComponent::filesDropped (const StringArray& files, int, int) { - OwnedArray typesFound; + OwnedArray typesFound; list.scanAndAddDragAndDroppedFiles (formatManager, files, typesFound); } @@ -313,11 +330,11 @@ void PluginListComponent::setLastSearchPath (PropertiesFile& properties, AudioPl class PluginListComponent::Scanner : private Timer { public: - Scanner (PluginListComponent& plc, AudioPluginFormat& format, PropertiesFile* properties, int threads) + Scanner (PluginListComponent& plc, AudioPluginFormat& format, PropertiesFile* properties, + int threads, const String& title, const String& text) : owner (plc), formatToScan (format), propertiesToUse (properties), pathChooserWindow (TRANS("Select folders to scan..."), String::empty, AlertWindow::NoIcon), - progressWindow (TRANS("Scanning for plug-ins..."), - TRANS("Searching for all possible plug-in files..."), AlertWindow::NoIcon), + progressWindow (title, text, AlertWindow::NoIcon), progress (0.0), numThreads (threads), finished (false) { FileSearchPath path (formatToScan.getDefaultLocationsToSearch()); @@ -528,7 +545,9 @@ private: void PluginListComponent::scanFor (AudioPluginFormat& format) { - currentScanner = new Scanner (*this, format, propertiesToUse, numThreads); + currentScanner = new Scanner (*this, format, propertiesToUse, numThreads, + dialogTitle.isNotEmpty() ? dialogTitle : TRANS("Scanning for plug-ins..."), + dialogText.isNotEmpty() ? dialogText : TRANS("Searching for all possible plug-in files...")); } bool PluginListComponent::isScanning() const noexcept diff --git a/JuceLibraryCode/modules/juce_audio_processors/scanning/juce_PluginListComponent.h b/JuceLibraryCode/modules/juce_audio_processors/scanning/juce_PluginListComponent.h index 97751a8..a1d6f1d 100644 --- a/JuceLibraryCode/modules/juce_audio_processors/scanning/juce_PluginListComponent.h +++ b/JuceLibraryCode/modules/juce_audio_processors/scanning/juce_PluginListComponent.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -55,6 +55,10 @@ public: /** Changes the text in the panel's options button. */ void setOptionsButtonText (const String& newText); + /** Changes the text in the progress dialog box that is shown when scanning. */ + void setScanDialogText (const String& textForProgressWindowTitle, + const String& textForProgressWindowDescription); + /** Sets how many threads to simultaneously scan for plugins. If this is 0, then all scanning happens on the message thread (this is the default) */ @@ -72,6 +76,17 @@ public: /** Returns true if there's currently a scan in progress. */ bool isScanning() const noexcept; + /** Removes the plugins currently selected in the table. */ + void removeSelectedPlugins(); + + /** Sets a custom table model to be used. + This will take ownership of the model and delete it when no longer needed. + */ + void setTableModel (TableListBoxModel* model); + + /** Returns the table used to display the plugin list. */ + TableListBox& getTableListBox() noexcept { return table; } + private: //============================================================================== AudioPluginFormatManager& formatManager; @@ -80,12 +95,11 @@ private: TableListBox table; TextButton optionsButton; PropertiesFile* propertiesToUse; + String dialogTitle, dialogText; int numThreads; class TableModel; - friend class TableModel; - friend struct ContainerDeletePolicy; - ScopedPointer tableModel; + ScopedPointer tableModel; class Scanner; friend class Scanner; @@ -98,8 +112,8 @@ private: void updateList(); void showSelectedFolder(); bool canShowSelectedFolder() const; - void removeSelected(); void removeMissingPlugins(); + void removePluginItem (int index); void resized() override; bool isInterestedInFileDrag (const StringArray&) override; diff --git a/JuceLibraryCode/modules/juce_core/containers/juce_AbstractFifo.cpp b/JuceLibraryCode/modules/juce_core/containers/juce_AbstractFifo.cpp index 65b1615..d9db76c 100644 --- a/JuceLibraryCode/modules/juce_core/containers/juce_AbstractFifo.cpp +++ b/JuceLibraryCode/modules/juce_core/containers/juce_AbstractFifo.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this diff --git a/JuceLibraryCode/modules/juce_core/containers/juce_AbstractFifo.h b/JuceLibraryCode/modules/juce_core/containers/juce_AbstractFifo.h index 02feac7..251a8c2 100644 --- a/JuceLibraryCode/modules/juce_core/containers/juce_AbstractFifo.h +++ b/JuceLibraryCode/modules/juce_core/containers/juce_AbstractFifo.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this @@ -69,7 +69,7 @@ void readFromFifo (int* someData, int numItems) { int start1, size1, start2, size2; - abstractFifo.prepareToRead (numSamples, start1, size1, start2, size2); + abstractFifo.prepareToRead (numItems, start1, size1, start2, size2); if (size1 > 0) copySomeData (someData, myBuffer + start1, size1); diff --git a/JuceLibraryCode/modules/juce_core/containers/juce_Array.h b/JuceLibraryCode/modules/juce_core/containers/juce_Array.h index 375576a..c34b743 100644 --- a/JuceLibraryCode/modules/juce_core/containers/juce_Array.h +++ b/JuceLibraryCode/modules/juce_core/containers/juce_Array.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this @@ -65,8 +65,7 @@ private: public: //============================================================================== /** Creates an empty array. */ - Array() noexcept - : numUsed (0) + Array() noexcept : numUsed (0) { } @@ -97,8 +96,7 @@ public: @param values the array to copy from */ template - explicit Array (const TypeToCreateFrom* values) - : numUsed (0) + explicit Array (const TypeToCreateFrom* values) : numUsed (0) { while (*values != TypeToCreateFrom()) add (*values++); @@ -110,8 +108,7 @@ public: @param numValues the number of values in the array */ template - Array (const TypeToCreateFrom* values, int numValues) - : numUsed (numValues) + Array (const TypeToCreateFrom* values, int numValues) : numUsed (numValues) { data.setAllocatedSize (numValues); @@ -119,6 +116,14 @@ public: new (data.elements + i) ElementType (values[i]); } + #if JUCE_COMPILER_SUPPORTS_INITIALIZER_LISTS + template + Array (const std::initializer_list& items) : numUsed (0) + { + addArray (items); + } + #endif + /** Destructor. */ ~Array() { @@ -475,7 +480,11 @@ public: numUsed += numberOfTimesToInsertIt; while (--numberOfTimesToInsertIt >= 0) - new (insertPos++) ElementType (newElement); + { + new (insertPos) ElementType (newElement); + ++insertPos; // NB: this increment is done separately from the + // new statement to avoid a compiler bug in VS2014 + } } } @@ -601,6 +610,21 @@ public: } } + #if JUCE_COMPILER_SUPPORTS_INITIALIZER_LISTS + template + void addArray (const std::initializer_list& items) + { + const ScopedLockType lock (getLock()); + data.ensureAllocatedSize (numUsed + (int) items.size()); + + for (auto& item : items) + { + new (data.elements + numUsed) ElementType (item); + ++numUsed; + } + } + #endif + /** Adds elements from a null-terminated array of pointers to the end of this array. @param elementsToAdd an array of pointers to some kind of object from which elements @@ -808,8 +832,8 @@ public: /** Removes an item from the array. - This will remove the first occurrence of the given element from the array. - If the item isn't found, no action is taken. + This will remove all occurrences of the given element from the array. + If no such items are found, no action is taken. @param valueToRemove the object to try to remove @see remove, removeRange diff --git a/JuceLibraryCode/modules/juce_core/containers/juce_ArrayAllocationBase.h b/JuceLibraryCode/modules/juce_core/containers/juce_ArrayAllocationBase.h index cfbe464..1a673c9 100644 --- a/JuceLibraryCode/modules/juce_core/containers/juce_ArrayAllocationBase.h +++ b/JuceLibraryCode/modules/juce_core/containers/juce_ArrayAllocationBase.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this diff --git a/JuceLibraryCode/modules/juce_core/containers/juce_DynamicObject.cpp b/JuceLibraryCode/modules/juce_core/containers/juce_DynamicObject.cpp index 38f5c5f..5a4cae7 100644 --- a/JuceLibraryCode/modules/juce_core/containers/juce_DynamicObject.cpp +++ b/JuceLibraryCode/modules/juce_core/containers/juce_DynamicObject.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this @@ -45,7 +45,7 @@ bool DynamicObject::hasProperty (const Identifier& propertyName) const return v != nullptr && ! v->isMethod(); } -var DynamicObject::getProperty (const Identifier& propertyName) const +const var& DynamicObject::getProperty (const Identifier& propertyName) const { return properties [propertyName]; } diff --git a/JuceLibraryCode/modules/juce_core/containers/juce_DynamicObject.h b/JuceLibraryCode/modules/juce_core/containers/juce_DynamicObject.h index 5c624a4..0133676 100644 --- a/JuceLibraryCode/modules/juce_core/containers/juce_DynamicObject.h +++ b/JuceLibraryCode/modules/juce_core/containers/juce_DynamicObject.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this @@ -60,7 +60,7 @@ public: /** Returns a named property. This returns var::null if no such property exists. */ - virtual var getProperty (const Identifier& propertyName) const; + virtual const var& getProperty (const Identifier& propertyName) const; /** Sets a named property. */ virtual void setProperty (const Identifier& propertyName, const var& newValue); diff --git a/JuceLibraryCode/modules/juce_core/containers/juce_ElementComparator.h b/JuceLibraryCode/modules/juce_core/containers/juce_ElementComparator.h index 01dc5b7..41f63ca 100644 --- a/JuceLibraryCode/modules/juce_core/containers/juce_ElementComparator.h +++ b/JuceLibraryCode/modules/juce_core/containers/juce_ElementComparator.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this diff --git a/JuceLibraryCode/modules/juce_core/containers/juce_HashMap.h b/JuceLibraryCode/modules/juce_core/containers/juce_HashMap.h index 07d02b4..cadfdac 100644 --- a/JuceLibraryCode/modules/juce_core/containers/juce_HashMap.h +++ b/JuceLibraryCode/modules/juce_core/containers/juce_HashMap.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this diff --git a/JuceLibraryCode/modules/juce_core/containers/juce_LinkedListPointer.h b/JuceLibraryCode/modules/juce_core/containers/juce_LinkedListPointer.h index a27e521..53b89b5 100644 --- a/JuceLibraryCode/modules/juce_core/containers/juce_LinkedListPointer.h +++ b/JuceLibraryCode/modules/juce_core/containers/juce_LinkedListPointer.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this diff --git a/JuceLibraryCode/modules/juce_core/containers/juce_NamedValueSet.cpp b/JuceLibraryCode/modules/juce_core/containers/juce_NamedValueSet.cpp index c4e198d..68ba5f8 100644 --- a/JuceLibraryCode/modules/juce_core/containers/juce_NamedValueSet.cpp +++ b/JuceLibraryCode/modules/juce_core/containers/juce_NamedValueSet.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this @@ -29,7 +29,7 @@ struct NamedValueSet::NamedValue { NamedValue() noexcept {} - NamedValue (Identifier n, const var& v) : name (n), value (v) {} + NamedValue (const Identifier& n, const var& v) : name (n), value (v) {} NamedValue (const NamedValue& other) : name (other.name), value (other.value) {} #if JUCE_COMPILER_SUPPORTS_MOVE_SEMANTICS @@ -39,7 +39,9 @@ struct NamedValueSet::NamedValue { } - NamedValue (Identifier n, var&& v) : name (n), value (static_cast (v)) + NamedValue (Identifier&& n, var&& v) + : name (static_cast (n)), + value (static_cast (v)) { } @@ -88,9 +90,8 @@ NamedValueSet& NamedValueSet::operator= (NamedValueSet&& other) noexcept } #endif -NamedValueSet::~NamedValueSet() +NamedValueSet::~NamedValueSet() noexcept { - clear(); } void NamedValueSet::clear() @@ -113,7 +114,7 @@ int NamedValueSet::size() const noexcept return values.size(); } -const var& NamedValueSet::operator[] (const Identifier& name) const +const var& NamedValueSet::operator[] (const Identifier& name) const noexcept { if (const var* v = getVarPointer (name)) return *v; @@ -139,7 +140,7 @@ var* NamedValueSet::getVarPointer (const Identifier& name) const noexcept } #if JUCE_COMPILER_SUPPORTS_MOVE_SEMANTICS -bool NamedValueSet::set (Identifier name, var&& newValue) +bool NamedValueSet::set (const Identifier& name, var&& newValue) { if (var* const v = getVarPointer (name)) { @@ -155,7 +156,7 @@ bool NamedValueSet::set (Identifier name, var&& newValue) } #endif -bool NamedValueSet::set (Identifier name, const var& newValue) +bool NamedValueSet::set (const Identifier& name, const var& newValue) { if (var* const v = getVarPointer (name)) { @@ -170,7 +171,7 @@ bool NamedValueSet::set (Identifier name, const var& newValue) return true; } -bool NamedValueSet::contains (const Identifier& name) const +bool NamedValueSet::contains (const Identifier& name) const noexcept { return getVarPointer (name) != nullptr; } diff --git a/JuceLibraryCode/modules/juce_core/containers/juce_NamedValueSet.h b/JuceLibraryCode/modules/juce_core/containers/juce_NamedValueSet.h index 0216326..21b75b0 100644 --- a/JuceLibraryCode/modules/juce_core/containers/juce_NamedValueSet.h +++ b/JuceLibraryCode/modules/juce_core/containers/juce_NamedValueSet.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this @@ -54,7 +54,7 @@ public: #endif /** Destructor. */ - ~NamedValueSet(); + ~NamedValueSet() noexcept; bool operator== (const NamedValueSet&) const; bool operator!= (const NamedValueSet&) const; @@ -67,7 +67,7 @@ public: If the name isn't found, this will return a void variant. @see getProperty */ - const var& operator[] (const Identifier& name) const; + const var& operator[] (const Identifier& name) const noexcept; /** Tries to return the named value, but if no such value is found, this will instead return the supplied default value. @@ -78,18 +78,18 @@ public: @returns true if a value was changed or added; false if the value was already set the value passed-in. */ - bool set (Identifier name, const var& newValue); + bool set (const Identifier& name, const var& newValue); #if JUCE_COMPILER_SUPPORTS_MOVE_SEMANTICS /** Changes or adds a named value. @returns true if a value was changed or added; false if the value was already set the value passed-in. */ - bool set (Identifier name, var&& newValue); + bool set (const Identifier& name, var&& newValue); #endif /** Returns true if the set contains an item with the specified name. */ - bool contains (const Identifier& name) const; + bool contains (const Identifier& name) const noexcept; /** Removes a value from the set. @returns true if a value was removed; false if there was no value diff --git a/JuceLibraryCode/modules/juce_core/containers/juce_OwnedArray.h b/JuceLibraryCode/modules/juce_core/containers/juce_OwnedArray.h index a116df8..aa2f2fb 100644 --- a/JuceLibraryCode/modules/juce_core/containers/juce_OwnedArray.h +++ b/JuceLibraryCode/modules/juce_core/containers/juce_OwnedArray.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this @@ -830,7 +830,7 @@ public: This will use a comparator object to sort the elements into order. The object passed must have a method of the form: @code - int compareElements (ElementType first, ElementType second); + int compareElements (ElementType* first, ElementType* second); @endcode ..and this method must return: diff --git a/JuceLibraryCode/modules/juce_core/containers/juce_PropertySet.cpp b/JuceLibraryCode/modules/juce_core/containers/juce_PropertySet.cpp index 6b02baf..057ae87 100644 --- a/JuceLibraryCode/modules/juce_core/containers/juce_PropertySet.cpp +++ b/JuceLibraryCode/modules/juce_core/containers/juce_PropertySet.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this diff --git a/JuceLibraryCode/modules/juce_core/containers/juce_PropertySet.h b/JuceLibraryCode/modules/juce_core/containers/juce_PropertySet.h index 2a4ecb1..88284e6 100644 --- a/JuceLibraryCode/modules/juce_core/containers/juce_PropertySet.h +++ b/JuceLibraryCode/modules/juce_core/containers/juce_PropertySet.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this diff --git a/JuceLibraryCode/modules/juce_core/containers/juce_ReferenceCountedArray.h b/JuceLibraryCode/modules/juce_core/containers/juce_ReferenceCountedArray.h index 8de5ec9..12a8925 100644 --- a/JuceLibraryCode/modules/juce_core/containers/juce_ReferenceCountedArray.h +++ b/JuceLibraryCode/modules/juce_core/containers/juce_ReferenceCountedArray.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this @@ -38,7 +38,7 @@ The template parameter specifies the class of the object you want to point to - the easiest way to make a class reference-countable is to simply make it inherit from ReferenceCountedObject or SingleThreadedReferenceCountedObject, but if you need to, you can roll your own reference-countable - class by implementing a set of mathods called incReferenceCount(), decReferenceCount(), and + class by implementing a set of methods called incReferenceCount(), decReferenceCount(), and decReferenceCountWithoutDeleting(). See ReferenceCountedObject for examples of how these methods should behave. @@ -72,7 +72,7 @@ public: const ScopedLockType lock (other.getLock()); numUsed = other.size(); data.setAllocatedSize (numUsed); - memcpy (data.elements, other.getRawDataPointer(), numUsed * sizeof (ObjectClass*)); + memcpy (data.elements, other.getRawDataPointer(), (size_t) numUsed * sizeof (ObjectClass*)); for (int i = numUsed; --i >= 0;) if (ObjectClass* o = data.elements[i]) @@ -119,26 +119,30 @@ public: */ ~ReferenceCountedArray() { - clear(); + releaseAllObjects(); } //============================================================================== /** Removes all objects from the array. - - Any objects in the array that are not referenced from elsewhere will be deleted. + Any objects in the array that whose reference counts drop to zero will be deleted. */ void clear() { const ScopedLockType lock (getLock()); - - while (numUsed > 0) - if (ObjectClass* o = data.elements [--numUsed]) - releaseObject (o); - - jassert (numUsed == 0); + releaseAllObjects(); data.setAllocatedSize (0); } + /** Removes all objects from the array without freeing the array's allocated storage. + Any objects in the array that whose reference counts drop to zero will be deleted. + @see clear + */ + void clearQuick() + { + const ScopedLockType lock (getLock()); + releaseAllObjects(); + } + /** Returns the current number of objects in the array. */ inline int size() const noexcept { @@ -886,6 +890,15 @@ private: ArrayAllocationBase data; int numUsed; + void releaseAllObjects() + { + while (numUsed > 0) + if (ObjectClass* o = data.elements [--numUsed]) + releaseObject (o); + + jassert (numUsed == 0); + } + static void releaseObject (ObjectClass* o) { if (o->decReferenceCountWithoutDeleting()) diff --git a/JuceLibraryCode/modules/juce_core/containers/juce_ScopedValueSetter.h b/JuceLibraryCode/modules/juce_core/containers/juce_ScopedValueSetter.h index 13b871e..840ca91 100644 --- a/JuceLibraryCode/modules/juce_core/containers/juce_ScopedValueSetter.h +++ b/JuceLibraryCode/modules/juce_core/containers/juce_ScopedValueSetter.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this diff --git a/JuceLibraryCode/modules/juce_core/containers/juce_SortedSet.h b/JuceLibraryCode/modules/juce_core/containers/juce_SortedSet.h index 62fd923..90a2396 100644 --- a/JuceLibraryCode/modules/juce_core/containers/juce_SortedSet.h +++ b/JuceLibraryCode/modules/juce_core/containers/juce_SortedSet.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this diff --git a/JuceLibraryCode/modules/juce_core/containers/juce_SparseSet.h b/JuceLibraryCode/modules/juce_core/containers/juce_SparseSet.h index 86366fc..573975a 100644 --- a/JuceLibraryCode/modules/juce_core/containers/juce_SparseSet.h +++ b/JuceLibraryCode/modules/juce_core/containers/juce_SparseSet.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this diff --git a/JuceLibraryCode/modules/juce_core/containers/juce_Variant.cpp b/JuceLibraryCode/modules/juce_core/containers/juce_Variant.cpp index db3f2f5..849bd8f 100644 --- a/JuceLibraryCode/modules/juce_core/containers/juce_Variant.cpp +++ b/JuceLibraryCode/modules/juce_core/containers/juce_Variant.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this @@ -174,7 +174,7 @@ public: int toInt (const ValueUnion& data) const noexcept override { return (int) data.doubleValue; }; int64 toInt64 (const ValueUnion& data) const noexcept override { return (int64) data.doubleValue; }; double toDouble (const ValueUnion& data) const noexcept override { return data.doubleValue; } - String toString (const ValueUnion& data) const override { return String (data.doubleValue); } + String toString (const ValueUnion& data) const override { return String (data.doubleValue, 20); } bool toBool (const ValueUnion& data) const noexcept override { return data.doubleValue != 0; } bool isDouble() const noexcept override { return true; } @@ -253,8 +253,8 @@ public: } private: - static inline const String* getString (const ValueUnion& data) noexcept { return reinterpret_cast (data.stringValue); } - static inline String* getString (ValueUnion& data) noexcept { return reinterpret_cast (data.stringValue); } + static inline const String* getString (const ValueUnion& data) noexcept { return reinterpret_cast (data.stringValue); } + static inline String* getString (ValueUnion& data) noexcept { return reinterpret_cast (data.stringValue); } }; //============================================================================== @@ -487,7 +487,7 @@ var::operator String() const { return type->toString ReferenceCountedObject* var::getObject() const noexcept { return type->toObject (value); } Array* var::getArray() const noexcept { return type->toArray (value); } MemoryBlock* var::getBinaryData() const noexcept { return type->toBinary (value); } -DynamicObject* var::getDynamicObject() const noexcept { return dynamic_cast (getObject()); } +DynamicObject* var::getDynamicObject() const noexcept { return dynamic_cast (getObject()); } //============================================================================== void var::swapWith (var& other) noexcept @@ -576,20 +576,20 @@ var var::clone() const noexcept } //============================================================================== -var var::operator[] (const Identifier propertyName) const +const var& var::operator[] (const Identifier& propertyName) const { if (DynamicObject* const o = getDynamicObject()) return o->getProperty (propertyName); - return var(); + return var::null; } -var var::operator[] (const char* const propertyName) const +const var& var::operator[] (const char* const propertyName) const { return operator[] (Identifier (propertyName)); } -var var::getProperty (const Identifier propertyName, const var& defaultReturnValue) const +var var::getProperty (const Identifier& propertyName, const var& defaultReturnValue) const { if (DynamicObject* const o = getDynamicObject()) return o->getProperties().getWithDefault (propertyName, defaultReturnValue); @@ -602,7 +602,7 @@ var::NativeFunction var::getNativeFunction() const return isMethod() ? value.methodValue : nullptr; } -var var::invoke (Identifier method, const var* arguments, int numArguments) const +var var::invoke (const Identifier& method, const var* arguments, int numArguments) const { if (DynamicObject* const o = getDynamicObject()) return o->invokeMethod (method, var::NativeFunctionArgs (*this, arguments, numArguments)); @@ -610,35 +610,35 @@ var var::invoke (Identifier method, const var* arguments, int numArguments) cons return var(); } -var var::call (const Identifier method) const +var var::call (const Identifier& method) const { return invoke (method, nullptr, 0); } -var var::call (const Identifier method, const var& arg1) const +var var::call (const Identifier& method, const var& arg1) const { return invoke (method, &arg1, 1); } -var var::call (const Identifier method, const var& arg1, const var& arg2) const +var var::call (const Identifier& method, const var& arg1, const var& arg2) const { var args[] = { arg1, arg2 }; return invoke (method, args, 2); } -var var::call (const Identifier method, const var& arg1, const var& arg2, const var& arg3) +var var::call (const Identifier& method, const var& arg1, const var& arg2, const var& arg3) { var args[] = { arg1, arg2, arg3 }; return invoke (method, args, 3); } -var var::call (const Identifier method, const var& arg1, const var& arg2, const var& arg3, const var& arg4) const +var var::call (const Identifier& method, const var& arg1, const var& arg2, const var& arg3, const var& arg4) const { var args[] = { arg1, arg2, arg3, arg4 }; return invoke (method, args, 4); } -var var::call (const Identifier method, const var& arg1, const var& arg2, const var& arg3, const var& arg4, const var& arg5) const +var var::call (const Identifier& method, const var& arg1, const var& arg2, const var& arg3, const var& arg4, const var& arg5) const { var args[] = { arg1, arg2, arg3, arg4, arg5 }; return invoke (method, args, 5); diff --git a/JuceLibraryCode/modules/juce_core/containers/juce_Variant.h b/JuceLibraryCode/modules/juce_core/containers/juce_Variant.h index 41a4884..25d0dcd 100644 --- a/JuceLibraryCode/modules/juce_core/containers/juce_Variant.h +++ b/JuceLibraryCode/modules/juce_core/containers/juce_Variant.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this @@ -62,7 +62,6 @@ public: }; typedef var (*NativeFunction) (const NativeFunctionArgs&); - typedef Identifier identifier; //============================================================================== /** Creates a void variant. */ @@ -242,27 +241,27 @@ public: //============================================================================== /** If this variant is an object, this returns one of its properties. */ - var operator[] (Identifier propertyName) const; + const var& operator[] (const Identifier& propertyName) const; /** If this variant is an object, this returns one of its properties. */ - var operator[] (const char* propertyName) const; + const var& operator[] (const char* propertyName) const; /** If this variant is an object, this returns one of its properties, or a default fallback value if the property is not set. */ - var getProperty (Identifier propertyName, const var& defaultReturnValue) const; + var getProperty (const Identifier& propertyName, const var& defaultReturnValue) const; /** Invokes a named method call with no arguments. */ - var call (Identifier method) const; + var call (const Identifier& method) const; /** Invokes a named method call with one argument. */ - var call (Identifier method, const var& arg1) const; + var call (const Identifier& method, const var& arg1) const; /** Invokes a named method call with 2 arguments. */ - var call (Identifier method, const var& arg1, const var& arg2) const; + var call (const Identifier& method, const var& arg1, const var& arg2) const; /** Invokes a named method call with 3 arguments. */ - var call (Identifier method, const var& arg1, const var& arg2, const var& arg3); + var call (const Identifier& method, const var& arg1, const var& arg2, const var& arg3); /** Invokes a named method call with 4 arguments. */ - var call (Identifier method, const var& arg1, const var& arg2, const var& arg3, const var& arg4) const; + var call (const Identifier& method, const var& arg1, const var& arg2, const var& arg3, const var& arg4) const; /** Invokes a named method call with 5 arguments. */ - var call (Identifier method, const var& arg1, const var& arg2, const var& arg3, const var& arg4, const var& arg5) const; + var call (const Identifier& method, const var& arg1, const var& arg2, const var& arg3, const var& arg4, const var& arg5) const; /** Invokes a named method call with a list of arguments. */ - var invoke (Identifier method, const var* arguments, int numArguments) const; + var invoke (const Identifier& method, const var* arguments, int numArguments) const; /** If this object is a method, this returns the function pointer. */ NativeFunction getNativeFunction() const; diff --git a/JuceLibraryCode/modules/juce_core/files/juce_DirectoryIterator.cpp b/JuceLibraryCode/modules/juce_core/files/juce_DirectoryIterator.cpp index 7d6dd4b..76b503b 100644 --- a/JuceLibraryCode/modules/juce_core/files/juce_DirectoryIterator.cpp +++ b/JuceLibraryCode/modules/juce_core/files/juce_DirectoryIterator.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this @@ -73,64 +73,71 @@ bool DirectoryIterator::next() bool DirectoryIterator::next (bool* const isDirResult, bool* const isHiddenResult, int64* const fileSize, Time* const modTime, Time* const creationTime, bool* const isReadOnly) { - hasBeenAdvanced = true; - - if (subIterator != nullptr) + for (;;) { - if (subIterator->next (isDirResult, isHiddenResult, fileSize, modTime, creationTime, isReadOnly)) - return true; + hasBeenAdvanced = true; - subIterator = nullptr; - } - - String filename; - bool isDirectory, isHidden = false; - - while (fileFinder.next (filename, &isDirectory, - (isHiddenResult != nullptr || (whatToLookFor & File::ignoreHiddenFiles) != 0) ? &isHidden : nullptr, - fileSize, modTime, creationTime, isReadOnly)) - { - ++index; - - if (! filename.containsOnly (".")) + if (subIterator != nullptr) { - bool matches = false; - - if (isDirectory) - { - if (isRecursive && ((whatToLookFor & File::ignoreHiddenFiles) == 0 || ! isHidden)) - subIterator = new DirectoryIterator (File::createFileWithoutCheckingPath (path + filename), - true, wildCard, whatToLookFor); - - matches = (whatToLookFor & File::findDirectories) != 0; - } - else - { - matches = (whatToLookFor & File::findFiles) != 0; - } - - // if we're not relying on the OS iterator to do the wildcard match, do it now.. - if (matches && (isRecursive || wildCards.size() > 1)) - matches = fileMatches (wildCards, filename); - - if (matches && (whatToLookFor & File::ignoreHiddenFiles) != 0) - matches = ! isHidden; - - if (matches) - { - currentFile = File::createFileWithoutCheckingPath (path + filename); - if (isHiddenResult != nullptr) *isHiddenResult = isHidden; - if (isDirResult != nullptr) *isDirResult = isDirectory; - + if (subIterator->next (isDirResult, isHiddenResult, fileSize, modTime, creationTime, isReadOnly)) return true; - } - if (subIterator != nullptr) - return next (isDirResult, isHiddenResult, fileSize, modTime, creationTime, isReadOnly); + subIterator = nullptr; } - } - return false; + String filename; + bool isDirectory, isHidden = false, shouldContinue = false; + + while (fileFinder.next (filename, &isDirectory, + (isHiddenResult != nullptr || (whatToLookFor & File::ignoreHiddenFiles) != 0) ? &isHidden : nullptr, + fileSize, modTime, creationTime, isReadOnly)) + { + ++index; + + if (! filename.containsOnly (".")) + { + bool matches = false; + + if (isDirectory) + { + if (isRecursive && ((whatToLookFor & File::ignoreHiddenFiles) == 0 || ! isHidden)) + subIterator = new DirectoryIterator (File::createFileWithoutCheckingPath (path + filename), + true, wildCard, whatToLookFor); + + matches = (whatToLookFor & File::findDirectories) != 0; + } + else + { + matches = (whatToLookFor & File::findFiles) != 0; + } + + // if we're not relying on the OS iterator to do the wildcard match, do it now.. + if (matches && (isRecursive || wildCards.size() > 1)) + matches = fileMatches (wildCards, filename); + + if (matches && (whatToLookFor & File::ignoreHiddenFiles) != 0) + matches = ! isHidden; + + if (matches) + { + currentFile = File::createFileWithoutCheckingPath (path + filename); + if (isHiddenResult != nullptr) *isHiddenResult = isHidden; + if (isDirResult != nullptr) *isDirResult = isDirectory; + + return true; + } + + if (subIterator != nullptr) + { + shouldContinue = true; + break; + } + } + } + + if (! shouldContinue) + return false; + } } const File& DirectoryIterator::getFile() const diff --git a/JuceLibraryCode/modules/juce_core/files/juce_DirectoryIterator.h b/JuceLibraryCode/modules/juce_core/files/juce_DirectoryIterator.h index 3ca2265..bd71697 100644 --- a/JuceLibraryCode/modules/juce_core/files/juce_DirectoryIterator.h +++ b/JuceLibraryCode/modules/juce_core/files/juce_DirectoryIterator.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this diff --git a/JuceLibraryCode/modules/juce_core/files/juce_File.cpp b/JuceLibraryCode/modules/juce_core/files/juce_File.cpp index 695d48e..1b4687e 100644 --- a/JuceLibraryCode/modules/juce_core/files/juce_File.cpp +++ b/JuceLibraryCode/modules/juce_core/files/juce_File.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this @@ -219,6 +219,11 @@ bool File::setReadOnly (const bool shouldBeReadOnly, return setFileReadOnlyInternal (shouldBeReadOnly) && worked; } +bool File::setExecutePermission (bool shouldBeExecutable) const +{ + return setFileExecutableInternal (shouldBeExecutable); +} + bool File::deleteRecursively() const { bool worked = true; @@ -476,7 +481,7 @@ bool File::loadFileAsData (MemoryBlock& destBlock) const return false; FileInputStream in (*this); - return in.openedOk() && getSize() == in.readIntoMemoryBlock (destBlock); + return in.openedOk() && getSize() == (int64) in.readIntoMemoryBlock (destBlock); } String File::loadFileAsString() const @@ -911,6 +916,11 @@ public: const File temp (File::getSpecialLocation (File::tempDirectory)); expect (! File::nonexistent.exists()); + expect (! File::nonexistent.existsAsFile()); + expect (! File::nonexistent.isDirectory()); + #if ! JUCE_WINDOWS + expect (File("/").isDirectory()); + #endif expect (home.isDirectory()); expect (home.exists()); expect (! home.existsAsFile()); diff --git a/JuceLibraryCode/modules/juce_core/files/juce_File.h b/JuceLibraryCode/modules/juce_core/files/juce_File.h index 28c2e70..8a28d51 100644 --- a/JuceLibraryCode/modules/juce_core/files/juce_File.h +++ b/JuceLibraryCode/modules/juce_core/files/juce_File.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this @@ -348,6 +348,13 @@ public: bool setReadOnly (bool shouldBeReadOnly, bool applyRecursively = false) const; + /** Changes the execute-permissions of a file. + + @param shouldBeExecutable whether to add or remove execute-permission + @returns true if it manages to change the file's permissions. + */ + bool setExecutePermission (bool shouldBeExecutable) const; + /** Returns true if this file is a hidden or system file. The criteria for deciding whether a file is hidden are platform-dependent. */ @@ -486,6 +493,9 @@ public: Note that the destination file isn't the directory to put it in, it's the actual filename that you want the new file to have. + Also note that on some OSes (e.g. Windows), moving files between different + volumes may not be possible. + @returns true if the operation succeeds */ bool moveFileTo (const File& targetLocation) const; @@ -844,6 +854,11 @@ public: /** In a plugin, this will return the path of the host executable. */ hostApplicationPath, + #if JUCE_WINDOWS + /** On a Windows machine, returns the location of the Windows/System32 folder. */ + windowsSystemDirectory, + #endif + /** The directory in which applications normally get installed. So on windows, this would be something like "c:\program files", on the Mac "/Applications", or "/usr" on linux. @@ -963,6 +978,7 @@ private: bool setFileTimesInternal (int64 m, int64 a, int64 c) const; void getFileTimesInternal (int64& m, int64& a, int64& c) const; bool setFileReadOnlyInternal (bool) const; + bool setFileExecutableInternal (bool) const; }; #endif // JUCE_FILE_H_INCLUDED diff --git a/JuceLibraryCode/modules/juce_core/files/juce_FileFilter.cpp b/JuceLibraryCode/modules/juce_core/files/juce_FileFilter.cpp index bd0bdf8..118c321 100644 --- a/JuceLibraryCode/modules/juce_core/files/juce_FileFilter.cpp +++ b/JuceLibraryCode/modules/juce_core/files/juce_FileFilter.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this diff --git a/JuceLibraryCode/modules/juce_core/files/juce_FileFilter.h b/JuceLibraryCode/modules/juce_core/files/juce_FileFilter.h index 4c02415..9dae801 100644 --- a/JuceLibraryCode/modules/juce_core/files/juce_FileFilter.h +++ b/JuceLibraryCode/modules/juce_core/files/juce_FileFilter.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this diff --git a/JuceLibraryCode/modules/juce_core/files/juce_FileInputStream.cpp b/JuceLibraryCode/modules/juce_core/files/juce_FileInputStream.cpp index 801ccfa..c6ed3d6 100644 --- a/JuceLibraryCode/modules/juce_core/files/juce_FileInputStream.cpp +++ b/JuceLibraryCode/modules/juce_core/files/juce_FileInputStream.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this @@ -57,7 +57,7 @@ int FileInputStream::read (void* buffer, int bytesToRead) jassert (buffer != nullptr && bytesToRead >= 0); const size_t num = readInternal (buffer, (size_t) bytesToRead); - currentPosition += num; + currentPosition += (int64) num; return (int) num; } diff --git a/JuceLibraryCode/modules/juce_core/files/juce_FileInputStream.h b/JuceLibraryCode/modules/juce_core/files/juce_FileInputStream.h index 35963ba..7c31568 100644 --- a/JuceLibraryCode/modules/juce_core/files/juce_FileInputStream.h +++ b/JuceLibraryCode/modules/juce_core/files/juce_FileInputStream.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this diff --git a/JuceLibraryCode/modules/juce_core/files/juce_FileOutputStream.cpp b/JuceLibraryCode/modules/juce_core/files/juce_FileOutputStream.cpp index 961a8d1..d5c25e7 100644 --- a/JuceLibraryCode/modules/juce_core/files/juce_FileOutputStream.cpp +++ b/JuceLibraryCode/modules/juce_core/files/juce_FileOutputStream.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this @@ -90,7 +90,7 @@ bool FileOutputStream::write (const void* const src, const size_t numBytes) { memcpy (buffer + bytesInBuffer, src, numBytes); bytesInBuffer += numBytes; - currentPosition += numBytes; + currentPosition += (int64) numBytes; } else { @@ -101,7 +101,7 @@ bool FileOutputStream::write (const void* const src, const size_t numBytes) { memcpy (buffer + bytesInBuffer, src, numBytes); bytesInBuffer += numBytes; - currentPosition += numBytes; + currentPosition += (int64) numBytes; } else { @@ -110,7 +110,7 @@ bool FileOutputStream::write (const void* const src, const size_t numBytes) if (bytesWritten < 0) return false; - currentPosition += bytesWritten; + currentPosition += (int64) bytesWritten; return bytesWritten == (ssize_t) numBytes; } } @@ -126,7 +126,7 @@ bool FileOutputStream::writeRepeatedByte (uint8 byte, size_t numBytes) { memset (buffer + bytesInBuffer, byte, numBytes); bytesInBuffer += numBytes; - currentPosition += numBytes; + currentPosition += (int64) numBytes; return true; } diff --git a/JuceLibraryCode/modules/juce_core/files/juce_FileOutputStream.h b/JuceLibraryCode/modules/juce_core/files/juce_FileOutputStream.h index f80705f..7d1520c 100644 --- a/JuceLibraryCode/modules/juce_core/files/juce_FileOutputStream.h +++ b/JuceLibraryCode/modules/juce_core/files/juce_FileOutputStream.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this diff --git a/JuceLibraryCode/modules/juce_core/files/juce_FileSearchPath.cpp b/JuceLibraryCode/modules/juce_core/files/juce_FileSearchPath.cpp index ce0af7e..5531c62 100644 --- a/JuceLibraryCode/modules/juce_core/files/juce_FileSearchPath.cpp +++ b/JuceLibraryCode/modules/juce_core/files/juce_FileSearchPath.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this diff --git a/JuceLibraryCode/modules/juce_core/files/juce_FileSearchPath.h b/JuceLibraryCode/modules/juce_core/files/juce_FileSearchPath.h index 51baf2e..3744a49 100644 --- a/JuceLibraryCode/modules/juce_core/files/juce_FileSearchPath.h +++ b/JuceLibraryCode/modules/juce_core/files/juce_FileSearchPath.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this diff --git a/JuceLibraryCode/modules/juce_core/files/juce_MemoryMappedFile.h b/JuceLibraryCode/modules/juce_core/files/juce_MemoryMappedFile.h index 8a79185..48e0eb6 100644 --- a/JuceLibraryCode/modules/juce_core/files/juce_MemoryMappedFile.h +++ b/JuceLibraryCode/modules/juce_core/files/juce_MemoryMappedFile.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this diff --git a/JuceLibraryCode/modules/juce_core/files/juce_TemporaryFile.cpp b/JuceLibraryCode/modules/juce_core/files/juce_TemporaryFile.cpp index 50475d5..acb1af0 100644 --- a/JuceLibraryCode/modules/juce_core/files/juce_TemporaryFile.cpp +++ b/JuceLibraryCode/modules/juce_core/files/juce_TemporaryFile.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this diff --git a/JuceLibraryCode/modules/juce_core/files/juce_TemporaryFile.h b/JuceLibraryCode/modules/juce_core/files/juce_TemporaryFile.h index 04561a7..0aad9c9 100644 --- a/JuceLibraryCode/modules/juce_core/files/juce_TemporaryFile.h +++ b/JuceLibraryCode/modules/juce_core/files/juce_TemporaryFile.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this diff --git a/JuceLibraryCode/modules/juce_core/files/juce_WildcardFileFilter.cpp b/JuceLibraryCode/modules/juce_core/files/juce_WildcardFileFilter.cpp index 1fef455..8e51da7 100644 --- a/JuceLibraryCode/modules/juce_core/files/juce_WildcardFileFilter.cpp +++ b/JuceLibraryCode/modules/juce_core/files/juce_WildcardFileFilter.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this @@ -26,32 +26,7 @@ ============================================================================== */ -WildcardFileFilter::WildcardFileFilter (const String& fileWildcardPatterns, - const String& directoryWildcardPatterns, - const String& desc) - : FileFilter (desc.isEmpty() ? fileWildcardPatterns - : (desc + " (" + fileWildcardPatterns + ")")) -{ - parse (fileWildcardPatterns, fileWildcards); - parse (directoryWildcardPatterns, directoryWildcards); -} - -WildcardFileFilter::~WildcardFileFilter() -{ -} - -bool WildcardFileFilter::isFileSuitable (const File& file) const -{ - return match (file, fileWildcards); -} - -bool WildcardFileFilter::isDirectorySuitable (const File& file) const -{ - return match (file, directoryWildcards); -} - -//============================================================================== -void WildcardFileFilter::parse (const String& pattern, StringArray& result) +static void parseWildcard (const String& pattern, StringArray& result) { result.addTokens (pattern.toLowerCase(), ";,", "\"'"); @@ -65,7 +40,7 @@ void WildcardFileFilter::parse (const String& pattern, StringArray& result) result.set (i, "*"); } -bool WildcardFileFilter::match (const File& file, const StringArray& wildcards) +static bool matchWildcard (const File& file, const StringArray& wildcards) { const String filename (file.getFileName()); @@ -75,3 +50,27 @@ bool WildcardFileFilter::match (const File& file, const StringArray& wildcards) return false; } + +WildcardFileFilter::WildcardFileFilter (const String& fileWildcardPatterns, + const String& directoryWildcardPatterns, + const String& desc) + : FileFilter (desc.isEmpty() ? fileWildcardPatterns + : (desc + " (" + fileWildcardPatterns + ")")) +{ + parseWildcard (fileWildcardPatterns, fileWildcards); + parseWildcard (directoryWildcardPatterns, directoryWildcards); +} + +WildcardFileFilter::~WildcardFileFilter() +{ +} + +bool WildcardFileFilter::isFileSuitable (const File& file) const +{ + return matchWildcard (file, fileWildcards); +} + +bool WildcardFileFilter::isDirectorySuitable (const File& file) const +{ + return matchWildcard (file, directoryWildcards); +} diff --git a/JuceLibraryCode/modules/juce_core/files/juce_WildcardFileFilter.h b/JuceLibraryCode/modules/juce_core/files/juce_WildcardFileFilter.h index 166ae4a..af9a757 100644 --- a/JuceLibraryCode/modules/juce_core/files/juce_WildcardFileFilter.h +++ b/JuceLibraryCode/modules/juce_core/files/juce_WildcardFileFilter.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this @@ -75,12 +75,8 @@ private: //============================================================================== StringArray fileWildcards, directoryWildcards; - static void parse (const String& pattern, StringArray& result); - static bool match (const File& file, const StringArray& wildcards); - JUCE_LEAK_DETECTOR (WildcardFileFilter) }; - #endif // JUCE_WILDCARDFILEFILTER_H_INCLUDED diff --git a/JuceLibraryCode/modules/juce_core/javascript/juce_JSON.cpp b/JuceLibraryCode/modules/juce_core/javascript/juce_JSON.cpp index 5a0f7f7..9dbd415 100644 --- a/JuceLibraryCode/modules/juce_core/javascript/juce_JSON.cpp +++ b/JuceLibraryCode/modules/juce_core/javascript/juce_JSON.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this @@ -579,7 +579,7 @@ public: case 1: return r.nextInt(); case 2: return r.nextInt64(); case 3: return r.nextBool(); - case 4: return r.nextDouble(); + case 4: return String (r.nextDouble(), 8).getDoubleValue(); case 5: return createRandomWideCharString (r); case 6: diff --git a/JuceLibraryCode/modules/juce_core/javascript/juce_JSON.h b/JuceLibraryCode/modules/juce_core/javascript/juce_JSON.h index 7fb17ee..31a2ff5 100644 --- a/JuceLibraryCode/modules/juce_core/javascript/juce_JSON.h +++ b/JuceLibraryCode/modules/juce_core/javascript/juce_JSON.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this diff --git a/JuceLibraryCode/modules/juce_core/javascript/juce_Javascript.cpp b/JuceLibraryCode/modules/juce_core/javascript/juce_Javascript.cpp index 16641d6..761cbbe 100644 --- a/JuceLibraryCode/modules/juce_core/javascript/juce_Javascript.cpp +++ b/JuceLibraryCode/modules/juce_core/javascript/juce_Javascript.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this @@ -102,6 +102,7 @@ struct JavascriptEngine::RootObject : public DynamicObject static bool isNumericOrUndefined (const var& v) { return v.isInt() || v.isDouble() || v.isInt64() || v.isBool() || v.isUndefined(); } static int64 getOctalValue (const String& s) { BigInteger b; b.parseString (s, 8); return b.toInt64(); } static Identifier getPrototypeIdentifier() { static const Identifier i ("prototype"); return i; } + static var* getPropertyPointer (DynamicObject* o, const Identifier& i) { return o->getProperties().getVarPointer (i); } //============================================================================== struct CodeLocation @@ -135,19 +136,23 @@ struct JavascriptEngine::RootObject : public DynamicObject ReferenceCountedObjectPtr root; DynamicObject::Ptr scope; - var findFunctionCall (const CodeLocation& location, const var& targetObject, Identifier functionName) const + var findFunctionCall (const CodeLocation& location, const var& targetObject, const Identifier& functionName) const { if (DynamicObject* o = targetObject.getDynamicObject()) { - if (var* prop = o->getProperties().getVarPointer (functionName)) + if (const var* prop = getPropertyPointer (o, functionName)) return *prop; for (DynamicObject* p = o->getProperty (getPrototypeIdentifier()).getDynamicObject(); p != nullptr; p = p->getProperty (getPrototypeIdentifier()).getDynamicObject()) { - if (var* prop = p->getProperties().getVarPointer (functionName)) + if (const var* prop = getPropertyPointer (p, functionName)) return *prop; } + + // if there's a class with an overridden DynamicObject::hasMethod, this avoids an error + if (o->hasMethod (functionName)) + return var(); } if (targetObject.isString()) @@ -165,32 +170,30 @@ struct JavascriptEngine::RootObject : public DynamicObject return var(); } - var* findRootClassProperty (Identifier className, Identifier propName) const + var* findRootClassProperty (const Identifier& className, const Identifier& propName) const { if (DynamicObject* cls = root->getProperty (className).getDynamicObject()) - return cls->getProperties().getVarPointer (propName); + return getPropertyPointer (cls, propName); return nullptr; } - var findSymbolInParentScopes (Identifier name) const + var findSymbolInParentScopes (const Identifier& name) const { - if (var* v = scope->getProperties().getVarPointer (name)) + if (const var* v = getPropertyPointer (scope, name)) return *v; return parent != nullptr ? parent->findSymbolInParentScopes (name) : var::undefined(); } - bool findAndInvokeMethod (Identifier function, const var::NativeFunctionArgs& args, var& result) const + bool findAndInvokeMethod (const Identifier& function, const var::NativeFunctionArgs& args, var& result) const { - const NamedValueSet& props = scope->getProperties(); - DynamicObject* target = args.thisObject.getDynamicObject(); if (target == nullptr || target == scope) { - if (const var* m = props.getVarPointer (function)) + if (const var* m = getPropertyPointer (scope, function)) { if (FunctionObject* fo = dynamic_cast (m->getObject())) { @@ -200,6 +203,8 @@ struct JavascriptEngine::RootObject : public DynamicObject } } + const NamedValueSet& props = scope->getProperties(); + for (int i = 0; i < props.size(); ++i) if (DynamicObject* o = props.getValueAt (i).getDynamicObject()) if (Scope (this, root, o).findAndInvokeMethod (function, args, result)) @@ -347,13 +352,13 @@ struct JavascriptEngine::RootObject : public DynamicObject struct UnqualifiedName : public Expression { - UnqualifiedName (const CodeLocation& l, Identifier n) noexcept : Expression (l), name (n) {} + UnqualifiedName (const CodeLocation& l, const Identifier& n) noexcept : Expression (l), name (n) {} var getResult (const Scope& s) const override { return s.findSymbolInParentScopes (name); } void assign (const Scope& s, const var& newValue) const override { - if (var* v = s.scope->getProperties().getVarPointer (name)) + if (var* v = getPropertyPointer (s.scope, name)) *v = newValue; else s.root->setProperty (name, newValue); @@ -364,7 +369,7 @@ struct JavascriptEngine::RootObject : public DynamicObject struct DotOperator : public Expression { - DotOperator (const CodeLocation& l, ExpPtr& p, Identifier c) noexcept : Expression (l), parent (p), child (c) {} + DotOperator (const CodeLocation& l, ExpPtr& p, const Identifier& c) noexcept : Expression (l), parent (p), child (c) {} var getResult (const Scope& s) const override { @@ -378,7 +383,7 @@ struct JavascriptEngine::RootObject : public DynamicObject } if (DynamicObject* o = p.getDynamicObject()) - if (var* v = o->getProperties().getVarPointer (child)) + if (const var* v = getPropertyPointer (o, child)) return *v; return var::undefined(); @@ -543,14 +548,14 @@ struct JavascriptEngine::RootObject : public DynamicObject struct DivideOp : public BinaryOperator { DivideOp (const CodeLocation& l, ExpPtr& a, ExpPtr& b) noexcept : BinaryOperator (l, a, b, TokenTypes::divide) {} - var getWithDoubles (double a, double b) const override { return a / b; } - var getWithInts (int64 a, int64 b) const override { return a / b; } + var getWithDoubles (double a, double b) const override { return b != 0 ? a / b : std::numeric_limits::infinity(); } + var getWithInts (int64 a, int64 b) const override { return b != 0 ? var (a / (double) b) : var (std::numeric_limits::infinity()); } }; struct ModuloOp : public BinaryOperator { ModuloOp (const CodeLocation& l, ExpPtr& a, ExpPtr& b) noexcept : BinaryOperator (l, a, b, TokenTypes::modulo) {} - var getWithInts (int64 a, int64 b) const override { return a % b; } + var getWithInts (int64 a, int64 b) const override { return b != 0 ? var (a % b) : var (std::numeric_limits::infinity()); } }; struct BitwiseOrOp : public BinaryOperator @@ -698,6 +703,11 @@ struct JavascriptEngine::RootObject : public DynamicObject if (FunctionObject* fo = dynamic_cast (function.getObject())) return fo->invoke (s, args); + if (DotOperator* dot = dynamic_cast (object.get())) + if (DynamicObject* o = thisObject.getDynamicObject()) + if (o->hasMethod (dot->child)) // allow an overridden DynamicObject::invokeMethod to accept a method call. + return o->invokeMethod (dot->child, args); + location.throwError ("This expression is not a function!"); return var(); } @@ -843,7 +853,7 @@ struct JavascriptEngine::RootObject : public DynamicObject String::CharPointerType end (p); while (isIdentifierBody (*++end)) {} - const size_t len = end - p; + const size_t len = (size_t) (end - p); #define JUCE_JS_COMPARE_KEYWORD(name, str) if (len == sizeof (str) - 1 && matchToken (TokenTypes::name, len)) return TokenTypes::name; JUCE_JS_KEYWORDS (JUCE_JS_COMPARE_KEYWORD) @@ -1145,8 +1155,14 @@ struct JavascriptEngine::RootObject : public DynamicObject match (TokenTypes::semicolon); } - s->iterator = parseExpression(); - match (TokenTypes::closeParen); + if (matchIf (TokenTypes::closeParen)) + s->iterator = new Statement (location); + else + { + s->iterator = parseExpression(); + match (TokenTypes::closeParen); + } + s->body = parseStatement(); return s.release(); } @@ -1446,12 +1462,12 @@ struct JavascriptEngine::RootObject : public DynamicObject ObjectClass() { setMethod ("dump", dump); - setMethod ("clone", clone); + setMethod ("clone", cloneFn); } static Identifier getClassName() { static const Identifier i ("Object"); return i; } static var dump (Args a) { DBG (JSON::toString (a.thisObject)); (void) a; return var::undefined(); } - static var clone (Args a) { return a.thisObject.clone(); } + static var cloneFn (Args a) { return a.thisObject.clone(); } }; //============================================================================== @@ -1555,6 +1571,7 @@ struct JavascriptEngine::RootObject : public DynamicObject setMethod ("log", Math_log); setMethod ("log10", Math_log10); setMethod ("exp", Math_exp); setMethod ("pow", Math_pow); setMethod ("sqr", Math_sqr); setMethod ("sqrt", Math_sqrt); + setMethod ("ceil", Math_ceil); setMethod ("floor", Math_floor); } static var Math_pi (Args) { return double_Pi; } @@ -1567,8 +1584,8 @@ struct JavascriptEngine::RootObject : public DynamicObject static var Math_range (Args a) { return isInt (a, 0) ? var (jlimit (getInt (a, 1), getInt (a, 2), getInt (a, 0))) : var (jlimit (getDouble (a, 1), getDouble (a, 2), getDouble (a, 0))); } static var Math_min (Args a) { return (isInt (a, 0) && isInt (a, 1)) ? var (jmin (getInt (a, 0), getInt (a, 1))) : var (jmin (getDouble (a, 0), getDouble (a, 1))); } static var Math_max (Args a) { return (isInt (a, 0) && isInt (a, 1)) ? var (jmax (getInt (a, 0), getInt (a, 1))) : var (jmax (getDouble (a, 0), getDouble (a, 1))); } - static var Math_toDegrees (Args a) { return (180.0 / double_Pi) * getDouble (a, 0); } - static var Math_toRadians (Args a) { return (double_Pi / 180.0) * getDouble (a, 0); } + static var Math_toDegrees (Args a) { return radiansToDegrees (getDouble (a, 0)); } + static var Math_toRadians (Args a) { return degreesToRadians (getDouble (a, 0)); } static var Math_sin (Args a) { return sin (getDouble (a, 0)); } static var Math_asin (Args a) { return asin (getDouble (a, 0)); } static var Math_cos (Args a) { return cos (getDouble (a, 0)); } @@ -1587,6 +1604,8 @@ struct JavascriptEngine::RootObject : public DynamicObject static var Math_pow (Args a) { return pow (getDouble (a, 0), getDouble (a, 1)); } static var Math_sqr (Args a) { double x = getDouble (a, 0); return x * x; } static var Math_sqrt (Args a) { return std::sqrt (getDouble (a, 0)); } + static var Math_ceil (Args a) { return std::ceil (getDouble (a, 0)); } + static var Math_floor (Args a) { return std::floor (getDouble (a, 0)); } static Identifier getClassName() { static const Identifier i ("Math"); return i; } template static Type sign (Type n) noexcept { return n > 0 ? (Type) 1 : (n < 0 ? (Type) -1 : 0); } @@ -1649,9 +1668,9 @@ JavascriptEngine::JavascriptEngine() : maximumExecutionTime (15.0), root (new R JavascriptEngine::~JavascriptEngine() {} -void JavascriptEngine::prepareTimeout() const { root->timeout = Time::getCurrentTime() + maximumExecutionTime; } +void JavascriptEngine::prepareTimeout() const noexcept { root->timeout = Time::getCurrentTime() + maximumExecutionTime; } -void JavascriptEngine::registerNativeObject (Identifier name, DynamicObject* object) +void JavascriptEngine::registerNativeObject (const Identifier& name, DynamicObject* object) { root->setProperty (name, object); } @@ -1687,7 +1706,7 @@ var JavascriptEngine::evaluate (const String& code, Result* result) return var::undefined(); } -var JavascriptEngine::callFunction (Identifier function, const var::NativeFunctionArgs& args, Result* result) +var JavascriptEngine::callFunction (const Identifier& function, const var::NativeFunctionArgs& args, Result* result) { var returnVal (var::undefined()); @@ -1705,6 +1724,11 @@ var JavascriptEngine::callFunction (Identifier function, const var::NativeFuncti return returnVal; } +const NamedValueSet& JavascriptEngine::getRootObjectProperties() const noexcept +{ + return root->getProperties(); +} + #if JUCE_MSVC #pragma warning (pop) #endif diff --git a/JuceLibraryCode/modules/juce_core/javascript/juce_Javascript.h b/JuceLibraryCode/modules/juce_core/javascript/juce_Javascript.h index 42368a4..0de35ae 100644 --- a/JuceLibraryCode/modules/juce_core/javascript/juce_Javascript.h +++ b/JuceLibraryCode/modules/juce_core/javascript/juce_Javascript.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this @@ -78,7 +78,7 @@ public: The function arguments are passed in the same format as used by native methods in the var class. */ - var callFunction (Identifier function, + var callFunction (const Identifier& function, const var::NativeFunctionArgs& args, Result* errorMessage = nullptr); @@ -87,7 +87,7 @@ public: engine until the engine is deleted. The name must be a simple JS identifier, without any dots. */ - void registerNativeObject (Identifier objectName, DynamicObject* object); + void registerNativeObject (const Identifier& objectName, DynamicObject* object); /** This value indicates how long a call to one of the evaluate methods is permitted to run before timing-out and failing. @@ -96,10 +96,13 @@ public: */ RelativeTime maximumExecutionTime; + /** Provides access to the set of properties of the root namespace object. */ + const NamedValueSet& getRootObjectProperties() const noexcept; + private: JUCE_PUBLIC_IN_DLL_BUILD (struct RootObject) - ReferenceCountedObjectPtr root; - void prepareTimeout() const; + const ReferenceCountedObjectPtr root; + void prepareTimeout() const noexcept; JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (JavascriptEngine) }; diff --git a/JuceLibraryCode/modules/juce_core/juce_core.cpp b/JuceLibraryCode/modules/juce_core/juce_core.cpp index c992d50..d5ad930 100644 --- a/JuceLibraryCode/modules/juce_core/juce_core.cpp +++ b/JuceLibraryCode/modules/juce_core/juce_core.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this @@ -45,14 +45,16 @@ #include #include -#include #if ! JUCE_ANDROID + #include #include #endif #if JUCE_WINDOWS #include + + #define _WINSOCK_DEPRECATED_NO_WARNINGS 1 #include #include @@ -79,6 +81,11 @@ #if JUCE_LINUX #include + #include + + #if JUCE_USE_CURL + #include + #endif #endif #include @@ -104,6 +111,11 @@ #include #endif +//============================================================================== +#ifndef JUCE_STANDALONE_APPLICATION + JUCE_COMPILER_WARNING ("Please re-save your Introjucer project with the latest Introjucer version to avoid this warning") + #define JUCE_STANDALONE_APPLICATION 0 +#endif //============================================================================== namespace juce @@ -202,6 +214,9 @@ namespace juce #include "native/juce_linux_CommonFile.cpp" #include "native/juce_linux_Files.cpp" #include "native/juce_linux_Network.cpp" +#if JUCE_USE_CURL + #include "native/juce_curl_Network.cpp" +#endif #include "native/juce_linux_SystemStats.cpp" #include "native/juce_linux_Threads.cpp" diff --git a/JuceLibraryCode/modules/juce_core/juce_core.h b/JuceLibraryCode/modules/juce_core/juce_core.h index 9496064..33fd07d 100644 --- a/JuceLibraryCode/modules/juce_core/juce_core.h +++ b/JuceLibraryCode/modules/juce_core/juce_core.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this @@ -48,6 +48,15 @@ #endif #endif +#ifdef _MSC_VER + #pragma warning (push) + // Disable warnings for long class names, padding, and undefined preprocessor definitions. + #pragma warning (disable: 4251 4786 4668 4820) + #ifdef __INTEL_COMPILER + #pragma warning (disable: 1125) + #endif +#endif + //============================================================================== #include "system/juce_TargetPlatform.h" @@ -117,6 +126,17 @@ #define JUCE_ZLIB_INCLUDE_PATH #endif +/** Config: JUCE_USE_CURL + Enables http/https support via libcurl (Linux only). Enabling this will add an additional + run-time dynmic dependency to libcurl. + + If you disable this then https/ssl support will not be available on linux. +*/ +#ifndef JUCE_USE_CURL + #define JUCE_USE_CURL 0 +#endif + + /* Config: JUCE_CATCH_UNHANDLED_EXCEPTIONS If enabled, this will add some exception-catching code to forward unhandled exceptions to your JUCEApplicationBase::unhandledException() callback. @@ -131,14 +151,6 @@ //============================================================================= //============================================================================= -#if JUCE_MSVC - #pragma warning (disable: 4251) // (DLL build warning, must be disabled before pushing the warning state) - #pragma warning (push) - #pragma warning (disable: 4786) // (long class name warning) - #ifdef __INTEL_COMPILER - #pragma warning (disable: 1125) - #endif -#endif #include "system/juce_StandardHeader.h" @@ -194,6 +206,7 @@ extern JUCE_API void JUCE_CALLTYPE logAssertion (const char* file, int line) noe #include "threads/juce_ScopedLock.h" #include "threads/juce_CriticalSection.h" #include "maths/juce_Range.h" +#include "maths/juce_NormalisableRange.h" #include "containers/juce_ElementComparator.h" #include "containers/juce_ArrayAllocationBase.h" #include "containers/juce_Array.h" @@ -243,7 +256,6 @@ extern JUCE_API void JUCE_CALLTYPE logAssertion (const char* file, int line) noe #include "maths/juce_Random.h" #include "misc/juce_Uuid.h" #include "misc/juce_WindowsRegistry.h" -#include "system/juce_PlatformDefs.h" #include "system/juce_SystemStats.h" #include "threads/juce_ChildProcess.h" #include "threads/juce_DynamicLibrary.h" diff --git a/JuceLibraryCode/modules/juce_core/juce_core.mm b/JuceLibraryCode/modules/juce_core/juce_core.mm index 90a2f7c..4f48e15 100644 --- a/JuceLibraryCode/modules/juce_core/juce_core.mm +++ b/JuceLibraryCode/modules/juce_core/juce_core.mm @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this diff --git a/JuceLibraryCode/modules/juce_core/juce_module_info b/JuceLibraryCode/modules/juce_core/juce_module_info index 7f44564..d98e635 100644 --- a/JuceLibraryCode/modules/juce_core/juce_module_info +++ b/JuceLibraryCode/modules/juce_core/juce_module_info @@ -1,7 +1,7 @@ { "id": "juce_core", "name": "JUCE core classes", - "version": "3.0.6", + "version": "3.2.0", "description": "The essential set of basic JUCE classes, as required by all the other JUCE modules. Includes text, container, memory, threading and i/o functionality.", "website": "http://www.juce.com/juce", "license": "ISC Permissive", diff --git a/JuceLibraryCode/modules/juce_core/logging/juce_FileLogger.cpp b/JuceLibraryCode/modules/juce_core/logging/juce_FileLogger.cpp index 8cadfda..55db2af 100644 --- a/JuceLibraryCode/modules/juce_core/logging/juce_FileLogger.cpp +++ b/JuceLibraryCode/modules/juce_core/logging/juce_FileLogger.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this @@ -32,7 +32,7 @@ FileLogger::FileLogger (const File& file, : logFile (file) { if (maxInitialFileSizeBytes >= 0) - trimFileSize (maxInitialFileSizeBytes); + trimFileSize (logFile, maxInitialFileSizeBytes); if (! file.exists()) file.create(); // (to create the parent directories) @@ -57,23 +57,23 @@ void FileLogger::logMessage (const String& message) out << message << newLine; } -void FileLogger::trimFileSize (int64 maxFileSizeBytes) const +void FileLogger::trimFileSize (const File& file, int64 maxFileSizeBytes) { if (maxFileSizeBytes <= 0) { - logFile.deleteFile(); + file.deleteFile(); } else { - const int64 fileSize = logFile.getSize(); + const int64 fileSize = file.getSize(); if (fileSize > maxFileSizeBytes) { - TemporaryFile tempFile (logFile); + TemporaryFile tempFile (file); { FileOutputStream out (tempFile.getFile()); - FileInputStream in (logFile); + FileInputStream in (file); if (! (out.openedOk() && in.openedOk())) return; diff --git a/JuceLibraryCode/modules/juce_core/logging/juce_FileLogger.h b/JuceLibraryCode/modules/juce_core/logging/juce_FileLogger.h index 6be1668..7f82360 100644 --- a/JuceLibraryCode/modules/juce_core/logging/juce_FileLogger.h +++ b/JuceLibraryCode/modules/juce_core/logging/juce_FileLogger.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this @@ -121,13 +121,17 @@ public: // (implementation of the Logger virtual method) void logMessage (const String&); + //============================================================================== + /** This is a utility function which removes lines from the start of a text + file to make sure that its total size is below the given size. + */ + static void trimFileSize (const File& file, int64 maxFileSize); + private: //============================================================================== File logFile; CriticalSection logLock; - void trimFileSize (int64 maxFileSizeBytes) const; - JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (FileLogger) }; diff --git a/JuceLibraryCode/modules/juce_core/logging/juce_Logger.cpp b/JuceLibraryCode/modules/juce_core/logging/juce_Logger.cpp index 0b1c8d6..00dec72 100644 --- a/JuceLibraryCode/modules/juce_core/logging/juce_Logger.cpp +++ b/JuceLibraryCode/modules/juce_core/logging/juce_Logger.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this diff --git a/JuceLibraryCode/modules/juce_core/logging/juce_Logger.h b/JuceLibraryCode/modules/juce_core/logging/juce_Logger.h index d0d3af5..1af9eb5 100644 --- a/JuceLibraryCode/modules/juce_core/logging/juce_Logger.h +++ b/JuceLibraryCode/modules/juce_core/logging/juce_Logger.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this diff --git a/JuceLibraryCode/modules/juce_core/maths/juce_BigInteger.cpp b/JuceLibraryCode/modules/juce_core/maths/juce_BigInteger.cpp index ba19414..602f2da 100644 --- a/JuceLibraryCode/modules/juce_core/maths/juce_BigInteger.cpp +++ b/JuceLibraryCode/modules/juce_core/maths/juce_BigInteger.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this @@ -307,41 +307,28 @@ void BigInteger::negate() noexcept negative = (! negative) && ! isZero(); } -#if JUCE_USE_INTRINSICS && ! defined (__INTEL_COMPILER) +#if JUCE_USE_MSVC_INTRINSICS && ! defined (__INTEL_COMPILER) #pragma intrinsic (_BitScanReverse) #endif -namespace BitFunctions +inline static int highestBitInInt (uint32 n) noexcept { - inline int countBitsInInt32 (uint32 n) noexcept - { - n -= ((n >> 1) & 0x55555555); - n = (((n >> 2) & 0x33333333) + (n & 0x33333333)); - n = (((n >> 4) + n) & 0x0f0f0f0f); - n += (n >> 8); - n += (n >> 16); - return (int) (n & 0x3f); - } + jassert (n != 0); // (the built-in functions may not work for n = 0) - inline int highestBitInInt (uint32 n) noexcept - { - jassert (n != 0); // (the built-in functions may not work for n = 0) - - #if JUCE_GCC - return 31 - __builtin_clz (n); - #elif JUCE_USE_INTRINSICS - unsigned long highest; - _BitScanReverse (&highest, n); - return (int) highest; - #else - n |= (n >> 1); - n |= (n >> 2); - n |= (n >> 4); - n |= (n >> 8); - n |= (n >> 16); - return countBitsInInt32 (n >> 1); - #endif - } + #if JUCE_GCC + return 31 - __builtin_clz (n); + #elif JUCE_USE_MSVC_INTRINSICS + unsigned long highest; + _BitScanReverse (&highest, n); + return (int) highest; + #else + n |= (n >> 1); + n |= (n >> 2); + n |= (n >> 4); + n |= (n >> 8); + n |= (n >> 16); + return countBitsInInt32 (n >> 1); + #endif } int BigInteger::countNumberOfSetBits() const noexcept @@ -349,7 +336,7 @@ int BigInteger::countNumberOfSetBits() const noexcept int total = 0; for (int i = (int) bitToIndex (highestBit) + 1; --i >= 0;) - total += BitFunctions::countBitsInInt32 (values[i]); + total += countNumberOfBits (values[i]); return total; } @@ -361,7 +348,7 @@ int BigInteger::getHighestBit() const noexcept const uint32 n = values[i]; if (n != 0) - return BitFunctions::highestBitInInt (n) + (i << 5); + return highestBitInInt (n) + (i << 5); } return -1; diff --git a/JuceLibraryCode/modules/juce_core/maths/juce_BigInteger.h b/JuceLibraryCode/modules/juce_core/maths/juce_BigInteger.h index 4c6c25c..2f99424 100644 --- a/JuceLibraryCode/modules/juce_core/maths/juce_BigInteger.h +++ b/JuceLibraryCode/modules/juce_core/maths/juce_BigInteger.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this diff --git a/JuceLibraryCode/modules/juce_core/maths/juce_Expression.cpp b/JuceLibraryCode/modules/juce_core/maths/juce_Expression.cpp index a18effa..2a16913 100644 --- a/JuceLibraryCode/modules/juce_core/maths/juce_Expression.cpp +++ b/JuceLibraryCode/modules/juce_core/maths/juce_Expression.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this @@ -1162,9 +1162,9 @@ double Expression::Scope::evaluateFunction (const String& functionName, const do if (numParams == 1) { - if (functionName == "sin") return sin (parameters[0]); - if (functionName == "cos") return cos (parameters[0]); - if (functionName == "tan") return tan (parameters[0]); + if (functionName == "sin") return std::sin (parameters[0]); + if (functionName == "cos") return std::cos (parameters[0]); + if (functionName == "tan") return std::tan (parameters[0]); if (functionName == "abs") return std::abs (parameters[0]); } } diff --git a/JuceLibraryCode/modules/juce_core/maths/juce_Expression.h b/JuceLibraryCode/modules/juce_core/maths/juce_Expression.h index 8939129..0f12db2 100644 --- a/JuceLibraryCode/modules/juce_core/maths/juce_Expression.h +++ b/JuceLibraryCode/modules/juce_core/maths/juce_Expression.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this diff --git a/JuceLibraryCode/modules/juce_core/maths/juce_MathsFunctions.h b/JuceLibraryCode/modules/juce_core/maths/juce_MathsFunctions.h index c9ce7fe..61ab44d 100644 --- a/JuceLibraryCode/modules/juce_core/maths/juce_MathsFunctions.h +++ b/JuceLibraryCode/modules/juce_core/maths/juce_MathsFunctions.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this @@ -119,6 +119,22 @@ inline Type jmin (const Type a, const Type b, const Type c) template inline Type jmin (const Type a, const Type b, const Type c, const Type d) { return jmin (a, jmin (b, c, d)); } +/** Remaps a normalised value (between 0 and 1) to a target range. + This effectively returns (targetRangeMin + value0To1 * (targetRangeMax - targetRangeMin)) +*/ +template +static Type jmap (Type value0To1, Type targetRangeMin, Type targetRangeMax) +{ + return targetRangeMin + value0To1 * (targetRangeMax - targetRangeMin); +} + +/** Remaps a value from a source range to a target range. */ +template +static Type jmap (Type sourceValue, Type sourceRangeMin, Type sourceRangeMax, Type targetRangeMin, Type targetRangeMax) +{ + return targetRangeMin + ((targetRangeMax - targetRangeMin) * (sourceValue - sourceRangeMin)) / (sourceRangeMax - sourceRangeMin); +} + /** Scans an array of values, returning the minimum value that it contains. */ template const Type findMinimum (const Type* data, int numValues) @@ -258,6 +274,19 @@ inline void swapVariables (Type& variable1, Type& variable2) std::swap (variable1, variable2); } +/** Handy function for avoiding unused variables warning. */ +template +void ignoreUnused (const Type1&) noexcept {} + +template +void ignoreUnused (const Type1&, const Type2&) noexcept {} + +template +void ignoreUnused (const Type1&, const Type2&, const Type3&) noexcept {} + +template +void ignoreUnused (const Type1&, const Type2&, const Type3&, const Type4&) noexcept {} + /** Handy function for getting the number of elements in a simple const C array. E.g. @code @@ -277,22 +306,30 @@ inline int numElementsInArray (Type (&array)[N]) //============================================================================== // Some useful maths functions that aren't always present with all compilers and build settings. - /** Using juce_hypot is easier than dealing with the different types of hypot function that are provided by the various platforms and compilers. */ template inline Type juce_hypot (Type a, Type b) noexcept { - -#ifndef IGNORE_JUCE_HYPOT #if JUCE_MSVC - return static_cast (_hypot (a, b)); + return static_cast (_hypot (a, b)); #else - return static_cast (hypot (a, b)); + return static_cast (hypot (a, b)); #endif -#endif } +#ifndef DOXYGEN +template <> +inline float juce_hypot (float a, float b) noexcept +{ + #if JUCE_MSVC + return (_hypotf (a, b)); + #else + return (hypotf (a, b)); + #endif +} +#endif + /** 64-bit abs function. */ inline int64 abs64 (const int64 n) noexcept { @@ -317,17 +354,40 @@ const double double_Pi = 3.1415926535897932384626433832795; const float float_Pi = 3.14159265358979323846f; +/** Converts an angle in degrees to radians. */ +template +inline FloatType degreesToRadians (FloatType degrees) noexcept { return degrees * static_cast (double_Pi / 180.0); } + +/** Converts an angle in radians to degrees. */ +template +inline FloatType radiansToDegrees (FloatType radians) noexcept { return radians * static_cast (180.0 / double_Pi); } + + //============================================================================== /** The isfinite() method seems to vary between platforms, so this is a platform-independent function for it. */ -template -inline bool juce_isfinite (FloatingPointType value) +template +inline bool juce_isfinite (NumericType) noexcept +{ + return true; // Integer types are always finite +} + +template <> +inline bool juce_isfinite (float value) noexcept { #if JUCE_WINDOWS - return _finite (value); - #elif JUCE_ANDROID - return isfinite (value); + return _finite (value) != 0; + #else + return std::isfinite (value); + #endif +} + +template <> +inline bool juce_isfinite (double value) noexcept +{ + #if JUCE_WINDOWS + return _finite (value) != 0; #else return std::isfinite (value); #endif @@ -368,6 +428,11 @@ inline int roundToInt (const FloatType value) noexcept #endif } +inline int roundToInt (int value) noexcept +{ + return value; +} + #if JUCE_MSVC #ifndef __INTEL_COMPILER #pragma float_control (pop) @@ -421,16 +486,14 @@ inline int roundFloatToInt (const float value) noexcept } //============================================================================== -/** Returns true if the specified integer is a power-of-two. -*/ +/** Returns true if the specified integer is a power-of-two. */ template bool isPowerOfTwo (IntegerType value) { return (value & (value - 1)) == 0; } -/** Returns the smallest power-of-two which is equal to or greater than the given integer. -*/ +/** Returns the smallest power-of-two which is equal to or greater than the given integer. */ inline int nextPowerOfTwo (int n) noexcept { --n; @@ -442,6 +505,23 @@ inline int nextPowerOfTwo (int n) noexcept return n + 1; } +/** Returns the number of bits in a 32-bit integer. */ +inline int countNumberOfBits (uint32 n) noexcept +{ + n -= ((n >> 1) & 0x55555555); + n = (((n >> 2) & 0x33333333) + (n & 0x33333333)); + n = (((n >> 4) + n) & 0x0f0f0f0f); + n += (n >> 8); + n += (n >> 16); + return (int) (n & 0x3f); +} + +/** Returns the number of bits in a 64-bit integer. */ +inline int countNumberOfBits (uint64 n) noexcept +{ + return countNumberOfBits ((uint32) n) + countNumberOfBits ((uint32) (n >> 32)); +} + /** Performs a modulo operation, but can cope with the dividend being negative. The divisor must be greater than zero. */ @@ -460,13 +540,14 @@ NumericType square (NumericType n) noexcept return n * n; } + //============================================================================== -#if (JUCE_INTEL && JUCE_32BIT) || defined (DOXYGEN) +#if JUCE_INTEL || defined (DOXYGEN) /** This macro can be applied to a float variable to check whether it contains a denormalised value, and to normalise it if necessary. On CPUs that aren't vulnerable to denormalisation problems, this will have no effect. */ - #define JUCE_UNDENORMALISE(x) x += 1.0f; x -= 1.0f; + #define JUCE_UNDENORMALISE(x) { (x) += 0.1f; (x) -= 0.1f; } #else #define JUCE_UNDENORMALISE(x) #endif diff --git a/JuceLibraryCode/modules/juce_core/maths/juce_Random.cpp b/JuceLibraryCode/modules/juce_core/maths/juce_Random.cpp index a196256..c0a3aaf 100644 --- a/JuceLibraryCode/modules/juce_core/maths/juce_Random.cpp +++ b/JuceLibraryCode/modules/juce_core/maths/juce_Random.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this diff --git a/JuceLibraryCode/modules/juce_core/maths/juce_Random.h b/JuceLibraryCode/modules/juce_core/maths/juce_Random.h index 19e6d6e..9db4534 100644 --- a/JuceLibraryCode/modules/juce_core/maths/juce_Random.h +++ b/JuceLibraryCode/modules/juce_core/maths/juce_Random.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this diff --git a/JuceLibraryCode/modules/juce_core/maths/juce_Range.h b/JuceLibraryCode/modules/juce_core/maths/juce_Range.h index 0aa9be4..d1b1e45 100644 --- a/JuceLibraryCode/modules/juce_core/maths/juce_Range.h +++ b/JuceLibraryCode/modules/juce_core/maths/juce_Range.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this @@ -77,6 +77,13 @@ public: : Range (position2, position1); } + /** Returns a range with a given start and length. */ + static Range withStartAndLength (const ValueType startValue, const ValueType length) noexcept + { + jassert (length >= ValueType()); + return Range (startValue, startValue + length); + } + /** Returns a range with the specified start position and a length of zero. */ static Range emptyRange (const ValueType start) noexcept { diff --git a/JuceLibraryCode/modules/juce_core/memory/juce_Atomic.h b/JuceLibraryCode/modules/juce_core/memory/juce_Atomic.h index d0dd6be..5942094 100644 --- a/JuceLibraryCode/modules/juce_core/memory/juce_Atomic.h +++ b/JuceLibraryCode/modules/juce_core/memory/juce_Atomic.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this @@ -218,7 +218,7 @@ private: #else #define JUCE_ATOMICS_WINDOWS 1 // Windows with intrinsics - #if JUCE_USE_INTRINSICS + #if JUCE_USE_MSVC_INTRINSICS #ifndef __INTEL_COMPILER #pragma intrinsic (_InterlockedExchange, _InterlockedIncrement, _InterlockedDecrement, _InterlockedCompareExchange, \ _InterlockedCompareExchange64, _InterlockedExchangeAdd, _ReadWriteBarrier) diff --git a/JuceLibraryCode/modules/juce_core/memory/juce_ByteOrder.h b/JuceLibraryCode/modules/juce_core/memory/juce_ByteOrder.h index 4d3ba0e..b4f7df6 100644 --- a/JuceLibraryCode/modules/juce_core/memory/juce_ByteOrder.h +++ b/JuceLibraryCode/modules/juce_core/memory/juce_ByteOrder.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this @@ -87,16 +87,16 @@ public: //============================================================================== /** Converts 3 little-endian bytes into a signed 24-bit value (which is sign-extended to 32 bits). */ - static int littleEndian24Bit (const char* bytes) noexcept; + static int littleEndian24Bit (const void* bytes) noexcept; /** Converts 3 big-endian bytes into a signed 24-bit value (which is sign-extended to 32 bits). */ - static int bigEndian24Bit (const char* bytes) noexcept; + static int bigEndian24Bit (const void* bytes) noexcept; /** Copies a 24-bit number to 3 little-endian bytes. */ - static void littleEndian24BitToChars (int value, char* destBytes) noexcept; + static void littleEndian24BitToChars (int value, void* destBytes) noexcept; /** Copies a 24-bit number to 3 big-endian bytes. */ - static void bigEndian24BitToChars (int value, char* destBytes) noexcept; + static void bigEndian24BitToChars (int value, void* destBytes) noexcept; //============================================================================== /** Returns true if the current CPU is big-endian. */ @@ -110,16 +110,16 @@ private: //============================================================================== -#if JUCE_USE_INTRINSICS && ! defined (__INTEL_COMPILER) +#if JUCE_USE_MSVC_INTRINSICS && ! defined (__INTEL_COMPILER) #pragma intrinsic (_byteswap_ulong) #endif inline uint16 ByteOrder::swap (uint16 n) noexcept { - #if JUCE_USE_INTRINSICSxxx // agh - the MS compiler has an internal error when you try to use this intrinsic! - return static_cast (_byteswap_ushort (n)); + #if JUCE_USE_MSVC_INTRINSICSxxx // agh - the MS compiler has an internal error when you try to use this intrinsic! + return static_cast (_byteswap_ushort (n)); #else - return static_cast ((n << 8) | (n >> 8)); + return static_cast ((n << 8) | (n >> 8)); #endif } @@ -130,7 +130,7 @@ inline uint32 ByteOrder::swap (uint32 n) noexcept #elif JUCE_GCC && JUCE_INTEL && ! JUCE_NO_INLINE_ASM asm("bswap %%eax" : "=a"(n) : "a"(n)); return n; - #elif JUCE_USE_INTRINSICS + #elif JUCE_USE_MSVC_INTRINSICS return _byteswap_ulong (n); #elif JUCE_MSVC && ! JUCE_NO_INLINE_ASM __asm { @@ -150,10 +150,10 @@ inline uint64 ByteOrder::swap (uint64 value) noexcept { #if JUCE_MAC || JUCE_IOS return OSSwapInt64 (value); - #elif JUCE_USE_INTRINSICS + #elif JUCE_USE_MSVC_INTRINSICS return _byteswap_uint64 (value); #else - return (((int64) swap ((uint32) value)) << 32) | swap ((uint32) (value >> 32)); + return (((uint64) swap ((uint32) value)) << 32) | swap ((uint32) (value >> 32)); #endif } @@ -164,12 +164,12 @@ inline uint64 ByteOrder::swap (uint64 value) noexcept inline uint16 ByteOrder::swapIfLittleEndian (const uint16 v) noexcept { return swap (v); } inline uint32 ByteOrder::swapIfLittleEndian (const uint32 v) noexcept { return swap (v); } inline uint64 ByteOrder::swapIfLittleEndian (const uint64 v) noexcept { return swap (v); } - inline uint32 ByteOrder::littleEndianInt (const void* const bytes) noexcept { return *static_cast (bytes); } - inline uint64 ByteOrder::littleEndianInt64 (const void* const bytes) noexcept { return *static_cast (bytes); } - inline uint16 ByteOrder::littleEndianShort (const void* const bytes) noexcept { return *static_cast (bytes); } - inline uint32 ByteOrder::bigEndianInt (const void* const bytes) noexcept { return swap (*static_cast (bytes)); } - inline uint64 ByteOrder::bigEndianInt64 (const void* const bytes) noexcept { return swap (*static_cast (bytes)); } - inline uint16 ByteOrder::bigEndianShort (const void* const bytes) noexcept { return swap (*static_cast (bytes)); } + inline uint32 ByteOrder::littleEndianInt (const void* const bytes) noexcept { return *static_cast (bytes); } + inline uint64 ByteOrder::littleEndianInt64 (const void* const bytes) noexcept { return *static_cast (bytes); } + inline uint16 ByteOrder::littleEndianShort (const void* const bytes) noexcept { return *static_cast (bytes); } + inline uint32 ByteOrder::bigEndianInt (const void* const bytes) noexcept { return swap (*static_cast (bytes)); } + inline uint64 ByteOrder::bigEndianInt64 (const void* const bytes) noexcept { return swap (*static_cast (bytes)); } + inline uint16 ByteOrder::bigEndianShort (const void* const bytes) noexcept { return swap (*static_cast (bytes)); } inline bool ByteOrder::isBigEndian() noexcept { return false; } #else inline uint16 ByteOrder::swapIfBigEndian (const uint16 v) noexcept { return swap (v); } @@ -178,19 +178,19 @@ inline uint64 ByteOrder::swap (uint64 value) noexcept inline uint16 ByteOrder::swapIfLittleEndian (const uint16 v) noexcept { return v; } inline uint32 ByteOrder::swapIfLittleEndian (const uint32 v) noexcept { return v; } inline uint64 ByteOrder::swapIfLittleEndian (const uint64 v) noexcept { return v; } - inline uint32 ByteOrder::littleEndianInt (const void* const bytes) noexcept { return swap (*static_cast (bytes)); } - inline uint64 ByteOrder::littleEndianInt64 (const void* const bytes) noexcept { return swap (*static_cast (bytes)); } - inline uint16 ByteOrder::littleEndianShort (const void* const bytes) noexcept { return swap (*static_cast (bytes)); } - inline uint32 ByteOrder::bigEndianInt (const void* const bytes) noexcept { return *static_cast (bytes); } - inline uint64 ByteOrder::bigEndianInt64 (const void* const bytes) noexcept { return *static_cast (bytes); } - inline uint16 ByteOrder::bigEndianShort (const void* const bytes) noexcept { return *static_cast (bytes); } + inline uint32 ByteOrder::littleEndianInt (const void* const bytes) noexcept { return swap (*static_cast (bytes)); } + inline uint64 ByteOrder::littleEndianInt64 (const void* const bytes) noexcept { return swap (*static_cast (bytes)); } + inline uint16 ByteOrder::littleEndianShort (const void* const bytes) noexcept { return swap (*static_cast (bytes)); } + inline uint32 ByteOrder::bigEndianInt (const void* const bytes) noexcept { return *static_cast (bytes); } + inline uint64 ByteOrder::bigEndianInt64 (const void* const bytes) noexcept { return *static_cast (bytes); } + inline uint16 ByteOrder::bigEndianShort (const void* const bytes) noexcept { return *static_cast (bytes); } inline bool ByteOrder::isBigEndian() noexcept { return true; } #endif -inline int ByteOrder::littleEndian24Bit (const char* const bytes) noexcept { return (((int) bytes[2]) << 16) | (((int) (uint8) bytes[1]) << 8) | ((int) (uint8) bytes[0]); } -inline int ByteOrder::bigEndian24Bit (const char* const bytes) noexcept { return (((int) bytes[0]) << 16) | (((int) (uint8) bytes[1]) << 8) | ((int) (uint8) bytes[2]); } -inline void ByteOrder::littleEndian24BitToChars (const int value, char* const destBytes) noexcept { destBytes[0] = (char)(value & 0xff); destBytes[1] = (char)((value >> 8) & 0xff); destBytes[2] = (char)((value >> 16) & 0xff); } -inline void ByteOrder::bigEndian24BitToChars (const int value, char* const destBytes) noexcept { destBytes[0] = (char)((value >> 16) & 0xff); destBytes[1] = (char)((value >> 8) & 0xff); destBytes[2] = (char)(value & 0xff); } +inline int ByteOrder::littleEndian24Bit (const void* const bytes) noexcept { return (((int) static_cast (bytes)[2]) << 16) | (((int) static_cast (bytes)[1]) << 8) | ((int) static_cast (bytes)[0]); } +inline int ByteOrder::bigEndian24Bit (const void* const bytes) noexcept { return (((int) static_cast (bytes)[0]) << 16) | (((int) static_cast (bytes)[1]) << 8) | ((int) static_cast (bytes)[2]); } +inline void ByteOrder::littleEndian24BitToChars (const int value, void* const destBytes) noexcept { static_cast (destBytes)[0] = (uint8) value; static_cast (destBytes)[1] = (uint8) (value >> 8); static_cast (destBytes)[2] = (uint8) (value >> 16); } +inline void ByteOrder::bigEndian24BitToChars (const int value, void* const destBytes) noexcept { static_cast (destBytes)[0] = (uint8) (value >> 16); static_cast (destBytes)[1] = (uint8) (value >> 8); static_cast (destBytes)[2] = (uint8) value; } #endif // JUCE_BYTEORDER_H_INCLUDED diff --git a/JuceLibraryCode/modules/juce_core/memory/juce_ContainerDeletePolicy.h b/JuceLibraryCode/modules/juce_core/memory/juce_ContainerDeletePolicy.h index 60cddaa..7ea2884 100644 --- a/JuceLibraryCode/modules/juce_core/memory/juce_ContainerDeletePolicy.h +++ b/JuceLibraryCode/modules/juce_core/memory/juce_ContainerDeletePolicy.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this @@ -45,6 +45,16 @@ struct ContainerDeletePolicy { static void destroy (ObjectType* object) { + // If the line below triggers a compiler error, it means that you are using + // an incomplete type for ObjectType (for example, a type that is declared + // but not defined). This is a problem because then the following delete is + // undefined behaviour. The purpose of the sizeof is to capture this situation. + // If this was caused by a ScopedPointer to a forward-declared type, move the + // implementation of all methods trying to use the ScopedPointer (e.g. the destructor + // of the class owning it) into cpp files where they can see to the definition + // of ObjectType. This should fix the error. + ignoreUnused (sizeof (ObjectType)); + delete object; } }; diff --git a/JuceLibraryCode/modules/juce_core/memory/juce_HeapBlock.h b/JuceLibraryCode/modules/juce_core/memory/juce_HeapBlock.h index 3731f0b..5672d37 100644 --- a/JuceLibraryCode/modules/juce_core/memory/juce_HeapBlock.h +++ b/JuceLibraryCode/modules/juce_core/memory/juce_HeapBlock.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this @@ -36,7 +36,7 @@ namespace HeapBlockHelper struct ThrowOnFail { static void check (void*) {} }; template<> - struct ThrowOnFail { static void check (void* data) { if (data == nullptr) throw std::bad_alloc(); } }; + struct ThrowOnFail { static void check (void* data) { if (data == nullptr) throw std::bad_alloc(); } }; } #endif @@ -67,7 +67,7 @@ namespace HeapBlockHelper ..you could just write this: @code - HeapBlock temp (1024); + HeapBlock temp (1024); memcpy (temp, xyz, 1024 * sizeof (int)); temp.calloc (2048); temp[0] = 1234; @@ -109,7 +109,7 @@ public: other constructor that takes an InitialisationState parameter. */ explicit HeapBlock (const size_t numElements) - : data (static_cast (std::malloc (numElements * sizeof (ElementType)))) + : data (static_cast (std::malloc (numElements * sizeof (ElementType)))) { throwOnAllocationFailure(); } @@ -120,7 +120,7 @@ public: or left uninitialised. */ HeapBlock (const size_t numElements, const bool initialiseToZero) - : data (static_cast (initialiseToZero + : data (static_cast (initialiseToZero ? std::calloc (numElements, sizeof (ElementType)) : std::malloc (numElements * sizeof (ElementType)))) { @@ -166,13 +166,13 @@ public: This may be a null pointer if the data hasn't yet been allocated, or if it has been freed by calling the free() method. */ - inline operator void*() const noexcept { return static_cast (data); } + inline operator void*() const noexcept { return static_cast (data); } /** Returns a void pointer to the allocated data. This may be a null pointer if the data hasn't yet been allocated, or if it has been freed by calling the free() method. */ - inline operator const void*() const noexcept { return static_cast (data); } + inline operator const void*() const noexcept { return static_cast (data); } /** Lets you use indirect calls to the first element in the array. Obviously this will cause problems if the array hasn't been initialised, because it'll @@ -220,7 +220,7 @@ public: void malloc (const size_t newNumElements, const size_t elementSize = sizeof (ElementType)) { std::free (data); - data = static_cast (std::malloc (newNumElements * elementSize)); + data = static_cast (std::malloc (newNumElements * elementSize)); throwOnAllocationFailure(); } @@ -230,7 +230,7 @@ public: void calloc (const size_t newNumElements, const size_t elementSize = sizeof (ElementType)) { std::free (data); - data = static_cast (std::calloc (newNumElements, elementSize)); + data = static_cast (std::calloc (newNumElements, elementSize)); throwOnAllocationFailure(); } @@ -241,7 +241,7 @@ public: void allocate (const size_t newNumElements, bool initialiseToZero) { std::free (data); - data = static_cast (initialiseToZero + data = static_cast (initialiseToZero ? std::calloc (newNumElements, sizeof (ElementType)) : std::malloc (newNumElements * sizeof (ElementType))); throwOnAllocationFailure(); @@ -254,15 +254,15 @@ public: */ void realloc (const size_t newNumElements, const size_t elementSize = sizeof (ElementType)) { - data = static_cast (data == nullptr ? std::malloc (newNumElements * elementSize) - : std::realloc (data, newNumElements * elementSize)); + data = static_cast (data == nullptr ? std::malloc (newNumElements * elementSize) + : std::realloc (data, newNumElements * elementSize)); throwOnAllocationFailure(); } /** Frees any currently-allocated data. This will free the data and reset this object to be a null pointer. */ - void free() + void free() noexcept { std::free (data); data = nullptr; @@ -272,7 +272,7 @@ public: The two objects simply exchange their data pointers. */ template - void swapWith (HeapBlock & other) noexcept + void swapWith (HeapBlock& other) noexcept { std::swap (data, other.data); } diff --git a/JuceLibraryCode/modules/juce_core/memory/juce_LeakedObjectDetector.h b/JuceLibraryCode/modules/juce_core/memory/juce_LeakedObjectDetector.h index 248e7bc..9a12e93 100644 --- a/JuceLibraryCode/modules/juce_core/memory/juce_LeakedObjectDetector.h +++ b/JuceLibraryCode/modules/juce_core/memory/juce_LeakedObjectDetector.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this diff --git a/JuceLibraryCode/modules/juce_core/memory/juce_Memory.h b/JuceLibraryCode/modules/juce_core/memory/juce_Memory.h index 57d1644..61c7731 100644 --- a/JuceLibraryCode/modules/juce_core/memory/juce_Memory.h +++ b/JuceLibraryCode/modules/juce_core/memory/juce_Memory.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this @@ -50,7 +50,7 @@ inline void deleteAndZero (Type& pointer) { delete poi a specific number of bytes, */ template -inline Type* addBytesToPointer (Type* pointer, IntegerType bytes) noexcept { return (Type*) (((char*) pointer) + bytes); } +inline Type* addBytesToPointer (Type* basePointer, IntegerType bytes) noexcept { return (Type*) (((char*) basePointer) + bytes); } /** A handy function which returns the difference between any two pointers, in bytes. The address of the second pointer is subtracted from the first, and the difference in bytes is returned. @@ -62,7 +62,25 @@ inline int getAddressDifference (Type1* pointer1, Type2* pointer2) noexcept { r nullptr if the pointer is null. */ template -inline Type* createCopyIfNotNull (const Type* pointer) { return pointer != nullptr ? new Type (*pointer) : nullptr; } +inline Type* createCopyIfNotNull (const Type* objectToCopy) { return objectToCopy != nullptr ? new Type (*objectToCopy) : nullptr; } + +//============================================================================== +/** A handy function to read un-aligned memory without a performance penalty or bus-error. */ +template +inline Type readUnaligned (const void* srcPtr) noexcept +{ + Type value; + memcpy (&value, srcPtr, sizeof (Type)); + + return value; +} + +/** A handy function to write un-aligned memory without a performance penalty or bus-error. */ +template +inline void writeUnaligned (void* dstPtr, Type value) noexcept +{ + memcpy (dstPtr, &value, sizeof(Type)); +} //============================================================================== #if JUCE_MAC || JUCE_IOS || DOXYGEN diff --git a/JuceLibraryCode/modules/juce_core/memory/juce_MemoryBlock.cpp b/JuceLibraryCode/modules/juce_core/memory/juce_MemoryBlock.cpp index a827037..0efd21b 100644 --- a/JuceLibraryCode/modules/juce_core/memory/juce_MemoryBlock.cpp +++ b/JuceLibraryCode/modules/juce_core/memory/juce_MemoryBlock.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this @@ -88,14 +88,14 @@ MemoryBlock& MemoryBlock::operator= (const MemoryBlock& other) #if JUCE_COMPILER_SUPPORTS_MOVE_SEMANTICS MemoryBlock::MemoryBlock (MemoryBlock&& other) noexcept - : data (static_cast &&> (other.data)), + : data (static_cast&&> (other.data)), size (other.size) { } MemoryBlock& MemoryBlock::operator= (MemoryBlock&& other) noexcept { - data = static_cast &&> (other.data); + data = static_cast&&> (other.data); size = other.size; return *this; } @@ -259,7 +259,7 @@ void MemoryBlock::copyTo (void* const dst, int offset, size_t num) const noexcep if ((size_t) offset + num > size) { - const size_t newNum = size - (size_t) offset; + const size_t newNum = (size_t) size - (size_t) offset; zeromem (d + newNum, num - newNum); num = newNum; } @@ -346,7 +346,7 @@ void MemoryBlock::loadFromHexString (StringRef hex) if (c == 0) { - setSize (static_cast (dest - data)); + setSize (static_cast (dest - data)); return; } } diff --git a/JuceLibraryCode/modules/juce_core/memory/juce_MemoryBlock.h b/JuceLibraryCode/modules/juce_core/memory/juce_MemoryBlock.h index 30bb3ca..cbe025c 100644 --- a/JuceLibraryCode/modules/juce_core/memory/juce_MemoryBlock.h +++ b/JuceLibraryCode/modules/juce_core/memory/juce_MemoryBlock.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this diff --git a/JuceLibraryCode/modules/juce_core/memory/juce_OptionalScopedPointer.h b/JuceLibraryCode/modules/juce_core/memory/juce_OptionalScopedPointer.h index a633dca..fd0d5f6 100644 --- a/JuceLibraryCode/modules/juce_core/memory/juce_OptionalScopedPointer.h +++ b/JuceLibraryCode/modules/juce_core/memory/juce_OptionalScopedPointer.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this diff --git a/JuceLibraryCode/modules/juce_core/memory/juce_ReferenceCountedObject.h b/JuceLibraryCode/modules/juce_core/memory/juce_ReferenceCountedObject.h index 6464d85..3dac3c4 100644 --- a/JuceLibraryCode/modules/juce_core/memory/juce_ReferenceCountedObject.h +++ b/JuceLibraryCode/modules/juce_core/memory/juce_ReferenceCountedObject.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this @@ -208,7 +208,7 @@ private: The template parameter specifies the class of the object you want to point to - the easiest way to make a class reference-countable is to simply make it inherit from ReferenceCountedObject or SingleThreadedReferenceCountedObject, but if you need to, you can roll your own reference-countable - class by implementing a set of mathods called incReferenceCount(), decReferenceCount(), and + class by implementing a set of methods called incReferenceCount(), decReferenceCount(), and decReferenceCountWithoutDeleting(). See ReferenceCountedObject for examples of how these methods should behave. diff --git a/JuceLibraryCode/modules/juce_core/memory/juce_ScopedPointer.h b/JuceLibraryCode/modules/juce_core/memory/juce_ScopedPointer.h index a7fcff0..557104e 100644 --- a/JuceLibraryCode/modules/juce_core/memory/juce_ScopedPointer.h +++ b/JuceLibraryCode/modules/juce_core/memory/juce_ScopedPointer.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this @@ -182,11 +182,11 @@ public: /** Swaps this object with that of another ScopedPointer. The two objects simply exchange their pointers. */ - void swapWith (ScopedPointer & other) noexcept + void swapWith (ScopedPointer& other) noexcept { // Two ScopedPointers should never be able to refer to the same object - if // this happens, you must have done something dodgy! - jassert (object != other.object || this == other.getAddress()); + jassert (object != other.object || this == other.getAddress() || object == nullptr); std::swap (object, other.object); } @@ -231,7 +231,7 @@ private: template bool operator== (const ScopedPointer& pointer1, ObjectType* const pointer2) noexcept { - return static_cast (pointer1) == pointer2; + return static_cast (pointer1) == pointer2; } /** Compares a ScopedPointer with another pointer. @@ -240,7 +240,7 @@ bool operator== (const ScopedPointer& pointer1, ObjectType* const po template bool operator!= (const ScopedPointer& pointer1, ObjectType* const pointer2) noexcept { - return static_cast (pointer1) != pointer2; + return static_cast (pointer1) != pointer2; } //============================================================================== diff --git a/JuceLibraryCode/modules/juce_core/memory/juce_SharedResourcePointer.h b/JuceLibraryCode/modules/juce_core/memory/juce_SharedResourcePointer.h index 53d314b..307b559 100644 --- a/JuceLibraryCode/modules/juce_core/memory/juce_SharedResourcePointer.h +++ b/JuceLibraryCode/modules/juce_core/memory/juce_SharedResourcePointer.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this @@ -94,13 +94,12 @@ public: */ SharedResourcePointer() { - SharedObjectHolder& holder = getSharedObjectHolder(); - const SpinLock::ScopedLockType sl (holder.lock); + initialise(); + } - if (++(holder.refCount) == 1) - holder.sharedInstance = new SharedObjectType(); - - sharedObject = holder.sharedInstance; + SharedResourcePointer (const SharedResourcePointer&) + { + initialise(); } /** Destructor. @@ -145,7 +144,22 @@ private: SharedObjectType* sharedObject; - JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (SharedResourcePointer) + void initialise() + { + SharedObjectHolder& holder = getSharedObjectHolder(); + const SpinLock::ScopedLockType sl (holder.lock); + + if (++(holder.refCount) == 1) + holder.sharedInstance = new SharedObjectType(); + + sharedObject = holder.sharedInstance; + } + + // There's no need to assign to a SharedResourcePointer because every + // instance of the class is exactly the same! + SharedResourcePointer& operator= (const SharedResourcePointer&) JUCE_DELETED_FUNCTION; + + JUCE_LEAK_DETECTOR (SharedResourcePointer) }; diff --git a/JuceLibraryCode/modules/juce_core/memory/juce_Singleton.h b/JuceLibraryCode/modules/juce_core/memory/juce_Singleton.h index 00ea0af..d424784 100644 --- a/JuceLibraryCode/modules/juce_core/memory/juce_Singleton.h +++ b/JuceLibraryCode/modules/juce_core/memory/juce_Singleton.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this @@ -44,7 +44,7 @@ destructor, in case it is deleted by other means than deleteInstance() Clients can then call the static method MyClass::getInstance() to get a pointer - to the singleton, or MyClass::getInstanceWithoutCreating() which will return 0 if + to the singleton, or MyClass::getInstanceWithoutCreating() which will return nullptr if no instance currently exists. e.g. @code diff --git a/JuceLibraryCode/modules/juce_core/memory/juce_WeakReference.h b/JuceLibraryCode/modules/juce_core/memory/juce_WeakReference.h index b56808a..ff23d99 100644 --- a/JuceLibraryCode/modules/juce_core/memory/juce_WeakReference.h +++ b/JuceLibraryCode/modules/juce_core/memory/juce_WeakReference.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this @@ -158,7 +158,7 @@ public: public: Master() noexcept {} - ~Master() + ~Master() noexcept { // You must remember to call clear() in your source object's destructor! See the notes // for the WeakReference class for an example of how to do this. @@ -187,7 +187,7 @@ public: to zero all the references to this object that may be out there. See the WeakReference class notes for an example of how to do this. */ - void clear() + void clear() noexcept { if (sharedPointer != nullptr) sharedPointer->clearPointer(); diff --git a/JuceLibraryCode/modules/juce_core/misc/juce_Result.cpp b/JuceLibraryCode/modules/juce_core/misc/juce_Result.cpp index 1734907..0999531 100644 --- a/JuceLibraryCode/modules/juce_core/misc/juce_Result.cpp +++ b/JuceLibraryCode/modules/juce_core/misc/juce_Result.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this diff --git a/JuceLibraryCode/modules/juce_core/misc/juce_Result.h b/JuceLibraryCode/modules/juce_core/misc/juce_Result.h index 7c320ac..218ffb6 100644 --- a/JuceLibraryCode/modules/juce_core/misc/juce_Result.h +++ b/JuceLibraryCode/modules/juce_core/misc/juce_Result.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this diff --git a/JuceLibraryCode/modules/juce_core/misc/juce_Uuid.cpp b/JuceLibraryCode/modules/juce_core/misc/juce_Uuid.cpp index eb74964..e0d0c15 100644 --- a/JuceLibraryCode/modules/juce_core/misc/juce_Uuid.cpp +++ b/JuceLibraryCode/modules/juce_core/misc/juce_Uuid.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this diff --git a/JuceLibraryCode/modules/juce_core/misc/juce_Uuid.h b/JuceLibraryCode/modules/juce_core/misc/juce_Uuid.h index cd7af0d..2a0ff05 100644 --- a/JuceLibraryCode/modules/juce_core/misc/juce_Uuid.h +++ b/JuceLibraryCode/modules/juce_core/misc/juce_Uuid.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this diff --git a/JuceLibraryCode/modules/juce_core/misc/juce_WindowsRegistry.h b/JuceLibraryCode/modules/juce_core/misc/juce_WindowsRegistry.h index a1fb2a2..987d87c 100644 --- a/JuceLibraryCode/modules/juce_core/misc/juce_WindowsRegistry.h +++ b/JuceLibraryCode/modules/juce_core/misc/juce_WindowsRegistry.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this diff --git a/JuceLibraryCode/modules/juce_core/native/java/JuceAppActivity.java b/JuceLibraryCode/modules/juce_core/native/java/JuceAppActivity.java index 882d0e0..5145319 100644 --- a/JuceLibraryCode/modules/juce_core/native/java/JuceAppActivity.java +++ b/JuceLibraryCode/modules/juce_core/native/java/JuceAppActivity.java @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -42,10 +42,8 @@ import android.opengl.*; import android.text.ClipboardManager; import android.text.InputType; import android.util.DisplayMetrics; -import java.io.BufferedInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; +import android.util.Log; +import java.io.*; import java.net.URL; import java.net.HttpURLConnection; import javax.microedition.khronos.egl.EGLConfig; @@ -55,7 +53,7 @@ import android.media.MediaScannerConnection; import android.media.MediaScannerConnection.MediaScannerConnectionClient; //============================================================================== -public final class JuceAppActivity extends Activity +public class JuceAppActivity extends Activity { //============================================================================== static @@ -64,7 +62,7 @@ public final class JuceAppActivity extends Activity } @Override - public final void onCreate (Bundle savedInstanceState) + public void onCreate (Bundle savedInstanceState) { super.onCreate (savedInstanceState); @@ -75,14 +73,16 @@ public final class JuceAppActivity extends Activity } @Override - protected final void onDestroy() + protected void onDestroy() { quitApp(); super.onDestroy(); + + clearDataCache(); } @Override - protected final void onPause() + protected void onPause() { if (viewHolder != null) viewHolder.onPause(); @@ -92,7 +92,7 @@ public final class JuceAppActivity extends Activity } @Override - protected final void onResume() + protected void onResume() { super.onResume(); @@ -157,6 +157,14 @@ public final class JuceAppActivity extends Activity group.removeView (view); } + public final void deleteOpenGLView (OpenGLView view) + { + ViewGroup group = (ViewGroup) (view.getParent()); + + if (group != null) + group.removeView (view); + } + final class ViewHolder extends ViewGroup { public ViewHolder (Context context) @@ -323,15 +331,26 @@ public final class JuceAppActivity extends Activity setFocusableInTouchMode (true); setOnFocusChangeListener (this); requestFocus(); + + // swap red and blue colours to match internal opengl texture format + ColorMatrix colorMatrix = new ColorMatrix(); + + float[] colorTransform = { 0, 0, 1.0f, 0, 0, + 0, 1.0f, 0, 0, 0, + 1.0f, 0, 0, 0, 0, + 0, 0, 0, 1.0f, 0 }; + + colorMatrix.set (colorTransform); + paint.setColorFilter (new ColorMatrixColorFilter (colorMatrix)); } //============================================================================== - private native void handlePaint (long host, Canvas canvas); + private native void handlePaint (long host, Canvas canvas, Paint paint); @Override public void onDraw (Canvas canvas) { - handlePaint (host, canvas); + handlePaint (host, canvas, paint); } @Override @@ -342,6 +361,7 @@ public final class JuceAppActivity extends Activity private boolean opaque; private long host; + private Paint paint = new Paint(); //============================================================================== private native void handleMouseDown (long host, int index, float x, float y, long time); @@ -440,6 +460,22 @@ public final class JuceAppActivity extends Activity return true; } + @Override + public boolean onKeyMultiple (int keyCode, int count, KeyEvent event) + { + if (keyCode != KeyEvent.KEYCODE_UNKNOWN || event.getAction() != KeyEvent.ACTION_MULTIPLE) + return super.onKeyMultiple (keyCode, count, event); + + if (event.getCharacters() != null) + { + int utf8Char = event.getCharacters().codePointAt (0); + handleKeyDown (host, utf8Char, utf8Char); + return true; + } + + return false; + } + // this is here to make keyboard entry work on a Galaxy Tab2 10.1 @Override public InputConnection onCreateInputConnection (EditorInfo outAttrs) @@ -666,38 +702,103 @@ public final class JuceAppActivity extends Activity public static final HTTPStream createHTTPStream (String address, boolean isPost, byte[] postData, String headers, int timeOutMs, int[] statusCode, - StringBuffer responseHeaders) + StringBuffer responseHeaders, + int numRedirectsToFollow) { - try - { - HttpURLConnection connection = (HttpURLConnection) (new URL(address) - .openConnection()); - if (connection != null) - { - try - { - if (isPost) - { - connection.setRequestMethod("POST"); - connection.setConnectTimeout(timeOutMs); - connection.setDoOutput(true); - connection.setChunkedStreamingMode(0); - OutputStream out = connection.getOutputStream(); - out.write(postData); - out.flush(); - } + // timeout parameter of zero for HttpUrlConnection is a blocking connect (negative value for juce::URL) + if (timeOutMs < 0) + timeOutMs = 0; + else if (timeOutMs == 0) + timeOutMs = 30000; - return new HTTPStream (connection, statusCode, responseHeaders); - } - catch (Throwable e) + // headers - if not empty, this string is appended onto the headers that are used for the request. It must therefore be a valid set of HTML header directives, separated by newlines. + // So convert headers string to an array, with an element for each line + String headerLines[] = headers.split("\\n"); + + for (;;) + { + try + { + HttpURLConnection connection = (HttpURLConnection) (new URL(address).openConnection()); + + if (connection != null) { - connection.disconnect(); + try + { + connection.setInstanceFollowRedirects (false); + connection.setConnectTimeout (timeOutMs); + connection.setReadTimeout (timeOutMs); + + // Set request headers + for (int i = 0; i < headerLines.length; ++i) + { + int pos = headerLines[i].indexOf (":"); + + if (pos > 0 && pos < headerLines[i].length()) + { + String field = headerLines[i].substring (0, pos); + String value = headerLines[i].substring (pos + 1); + + if (value.length() > 0) + connection.setRequestProperty (field, value); + } + } + + if (isPost) + { + connection.setRequestMethod ("POST"); + connection.setDoOutput (true); + + if (postData != null) + { + OutputStream out = connection.getOutputStream(); + out.write(postData); + out.flush(); + } + } + + HTTPStream httpStream = new HTTPStream (connection, statusCode, responseHeaders); + + // Process redirect & continue as necessary + int status = statusCode[0]; + + if (--numRedirectsToFollow >= 0 + && (status == 301 || status == 302 || status == 303 || status == 307)) + { + // Assumes only one occurrence of "Location" + int pos1 = responseHeaders.indexOf ("Location:") + 10; + int pos2 = responseHeaders.indexOf ("\n", pos1); + + if (pos2 > pos1) + { + String newLocation = responseHeaders.substring(pos1, pos2); + // Handle newLocation whether it's absolute or relative + URL baseUrl = new URL (address); + URL newUrl = new URL (baseUrl, newLocation); + String transformedNewLocation = newUrl.toString(); + + if (transformedNewLocation != address) + { + address = transformedNewLocation; + // Clear responseHeaders before next iteration + responseHeaders.delete (0, responseHeaders.length()); + continue; + } + } + } + + return httpStream; + } + catch (Throwable e) + { + connection.disconnect(); + } } } - } - catch (Throwable e) {} + catch (Throwable e) {} - return null; + return null; + } } public final void launchURL (String url) @@ -743,4 +844,85 @@ public final class JuceAppActivity extends Activity { new SingleMediaScanner (this, filename); } + + public final Typeface getTypeFaceFromAsset (String assetName) + { + try + { + return Typeface.createFromAsset (this.getResources().getAssets(), assetName); + } + catch (Throwable e) {} + + return null; + } + + final protected static char[] hexArray = "0123456789ABCDEF".toCharArray(); + + public static String bytesToHex (byte[] bytes) + { + char[] hexChars = new char[bytes.length * 2]; + + for (int j = 0; j < bytes.length; ++j) + { + int v = bytes[j] & 0xff; + hexChars[j * 2] = hexArray[v >>> 4]; + hexChars[j * 2 + 1] = hexArray[v & 0x0f]; + } + + return new String (hexChars); + } + + final private java.util.Map dataCache = new java.util.HashMap(); + + synchronized private final File getDataCacheFile (byte[] data) + { + try + { + java.security.MessageDigest digest = java.security.MessageDigest.getInstance ("MD5"); + digest.update (data); + + String key = bytesToHex (digest.digest()); + + if (dataCache.containsKey (key)) + return (File) dataCache.get (key); + + File f = new File (this.getCacheDir(), "bindata_" + key); + f.delete(); + FileOutputStream os = new FileOutputStream (f); + os.write (data, 0, data.length); + dataCache.put (key, f); + return f; + } + catch (Throwable e) {} + + return null; + } + + private final void clearDataCache() + { + java.util.Iterator it = dataCache.values().iterator(); + + while (it.hasNext()) + { + File f = (File) it.next(); + f.delete(); + } + } + + public final Typeface getTypeFaceFromByteArray (byte[] data) + { + try + { + File f = getDataCacheFile (data); + + if (f != null) + return Typeface.createFromFile (f); + } + catch (Exception e) + { + Log.e ("JUCE", e.toString()); + } + + return null; + } } diff --git a/JuceLibraryCode/modules/juce_core/native/juce_BasicNativeHeaders.h b/JuceLibraryCode/modules/juce_core/native/juce_BasicNativeHeaders.h index cdaa0ef..c0b07bd 100644 --- a/JuceLibraryCode/modules/juce_core/native/juce_BasicNativeHeaders.h +++ b/JuceLibraryCode/modules/juce_core/native/juce_BasicNativeHeaders.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this diff --git a/JuceLibraryCode/modules/juce_core/native/juce_android_Files.cpp b/JuceLibraryCode/modules/juce_core/native/juce_android_Files.cpp index 45903b1..591c4dc 100644 --- a/JuceLibraryCode/modules/juce_core/native/juce_android_Files.cpp +++ b/JuceLibraryCode/modules/juce_core/native/juce_android_Files.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this diff --git a/JuceLibraryCode/modules/juce_core/native/juce_android_JNIHelpers.h b/JuceLibraryCode/modules/juce_core/native/juce_android_JNIHelpers.h index 044679e..9149441 100644 --- a/JuceLibraryCode/modules/juce_core/native/juce_android_JNIHelpers.h +++ b/JuceLibraryCode/modules/juce_core/native/juce_android_JNIHelpers.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this @@ -227,8 +227,14 @@ private: //============================================================================== +#if defined (__arm__) + #define JUCE_ARM_SOFT_FLOAT_ABI __attribute__ ((pcs("aapcs"))) +#else + #define JUCE_ARM_SOFT_FLOAT_ABI +#endif + #define JUCE_JNI_CALLBACK(className, methodName, returnType, params) \ - extern "C" __attribute__ ((visibility("default"))) returnType JUCE_JOIN_MACRO (JUCE_JOIN_MACRO (Java_, className), _ ## methodName) params + extern "C" __attribute__ ((visibility("default"))) JUCE_ARM_SOFT_FLOAT_ABI returnType JUCE_JOIN_MACRO (JUCE_JOIN_MACRO (Java_, className), _ ## methodName) params //============================================================================== class AndroidSystem @@ -271,26 +277,43 @@ public: JNIEnv* attach() noexcept { - if (JNIEnv* env = attachToCurrentThread()) + if (android.activity != nullptr) { - SpinLock::ScopedLockType sl (addRemoveLock); - return addEnv (env); + if (JNIEnv* env = attachToCurrentThread()) + { + SpinLock::ScopedLockType sl (addRemoveLock); + return addEnv (env); + } + + jassertfalse; } - jassertfalse; return nullptr; } void detach() noexcept { - jvm->DetachCurrentThread(); + if (android.activity != nullptr) + { + jvm->DetachCurrentThread(); + removeCurrentThreadFromCache(); + } + } + void removeCurrentThreadFromCache() + { const pthread_t thisThread = pthread_self(); SpinLock::ScopedLockType sl (addRemoveLock); + for (int i = 0; i < maxThreads; ++i) + { if (threads[i] == thisThread) + { threads[i] = 0; + envs[i] = nullptr; + } + } } JNIEnv* getOrAttach() noexcept @@ -355,23 +378,32 @@ private: extern ThreadLocalJNIEnvHolder threadLocalJNIEnvHolder; +struct AndroidThreadScope +{ + AndroidThreadScope() { threadLocalJNIEnvHolder.attach(); } + ~AndroidThreadScope() { threadLocalJNIEnvHolder.detach(); } +}; + //============================================================================== #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD) \ METHOD (createNewView, "createNewView", "(ZJ)L" JUCE_ANDROID_ACTIVITY_CLASSPATH "$ComponentPeerView;") \ METHOD (deleteView, "deleteView", "(L" JUCE_ANDROID_ACTIVITY_CLASSPATH "$ComponentPeerView;)V") \ + METHOD (deleteOpenGLView, "deleteOpenGLView", "(L" JUCE_ANDROID_ACTIVITY_CLASSPATH "$OpenGLView;)V") \ METHOD (postMessage, "postMessage", "(J)V") \ METHOD (finish, "finish", "()V") \ METHOD (getClipboardContent, "getClipboardContent", "()Ljava/lang/String;") \ METHOD (setClipboardContent, "setClipboardContent", "(Ljava/lang/String;)V") \ METHOD (excludeClipRegion, "excludeClipRegion", "(Landroid/graphics/Canvas;FFFF)V") \ METHOD (renderGlyph, "renderGlyph", "(CLandroid/graphics/Paint;Landroid/graphics/Matrix;Landroid/graphics/Rect;)[I") \ - STATICMETHOD (createHTTPStream, "createHTTPStream", "(Ljava/lang/String;Z[BLjava/lang/String;I[ILjava/lang/StringBuffer;)L" JUCE_ANDROID_ACTIVITY_CLASSPATH "$HTTPStream;") \ + STATICMETHOD (createHTTPStream, "createHTTPStream", "(Ljava/lang/String;Z[BLjava/lang/String;I[ILjava/lang/StringBuffer;I)L" JUCE_ANDROID_ACTIVITY_CLASSPATH "$HTTPStream;") \ METHOD (launchURL, "launchURL", "(Ljava/lang/String;)V") \ METHOD (showMessageBox, "showMessageBox", "(Ljava/lang/String;Ljava/lang/String;J)V") \ METHOD (showOkCancelBox, "showOkCancelBox", "(Ljava/lang/String;Ljava/lang/String;J)V") \ METHOD (showYesNoCancelBox, "showYesNoCancelBox", "(Ljava/lang/String;Ljava/lang/String;J)V") \ STATICMETHOD (getLocaleValue, "getLocaleValue", "(Z)Ljava/lang/String;") \ - METHOD (scanFile, "scanFile", "(Ljava/lang/String;)V") + METHOD (scanFile, "scanFile", "(Ljava/lang/String;)V") \ + METHOD (getTypeFaceFromAsset, "getTypeFaceFromAsset", "(Ljava/lang/String;)Landroid/graphics/Typeface;") \ + METHOD (getTypeFaceFromByteArray,"getTypeFaceFromByteArray","([B)Landroid/graphics/Typeface;") DECLARE_JNI_CLASS (JuceAppActivity, JUCE_ANDROID_ACTIVITY_CLASSPATH); #undef JNI_CLASS_MEMBERS diff --git a/JuceLibraryCode/modules/juce_core/native/juce_android_Misc.cpp b/JuceLibraryCode/modules/juce_core/native/juce_android_Misc.cpp index d26adc1..3333112 100644 --- a/JuceLibraryCode/modules/juce_core/native/juce_android_Misc.cpp +++ b/JuceLibraryCode/modules/juce_core/native/juce_android_Misc.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this diff --git a/JuceLibraryCode/modules/juce_core/native/juce_android_Network.cpp b/JuceLibraryCode/modules/juce_core/native/juce_android_Network.cpp index 1b86dee..dd2278c 100644 --- a/JuceLibraryCode/modules/juce_core/native/juce_android_Network.cpp +++ b/JuceLibraryCode/modules/juce_core/native/juce_android_Network.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this @@ -70,7 +70,7 @@ class WebInputStream : public InputStream public: WebInputStream (String address, bool isPost, const MemoryBlock& postData, URL::OpenStreamProgressCallback* progressCallback, void* progressCallbackContext, - const String& headers, int timeOutMs, StringPairArray* responseHeaders) + const String& headers, int timeOutMs, StringPairArray* responseHeaders, const int numRedirectsToFollow) : statusCode (0) { if (! address.contains ("://")) @@ -103,7 +103,8 @@ public: javaString (headers).get(), (jint) timeOutMs, statusCodeArray, - responseHeaderBuffer.get())); + responseHeaderBuffer.get(), + (jint) numRedirectsToFollow)); jint* const statusCodeElements = env->GetIntArrayElements (statusCodeArray, 0); statusCode = statusCodeElements[0]; @@ -166,7 +167,7 @@ public: int numBytes = stream.callIntMethod (HTTPStream.read, javaArray, (jint) bytesToRead); if (numBytes > 0) - env->GetByteArrayRegion (javaArray, 0, numBytes, static_cast (buffer)); + env->GetByteArrayRegion (javaArray, 0, numBytes, static_cast (buffer)); env->DeleteLocalRef (javaArray); return numBytes; diff --git a/JuceLibraryCode/modules/juce_core/native/juce_android_SystemStats.cpp b/JuceLibraryCode/modules/juce_core/native/juce_android_SystemStats.cpp index 8223b89..07facfc 100644 --- a/JuceLibraryCode/modules/juce_core/native/juce_android_SystemStats.cpp +++ b/JuceLibraryCode/modules/juce_core/native/juce_android_SystemStats.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this @@ -278,7 +278,7 @@ String SystemStats::getDisplayLanguage() { return getUserLanguage() + "-" + getU //============================================================================== void CPUInformation::initialise() noexcept { - numCpus = jmax (1, sysconf (_SC_NPROCESSORS_ONLN)); + numCpus = jmax ((int) 1, (int) sysconf (_SC_NPROCESSORS_ONLN)); } //============================================================================== diff --git a/JuceLibraryCode/modules/juce_core/native/juce_android_Threads.cpp b/JuceLibraryCode/modules/juce_core/native/juce_android_Threads.cpp index 981be9a..b601e97 100644 --- a/JuceLibraryCode/modules/juce_core/native/juce_android_Threads.cpp +++ b/JuceLibraryCode/modules/juce_core/native/juce_android_Threads.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this diff --git a/JuceLibraryCode/modules/juce_core/native/juce_linux_CommonFile.cpp b/JuceLibraryCode/modules/juce_core/native/juce_linux_CommonFile.cpp index 2ce98b3..924d5e9 100644 --- a/JuceLibraryCode/modules/juce_core/native/juce_linux_CommonFile.cpp +++ b/JuceLibraryCode/modules/juce_core/native/juce_linux_CommonFile.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this @@ -138,8 +138,8 @@ private: JUCE_DECLARE_NON_COPYABLE (Pimpl) }; -DirectoryIterator::NativeIterator::NativeIterator (const File& directory, const String& wildCard) - : pimpl (new DirectoryIterator::NativeIterator::Pimpl (directory, wildCard)) +DirectoryIterator::NativeIterator::NativeIterator (const File& directory, const String& wildCardStr) + : pimpl (new DirectoryIterator::NativeIterator::Pimpl (directory, wildCardStr)) { } diff --git a/JuceLibraryCode/modules/juce_core/native/juce_linux_Files.cpp b/JuceLibraryCode/modules/juce_core/native/juce_linux_Files.cpp index d0dd54d..ede4e5e 100644 --- a/JuceLibraryCode/modules/juce_core/native/juce_linux_Files.cpp +++ b/JuceLibraryCode/modules/juce_core/native/juce_linux_Files.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this @@ -150,7 +150,10 @@ File File::getSpecialLocation (const SpecialLocationType type) case currentExecutableFile: case currentApplicationFile: + #if ! JUCE_STANDALONE_APPLICATION return juce_getExecutableFile(); + #endif + // deliberate fall-through if this is not a shared-library case hostApplicationPath: { diff --git a/JuceLibraryCode/modules/juce_core/native/juce_linux_Network.cpp b/JuceLibraryCode/modules/juce_core/native/juce_linux_Network.cpp index 7543a77..951ef9f 100644 --- a/JuceLibraryCode/modules/juce_core/native/juce_linux_Network.cpp +++ b/JuceLibraryCode/modules/juce_core/native/juce_linux_Network.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this @@ -31,26 +31,26 @@ void MACAddress::findAllAddresses (Array& result) const int s = socket (AF_INET, SOCK_DGRAM, 0); if (s != -1) { - char buf [1024]; - struct ifconf ifc; - ifc.ifc_len = sizeof (buf); - ifc.ifc_buf = buf; - ioctl (s, SIOCGIFCONF, &ifc); + struct ifaddrs* addrs = nullptr; - for (unsigned int i = 0; i < ifc.ifc_len / sizeof (struct ifreq); ++i) + if (getifaddrs (&addrs) != -1) { - struct ifreq ifr; - strcpy (ifr.ifr_name, ifc.ifc_req[i].ifr_name); - - if (ioctl (s, SIOCGIFFLAGS, &ifr) == 0 - && (ifr.ifr_flags & IFF_LOOPBACK) == 0 - && ioctl (s, SIOCGIFHWADDR, &ifr) == 0) + for (struct ifaddrs* i = addrs; i != nullptr; i = i->ifa_next) { - MACAddress ma ((const uint8*) ifr.ifr_hwaddr.sa_data); + struct ifreq ifr; + strcpy (ifr.ifr_name, i->ifa_name); + ifr.ifr_addr.sa_family = AF_INET; - if (! ma.isNull()) - result.addIfNotAlreadyThere (ma); + if (ioctl (s, SIOCGIFHWADDR, &ifr) == 0) + { + MACAddress ma ((const uint8*) ifr.ifr_hwaddr.sa_data); + + if (! ma.isNull()) + result.addIfNotAlreadyThere (ma); + } } + + freeifaddrs (addrs); } close (s); @@ -67,19 +67,21 @@ bool JUCE_CALLTYPE Process::openEmailWithAttachments (const String& /* targetEma return false; } - //============================================================================== +#if ! JUCE_USE_CURL class WebInputStream : public InputStream { public: WebInputStream (const String& address_, bool isPost_, const MemoryBlock& postData_, URL::OpenStreamProgressCallback* progressCallback, void* progressCallbackContext, - const String& headers_, int timeOutMs_, StringPairArray* responseHeaders) + const String& headers_, int timeOutMs_, StringPairArray* responseHeaders, + const int maxRedirects) : statusCode (0), socketHandle (-1), levelsOfRedirection (0), - address (address_), headers (headers_), postData (postData_), position (0), - finished (false), isPost (isPost_), timeOutMs (timeOutMs_) + address (address_), headers (headers_), postData (postData_), contentLength (-1), position (0), + finished (false), isPost (isPost_), timeOutMs (timeOutMs_), numRedirectsToFollow (maxRedirects), + chunkEnd (0), isChunked (false), readingChunk (false) { - statusCode = createConnection (progressCallback, progressCallbackContext); + statusCode = createConnection (progressCallback, progressCallbackContext, numRedirectsToFollow); if (responseHeaders != nullptr && ! isError()) { @@ -103,18 +105,63 @@ public: bool isError() const { return socketHandle < 0; } bool isExhausted() override { return finished; } int64 getPosition() override { return position; } - - int64 getTotalLength() override - { - //xxx to do - return -1; - } + int64 getTotalLength() override { return contentLength; } int read (void* buffer, int bytesToRead) override { if (finished || isError()) return 0; + if (isChunked && ! readingChunk) + { + if (position >= chunkEnd) + { + const ScopedValueSetter setter (readingChunk, true, false); + MemoryOutputStream chunkLengthBuffer; + char c = 0; + + if (chunkEnd > 0) + { + if (read (&c, 1) != 1 || c != '\r' + || read (&c, 1) != 1 || c != '\n') + { + finished = true; + return 0; + } + } + + while (chunkLengthBuffer.getDataSize() < 512 && ! (finished || isError())) + { + if (read (&c, 1) != 1) + { + finished = true; + return 0; + } + + if (c == '\r') + continue; + + if (c == '\n') + break; + + chunkLengthBuffer.writeByte (c); + } + + const int64 chunkSize = chunkLengthBuffer.toString().trimStart().getHexValue64(); + + if (chunkSize == 0) + { + finished = true; + return 0; + } + + chunkEnd += chunkSize; + } + + if (bytesToRead > chunkEnd - position) + bytesToRead = chunkEnd - position; + } + fd_set readbits; FD_ZERO (&readbits); FD_SET (socketHandle, &readbits); @@ -126,11 +173,13 @@ public: if (select (socketHandle + 1, &readbits, 0, 0, &tv) <= 0) return 0; // (timeout) - const int bytesRead = jmax (0, (int) recv (socketHandle, buffer, bytesToRead, MSG_WAITALL)); + const int bytesRead = jmax (0, (int) recv (socketHandle, buffer, (size_t) bytesToRead, MSG_WAITALL)); if (bytesRead == 0) finished = true; - position += bytesRead; + if (! readingChunk) + position += bytesRead; + return bytesRead; } @@ -147,7 +196,7 @@ public: { closeSocket(); position = 0; - statusCode = createConnection (0, 0); + statusCode = createConnection (0, 0, numRedirectsToFollow); } skipNextBytes (wantedPos - position); @@ -164,32 +213,37 @@ private: StringArray headerLines; String address, headers; MemoryBlock postData; - int64 position; + int64 contentLength, position; bool finished; const bool isPost; const int timeOutMs; + const int numRedirectsToFollow; + int64 chunkEnd; + bool isChunked, readingChunk; - void closeSocket() + void closeSocket (bool resetLevelsOfRedirection = true) { if (socketHandle >= 0) close (socketHandle); socketHandle = -1; - levelsOfRedirection = 0; + if (resetLevelsOfRedirection) + levelsOfRedirection = 0; } - int createConnection (URL::OpenStreamProgressCallback* progressCallback, void* progressCallbackContext) + int createConnection (URL::OpenStreamProgressCallback* progressCallback, void* progressCallbackContext, + const int numRedirects) { - closeSocket(); + closeSocket (false); uint32 timeOutTime = Time::getMillisecondCounter(); if (timeOutMs == 0) - timeOutTime += 60000; + timeOutTime += 30000; else if (timeOutMs < 0) timeOutTime = 0xffffffff; else - timeOutTime += timeOutMs; + timeOutTime += (uint32) timeOutMs; String hostName, hostPath; int hostPort; @@ -263,7 +317,7 @@ private: } } - String responseHeader (readResponse (socketHandle, timeOutTime)); + String responseHeader (readResponse (timeOutTime)); position = 0; if (responseHeader.isNotEmpty()) @@ -273,28 +327,35 @@ private: const int status = responseHeader.fromFirstOccurrenceOf (" ", false, false) .substring (0, 3).getIntValue(); - //int contentLength = findHeaderItem (lines, "Content-Length:").getIntValue(); - //bool isChunked = findHeaderItem (lines, "Transfer-Encoding:").equalsIgnoreCase ("chunked"); - String location (findHeaderItem (headerLines, "Location:")); - if (status >= 300 && status < 400 + if (++levelsOfRedirection <= numRedirects + && status >= 300 && status < 400 && location.isNotEmpty() && location != address) { - if (! location.startsWithIgnoreCase ("http://")) - location = "http://" + location; - - if (++levelsOfRedirection <= 3) + if (! (location.startsWithIgnoreCase ("http://") + || location.startsWithIgnoreCase ("https://") + || location.startsWithIgnoreCase ("ftp://"))) { - address = location; - return createConnection (progressCallback, progressCallbackContext); + // The following is a bit dodgy. Ideally, we should do a proper transform of the relative URI to a target URI + if (location.startsWithChar ('/')) + location = URL (address).withNewSubPath (location).toString (true); + else + location = address + "/" + location; } + + address = location; + return createConnection (progressCallback, progressCallbackContext, numRedirects); } - else - { - levelsOfRedirection = 0; - return status; - } + + String contentLengthString (findHeaderItem (headerLines, "Content-Length:")); + + if (contentLengthString.isNotEmpty()) + contentLength = contentLengthString.getLargeIntValue(); + + isChunked = (findHeaderItem (headerLines, "Transfer-Encoding:") == "chunked"); + + return status; } closeSocket(); @@ -302,7 +363,7 @@ private: } //============================================================================== - String readResponse (const int socketHandle, const uint32 timeOutTime) + String readResponse (const uint32 timeOutTime) { int numConsecutiveLFs = 0; MemoryOutputStream buffer; @@ -338,9 +399,14 @@ private: dest << "\r\n" << key << ' ' << value; } - static void writeHost (MemoryOutputStream& dest, const bool isPost, const String& path, const String& host, const int port) + static void writeHost (MemoryOutputStream& dest, const bool isPost, + const String& path, const String& host, int port) { - dest << (isPost ? "POST " : "GET ") << path << " HTTP/1.0\r\nHost: " << host; + dest << (isPost ? "POST " : "GET ") << path << " HTTP/1.1\r\nHost: " << host; + + /* HTTP spec 14.23 says that the port number must be included in the header if it is not 80 */ + if (port != 80) + dest << ':' << port; } static MemoryBlock createRequestHeader (const String& hostName, const int hostPort, @@ -362,10 +428,14 @@ private: writeValueIfNotPresent (header, userHeaders, "Connection:", "close"); if (isPost) + { writeValueIfNotPresent (header, userHeaders, "Content-Length:", String ((int) postData.getSize())); - - header << "\r\n" << userHeaders - << "\r\n" << postData; + header << userHeaders << "\r\n" << postData; + } + else + { + header << "\r\n" << userHeaders << "\r\n"; + } return header.getMemoryBlock(); } @@ -382,12 +452,12 @@ private: const int numToSend = jmin (1024, (int) (requestHeader.getSize() - totalHeaderSent)); - if (send (socketHandle, static_cast (requestHeader.getData()) + totalHeaderSent, numToSend, 0) != numToSend) + if (send (socketHandle, static_cast (requestHeader.getData()) + totalHeaderSent, (size_t) numToSend, 0) != numToSend) return false; - totalHeaderSent += numToSend; + totalHeaderSent += (size_t) numToSend; - if (progressCallback != nullptr && ! progressCallback (progressCallbackContext, totalHeaderSent, requestHeader.getSize())) + if (progressCallback != nullptr && ! progressCallback (progressCallbackContext, (int) totalHeaderSent, (int) requestHeader.getSize())) return false; } @@ -442,3 +512,4 @@ private: JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (WebInputStream) }; +#endif diff --git a/JuceLibraryCode/modules/juce_core/native/juce_linux_SystemStats.cpp b/JuceLibraryCode/modules/juce_core/native/juce_linux_SystemStats.cpp index 939edb4..9ac6901 100644 --- a/JuceLibraryCode/modules/juce_core/native/juce_linux_SystemStats.cpp +++ b/JuceLibraryCode/modules/juce_core/native/juce_linux_SystemStats.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this @@ -55,10 +55,10 @@ bool SystemStats::isOperatingSystem64Bit() //============================================================================== namespace LinuxStatsHelpers { - String getCpuInfo (const char* const key) + String getConfigFileValue (const char* file, const char* const key) { StringArray lines; - File ("/proc/cpuinfo").readLines (lines); + File (file).readLines (lines); for (int i = lines.size(); --i >= 0;) // (NB - it's important that this runs in reverse order) if (lines[i].upToFirstOccurrenceOf (":", false, false).trim().equalsIgnoreCase (key)) @@ -66,6 +66,11 @@ namespace LinuxStatsHelpers return String(); } + + String getCpuInfo (const char* key) + { + return getConfigFileValue ("/proc/cpuinfo", key); + } } String SystemStats::getDeviceDescription() @@ -93,14 +98,14 @@ int SystemStats::getMemorySizeInMegabytes() struct sysinfo sysi; if (sysinfo (&sysi) == 0) - return sysi.totalram * sysi.mem_unit / (1024 * 1024); + return (int) (sysi.totalram * sysi.mem_unit / (1024 * 1024)); return 0; } int SystemStats::getPageSize() { - return sysconf (_SC_PAGESIZE); + return (int) sysconf (_SC_PAGESIZE); } //============================================================================== @@ -150,6 +155,8 @@ void CPUInformation::initialise() noexcept hasSSE2 = flags.contains ("sse2"); hasSSE3 = flags.contains ("sse3"); has3DNow = flags.contains ("3dnow"); + hasSSSE3 = flags.contains ("ssse3"); + hasAVX = flags.contains ("avx"); numCpus = LinuxStatsHelpers::getCpuInfo ("processor").getIntValue() + 1; } @@ -160,7 +167,7 @@ uint32 juce_millisecondsSinceStartup() noexcept timespec t; clock_gettime (CLOCK_MONOTONIC, &t); - return t.tv_sec * 1000 + t.tv_nsec / 1000000; + return (uint32) (t.tv_sec * 1000 + t.tv_nsec / 1000000); } int64 Time::getHighResolutionTicks() noexcept @@ -189,3 +196,13 @@ bool Time::setSystemTimeToThisTime() const return settimeofday (&t, 0) == 0; } + +JUCE_API bool JUCE_CALLTYPE juce_isRunningUnderDebugger() +{ + #if JUCE_BSD + return false; + #else + return LinuxStatsHelpers::getConfigFileValue ("/proc/self/status", "TracerPid") + .getIntValue() > 0; + #endif +} diff --git a/JuceLibraryCode/modules/juce_core/native/juce_linux_Threads.cpp b/JuceLibraryCode/modules/juce_core/native/juce_linux_Threads.cpp index a75094a..b9d3d45 100644 --- a/JuceLibraryCode/modules/juce_core/native/juce_linux_Threads.cpp +++ b/JuceLibraryCode/modules/juce_core/native/juce_linux_Threads.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this @@ -52,37 +52,16 @@ JUCE_API void JUCE_CALLTYPE Process::setPriority (const ProcessPriority prior) pthread_setschedparam (pthread_self(), policy, ¶m); } -JUCE_API bool JUCE_CALLTYPE juce_isRunningUnderDebugger() -{ - #if JUCE_BSD - return false; - #else - static char testResult = 0; - - if (testResult == 0) - { - testResult = (char) ptrace (PT_TRACE_ME, 0, 0, 0); - - if (testResult >= 0) - { - ptrace (PT_DETACH, 0, (caddr_t) 1, 0); - testResult = 1; - } - } - - return testResult < 0; - #endif -} - JUCE_API bool JUCE_CALLTYPE Process::isRunningUnderDebugger() { return juce_isRunningUnderDebugger(); } -static void swapUserAndEffectiveUser() +static bool swapUserAndEffectiveUser() { - (void) setreuid (geteuid(), getuid()); - (void) setregid (getegid(), getgid()); + int result1 = setreuid (geteuid(), getuid()); + int result2 = setregid (getegid(), getgid()); + return result1 == 0 && result2 == 0; } JUCE_API void JUCE_CALLTYPE Process::raisePrivilege() { if (geteuid() != 0 && getuid() == 0) swapUserAndEffectiveUser(); } diff --git a/JuceLibraryCode/modules/juce_core/native/juce_mac_Files.mm b/JuceLibraryCode/modules/juce_core/native/juce_mac_Files.mm index 0a00e92..afe4e7b 100644 --- a/JuceLibraryCode/modules/juce_core/native/juce_mac_Files.mm +++ b/JuceLibraryCode/modules/juce_core/native/juce_mac_Files.mm @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this diff --git a/JuceLibraryCode/modules/juce_core/native/juce_mac_Network.mm b/JuceLibraryCode/modules/juce_core/native/juce_mac_Network.mm index 130759e..d4da1cf 100644 --- a/JuceLibraryCode/modules/juce_core/native/juce_mac_Network.mm +++ b/JuceLibraryCode/modules/juce_core/native/juce_mac_Network.mm @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this @@ -115,7 +115,7 @@ bool JUCE_CALLTYPE Process::openEmailWithAttachments (const String& targetEmailA class URLConnectionState : public Thread { public: - URLConnectionState (NSURLRequest* req) + URLConnectionState (NSURLRequest* req, const int maxRedirects) : Thread ("http connection"), contentLength (-1), delegate (nil), @@ -126,7 +126,10 @@ public: statusCode (0), initialised (false), hasFailed (false), - hasFinished (false) + hasFinished (false), + numRedirectsToFollow (maxRedirects), + numRedirects (0), + latestTotalBytes (0) { static DelegateClass cls; delegate = [cls.createInstance() init]; @@ -150,7 +153,7 @@ public: while (isThreadRunning() && ! initialised) { if (callback != nullptr) - callback (context, -1, (int) [[request HTTPBody] length]); + callback (context, latestTotalBytes, (int) [[request HTTPBody] length]); Thread::sleep (1); } @@ -201,7 +204,6 @@ public: [data setLength: 0]; } - initialised = true; contentLength = [response expectedContentLength]; [headers release]; @@ -213,6 +215,21 @@ public: headers = [[httpResponse allHeaderFields] retain]; statusCode = (int) [httpResponse statusCode]; } + + initialised = true; + } + + NSURLRequest* willSendRequest (NSURLRequest* newRequest, NSURLResponse* redirectResponse) + { + if (redirectResponse != nullptr) + { + if (numRedirects >= numRedirectsToFollow) + return nil; // Cancel redirect and allow connection to continue + + ++numRedirects; + } + + return newRequest; } void didFailWithError (NSError* error) @@ -230,8 +247,9 @@ public: initialised = true; } - void didSendBodyData (NSInteger /*totalBytesWritten*/, NSInteger /*totalBytesExpected*/) + void didSendBodyData (NSInteger totalBytesWritten, NSInteger /*totalBytesExpected*/) { + latestTotalBytes = static_cast (totalBytesWritten); } void finishedLoading() @@ -263,6 +281,9 @@ public: NSDictionary* headers; int statusCode; bool initialised, hasFailed, hasFinished; + const int numRedirectsToFollow; + int numRedirects; + int latestTotalBytes; private: //============================================================================== @@ -278,7 +299,7 @@ private: addMethod (@selector (connection:didSendBodyData:totalBytesWritten:totalBytesExpectedToWrite:), connectionDidSendBodyData, "v@:@iii"); addMethod (@selector (connectionDidFinishLoading:), connectionDidFinishLoading, "v@:@"); - addMethod (@selector (connection:willSendRequest:redirectResponse:), willSendRequest, "@@:@@"); + addMethod (@selector (connection:willSendRequest:redirectResponse:), willSendRequest, "@@:@@@"); registerClass(); } @@ -302,9 +323,9 @@ private: getState (self)->didReceiveData (newData); } - static NSURLRequest* willSendRequest (id, SEL, NSURLConnection*, NSURLRequest* request, NSURLResponse*) + static NSURLRequest* willSendRequest (id self, SEL, NSURLConnection*, NSURLRequest* request, NSURLResponse* response) { - return request; + return getState (self)->willSendRequest (request, response); } static void connectionDidSendBodyData (id self, SEL, NSURLConnection*, NSInteger, NSInteger totalBytesWritten, NSInteger totalBytesExpected) @@ -328,23 +349,27 @@ class WebInputStream : public InputStream public: WebInputStream (const String& address_, bool isPost_, const MemoryBlock& postData_, URL::OpenStreamProgressCallback* progressCallback, void* progressCallbackContext, - const String& headers_, int timeOutMs_, StringPairArray* responseHeaders) + const String& headers_, int timeOutMs_, StringPairArray* responseHeaders, + const int numRedirectsToFollow_) : statusCode (0), address (address_), headers (headers_), postData (postData_), position (0), - finished (false), isPost (isPost_), timeOutMs (timeOutMs_) + finished (false), isPost (isPost_), timeOutMs (timeOutMs_), numRedirectsToFollow (numRedirectsToFollow_) { JUCE_AUTORELEASEPOOL { createConnection (progressCallback, progressCallbackContext); - if (responseHeaders != nullptr && connection != nullptr && connection->headers != nil) + if (connection != nullptr && connection->headers != nil) { statusCode = connection->statusCode; - NSEnumerator* enumerator = [connection->headers keyEnumerator]; + if (responseHeaders != nullptr) + { + NSEnumerator* enumerator = [connection->headers keyEnumerator]; - while (NSString* key = [enumerator nextObject]) - responseHeaders->set (nsStringToJuce (key), - nsStringToJuce ((NSString*) [connection->headers objectForKey: key])); + while (NSString* key = [enumerator nextObject]) + responseHeaders->set (nsStringToJuce (key), + nsStringToJuce ((NSString*) [connection->headers objectForKey: key])); + } } } } @@ -403,6 +428,7 @@ private: bool finished; const bool isPost; const int timeOutMs; + const int numRedirectsToFollow; void createConnection (URL::OpenStreamProgressCallback* progressCallback, void* progressCallbackContext) { @@ -434,7 +460,7 @@ private: [req setHTTPBody: [NSData dataWithBytes: postData.getData() length: postData.getSize()]]; - connection = new URLConnectionState (req); + connection = new URLConnectionState (req, numRedirectsToFollow); if (! connection->start (progressCallback, progressCallbackContext)) connection = nullptr; diff --git a/JuceLibraryCode/modules/juce_core/native/juce_mac_Strings.mm b/JuceLibraryCode/modules/juce_core/native/juce_mac_Strings.mm index 862eb53..53341e0 100644 --- a/JuceLibraryCode/modules/juce_core/native/juce_mac_Strings.mm +++ b/JuceLibraryCode/modules/juce_core/native/juce_mac_Strings.mm @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this @@ -32,17 +32,21 @@ String String::fromCFString (CFStringRef cfString) return String(); CFRange range = { 0, CFStringGetLength (cfString) }; - HeapBlock u ((size_t) range.length + 1); - CFStringGetCharacters (cfString, range, u); - u[range.length] = 0; + CFIndex bytesNeeded = 0; + CFStringGetBytes (cfString, range, kCFStringEncodingUTF8, 0, false, nullptr, 0, &bytesNeeded); - return String (CharPointer_UTF16 ((const CharPointer_UTF16::CharType*) u.getData())); + HeapBlock utf8 ((size_t) bytesNeeded + 1); + CFStringGetBytes (cfString, range, kCFStringEncodingUTF8, 0, false, utf8, bytesNeeded + 1, nullptr); + + return String (CharPointer_UTF8 ((const CharPointer_UTF8::CharType*) utf8.getData()), + CharPointer_UTF8 ((const CharPointer_UTF8::CharType*) utf8.getData() + bytesNeeded)); } CFStringRef String::toCFString() const { - CharPointer_UTF16 utf16 (toUTF16()); - return CFStringCreateWithCharacters (kCFAllocatorDefault, (const UniChar*) utf16.getAddress(), (CFIndex) utf16.length()); + const char* const utf8 = toRawUTF8(); + return CFStringCreateWithBytes (kCFAllocatorDefault, (const UInt8*) utf8, + (CFIndex) strlen (utf8), kCFStringEncodingUTF8, false); } String String::convertToPrecomposedUnicode() const @@ -72,7 +76,7 @@ String String::convertToPrecomposedUnicode() const { const size_t bytesNeeded = CharPointer_UTF16::getBytesRequiredFor (getCharPointer()); - HeapBlock tempOut; + HeapBlock tempOut; tempOut.calloc (bytesNeeded + 4); ByteCount bytesRead = 0; diff --git a/JuceLibraryCode/modules/juce_core/native/juce_mac_SystemStats.mm b/JuceLibraryCode/modules/juce_core/native/juce_mac_SystemStats.mm index 2d49ae6..c1b4371 100644 --- a/JuceLibraryCode/modules/juce_core/native/juce_mac_SystemStats.mm +++ b/JuceLibraryCode/modules/juce_core/native/juce_mac_SystemStats.mm @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this @@ -80,6 +80,8 @@ void CPUInformation::initialise() noexcept hasSSE2 = (d & (1u << 26)) != 0; has3DNow = (b & (1u << 31)) != 0; hasSSE3 = (c & (1u << 0)) != 0; + hasSSSE3 = (c & (1u << 9)) != 0; + hasAVX = (c & (1u << 28)) != 0; #endif #if JUCE_IOS || (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5) diff --git a/JuceLibraryCode/modules/juce_core/native/juce_mac_Threads.mm b/JuceLibraryCode/modules/juce_core/native/juce_mac_Threads.mm index 004baeb..8150a15 100644 --- a/JuceLibraryCode/modules/juce_core/native/juce_mac_Threads.mm +++ b/JuceLibraryCode/modules/juce_core/native/juce_mac_Threads.mm @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this diff --git a/JuceLibraryCode/modules/juce_core/native/juce_osx_ObjCHelpers.h b/JuceLibraryCode/modules/juce_core/native/juce_osx_ObjCHelpers.h index e66aa2d..cc7c56a 100644 --- a/JuceLibraryCode/modules/juce_core/native/juce_osx_ObjCHelpers.h +++ b/JuceLibraryCode/modules/juce_core/native/juce_osx_ObjCHelpers.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this @@ -65,6 +65,15 @@ namespace static_cast (r.getWidth()), static_cast (r.getHeight())); } + + // These hacks are a workaround for newer Xcode builds which by default prevent calls to these objc functions.. + typedef id (*MsgSendSuperFn) (struct objc_super*, SEL, ...); + static inline MsgSendSuperFn getMsgSendSuperFn() noexcept { return (MsgSendSuperFn) (void*) objc_msgSendSuper; } + + #if ! JUCE_PPC + typedef double (*MsgSendFPRetFn) (id, SEL op, ...); + static inline MsgSendFPRetFn getMsgSendFPRetFn() noexcept { return (MsgSendFPRetFn) (void*) objc_msgSend_fpret; } + #endif #endif } @@ -140,11 +149,13 @@ struct ObjCClass jassert (b); (void) b; } -// static id sendSuperclassMessage (id self, SEL selector) -// { -// objc_super s = { self, [SuperclassType class] }; -// return objc_msgSendSuper (&s, selector); -// } + #if JUCE_MAC + static id sendSuperclassMessage (id self, SEL selector) + { + objc_super s = { self, [SuperclassType class] }; + return getMsgSendSuperFn() (&s, selector); + } + #endif template static Type getIvar (id self, const char* name) diff --git a/JuceLibraryCode/modules/juce_core/native/juce_posix_NamedPipe.cpp b/JuceLibraryCode/modules/juce_core/native/juce_posix_NamedPipe.cpp index d0c0b09..e0ca302 100644 --- a/JuceLibraryCode/modules/juce_core/native/juce_posix_NamedPipe.cpp +++ b/JuceLibraryCode/modules/juce_core/native/juce_posix_NamedPipe.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this diff --git a/JuceLibraryCode/modules/juce_core/native/juce_posix_SharedCode.h b/JuceLibraryCode/modules/juce_core/native/juce_posix_SharedCode.h index 5e0ba45..b6fff48 100644 --- a/JuceLibraryCode/modules/juce_core/native/juce_posix_SharedCode.h +++ b/JuceLibraryCode/modules/juce_core/native/juce_posix_SharedCode.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this @@ -223,6 +223,12 @@ namespace return statfs (f.getFullPathName().toUTF8(), &result) == 0; } + #if (JUCE_MAC && MAC_OS_X_VERSION_MIN_REQUIRED > MAC_OS_X_VERSION_10_5) || JUCE_IOS + static int64 getCreationTime (const juce_statStruct& s) noexcept { return (int64) s.st_birthtime; } + #else + static int64 getCreationTime (const juce_statStruct& s) noexcept { return (int64) s.st_ctime; } + #endif + void updateStatInfoForFile (const String& path, bool* const isDir, int64* const fileSize, Time* const modTime, Time* const creationTime, bool* const isReadOnly) { @@ -232,9 +238,9 @@ namespace const bool statOk = juce_stat (path, info); if (isDir != nullptr) *isDir = statOk && ((info.st_mode & S_IFDIR) != 0); - if (fileSize != nullptr) *fileSize = statOk ? info.st_size : 0; - if (modTime != nullptr) *modTime = Time (statOk ? (int64) info.st_mtime * 1000 : 0); - if (creationTime != nullptr) *creationTime = Time (statOk ? (int64) info.st_ctime * 1000 : 0); + if (fileSize != nullptr) *fileSize = statOk ? (int64) info.st_size : 0; + if (modTime != nullptr) *modTime = Time (statOk ? (int64) info.st_mtime * 1000 : 0); + if (creationTime != nullptr) *creationTime = Time (statOk ? getCreationTime (info) * 1000 : 0); } if (isReadOnly != nullptr) @@ -259,8 +265,8 @@ bool File::isDirectory() const { juce_statStruct info; - return fullPath.isEmpty() - || (juce_stat (fullPath, info) && ((info.st_mode & S_IFDIR) != 0)); + return fullPath.isNotEmpty() + && (juce_stat (fullPath, info) && ((info.st_mode & S_IFDIR) != 0)); } bool File::exists() const @@ -298,23 +304,33 @@ bool File::hasWriteAccess() const return false; } -bool File::setFileReadOnlyInternal (const bool shouldBeReadOnly) const +static bool setFileModeFlags (const String& fullPath, mode_t flags, bool shouldSet) noexcept { juce_statStruct info; if (! juce_stat (fullPath, info)) return false; - info.st_mode &= 0777; // Just permissions + info.st_mode &= 0777; - if (shouldBeReadOnly) - info.st_mode &= ~(S_IWUSR | S_IWGRP | S_IWOTH); + if (shouldSet) + info.st_mode |= flags; else - // Give everybody write permission? - info.st_mode |= S_IWUSR | S_IWGRP | S_IWOTH; + info.st_mode &= ~flags; return chmod (fullPath.toUTF8(), info.st_mode) == 0; } +bool File::setFileReadOnlyInternal (bool shouldBeReadOnly) const +{ + // Hmm.. should we give global write permission or just the current user? + return setFileModeFlags (fullPath, S_IWUSR | S_IWGRP | S_IWOTH, ! shouldBeReadOnly); +} + +bool File::setFileExecutableInternal (bool shouldBeExecutable) const +{ + return setFileModeFlags (fullPath, S_IXUSR | S_IXGRP | S_IXOTH, shouldBeExecutable); +} + void File::getFileTimesInternal (int64& modificationTime, int64& accessTime, int64& creationTime) const { modificationTime = 0; @@ -322,11 +338,12 @@ void File::getFileTimesInternal (int64& modificationTime, int64& accessTime, int creationTime = 0; juce_statStruct info; + if (juce_stat (fullPath, info)) { - modificationTime = (int64) info.st_mtime * 1000; - accessTime = (int64) info.st_atime * 1000; - creationTime = (int64) info.st_ctime * 1000; + modificationTime = (int64) info.st_mtime * 1000; + accessTime = (int64) info.st_atime * 1000; + creationTime = (int64) info.st_ctime * 1000; } } @@ -664,6 +681,7 @@ int File::getVolumeSerialNumber() const } //============================================================================== +#if ! JUCE_IOS void juce_runSystemCommand (const String&); void juce_runSystemCommand (const String& command) { @@ -684,7 +702,7 @@ String juce_getOutputFromCommand (const String& command) tempFile.deleteFile(); return result; } - +#endif //============================================================================== #if JUCE_IOS @@ -837,12 +855,6 @@ extern "C" void* threadEntryProc (void* userData) JUCE_AUTORELEASEPOOL { #if JUCE_ANDROID - struct AndroidThreadScope - { - AndroidThreadScope() { threadLocalJNIEnvHolder.attach(); } - ~AndroidThreadScope() { threadLocalJNIEnvHolder.detach(); } - }; - const AndroidThreadScope androidEnv; #endif @@ -949,22 +961,22 @@ void JUCE_CALLTYPE Thread::setCurrentThreadAffinityMask (const uint32 affinityMa if ((affinityMask & (1 << i)) != 0) CPU_SET (i, &affinity); - /* - N.B. If this line causes a compile error, then you've probably not got the latest - version of glibc installed. - - If you don't want to update your copy of glibc and don't care about cpu affinities, - then you can just disable all this stuff by setting the SUPPORT_AFFINITIES macro to 0. - */ + #if (! JUCE_ANDROID) && ((! JUCE_LINUX) || ((__GLIBC__ * 1000 + __GLIBC_MINOR__) >= 2004)) + pthread_setaffinity_np (pthread_self(), sizeof (cpu_set_t), &affinity); + #else + // NB: this call isn't really correct because it sets the affinity of the process, + // not the thread. But it's included here as a fallback for people who are using + // ridiculously old versions of glibc sched_setaffinity (getpid(), sizeof (cpu_set_t), &affinity); + #endif + sched_yield(); #else - /* affinities aren't supported because either the appropriate header files weren't found, - or the SUPPORT_AFFINITIES macro was turned off - */ + // affinities aren't supported because either the appropriate header files weren't found, + // or the SUPPORT_AFFINITIES macro was turned off jassertfalse; - (void) affinityMask; + ignoreUnused (affinityMask); #endif } @@ -1150,16 +1162,25 @@ struct HighResolutionTimer::Pimpl void start (int newPeriod) { - periodMs = newPeriod; - - if (thread == 0) + if (periodMs != newPeriod) { - shouldStop = false; + if (thread != pthread_self()) + { + stop(); - if (pthread_create (&thread, nullptr, timerThread, this) == 0) - setThreadToRealtime (thread, (uint64) newPeriod); + periodMs = newPeriod; + shouldStop = false; + + if (pthread_create (&thread, nullptr, timerThread, this) == 0) + setThreadToRealtime (thread, (uint64) newPeriod); + else + jassertfalse; + } else - jassertfalse; + { + periodMs = newPeriod; + shouldStop = false; + } } } @@ -1183,7 +1204,9 @@ private: static void* timerThread (void* param) { - #if ! JUCE_ANDROID + #if JUCE_ANDROID + const AndroidThreadScope androidEnv; + #else int dummy; pthread_setcancelstate (PTHREAD_CANCEL_ENABLE, &dummy); #endif @@ -1194,12 +1217,19 @@ private: void timerThread() { - Clock clock (periodMs); + int lastPeriod = periodMs; + Clock clock (lastPeriod); while (! shouldStop) { clock.wait(); owner.hiResTimerCallback(); + + if (lastPeriod != periodMs) + { + lastPeriod = periodMs; + clock = Clock (lastPeriod); + } } periodMs = 0; @@ -1244,7 +1274,7 @@ private: { struct timespec t; clock_gettime (CLOCK_MONOTONIC, &t); - time = 1000000000 * (int64) t.tv_sec + t.tv_nsec; + time = (uint64) (1000000000 * (int64) t.tv_sec + (int64) t.tv_nsec); } void wait() noexcept diff --git a/JuceLibraryCode/modules/juce_core/native/juce_win32_ComSmartPtr.h b/JuceLibraryCode/modules/juce_core/native/juce_win32_ComSmartPtr.h index 0dc0efc..10d5d20 100644 --- a/JuceLibraryCode/modules/juce_core/native/juce_win32_ComSmartPtr.h +++ b/JuceLibraryCode/modules/juce_core/native/juce_win32_ComSmartPtr.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this diff --git a/JuceLibraryCode/modules/juce_core/native/juce_win32_Files.cpp b/JuceLibraryCode/modules/juce_core/native/juce_win32_Files.cpp index 80ad084..143ea9e 100644 --- a/JuceLibraryCode/modules/juce_core/native/juce_win32_Files.cpp +++ b/JuceLibraryCode/modules/juce_core/native/juce_win32_Files.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this @@ -137,17 +137,22 @@ bool File::existsAsFile() const bool File::isDirectory() const { const DWORD attr = WindowsFileHelpers::getAtts (fullPath); - return ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0) && (attr != INVALID_FILE_ATTRIBUTES); + return (attr & FILE_ATTRIBUTE_DIRECTORY) != 0 && attr != INVALID_FILE_ATTRIBUTES; } bool File::hasWriteAccess() const { - if (exists()) - return (WindowsFileHelpers::getAtts (fullPath) & FILE_ATTRIBUTE_READONLY) == 0; + if (fullPath.isEmpty()) + return true; - // on windows, it seems that even read-only directories can still be written into, - // so checking the parent directory's permissions would return the wrong result.. - return true; + const DWORD attr = WindowsFileHelpers::getAtts (fullPath); + + // NB: According to MS, the FILE_ATTRIBUTE_READONLY attribute doesn't work for + // folders, and can be incorrectly set for some special folders, so we'll just say + // that folders are always writable. + return attr == INVALID_FILE_ATTRIBUTES + || (attr & FILE_ATTRIBUTE_DIRECTORY) != 0 + || (attr & FILE_ATTRIBUTE_READONLY) == 0; } bool File::setFileReadOnlyInternal (const bool shouldBeReadOnly) const @@ -163,6 +168,12 @@ bool File::setFileReadOnlyInternal (const bool shouldBeReadOnly) const || SetFileAttributes (fullPath.toWideCharPointer(), newAtts) != FALSE; } +bool File::setFileExecutableInternal (bool /*shouldBeExecutable*/) const +{ + // XXX is this possible? + return false; +} + bool File::isHidden() const { return (WindowsFileHelpers::getAtts (fullPath) & FILE_ATTRIBUTE_HIDDEN) != 0; @@ -554,6 +565,14 @@ File JUCE_CALLTYPE File::getSpecialLocation (const SpecialLocationType type) return File (String (dest)); } + case windowsSystemDirectory: + { + WCHAR dest [2048]; + dest[0] = 0; + GetSystemDirectoryW (dest, (UINT) numElementsInArray (dest)); + return File (String (dest)); + } + case invokedExecutableFile: case currentExecutableFile: case currentApplicationFile: @@ -776,18 +795,19 @@ public: connected (false), ownsPipe (createPipe), shouldStop (false) { if (createPipe) + { pipeH = CreateNamedPipe (filename.toWideCharPointer(), PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED, 0, PIPE_UNLIMITED_INSTANCES, 4096, 4096, 0, 0); + + if (GetLastError() == ERROR_ALREADY_EXISTS) + closePipeHandle(); + } } ~Pimpl() { - disconnectPipe(); - - if (pipeH != INVALID_HANDLE_VALUE) - CloseHandle (pipeH); - + closePipeHandle(); CloseHandle (cancelEvent); } @@ -849,6 +869,16 @@ public: } } + void closePipeHandle() + { + if (pipeH != INVALID_HANDLE_VALUE) + { + disconnectPipe(); + CloseHandle (pipeH); + pipeH = INVALID_HANDLE_VALUE; + } + } + int read (void* destBuffer, const int maxBytesToRead, const int timeOutMilliseconds) { while (connect (timeOutMilliseconds)) diff --git a/JuceLibraryCode/modules/juce_core/native/juce_win32_Network.cpp b/JuceLibraryCode/modules/juce_core/native/juce_win32_Network.cpp index e7af2c1..baf9957 100644 --- a/JuceLibraryCode/modules/juce_core/native/juce_win32_Network.cpp +++ b/JuceLibraryCode/modules/juce_core/native/juce_win32_Network.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this @@ -40,18 +40,19 @@ class WebInputStream : public InputStream public: WebInputStream (const String& address_, bool isPost_, const MemoryBlock& postData_, URL::OpenStreamProgressCallback* progressCallback, void* progressCallbackContext, - const String& headers_, int timeOutMs_, StringPairArray* responseHeaders) + const String& headers_, int timeOutMs_, StringPairArray* responseHeaders, int numRedirectsToFollow) : statusCode (0), connection (0), request (0), address (address_), headers (headers_), postData (postData_), position (0), finished (false), isPost (isPost_), timeOutMs (timeOutMs_) { - createConnection (progressCallback, progressCallbackContext); - - if (! isError()) + while (numRedirectsToFollow-- >= 0) { - if (responseHeaders != nullptr) + createConnection (progressCallback, progressCallbackContext); + + if (! isError()) { DWORD bufferSizeBytes = 4096; + StringPairArray headers (false); for (;;) { @@ -65,11 +66,10 @@ public: for (int i = 0; i < headersArray.size(); ++i) { const String& header = headersArray[i]; - const String key (header.upToFirstOccurrenceOf (": ", false, false)); + const String key (header.upToFirstOccurrenceOf (": ", false, false)); const String value (header.fromFirstOccurrenceOf (": ", false, false)); - const String previousValue ((*responseHeaders) [key]); - - responseHeaders->set (key, previousValue.isEmpty() ? value : (previousValue + "," + value)); + const String previousValue (headers[key]); + headers.set (key, previousValue.isEmpty() ? value : (previousValue + "," + value)); } break; @@ -77,14 +77,47 @@ public: if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) break; + + bufferSizeBytes += 4096; } + + DWORD status = 0; + DWORD statusSize = sizeof (status); + + if (HttpQueryInfo (request, HTTP_QUERY_STATUS_CODE | HTTP_QUERY_FLAG_NUMBER, &status, &statusSize, 0)) + { + statusCode = (int) status; + + if (numRedirectsToFollow >= 0 + && (statusCode == 301 || statusCode == 302 || statusCode == 303 || statusCode == 307)) + { + String newLocation (headers["Location"]); + + // Check whether location is a relative URI - this is an incomplete test for relative path, + // but we'll use it for now (valid protocols for this implementation are http, https & ftp) + if (! (newLocation.startsWithIgnoreCase ("http://") + || newLocation.startsWithIgnoreCase ("https://") + || newLocation.startsWithIgnoreCase ("ftp://"))) + { + if (newLocation.startsWithChar ('/')) + newLocation = URL (address).withNewSubPath (newLocation).toString (true); + else + newLocation = address + "/" + newLocation; + } + + if (newLocation.isNotEmpty() && newLocation != address) + { + address = newLocation; + continue; + } + } + } + + if (responseHeaders != nullptr) + responseHeaders->addArray (headers); } - DWORD status = 0; - DWORD statusSize = sizeof (status); - - if (HttpQueryInfo (request, HTTP_QUERY_STATUS_CODE | HTTP_QUERY_FLAG_NUMBER, &status, &statusSize, 0)) - statusCode = (int) status; + break; } } @@ -259,7 +292,8 @@ private: { const TCHAR* mimeTypes[] = { _T("*/*"), nullptr }; - DWORD flags = INTERNET_FLAG_RELOAD | INTERNET_FLAG_NO_CACHE_WRITE | INTERNET_FLAG_NO_COOKIES; + DWORD flags = INTERNET_FLAG_RELOAD | INTERNET_FLAG_NO_CACHE_WRITE | INTERNET_FLAG_NO_COOKIES + | INTERNET_FLAG_NO_AUTO_REDIRECT | SECURITY_SET_MASK; if (address.startsWithIgnoreCase ("https:")) flags |= INTERNET_FLAG_SECURE; // (this flag only seems necessary if the OS is running IE6 - @@ -270,6 +304,8 @@ private: if (request != 0) { + setSecurityFlags(); + INTERNET_BUFFERS buffers = { 0 }; buffers.dwStructSize = sizeof (INTERNET_BUFFERS); buffers.lpcszHeader = headers.toWideCharPointer(); @@ -313,6 +349,14 @@ private: close(); } + void setSecurityFlags() + { + DWORD dwFlags = 0, dwBuffLen = sizeof (DWORD); + InternetQueryOption (request, INTERNET_OPTION_SECURITY_FLAGS, &dwFlags, &dwBuffLen); + dwFlags |= SECURITY_FLAG_IGNORE_UNKNOWN_CA | SECURITY_SET_MASK; + InternetSetOption (request, INTERNET_OPTION_SECURITY_FLAGS, &dwFlags, sizeof (dwFlags)); + } + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (WebInputStream) }; diff --git a/JuceLibraryCode/modules/juce_core/native/juce_win32_Registry.cpp b/JuceLibraryCode/modules/juce_core/native/juce_win32_Registry.cpp index 8119474..164f2e2 100644 --- a/JuceLibraryCode/modules/juce_core/native/juce_win32_Registry.cpp +++ b/JuceLibraryCode/modules/juce_core/native/juce_win32_Registry.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this diff --git a/JuceLibraryCode/modules/juce_core/native/juce_win32_SystemStats.cpp b/JuceLibraryCode/modules/juce_core/native/juce_win32_SystemStats.cpp index 86f1051..b9007d3 100644 --- a/JuceLibraryCode/modules/juce_core/native/juce_win32_SystemStats.cpp +++ b/JuceLibraryCode/modules/juce_core/native/juce_win32_SystemStats.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this @@ -38,7 +38,7 @@ void Logger::outputDebugString (const String& text) #endif //============================================================================== -#if JUCE_USE_INTRINSICS +#if JUCE_USE_MSVC_INTRINSICS // CPU info functions using intrinsics... @@ -105,6 +105,8 @@ void CPUInformation::initialise() noexcept hasSSE = (info[3] & (1 << 25)) != 0; hasSSE2 = (info[3] & (1 << 26)) != 0; hasSSE3 = (info[2] & (1 << 0)) != 0; + hasAVX = (info[2] & (1 << 28)) != 0; + hasSSSE3 = (info[2] & (1 << 9)) != 0; has3DNow = (info[1] & (1 << 31)) != 0; SYSTEM_INFO systemInfo; @@ -131,16 +133,22 @@ static bool isWindowsVersionOrLater (SystemStats::OperatingSystemType target) zerostruct (info); info.dwOSVersionInfoSize = sizeof (OSVERSIONINFOEX); - if (target >= SystemStats::WinVista) + if (target >= SystemStats::Windows10) + { + info.dwMajorVersion = 10; + info.dwMinorVersion = 0; + } + else if (target >= SystemStats::WinVista) { info.dwMajorVersion = 6; switch (target) { - case SystemStats::WinVista: info.dwMinorVersion = 0; break; - case SystemStats::Windows7: info.dwMinorVersion = 1; break; - case SystemStats::Windows8: info.dwMinorVersion = 2; break; - default: jassertfalse; break; + case SystemStats::WinVista: break; + case SystemStats::Windows7: info.dwMinorVersion = 1; break; + case SystemStats::Windows8_0: info.dwMinorVersion = 2; break; + case SystemStats::Windows8_1: info.dwMinorVersion = 3; break; + default: jassertfalse; break; } } else @@ -165,7 +173,7 @@ static bool isWindowsVersionOrLater (SystemStats::OperatingSystemType target) SystemStats::OperatingSystemType SystemStats::getOperatingSystemType() { const SystemStats::OperatingSystemType types[] - = { Windows8, Windows7, WinVista, WinXP, Win2000 }; + = { Windows10, Windows8_1, Windows8_0, Windows7, WinVista, WinXP, Win2000 }; for (int i = 0; i < numElementsInArray (types); ++i) if (isWindowsVersionOrLater (types[i])) @@ -181,8 +189,10 @@ String SystemStats::getOperatingSystemName() switch (getOperatingSystemType()) { + case Windows10: name = "Windows 10"; break; + case Windows8_1: name = "Windows 8.1"; break; + case Windows8_0: name = "Windows 8.0"; break; case Windows7: name = "Windows 7"; break; - case Windows8: name = "Windows 8"; break; case WinVista: name = "Windows Vista"; break; case WinXP: name = "Windows XP"; break; case Win2000: name = "Windows 2000"; break; @@ -194,7 +204,7 @@ String SystemStats::getOperatingSystemName() String SystemStats::getDeviceDescription() { - return String::empty; + return String(); } bool SystemStats::isOperatingSystem64Bit() @@ -251,9 +261,23 @@ public: HiResCounterHandler() : hiResTicksOffset (0) { - const MMRESULT res = timeBeginPeriod (1); + // This macro allows you to override the default timer-period + // used on Windows. By default this is set to 1, because that has + // always been the value used in JUCE apps, and changing it could + // affect the behaviour of existing code, but you may wish to make + // it larger (or set it to 0 to use the system default) to make your + // app less demanding on the CPU. + // For more info, see win32 documentation about the timeBeginPeriod + // function. + #ifndef JUCE_WIN32_TIMER_PERIOD + #define JUCE_WIN32_TIMER_PERIOD 1 + #endif + + #if JUCE_WIN32_TIMER_PERIOD > 0 + const MMRESULT res = timeBeginPeriod (JUCE_WIN32_TIMER_PERIOD); (void) res; jassert (res == TIMERR_NOERROR); + #endif LARGE_INTEGER f; QueryPerformanceFrequency (&f); @@ -297,7 +321,7 @@ double Time::getMillisecondCounterHiRes() noexcept { return hiResCounterHa //============================================================================== static int64 juce_getClockCycleCounter() noexcept { - #if JUCE_USE_INTRINSICS + #if JUCE_USE_MSVC_INTRINSICS // MS intrinsics version... return (int64) __rdtsc(); diff --git a/JuceLibraryCode/modules/juce_core/native/juce_win32_Threads.cpp b/JuceLibraryCode/modules/juce_core/native/juce_win32_Threads.cpp index 4eb24e2..a7baf44 100644 --- a/JuceLibraryCode/modules/juce_core/native/juce_win32_Threads.cpp +++ b/JuceLibraryCode/modules/juce_core/native/juce_win32_Threads.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this @@ -36,7 +36,7 @@ void* getUser32Function (const char* functionName) } //============================================================================== -#if ! JUCE_USE_INTRINSICS +#if ! JUCE_USE_MSVC_INTRINSICS // In newer compilers, the inline versions of these are used (in juce_Atomic.h), but in // older ones we have to actually call the ops as win32 functions.. long juce_InterlockedExchange (volatile long* a, long b) noexcept { return InterlockedExchange (a, b); } diff --git a/JuceLibraryCode/modules/juce_core/network/juce_IPAddress.cpp b/JuceLibraryCode/modules/juce_core/network/juce_IPAddress.cpp index 6c4d087..5f137fc 100644 --- a/JuceLibraryCode/modules/juce_core/network/juce_IPAddress.cpp +++ b/JuceLibraryCode/modules/juce_core/network/juce_IPAddress.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this @@ -126,7 +126,7 @@ static void findIPAddresses (int sock, Array& result) cfg.ifc_buf += IFNAMSIZ + cfg.ifc_req->ifr_addr.sa_len; } #else - for (size_t i = 0; i < cfg.ifc_len / sizeof (struct ifreq); ++i) + for (size_t i = 0; i < (size_t) cfg.ifc_len / (size_t) sizeof (struct ifreq); ++i) { const ifreq& item = cfg.ifc_req[i]; diff --git a/JuceLibraryCode/modules/juce_core/network/juce_IPAddress.h b/JuceLibraryCode/modules/juce_core/network/juce_IPAddress.h index 1f2f0e8..eb82e3f 100644 --- a/JuceLibraryCode/modules/juce_core/network/juce_IPAddress.h +++ b/JuceLibraryCode/modules/juce_core/network/juce_IPAddress.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this diff --git a/JuceLibraryCode/modules/juce_core/network/juce_MACAddress.cpp b/JuceLibraryCode/modules/juce_core/network/juce_MACAddress.cpp index b7cb3c1..78391f8 100644 --- a/JuceLibraryCode/modules/juce_core/network/juce_MACAddress.cpp +++ b/JuceLibraryCode/modules/juce_core/network/juce_MACAddress.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this diff --git a/JuceLibraryCode/modules/juce_core/network/juce_MACAddress.h b/JuceLibraryCode/modules/juce_core/network/juce_MACAddress.h index 67e119e..10a55f7 100644 --- a/JuceLibraryCode/modules/juce_core/network/juce_MACAddress.h +++ b/JuceLibraryCode/modules/juce_core/network/juce_MACAddress.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this diff --git a/JuceLibraryCode/modules/juce_core/network/juce_NamedPipe.cpp b/JuceLibraryCode/modules/juce_core/network/juce_NamedPipe.cpp index 488e63f..bb580f7 100644 --- a/JuceLibraryCode/modules/juce_core/network/juce_NamedPipe.cpp +++ b/JuceLibraryCode/modules/juce_core/network/juce_NamedPipe.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this diff --git a/JuceLibraryCode/modules/juce_core/network/juce_NamedPipe.h b/JuceLibraryCode/modules/juce_core/network/juce_NamedPipe.h index d2029bd..9b957c3 100644 --- a/JuceLibraryCode/modules/juce_core/network/juce_NamedPipe.h +++ b/JuceLibraryCode/modules/juce_core/network/juce_NamedPipe.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this diff --git a/JuceLibraryCode/modules/juce_core/network/juce_Socket.cpp b/JuceLibraryCode/modules/juce_core/network/juce_Socket.cpp index 2d5d1fe..6753694 100644 --- a/JuceLibraryCode/modules/juce_core/network/juce_Socket.cpp +++ b/JuceLibraryCode/modules/juce_core/network/juce_Socket.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this @@ -75,9 +75,59 @@ namespace SocketHelpers : (setsockopt (handle, IPPROTO_TCP, TCP_NODELAY, (const char*) &one, sizeof (one)) == 0)); } - static bool bindSocketToPort (const SocketHandle handle, const int port) noexcept + static void closeSocket (volatile int& handle, CriticalSection& readLock, + const bool isListener, int portNumber, bool& connected) noexcept { - if (handle <= 0 || port <= 0) + const SocketHandle h = handle; + handle = -1; + + #if JUCE_WINDOWS + ignoreUnused (portNumber, isListener, readLock); + + if (h != SOCKET_ERROR || connected) + closesocket (h); + + // make sure any read process finishes before we delete the socket + CriticalSection::ScopedLockType lock(readLock); + connected = false; + #else + if (connected) + { + connected = false; + + if (isListener) + { + // need to do this to interrupt the accept() function.. + StreamingSocket temp; + temp.connect (IPAddress::local().toString(), portNumber, 1000); + } + } + + if (h != -1) + { + // unblock any pending read requests + ::shutdown (h, SHUT_RDWR); + { + // see man-page of recv on linux about a race condition where the + // shutdown command is lost if the receiving thread does not have + // a chance to process before close is called. On Mac OS X shutdown + // does not unblock a select call, so using a lock here will dead-lock + // both threads. + #if JUCE_LINUX + CriticalSection::ScopedLockType lock (readLock); + ::close (h); + #else + ::close (h); + CriticalSection::ScopedLockType lock (readLock); + #endif + } + } + #endif + } + + static bool bindSocket (const SocketHandle handle, const int port, const String& address) noexcept + { + if (handle <= 0 || port < 0) return false; struct sockaddr_in servTmpAddr; @@ -86,30 +136,64 @@ namespace SocketHelpers servTmpAddr.sin_addr.s_addr = htonl (INADDR_ANY); servTmpAddr.sin_port = htons ((uint16) port); + if (address.isNotEmpty()) + servTmpAddr.sin_addr.s_addr = ::inet_addr (address.toUTF8()); + return bind (handle, (struct sockaddr*) &servTmpAddr, sizeof (struct sockaddr_in)) >= 0; } + static int getBoundPort (const SocketHandle handle) noexcept + { + if (handle <= 0) + return -1; + + struct sockaddr_in sin_addr; + socklen_t len = sizeof (sin_addr); + + if (getsockname (handle, (struct sockaddr*) &sin_addr, &len) == 0) + return ntohs (sin_addr.sin_port); + + return -1; + } + static int readSocket (const SocketHandle handle, void* const destBuffer, const int maxBytesToRead, bool volatile& connected, - const bool blockUntilSpecifiedAmountHasArrived) noexcept + const bool blockUntilSpecifiedAmountHasArrived, + CriticalSection& readLock, + String* senderIP = nullptr, + int* senderPort = nullptr) noexcept { int bytesRead = 0; while (bytesRead < maxBytesToRead) { - int bytesThisTime; + long bytesThisTime = -1; + char* const buffer = static_cast (destBuffer) + bytesRead; + const juce_socklen_t numToRead = (juce_socklen_t) (maxBytesToRead - bytesRead); - #if JUCE_WINDOWS - bytesThisTime = recv (handle, static_cast (destBuffer) + bytesRead, maxBytesToRead - bytesRead, 0); - #else - while ((bytesThisTime = (int) ::read (handle, addBytesToPointer (destBuffer, bytesRead), - (size_t) (maxBytesToRead - bytesRead))) < 0 - && errno == EINTR - && connected) { + // avoid race-condition + CriticalSection::ScopedTryLockType lock (readLock); + + if (lock.isLocked()) + { + if (senderIP == nullptr || senderPort == nullptr) + { + bytesThisTime = ::recv (handle, buffer, numToRead, 0); + } + else + { + sockaddr_in client; + socklen_t clientLen = sizeof (sockaddr); + + bytesThisTime = ::recvfrom (handle, buffer, numToRead, 0, (sockaddr*) &client, &clientLen); + + *senderIP = String::fromUTF8 (inet_ntoa (client.sin_addr), 16); + *senderPort = ntohs (client.sin_port); + } + } } - #endif if (bytesThisTime <= 0 || ! connected) { @@ -125,11 +209,20 @@ namespace SocketHelpers break; } - return bytesRead; + return (int) bytesRead; } - static int waitForReadiness (const SocketHandle handle, const bool forReading, const int timeoutMsecs) noexcept + static int waitForReadiness (const volatile int& handle, CriticalSection& readLock, + const bool forReading, const int timeoutMsecs) noexcept { + // avoid race-condition + CriticalSection::ScopedTryLockType lock (readLock); + + if (! lock.isLocked()) + return -1; + + int h = handle; + struct timeval timeout; struct timeval* timeoutp; @@ -146,20 +239,20 @@ namespace SocketHelpers fd_set rset, wset; FD_ZERO (&rset); - FD_SET (handle, &rset); + FD_SET (h, &rset); FD_ZERO (&wset); - FD_SET (handle, &wset); + FD_SET (h, &wset); fd_set* const prset = forReading ? &rset : nullptr; fd_set* const pwset = forReading ? nullptr : &wset; #if JUCE_WINDOWS - if (select ((int) handle + 1, prset, pwset, 0, timeoutp) < 0) + if (select ((int) h + 1, prset, pwset, 0, timeoutp) < 0) return -1; #else { int result; - while ((result = select (handle + 1, prset, pwset, 0, timeoutp)) < 0 + while ((result = select (h + 1, prset, pwset, 0, timeoutp)) < 0 && errno == EINTR) { } @@ -169,16 +262,20 @@ namespace SocketHelpers } #endif + // we are closing + if (handle < 0) + return -1; + { int opt; juce_socklen_t len = sizeof (opt); - if (getsockopt (handle, SOL_SOCKET, SO_ERROR, (char*) &opt, &len) < 0 + if (getsockopt (h, SOL_SOCKET, SO_ERROR, (char*) &opt, &len) < 0 || opt != 0) return -1; } - return FD_ISSET (handle, forReading ? &rset : &wset) ? 1 : 0; + return FD_ISSET (h, forReading ? &rset : &wset) ? 1 : 0; } static bool setSocketBlockingState (const SocketHandle handle, const bool shouldBlock) noexcept @@ -201,12 +298,7 @@ namespace SocketHelpers #endif } - static bool connectSocket (int volatile& handle, - const bool isDatagram, - struct addrinfo** const serverAddress, - const String& hostName, - const int portNumber, - const int timeOutMillisecs) noexcept + static addrinfo* getAddressInfo (const bool isDatagram, const String& hostName, int portNumber) { struct addrinfo hints; zerostruct (hints); @@ -216,8 +308,22 @@ namespace SocketHelpers hints.ai_flags = AI_NUMERICSERV; struct addrinfo* info = nullptr; - if (getaddrinfo (hostName.toUTF8(), String (portNumber).toUTF8(), &hints, &info) != 0 - || info == nullptr) + if (getaddrinfo (hostName.toUTF8(), String (portNumber).toUTF8(), &hints, &info) == 0 + && info != nullptr) + return info; + + return nullptr; + } + + static bool connectSocket (int volatile& handle, + CriticalSection& readLock, + const String& hostName, + const int portNumber, + const int timeOutMillisecs) noexcept + { + struct addrinfo* info = getAddressInfo (false, hostName, portNumber); + + if (info == nullptr) return false; if (handle < 0) @@ -229,19 +335,12 @@ namespace SocketHelpers return false; } - if (isDatagram) - { - if (*serverAddress != nullptr) - freeaddrinfo (*serverAddress); - - *serverAddress = info; - return true; - } - setSocketBlockingState (handle, false); const int result = ::connect (handle, info->ai_addr, (socklen_t) info->ai_addrlen); freeaddrinfo (info); + bool retval = (result >= 0); + if (result < 0) { #if JUCE_WINDOWS @@ -250,18 +349,40 @@ namespace SocketHelpers if (errno == EINPROGRESS) #endif { - if (waitForReadiness (handle, false, timeOutMillisecs) != 1) - { - setSocketBlockingState (handle, true); - return false; - } + if (waitForReadiness (handle, readLock, false, timeOutMillisecs) == 1) + retval = true; } } setSocketBlockingState (handle, true); - resetSocketOptions (handle, false, false); - return true; + if (retval) + resetSocketOptions (handle, false, false); + + return retval; + } + + static void makeReusable (int handle) noexcept + { + const int reuse = 1; + setsockopt (handle, SOL_SOCKET, SO_REUSEADDR, (const char*) &reuse, sizeof (reuse)); + } + + static bool multicast (int handle, const String& multicastIPAddress, + const String& interfaceIPAddress, bool join) noexcept + { + struct ip_mreq mreq; + + zerostruct (mreq); + mreq.imr_multiaddr.s_addr = inet_addr (multicastIPAddress.toUTF8()); + mreq.imr_interface.s_addr = INADDR_ANY; + + if (interfaceIPAddress.isNotEmpty()) + mreq.imr_interface.s_addr = inet_addr (interfaceIPAddress.toUTF8()); + + int joinCmd = join ? IP_ADD_MEMBERSHIP : IP_DROP_MEMBERSHIP; + + return setsockopt (handle, IPPROTO_IP, joinCmd, (const char*) &mreq, sizeof (mreq)) == 0; } } @@ -292,11 +413,10 @@ StreamingSocket::~StreamingSocket() } //============================================================================== -int StreamingSocket::read (void* destBuffer, const int maxBytesToRead, - const bool blockUntilSpecifiedAmountHasArrived) +int StreamingSocket::read (void* destBuffer, const int maxBytesToRead, bool shouldBlock) { return (connected && ! isListener) ? SocketHelpers::readSocket (handle, destBuffer, maxBytesToRead, - connected, blockUntilSpecifiedAmountHasArrived) + connected, shouldBlock, readLock) : -1; } @@ -305,32 +425,31 @@ int StreamingSocket::write (const void* sourceBuffer, const int numBytesToWrite) if (isListener || ! connected) return -1; - #if JUCE_WINDOWS - return send (handle, (const char*) sourceBuffer, numBytesToWrite, 0); - #else - int result; - - while ((result = (int) ::write (handle, sourceBuffer, (size_t) numBytesToWrite)) < 0 - && errno == EINTR) - { - } - - return result; - #endif + return (int) ::send (handle, (const char*) sourceBuffer, (juce_socklen_t) numBytesToWrite, 0); } //============================================================================== int StreamingSocket::waitUntilReady (const bool readyForReading, const int timeoutMsecs) const { - return connected ? SocketHelpers::waitForReadiness (handle, readyForReading, timeoutMsecs) + return connected ? SocketHelpers::waitForReadiness (handle, readLock, readyForReading, timeoutMsecs) : -1; } //============================================================================== bool StreamingSocket::bindToPort (const int port) { - return SocketHelpers::bindSocketToPort (handle, port); + return bindToPort (port, String()); +} + +bool StreamingSocket::bindToPort (const int port, const String& addr) +{ + return SocketHelpers::bindSocket (handle, port, addr); +} + +int StreamingSocket::getBoundPort() const noexcept +{ + return SocketHelpers::getBoundPort (handle); } bool StreamingSocket::connect (const String& remoteHostName, @@ -350,7 +469,7 @@ bool StreamingSocket::connect (const String& remoteHostName, portNumber = remotePortNumber; isListener = false; - connected = SocketHelpers::connectSocket (handle, false, nullptr, remoteHostName, + connected = SocketHelpers::connectSocket (handle, readLock, remoteHostName, remotePortNumber, timeOutMillisecs); if (! (connected && SocketHelpers::resetSocketOptions (handle, false, false))) @@ -364,27 +483,7 @@ bool StreamingSocket::connect (const String& remoteHostName, void StreamingSocket::close() { - #if JUCE_WINDOWS - if (handle != SOCKET_ERROR || connected) - closesocket (handle); - - connected = false; - #else - if (connected) - { - connected = false; - - if (isListener) - { - // need to do this to interrupt the accept() function.. - StreamingSocket temp; - temp.connect ("localhost", portNumber, 1000); - } - } - - if (handle != -1) - ::close (handle); - #endif + SocketHelpers::closeSocket (handle, readLock, isListener, portNumber, connected); hostName.clear(); portNumber = 0; @@ -418,8 +517,9 @@ bool StreamingSocket::createListener (const int newPortNumber, const String& loc if (handle < 0) return false; - const int reuse = 1; - setsockopt (handle, SOL_SOCKET, SO_REUSEADDR, (const char*) &reuse, sizeof (reuse)); + #if ! JUCE_WINDOWS // on windows, adding this option produces behaviour different to posix + SocketHelpers::makeReusable (handle); + #endif if (bind (handle, (struct sockaddr*) &servTmpAddr, sizeof (struct sockaddr_in)) < 0 || listen (handle, SOMAXCONN) < 0) @@ -460,132 +560,109 @@ bool StreamingSocket::isLocal() const noexcept //============================================================================== //============================================================================== -DatagramSocket::DatagramSocket (const int localPortNumber, const bool canBroadcast) - : portNumber (0), - handle (-1), - connected (true), - allowBroadcast (canBroadcast), - serverAddress (nullptr) +DatagramSocket::DatagramSocket (const bool canBroadcast) + : handle (-1), + isBound (false), + lastServerPort (-1), + lastServerAddress (nullptr) { SocketHelpers::initSockets(); handle = (int) socket (AF_INET, SOCK_DGRAM, 0); - bindToPort (localPortNumber); -} - -DatagramSocket::DatagramSocket (const String& host, const int portNum, - const int h, const int localPortNumber) - : hostName (host), - portNumber (portNum), - handle (h), - connected (true), - allowBroadcast (false), - serverAddress (nullptr) -{ - SocketHelpers::initSockets(); - - SocketHelpers::resetSocketOptions (h, true, allowBroadcast); - bindToPort (localPortNumber); + SocketHelpers::resetSocketOptions (handle, true, canBroadcast); + SocketHelpers::makeReusable (handle); } DatagramSocket::~DatagramSocket() { - close(); + if (lastServerAddress != nullptr) + freeaddrinfo (static_cast (lastServerAddress)); - if (serverAddress != nullptr) - freeaddrinfo (static_cast (serverAddress)); -} - -void DatagramSocket::close() -{ - #if JUCE_WINDOWS - closesocket (handle); - connected = false; - #else - connected = false; - ::close (handle); - #endif - - hostName.clear(); - portNumber = 0; - handle = -1; + bool connected = false; + SocketHelpers::closeSocket (handle, readLock, false, 0, connected); } bool DatagramSocket::bindToPort (const int port) { - return SocketHelpers::bindSocketToPort (handle, port); + return bindToPort (port, String()); } -bool DatagramSocket::connect (const String& remoteHostName, - const int remotePortNumber, - const int timeOutMillisecs) +bool DatagramSocket::bindToPort (const int port, const String& addr) { - if (connected) - close(); - - hostName = remoteHostName; - portNumber = remotePortNumber; - - connected = SocketHelpers::connectSocket (handle, true, (struct addrinfo**) &serverAddress, - remoteHostName, remotePortNumber, - timeOutMillisecs); - - if (! (connected && SocketHelpers::resetSocketOptions (handle, true, allowBroadcast))) + if (SocketHelpers::bindSocket (handle, port, addr)) { - close(); - return false; + isBound = true; + lastBindAddress = addr; + + return true; } - return true; + return false; } -DatagramSocket* DatagramSocket::waitForNextConnection() const +int DatagramSocket::getBoundPort() const noexcept { - while (waitUntilReady (true, -1) == 1) - { - struct sockaddr_storage address; - juce_socklen_t len = sizeof (address); - char buf[1]; - - if (recvfrom (handle, buf, 0, 0, (struct sockaddr*) &address, &len) > 0) - return new DatagramSocket (inet_ntoa (((struct sockaddr_in*) &address)->sin_addr), - ntohs (((struct sockaddr_in*) &address)->sin_port), - -1, -1); - } - - return nullptr; + return isBound ? SocketHelpers::getBoundPort (handle) : -1; } //============================================================================== int DatagramSocket::waitUntilReady (const bool readyForReading, const int timeoutMsecs) const { - return connected ? SocketHelpers::waitForReadiness (handle, readyForReading, timeoutMsecs) - : -1; + return SocketHelpers::waitForReadiness (handle, readLock, readyForReading, timeoutMsecs); } -int DatagramSocket::read (void* destBuffer, const int maxBytesToRead, const bool blockUntilSpecifiedAmountHasArrived) +int DatagramSocket::read (void* destBuffer, int maxBytesToRead, bool shouldBlock) { - return connected ? SocketHelpers::readSocket (handle, destBuffer, maxBytesToRead, - connected, blockUntilSpecifiedAmountHasArrived) - : -1; + bool connected = true; + return isBound ? SocketHelpers::readSocket (handle, destBuffer, maxBytesToRead, + connected, shouldBlock, readLock) : -1; } -int DatagramSocket::write (const void* sourceBuffer, const int numBytesToWrite) +int DatagramSocket::read (void* destBuffer, int maxBytesToRead, bool shouldBlock, String& senderIPAddress, int& senderPort) { - // You need to call connect() first to set the server address.. - jassert (serverAddress != nullptr && connected); - - return connected ? (int) sendto (handle, (const char*) sourceBuffer, - (size_t) numBytesToWrite, 0, - static_cast (serverAddress)->ai_addr, - (juce_socklen_t) static_cast (serverAddress)->ai_addrlen) - : -1; + bool connected = true; + return isBound ? SocketHelpers::readSocket (handle, destBuffer, maxBytesToRead, connected, + shouldBlock, readLock, &senderIPAddress, &senderPort) : -1; } -bool DatagramSocket::isLocal() const noexcept +int DatagramSocket::write (const String& remoteHostname, int remotePortNumber, + const void* sourceBuffer, int numBytesToWrite) { - return hostName == "127.0.0.1"; + struct addrinfo*& info = reinterpret_cast (lastServerAddress); + + // getaddrinfo can be quite slow so cache the result of the address lookup + if (info == nullptr || remoteHostname != lastServerHost || remotePortNumber != lastServerPort) + { + if (info != nullptr) + freeaddrinfo (info); + + if ((info = SocketHelpers::getAddressInfo (true, remoteHostname, remotePortNumber)) == nullptr) + return -1; + + lastServerHost = remoteHostname; + lastServerPort = remotePortNumber; + } + + return (int) ::sendto (handle, (const char*) sourceBuffer, + (juce_socklen_t) numBytesToWrite, 0, + info->ai_addr, (socklen_t) info->ai_addrlen); +} + +bool DatagramSocket::joinMulticast (const String& multicastIPAddress) +{ + if (! isBound) + return false; + + return SocketHelpers::multicast (handle, multicastIPAddress, lastBindAddress, true); +} + +bool DatagramSocket::leaveMulticast (const String& multicastIPAddress) +{ + if (! isBound) + return false; + + return SocketHelpers::multicast (handle, multicastIPAddress, lastBindAddress, false); } #if JUCE_MSVC diff --git a/JuceLibraryCode/modules/juce_core/network/juce_Socket.h b/JuceLibraryCode/modules/juce_core/network/juce_Socket.h index 73795c9..56e9b8d 100644 --- a/JuceLibraryCode/modules/juce_core/network/juce_Socket.h +++ b/JuceLibraryCode/modules/juce_core/network/juce_Socket.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this @@ -65,6 +65,25 @@ public: */ bool bindToPort (int localPortNumber); + /** Binds the socket to the specified local port and local address. + + If localAddress is not an empty string then the socket will be bound to localAddress + as well. This is useful if you would like to bind your socket to a specific network + adapter. Note that localAddress must be an IP address assigned to one of your + network address otherwise this function will fail. + @returns true on success; false may indicate that another socket is already bound + on the same port + @see bindToPort(int localPortNumber), IPAddress::findAllAddresses + */ + bool bindToPort (int localPortNumber, const String& localAddress); + + /** Returns the local port number to which this socket is currently bound. + + This is useful if you need to know to which port the OS has actually bound your + socket when calling the constructor or bindToPort with zero as the + localPortNumber argument. Returns -1 if the function fails. */ + int getBoundPort() const noexcept; + /** Tries to connect the socket to hostname:port. If timeOutMillisecs is 0, then this method will block until the operating system @@ -164,6 +183,7 @@ private: String hostName; int volatile portNumber, handle; bool connected, isListener; + mutable CriticalSection readLock; StreamingSocket (const String& hostname, int portNumber, int handle); @@ -185,22 +205,16 @@ class JUCE_API DatagramSocket public: //============================================================================== /** - Creates an (uninitialised) datagram socket. + Creates a datagram socket. - The localPortNumber is the port on which to bind this socket. If this value is 0, - the port number is assigned by the operating system. - - To use the socket for sending, call the connect() method. This will not immediately - make a connection, but will save the destination you've provided. After this, you can - call read() or write(). + You first need to bind this socket to a port with bindToPort if you intend to read + from this socket. If enableBroadcasting is true, the socket will be allowed to send broadcast messages (may require extra privileges on linux) - - To wait for other sockets to connect to this one, call waitForNextConnection(). */ - DatagramSocket (int localPortNumber, - bool enableBroadcasting = false); + DatagramSocket (bool enableBroadcasting = false); + /** Destructor. */ ~DatagramSocket(); @@ -208,37 +222,33 @@ public: //============================================================================== /** Binds the socket to the specified local port. + The localPortNumber is the port on which to bind this socket. If this value is 0, + the port number is assigned by the operating system. + @returns true on success; false may indicate that another socket is already bound on the same port */ bool bindToPort (int localPortNumber); - /** Tries to connect the socket to hostname:port. + /** Binds the socket to the specified local port and local address. - If timeOutMillisecs is 0, then this method will block until the operating system - rejects the connection (which could take a long time). - - @returns true if it succeeds. - @see isConnected + If localAddress is not an empty string then the socket will be bound to localAddress + as well. This is useful if you would like to bind your socket to a specific network + adapter. Note that localAddress must be an IP address assigned to one of your + network address otherwise this function will fail. + @returns true on success; false may indicate that another socket is already bound + on the same port + @see bindToPort(int localPortNumber), IPAddress::findAllAddresses */ - bool connect (const String& remoteHostname, - int remotePortNumber, - int timeOutMillisecs = 3000); + bool bindToPort (int localPortNumber, const String& localAddress); - /** True if the socket is currently connected. */ - bool isConnected() const noexcept { return connected; } + /** Returns the local port number to which this socket is currently bound. - /** Closes the connection. */ - void close(); + This is useful if you need to know to which port the OS has actually bound your + socket when bindToPort was called with zero. - /** Returns the name of the currently connected host. */ - const String& getHostName() const noexcept { return hostName; } - - /** Returns the port number that's currently open. */ - int getPort() const noexcept { return portNumber; } - - /** True if the socket is connected to this machine rather than over the network. */ - bool isLocal() const noexcept; + Returns -1 if the socket didn't bind to any port yet or an error occured. */ + int getBoundPort() const noexcept; /** Returns the OS's socket handle that's currently open. */ int getRawSocketHandle() const noexcept { return handle; } @@ -271,6 +281,21 @@ public: int read (void* destBuffer, int maxBytesToRead, bool blockUntilSpecifiedAmountHasArrived); + /** Reads bytes from the socket and return the IP address of the sender. + + If blockUntilSpecifiedAmountHasArrived is true, the method will block until + maxBytesToRead bytes have been read, (or until an error occurs). If this + flag is false, the method will return as much data as is currently available + without blocking. + + @returns the number of bytes read, or -1 if there was an error. On a successful + result, the senderIPAddress value will be set to the IP of the sender. + @see waitUntilReady + */ + int read (void* destBuffer, int maxBytesToRead, + bool blockUntilSpecifiedAmountHasArrived, + String& senderIPAddress, int& senderPortNumber); + /** Writes bytes to the socket from a buffer. Note that this method will block unless you have checked the socket is ready @@ -278,25 +303,30 @@ public: @returns the number of bytes written, or -1 if there was an error. */ - int write (const void* sourceBuffer, int numBytesToWrite); + int write (const String& remoteHostname, int remotePortNumber, + const void* sourceBuffer, int numBytesToWrite); //============================================================================== - /** This waits for incoming data to be sent, and returns a socket that can be used - to read it. + /** Join a multicast group - The object that gets returned is owned by the caller, and can't be used for - sending, but can be used to read the data. + @returns true if it succeeds. */ - DatagramSocket* waitForNextConnection() const; + bool joinMulticast (const String& multicastIPAddress); + + /** Leave a multicast group + + @returns true if it succeeds. + */ + bool leaveMulticast (const String& multicastIPAddress); private: //============================================================================== - String hostName; - int volatile portNumber, handle; - bool connected, allowBroadcast; - void* serverAddress; - - DatagramSocket (const String& hostname, int portNumber, int handle, int localPortNumber); + int handle; + bool isBound; + String lastBindAddress, lastServerHost; + int lastServerPort; + void* lastServerAddress; + mutable CriticalSection readLock; JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (DatagramSocket) }; diff --git a/JuceLibraryCode/modules/juce_core/network/juce_URL.cpp b/JuceLibraryCode/modules/juce_core/network/juce_URL.cpp index 49db1f9..200a82b 100644 --- a/JuceLibraryCode/modules/juce_core/network/juce_URL.cpp +++ b/JuceLibraryCode/modules/juce_core/network/juce_URL.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this @@ -179,6 +179,11 @@ String URL::toString (const bool includeGetParameters) const return url; } +bool URL::isEmpty() const noexcept +{ + return url.isEmpty(); +} + bool URL::isWellFormed() const { //xxx TODO @@ -329,7 +334,8 @@ InputStream* URL::createInputStream (const bool usePostCommand, String headers, const int timeOutMs, StringPairArray* const responseHeaders, - int* statusCode) const + int* statusCode, + const int numRedirectsToFollow) const { MemoryBlock headersAndPostData; @@ -345,7 +351,8 @@ InputStream* URL::createInputStream (const bool usePostCommand, ScopedPointer wi (new WebInputStream (toString (! usePostCommand), usePostCommand, headersAndPostData, progressCallback, progressCallbackContext, - headers, timeOutMs, responseHeaders)); + headers, timeOutMs, responseHeaders, + numRedirectsToFollow)); if (statusCode != nullptr) *statusCode = wi->statusCode; @@ -392,6 +399,17 @@ URL URL::withParameter (const String& parameterName, return u; } +URL URL::withParameters (const StringPairArray& parametersToAdd) const +{ + URL u (*this); + + for (int i = 0; i < parametersToAdd.size(); ++i) + u.addParameter (parametersToAdd.getAllKeys()[i], + parametersToAdd.getAllValues()[i]); + + return u; +} + URL URL::withPOSTData (const String& newPostData) const { URL u (*this); @@ -477,8 +495,8 @@ String URL::addEscapeChars (const String& s, const bool isParameter) || legalChars.indexOf ((juce_wchar) c) >= 0)) { utf8.set (i, '%'); - utf8.insert (++i, "0123456789abcdef" [((uint8) c) >> 4]); - utf8.insert (++i, "0123456789abcdef" [c & 15]); + utf8.insert (++i, "0123456789ABCDEF" [((uint8) c) >> 4]); + utf8.insert (++i, "0123456789ABCDEF" [c & 15]); } } diff --git a/JuceLibraryCode/modules/juce_core/network/juce_URL.h b/JuceLibraryCode/modules/juce_core/network/juce_URL.h index 4f511d8..722b69f 100644 --- a/JuceLibraryCode/modules/juce_core/network/juce_URL.h +++ b/JuceLibraryCode/modules/juce_core/network/juce_URL.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this @@ -76,6 +76,9 @@ public: */ String toString (bool includeGetParameters) const; + /** Returns true if the URL is an empty string. */ + bool isEmpty() const noexcept; + /** True if it seems to be valid. */ bool isWellFormed() const; @@ -137,6 +140,12 @@ public: URL withParameter (const String& parameterName, const String& parameterValue) const; + /** Returns a copy of this URL, with a set of GET or POST parameters added. + This is a convenience method, equivalent to calling withParameter for each value. + @see withParameter + */ + URL withParameters (const StringPairArray& parametersToAdd) const; + /** Returns a copy of this URL, with a file-upload type parameter added to it. When performing a POST where one of your parameters is a binary file, this @@ -239,6 +248,9 @@ public: /** Attempts to open a stream that can read from this URL. + Note that on some platforms (Android, for example) it's not permitted to do any network + action from the message thread, so you must only call it from a background thread. + @param usePostCommand if true, it will try to do use a http 'POST' to pass the parameters, otherwise it'll encode them into the URL and do a 'GET'. @@ -257,6 +269,8 @@ public: in the response will be stored in this array @param statusCode if this is non-null, it will get set to the http status code, if one is known, or 0 if a code isn't available + @param numRedirectsToFollow specifies the number of redirects that will be followed before + returning a response (ignored for Android which follows up to 5 redirects) @returns an input stream that the caller must delete, or a null pointer if there was an error trying to open it. */ @@ -266,7 +280,8 @@ public: String extraHeaders = String(), int connectionTimeOutMs = 0, StringPairArray* responseHeaders = nullptr, - int* statusCode = nullptr) const; + int* statusCode = nullptr, + int numRedirectsToFollow = 5) const; //============================================================================== @@ -275,6 +290,9 @@ public: If it succeeds, this will return true and append the data it read onto the end of the memory block. + Note that on some platforms (Android, for example) it's not permitted to do any network + action from the message thread, so you must only call it from a background thread. + @param destData the memory block to append the new data to @param usePostCommand whether to use a POST command to get the data (uses a GET command if this is false) @@ -290,6 +308,9 @@ public: operation that fails and one that returns an empty string, you'll need to use a different method, such as readEntireBinaryStream(). + Note that on some platforms (Android, for example) it's not permitted to do any network + action from the message thread, so you must only call it from a background thread. + @param usePostCommand whether to use a POST command to get the data (uses a GET command if this is false) @see readEntireBinaryStream, readEntireXmlStream @@ -304,6 +325,9 @@ public: When it returns a valid XmlElement object, the caller is responsibile for deleting this object when no longer needed. + Note that on some platforms (Android, for example) it's not permitted to do any network + action from the message thread, so you must only call it from a background thread. + @param usePostCommand whether to use a POST command to get the data (uses a GET command if this is false) diff --git a/JuceLibraryCode/modules/juce_core/streams/juce_BufferedInputStream.cpp b/JuceLibraryCode/modules/juce_core/streams/juce_BufferedInputStream.cpp index ec01f8e..ea91f64 100644 --- a/JuceLibraryCode/modules/juce_core/streams/juce_BufferedInputStream.cpp +++ b/JuceLibraryCode/modules/juce_core/streams/juce_BufferedInputStream.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this diff --git a/JuceLibraryCode/modules/juce_core/streams/juce_BufferedInputStream.h b/JuceLibraryCode/modules/juce_core/streams/juce_BufferedInputStream.h index 8f1e633..e0e74a2 100644 --- a/JuceLibraryCode/modules/juce_core/streams/juce_BufferedInputStream.h +++ b/JuceLibraryCode/modules/juce_core/streams/juce_BufferedInputStream.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this diff --git a/JuceLibraryCode/modules/juce_core/streams/juce_FileInputSource.cpp b/JuceLibraryCode/modules/juce_core/streams/juce_FileInputSource.cpp index 51b9db9..9cbeaf1 100644 --- a/JuceLibraryCode/modules/juce_core/streams/juce_FileInputSource.cpp +++ b/JuceLibraryCode/modules/juce_core/streams/juce_FileInputSource.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this diff --git a/JuceLibraryCode/modules/juce_core/streams/juce_FileInputSource.h b/JuceLibraryCode/modules/juce_core/streams/juce_FileInputSource.h index d2e6d86..5a58c77 100644 --- a/JuceLibraryCode/modules/juce_core/streams/juce_FileInputSource.h +++ b/JuceLibraryCode/modules/juce_core/streams/juce_FileInputSource.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this diff --git a/JuceLibraryCode/modules/juce_core/streams/juce_InputSource.h b/JuceLibraryCode/modules/juce_core/streams/juce_InputSource.h index 0e13ac5..a571ed0 100644 --- a/JuceLibraryCode/modules/juce_core/streams/juce_InputSource.h +++ b/JuceLibraryCode/modules/juce_core/streams/juce_InputSource.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this diff --git a/JuceLibraryCode/modules/juce_core/streams/juce_InputStream.cpp b/JuceLibraryCode/modules/juce_core/streams/juce_InputStream.cpp index 08ff61c..2cf3e00 100644 --- a/JuceLibraryCode/modules/juce_core/streams/juce_InputStream.cpp +++ b/JuceLibraryCode/modules/juce_core/streams/juce_InputStream.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this @@ -209,10 +209,10 @@ String InputStream::readNextLine() return String::fromUTF8 (data, (int) i); } -int InputStream::readIntoMemoryBlock (MemoryBlock& block, ssize_t numBytes) +size_t InputStream::readIntoMemoryBlock (MemoryBlock& block, ssize_t numBytes) { MemoryOutputStream mo (block, true); - return mo.writeFromInputStream (*this, numBytes); + return (size_t) mo.writeFromInputStream (*this, numBytes); } String InputStream::readEntireStreamAsString() diff --git a/JuceLibraryCode/modules/juce_core/streams/juce_InputStream.h b/JuceLibraryCode/modules/juce_core/streams/juce_InputStream.h index 0c7e2dc..0149f0b 100644 --- a/JuceLibraryCode/modules/juce_core/streams/juce_InputStream.h +++ b/JuceLibraryCode/modules/juce_core/streams/juce_InputStream.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this @@ -211,7 +211,7 @@ public: /** Tries to read the whole stream and turn it into a string. This will read from the stream's current position until the end-of-stream. - It can read from either UTF-16 or UTF-8 formats. + It can read from UTF-8 data, or UTF-16 if it detects suitable header-bytes. */ virtual String readEntireStreamAsString(); @@ -223,8 +223,8 @@ public: will be read until the stream is exhausted. @returns the number of bytes that were added to the memory block */ - virtual int readIntoMemoryBlock (MemoryBlock& destBlock, - ssize_t maxNumBytesToRead = -1); + virtual size_t readIntoMemoryBlock (MemoryBlock& destBlock, + ssize_t maxNumBytesToRead = -1); //============================================================================== /** Returns the offset of the next byte that will be read from the stream. diff --git a/JuceLibraryCode/modules/juce_core/streams/juce_MemoryInputStream.cpp b/JuceLibraryCode/modules/juce_core/streams/juce_MemoryInputStream.cpp index 19b1052..2621e4f 100644 --- a/JuceLibraryCode/modules/juce_core/streams/juce_MemoryInputStream.cpp +++ b/JuceLibraryCode/modules/juce_core/streams/juce_MemoryInputStream.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this @@ -60,7 +60,7 @@ MemoryInputStream::~MemoryInputStream() int64 MemoryInputStream::getTotalLength() { - return dataSize; + return (int64) dataSize; } int MemoryInputStream::read (void* const buffer, const int howMany) @@ -89,7 +89,7 @@ bool MemoryInputStream::setPosition (const int64 pos) int64 MemoryInputStream::getPosition() { - return position; + return (int64) position; } diff --git a/JuceLibraryCode/modules/juce_core/streams/juce_MemoryInputStream.h b/JuceLibraryCode/modules/juce_core/streams/juce_MemoryInputStream.h index 013bc39..6350f65 100644 --- a/JuceLibraryCode/modules/juce_core/streams/juce_MemoryInputStream.h +++ b/JuceLibraryCode/modules/juce_core/streams/juce_MemoryInputStream.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this diff --git a/JuceLibraryCode/modules/juce_core/streams/juce_MemoryOutputStream.cpp b/JuceLibraryCode/modules/juce_core/streams/juce_MemoryOutputStream.cpp index 7d07ce6..9c02670 100644 --- a/JuceLibraryCode/modules/juce_core/streams/juce_MemoryOutputStream.cpp +++ b/JuceLibraryCode/modules/juce_core/streams/juce_MemoryOutputStream.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this @@ -89,14 +89,14 @@ char* MemoryOutputStream::prepareToWrite (size_t numBytes) if (storageNeeded >= blockToUse->getSize()) blockToUse->ensureSize ((storageNeeded + jmin (storageNeeded / 2, (size_t) (1024 * 1024)) + 32) & ~31u); - data = static_cast (blockToUse->getData()); + data = static_cast (blockToUse->getData()); } else { if (storageNeeded > availableSize) return nullptr; - data = static_cast (externalData); + data = static_cast (externalData); } char* const writePointer = data + position; @@ -157,7 +157,7 @@ const void* MemoryOutputStream::getData() const noexcept return externalData; if (blockToUse->getSize() > size) - static_cast (blockToUse->getData()) [size] = 0; + static_cast (blockToUse->getData()) [size] = 0; return blockToUse->getData(); } @@ -175,14 +175,14 @@ bool MemoryOutputStream::setPosition (int64 newPosition) return false; } -int MemoryOutputStream::writeFromInputStream (InputStream& source, int64 maxNumBytesToWrite) +int64 MemoryOutputStream::writeFromInputStream (InputStream& source, int64 maxNumBytesToWrite) { // before writing from an input, see if we can preallocate to make it more efficient.. int64 availableData = source.getTotalLength() - source.getPosition(); if (availableData > 0) { - if (maxNumBytesToWrite > availableData) + if (maxNumBytesToWrite > availableData || maxNumBytesToWrite < 0) maxNumBytesToWrite = availableData; if (blockToUse != nullptr) @@ -194,7 +194,7 @@ int MemoryOutputStream::writeFromInputStream (InputStream& source, int64 maxNumB String MemoryOutputStream::toUTF8() const { - const char* const d = static_cast (getData()); + const char* const d = static_cast (getData()); return String (CharPointer_UTF8 (d), CharPointer_UTF8 (d + getDataSize())); } diff --git a/JuceLibraryCode/modules/juce_core/streams/juce_MemoryOutputStream.h b/JuceLibraryCode/modules/juce_core/streams/juce_MemoryOutputStream.h index 95d7be4..6109444 100644 --- a/JuceLibraryCode/modules/juce_core/streams/juce_MemoryOutputStream.h +++ b/JuceLibraryCode/modules/juce_core/streams/juce_MemoryOutputStream.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this @@ -111,12 +111,12 @@ public: capacity off the block, so that its length matches the amount of actual data that has been written so far. */ - void flush(); + void flush() override; bool write (const void*, size_t) override; - int64 getPosition() override { return position; } + int64 getPosition() override { return (int64) position; } bool setPosition (int64) override; - int writeFromInputStream (InputStream&, int64 maxNumBytesToWrite) override; + int64 writeFromInputStream (InputStream&, int64 maxNumBytesToWrite) override; bool writeRepeatedByte (uint8 byte, size_t numTimesToRepeat) override; private: diff --git a/JuceLibraryCode/modules/juce_core/streams/juce_OutputStream.cpp b/JuceLibraryCode/modules/juce_core/streams/juce_OutputStream.cpp index 7c6d0bd..8b5585f 100644 --- a/JuceLibraryCode/modules/juce_core/streams/juce_OutputStream.cpp +++ b/JuceLibraryCode/modules/juce_core/streams/juce_OutputStream.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this @@ -252,12 +252,12 @@ bool OutputStream::writeText (const String& text, const bool asUTF16, return true; } -int OutputStream::writeFromInputStream (InputStream& source, int64 numBytesToWrite) +int64 OutputStream::writeFromInputStream (InputStream& source, int64 numBytesToWrite) { if (numBytesToWrite < 0) numBytesToWrite = std::numeric_limits::max(); - int numWritten = 0; + int64 numWritten = 0; while (numBytesToWrite > 0) { diff --git a/JuceLibraryCode/modules/juce_core/streams/juce_OutputStream.h b/JuceLibraryCode/modules/juce_core/streams/juce_OutputStream.h index de40888..407d342 100644 --- a/JuceLibraryCode/modules/juce_core/streams/juce_OutputStream.h +++ b/JuceLibraryCode/modules/juce_core/streams/juce_OutputStream.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this @@ -221,7 +221,7 @@ public: is exhausted) @returns the number of bytes written */ - virtual int writeFromInputStream (InputStream& source, int64 maxNumBytesToWrite); + virtual int64 writeFromInputStream (InputStream& source, int64 maxNumBytesToWrite); //============================================================================== /** Sets the string that will be written to the stream when the writeNewLine() diff --git a/JuceLibraryCode/modules/juce_core/streams/juce_SubregionStream.cpp b/JuceLibraryCode/modules/juce_core/streams/juce_SubregionStream.cpp index c998c79..4398ab7 100644 --- a/JuceLibraryCode/modules/juce_core/streams/juce_SubregionStream.cpp +++ b/JuceLibraryCode/modules/juce_core/streams/juce_SubregionStream.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this diff --git a/JuceLibraryCode/modules/juce_core/streams/juce_SubregionStream.h b/JuceLibraryCode/modules/juce_core/streams/juce_SubregionStream.h index d291a03..55e4ccc 100644 --- a/JuceLibraryCode/modules/juce_core/streams/juce_SubregionStream.h +++ b/JuceLibraryCode/modules/juce_core/streams/juce_SubregionStream.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this diff --git a/JuceLibraryCode/modules/juce_core/system/juce_PlatformDefs.h b/JuceLibraryCode/modules/juce_core/system/juce_PlatformDefs.h index 6f59979..bac29ac 100644 --- a/JuceLibraryCode/modules/juce_core/system/juce_PlatformDefs.h +++ b/JuceLibraryCode/modules/juce_core/system/juce_PlatformDefs.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this @@ -63,12 +63,12 @@ //============================================================================== #if JUCE_IOS || JUCE_LINUX || JUCE_ANDROID || JUCE_PPC /** This will try to break into the debugger if the app is currently being debugged. - If called by an app that's not being debugged, the behaiour isn't defined - it may crash or not, depending - on the platform. + If called by an app that's not being debugged, the behaviour isn't defined - it may + crash or not, depending on the platform. @see jassert() */ #define juce_breakDebugger { ::kill (0, SIGTRAP); } -#elif JUCE_USE_INTRINSICS +#elif JUCE_USE_MSVC_INTRINSICS #ifndef __INTEL_COMPILER #pragma intrinsic (__debugbreak) #endif @@ -94,20 +94,34 @@ #define JUCE_ANALYZER_NORETURN #endif +//============================================================================== +#if JUCE_MSVC && ! DOXYGEN + #define MACRO_WITH_FORCED_SEMICOLON(x) \ + __pragma(warning(push)) \ + __pragma(warning(disable:4127)) \ + do { x } while (false) \ + __pragma(warning(pop)) +#else + /** This is the good old C++ trick for creating a macro that forces the user to put + a semicolon after it when they use it. + */ + #define MACRO_WITH_FORCED_SEMICOLON(x) do { x } while (false) +#endif + //============================================================================== #if JUCE_DEBUG || DOXYGEN /** Writes a string to the standard error stream. This is only compiled in a debug build. @see Logger::outputDebugString */ - #define DBG(dbgtext) { juce::String tempDbgBuf; tempDbgBuf << dbgtext; juce::Logger::outputDebugString (tempDbgBuf); } + #define DBG(dbgtext) MACRO_WITH_FORCED_SEMICOLON (juce::String tempDbgBuf; tempDbgBuf << dbgtext; juce::Logger::outputDebugString (tempDbgBuf);) //============================================================================== /** This will always cause an assertion failure. It is only compiled in a debug build, (unless JUCE_LOG_ASSERTIONS is enabled for your build). @see jassert */ - #define jassertfalse { juce_LogCurrentAssertion; if (juce::juce_isRunningUnderDebugger()) juce_breakDebugger; JUCE_ANALYZER_NORETURN } + #define jassertfalse MACRO_WITH_FORCED_SEMICOLON (juce_LogCurrentAssertion; if (juce::juce_isRunningUnderDebugger()) juce_breakDebugger; JUCE_ANALYZER_NORETURN) //============================================================================== /** Platform-independent assertion macro. @@ -117,19 +131,19 @@ correct behaviour of your program! @see jassertfalse */ - #define jassert(expression) { if (! (expression)) jassertfalse; } + #define jassert(expression) MACRO_WITH_FORCED_SEMICOLON (if (! (expression)) jassertfalse;) #else //============================================================================== // If debugging is disabled, these dummy debug and assertion macros are used.. #define DBG(dbgtext) - #define jassertfalse { juce_LogCurrentAssertion } + #define jassertfalse MACRO_WITH_FORCED_SEMICOLON (juce_LogCurrentAssertion) #if JUCE_LOG_ASSERTIONS - #define jassert(expression) { if (! (expression)) jassertfalse; } + #define jassert(expression) MACRO_WITH_FORCED_SEMICOLON (if (! (expression)) jassertfalse;) #else - #define jassert(a) {} + #define jassert(a) MACRO_WITH_FORCED_SEMICOLON ( ; ) #endif #endif @@ -139,7 +153,7 @@ namespace juce { template struct JuceStaticAssert; - template <> struct JuceStaticAssert { static void dummy() {} }; + template <> struct JuceStaticAssert { static void dummy() {} }; } #endif @@ -211,6 +225,26 @@ namespace juce #define JUCE_STRINGIFY(item) JUCE_STRINGIFY_MACRO_HELPER (item) +//============================================================================== +#if JUCE_MSVC && ! defined (DOXYGEN) + #define JUCE_WARNING_HELPER(file, line, mess) message(file "(" JUCE_STRINGIFY (line) ") : Warning: " #mess) + #define JUCE_COMPILER_WARNING(message) __pragma(JUCE_WARNING_HELPER (__FILE__, __LINE__, message)); +#else + #ifndef DOXYGEN + #define JUCE_WARNING_HELPER(mess) message(#mess) + #endif + + /** This macro allows you to emit a custom compiler warning message. + Very handy for marking bits of code as "to-do" items, or for shaming + code written by your co-workers in a way that's hard to ignore. + + GCC and Clang provide the \#warning directive, but MSVC doesn't, so this macro + is a cross-compiler way to get the same functionality as \#warning. + */ + #define JUCE_COMPILER_WARNING(message) _Pragma(JUCE_STRINGIFY (JUCE_WARNING_HELPER (message))); +#endif + + //============================================================================== #if JUCE_CATCH_UNHANDLED_EXCEPTIONS @@ -302,84 +336,4 @@ namespace juce #define JUCE_PACKED #endif -//============================================================================== -// Here, we'll check for C++11 compiler support, and if it's not available, define -// a few workarounds, so that we can still use some of the newer language features. -#if (__cplusplus >= 201103L || defined (__GXX_EXPERIMENTAL_CXX0X__)) && (__GNUC__ * 100 + __GNUC_MINOR__) >= 405 - #define JUCE_COMPILER_SUPPORTS_NOEXCEPT 1 - #define JUCE_COMPILER_SUPPORTS_NULLPTR 1 - #define JUCE_COMPILER_SUPPORTS_MOVE_SEMANTICS 1 - - #if (__GNUC__ * 100 + __GNUC_MINOR__) >= 407 && ! defined (JUCE_COMPILER_SUPPORTS_OVERRIDE_AND_FINAL) - #define JUCE_COMPILER_SUPPORTS_OVERRIDE_AND_FINAL 1 - #endif - - #if (__GNUC__ * 100 + __GNUC_MINOR__) >= 407 && ! defined (JUCE_DELETED_FUNCTION) - #define JUCE_DELETED_FUNCTION = delete - #endif -#endif - -#if JUCE_CLANG && defined (__has_feature) - #if __has_feature (cxx_nullptr) - #define JUCE_COMPILER_SUPPORTS_NULLPTR 1 - #endif - - #if __has_feature (cxx_noexcept) - #define JUCE_COMPILER_SUPPORTS_NOEXCEPT 1 - #endif - - #if __has_feature (cxx_rvalue_references) - #define JUCE_COMPILER_SUPPORTS_MOVE_SEMANTICS 1 - #endif - - #if __has_feature (cxx_deleted_functions) - #define JUCE_DELETED_FUNCTION = delete - #endif - - #ifndef JUCE_COMPILER_SUPPORTS_OVERRIDE_AND_FINAL - #define JUCE_COMPILER_SUPPORTS_OVERRIDE_AND_FINAL 1 - #endif - - #ifndef JUCE_COMPILER_SUPPORTS_ARC - #define JUCE_COMPILER_SUPPORTS_ARC 1 - #endif -#endif - -#if defined (_MSC_VER) && _MSC_VER >= 1600 - #define JUCE_COMPILER_SUPPORTS_NULLPTR 1 - #define JUCE_COMPILER_SUPPORTS_MOVE_SEMANTICS 1 -#endif - -#if defined (_MSC_VER) && _MSC_VER >= 1700 - #define JUCE_COMPILER_SUPPORTS_OVERRIDE_AND_FINAL 1 -#endif - -#ifndef JUCE_DELETED_FUNCTION - #define JUCE_DELETED_FUNCTION -#endif - -//============================================================================== -// Declare some fake versions of nullptr and noexcept, for older compilers: -#if ! (DOXYGEN || JUCE_COMPILER_SUPPORTS_NOEXCEPT) - #ifdef noexcept - #undef noexcept - #endif - #define noexcept throw() - #if defined (_MSC_VER) && _MSC_VER > 1600 - #define _ALLOW_KEYWORD_MACROS 1 // (to stop VC2012 complaining) - #endif -#endif - -#if ! (DOXYGEN || JUCE_COMPILER_SUPPORTS_NULLPTR) - #ifdef nullptr - #undef nullptr - #endif - #define nullptr (0) -#endif - -#if ! (DOXYGEN || JUCE_COMPILER_SUPPORTS_OVERRIDE_AND_FINAL) - #undef override - #define override -#endif - #endif // JUCE_PLATFORMDEFS_H_INCLUDED diff --git a/JuceLibraryCode/modules/juce_core/system/juce_StandardHeader.h b/JuceLibraryCode/modules/juce_core/system/juce_StandardHeader.h index edd6a54..46b7610 100644 --- a/JuceLibraryCode/modules/juce_core/system/juce_StandardHeader.h +++ b/JuceLibraryCode/modules/juce_core/system/juce_StandardHeader.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this @@ -35,8 +35,8 @@ See also SystemStats::getJUCEVersion() for a string version. */ #define JUCE_MAJOR_VERSION 3 -#define JUCE_MINOR_VERSION 0 -#define JUCE_BUILDNUMBER 6 +#define JUCE_MINOR_VERSION 2 +#define JUCE_BUILDNUMBER 0 /** Current Juce version number. @@ -50,7 +50,10 @@ //============================================================================== +#include // included before platform defs to provide a definition of _LIBCPP_VERSION + #include "juce_PlatformDefs.h" +#include "juce_CompilerSupport.h" //============================================================================== // Now we'll include some common OS headers.. @@ -70,10 +73,10 @@ #include #include #include -#include #include +#include -#if JUCE_USE_INTRINSICS +#if JUCE_USE_MSVC_INTRINSICS #include #endif @@ -102,7 +105,7 @@ #endif #if JUCE_ANDROID - #include + #include #include #endif @@ -111,6 +114,8 @@ #undef TYPE_BOOL #undef max #undef min +#undef major +#undef minor //============================================================================== // DLL building settings on Windows diff --git a/JuceLibraryCode/modules/juce_core/system/juce_SystemStats.cpp b/JuceLibraryCode/modules/juce_core/system/juce_SystemStats.cpp index 365e94d..65bb117 100644 --- a/JuceLibraryCode/modules/juce_core/system/juce_SystemStats.cpp +++ b/JuceLibraryCode/modules/juce_core/system/juce_SystemStats.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this @@ -67,7 +67,8 @@ struct CPUInformation { CPUInformation() noexcept : numCpus (0), hasMMX (false), hasSSE (false), - hasSSE2 (false), hasSSE3 (false), has3DNow (false) + hasSSE2 (false), hasSSE3 (false), has3DNow (false), + hasSSSE3 (false), hasAVX (false) { initialise(); } @@ -75,7 +76,7 @@ struct CPUInformation void initialise() noexcept; int numCpus; - bool hasMMX, hasSSE, hasSSE2, hasSSE3, has3DNow; + bool hasMMX, hasSSE, hasSSE2, hasSSE3, has3DNow, hasSSSE3, hasAVX; }; static const CPUInformation& getCPUInformation() noexcept @@ -86,10 +87,12 @@ static const CPUInformation& getCPUInformation() noexcept int SystemStats::getNumCpus() noexcept { return getCPUInformation().numCpus; } bool SystemStats::hasMMX() noexcept { return getCPUInformation().hasMMX; } +bool SystemStats::has3DNow() noexcept { return getCPUInformation().has3DNow; } bool SystemStats::hasSSE() noexcept { return getCPUInformation().hasSSE; } bool SystemStats::hasSSE2() noexcept { return getCPUInformation().hasSSE2; } bool SystemStats::hasSSE3() noexcept { return getCPUInformation().hasSSE3; } -bool SystemStats::has3DNow() noexcept { return getCPUInformation().has3DNow; } +bool SystemStats::hasSSSE3() noexcept { return getCPUInformation().hasSSSE3; } +bool SystemStats::hasAVX() noexcept { return getCPUInformation().hasAVX; } //============================================================================== diff --git a/JuceLibraryCode/modules/juce_core/system/juce_SystemStats.h b/JuceLibraryCode/modules/juce_core/system/juce_SystemStats.h index 833bf5a..540bf73 100644 --- a/JuceLibraryCode/modules/juce_core/system/juce_SystemStats.h +++ b/JuceLibraryCode/modules/juce_core/system/juce_SystemStats.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this @@ -47,27 +47,31 @@ public: /** The set of possible results of the getOperatingSystemType() method. */ enum OperatingSystemType { - UnknownOS = 0, + UnknownOS = 0, - Linux = 0x2000, - Android = 0x3000, - iOS = 0x8000, + MacOSX = 0x0100, /**< To test whether any version of OSX is running, + you can use the expression ((getOperatingSystemType() & MacOSX) != 0). */ + Windows = 0x0200, /**< To test whether any version of Windows is running, + you can use the expression ((getOperatingSystemType() & Windows) != 0). */ + Linux = 0x0400, + Android = 0x0800, + iOS = 0x1000, - MacOSX_10_4 = 0x1004, - MacOSX_10_5 = 0x1005, - MacOSX_10_6 = 0x1006, - MacOSX_10_7 = 0x1007, - MacOSX_10_8 = 0x1008, - MacOSX_10_9 = 0x1009, + MacOSX_10_4 = MacOSX | 4, + MacOSX_10_5 = MacOSX | 5, + MacOSX_10_6 = MacOSX | 6, + MacOSX_10_7 = MacOSX | 7, + MacOSX_10_8 = MacOSX | 8, + MacOSX_10_9 = MacOSX | 9, + MacOSX_10_10 = MacOSX | 10, - Win2000 = 0x4105, - WinXP = 0x4106, - WinVista = 0x4107, - Windows7 = 0x4108, - Windows8 = 0x4109, - - Windows = 0x4000, /**< To test whether any version of Windows is running, - you can use the expression ((getOperatingSystemType() & Windows) != 0). */ + Win2000 = Windows | 1, + WinXP = Windows | 2, + WinVista = Windows | 3, + Windows7 = Windows | 4, + Windows8_0 = Windows | 5, + Windows8_1 = Windows | 6, + Windows10 = Windows | 7 }; /** Returns the type of operating system we're running on. @@ -148,10 +152,12 @@ public: static String getCpuVendor(); static bool hasMMX() noexcept; /**< Returns true if Intel MMX instructions are available. */ + static bool has3DNow() noexcept; /**< Returns true if AMD 3DNOW instructions are available. */ static bool hasSSE() noexcept; /**< Returns true if Intel SSE instructions are available. */ static bool hasSSE2() noexcept; /**< Returns true if Intel SSE2 instructions are available. */ static bool hasSSE3() noexcept; /**< Returns true if Intel SSE2 instructions are available. */ - static bool has3DNow() noexcept; /**< Returns true if AMD 3DNOW instructions are available. */ + static bool hasSSSE3() noexcept; /**< Returns true if Intel SSSE3 instructions are available. */ + static bool hasAVX() noexcept; /**< Returns true if Intel AVX instructions are available. */ //============================================================================== /** Finds out how much RAM is in the machine. diff --git a/JuceLibraryCode/modules/juce_core/system/juce_TargetPlatform.h b/JuceLibraryCode/modules/juce_core/system/juce_TargetPlatform.h index 86adc38..75e363f 100644 --- a/JuceLibraryCode/modules/juce_core/system/juce_TargetPlatform.h +++ b/JuceLibraryCode/modules/juce_core/system/juce_TargetPlatform.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this @@ -155,7 +155,7 @@ #define JUCE_BIG_ENDIAN 1 #endif - #if defined (__LP64__) || defined (_LP64) + #if defined (__LP64__) || defined (_LP64) || defined (__arm64__) #define JUCE_64BIT 1 #else #define JUCE_32BIT 1 @@ -192,7 +192,7 @@ #endif #if JUCE_64BIT || ! JUCE_VC7_OR_EARLIER - #define JUCE_USE_INTRINSICS 1 + #define JUCE_USE_MSVC_INTRINSICS 1 #endif #else #error unknown compiler diff --git a/JuceLibraryCode/modules/juce_core/text/juce_CharPointer_ASCII.h b/JuceLibraryCode/modules/juce_core/text/juce_CharPointer_ASCII.h index a966543..3b68e4c 100644 --- a/JuceLibraryCode/modules/juce_core/text/juce_CharPointer_ASCII.h +++ b/JuceLibraryCode/modules/juce_core/text/juce_CharPointer_ASCII.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this @@ -276,8 +276,10 @@ public: int compareIgnoreCase (const CharPointer_ASCII other) const { - #if JUCE_WINDOWS + #if JUCE_MSVC return stricmp (data, other.data); + #elif JUCE_MINGW + return CharacterFunctions::compareIgnoreCase (*this, other); #else return strcasecmp (data, other.data); #endif @@ -344,7 +346,7 @@ public: /** Parses this string as a 64-bit integer. */ int64 getIntValue64() const noexcept { - #if JUCE_LINUX || JUCE_ANDROID + #if JUCE_LINUX || JUCE_ANDROID || JUCE_MINGW return atoll (data); #elif JUCE_WINDOWS return _atoi64 (data); diff --git a/JuceLibraryCode/modules/juce_core/text/juce_CharPointer_UTF16.h b/JuceLibraryCode/modules/juce_core/text/juce_CharPointer_UTF16.h index d0eba5c..7a245e1 100644 --- a/JuceLibraryCode/modules/juce_core/text/juce_CharPointer_UTF16.h +++ b/JuceLibraryCode/modules/juce_core/text/juce_CharPointer_UTF16.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this @@ -349,7 +349,7 @@ public: return CharacterFunctions::compareIgnoreCaseUpTo (*this, other, maxChars); } - #if JUCE_WINDOWS && ! DOXYGEN + #if JUCE_MSVC && ! DOXYGEN int compareIgnoreCase (const CharPointer_UTF16 other) const noexcept { return _wcsicmp (data, other.data); @@ -408,7 +408,7 @@ public: /** Parses this string as a 32-bit integer. */ int getIntValue32() const noexcept { - #if JUCE_WINDOWS + #if JUCE_MSVC return _wtoi (data); #else return CharacterFunctions::getIntValue (*this); @@ -418,7 +418,7 @@ public: /** Parses this string as a 64-bit integer. */ int64 getIntValue64() const noexcept { - #if JUCE_WINDOWS + #if JUCE_MSVC return _wtoi64 (data); #else return CharacterFunctions::getIntValue (*this); diff --git a/JuceLibraryCode/modules/juce_core/text/juce_CharPointer_UTF32.h b/JuceLibraryCode/modules/juce_core/text/juce_CharPointer_UTF32.h index 42cfe48..9e96d70 100644 --- a/JuceLibraryCode/modules/juce_core/text/juce_CharPointer_UTF32.h +++ b/JuceLibraryCode/modules/juce_core/text/juce_CharPointer_UTF32.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this diff --git a/JuceLibraryCode/modules/juce_core/text/juce_CharPointer_UTF8.h b/JuceLibraryCode/modules/juce_core/text/juce_CharPointer_UTF8.h index 78d9a97..9c466f3 100644 --- a/JuceLibraryCode/modules/juce_core/text/juce_CharPointer_UTF8.h +++ b/JuceLibraryCode/modules/juce_core/text/juce_CharPointer_UTF8.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this @@ -421,8 +421,10 @@ public: /** Compares this string with another one. */ int compareIgnoreCase (const CharPointer_UTF8 other) const noexcept { - #if JUCE_WINDOWS + #if JUCE_MSVC return stricmp (data, other.data); + #elif JUCE_MINGW + return CharacterFunctions::compareIgnoreCase (*this, other); #else return strcasecmp (data, other.data); #endif @@ -456,9 +458,9 @@ public: } /** Returns true if the first character of this string is whitespace. */ - bool isWhitespace() const noexcept { return *data == ' ' || (*data <= 13 && *data >= 9); } + bool isWhitespace() const noexcept { const CharType c = *data; return c == ' ' || (c <= 13 && c >= 9); } /** Returns true if the first character of this string is a digit. */ - bool isDigit() const noexcept { return *data >= '0' && *data <= '9'; } + bool isDigit() const noexcept { const CharType c = *data; return c >= '0' && c <= '9'; } /** Returns true if the first character of this string is a letter. */ bool isLetter() const noexcept { return CharacterFunctions::isLetter (operator*()) != 0; } /** Returns true if the first character of this string is a letter or digit. */ @@ -479,7 +481,7 @@ public: /** Parses this string as a 64-bit integer. */ int64 getIntValue64() const noexcept { - #if JUCE_LINUX || JUCE_ANDROID + #if JUCE_LINUX || JUCE_ANDROID || JUCE_MINGW return atoll (data); #elif JUCE_WINDOWS return _atoi64 (data); @@ -509,7 +511,7 @@ public: if (byte < 0) { - uint8 bit = 0x40; + int bit = 0x40; int numExtraValues = 0; while ((byte & bit) != 0) diff --git a/JuceLibraryCode/modules/juce_core/text/juce_CharacterFunctions.cpp b/JuceLibraryCode/modules/juce_core/text/juce_CharacterFunctions.cpp index 11eaa18..9b9d7a9 100644 --- a/JuceLibraryCode/modules/juce_core/text/juce_CharacterFunctions.cpp +++ b/JuceLibraryCode/modules/juce_core/text/juce_CharacterFunctions.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this @@ -34,18 +34,18 @@ juce_wchar CharacterFunctions::toUpperCase (const juce_wchar character) noexcept { - return towupper ((wchar_t) character); + return (juce_wchar) towupper ((wint_t) character); } juce_wchar CharacterFunctions::toLowerCase (const juce_wchar character) noexcept { - return towlower ((wchar_t) character); + return (juce_wchar) towlower ((wint_t) character); } bool CharacterFunctions::isUpperCase (const juce_wchar character) noexcept { #if JUCE_WINDOWS - return iswupper ((wchar_t) character) != 0; + return iswupper ((wint_t) character) != 0; #else return toLowerCase (character) != character; #endif @@ -54,7 +54,7 @@ bool CharacterFunctions::isUpperCase (const juce_wchar character) noexcept bool CharacterFunctions::isLowerCase (const juce_wchar character) noexcept { #if JUCE_WINDOWS - return iswlower ((wchar_t) character) != 0; + return iswlower ((wint_t) character) != 0; #else return toUpperCase (character) != character; #endif @@ -72,7 +72,7 @@ bool CharacterFunctions::isWhitespace (const char character) noexcept bool CharacterFunctions::isWhitespace (const juce_wchar character) noexcept { - return iswspace ((wchar_t) character) != 0; + return iswspace ((wint_t) character) != 0; } bool CharacterFunctions::isDigit (const char character) noexcept @@ -82,7 +82,7 @@ bool CharacterFunctions::isDigit (const char character) noexcept bool CharacterFunctions::isDigit (const juce_wchar character) noexcept { - return iswdigit ((wchar_t) character) != 0; + return iswdigit ((wint_t) character) != 0; } bool CharacterFunctions::isLetter (const char character) noexcept @@ -93,7 +93,7 @@ bool CharacterFunctions::isLetter (const char character) noexcept bool CharacterFunctions::isLetter (const juce_wchar character) noexcept { - return iswalpha ((wchar_t) character) != 0; + return iswalpha ((wint_t) character) != 0; } bool CharacterFunctions::isLetterOrDigit (const char character) noexcept @@ -105,7 +105,7 @@ bool CharacterFunctions::isLetterOrDigit (const char character) noexcept bool CharacterFunctions::isLetterOrDigit (const juce_wchar character) noexcept { - return iswalnum ((wchar_t) character) != 0; + return iswalnum ((wint_t) character) != 0; } int CharacterFunctions::getHexDigitValue (const juce_wchar digit) noexcept diff --git a/JuceLibraryCode/modules/juce_core/text/juce_CharacterFunctions.h b/JuceLibraryCode/modules/juce_core/text/juce_CharacterFunctions.h index bade0dd..82adf54 100644 --- a/JuceLibraryCode/modules/juce_core/text/juce_CharacterFunctions.h +++ b/JuceLibraryCode/modules/juce_core/text/juce_CharacterFunctions.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this diff --git a/JuceLibraryCode/modules/juce_core/text/juce_Identifier.cpp b/JuceLibraryCode/modules/juce_core/text/juce_Identifier.cpp index bac4dd5..13821b6 100644 --- a/JuceLibraryCode/modules/juce_core/text/juce_Identifier.cpp +++ b/JuceLibraryCode/modules/juce_core/text/juce_Identifier.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this @@ -31,7 +31,17 @@ Identifier::~Identifier() noexcept {} Identifier::Identifier (const Identifier& other) noexcept : name (other.name) {} -Identifier& Identifier::operator= (const Identifier other) noexcept +#if JUCE_COMPILER_SUPPORTS_MOVE_SEMANTICS +Identifier::Identifier (Identifier&& other) noexcept : name (static_cast (other.name)) {} + +Identifier& Identifier::operator= (Identifier&& other) noexcept +{ + name = static_cast (other.name); + return *this; +} +#endif + +Identifier& Identifier::operator= (const Identifier& other) noexcept { name = other.name; return *this; @@ -40,25 +50,22 @@ Identifier& Identifier::operator= (const Identifier other) noexcept Identifier::Identifier (const String& nm) : name (StringPool::getGlobalPool().getPooledString (nm)) { - /* An Identifier string must be suitable for use as a script variable or XML - attribute, so it can only contain this limited set of characters.. */ - jassert (isValidIdentifier (toString())); + // An Identifier cannot be created from an empty string! + jassert (nm.isNotEmpty()); } Identifier::Identifier (const char* nm) : name (StringPool::getGlobalPool().getPooledString (nm)) { - /* An Identifier string must be suitable for use as a script variable or XML - attribute, so it can only contain this limited set of characters.. */ - jassert (isValidIdentifier (toString())); + // An Identifier cannot be created from an empty string! + jassert (nm != nullptr && nm[0] != 0); } Identifier::Identifier (String::CharPointerType start, String::CharPointerType end) : name (StringPool::getGlobalPool().getPooledString (start, end)) { - /* An Identifier string must be suitable for use as a script variable or XML - attribute, so it can only contain this limited set of characters.. */ - jassert (isValidIdentifier (toString())); + // An Identifier cannot be created from an empty string! + jassert (start < end); } Identifier Identifier::null; diff --git a/JuceLibraryCode/modules/juce_core/text/juce_Identifier.h b/JuceLibraryCode/modules/juce_core/text/juce_Identifier.h index f60eec8..7891443 100644 --- a/JuceLibraryCode/modules/juce_core/text/juce_Identifier.h +++ b/JuceLibraryCode/modules/juce_core/text/juce_Identifier.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this @@ -68,16 +68,24 @@ public: Identifier (const Identifier& other) noexcept; /** Creates a copy of another identifier. */ - Identifier& operator= (const Identifier other) noexcept; + Identifier& operator= (const Identifier& other) noexcept; + + #if JUCE_COMPILER_SUPPORTS_MOVE_SEMANTICS + /** Creates a copy of another identifier. */ + Identifier (Identifier&& other) noexcept; + + /** Creates a copy of another identifier. */ + Identifier& operator= (Identifier&& other) noexcept; + #endif /** Destructor */ ~Identifier() noexcept; /** Compares two identifiers. This is a very fast operation. */ - inline bool operator== (Identifier other) const noexcept { return name.getCharPointer() == other.name.getCharPointer(); } + inline bool operator== (const Identifier& other) const noexcept { return name.getCharPointer() == other.name.getCharPointer(); } /** Compares two identifiers. This is a very fast operation. */ - inline bool operator!= (Identifier other) const noexcept { return name.getCharPointer() != other.name.getCharPointer(); } + inline bool operator!= (const Identifier& other) const noexcept { return name.getCharPointer() != other.name.getCharPointer(); } /** Compares the identifier with a string. */ inline bool operator== (StringRef other) const noexcept { return name == other; } diff --git a/JuceLibraryCode/modules/juce_core/text/juce_LocalisedStrings.cpp b/JuceLibraryCode/modules/juce_core/text/juce_LocalisedStrings.cpp index e6118d3..3671fe0 100644 --- a/JuceLibraryCode/modules/juce_core/text/juce_LocalisedStrings.cpp +++ b/JuceLibraryCode/modules/juce_core/text/juce_LocalisedStrings.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this diff --git a/JuceLibraryCode/modules/juce_core/text/juce_LocalisedStrings.h b/JuceLibraryCode/modules/juce_core/text/juce_LocalisedStrings.h index a594919..8eb7998 100644 --- a/JuceLibraryCode/modules/juce_core/text/juce_LocalisedStrings.h +++ b/JuceLibraryCode/modules/juce_core/text/juce_LocalisedStrings.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this diff --git a/JuceLibraryCode/modules/juce_core/text/juce_NewLine.h b/JuceLibraryCode/modules/juce_core/text/juce_NewLine.h index 980ac23..0d310cd 100644 --- a/JuceLibraryCode/modules/juce_core/text/juce_NewLine.h +++ b/JuceLibraryCode/modules/juce_core/text/juce_NewLine.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this diff --git a/JuceLibraryCode/modules/juce_core/text/juce_String.cpp b/JuceLibraryCode/modules/juce_core/text/juce_String.cpp index 81e234e..39e2843 100644 --- a/JuceLibraryCode/modules/juce_core/text/juce_String.cpp +++ b/JuceLibraryCode/modules/juce_core/text/juce_String.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this @@ -221,8 +221,8 @@ private: static inline StringHolder* bufferFromText (const CharPointerType text) noexcept { // (Can't use offsetof() here because of warnings about this not being a POD) - return reinterpret_cast (reinterpret_cast (text.getAddress()) - - (reinterpret_cast (reinterpret_cast (1)->text) - 1)); + return reinterpret_cast (reinterpret_cast (text.getAddress()) + - (reinterpret_cast (reinterpret_cast (1)->text) - 1)); } void compileTimeChecks() @@ -558,7 +558,7 @@ struct HashGenerator Type result = Type(); while (! t.isEmpty()) - result = multiplier * result + t.getAndAdvance(); + result = ((Type) multiplier) * result + (Type) t.getAndAdvance(); return result; } @@ -566,9 +566,9 @@ struct HashGenerator enum { multiplier = sizeof (Type) > 4 ? 101 : 31 }; }; -int String::hashCode() const noexcept { return HashGenerator ::calculate (text); } -int64 String::hashCode64() const noexcept { return HashGenerator ::calculate (text); } -std::size_t String::hash() const noexcept { return HashGenerator::calculate (text); } +int String::hashCode() const noexcept { return HashGenerator ::calculate (text); } +int64 String::hashCode64() const noexcept { return HashGenerator ::calculate (text); } +size_t String::hash() const noexcept { return HashGenerator ::calculate (text); } //============================================================================== JUCE_API bool JUCE_CALLTYPE operator== (const String& s1, const String& s2) noexcept { return s1.compare (s2) == 0; } @@ -618,25 +618,110 @@ int String::compare (const char* const other) const noexcept { return text int String::compare (const wchar_t* const other) const noexcept { return text.compare (castToCharPointer_wchar_t (other)); } int String::compareIgnoreCase (const String& other) const noexcept { return (text == other.text) ? 0 : text.compareIgnoreCase (other.text); } -int String::compareLexicographically (const String& other) const noexcept +static int stringCompareRight (String::CharPointerType s1, String::CharPointerType s2) noexcept { - CharPointerType s1 (text); + for (int bias = 0;;) + { + const juce_wchar c1 = s1.getAndAdvance(); + const bool isDigit1 = CharacterFunctions::isDigit (c1); - while (! (s1.isEmpty() || s1.isLetterOrDigit())) - ++s1; + const juce_wchar c2 = s2.getAndAdvance(); + const bool isDigit2 = CharacterFunctions::isDigit (c2); - CharPointerType s2 (other.text); + if (! (isDigit1 || isDigit2)) return bias; + if (! isDigit1) return -1; + if (! isDigit2) return 1; - while (! (s2.isEmpty() || s2.isLetterOrDigit())) - ++s2; + if (c1 != c2 && bias == 0) + bias = c1 < c2 ? -1 : 1; - return s1.compareIgnoreCase (s2); + jassert (c1 != 0 && c2 != 0); + } +} + +static int stringCompareLeft (String::CharPointerType s1, String::CharPointerType s2) noexcept +{ + for (;;) + { + const juce_wchar c1 = s1.getAndAdvance(); + const bool isDigit1 = CharacterFunctions::isDigit (c1); + + const juce_wchar c2 = s2.getAndAdvance(); + const bool isDigit2 = CharacterFunctions::isDigit (c2); + + if (! (isDigit1 || isDigit2)) return 0; + if (! isDigit1) return -1; + if (! isDigit2) return 1; + if (c1 < c2) return -1; + if (c1 > c2) return 1; + } +} + +static int naturalStringCompare (String::CharPointerType s1, String::CharPointerType s2) noexcept +{ + bool firstLoop = true; + + for (;;) + { + const bool hasSpace1 = s1.isWhitespace(); + const bool hasSpace2 = s2.isWhitespace(); + + if ((! firstLoop) && (hasSpace1 ^ hasSpace2)) + return hasSpace2 ? 1 : -1; + + firstLoop = false; + + if (hasSpace1) s1 = s1.findEndOfWhitespace(); + if (hasSpace2) s2 = s2.findEndOfWhitespace(); + + if (s1.isDigit() && s2.isDigit()) + { + const int result = (*s1 == '0' || *s2 == '0') ? stringCompareLeft (s1, s2) + : stringCompareRight (s1, s2); + + if (result != 0) + return result; + } + + juce_wchar c1 = s1.getAndAdvance(); + juce_wchar c2 = s2.getAndAdvance(); + + if (c1 != c2) + { + c1 = CharacterFunctions::toUpperCase (c1); + c2 = CharacterFunctions::toUpperCase (c2); + } + + if (c1 == c2) + { + if (c1 == 0) + return 0; + } + else + { + const bool isAlphaNum1 = CharacterFunctions::isLetterOrDigit (c1); + const bool isAlphaNum2 = CharacterFunctions::isLetterOrDigit (c2); + + if (isAlphaNum2 && ! isAlphaNum1) return -1; + if (isAlphaNum1 && ! isAlphaNum2) return 1; + + return c1 < c2 ? -1 : 1; + } + + jassert (c1 != 0 && c2 != 0); + } +} + +int String::compareNatural (StringRef other) const noexcept +{ + return naturalStringCompare (getCharPointer(), other.text); } //============================================================================== void String::append (const String& textToAppend, size_t maxCharsToTake) { - appendCharPointer (textToAppend.text, maxCharsToTake); + appendCharPointer (this == &textToAppend ? String (textToAppend).text + : textToAppend.text, maxCharsToTake); } void String::appendCharPointer (const CharPointerType textToAppend) @@ -681,6 +766,9 @@ String& String::operator+= (const String& other) if (isEmpty()) return operator= (other); + if (this == &other) + return operator+= (String (*this)); + appendCharPointer (other.text); return *this; } @@ -1529,10 +1617,10 @@ String String::upToLastOccurrenceOf (StringRef sub, bool String::isQuotedString() const { - const String trimmed (trimStart()); + const juce_wchar trimmedStart = trimStart()[0]; - return trimmed[0] == '"' - || trimmed[0] == '\''; + return trimmedStart == '"' + || trimmedStart == '\''; } String String::unquoted() const @@ -1760,13 +1848,13 @@ String String::formatted (const String pf, ... ) va_start (args, pf); #if JUCE_WINDOWS - HeapBlock temp (bufferSize); + HeapBlock temp (bufferSize); const int num = (int) _vsnwprintf (temp.getData(), bufferSize - 1, pf.toWideCharPointer(), args); #elif JUCE_ANDROID - HeapBlock temp (bufferSize); + HeapBlock temp (bufferSize); const int num = (int) vsnprintf (temp.getData(), bufferSize - 1, pf.toUTF8(), args); #else - HeapBlock temp (bufferSize); + HeapBlock temp (bufferSize); const int num = (int) vswprintf (temp.getData(), bufferSize - 1, pf.toWideCharPointer(), args); #endif @@ -1921,12 +2009,12 @@ struct StringEncodingConverter { static CharPointerType_Dest convert (const String& s) { - String& source = const_cast (s); + String& source = const_cast (s); typedef typename CharPointerType_Dest::CharType DestChar; if (source.isEmpty()) - return CharPointerType_Dest (reinterpret_cast (&emptyChar)); + return CharPointerType_Dest (reinterpret_cast (&emptyChar)); CharPointerType_Src text (source.getCharPointer()); const size_t extraBytesNeeded = CharPointerType_Dest::getBytesRequiredFor (text) + sizeof (typename CharPointerType_Dest::CharType); @@ -1936,7 +2024,7 @@ struct StringEncodingConverter text = source.getCharPointer(); void* const newSpace = addBytesToPointer (text.getAddress(), (int) endOffset); - const CharPointerType_Dest extraSpace (static_cast (newSpace)); + const CharPointerType_Dest extraSpace (static_cast (newSpace)); #if JUCE_DEBUG // (This just avoids spurious warnings from valgrind about the uninitialised bytes at the end of the buffer..) const size_t bytesToClear = (size_t) jmin ((int) extraBytesNeeded, 4); @@ -2189,6 +2277,12 @@ public: expect (s.compare (String ("012345678")) == 0); expect (s.compare (String ("012345679")) < 0); expect (s.compare (String ("012345676")) > 0); + expect (String("a").compareNatural ("A") == 0); + expect (String("A").compareNatural ("B") < 0); + expect (String("a").compareNatural ("B") < 0); + expect (String("10").compareNatural ("2") > 0); + expect (String("Abc 10").compareNatural ("aBC 2") > 0); + expect (String("Abc 1").compareNatural ("aBC 2") < 0); expect (s.substring (2, 3) == String::charToString (s[2])); expect (s.substring (0, 1) == String::charToString (s[0])); expect (s.getLastCharacter() == s [s.length() - 1]); @@ -2428,14 +2522,13 @@ public: beginTest ("var"); var v1 = 0; - var v2 = 0.1; - var v3 = "0.1"; + var v2 = 0.16; + var v3 = "0.16"; var v4 = (int64) 0; var v5 = 0.0; expect (! v2.equals (v1)); expect (! v1.equals (v2)); expect (v2.equals (v3)); - expect (v3.equals (v2)); expect (! v3.equals (v1)); expect (! v1.equals (v3)); expect (v1.equals (v4)); diff --git a/JuceLibraryCode/modules/juce_core/text/juce_String.h b/JuceLibraryCode/modules/juce_core/text/juce_String.h index 1827d54..5c2a89f 100644 --- a/JuceLibraryCode/modules/juce_core/text/juce_String.h +++ b/JuceLibraryCode/modules/juce_core/text/juce_String.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this @@ -89,12 +89,12 @@ public: */ String (const char* text, size_t maxChars); - /** Creates a string from a whcar_t character string. + /** Creates a string from a wchar_t character string. Depending on the platform, this may be treated as either UTF-32 or UTF-16. */ String (const wchar_t* text); - /** Creates a string from a whcar_t character string. + /** Creates a string from a wchar_t character string. Depending on the platform, this may be treated as either UTF-32 or UTF-16. */ String (const wchar_t* text, size_t maxChars); @@ -167,7 +167,7 @@ public: typedef CharPointer_UTF32 CharPointerType; #elif (JUCE_STRING_UTF_TYPE == 16) typedef CharPointer_UTF16 CharPointerType; - #elif (JUCE_STRING_UTF_TYPE == 8) + #elif (DOXYGEN || JUCE_STRING_UTF_TYPE == 8) typedef CharPointer_UTF8 CharPointerType; #else #error "You must set the value of JUCE_STRING_UTF_TYPE to be either 8, 16, or 32!" @@ -181,7 +181,7 @@ public: int64 hashCode64() const noexcept; /** Generates a probably-unique hashcode from this string. */ - std::size_t hash() const noexcept; + size_t hash() const noexcept; /** Returns the number of characters in the string. */ int length() const noexcept; @@ -299,13 +299,13 @@ public: Note that there's also an isNotEmpty() method to help write readable code. @see containsNonWhitespaceChars() */ - inline bool isEmpty() const noexcept { return text[0] == 0; } + inline bool isEmpty() const noexcept { return text.isEmpty(); } /** Returns true if the string contains at least one character. Note that there's also an isEmpty() method to help write readable code. @see containsNonWhitespaceChars() */ - inline bool isNotEmpty() const noexcept { return text[0] != 0; } + inline bool isNotEmpty() const noexcept { return ! text.isEmpty(); } /** Resets this string to be empty. */ void clear() noexcept; @@ -346,15 +346,15 @@ public: */ int compareIgnoreCase (const String& other) const noexcept; - /** Lexicographic comparison with another string. + /** Compares two strings, taking into account textual characteristics like numbers and spaces. - The comparison used here is case-insensitive and ignores leading non-alphanumeric - characters, making it good for sorting human-readable strings. + This comparison is case-insensitive and can detect words and embedded numbers in the + strings, making it good for sorting human-readable lists of things like filenames. @returns 0 if the two strings are identical; negative if this string comes before the other one alphabetically, or positive if it comes after it. */ - int compareLexicographically (const String& other) const noexcept; + int compareNatural (StringRef other) const noexcept; /** Tests whether the string begins with another string. If the parameter is an empty string, this will always return true. @@ -1204,16 +1204,16 @@ public: //============================================================================== #if JUCE_MAC || JUCE_IOS || DOXYGEN - /** MAC ONLY - Creates a String from an OSX CFString. */ + /** OSX ONLY - Creates a String from an OSX CFString. */ static String fromCFString (CFStringRef cfString); - /** MAC ONLY - Converts this string to a CFString. + /** OSX ONLY - Converts this string to a CFString. Remember that you must use CFRelease() to free the returned string when you're finished with it. */ CFStringRef toCFString() const; - /** MAC ONLY - Returns a copy of this string in which any decomposed unicode characters have + /** OSX ONLY - Returns a copy of this string in which any decomposed unicode characters have been converted to their precomposed equivalents. */ String convertToPrecomposedUnicode() const; #endif diff --git a/JuceLibraryCode/modules/juce_core/text/juce_StringArray.cpp b/JuceLibraryCode/modules/juce_core/text/juce_StringArray.cpp index e26d38d..de6ac3e 100644 --- a/JuceLibraryCode/modules/juce_core/text/juce_StringArray.cpp +++ b/JuceLibraryCode/modules/juce_core/text/juce_StringArray.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this @@ -86,6 +86,13 @@ StringArray& StringArray::operator= (StringArray&& other) noexcept } #endif +#if JUCE_COMPILER_SUPPORTS_INITIALIZER_LISTS +StringArray::StringArray (const std::initializer_list& stringList) +{ + strings.addArray (stringList); +} +#endif + StringArray::~StringArray() { } @@ -199,6 +206,11 @@ int StringArray::indexOf (StringRef stringToLookFor, const bool ignoreCase, int return -1; } +void StringArray::move (const int currentIndex, const int newIndex) noexcept +{ + strings.move (currentIndex, newIndex); +} + //============================================================================== void StringArray::remove (const int index) { @@ -255,12 +267,17 @@ void StringArray::trim() //============================================================================== struct InternalStringArrayComparator_CaseSensitive { - static int compareElements (String& first, String& second) { return first.compare (second); } + static int compareElements (String& s1, String& s2) noexcept { return s1.compare (s2); } }; struct InternalStringArrayComparator_CaseInsensitive { - static int compareElements (String& first, String& second) { return first.compareIgnoreCase (second); } + static int compareElements (String& s1, String& s2) noexcept { return s1.compareIgnoreCase (s2); } +}; + +struct InternalStringArrayComparator_Natural +{ + static int compareElements (String& s1, String& s2) noexcept { return s1.compareNatural (s2); } }; void StringArray::sort (const bool ignoreCase) @@ -277,12 +294,12 @@ void StringArray::sort (const bool ignoreCase) } } -void StringArray::move (const int currentIndex, int newIndex) noexcept +void StringArray::sortNatural() { - strings.move (currentIndex, newIndex); + InternalStringArrayComparator_Natural comp; + strings.sort (comp); } - //============================================================================== String StringArray::joinIntoString (StringRef separator, int start, int numberToJoin) const { diff --git a/JuceLibraryCode/modules/juce_core/text/juce_StringArray.h b/JuceLibraryCode/modules/juce_core/text/juce_StringArray.h index 251a44d..4108c0d 100644 --- a/JuceLibraryCode/modules/juce_core/text/juce_StringArray.h +++ b/JuceLibraryCode/modules/juce_core/text/juce_StringArray.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this @@ -86,6 +86,10 @@ public: */ StringArray (const wchar_t* const* strings, int numberOfStrings); + #if JUCE_COMPILER_SUPPORTS_INITIALIZER_LISTS + StringArray (const std::initializer_list& strings); + #endif + /** Destructor. */ ~StringArray(); @@ -134,18 +138,12 @@ public: /** Returns a pointer to the first String in the array. This method is provided for compatibility with standard C++ iteration mechanisms. */ - inline String* begin() const noexcept - { - return strings.begin(); - } + inline String* begin() const noexcept { return strings.begin(); } /** Returns a pointer to the String which follows the last element in the array. This method is provided for compatibility with standard C++ iteration mechanisms. */ - inline String* end() const noexcept - { - return strings.end(); - } + inline String* end() const noexcept { return strings.end(); } /** Searches for a string in the array. @@ -387,11 +385,16 @@ public: //============================================================================== /** Sorts the array into alphabetical order. - @param ignoreCase if true, the comparisons used will be case-sensitive. */ void sort (bool ignoreCase); + /** Sorts the array using extra language-aware rules to do a better job of comparing + words containing spaces and numbers. + @see String::compareNatural() + */ + void sortNatural(); + //============================================================================== /** Increases the array's internal storage to hold a minimum number of elements. diff --git a/JuceLibraryCode/modules/juce_core/text/juce_StringPairArray.cpp b/JuceLibraryCode/modules/juce_core/text/juce_StringPairArray.cpp index 3275d2d..d6bf37f 100644 --- a/JuceLibraryCode/modules/juce_core/text/juce_StringPairArray.cpp +++ b/JuceLibraryCode/modules/juce_core/text/juce_StringPairArray.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this diff --git a/JuceLibraryCode/modules/juce_core/text/juce_StringPairArray.h b/JuceLibraryCode/modules/juce_core/text/juce_StringPairArray.h index e1c774d..81367fd 100644 --- a/JuceLibraryCode/modules/juce_core/text/juce_StringPairArray.h +++ b/JuceLibraryCode/modules/juce_core/text/juce_StringPairArray.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this diff --git a/JuceLibraryCode/modules/juce_core/text/juce_StringPool.cpp b/JuceLibraryCode/modules/juce_core/text/juce_StringPool.cpp index 039a30b..e9d295c 100644 --- a/JuceLibraryCode/modules/juce_core/text/juce_StringPool.cpp +++ b/JuceLibraryCode/modules/juce_core/text/juce_StringPool.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this diff --git a/JuceLibraryCode/modules/juce_core/text/juce_StringPool.h b/JuceLibraryCode/modules/juce_core/text/juce_StringPool.h index 4de2186..047af53 100644 --- a/JuceLibraryCode/modules/juce_core/text/juce_StringPool.h +++ b/JuceLibraryCode/modules/juce_core/text/juce_StringPool.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this @@ -88,6 +88,8 @@ private: uint32 lastGarbageCollectionTime; void garbageCollectIfNeeded(); + + JUCE_DECLARE_NON_COPYABLE (StringPool) }; diff --git a/JuceLibraryCode/modules/juce_core/text/juce_StringRef.h b/JuceLibraryCode/modules/juce_core/text/juce_StringRef.h index 434bf4a..3c17600 100644 --- a/JuceLibraryCode/modules/juce_core/text/juce_StringRef.h +++ b/JuceLibraryCode/modules/juce_core/text/juce_StringRef.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this diff --git a/JuceLibraryCode/modules/juce_core/text/juce_TextDiff.cpp b/JuceLibraryCode/modules/juce_core/text/juce_TextDiff.cpp index 6b4c807..be805d0 100644 --- a/JuceLibraryCode/modules/juce_core/text/juce_TextDiff.cpp +++ b/JuceLibraryCode/modules/juce_core/text/juce_TextDiff.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this diff --git a/JuceLibraryCode/modules/juce_core/text/juce_TextDiff.h b/JuceLibraryCode/modules/juce_core/text/juce_TextDiff.h index d420c3d..2d1c6cb 100644 --- a/JuceLibraryCode/modules/juce_core/text/juce_TextDiff.h +++ b/JuceLibraryCode/modules/juce_core/text/juce_TextDiff.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this diff --git a/JuceLibraryCode/modules/juce_core/threads/juce_ChildProcess.cpp b/JuceLibraryCode/modules/juce_core/threads/juce_ChildProcess.cpp index 4566b13..916c03b 100644 --- a/JuceLibraryCode/modules/juce_core/threads/juce_ChildProcess.cpp +++ b/JuceLibraryCode/modules/juce_core/threads/juce_ChildProcess.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this diff --git a/JuceLibraryCode/modules/juce_core/threads/juce_ChildProcess.h b/JuceLibraryCode/modules/juce_core/threads/juce_ChildProcess.h index 0adcb57..028d6fe 100644 --- a/JuceLibraryCode/modules/juce_core/threads/juce_ChildProcess.h +++ b/JuceLibraryCode/modules/juce_core/threads/juce_ChildProcess.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this diff --git a/JuceLibraryCode/modules/juce_core/threads/juce_CriticalSection.h b/JuceLibraryCode/modules/juce_core/threads/juce_CriticalSection.h index 60e61dd..d19e945 100644 --- a/JuceLibraryCode/modules/juce_core/threads/juce_CriticalSection.h +++ b/JuceLibraryCode/modules/juce_core/threads/juce_CriticalSection.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this diff --git a/JuceLibraryCode/modules/juce_core/threads/juce_DynamicLibrary.h b/JuceLibraryCode/modules/juce_core/threads/juce_DynamicLibrary.h index df6625b..ec2fcd1 100644 --- a/JuceLibraryCode/modules/juce_core/threads/juce_DynamicLibrary.h +++ b/JuceLibraryCode/modules/juce_core/threads/juce_DynamicLibrary.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this diff --git a/JuceLibraryCode/modules/juce_core/threads/juce_HighResolutionTimer.cpp b/JuceLibraryCode/modules/juce_core/threads/juce_HighResolutionTimer.cpp index 3475b74..791255b 100644 --- a/JuceLibraryCode/modules/juce_core/threads/juce_HighResolutionTimer.cpp +++ b/JuceLibraryCode/modules/juce_core/threads/juce_HighResolutionTimer.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this diff --git a/JuceLibraryCode/modules/juce_core/threads/juce_HighResolutionTimer.h b/JuceLibraryCode/modules/juce_core/threads/juce_HighResolutionTimer.h index 21022ad..7c840af 100644 --- a/JuceLibraryCode/modules/juce_core/threads/juce_HighResolutionTimer.h +++ b/JuceLibraryCode/modules/juce_core/threads/juce_HighResolutionTimer.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this diff --git a/JuceLibraryCode/modules/juce_core/threads/juce_InterProcessLock.h b/JuceLibraryCode/modules/juce_core/threads/juce_InterProcessLock.h index dc903b0..447dc88 100644 --- a/JuceLibraryCode/modules/juce_core/threads/juce_InterProcessLock.h +++ b/JuceLibraryCode/modules/juce_core/threads/juce_InterProcessLock.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this diff --git a/JuceLibraryCode/modules/juce_core/threads/juce_Process.h b/JuceLibraryCode/modules/juce_core/threads/juce_Process.h index f3efd66..eb5d59d 100644 --- a/JuceLibraryCode/modules/juce_core/threads/juce_Process.h +++ b/JuceLibraryCode/modules/juce_core/threads/juce_Process.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this diff --git a/JuceLibraryCode/modules/juce_core/threads/juce_ReadWriteLock.cpp b/JuceLibraryCode/modules/juce_core/threads/juce_ReadWriteLock.cpp index a0821b4..e05c427 100644 --- a/JuceLibraryCode/modules/juce_core/threads/juce_ReadWriteLock.cpp +++ b/JuceLibraryCode/modules/juce_core/threads/juce_ReadWriteLock.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this diff --git a/JuceLibraryCode/modules/juce_core/threads/juce_ReadWriteLock.h b/JuceLibraryCode/modules/juce_core/threads/juce_ReadWriteLock.h index c41d258..5193782 100644 --- a/JuceLibraryCode/modules/juce_core/threads/juce_ReadWriteLock.h +++ b/JuceLibraryCode/modules/juce_core/threads/juce_ReadWriteLock.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this diff --git a/JuceLibraryCode/modules/juce_core/threads/juce_ScopedLock.h b/JuceLibraryCode/modules/juce_core/threads/juce_ScopedLock.h index 442551a..f359d9d 100644 --- a/JuceLibraryCode/modules/juce_core/threads/juce_ScopedLock.h +++ b/JuceLibraryCode/modules/juce_core/threads/juce_ScopedLock.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this diff --git a/JuceLibraryCode/modules/juce_core/threads/juce_ScopedReadLock.h b/JuceLibraryCode/modules/juce_core/threads/juce_ScopedReadLock.h index 107e838..37cf14c 100644 --- a/JuceLibraryCode/modules/juce_core/threads/juce_ScopedReadLock.h +++ b/JuceLibraryCode/modules/juce_core/threads/juce_ScopedReadLock.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this diff --git a/JuceLibraryCode/modules/juce_core/threads/juce_ScopedWriteLock.h b/JuceLibraryCode/modules/juce_core/threads/juce_ScopedWriteLock.h index 44e3198..04072df 100644 --- a/JuceLibraryCode/modules/juce_core/threads/juce_ScopedWriteLock.h +++ b/JuceLibraryCode/modules/juce_core/threads/juce_ScopedWriteLock.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this diff --git a/JuceLibraryCode/modules/juce_core/threads/juce_SpinLock.h b/JuceLibraryCode/modules/juce_core/threads/juce_SpinLock.h index 664cc3c..0d42a26 100644 --- a/JuceLibraryCode/modules/juce_core/threads/juce_SpinLock.h +++ b/JuceLibraryCode/modules/juce_core/threads/juce_SpinLock.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this diff --git a/JuceLibraryCode/modules/juce_core/threads/juce_Thread.cpp b/JuceLibraryCode/modules/juce_core/threads/juce_Thread.cpp index 3d1ff0a..6189ca5 100644 --- a/JuceLibraryCode/modules/juce_core/threads/juce_Thread.cpp +++ b/JuceLibraryCode/modules/juce_core/threads/juce_Thread.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this diff --git a/JuceLibraryCode/modules/juce_core/threads/juce_Thread.h b/JuceLibraryCode/modules/juce_core/threads/juce_Thread.h index aef96b7..89a0c50 100644 --- a/JuceLibraryCode/modules/juce_core/threads/juce_Thread.h +++ b/JuceLibraryCode/modules/juce_core/threads/juce_Thread.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this @@ -235,7 +235,7 @@ public: /** Finds the thread object that is currently running. Note that the main UI thread (or other non-Juce threads) don't have a Thread - object associated with them, so this will return 0. + object associated with them, so this will return nullptr. */ static Thread* JUCE_CALLTYPE getCurrentThread(); diff --git a/JuceLibraryCode/modules/juce_core/threads/juce_ThreadLocalValue.h b/JuceLibraryCode/modules/juce_core/threads/juce_ThreadLocalValue.h index bd5c808..19107fd 100644 --- a/JuceLibraryCode/modules/juce_core/threads/juce_ThreadLocalValue.h +++ b/JuceLibraryCode/modules/juce_core/threads/juce_ThreadLocalValue.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this diff --git a/JuceLibraryCode/modules/juce_core/threads/juce_ThreadPool.cpp b/JuceLibraryCode/modules/juce_core/threads/juce_ThreadPool.cpp index e6b0b9f..4051610 100644 --- a/JuceLibraryCode/modules/juce_core/threads/juce_ThreadPool.cpp +++ b/JuceLibraryCode/modules/juce_core/threads/juce_ThreadPool.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this diff --git a/JuceLibraryCode/modules/juce_core/threads/juce_ThreadPool.h b/JuceLibraryCode/modules/juce_core/threads/juce_ThreadPool.h index 3d5f762..3934215 100644 --- a/JuceLibraryCode/modules/juce_core/threads/juce_ThreadPool.h +++ b/JuceLibraryCode/modules/juce_core/threads/juce_ThreadPool.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this diff --git a/JuceLibraryCode/modules/juce_core/threads/juce_TimeSliceThread.cpp b/JuceLibraryCode/modules/juce_core/threads/juce_TimeSliceThread.cpp index f055a15..63d537c 100644 --- a/JuceLibraryCode/modules/juce_core/threads/juce_TimeSliceThread.cpp +++ b/JuceLibraryCode/modules/juce_core/threads/juce_TimeSliceThread.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this diff --git a/JuceLibraryCode/modules/juce_core/threads/juce_TimeSliceThread.h b/JuceLibraryCode/modules/juce_core/threads/juce_TimeSliceThread.h index 8c30567..5db4b41 100644 --- a/JuceLibraryCode/modules/juce_core/threads/juce_TimeSliceThread.h +++ b/JuceLibraryCode/modules/juce_core/threads/juce_TimeSliceThread.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this diff --git a/JuceLibraryCode/modules/juce_core/threads/juce_WaitableEvent.h b/JuceLibraryCode/modules/juce_core/threads/juce_WaitableEvent.h index 83f6f06..ce10b46 100644 --- a/JuceLibraryCode/modules/juce_core/threads/juce_WaitableEvent.h +++ b/JuceLibraryCode/modules/juce_core/threads/juce_WaitableEvent.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this diff --git a/JuceLibraryCode/modules/juce_core/time/juce_PerformanceCounter.cpp b/JuceLibraryCode/modules/juce_core/time/juce_PerformanceCounter.cpp index b22d5e4..12fac64 100644 --- a/JuceLibraryCode/modules/juce_core/time/juce_PerformanceCounter.cpp +++ b/JuceLibraryCode/modules/juce_core/time/juce_PerformanceCounter.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this diff --git a/JuceLibraryCode/modules/juce_core/time/juce_PerformanceCounter.h b/JuceLibraryCode/modules/juce_core/time/juce_PerformanceCounter.h index aac50d2..5426636 100644 --- a/JuceLibraryCode/modules/juce_core/time/juce_PerformanceCounter.h +++ b/JuceLibraryCode/modules/juce_core/time/juce_PerformanceCounter.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this diff --git a/JuceLibraryCode/modules/juce_core/time/juce_RelativeTime.cpp b/JuceLibraryCode/modules/juce_core/time/juce_RelativeTime.cpp index 6fca4fe..913cc6e 100644 --- a/JuceLibraryCode/modules/juce_core/time/juce_RelativeTime.cpp +++ b/JuceLibraryCode/modules/juce_core/time/juce_RelativeTime.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this diff --git a/JuceLibraryCode/modules/juce_core/time/juce_RelativeTime.h b/JuceLibraryCode/modules/juce_core/time/juce_RelativeTime.h index 7e39d21..76d8df5 100644 --- a/JuceLibraryCode/modules/juce_core/time/juce_RelativeTime.h +++ b/JuceLibraryCode/modules/juce_core/time/juce_RelativeTime.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this diff --git a/JuceLibraryCode/modules/juce_core/time/juce_Time.cpp b/JuceLibraryCode/modules/juce_core/time/juce_Time.cpp index 959275b..f28522c 100644 --- a/JuceLibraryCode/modules/juce_core/time/juce_Time.cpp +++ b/JuceLibraryCode/modules/juce_core/time/juce_Time.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this @@ -361,7 +361,7 @@ String Time::getTimeZone() const noexcept { String zone[2]; - #if JUCE_WINDOWS + #if JUCE_MSVC _tzset(); #ifdef _INC_TIME_INL @@ -378,7 +378,11 @@ String Time::getTimeZone() const noexcept zone[1] = zonePtr[1]; #endif #else + #if JUCE_MINGW + #warning "Can't find a replacement for tzset on mingw - ideas welcome!" + #else tzset(); + #endif const char** const zonePtr = (const char**) tzname; zone[0] = zonePtr[0]; zone[1] = zonePtr[1]; @@ -407,11 +411,11 @@ String Time::getWeekdayName (const bool threeLetterVersion) const return getWeekdayName (getDayOfWeek(), threeLetterVersion); } +static const char* const shortMonthNames[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; +static const char* const longMonthNames[] = { "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" }; + String Time::getMonthName (int monthNumber, const bool threeLetterVersion) { - static const char* const shortMonthNames[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; - static const char* const longMonthNames[] = { "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" }; - monthNumber %= 12; return TRANS (threeLetterVersion ? shortMonthNames [monthNumber] @@ -430,17 +434,40 @@ String Time::getWeekdayName (int day, const bool threeLetterVersion) } //============================================================================== -Time& Time::operator+= (RelativeTime delta) { millisSinceEpoch += delta.inMilliseconds(); return *this; } -Time& Time::operator-= (RelativeTime delta) { millisSinceEpoch -= delta.inMilliseconds(); return *this; } +Time& Time::operator+= (RelativeTime delta) noexcept { millisSinceEpoch += delta.inMilliseconds(); return *this; } +Time& Time::operator-= (RelativeTime delta) noexcept { millisSinceEpoch -= delta.inMilliseconds(); return *this; } -Time operator+ (Time time, RelativeTime delta) { Time t (time); return t += delta; } -Time operator- (Time time, RelativeTime delta) { Time t (time); return t -= delta; } -Time operator+ (RelativeTime delta, Time time) { Time t (time); return t += delta; } -const RelativeTime operator- (Time time1, Time time2) { return RelativeTime::milliseconds (time1.toMilliseconds() - time2.toMilliseconds()); } +Time operator+ (Time time, RelativeTime delta) noexcept { Time t (time); return t += delta; } +Time operator- (Time time, RelativeTime delta) noexcept { Time t (time); return t -= delta; } +Time operator+ (RelativeTime delta, Time time) noexcept { Time t (time); return t += delta; } +const RelativeTime operator- (Time time1, Time time2) noexcept { return RelativeTime::milliseconds (time1.toMilliseconds() - time2.toMilliseconds()); } -bool operator== (Time time1, Time time2) { return time1.toMilliseconds() == time2.toMilliseconds(); } -bool operator!= (Time time1, Time time2) { return time1.toMilliseconds() != time2.toMilliseconds(); } -bool operator< (Time time1, Time time2) { return time1.toMilliseconds() < time2.toMilliseconds(); } -bool operator> (Time time1, Time time2) { return time1.toMilliseconds() > time2.toMilliseconds(); } -bool operator<= (Time time1, Time time2) { return time1.toMilliseconds() <= time2.toMilliseconds(); } -bool operator>= (Time time1, Time time2) { return time1.toMilliseconds() >= time2.toMilliseconds(); } +bool operator== (Time time1, Time time2) noexcept { return time1.toMilliseconds() == time2.toMilliseconds(); } +bool operator!= (Time time1, Time time2) noexcept { return time1.toMilliseconds() != time2.toMilliseconds(); } +bool operator< (Time time1, Time time2) noexcept { return time1.toMilliseconds() < time2.toMilliseconds(); } +bool operator> (Time time1, Time time2) noexcept { return time1.toMilliseconds() > time2.toMilliseconds(); } +bool operator<= (Time time1, Time time2) noexcept { return time1.toMilliseconds() <= time2.toMilliseconds(); } +bool operator>= (Time time1, Time time2) noexcept { return time1.toMilliseconds() >= time2.toMilliseconds(); } + +static int getMonthNumberForCompileDate (const String& m) noexcept +{ + for (int i = 0; i < 12; ++i) + if (m.equalsIgnoreCase (shortMonthNames[i])) + return i; + + // If you hit this because your compiler has a non-standard __DATE__ format, + // let me know so we can add support for it! + jassertfalse; + return 0; +} + +Time Time::getCompilationDate() +{ + StringArray dateTokens; + dateTokens.addTokens (__DATE__, true); + dateTokens.removeEmptyStrings (true); + + return Time (dateTokens[2].getIntValue(), + getMonthNumberForCompileDate (dateTokens[0]), + dateTokens[1].getIntValue(), 12, 0); +} diff --git a/JuceLibraryCode/modules/juce_core/time/juce_Time.h b/JuceLibraryCode/modules/juce_core/time/juce_Time.h index f72fb2c..b51ed07 100644 --- a/JuceLibraryCode/modules/juce_core/time/juce_Time.h +++ b/JuceLibraryCode/modules/juce_core/time/juce_Time.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this @@ -253,9 +253,9 @@ public: //============================================================================== /** Adds a RelativeTime to this time. */ - Time& operator+= (RelativeTime delta); + Time& operator+= (RelativeTime delta) noexcept; /** Subtracts a RelativeTime from this time. */ - Time& operator-= (RelativeTime delta); + Time& operator-= (RelativeTime delta) noexcept; //============================================================================== /** Tries to set the computer's clock. @@ -272,8 +272,7 @@ public: @param threeLetterVersion if true, it'll return a 3-letter abbreviation, e.g. "Tue"; if false, it'll return the full version, e.g. "Tuesday". */ - static String getWeekdayName (int dayNumber, - bool threeLetterVersion); + static String getWeekdayName (int dayNumber, bool threeLetterVersion); /** Returns the name of one of the months. @@ -281,8 +280,7 @@ public: @param threeLetterVersion if true, it'll be a 3-letter abbreviation, e.g. "Jan"; if false it'll return the long form, e.g. "January" */ - static String getMonthName (int monthNumber, - bool threeLetterVersion); + static String getMonthName (int monthNumber, bool threeLetterVersion); //============================================================================== // Static methods for getting system timers directly.. @@ -370,6 +368,8 @@ public: */ static int64 secondsToHighResolutionTicks (double seconds) noexcept; + /** Returns a Time based on the value of the __DATE__ macro when this module was compiled */ + static Time getCompilationDate(); private: //============================================================================== @@ -378,27 +378,27 @@ private: //============================================================================== /** Adds a RelativeTime to a Time. */ -JUCE_API Time operator+ (Time time, RelativeTime delta); +JUCE_API Time operator+ (Time time, RelativeTime delta) noexcept; /** Adds a RelativeTime to a Time. */ -JUCE_API Time operator+ (RelativeTime delta, Time time); +JUCE_API Time operator+ (RelativeTime delta, Time time) noexcept; /** Subtracts a RelativeTime from a Time. */ -JUCE_API Time operator- (Time time, RelativeTime delta); +JUCE_API Time operator- (Time time, RelativeTime delta) noexcept; /** Returns the relative time difference between two times. */ -JUCE_API const RelativeTime operator- (Time time1, Time time2); +JUCE_API const RelativeTime operator- (Time time1, Time time2) noexcept; /** Compares two Time objects. */ -JUCE_API bool operator== (Time time1, Time time2); +JUCE_API bool operator== (Time time1, Time time2) noexcept; /** Compares two Time objects. */ -JUCE_API bool operator!= (Time time1, Time time2); +JUCE_API bool operator!= (Time time1, Time time2) noexcept; /** Compares two Time objects. */ -JUCE_API bool operator< (Time time1, Time time2); +JUCE_API bool operator< (Time time1, Time time2) noexcept; /** Compares two Time objects. */ -JUCE_API bool operator<= (Time time1, Time time2); +JUCE_API bool operator<= (Time time1, Time time2) noexcept; /** Compares two Time objects. */ -JUCE_API bool operator> (Time time1, Time time2); +JUCE_API bool operator> (Time time1, Time time2) noexcept; /** Compares two Time objects. */ -JUCE_API bool operator>= (Time time1, Time time2); +JUCE_API bool operator>= (Time time1, Time time2) noexcept; #endif // JUCE_TIME_H_INCLUDED diff --git a/JuceLibraryCode/modules/juce_core/unit_tests/juce_UnitTest.cpp b/JuceLibraryCode/modules/juce_core/unit_tests/juce_UnitTest.cpp index f5a60c1..249374b 100644 --- a/JuceLibraryCode/modules/juce_core/unit_tests/juce_UnitTest.cpp +++ b/JuceLibraryCode/modules/juce_core/unit_tests/juce_UnitTest.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this diff --git a/JuceLibraryCode/modules/juce_core/unit_tests/juce_UnitTest.h b/JuceLibraryCode/modules/juce_core/unit_tests/juce_UnitTest.h index f5908c1..02ad9f9 100644 --- a/JuceLibraryCode/modules/juce_core/unit_tests/juce_UnitTest.h +++ b/JuceLibraryCode/modules/juce_core/unit_tests/juce_UnitTest.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this diff --git a/JuceLibraryCode/modules/juce_core/xml/juce_XmlDocument.cpp b/JuceLibraryCode/modules/juce_core/xml/juce_XmlDocument.cpp index 2eab527..de77013 100644 --- a/JuceLibraryCode/modules/juce_core/xml/juce_XmlDocument.cpp +++ b/JuceLibraryCode/modules/juce_core/xml/juce_XmlDocument.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this @@ -555,7 +555,8 @@ void XmlDocument::readChildElements (XmlElement& parent) else // must be a character block { input = preWhitespaceInput; // roll back to include the leading whitespace - String textElementContent; + MemoryOutputStream textElementContent; + bool contentShouldBeUsed = ! ignoreEmptyTextElements; for (;;) { @@ -602,28 +603,20 @@ void XmlDocument::readChildElements (XmlElement& parent) input = entity.getCharPointer(); outOfData = false; - for (;;) - { - XmlElement* const n = readNextElement (true); - - if (n == nullptr) - break; - + while (XmlElement* n = readNextElement (true)) childAppender.append (n); - } input = oldInput; outOfData = oldOutOfData; } else { - textElementContent += entity; + textElementContent << entity; + contentShouldBeUsed = contentShouldBeUsed || entity.containsNonWhitespaceChars(); } } else { - const String::CharPointerType start (input); - for (;;) { const juce_wchar nextChar = *input; @@ -638,15 +631,15 @@ void XmlDocument::readChildElements (XmlElement& parent) return; } + textElementContent.appendUTF8Char (nextChar); + contentShouldBeUsed = contentShouldBeUsed || ! CharacterFunctions::isWhitespace (nextChar); ++input; } - - textElementContent.appendCharPointer (start, input); } } - if ((! ignoreEmptyTextElements) || textElementContent.containsNonWhitespaceChars()) - childAppender.append (XmlElement::createTextElement (textElementContent)); + if (contentShouldBeUsed) + childAppender.append (XmlElement::createTextElement (textElementContent.toUTF8())); } } } diff --git a/JuceLibraryCode/modules/juce_core/xml/juce_XmlDocument.h b/JuceLibraryCode/modules/juce_core/xml/juce_XmlDocument.h index d2a5b49..84d0871 100644 --- a/JuceLibraryCode/modules/juce_core/xml/juce_XmlDocument.h +++ b/JuceLibraryCode/modules/juce_core/xml/juce_XmlDocument.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this @@ -41,7 +41,7 @@ @code XmlDocument myDocument (File ("myfile.xml")); - XmlElement* mainElement = myDocument.getDocumentElement(); + ScopedPointer mainElement (myDocument.getDocumentElement()); if (mainElement == nullptr) { @@ -57,7 +57,7 @@ Or you can use the static helper methods for quick parsing.. @code - XmlElement* xml = XmlDocument::parse (myXmlFile); + ScopedPointer xml (XmlDocument::parse (myXmlFile)); if (xml != nullptr && xml->hasTagName ("foobar")) { diff --git a/JuceLibraryCode/modules/juce_core/xml/juce_XmlElement.cpp b/JuceLibraryCode/modules/juce_core/xml/juce_XmlElement.cpp index 000df15..d0fd99d 100644 --- a/JuceLibraryCode/modules/juce_core/xml/juce_XmlElement.cpp +++ b/JuceLibraryCode/modules/juce_core/xml/juce_XmlElement.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this @@ -53,7 +53,7 @@ static void sanityCheckTagName (const String& tag) (void) tag; // the tag name mustn't be empty, or it'll look like a text element! - jassert (tag.containsNonWhitespaceChars()) + jassert (tag.containsNonWhitespaceChars()); // The tag can't contain spaces or other characters that would create invalid XML! jassert (! tag.containsAnyOf (" <>/&(){}")); @@ -714,7 +714,7 @@ bool XmlElement::isEquivalentTo (const XmlElement* const other, { if (thisAtt == nullptr || otherAtt == nullptr) { - if (thisAtt == otherAtt) // both 0, so it's a match + if (thisAtt == otherAtt) // both nullptr, so it's a match break; return false; diff --git a/JuceLibraryCode/modules/juce_core/xml/juce_XmlElement.h b/JuceLibraryCode/modules/juce_core/xml/juce_XmlElement.h index 4ab4d08..b410165 100644 --- a/JuceLibraryCode/modules/juce_core/xml/juce_XmlElement.h +++ b/JuceLibraryCode/modules/juce_core/xml/juce_XmlElement.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this @@ -352,7 +352,7 @@ public: /** Returns the value of a named attribute as floating-point. - This will try to find the attribute and convert it to an integer (using + This will try to find the attribute and convert it to a double (using the String::getDoubleValue() method). @param attributeName the name of the attribute to look up @@ -599,10 +599,17 @@ public: /** Returns true if the given element is a child of this one. */ bool containsChildElement (const XmlElement* possibleChild) const noexcept; - /** Recursively searches all sub-elements to find one that contains the specified - child element. + /** Recursively searches all sub-elements of this one, looking for an element + which is the direct parent of the specified element. + + Because elements don't store a pointer to their parent, if you have one + and need to find its parent, the only way to do so is to exhaustively + search the whole tree for it. + + If the given child is found somewhere in this element's hierarchy, then + this method will return its parent. If not, it will return nullptr. */ - XmlElement* findParentElementOf (const XmlElement* elementToLookFor) noexcept; + XmlElement* findParentElementOf (const XmlElement* childToSearchFor) noexcept; //============================================================================== /** Sorts the child elements using a comparator. diff --git a/JuceLibraryCode/modules/juce_core/zip/juce_GZIPCompressorOutputStream.cpp b/JuceLibraryCode/modules/juce_core/zip/juce_GZIPCompressorOutputStream.cpp index cb9a577..f1db2b4 100644 --- a/JuceLibraryCode/modules/juce_core/zip/juce_GZIPCompressorOutputStream.cpp +++ b/JuceLibraryCode/modules/juce_core/zip/juce_GZIPCompressorOutputStream.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this diff --git a/JuceLibraryCode/modules/juce_core/zip/juce_GZIPCompressorOutputStream.h b/JuceLibraryCode/modules/juce_core/zip/juce_GZIPCompressorOutputStream.h index 3309486..5ce8c56 100644 --- a/JuceLibraryCode/modules/juce_core/zip/juce_GZIPCompressorOutputStream.h +++ b/JuceLibraryCode/modules/juce_core/zip/juce_GZIPCompressorOutputStream.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this @@ -72,7 +72,7 @@ public: the stream is closed - this means that no more data can be written to it, and any subsequent attempts to call write() will cause an assertion. */ - void flush(); + void flush() override; int64 getPosition() override; bool setPosition (int64) override; diff --git a/JuceLibraryCode/modules/juce_core/zip/juce_GZIPDecompressorInputStream.cpp b/JuceLibraryCode/modules/juce_core/zip/juce_GZIPDecompressorInputStream.cpp index 71e0850..88d49a3 100644 --- a/JuceLibraryCode/modules/juce_core/zip/juce_GZIPDecompressorInputStream.cpp +++ b/JuceLibraryCode/modules/juce_core/zip/juce_GZIPDecompressorInputStream.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this @@ -90,7 +90,7 @@ namespace zlibNamespace class GZIPDecompressorInputStream::GZIPDecompressHelper { public: - GZIPDecompressHelper (const bool dontWrap) + GZIPDecompressHelper (Format f) : finished (true), needsDictionary (false), error (true), @@ -100,7 +100,7 @@ public: { using namespace zlibNamespace; zerostruct (stream); - streamIsValid = (inflateInit2 (&stream, dontWrap ? -MAX_WBITS : MAX_WBITS) == Z_OK); + streamIsValid = (inflateInit2 (&stream, getBitsForFormat (f)) == Z_OK); finished = error = ! streamIsValid; } @@ -157,6 +157,19 @@ public: return 0; } + static int getBitsForFormat (Format f) noexcept + { + switch (f) + { + case zlibFormat: return MAX_WBITS; + case deflateFormat: return -MAX_WBITS; + case gzipFormat: return MAX_WBITS | 16; + default: jassertfalse; break; + } + + return MAX_WBITS; + } + bool finished, needsDictionary, error, streamIsValid; enum { gzipDecompBufferSize = 32768 }; @@ -170,32 +183,30 @@ private: }; //============================================================================== -GZIPDecompressorInputStream::GZIPDecompressorInputStream (InputStream* const source, - const bool deleteSourceWhenDestroyed, - const bool noWrap_, - const int64 uncompressedStreamLength_) +GZIPDecompressorInputStream::GZIPDecompressorInputStream (InputStream* source, bool deleteSourceWhenDestroyed, + Format f, int64 uncompressedLength) : sourceStream (source, deleteSourceWhenDestroyed), - uncompressedStreamLength (uncompressedStreamLength_), - noWrap (noWrap_), + uncompressedStreamLength (uncompressedLength), + format (f), isEof (false), activeBufferSize (0), originalSourcePos (source->getPosition()), currentPos (0), buffer ((size_t) GZIPDecompressHelper::gzipDecompBufferSize), - helper (new GZIPDecompressHelper (noWrap_)) + helper (new GZIPDecompressHelper (f)) { } GZIPDecompressorInputStream::GZIPDecompressorInputStream (InputStream& source) : sourceStream (&source, false), uncompressedStreamLength (-1), - noWrap (false), + format (zlibFormat), isEof (false), activeBufferSize (0), originalSourcePos (source.getPosition()), currentPos (0), buffer ((size_t) GZIPDecompressHelper::gzipDecompBufferSize), - helper (new GZIPDecompressHelper (false)) + helper (new GZIPDecompressHelper (zlibFormat)) { } @@ -278,7 +289,7 @@ bool GZIPDecompressorInputStream::setPosition (int64 newPos) isEof = false; activeBufferSize = 0; currentPos = 0; - helper = new GZIPDecompressHelper (noWrap); + helper = new GZIPDecompressHelper (format); sourceStream->setPosition (originalSourcePos); } diff --git a/JuceLibraryCode/modules/juce_core/zip/juce_GZIPDecompressorInputStream.h b/JuceLibraryCode/modules/juce_core/zip/juce_GZIPDecompressorInputStream.h index 78a0b77..cdd9fd2 100644 --- a/JuceLibraryCode/modules/juce_core/zip/juce_GZIPDecompressorInputStream.h +++ b/JuceLibraryCode/modules/juce_core/zip/juce_GZIPDecompressorInputStream.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this @@ -43,21 +43,28 @@ class JUCE_API GZIPDecompressorInputStream : public InputStream { public: + enum Format + { + zlibFormat = 0, + deflateFormat, + gzipFormat + }; + //============================================================================== /** Creates a decompressor stream. @param sourceStream the stream to read from @param deleteSourceWhenDestroyed whether or not to delete the source stream when this object is destroyed - @param noWrap this is used internally by the ZipFile class - and should be ignored by user applications + @param sourceFormat can be used to select which of the supported + formats the data is expected to be in @param uncompressedStreamLength if the creator knows the length that the uncompressed stream will be, then it can supply this value, which will be returned by getTotalLength() */ GZIPDecompressorInputStream (InputStream* sourceStream, bool deleteSourceWhenDestroyed, - bool noWrap = false, + Format sourceFormat = zlibFormat, int64 uncompressedStreamLength = -1); /** Creates a decompressor stream. @@ -81,7 +88,7 @@ private: //============================================================================== OptionalScopedPointer sourceStream; const int64 uncompressedStreamLength; - const bool noWrap; + const Format format; bool isEof; int activeBufferSize; int64 originalSourcePos, currentPos; @@ -91,6 +98,11 @@ private: friend struct ContainerDeletePolicy; ScopedPointer helper; + #if JUCE_CATCH_DEPRECATED_CODE_MISUSE + // The arguments to this method have changed! Please pass a Format enum instead of the old dontWrap bool. + GZIPDecompressorInputStream (InputStream*, bool, bool, int64 x = -1); + #endif + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (GZIPDecompressorInputStream) }; diff --git a/JuceLibraryCode/modules/juce_core/zip/juce_ZipFile.cpp b/JuceLibraryCode/modules/juce_core/zip/juce_ZipFile.cpp index 629443b..c7ae45d 100644 --- a/JuceLibraryCode/modules/juce_core/zip/juce_ZipFile.cpp +++ b/JuceLibraryCode/modules/juce_core/zip/juce_ZipFile.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this @@ -135,7 +135,7 @@ public: char buffer [30]; if (inputStream != nullptr - && inputStream->setPosition (zei.streamOffset) + && inputStream->setPosition ((int64) zei.streamOffset) && inputStream->read (buffer, 30) == 30 && ByteOrder::littleEndianInt (buffer) == 0x04034b50) { @@ -154,7 +154,7 @@ public: int64 getTotalLength() { - return zipEntryHolder.compressedSize; + return (int64) zipEntryHolder.compressedSize; } int read (void* buffer, int howMany) @@ -162,7 +162,7 @@ public: if (headerSize <= 0) return 0; - howMany = (int) jmin ((int64) howMany, (int64) (zipEntryHolder.compressedSize - pos)); + howMany = (int) jmin ((int64) howMany, ((int64) zipEntryHolder.compressedSize) - pos); if (inputStream == nullptr) return 0; @@ -172,12 +172,12 @@ public: if (inputStream == file.inputStream) { const ScopedLock sl (file.lock); - inputStream->setPosition (pos + zipEntryHolder.streamOffset + headerSize); + inputStream->setPosition (pos + (int64) zipEntryHolder.streamOffset + headerSize); num = inputStream->read (buffer, howMany); } else { - inputStream->setPosition (pos + zipEntryHolder.streamOffset + headerSize); + inputStream->setPosition (pos + (int64) zipEntryHolder.streamOffset + headerSize); num = inputStream->read (buffer, howMany); } @@ -298,8 +298,9 @@ InputStream* ZipFile::createStreamForEntry (const int index) if (zei->compressed) { - stream = new GZIPDecompressorInputStream (stream, true, true, - zei->entry.uncompressedSize); + stream = new GZIPDecompressorInputStream (stream, true, + GZIPDecompressorInputStream::deflateFormat, + (int64) zei->entry.uncompressedSize); // (much faster to unzip in big blocks using a buffer..) stream = new BufferedInputStream (stream, 32768, true); @@ -327,7 +328,7 @@ void ZipFile::sortEntriesByFilename() //============================================================================== void ZipFile::init() { - ScopedPointer toDelete; + ScopedPointer toDelete; InputStream* in = inputStream; if (inputSource != nullptr) @@ -348,7 +349,7 @@ void ZipFile::init() in->setPosition (pos); MemoryBlock headerData; - if (in->readIntoMemoryBlock (headerData, size) == size) + if (in->readIntoMemoryBlock (headerData, size) == (size_t) size) { pos = 0; @@ -357,7 +358,7 @@ void ZipFile::init() if (pos + 46 > size) break; - const char* const buffer = static_cast (headerData.getData()) + pos; + const char* const buffer = static_cast (headerData.getData()) + pos; const int fileNameLen = ByteOrder::littleEndianShort (buffer + 28); diff --git a/JuceLibraryCode/modules/juce_core/zip/juce_ZipFile.h b/JuceLibraryCode/modules/juce_core/zip/juce_ZipFile.h index ccf9064..43f3c10 100644 --- a/JuceLibraryCode/modules/juce_core/zip/juce_ZipFile.h +++ b/JuceLibraryCode/modules/juce_core/zip/juce_ZipFile.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the juce_core module of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this @@ -40,7 +40,7 @@ class JUCE_API ZipFile { public: - /** Creates a ZipFile based for a file. */ + /** Creates a ZipFile to read a specific file. */ explicit ZipFile (const File& file); //============================================================================== @@ -91,15 +91,12 @@ public: int getNumEntries() const noexcept; /** Returns a structure that describes one of the entries in the zip file. - This may return zero if the index is out of range. - @see ZipFile::ZipEntry */ const ZipEntry* getEntry (int index) const noexcept; /** Returns the index of the first entry with a given filename. - This uses a case-sensitive comparison to look for a filename in the list of entries. It might return -1 if no match is found. @@ -116,8 +113,7 @@ public: */ const ZipEntry* getEntry (const String& fileName) const noexcept; - /** Sorts the list of entries, based on the filename. - */ + /** Sorts the list of entries, based on the filename. */ void sortEntriesByFilename(); //============================================================================== @@ -128,6 +124,11 @@ public: The stream must not be used after the ZipFile object that created has been deleted. + + Note that if the ZipFile was created with a user-supplied InputStream object, + then all the streams which are created by this method will by trying to share + the same source stream, so cannot be safely used on multiple threads! (But if + you create the ZipFile from a File or InputSource, then it is safe to do this). */ InputStream* createStreamForEntry (int index); @@ -138,6 +139,11 @@ public: The stream must not be used after the ZipFile object that created has been deleted. + + Note that if the ZipFile was created with a user-supplied InputStream object, + then all the streams which are created by this method will by trying to share + the same source stream, so cannot be safely used on multiple threads! (But if + you create the ZipFile from a File or InputSource, then it is safe to do this). */ InputStream* createStreamForEntry (const ZipEntry& entry); @@ -194,7 +200,7 @@ public: will be stored for this file. */ void addFile (const File& fileToAdd, int compressionLevel, - const String& storedPathName = String::empty); + const String& storedPathName = String()); /** Adds a file while should be added to the archive. @@ -233,11 +239,11 @@ private: friend class ZipInputStream; friend class ZipEntryHolder; - OwnedArray entries; + OwnedArray entries; CriticalSection lock; InputStream* inputStream; - ScopedPointer streamToDelete; - ScopedPointer inputSource; + ScopedPointer streamToDelete; + ScopedPointer inputSource; #if JUCE_DEBUG struct OpenStreamCounter diff --git a/JuceLibraryCode/modules/juce_core/zip/zlib/trees.c b/JuceLibraryCode/modules/juce_core/zip/zlib/trees.c index 36a124d..463bfc2 100644 --- a/JuceLibraryCode/modules/juce_core/zip/zlib/trees.c +++ b/JuceLibraryCode/modules/juce_core/zip/zlib/trees.c @@ -571,7 +571,7 @@ local void gen_codes (ct_data *tree, /* the tree to decorate */ ushf *bl_count) /* number of codes at each bit length */ { ush next_code[MAX_BITS+1]; /* next code value for each bit length */ - ush code = 0; /* running code value */ + ush code_ = 0; /* running code value */ int bits; /* bit index */ int n; /* code index */ @@ -579,12 +579,12 @@ local void gen_codes (ct_data *tree, /* the tree to decorate */ * without bit reversal. */ for (bits = 1; bits <= MAX_BITS; bits++) { - next_code[bits] = code = (code + bl_count[bits-1]) << 1; + next_code[bits] = code_ = (code_ + bl_count[bits-1]) << 1; } /* Check that the bit counts in bl_count are consistent. The last code * must be all ones. */ - Assert (code + bl_count[MAX_BITS]-1 == (1<last_lit != 0) do { @@ -1066,21 +1066,21 @@ local void compress_block (deflate_state *s, Tracecv(isgraph(lc), (stderr," '%c' ", lc)); } else { /* Here, lc is the match length - MIN_MATCH */ - code = _length_code[lc]; - send_code(s, code+LITERALS+1, ltree); /* send the length code */ - extra = extra_lbits[code]; + code_ = _length_code[lc]; + send_code(s, code_+LITERALS+1, ltree); /* send the length code */ + extra = extra_lbits[code_]; if (extra != 0) { - lc -= base_length[code]; + lc -= base_length[code_]; send_bits(s, lc, extra); /* send the extra length bits */ } dist--; /* dist is now the match distance - 1 */ - code = d_code(dist); - Assert (code < D_CODES, "bad d_code"); + code_ = d_code(dist); + Assert (code_ < D_CODES, "bad d_code"); - send_code(s, code, dtree); /* send the distance code */ - extra = extra_dbits[code]; + send_code(s, code_, dtree); /* send the distance code */ + extra = extra_dbits[code_]; if (extra != 0) { - dist -= base_dist[code]; + dist -= base_dist[code_]; send_bits(s, dist, extra); /* send the extra distance bits */ } } /* literal or match pair ? */ @@ -1120,12 +1120,12 @@ local void set_data_type (deflate_state *s) * method would use a table) * IN assertion: 1 <= len <= 15 */ -local unsigned bi_reverse (unsigned code, int len) +local unsigned bi_reverse (unsigned code_, int len) { register unsigned res = 0; do { - res |= code & 1; - code >>= 1, res <<= 1; + res |= code_ & 1; + code_ >>= 1, res <<= 1; } while (--len > 0); return res >> 1; } diff --git a/JuceLibraryCode/modules/juce_data_structures/app_properties/juce_ApplicationProperties.cpp b/JuceLibraryCode/modules/juce_data_structures/app_properties/juce_ApplicationProperties.cpp index 6db825e..53ff453 100644 --- a/JuceLibraryCode/modules/juce_data_structures/app_properties/juce_ApplicationProperties.cpp +++ b/JuceLibraryCode/modules/juce_data_structures/app_properties/juce_ApplicationProperties.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_data_structures/app_properties/juce_ApplicationProperties.h b/JuceLibraryCode/modules/juce_data_structures/app_properties/juce_ApplicationProperties.h index 21edbc2..a047de8 100644 --- a/JuceLibraryCode/modules/juce_data_structures/app_properties/juce_ApplicationProperties.h +++ b/JuceLibraryCode/modules/juce_data_structures/app_properties/juce_ApplicationProperties.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_data_structures/app_properties/juce_PropertiesFile.cpp b/JuceLibraryCode/modules/juce_data_structures/app_properties/juce_PropertiesFile.cpp index ece2121..bd14b66 100644 --- a/JuceLibraryCode/modules/juce_data_structures/app_properties/juce_PropertiesFile.cpp +++ b/JuceLibraryCode/modules/juce_data_structures/app_properties/juce_PropertiesFile.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_data_structures/app_properties/juce_PropertiesFile.h b/JuceLibraryCode/modules/juce_data_structures/app_properties/juce_PropertiesFile.h index f3d9551..c91d61c 100644 --- a/JuceLibraryCode/modules/juce_data_structures/app_properties/juce_PropertiesFile.h +++ b/JuceLibraryCode/modules/juce_data_structures/app_properties/juce_PropertiesFile.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -223,7 +223,7 @@ public: protected: /** @internal */ - virtual void propertyChanged(); + void propertyChanged() override; private: //============================================================================== diff --git a/JuceLibraryCode/modules/juce_data_structures/juce_data_structures.cpp b/JuceLibraryCode/modules/juce_data_structures/juce_data_structures.cpp index fd1d12a..0d2b875 100644 --- a/JuceLibraryCode/modules/juce_data_structures/juce_data_structures.cpp +++ b/JuceLibraryCode/modules/juce_data_structures/juce_data_structures.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -42,6 +42,7 @@ namespace juce #include "values/juce_Value.cpp" #include "values/juce_ValueTree.cpp" +#include "values/juce_ValueTreeSynchroniser.cpp" #include "undomanager/juce_UndoManager.cpp" #include "app_properties/juce_ApplicationProperties.cpp" #include "app_properties/juce_PropertiesFile.cpp" diff --git a/JuceLibraryCode/modules/juce_data_structures/juce_data_structures.h b/JuceLibraryCode/modules/juce_data_structures/juce_data_structures.h index 629b88d..c130d57 100644 --- a/JuceLibraryCode/modules/juce_data_structures/juce_data_structures.h +++ b/JuceLibraryCode/modules/juce_data_structures/juce_data_structures.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -35,6 +35,7 @@ namespace juce #include "undomanager/juce_UndoManager.h" #include "values/juce_Value.h" #include "values/juce_ValueTree.h" +#include "values/juce_ValueTreeSynchroniser.h" #include "app_properties/juce_PropertiesFile.h" #include "app_properties/juce_ApplicationProperties.h" diff --git a/JuceLibraryCode/modules/juce_data_structures/juce_data_structures.mm b/JuceLibraryCode/modules/juce_data_structures/juce_data_structures.mm index 2eb4fb4..003a585 100644 --- a/JuceLibraryCode/modules/juce_data_structures/juce_data_structures.mm +++ b/JuceLibraryCode/modules/juce_data_structures/juce_data_structures.mm @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_data_structures/juce_module_info b/JuceLibraryCode/modules/juce_data_structures/juce_module_info index 064f14c..b66b876 100644 --- a/JuceLibraryCode/modules/juce_data_structures/juce_module_info +++ b/JuceLibraryCode/modules/juce_data_structures/juce_module_info @@ -1,7 +1,7 @@ { "id": "juce_data_structures", "name": "JUCE data model helper classes", - "version": "3.0.6", + "version": "3.2.0", "description": "Classes for undo/redo management, and smart data structures.", "website": "http://www.juce.com/juce", "license": "GPL/Commercial", diff --git a/JuceLibraryCode/modules/juce_data_structures/undomanager/juce_UndoManager.cpp b/JuceLibraryCode/modules/juce_data_structures/undomanager/juce_UndoManager.cpp index 3557b90..4dc27b8 100644 --- a/JuceLibraryCode/modules/juce_data_structures/undomanager/juce_UndoManager.cpp +++ b/JuceLibraryCode/modules/juce_data_structures/undomanager/juce_UndoManager.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -29,10 +29,6 @@ struct UndoManager::ActionSet time (Time::getCurrentTime()) {} - OwnedArray actions; - String name; - Time time; - bool perform() const { for (int i = 0; i < actions.size(); ++i) @@ -60,6 +56,10 @@ struct UndoManager::ActionSet return total; } + + OwnedArray actions; + String name; + Time time; }; //============================================================================== @@ -101,6 +101,19 @@ void UndoManager::setMaxNumberOfStoredUnits (const int maxNumberOfUnitsToKeep, //============================================================================== bool UndoManager::perform (UndoableAction* const newAction, const String& actionName) +{ + if (perform (newAction)) + { + if (actionName.isNotEmpty()) + setCurrentTransactionName (actionName); + + return true; + } + + return false; +} + +bool UndoManager::perform (UndoableAction* const newAction) { if (newAction != nullptr) { @@ -113,9 +126,6 @@ bool UndoManager::perform (UndoableAction* const newAction, const String& action return false; } - if (actionName.isNotEmpty()) - currentTransactionName = actionName; - if (action->perform()) { ActionSet* actionSet = getCurrentSet(); @@ -134,7 +144,7 @@ bool UndoManager::perform (UndoableAction* const newAction, const String& action } else { - actionSet = new ActionSet (currentTransactionName); + actionSet = new ActionSet (newTransactionName); transactions.insert (nextIndex, actionSet); ++nextIndex; } @@ -174,23 +184,39 @@ void UndoManager::clearFutureTransactions() } } -void UndoManager::beginNewTransaction (const String& actionName) +void UndoManager::beginNewTransaction() noexcept { - newTransaction = true; - currentTransactionName = actionName; + beginNewTransaction (String()); } -void UndoManager::setCurrentTransactionName (const String& newName) +void UndoManager::beginNewTransaction (const String& actionName) noexcept { - currentTransactionName = newName; + newTransaction = true; + newTransactionName = actionName; +} + +void UndoManager::setCurrentTransactionName (const String& newName) noexcept +{ + if (newTransaction) + newTransactionName = newName; + else if (ActionSet* action = getCurrentSet()) + action->name = newName; +} + +String UndoManager::getCurrentTransactionName() const noexcept +{ + if (ActionSet* action = getCurrentSet()) + return action->name; + + return newTransactionName; } //============================================================================== UndoManager::ActionSet* UndoManager::getCurrentSet() const noexcept { return transactions [nextIndex - 1]; } UndoManager::ActionSet* UndoManager::getNextSet() const noexcept { return transactions [nextIndex]; } -bool UndoManager::canUndo() const { return getCurrentSet() != nullptr; } -bool UndoManager::canRedo() const { return getNextSet() != nullptr; } +bool UndoManager::canUndo() const noexcept { return getCurrentSet() != nullptr; } +bool UndoManager::canRedo() const noexcept { return getNextSet() != nullptr; } bool UndoManager::undo() { @@ -267,7 +293,7 @@ bool UndoManager::undoCurrentTransactionOnly() return newTransaction ? false : undo(); } -void UndoManager::getActionsInCurrentTransaction (Array & actionsFound) const +void UndoManager::getActionsInCurrentTransaction (Array& actionsFound) const { if (! newTransaction) if (const ActionSet* const s = getCurrentSet()) diff --git a/JuceLibraryCode/modules/juce_data_structures/undomanager/juce_UndoManager.h b/JuceLibraryCode/modules/juce_data_structures/undomanager/juce_UndoManager.h index eee9cbc..1e740ee 100644 --- a/JuceLibraryCode/modules/juce_data_structures/undomanager/juce_UndoManager.h +++ b/JuceLibraryCode/modules/juce_data_structures/undomanager/juce_UndoManager.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -98,16 +98,32 @@ public: //============================================================================== /** Performs an action and adds it to the undo history list. - @param action the action to perform - this will be deleted by the UndoManager - when no longer needed + @param action the action to perform - this object will be deleted by + the UndoManager when no longer needed + @returns true if the command succeeds - see UndoableAction::perform + @see beginNewTransaction + */ + bool perform (UndoableAction* action); + + /** Performs an action and also gives it a name. + + @param action the action to perform - this object will be deleted by + the UndoManager when no longer needed @param actionName if this string is non-empty, the current transaction will be given this name; if it's empty, the current transaction name will be left unchanged. See setCurrentTransactionName() @returns true if the command succeeds - see UndoableAction::perform @see beginNewTransaction */ - bool perform (UndoableAction* action, - const String& actionName = String()); + bool perform (UndoableAction* action, const String& actionName); + + /** Starts a new group of actions that together will be treated as a single transaction. + + All actions that are passed to the perform() method between calls to this + method are grouped together and undone/redone together by a single call to + undo() or redo(). + */ + void beginNewTransaction() noexcept; /** Starts a new group of actions that together will be treated as a single transaction. @@ -118,7 +134,7 @@ public: @param actionName a description of the transaction that is about to be performed */ - void beginNewTransaction (const String& actionName = String()); + void beginNewTransaction (const String& actionName) noexcept; /** Changes the name stored for the current transaction. @@ -126,19 +142,20 @@ public: called, but this can be used to change that name without starting a new transaction. */ - void setCurrentTransactionName (const String& newName); + void setCurrentTransactionName (const String& newName) noexcept; + + /** Returns the name of the current transaction. + @see setCurrentTransactionName + */ + String getCurrentTransactionName() const noexcept; //============================================================================== /** Returns true if there's at least one action in the list to undo. @see getUndoDescription, undo, canRedo */ - bool canUndo() const; - - /** Returns the description of the transaction that would be next to get undone. - - The description returned is the one that was passed into beginNewTransaction - before the set of actions was performed. + bool canUndo() const noexcept; + /** Returns the name of the transaction that will be rolled-back when undo() is called. @see undo */ String getUndoDescription() const; @@ -172,7 +189,7 @@ public: The first item in the list is the earliest action performed. */ - void getActionsInCurrentTransaction (Array & actionsFound) const; + void getActionsInCurrentTransaction (Array& actionsFound) const; /** Returns the number of UndoableAction objects that have been performed during the transaction that is currently open. @@ -194,12 +211,9 @@ public: /** Returns true if there's at least one action in the list to redo. @see getRedoDescription, redo, canUndo */ - bool canRedo() const; - - /** Returns the description of the transaction that would be next to get redone. - The description returned is the one that was passed into beginNewTransaction - before the set of actions was performed. + bool canRedo() const noexcept; + /** Returns the name of the transaction that will be redone when redo() is called. @see redo */ String getRedoDescription() const; @@ -216,7 +230,7 @@ private: struct ActionSet; friend struct ContainerDeletePolicy; OwnedArray transactions; - String currentTransactionName; + String newTransactionName; int totalUnitsStored, maxNumUnitsToKeep, minimumTransactionsToKeep, nextIndex; bool newTransaction, reentrancyCheck; ActionSet* getCurrentSet() const noexcept; diff --git a/JuceLibraryCode/modules/juce_data_structures/undomanager/juce_UndoableAction.h b/JuceLibraryCode/modules/juce_data_structures/undomanager/juce_UndoableAction.h index 866d488..ff22895 100644 --- a/JuceLibraryCode/modules/juce_data_structures/undomanager/juce_UndoableAction.h +++ b/JuceLibraryCode/modules/juce_data_structures/undomanager/juce_UndoableAction.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_data_structures/values/juce_Value.cpp b/JuceLibraryCode/modules/juce_data_structures/values/juce_Value.cpp index dee3a47..1034381 100644 --- a/JuceLibraryCode/modules/juce_data_structures/values/juce_Value.cpp +++ b/JuceLibraryCode/modules/juce_data_structures/values/juce_Value.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -72,12 +72,12 @@ public: { } - var getValue() const + var getValue() const override { return value; } - void setValue (const var& newValue) + void setValue (const var& newValue) override { if (! newValue.equalsWithSameType (value)) { @@ -94,41 +94,41 @@ private: //============================================================================== -Value::Value() - : value (new SimpleValueSource()) +Value::Value() : value (new SimpleValueSource()) { } -Value::Value (ValueSource* const v) - : value (v) +Value::Value (ValueSource* const v) : value (v) { jassert (v != nullptr); } -Value::Value (const var& initialValue) - : value (new SimpleValueSource (initialValue)) +Value::Value (const var& initialValue) : value (new SimpleValueSource (initialValue)) { } -Value::Value (const Value& other) - : value (other.value) +Value::Value (const Value& other) : value (other.value) { } -Value& Value::operator= (const Value& other) -{ - value = other.value; - return *this; -} - #if JUCE_COMPILER_SUPPORTS_MOVE_SEMANTICS Value::Value (Value&& other) noexcept - : value (static_cast&&> (other.value)) { + // moving a Value with listeners will lose those listeners, which + // probably isn't what you wanted to happen! + jassert (other.listeners.size() == 0); + + other.removeFromListenerList(); + value = static_cast&&> (other.value); } Value& Value::operator= (Value&& other) noexcept { + // moving a Value with listeners will lose those listeners, which + // probably isn't what you wanted to happen! + jassert (other.listeners.size() == 0); + + other.removeFromListenerList(); value = static_cast&&> (other.value); return *this; } @@ -136,7 +136,12 @@ Value& Value::operator= (Value&& other) noexcept Value::~Value() { - if (listeners.size() > 0) + removeFromListenerList(); +} + +void Value::removeFromListenerList() +{ + if (listeners.size() > 0 && value != nullptr) // may be nullptr after a move operation value->valuesWithListeners.removeValue (this); } diff --git a/JuceLibraryCode/modules/juce_data_structures/values/juce_Value.h b/JuceLibraryCode/modules/juce_data_structures/values/juce_Value.h index d67c173..632a383 100644 --- a/JuceLibraryCode/modules/juce_data_structures/values/juce_Value.h +++ b/JuceLibraryCode/modules/juce_data_structures/values/juce_Value.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -147,9 +147,9 @@ public: The listener is added to this specific Value object, and not to the shared object that it refers to. When this object is deleted, all the listeners will be lost, even if other references to the same Value still exist. So when you're - adding a listener, make sure that you add it to a ValueTree instance that will last + adding a listener, make sure that you add it to a Value instance that will last for as long as you need the listener. In general, you'd never want to add a listener - to a local stack-based ValueTree, but more likely to one that's a member variable. + to a local stack-based Value, but more likely to one that's a member variable. @see removeListener */ @@ -217,10 +217,15 @@ private: ListenerList listeners; void callListeners(); + void removeFromListenerList(); // This is disallowed to avoid confusion about whether it should // do a by-value or by-reference copy. - Value& operator= (const Value&); + Value& operator= (const Value&) JUCE_DELETED_FUNCTION; + + // This declaration prevents accidental construction from an integer of 0, + // which is possible in some compilers via an implicit cast to a pointer. + explicit Value (void*) JUCE_DELETED_FUNCTION; }; /** Writes a Value to an OutputStream as a UTF8 string. */ diff --git a/JuceLibraryCode/modules/juce_data_structures/values/juce_ValueTree.cpp b/JuceLibraryCode/modules/juce_data_structures/values/juce_ValueTree.cpp index f776224..1d63817 100644 --- a/JuceLibraryCode/modules/juce_data_structures/values/juce_ValueTree.cpp +++ b/JuceLibraryCode/modules/juce_data_structures/values/juce_ValueTree.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -27,7 +27,7 @@ class ValueTree::SharedObject : public ReferenceCountedObject public: typedef ReferenceCountedObjectPtr Ptr; - explicit SharedObject (Identifier t) noexcept + explicit SharedObject (const Identifier& t) noexcept : type (t), parent (nullptr) { } @@ -62,23 +62,20 @@ public: { const int numListeners = valueTreesWithListeners.size(); - if (numListeners > 0) + if (numListeners == 1) { - if (numListeners == 1) - { - valueTreesWithListeners.getUnchecked(0)->listeners.call (method, tree); - } - else - { - const SortedSet listenersCopy (valueTreesWithListeners); + valueTreesWithListeners.getUnchecked(0)->listeners.call (method, tree); + } + else if (numListeners > 0) + { + const SortedSet listenersCopy (valueTreesWithListeners); - for (int i = 0; i < numListeners; ++i) - { - ValueTree* const v = listenersCopy.getUnchecked(i); + for (int i = 0; i < numListeners; ++i) + { + ValueTree* const v = listenersCopy.getUnchecked(i); - if (i == 0 || valueTreesWithListeners.contains (v)) - v->listeners.call (method, tree); - } + if (i == 0 || valueTreesWithListeners.contains (v)) + v->listeners.call (method, tree); } } } @@ -88,28 +85,48 @@ public: { const int numListeners = valueTreesWithListeners.size(); - if (numListeners > 0) + if (numListeners == 1) { - if (numListeners == 1) - { - valueTreesWithListeners.getUnchecked(0)->listeners.call (method, tree, param2); - } - else - { - const SortedSet listenersCopy (valueTreesWithListeners); + valueTreesWithListeners.getUnchecked(0)->listeners.call (method, tree, param2); + } + else if (numListeners > 0) + { + const SortedSet listenersCopy (valueTreesWithListeners); - for (int i = 0; i < numListeners; ++i) - { - ValueTree* const v = listenersCopy.getUnchecked(i); + for (int i = 0; i < numListeners; ++i) + { + ValueTree* const v = listenersCopy.getUnchecked(i); - if (i == 0 || valueTreesWithListeners.contains (v)) - v->listeners.call (method, tree, param2); - } + if (i == 0 || valueTreesWithListeners.contains (v)) + v->listeners.call (method, tree, param2); } } } - void sendPropertyChangeMessage (const Identifier property) + template + void callListeners (Method method, ValueTree& tree, ParamType1& param2, ParamType2& param3) const + { + const int numListeners = valueTreesWithListeners.size(); + + if (numListeners == 1) + { + valueTreesWithListeners.getUnchecked(0)->listeners.call (method, tree, param2, param3); + } + else if (numListeners > 0) + { + const SortedSet listenersCopy (valueTreesWithListeners); + + for (int i = 0; i < numListeners; ++i) + { + ValueTree* const v = listenersCopy.getUnchecked(i); + + if (i == 0 || valueTreesWithListeners.contains (v)) + v->listeners.call (method, tree, param2, param3); + } + } + } + + void sendPropertyChangeMessage (const Identifier& property) { ValueTree tree (this); @@ -125,20 +142,20 @@ public: t->callListeners (&ValueTree::Listener::valueTreeChildAdded, tree, child); } - void sendChildRemovedMessage (ValueTree child) + void sendChildRemovedMessage (ValueTree child, int index) { ValueTree tree (this); for (ValueTree::SharedObject* t = this; t != nullptr; t = t->parent) - t->callListeners (&ValueTree::Listener::valueTreeChildRemoved, tree, child); + t->callListeners (&ValueTree::Listener::valueTreeChildRemoved, tree, child, index); } - void sendChildOrderChangedMessage() + void sendChildOrderChangedMessage (int oldIndex, int newIndex) { ValueTree tree (this); for (ValueTree::SharedObject* t = this; t != nullptr; t = t->parent) - t->callListeners (&ValueTree::Listener::valueTreeChildOrderChanged, tree); + t->callListeners (&ValueTree::Listener::valueTreeChildOrderChanged, tree, oldIndex, newIndex); } void sendParentChangeMessage() @@ -152,7 +169,7 @@ public: callListeners (&ValueTree::Listener::valueTreeParentChanged, tree); } - void setProperty (const Identifier name, const var& newValue, UndoManager* const undoManager) + void setProperty (const Identifier& name, const var& newValue, UndoManager* const undoManager) { if (undoManager == nullptr) { @@ -173,12 +190,12 @@ public: } } - bool hasProperty (const Identifier name) const noexcept + bool hasProperty (const Identifier& name) const noexcept { return properties.contains (name); } - void removeProperty (const Identifier name, UndoManager* const undoManager) + void removeProperty (const Identifier& name, UndoManager* const undoManager) { if (undoManager == nullptr) { @@ -221,7 +238,7 @@ public: setProperty (source.properties.getName(i), source.properties.getValueAt(i), undoManager); } - ValueTree getChildWithName (const Identifier typeToMatch) const + ValueTree getChildWithName (const Identifier& typeToMatch) const { for (int i = 0; i < children.size(); ++i) { @@ -233,7 +250,7 @@ public: return ValueTree(); } - ValueTree getOrCreateChildWithName (const Identifier typeToMatch, UndoManager* undoManager) + ValueTree getOrCreateChildWithName (const Identifier& typeToMatch, UndoManager* undoManager) { for (int i = 0; i < children.size(); ++i) { @@ -248,7 +265,7 @@ public: } - ValueTree getChildWithProperty (const Identifier propertyName, const var& propertyValue) const + ValueTree getChildWithProperty (const Identifier& propertyName, const var& propertyValue) const { for (int i = 0; i < children.size(); ++i) { @@ -323,7 +340,7 @@ public: { children.remove (childIndex); child->parent = nullptr; - sendChildRemovedMessage (ValueTree (child)); + sendChildRemovedMessage (ValueTree (child), childIndex); child->sendParentChangeMessage(); } else @@ -350,7 +367,7 @@ public: if (undoManager == nullptr) { children.move (currentIndex, newIndex); - sendChildOrderChangedMessage(); + sendChildOrderChangedMessage (currentIndex, newIndex); } else { @@ -366,28 +383,15 @@ public: { jassert (newOrder.size() == children.size()); - if (undoManager == nullptr) + for (int i = 0; i < children.size(); ++i) { - children.clear(); - children.ensureStorageAllocated (newOrder.size()); + SharedObject* const child = newOrder.getUnchecked(i)->object; - for (int i = 0; i < newOrder.size(); ++i) - children.add (newOrder.getUnchecked(i)->object); - - sendChildOrderChangedMessage(); - } - else - { - for (int i = 0; i < children.size(); ++i) + if (children.getObjectPointerUnchecked (i) != child) { - SharedObject* const child = newOrder.getUnchecked(i)->object; - - if (children.getObjectPointerUnchecked (i) != child) - { - const int oldIndex = children.indexOf (child); - jassert (oldIndex >= 0); - moveChild (oldIndex, i, undoManager); - } + const int oldIndex = children.indexOf (child); + jassert (oldIndex >= 0); + moveChild (oldIndex, i, undoManager); } } } @@ -454,7 +458,7 @@ public: class SetPropertyAction : public UndoableAction { public: - SetPropertyAction (SharedObject* const so, const Identifier propertyName, + SetPropertyAction (SharedObject* const so, const Identifier& propertyName, const var& newVal, const var& oldVal, bool isAdding, bool isDeleting) : target (so), name (propertyName), newValue (newVal), oldValue (oldVal), isAddingNewProperty (isAdding), isDeletingProperty (isDeleting) @@ -492,7 +496,7 @@ public: { if (! (isAddingNewProperty || isDeletingProperty)) { - if (SetPropertyAction* const next = dynamic_cast (nextAction)) + if (SetPropertyAction* const next = dynamic_cast (nextAction)) if (next->target == target && next->name == name && ! (next->isAddingNewProperty || next->isDeletingProperty)) return new SetPropertyAction (target, name, next->newValue, oldValue, false, false); @@ -592,7 +596,7 @@ public: UndoableAction* createCoalescedAction (UndoableAction* nextAction) { - if (MoveChildAction* next = dynamic_cast (nextAction)) + if (MoveChildAction* next = dynamic_cast (nextAction)) if (next->parent == parent && next->startIndex == endIndex) return new MoveChildAction (parent, startIndex, next->endIndex); @@ -625,7 +629,7 @@ ValueTree::ValueTree() noexcept const ValueTree ValueTree::invalid; -ValueTree::ValueTree (Identifier type) : object (new ValueTree::SharedObject (type)) +ValueTree::ValueTree (const Identifier& type) : object (new ValueTree::SharedObject (type)) { jassert (type.toString().isNotEmpty()); // All objects must be given a sensible type name! } @@ -698,7 +702,7 @@ ValueTree ValueTree::createCopy() const return ValueTree (createCopyIfNotNull (object.get())); } -bool ValueTree::hasType (const Identifier typeName) const +bool ValueTree::hasType (const Identifier& typeName) const { return object != nullptr && object->type == typeName; } @@ -711,7 +715,7 @@ Identifier ValueTree::getType() const ValueTree ValueTree::getParent() const { return ValueTree (object != nullptr ? object->parent - : static_cast (nullptr)); + : static_cast (nullptr)); } ValueTree ValueTree::getSibling (const int delta) const @@ -723,24 +727,23 @@ ValueTree ValueTree::getSibling (const int delta) const return ValueTree (object->parent->children.getObjectPointer (index)); } -const var& ValueTree::operator[] (const Identifier name) const +const var& ValueTree::operator[] (const Identifier& name) const { return object == nullptr ? var::null : object->properties[name]; } -const var& ValueTree::getProperty (const Identifier name) const +const var& ValueTree::getProperty (const Identifier& name) const { return object == nullptr ? var::null : object->properties[name]; } -var ValueTree::getProperty (const Identifier name, const var& defaultReturnValue) const +var ValueTree::getProperty (const Identifier& name, const var& defaultReturnValue) const { return object == nullptr ? defaultReturnValue : object->properties.getWithDefault (name, defaultReturnValue); } -ValueTree& ValueTree::setProperty (const Identifier name, const var& newValue, - UndoManager* const undoManager) +ValueTree& ValueTree::setProperty (const Identifier& name, const var& newValue, UndoManager* undoManager) { jassert (name.toString().isNotEmpty()); // Must have a valid property name! jassert (object != nullptr); // Trying to add a property to a null ValueTree will fail! @@ -751,12 +754,12 @@ ValueTree& ValueTree::setProperty (const Identifier name, const var& newValue, return *this; } -bool ValueTree::hasProperty (const Identifier name) const +bool ValueTree::hasProperty (const Identifier& name) const { return object != nullptr && object->hasProperty (name); } -void ValueTree::removeProperty (const Identifier name, UndoManager* const undoManager) +void ValueTree::removeProperty (const Identifier& name, UndoManager* const undoManager) { if (object != nullptr) object->removeProperty (name, undoManager); @@ -789,12 +792,17 @@ void ValueTree::copyPropertiesFrom (const ValueTree& source, UndoManager* const object->copyPropertiesFrom (*(source.object), undoManager); } +int ValueTree::getReferenceCount() const noexcept +{ + return object != nullptr ? object->getReferenceCount() : 0; +} + //============================================================================== class ValueTreePropertyValueSource : public Value::ValueSource, private ValueTree::Listener { public: - ValueTreePropertyValueSource (const ValueTree& vt, const Identifier prop, UndoManager* um) + ValueTreePropertyValueSource (const ValueTree& vt, const Identifier& prop, UndoManager* um) : tree (vt), property (prop), undoManager (um) { tree.addListener (this); @@ -805,8 +813,8 @@ public: tree.removeListener (this); } - var getValue() const { return tree [property]; } - void setValue (const var& newValue) { tree.setProperty (property, newValue, undoManager); } + var getValue() const override { return tree [property]; } + void setValue (const var& newValue) override { tree.setProperty (property, newValue, undoManager); } private: ValueTree tree; @@ -820,14 +828,14 @@ private: } void valueTreeChildAdded (ValueTree&, ValueTree&) override {} - void valueTreeChildRemoved (ValueTree&, ValueTree&) override {} - void valueTreeChildOrderChanged (ValueTree&) override {} + void valueTreeChildRemoved (ValueTree&, ValueTree&, int) override {} + void valueTreeChildOrderChanged (ValueTree&, int, int) override {} void valueTreeParentChanged (ValueTree&) override {} JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ValueTreePropertyValueSource) }; -Value ValueTree::getPropertyAsValue (const Identifier name, UndoManager* const undoManager) +Value ValueTree::getPropertyAsValue (const Identifier& name, UndoManager* const undoManager) { return Value (new ValueTreePropertyValueSource (*this, name, undoManager)); } @@ -841,20 +849,20 @@ int ValueTree::getNumChildren() const ValueTree ValueTree::getChild (int index) const { return ValueTree (object != nullptr ? object->children.getObjectPointer (index) - : static_cast (nullptr)); + : static_cast (nullptr)); } -ValueTree ValueTree::getChildWithName (const Identifier type) const +ValueTree ValueTree::getChildWithName (const Identifier& type) const { return object != nullptr ? object->getChildWithName (type) : ValueTree(); } -ValueTree ValueTree::getOrCreateChildWithName (const Identifier type, UndoManager* undoManager) +ValueTree ValueTree::getOrCreateChildWithName (const Identifier& type, UndoManager* undoManager) { return object != nullptr ? object->getOrCreateChildWithName (type, undoManager) : ValueTree(); } -ValueTree ValueTree::getChildWithProperty (const Identifier propertyName, const var& propertyValue) const +ValueTree ValueTree::getChildWithProperty (const Identifier& propertyName, const var& propertyValue) const { return object != nullptr ? object->getChildWithProperty (propertyName, propertyValue) : ValueTree(); } @@ -936,7 +944,7 @@ void ValueTree::removeListener (Listener* listener) object->valueTreesWithListeners.removeValue (this); } -void ValueTree::sendPropertyChangeMessage (const Identifier property) +void ValueTree::sendPropertyChangeMessage (const Identifier& property) { if (object != nullptr) object->sendPropertyChangeMessage (property); @@ -950,6 +958,9 @@ XmlElement* ValueTree::createXml() const ValueTree ValueTree::fromXml (const XmlElement& xml) { + // ValueTrees don't have any equivalent to XML text elements! + jassert (! xml.isTextElement()); + ValueTree v (xml.getTagName()); v.object->properties.setFromXmlAttributes (xml); @@ -991,9 +1002,16 @@ ValueTree ValueTree::readFromStream (InputStream& input) for (int i = 0; i < numProps; ++i) { const String name (input.readString()); - jassert (name.isNotEmpty()); - const var value (var::readFromStream (input)); - v.object->properties.set (name, value); + + if (name.isNotEmpty()) + { + const var value (var::readFromStream (input)); + v.object->properties.set (name, value); + } + else + { + jassertfalse; // trying to read corrupted data! + } } const int numChildren = input.readCompressedInt(); @@ -1003,6 +1021,9 @@ ValueTree ValueTree::readFromStream (InputStream& input) { ValueTree child (readFromStream (input)); + if (! child.isValid()) + return v; + v.object->children.add (child.object); child.object->parent = v.object; } @@ -1100,8 +1121,8 @@ public: ValueTree v2 = ValueTree::readFromStream (mi); expect (v1.isEquivalentTo (v2)); - ScopedPointer xml1 (v1.createXml()); - ScopedPointer xml2 (v2.createCopy().createXml()); + ScopedPointer xml1 (v1.createXml()); + ScopedPointer xml2 (v2.createCopy().createXml()); expect (xml1->isEquivalentTo (xml2, false)); ValueTree v4 = v2.createCopy(); diff --git a/JuceLibraryCode/modules/juce_data_structures/values/juce_ValueTree.h b/JuceLibraryCode/modules/juce_data_structures/values/juce_ValueTree.h index 311d722..892f302 100644 --- a/JuceLibraryCode/modules/juce_data_structures/values/juce_ValueTree.h +++ b/JuceLibraryCode/modules/juce_data_structures/values/juce_ValueTree.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -79,7 +79,7 @@ public: Like an XmlElement, each ValueTree node has a type, which you can access with getType() and hasType(). */ - explicit ValueTree (Identifier type); + explicit ValueTree (const Identifier& type); /** Creates a reference to another ValueTree. */ ValueTree (const ValueTree&); @@ -134,7 +134,7 @@ public: /** Returns true if the node has this type. The comparison is case-sensitive. */ - bool hasType (const Identifier typeName) const; + bool hasType (const Identifier& typeName) const; //============================================================================== /** Returns the value of a named property. @@ -142,21 +142,21 @@ public: You can also use operator[] to get a property. @see var, setProperty, hasProperty */ - const var& getProperty (const Identifier name) const; + const var& getProperty (const Identifier& name) const; /** Returns the value of a named property, or a user-specified default if the property doesn't exist. If no such property has been set, this will return the value of defaultReturnValue. You can also use operator[] and getProperty to get a property. @see var, getProperty, setProperty, hasProperty */ - var getProperty (const Identifier name, const var& defaultReturnValue) const; + var getProperty (const Identifier& name, const var& defaultReturnValue) const; /** Returns the value of a named property. If no such property has been set, this will return a void variant. This is the same as calling getProperty(). @see getProperty */ - const var& operator[] (const Identifier name) const; + const var& operator[] (const Identifier& name) const; /** Changes a named property of the node. The name identifier must not be an empty string. @@ -165,16 +165,16 @@ public: @see var, getProperty, removeProperty @returns a reference to the value tree, so that you can daisy-chain calls to this method. */ - ValueTree& setProperty (const Identifier name, const var& newValue, UndoManager* undoManager); + ValueTree& setProperty (const Identifier& name, const var& newValue, UndoManager* undoManager); /** Returns true if the node contains a named property. */ - bool hasProperty (const Identifier name) const; + bool hasProperty (const Identifier& name) const; /** Removes a property from the node. If the undoManager parameter is non-null, its UndoManager::perform() method will be used, so that this change can be undone. */ - void removeProperty (const Identifier name, UndoManager* undoManager); + void removeProperty (const Identifier& name, UndoManager* undoManager); /** Removes all properties from the node. If the undoManager parameter is non-null, its UndoManager::perform() method will be used, @@ -198,7 +198,7 @@ public: it needs to change the value. Attaching a Value::Listener to the value object will provide callbacks whenever the property changes. */ - Value getPropertyAsValue (const Identifier name, UndoManager* undoManager); + Value getPropertyAsValue (const Identifier& name, UndoManager* undoManager); /** Overwrites all the properties in this tree with the properties of the source tree. Any properties that already exist will be updated; and new ones will be added, and @@ -223,7 +223,7 @@ public: whether a node is valid). @see getOrCreateChildWithName */ - ValueTree getChildWithName (const Identifier type) const; + ValueTree getChildWithName (const Identifier& type) const; /** Returns the first child node with the speficied type name, creating and adding a child with this name if there wasn't already one there. @@ -232,7 +232,7 @@ public: the method on is itself invalid. @see getChildWithName */ - ValueTree getOrCreateChildWithName (const Identifier type, UndoManager* undoManager); + ValueTree getOrCreateChildWithName (const Identifier& type, UndoManager* undoManager); /** Looks for the first child node that has the speficied property value. @@ -242,7 +242,7 @@ public: If no such node is found, it'll return an invalid node. (See isValid() to find out whether a node is valid). */ - ValueTree getChildWithProperty (const Identifier propertyName, const var& propertyValue) const; + ValueTree getChildWithProperty (const Identifier& propertyName, const var& propertyValue) const; /** Adds a child to this node. @@ -318,7 +318,10 @@ public: /** Creates an XmlElement that holds a complete image of this node and all its children. If this node is invalid, this may return nullptr. Otherwise, the XML that is produced can - be used to recreate a similar node by calling fromXml() + be used to recreate a similar node by calling fromXml(). + + The caller must delete the object that is returned. + @see fromXml */ XmlElement* createXml() const; @@ -400,7 +403,8 @@ public: just check the parentTree parameter to make sure it's the one that you're interested in. */ virtual void valueTreeChildRemoved (ValueTree& parentTree, - ValueTree& childWhichHasBeenRemoved) = 0; + ValueTree& childWhichHasBeenRemoved, + int indexFromWhichChildWasRemoved) = 0; /** This method is called when a tree's children have been re-shuffled. @@ -409,7 +413,8 @@ public: If your tree has sub-trees but you only want to know about changes to the top level tree, just check the parameter to make sure it's the tree that you're interested in. */ - virtual void valueTreeChildOrderChanged (ValueTree& parentTreeWhoseChildrenHaveMoved) = 0; + virtual void valueTreeChildOrderChanged (ValueTree& parentTreeWhoseChildrenHaveMoved, + int oldIndex, int newIndex) = 0; /** This method is called when a tree has been added or removed from a parent node. @@ -448,7 +453,7 @@ public: /** Causes a property-change callback to be triggered for the specified property, calling any listeners that are registered. */ - void sendPropertyChangeMessage (const Identifier property); + void sendPropertyChangeMessage (const Identifier& property); //============================================================================== /** This method uses a comparator object to sort the tree's children into order. @@ -479,7 +484,7 @@ public: { OwnedArray sortedList; createListOfChildren (sortedList); - ComparatorAdapter adapter (comparator); + ComparatorAdapter adapter (comparator); sortedList.sort (adapter, retainOrderOfEquivalentItems); reorderChildren (sortedList, undoManager); } @@ -490,6 +495,11 @@ public: */ static const ValueTree invalid; + /** Returns the total number of references to the shared underlying data structure that this + ValueTree is using. + */ + int getReferenceCount() const noexcept; + private: //============================================================================== JUCE_PUBLIC_IN_DLL_BUILD (class SharedObject) diff --git a/JuceLibraryCode/modules/juce_events/broadcasters/juce_ActionBroadcaster.cpp b/JuceLibraryCode/modules/juce_events/broadcasters/juce_ActionBroadcaster.cpp index a7d56a6..a1ff975 100644 --- a/JuceLibraryCode/modules/juce_events/broadcasters/juce_ActionBroadcaster.cpp +++ b/JuceLibraryCode/modules/juce_events/broadcasters/juce_ActionBroadcaster.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -25,12 +25,11 @@ class ActionBroadcaster::ActionMessage : public MessageManager::MessageBase { public: - ActionMessage (const ActionBroadcaster* const broadcaster_, - const String& messageText, - ActionListener* const listener_) noexcept - : broadcaster (const_cast (broadcaster_)), + ActionMessage (const ActionBroadcaster* ab, + const String& messageText, ActionListener* l) noexcept + : broadcaster (const_cast (ab)), message (messageText), - listener (listener_) + listener (l) {} void messageCallback() override diff --git a/JuceLibraryCode/modules/juce_events/broadcasters/juce_ActionBroadcaster.h b/JuceLibraryCode/modules/juce_events/broadcasters/juce_ActionBroadcaster.h index 8052bed..5926eef 100644 --- a/JuceLibraryCode/modules/juce_events/broadcasters/juce_ActionBroadcaster.h +++ b/JuceLibraryCode/modules/juce_events/broadcasters/juce_ActionBroadcaster.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_events/broadcasters/juce_ActionListener.h b/JuceLibraryCode/modules/juce_events/broadcasters/juce_ActionListener.h index 12257f9..8f1d5cd 100644 --- a/JuceLibraryCode/modules/juce_events/broadcasters/juce_ActionListener.h +++ b/JuceLibraryCode/modules/juce_events/broadcasters/juce_ActionListener.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_events/broadcasters/juce_AsyncUpdater.cpp b/JuceLibraryCode/modules/juce_events/broadcasters/juce_AsyncUpdater.cpp index de12202..64acb79 100644 --- a/JuceLibraryCode/modules/juce_events/broadcasters/juce_AsyncUpdater.cpp +++ b/JuceLibraryCode/modules/juce_events/broadcasters/juce_AsyncUpdater.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -61,7 +61,9 @@ AsyncUpdater::~AsyncUpdater() void AsyncUpdater::triggerAsyncUpdate() { if (activeMessage->shouldDeliver.compareAndSetBool (1, 0)) - activeMessage->post(); + if (! activeMessage->post()) + cancelPendingUpdate(); // if the message queue fails, this avoids getting + // trapped waiting for the message to arrive } void AsyncUpdater::cancelPendingUpdate() noexcept diff --git a/JuceLibraryCode/modules/juce_events/broadcasters/juce_AsyncUpdater.h b/JuceLibraryCode/modules/juce_events/broadcasters/juce_AsyncUpdater.h index 79ab6e1..d0c343b 100644 --- a/JuceLibraryCode/modules/juce_events/broadcasters/juce_AsyncUpdater.h +++ b/JuceLibraryCode/modules/juce_events/broadcasters/juce_AsyncUpdater.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_events/broadcasters/juce_ChangeBroadcaster.cpp b/JuceLibraryCode/modules/juce_events/broadcasters/juce_ChangeBroadcaster.cpp index bff1f1a..8f71c3b 100644 --- a/JuceLibraryCode/modules/juce_events/broadcasters/juce_ChangeBroadcaster.cpp +++ b/JuceLibraryCode/modules/juce_events/broadcasters/juce_ChangeBroadcaster.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_events/broadcasters/juce_ChangeBroadcaster.h b/JuceLibraryCode/modules/juce_events/broadcasters/juce_ChangeBroadcaster.h index 8d9aca9..8eb4da3 100644 --- a/JuceLibraryCode/modules/juce_events/broadcasters/juce_ChangeBroadcaster.h +++ b/JuceLibraryCode/modules/juce_events/broadcasters/juce_ChangeBroadcaster.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_events/broadcasters/juce_ChangeListener.h b/JuceLibraryCode/modules/juce_events/broadcasters/juce_ChangeListener.h index 59e3025..3e61948 100644 --- a/JuceLibraryCode/modules/juce_events/broadcasters/juce_ChangeListener.h +++ b/JuceLibraryCode/modules/juce_events/broadcasters/juce_ChangeListener.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_events/broadcasters/juce_ListenerList.h b/JuceLibraryCode/modules/juce_events/broadcasters/juce_ListenerList.h index 853e252..c68858f 100644 --- a/JuceLibraryCode/modules/juce_events/broadcasters/juce_ListenerList.h +++ b/JuceLibraryCode/modules/juce_events/broadcasters/juce_ListenerList.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_events/interprocess/juce_ConnectedChildProcess.cpp b/JuceLibraryCode/modules/juce_events/interprocess/juce_ConnectedChildProcess.cpp index 926798c..74b6d88 100644 --- a/JuceLibraryCode/modules/juce_events/interprocess/juce_ConnectedChildProcess.cpp +++ b/JuceLibraryCode/modules/juce_events/interprocess/juce_ConnectedChildProcess.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -27,7 +27,7 @@ enum { magicMastSlaveConnectionHeader = 0x712baf04 }; static const char* startMessage = "__ipc_st"; static const char* killMessage = "__ipc_k_"; static const char* pingMessage = "__ipc_p_"; -enum { specialMessageSize = 8 }; +enum { specialMessageSize = 8, defaultTimeoutMs = 8000 }; static String getCommandLinePrefix (const String& commandLineUniqueID) { @@ -40,7 +40,7 @@ static String getCommandLinePrefix (const String& commandLineUniqueID) struct ChildProcessPingThread : public Thread, private AsyncUpdater { - ChildProcessPingThread() : Thread ("IPC ping"), timeoutMs (8000) + ChildProcessPingThread (int timeout) : Thread ("IPC ping"), timeoutMs (timeout) { pingReceived(); } @@ -84,8 +84,10 @@ private: struct ChildProcessMaster::Connection : public InterprocessConnection, private ChildProcessPingThread { - Connection (ChildProcessMaster& m, const String& pipeName) - : InterprocessConnection (false, magicMastSlaveConnectionHeader), owner (m) + Connection (ChildProcessMaster& m, const String& pipeName, int timeout) + : InterprocessConnection (false, magicMastSlaveConnectionHeader), + ChildProcessPingThread (timeout), + owner (m) { if (createPipe (pipeName, timeoutMs)) startThread (4); @@ -140,7 +142,7 @@ bool ChildProcessMaster::sendMessageToSlave (const MemoryBlock& mb) return false; } -bool ChildProcessMaster::launchSlaveProcess (const File& executable, const String& commandLineUniqueID) +bool ChildProcessMaster::launchSlaveProcess (const File& executable, const String& commandLineUniqueID, int timeoutMs) { connection = nullptr; jassert (childProcess.kill()); @@ -153,7 +155,7 @@ bool ChildProcessMaster::launchSlaveProcess (const File& executable, const Strin if (childProcess.start (args)) { - connection = new Connection (*this, pipeName); + connection = new Connection (*this, pipeName, timeoutMs <= 0 ? defaultTimeoutMs : timeoutMs); if (connection->isConnected()) { @@ -171,8 +173,10 @@ bool ChildProcessMaster::launchSlaveProcess (const File& executable, const Strin struct ChildProcessSlave::Connection : public InterprocessConnection, private ChildProcessPingThread { - Connection (ChildProcessSlave& p, const String& pipeName) - : InterprocessConnection (false, magicMastSlaveConnectionHeader), owner (p) + Connection (ChildProcessSlave& p, const String& pipeName, int timeout) + : InterprocessConnection (false, magicMastSlaveConnectionHeader), + ChildProcessPingThread (timeout), + owner (p) { connectToPipe (pipeName, timeoutMs); startThread (4); @@ -237,7 +241,8 @@ bool ChildProcessSlave::sendMessageToMaster (const MemoryBlock& mb) } bool ChildProcessSlave::initialiseFromCommandLine (const String& commandLine, - const String& commandLineUniqueID) + const String& commandLineUniqueID, + int timeoutMs) { String prefix (getCommandLinePrefix (commandLineUniqueID)); @@ -248,7 +253,7 @@ bool ChildProcessSlave::initialiseFromCommandLine (const String& commandLine, if (pipeName.isNotEmpty()) { - connection = new Connection (*this, pipeName); + connection = new Connection (*this, pipeName, timeoutMs <= 0 ? defaultTimeoutMs : timeoutMs); if (! connection->isConnected()) connection = nullptr; diff --git a/JuceLibraryCode/modules/juce_events/interprocess/juce_ConnectedChildProcess.h b/JuceLibraryCode/modules/juce_events/interprocess/juce_ConnectedChildProcess.h index 0b3ec6b..7c91ed5 100644 --- a/JuceLibraryCode/modules/juce_events/interprocess/juce_ConnectedChildProcess.h +++ b/JuceLibraryCode/modules/juce_events/interprocess/juce_ConnectedChildProcess.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -64,10 +64,16 @@ public: The commandLineUniqueID should be a short alphanumeric identifier (no spaces!) that matches the string passed to ChildProcessMaster::launchSlaveProcess(). + The timeoutMs parameter lets you specify how long the child process is allowed + to run without receiving a ping from the master before the master is considered to + have died, and handleConnectionLost() will be called. Passing <= 0 for this timeout + makes it use a default value. + Returns true if the command-line matches and the connection is made successfully. */ bool initialiseFromCommandLine (const String& commandLine, - const String& commandLineUniqueID); + const String& commandLineUniqueID, + int timeoutMs = 0); //============================================================================== /** This will be called to deliver messages from the master process. @@ -141,11 +147,17 @@ public: that gets launched must respond by calling ChildProcessSlave::initialiseFromCommandLine() in its startup code, and must use a matching ID to commandLineUniqueID. + The timeoutMs parameter lets you specify how long the child process is allowed + to go without sending a ping before it is considered to have died and + handleConnectionLost() will be called. Passing <= 0 for this timeout makes + it use a default value. + If this all works, the method returns true, and you can begin sending and receiving messages with the slave process. */ bool launchSlaveProcess (const File& executableToLaunch, - const String& commandLineUniqueID); + const String& commandLineUniqueID, + int timeoutMs = 0); /** This will be called to deliver a message from the slave process. The call will probably be made on a background thread, so be careful with your thread-safety! diff --git a/JuceLibraryCode/modules/juce_events/interprocess/juce_InterprocessConnection.cpp b/JuceLibraryCode/modules/juce_events/interprocess/juce_InterprocessConnection.cpp index b1b72f7..34f5c5d 100644 --- a/JuceLibraryCode/modules/juce_events/interprocess/juce_InterprocessConnection.cpp +++ b/JuceLibraryCode/modules/juce_events/interprocess/juce_InterprocessConnection.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -31,7 +31,7 @@ struct InterprocessConnection::ConnectionThread : public Thread private: InterprocessConnection& owner; - JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ConnectionThread); + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ConnectionThread) }; //============================================================================== @@ -69,11 +69,9 @@ bool InterprocessConnection::connectToSocket (const String& hostName, thread->startThread(); return true; } - else - { - socket = nullptr; - return false; - } + + socket = nullptr; + return false; } bool InterprocessConnection::connectToPipe (const String& pipeName, const int timeoutMs) @@ -143,41 +141,43 @@ bool InterprocessConnection::isConnected() const String InterprocessConnection::getConnectedHostName() const { - if (pipe != nullptr) - return "localhost"; - - if (socket != nullptr) { - if (! socket->isLocal()) - return socket->getHostName(); + const ScopedLock sl (pipeAndSocketLock); - return "localhost"; + if (pipe == nullptr && socket == nullptr) + return String(); + + if (socket != nullptr && ! socket->isLocal()) + return socket->getHostName(); } - return String(); + return IPAddress::local().toString(); } //============================================================================== bool InterprocessConnection::sendMessage (const MemoryBlock& message) { - uint32 messageHeader[2]; - messageHeader [0] = ByteOrder::swapIfBigEndian (magicMessageHeader); - messageHeader [1] = ByteOrder::swapIfBigEndian ((uint32) message.getSize()); + uint32 messageHeader[2] = { ByteOrder::swapIfBigEndian (magicMessageHeader), + ByteOrder::swapIfBigEndian ((uint32) message.getSize()) }; MemoryBlock messageData (sizeof (messageHeader) + message.getSize()); messageData.copyFrom (messageHeader, 0, sizeof (messageHeader)); messageData.copyFrom (message.getData(), sizeof (messageHeader), message.getSize()); - int bytesWritten = 0; + return writeData (messageData.getData(), (int) messageData.getSize()) == (int) messageData.getSize(); +} +int InterprocessConnection::writeData (void* data, int dataSize) +{ const ScopedLock sl (pipeAndSocketLock); if (socket != nullptr) - bytesWritten = socket->write (messageData.getData(), (int) messageData.getSize()); - else if (pipe != nullptr) - bytesWritten = pipe->write (messageData.getData(), (int) messageData.getSize(), pipeReceiveMessageTimeout); + return socket->write (data, dataSize); - return bytesWritten == (int) messageData.getSize(); + if (pipe != nullptr) + return pipe->write (data, dataSize, pipeReceiveMessageTimeout); + + return 0; } //============================================================================== diff --git a/JuceLibraryCode/modules/juce_events/interprocess/juce_InterprocessConnection.h b/JuceLibraryCode/modules/juce_events/interprocess/juce_InterprocessConnection.h index 8f21a29..d2fdcd6 100644 --- a/JuceLibraryCode/modules/juce_events/interprocess/juce_InterprocessConnection.h +++ b/JuceLibraryCode/modules/juce_events/interprocess/juce_InterprocessConnection.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -201,6 +201,7 @@ private: friend struct ContainerDeletePolicy; ScopedPointer thread; void runThread(); + int writeData (void*, int); JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (InterprocessConnection) }; diff --git a/JuceLibraryCode/modules/juce_events/interprocess/juce_InterprocessConnectionServer.cpp b/JuceLibraryCode/modules/juce_events/interprocess/juce_InterprocessConnectionServer.cpp index e9b5426..b422a1c 100644 --- a/JuceLibraryCode/modules/juce_events/interprocess/juce_InterprocessConnectionServer.cpp +++ b/JuceLibraryCode/modules/juce_events/interprocess/juce_InterprocessConnectionServer.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_events/interprocess/juce_InterprocessConnectionServer.h b/JuceLibraryCode/modules/juce_events/interprocess/juce_InterprocessConnectionServer.h index 8de7b8f..2bf0a22 100644 --- a/JuceLibraryCode/modules/juce_events/interprocess/juce_InterprocessConnectionServer.h +++ b/JuceLibraryCode/modules/juce_events/interprocess/juce_InterprocessConnectionServer.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_events/juce_events.cpp b/JuceLibraryCode/modules/juce_events/juce_events.cpp index 2110d0a..53069c4 100644 --- a/JuceLibraryCode/modules/juce_events/juce_events.cpp +++ b/JuceLibraryCode/modules/juce_events/juce_events.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_events/juce_events.h b/JuceLibraryCode/modules/juce_events/juce_events.h index 02f7c63..0ef1070 100644 --- a/JuceLibraryCode/modules/juce_events/juce_events.h +++ b/JuceLibraryCode/modules/juce_events/juce_events.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -39,6 +39,7 @@ namespace juce #include "messages/juce_NotificationType.h" #include "messages/juce_ApplicationBase.h" #include "messages/juce_Initialisation.h" +#include "messages/juce_MountedVolumeListChangeDetector.h" #include "broadcasters/juce_ListenerList.h" #include "broadcasters/juce_ActionBroadcaster.h" #include "broadcasters/juce_ActionListener.h" diff --git a/JuceLibraryCode/modules/juce_events/juce_events.mm b/JuceLibraryCode/modules/juce_events/juce_events.mm index 45263f1..a1db9d4 100644 --- a/JuceLibraryCode/modules/juce_events/juce_events.mm +++ b/JuceLibraryCode/modules/juce_events/juce_events.mm @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_events/juce_module_info b/JuceLibraryCode/modules/juce_events/juce_module_info index 534fe89..3db2401 100644 --- a/JuceLibraryCode/modules/juce_events/juce_module_info +++ b/JuceLibraryCode/modules/juce_events/juce_module_info @@ -1,7 +1,7 @@ { "id": "juce_events", "name": "JUCE message and event handling classes", - "version": "3.0.6", + "version": "3.2.0", "description": "Classes for running an application's main event loop and sending/receiving messages, timers, etc.", "website": "http://www.juce.com/juce", "license": "GPL/Commercial", diff --git a/JuceLibraryCode/modules/juce_events/messages/juce_ApplicationBase.cpp b/JuceLibraryCode/modules/juce_events/messages/juce_ApplicationBase.cpp index 507823d..66cd07f 100644 --- a/JuceLibraryCode/modules/juce_events/messages/juce_ApplicationBase.cpp +++ b/JuceLibraryCode/modules/juce_events/messages/juce_ApplicationBase.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -138,7 +138,7 @@ String JUCEApplicationBase::getCommandLineParameters() { return String( #else -#if JUCE_WINDOWS +#if JUCE_WINDOWS && ! defined (_CONSOLE) String JUCE_CALLTYPE JUCEApplicationBase::getCommandLineParameters() { @@ -171,8 +171,13 @@ StringArray JUCE_CALLTYPE JUCEApplicationBase::getCommandLineParameterArray() extern void initialiseNSApplication(); #endif -extern const char* const* juce_argv; // declared in juce_core -extern int juce_argc; +#if JUCE_WINDOWS + const char* const* juce_argv = nullptr; + int juce_argc = 0; +#else + extern const char* const* juce_argv; // declared in juce_core + extern int juce_argc; +#endif String JUCEApplicationBase::getCommandLineParameters() { @@ -227,7 +232,7 @@ int JUCEApplicationBase::main() jassert (app != nullptr); if (! app->initialiseApp()) - return 0; + return app->shutdownApp(); JUCE_TRY { diff --git a/JuceLibraryCode/modules/juce_events/messages/juce_ApplicationBase.h b/JuceLibraryCode/modules/juce_events/messages/juce_ApplicationBase.h index 51f098c..bde123b 100644 --- a/JuceLibraryCode/modules/juce_events/messages/juce_ApplicationBase.h +++ b/JuceLibraryCode/modules/juce_events/messages/juce_ApplicationBase.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -50,24 +50,24 @@ MyJUCEApp() {} ~MyJUCEApp() {} - void initialise (const String& commandLine) + void initialise (const String& commandLine) override { myMainWindow = new MyApplicationWindow(); myMainWindow->setBounds (100, 100, 400, 500); myMainWindow->setVisible (true); } - void shutdown() + void shutdown() override { myMainWindow = nullptr; } - const String getApplicationName() + const String getApplicationName() override { return "Super JUCE-o-matic"; } - const String getApplicationVersion() + const String getApplicationVersion() override { return "1.0"; } @@ -259,6 +259,7 @@ public: static CreateInstanceFunction createInstance; virtual bool initialiseApp(); + int shutdownApp(); static void JUCE_CALLTYPE sendUnhandledException (const std::exception*, const char* sourceFile, int lineNumber); bool sendCommandLineToPreexistingInstance(); #endif @@ -274,8 +275,6 @@ private: friend struct ContainerDeletePolicy; ScopedPointer multipleInstanceHandler; - int shutdownApp(); - JUCE_DECLARE_NON_COPYABLE (JUCEApplicationBase) }; diff --git a/JuceLibraryCode/modules/juce_events/messages/juce_CallbackMessage.h b/JuceLibraryCode/modules/juce_events/messages/juce_CallbackMessage.h index 799defd..17ddbea 100644 --- a/JuceLibraryCode/modules/juce_events/messages/juce_CallbackMessage.h +++ b/JuceLibraryCode/modules/juce_events/messages/juce_CallbackMessage.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_events/messages/juce_DeletedAtShutdown.cpp b/JuceLibraryCode/modules/juce_events/messages/juce_DeletedAtShutdown.cpp index d3c6e97..c3357af 100644 --- a/JuceLibraryCode/modules/juce_events/messages/juce_DeletedAtShutdown.cpp +++ b/JuceLibraryCode/modules/juce_events/messages/juce_DeletedAtShutdown.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_events/messages/juce_DeletedAtShutdown.h b/JuceLibraryCode/modules/juce_events/messages/juce_DeletedAtShutdown.h index ce1f10e..b3215eb 100644 --- a/JuceLibraryCode/modules/juce_events/messages/juce_DeletedAtShutdown.h +++ b/JuceLibraryCode/modules/juce_events/messages/juce_DeletedAtShutdown.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_events/messages/juce_Initialisation.h b/JuceLibraryCode/modules/juce_events/messages/juce_Initialisation.h index 84f5e82..d358d0d 100644 --- a/JuceLibraryCode/modules/juce_events/messages/juce_Initialisation.h +++ b/JuceLibraryCode/modules/juce_events/messages/juce_Initialisation.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -92,18 +92,12 @@ public: juce::JUCEApplicationBase* juce_CreateApplication() { return new AppClass(); } #else - #if JUCE_WINDOWS - #if defined (WINAPI) || defined (_WINDOWS_) - #define JUCE_MAIN_FUNCTION int __stdcall WinMain (HINSTANCE, HINSTANCE, const LPSTR, int) - #elif defined (_UNICODE) - #define JUCE_MAIN_FUNCTION int __stdcall WinMain (void*, void*, const wchar_t*, int) - #else - #define JUCE_MAIN_FUNCTION int __stdcall WinMain (void*, void*, const char*, int) - #endif - #define JUCE_MAIN_FUNCTION_ARGS + #if JUCE_WINDOWS && ! defined (_CONSOLE) + #define JUCE_MAIN_FUNCTION int __stdcall WinMain (struct HINSTANCE__*, struct HINSTANCE__*, char*, int) + #define JUCE_MAIN_FUNCTION_ARGS #else - #define JUCE_MAIN_FUNCTION int main (int argc, char* argv[]) - #define JUCE_MAIN_FUNCTION_ARGS argc, (const char**) argv + #define JUCE_MAIN_FUNCTION int main (int argc, char* argv[]) + #define JUCE_MAIN_FUNCTION_ARGS argc, (const char**) argv #endif #define START_JUCE_APPLICATION(AppClass) \ diff --git a/JuceLibraryCode/modules/juce_events/messages/juce_Message.h b/JuceLibraryCode/modules/juce_events/messages/juce_Message.h index 4ae55f6..dab10a4 100644 --- a/JuceLibraryCode/modules/juce_events/messages/juce_Message.h +++ b/JuceLibraryCode/modules/juce_events/messages/juce_Message.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_events/messages/juce_MessageListener.cpp b/JuceLibraryCode/modules/juce_events/messages/juce_MessageListener.cpp index b398ffa..6bcd25e 100644 --- a/JuceLibraryCode/modules/juce_events/messages/juce_MessageListener.cpp +++ b/JuceLibraryCode/modules/juce_events/messages/juce_MessageListener.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_events/messages/juce_MessageListener.h b/JuceLibraryCode/modules/juce_events/messages/juce_MessageListener.h index ddd51e2..96edc1b 100644 --- a/JuceLibraryCode/modules/juce_events/messages/juce_MessageListener.h +++ b/JuceLibraryCode/modules/juce_events/messages/juce_MessageListener.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_events/messages/juce_MessageManager.cpp b/JuceLibraryCode/modules/juce_events/messages/juce_MessageManager.cpp index 9383d50..b7a1d81 100644 --- a/JuceLibraryCode/modules/juce_events/messages/juce_MessageManager.cpp +++ b/JuceLibraryCode/modules/juce_events/messages/juce_MessageManager.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -66,21 +66,21 @@ void MessageManager::deleteInstance() } //============================================================================== -void MessageManager::MessageBase::post() +bool MessageManager::MessageBase::post() { MessageManager* const mm = MessageManager::instance; if (mm == nullptr || mm->quitMessagePosted || ! postMessageToSystemQueue (this)) + { Ptr deleter (this); // (this will delete messages that were just created with a 0 ref count) + return false; + } + + return true; } //============================================================================== #if JUCE_MODAL_LOOPS_PERMITTED && ! (JUCE_MAC || JUCE_IOS) -void MessageManager::runDispatchLoop() -{ - runDispatchLoopUntil (-1); -} - bool MessageManager::runDispatchLoopUntil (int millisecondsToRunFor) { jassert (isThisTheMessageThread()); // must only be called by the message thread @@ -102,7 +102,9 @@ bool MessageManager::runDispatchLoopUntil (int millisecondsToRunFor) return ! quitMessageReceived; } +#endif +#if ! (JUCE_MAC || JUCE_IOS || JUCE_ANDROID) class MessageManager::QuitMessage : public MessageManager::MessageBase { public: @@ -117,6 +119,21 @@ public: JUCE_DECLARE_NON_COPYABLE (QuitMessage) }; +void MessageManager::runDispatchLoop() +{ + jassert (isThisTheMessageThread()); // must only be called by the message thread + + while (! quitMessageReceived) + { + JUCE_TRY + { + if (! dispatchNextMessageOnSystemQueue (false)) + Thread::sleep (1); + } + JUCE_CATCH_EXCEPTION + } +} + void MessageManager::stopDispatchLoop() { (new QuitMessage())->post(); @@ -125,6 +142,25 @@ void MessageManager::stopDispatchLoop() #endif +//============================================================================== +#if JUCE_COMPILER_SUPPORTS_LAMBDAS +struct AsyncFunction : private MessageManager::MessageBase +{ + AsyncFunction (std::function f) : fn (f) { post(); } + +private: + std::function fn; + void messageCallback() override { fn(); } + + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AsyncFunction) +}; + +void MessageManager::callAsync (std::function f) +{ + new AsyncFunction (f); +} +#endif + //============================================================================== class AsyncFunctionCallback : public MessageManager::MessageBase { @@ -158,9 +194,15 @@ void* MessageManager::callFunctionOnMessageThread (MessageCallbackFunction* cons jassert (! currentThreadHasLockedMessageManager()); const ReferenceCountedObjectPtr message (new AsyncFunctionCallback (func, parameter)); - message->post(); - message->finished.wait(); - return message->result; + + if (message->post()) + { + message->finished.wait(); + return message->result; + } + + jassertfalse; // the OS message queue failed to send the message! + return nullptr; } //============================================================================== @@ -275,7 +317,12 @@ bool MessageManagerLock::attemptLock (Thread* const threadToCheck, ThreadPoolJob } blockingMessage = new BlockingMessage(); - blockingMessage->post(); + + if (! blockingMessage->post()) + { + blockingMessage = nullptr; + return false; + } while (! blockingMessage->lockedEvent.wait (20)) { diff --git a/JuceLibraryCode/modules/juce_events/messages/juce_MessageManager.h b/JuceLibraryCode/modules/juce_events/messages/juce_MessageManager.h index d50c35c..23b8a62 100644 --- a/JuceLibraryCode/modules/juce_events/messages/juce_MessageManager.h +++ b/JuceLibraryCode/modules/juce_events/messages/juce_MessageManager.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -91,6 +91,13 @@ public: #endif //============================================================================== + #if JUCE_COMPILER_SUPPORTS_LAMBDAS + /** Asynchronously invokes a function or C++11 lambda on the message thread. + Internally this uses the CallbackMessage class to invoke the callback. + */ + static void callAsync (std::function); + #endif + /** Calls a function using the message-thread. This can be used by any thread to cause this function to be called-back @@ -170,7 +177,7 @@ public: virtual ~MessageBase() {} virtual void messageCallback() = 0; - void post(); + bool post(); typedef ReferenceCountedObjectPtr Ptr; diff --git a/JuceLibraryCode/modules/juce_events/messages/juce_NotificationType.h b/JuceLibraryCode/modules/juce_events/messages/juce_NotificationType.h index c3ecccc..9fb0c3a 100644 --- a/JuceLibraryCode/modules/juce_events/messages/juce_NotificationType.h +++ b/JuceLibraryCode/modules/juce_events/messages/juce_NotificationType.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_events/native/juce_ScopedXLock.h b/JuceLibraryCode/modules/juce_events/native/juce_ScopedXLock.h index d2136c7..1234207 100644 --- a/JuceLibraryCode/modules/juce_events/native/juce_ScopedXLock.h +++ b/JuceLibraryCode/modules/juce_events/native/juce_ScopedXLock.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_events/native/juce_android_Messaging.cpp b/JuceLibraryCode/modules/juce_events/native/juce_android_Messaging.cpp index 733994a..73cc3a4 100644 --- a/JuceLibraryCode/modules/juce_events/native/juce_android_Messaging.cpp +++ b/JuceLibraryCode/modules/juce_events/native/juce_android_Messaging.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -42,7 +42,7 @@ bool MessageManager::postMessageToSystemQueue (MessageManager::MessageBase* cons return true; } -JUCE_JNI_CALLBACK (JUCE_ANDROID_ACTIVITY_CLASSNAME, deliverMessage, void, (jobject activity, jlong value)) +JUCE_JNI_CALLBACK (JUCE_ANDROID_ACTIVITY_CLASSNAME, deliverMessage, void, (JNIEnv* env, jobject activity, jlong value)) { JUCE_TRY { diff --git a/JuceLibraryCode/modules/juce_events/native/juce_ios_MessageManager.mm b/JuceLibraryCode/modules/juce_events/native/juce_ios_MessageManager.mm index bdfed65..998cace 100644 --- a/JuceLibraryCode/modules/juce_events/native/juce_ios_MessageManager.mm +++ b/JuceLibraryCode/modules/juce_events/native/juce_ios_MessageManager.mm @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -25,7 +25,15 @@ void MessageManager::runDispatchLoop() { jassert (isThisTheMessageThread()); // must only be called by the message thread - runDispatchLoopUntil (-1); + + while (! quitMessagePosted) + { + JUCE_AUTORELEASEPOOL + { + [[NSRunLoop currentRunLoop] runMode: NSDefaultRunLoopMode + beforeDate: [NSDate dateWithTimeIntervalSinceNow: 0.001]]; + } + } } void MessageManager::stopDispatchLoop() @@ -34,6 +42,7 @@ void MessageManager::stopDispatchLoop() exit (0); // iOS apps get no mercy.. } +#if JUCE_MODAL_LOOPS_PERMITTED bool MessageManager::runDispatchLoopUntil (int millisecondsToRunFor) { JUCE_AUTORELEASEPOOL @@ -59,6 +68,7 @@ bool MessageManager::runDispatchLoopUntil (int millisecondsToRunFor) return ! quitMessagePosted; } } +#endif //============================================================================== static ScopedPointer messageQueue; diff --git a/JuceLibraryCode/modules/juce_events/native/juce_linux_Messaging.cpp b/JuceLibraryCode/modules/juce_events/native/juce_linux_Messaging.cpp index 48e28a7..62f8e4a 100644 --- a/JuceLibraryCode/modules/juce_events/native/juce_linux_Messaging.cpp +++ b/JuceLibraryCode/modules/juce_events/native/juce_linux_Messaging.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -37,8 +37,8 @@ typedef void (*SelectionRequestCallback) (XSelectionRequestEvent&); SelectionRequestCallback handleSelectionRequest = nullptr; //============================================================================== -ScopedXLock::ScopedXLock() { XLockDisplay (display); } -ScopedXLock::~ScopedXLock() { XUnlockDisplay (display); } +ScopedXLock::ScopedXLock() { if (display != nullptr) XLockDisplay (display); } +ScopedXLock::~ScopedXLock() { if (display != nullptr) XUnlockDisplay (display); } //============================================================================== class InternalMessageQueue @@ -74,7 +74,7 @@ public: ScopedUnlock ul (lock); const unsigned char x = 0xff; - size_t bytesWritten = write (fd[0], &x, 1); + ssize_t bytesWritten = write (fd[0], &x, 1); (void) bytesWritten; } } @@ -101,7 +101,7 @@ public: if (! isEmpty()) return true; - if (display != 0) + if (display != nullptr) { ScopedXLock xlock; if (XPending (display)) @@ -118,7 +118,7 @@ public: FD_ZERO (&readset); FD_SET (fd0, &readset); - if (display != 0) + if (display != nullptr) { ScopedXLock xlock; int fd1 = XConnectionNumber (display); @@ -131,7 +131,7 @@ public: } //============================================================================== - juce_DeclareSingleton_SingleThreaded_Minimal (InternalMessageQueue); + juce_DeclareSingleton_SingleThreaded_Minimal (InternalMessageQueue) private: CriticalSection lock; @@ -154,7 +154,7 @@ private: static bool dispatchNextXEvent() { - if (display == 0) + if (display == nullptr) return false; XEvent evt; @@ -186,7 +186,7 @@ private: const ScopedUnlock ul (lock); unsigned char x; - size_t numBytes = read (fd[1], &x, 1); + ssize_t numBytes = read (fd[1], &x, 1); (void) numBytes; } @@ -209,7 +209,7 @@ private: } }; -juce_ImplementSingleton_SingleThreaded (InternalMessageQueue); +juce_ImplementSingleton_SingleThreaded (InternalMessageQueue) //============================================================================== @@ -235,6 +235,8 @@ namespace LinuxErrorHandling int errorHandler (Display* display, XErrorEvent* event) { + (void) display; (void) event; + #if JUCE_DEBUG_XERRORS char errorStr[64] = { 0 }; char requestStr[64] = { 0 }; @@ -319,7 +321,7 @@ void MessageManager::doPlatformSpecificInitialisation() display = XOpenDisplay (displayName.toUTF8()); - if (display != 0) // This is not fatal! we can run headless. + if (display != nullptr) // This is not fatal! we can run headless. { // Create a context to store user data associated with Windows we create windowHandleXContext = XUniqueContext(); @@ -341,7 +343,7 @@ void MessageManager::doPlatformSpecificShutdown() { InternalMessageQueue::deleteInstance(); - if (display != 0 && ! LinuxErrorHandling::errorOccurred) + if (display != nullptr && ! LinuxErrorHandling::errorOccurred) { XDestroyWindow (display, juce_messageWindowHandle); XCloseDisplay (display); diff --git a/JuceLibraryCode/modules/juce_events/native/juce_mac_MessageManager.mm b/JuceLibraryCode/modules/juce_events/native/juce_mac_MessageManager.mm index 3aed8a2..e1f6d87 100644 --- a/JuceLibraryCode/modules/juce_events/native/juce_mac_MessageManager.mm +++ b/JuceLibraryCode/modules/juce_events/native/juce_mac_MessageManager.mm @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -53,7 +53,7 @@ public: [[NSDistributedNotificationCenter defaultCenter] addObserver: delegate selector: @selector (broadcastMessageCallback:) - name: getBroacastEventName() + name: getBroadcastEventName() object: nil]; } else @@ -79,14 +79,14 @@ public: [NSApp setDelegate: nil]; [[NSDistributedNotificationCenter defaultCenter] removeObserver: delegate - name: getBroacastEventName() + name: getBroadcastEventName() object: nil]; } [delegate release]; } - static NSString* getBroacastEventName() + static NSString* getBroadcastEventName() { return juceStringToNS ("juce_" + String::toHexString (File::getSpecialLocation (File::currentExecutableFile).hashCode64())); } @@ -96,26 +96,36 @@ public: private: //============================================================================== - struct AppDelegateClass : public ObjCClass + struct AppDelegateClass : public ObjCClass { - AppDelegateClass() : ObjCClass ("JUCEAppDelegate_") + AppDelegateClass() : ObjCClass ("JUCEAppDelegate_") { - addMethod (@selector (applicationShouldTerminate:), applicationShouldTerminate, "I@:@"); - addMethod (@selector (applicationWillTerminate:), applicationWillTerminate, "v@:@"); - addMethod (@selector (application:openFile:), application_openFile, "c@:@@"); - addMethod (@selector (application:openFiles:), application_openFiles, "v@:@@"); - addMethod (@selector (applicationDidBecomeActive:), applicationDidBecomeActive, "v@:@"); - addMethod (@selector (applicationDidResignActive:), applicationDidResignActive, "v@:@"); - addMethod (@selector (applicationWillUnhide:), applicationWillUnhide, "v@:@"); - addMethod (@selector (broadcastMessageCallback:), broadcastMessageCallback, "v@:@"); - addMethod (@selector (mainMenuTrackingBegan:), mainMenuTrackingBegan, "v@:@"); - addMethod (@selector (mainMenuTrackingEnded:), mainMenuTrackingEnded, "v@:@"); - addMethod (@selector (dummyMethod), dummyMethod, "v@:"); + addMethod (@selector (applicationWillFinishLaunching:), applicationWillFinishLaunching, "v@:@@"); + addMethod (@selector (getUrl:withReplyEvent:), getUrl_withReplyEvent, "v@:@@"); + addMethod (@selector (applicationShouldTerminate:), applicationShouldTerminate, "I@:@"); + addMethod (@selector (applicationWillTerminate:), applicationWillTerminate, "v@:@"); + addMethod (@selector (application:openFile:), application_openFile, "c@:@@"); + addMethod (@selector (application:openFiles:), application_openFiles, "v@:@@"); + addMethod (@selector (applicationDidBecomeActive:), applicationDidBecomeActive, "v@:@"); + addMethod (@selector (applicationDidResignActive:), applicationDidResignActive, "v@:@"); + addMethod (@selector (applicationWillUnhide:), applicationWillUnhide, "v@:@"); + addMethod (@selector (broadcastMessageCallback:), broadcastMessageCallback, "v@:@"); + addMethod (@selector (mainMenuTrackingBegan:), mainMenuTrackingBegan, "v@:@"); + addMethod (@selector (mainMenuTrackingEnded:), mainMenuTrackingEnded, "v@:@"); + addMethod (@selector (dummyMethod), dummyMethod, "v@:"); registerClass(); } private: + static void applicationWillFinishLaunching (id self, SEL, NSApplication*, NSNotification*) + { + [[NSAppleEventManager sharedAppleEventManager] setEventHandler: self + andSelector: @selector (getUrl:withReplyEvent:) + forEventClass: kInternetEventClass + andEventID: kAEGetURL]; + } + static NSApplicationTerminateReply applicationShouldTerminate (id /*self*/, SEL, NSApplication*) { if (JUCEApplicationBase* const app = JUCEApplicationBase::getInstance()) @@ -184,13 +194,18 @@ private: static void dummyMethod (id /*self*/, SEL) {} // (used as a way of running a dummy thread) - private: static void focusChanged() { if (appFocusChangeCallback != nullptr) (*appFocusChangeCallback)(); } + static void getUrl_withReplyEvent (id /*self*/, SEL, NSAppleEventDescriptor* event, NSAppleEventDescriptor*) + { + if (JUCEApplicationBase* const app = JUCEApplicationBase::getInstance()) + app->anotherInstanceStarted (quotedIfContainsSpaces ([[event paramDescriptorForKeyword: keyDirectObject] stringValue])); + } + static String quotedIfContainsSpaces (NSString* file) { String s (nsStringToJuce (file)); @@ -246,11 +261,13 @@ static void shutdownNSApp() void MessageManager::stopDispatchLoop() { + #if JUCE_PROJUCER_LIVE_BUILD quitMessagePosted = true; + #else - #if ! JUCE_PROJUCER_LIVE_BUILD if (isThisTheMessageThread()) { + quitMessagePosted = true; shutdownNSApp(); } else @@ -258,7 +275,7 @@ void MessageManager::stopDispatchLoop() struct QuitCallback : public CallbackMessage { QuitCallback() {} - void messageCallback() override { shutdownNSApp(); } + void messageCallback() override { MessageManager::getInstance()->stopDispatchLoop(); } }; (new QuitCallback())->post(); @@ -341,7 +358,7 @@ void MessageManager::broadcastMessage (const String& message) NSDictionary* info = [NSDictionary dictionaryWithObject: juceStringToNS (message) forKey: nsStringLiteral ("message")]; - [[NSDistributedNotificationCenter defaultCenter] postNotificationName: AppDelegate::getBroacastEventName() + [[NSDistributedNotificationCenter defaultCenter] postNotificationName: AppDelegate::getBroadcastEventName() object: nil userInfo: info]; } @@ -365,3 +382,54 @@ void repostCurrentNSEvent() (new EventReposter())->post(); } + + +//============================================================================== +#if JUCE_MAC +struct MountedVolumeListChangeDetector::Pimpl +{ + Pimpl (MountedVolumeListChangeDetector& d) : owner (d) + { + static ObserverClass cls; + delegate = [cls.createInstance() init]; + ObserverClass::setOwner (delegate, this); + + NSNotificationCenter* nc = [[NSWorkspace sharedWorkspace] notificationCenter]; + + [nc addObserver: delegate selector: @selector (changed:) name: NSWorkspaceDidMountNotification object: nil]; + [nc addObserver: delegate selector: @selector (changed:) name: NSWorkspaceDidUnmountNotification object: nil]; + } + + ~Pimpl() + { + [[[NSWorkspace sharedWorkspace] notificationCenter] removeObserver: delegate]; + [delegate release]; + } + +private: + MountedVolumeListChangeDetector& owner; + id delegate; + + struct ObserverClass : public ObjCClass + { + ObserverClass() : ObjCClass ("JUCEDriveObserver_") + { + addIvar ("owner"); + addMethod (@selector (changed:), changed, "v@:@"); + addProtocol (@protocol (NSTextInput)); + registerClass(); + } + + static Pimpl* getOwner (id self) { return getIvar (self, "owner"); } + static void setOwner (id self, Pimpl* owner) { object_setInstanceVariable (self, "owner", owner); } + + static void changed (id self, SEL, NSNotification*) + { + getOwner (self)->owner.mountedVolumeListChanged(); + } + }; +}; + +MountedVolumeListChangeDetector::MountedVolumeListChangeDetector() { pimpl = new Pimpl (*this); } +MountedVolumeListChangeDetector::~MountedVolumeListChangeDetector() {} +#endif diff --git a/JuceLibraryCode/modules/juce_events/native/juce_osx_MessageQueue.h b/JuceLibraryCode/modules/juce_events/native/juce_osx_MessageQueue.h index 6ffbefe..4b36564 100644 --- a/JuceLibraryCode/modules/juce_events/native/juce_osx_MessageQueue.h +++ b/JuceLibraryCode/modules/juce_events/native/juce_osx_MessageQueue.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_events/native/juce_win32_HiddenMessageWindow.h b/JuceLibraryCode/modules/juce_events/native/juce_win32_HiddenMessageWindow.h index c4747ec..1a859c0 100644 --- a/JuceLibraryCode/modules/juce_events/native/juce_win32_HiddenMessageWindow.h +++ b/JuceLibraryCode/modules/juce_events/native/juce_win32_HiddenMessageWindow.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -100,7 +100,6 @@ public: virtual ~DeviceChangeDetector() {} -protected: virtual void systemDeviceChanged() = 0; void triggerAsyncDeviceChangeCallback() diff --git a/JuceLibraryCode/modules/juce_events/native/juce_win32_Messaging.cpp b/JuceLibraryCode/modules/juce_events/native/juce_win32_Messaging.cpp index 0bc0f78..7c02752 100644 --- a/JuceLibraryCode/modules/juce_events/native/juce_win32_Messaging.cpp +++ b/JuceLibraryCode/modules/juce_events/native/juce_win32_Messaging.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -38,7 +38,7 @@ namespace WindowsMessageHelpers void dispatchMessageFromLParam (LPARAM lParam) { - MessageManager::MessageBase* const message = reinterpret_cast (lParam); + MessageManager::MessageBase* const message = reinterpret_cast (lParam); JUCE_TRY { @@ -61,15 +61,17 @@ namespace WindowsMessageHelpers dispatchMessageFromLParam (lParam); return 0; } - else if (message == broadcastId) + + if (message == broadcastId) { const ScopedPointer messageString ((String*) lParam); MessageManager::getInstance()->deliverBroadcastMessage (*messageString); return 0; } - else if (message == WM_COPYDATA) + + if (message == WM_COPYDATA) { - const COPYDATASTRUCT* const data = reinterpret_cast (lParam); + const COPYDATASTRUCT* const data = reinterpret_cast (lParam); if (data->dwData == broadcastId) { @@ -88,7 +90,7 @@ namespace WindowsMessageHelpers BOOL CALLBACK broadcastEnumWindowProc (HWND hwnd, LPARAM lParam) { if (hwnd != juce_messageWindowHandle) - reinterpret_cast *> (lParam)->add (hwnd); + reinterpret_cast*> (lParam)->add (hwnd); return TRUE; } @@ -157,9 +159,8 @@ void MessageManager::broadcastMessage (const String& value) { HWND hwnd = windows.getUnchecked(i); - TCHAR windowName [64]; // no need to read longer strings than this - GetWindowText (hwnd, windowName, 64); - windowName [63] = 0; + TCHAR windowName[64] = { 0 }; // no need to read longer strings than this + GetWindowText (hwnd, windowName, 63); if (String (windowName) == WindowsMessageHelpers::messageWindowName) { @@ -188,3 +189,30 @@ void MessageManager::doPlatformSpecificShutdown() OleUninitialize(); } + +//============================================================================== +struct MountedVolumeListChangeDetector::Pimpl : private DeviceChangeDetector +{ + Pimpl (MountedVolumeListChangeDetector& d) : DeviceChangeDetector (L"MountedVolumeList"), owner (d) + { + File::findFileSystemRoots (lastVolumeList); + } + + void systemDeviceChanged() override + { + Array newList; + File::findFileSystemRoots (newList); + + if (lastVolumeList != newList) + { + lastVolumeList = newList; + owner.mountedVolumeListChanged(); + } + } + + MountedVolumeListChangeDetector& owner; + Array lastVolumeList; +}; + +MountedVolumeListChangeDetector::MountedVolumeListChangeDetector() { pimpl = new Pimpl (*this); } +MountedVolumeListChangeDetector::~MountedVolumeListChangeDetector() {} diff --git a/JuceLibraryCode/modules/juce_events/timers/juce_MultiTimer.cpp b/JuceLibraryCode/modules/juce_events/timers/juce_MultiTimer.cpp index 4885e7b..7941cf3 100644 --- a/JuceLibraryCode/modules/juce_events/timers/juce_MultiTimer.cpp +++ b/JuceLibraryCode/modules/juce_events/timers/juce_MultiTimer.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_events/timers/juce_MultiTimer.h b/JuceLibraryCode/modules/juce_events/timers/juce_MultiTimer.h index c7fe0e4..d32a0dd 100644 --- a/JuceLibraryCode/modules/juce_events/timers/juce_MultiTimer.h +++ b/JuceLibraryCode/modules/juce_events/timers/juce_MultiTimer.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_events/timers/juce_Timer.cpp b/JuceLibraryCode/modules/juce_events/timers/juce_Timer.cpp index 6b7343a..284e1ce 100644 --- a/JuceLibraryCode/modules/juce_events/timers/juce_Timer.cpp +++ b/JuceLibraryCode/modules/juce_events/timers/juce_Timer.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -112,10 +112,10 @@ public: { const LockType::ScopedLockType sl (lock); - while (firstTimer != nullptr && firstTimer->countdownMs <= 0) + while (firstTimer != nullptr && firstTimer->timerCountdownMs <= 0) { Timer* const t = firstTimer; - t->countdownMs = t->periodMs; + t->timerCountdownMs = t->timerPeriodMs; removeTimer (t); addTimer (t); @@ -169,11 +169,11 @@ public: { if (instance != nullptr) { - tim->countdownMs = newCounter; - tim->periodMs = newCounter; + tim->timerCountdownMs = newCounter; + tim->timerPeriodMs = newCounter; - if ((tim->next != nullptr && tim->next->countdownMs < tim->countdownMs) - || (tim->previous != nullptr && tim->previous->countdownMs > tim->countdownMs)) + if ((tim->nextTimer != nullptr && tim->nextTimer->timerCountdownMs < tim->timerCountdownMs) + || (tim->previousTimer != nullptr && tim->previousTimer->timerCountdownMs > tim->timerCountdownMs)) { instance->removeTimer (tim); instance->addTimer (tim); @@ -186,7 +186,7 @@ public: private: Timer* volatile firstTimer; - Atomic callbackNeeded; + Atomic callbackNeeded; struct CallTimersMessage : public MessageManager::MessageBase { @@ -210,28 +210,28 @@ private: Timer* i = firstTimer; - if (i == nullptr || i->countdownMs > t->countdownMs) + if (i == nullptr || i->timerCountdownMs > t->timerCountdownMs) { - t->next = firstTimer; + t->nextTimer = firstTimer; firstTimer = t; } else { - while (i->next != nullptr && i->next->countdownMs <= t->countdownMs) - i = i->next; + while (i->nextTimer != nullptr && i->nextTimer->timerCountdownMs <= t->timerCountdownMs) + i = i->nextTimer; jassert (i != nullptr); - t->next = i->next; - t->previous = i; - i->next = t; + t->nextTimer = i->nextTimer; + t->previousTimer = i; + i->nextTimer = t; } - if (t->next != nullptr) - t->next->previous = t; + if (t->nextTimer != nullptr) + t->nextTimer->previousTimer = t; - jassert ((t->next == nullptr || t->next->countdownMs >= t->countdownMs) - && (t->previous == nullptr || t->previous->countdownMs <= t->countdownMs)); + jassert ((t->nextTimer == nullptr || t->nextTimer->timerCountdownMs >= t->timerCountdownMs) + && (t->previousTimer == nullptr || t->previousTimer->timerCountdownMs <= t->timerCountdownMs)); notify(); } @@ -244,32 +244,32 @@ private: jassert (timerExists (t)); #endif - if (t->previous != nullptr) + if (t->previousTimer != nullptr) { jassert (firstTimer != t); - t->previous->next = t->next; + t->previousTimer->nextTimer = t->nextTimer; } else { jassert (firstTimer == t); - firstTimer = t->next; + firstTimer = t->nextTimer; } - if (t->next != nullptr) - t->next->previous = t->previous; + if (t->nextTimer != nullptr) + t->nextTimer->previousTimer = t->previousTimer; - t->next = nullptr; - t->previous = nullptr; + t->nextTimer = nullptr; + t->previousTimer = nullptr; } int getTimeUntilFirstTimer (const int numMillisecsElapsed) const { const LockType::ScopedLockType sl (lock); - for (Timer* t = firstTimer; t != nullptr; t = t->next) - t->countdownMs -= numMillisecsElapsed; + for (Timer* t = firstTimer; t != nullptr; t = t->nextTimer) + t->timerCountdownMs -= numMillisecsElapsed; - return firstTimer != nullptr ? firstTimer->countdownMs : 1000; + return firstTimer != nullptr ? firstTimer->timerCountdownMs : 1000; } void handleAsyncUpdate() override @@ -280,7 +280,7 @@ private: #if JUCE_DEBUG bool timerExists (Timer* const t) const noexcept { - for (Timer* tt = firstTimer; tt != nullptr; tt = tt->next) + for (Timer* tt = firstTimer; tt != nullptr; tt = tt->nextTimer) if (tt == t) return true; @@ -296,18 +296,18 @@ Timer::TimerThread::LockType Timer::TimerThread::lock; //============================================================================== Timer::Timer() noexcept - : countdownMs (0), - periodMs (0), - previous (nullptr), - next (nullptr) + : timerCountdownMs (0), + timerPeriodMs (0), + previousTimer (nullptr), + nextTimer (nullptr) { } Timer::Timer (const Timer&) noexcept - : countdownMs (0), - periodMs (0), - previous (nullptr), - next (nullptr) + : timerCountdownMs (0), + timerPeriodMs (0), + previousTimer (nullptr), + nextTimer (nullptr) { } @@ -320,10 +320,10 @@ void Timer::startTimer (const int interval) noexcept { const TimerThread::LockType::ScopedLockType sl (TimerThread::lock); - if (periodMs == 0) + if (timerPeriodMs == 0) { - countdownMs = interval; - periodMs = jmax (1, interval); + timerCountdownMs = interval; + timerPeriodMs = jmax (1, interval); TimerThread::add (this); } else @@ -332,14 +332,22 @@ void Timer::startTimer (const int interval) noexcept } } +void Timer::startTimerHz (int timerFrequencyHz) noexcept +{ + if (timerFrequencyHz > 0) + startTimer (1000 / timerFrequencyHz); + else + stopTimer(); +} + void Timer::stopTimer() noexcept { const TimerThread::LockType::ScopedLockType sl (TimerThread::lock); - if (periodMs > 0) + if (timerPeriodMs > 0) { TimerThread::remove (this); - periodMs = 0; + timerPeriodMs = 0; } } diff --git a/JuceLibraryCode/modules/juce_events/timers/juce_Timer.h b/JuceLibraryCode/modules/juce_events/timers/juce_Timer.h index a2f823a..a6670e3 100644 --- a/JuceLibraryCode/modules/juce_events/timers/juce_Timer.h +++ b/JuceLibraryCode/modules/juce_events/timers/juce_Timer.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -54,7 +54,6 @@ class JUCE_API Timer protected: //============================================================================== /** Creates a Timer. - When created, the timer is stopped, so use startTimer() to get it going. */ Timer() noexcept; @@ -64,7 +63,7 @@ protected: Note that this timer won't be started, even if the one you're copying is running. */ - Timer (const Timer& other) noexcept; + Timer (const Timer&) noexcept; public: //============================================================================== @@ -86,11 +85,16 @@ public: time between calling this method and the next timer callback will not be less than the interval length passed in. - @param intervalInMilliseconds the interval to use (any values less than 1 will be - rounded up to 1) + @param intervalInMilliseconds the interval to use (any value less + than 1 will be rounded up to 1) */ void startTimer (int intervalInMilliseconds) noexcept; + /** Starts the timer with an interval specified in Hertz. + This is effectively the same as calling startTimer (1000 / timerFrequencyHz). + */ + void startTimerHz (int timerFrequencyHz) noexcept; + /** Stops the timer. No more callbacks will be made after this method returns. @@ -102,17 +106,13 @@ public: void stopTimer() noexcept; //============================================================================== - /** Checks if the timer has been started. - - @returns true if the timer is running. - */ - bool isTimerRunning() const noexcept { return periodMs > 0; } + /** Returns true if the timer is currently running. */ + bool isTimerRunning() const noexcept { return timerPeriodMs > 0; } /** Returns the timer's interval. - @returns the timer's interval in milliseconds if it's running, or 0 if it's not. */ - int getTimerInterval() const noexcept { return periodMs; } + int getTimerInterval() const noexcept { return timerPeriodMs; } //============================================================================== @@ -124,11 +124,10 @@ public: private: class TimerThread; friend class TimerThread; - int countdownMs, periodMs; - Timer* previous; - Timer* next; + int timerCountdownMs, timerPeriodMs; // NB: these member variable names are a little verbose + Timer* previousTimer, *nextTimer; // to reduce risk of name-clashes with user subclasses - Timer& operator= (const Timer&); + Timer& operator= (const Timer&) JUCE_DELETED_FUNCTION; }; #endif // JUCE_TIMER_H_INCLUDED diff --git a/JuceLibraryCode/modules/juce_graphics/colour/juce_Colour.cpp b/JuceLibraryCode/modules/juce_graphics/colour/juce_Colour.cpp index aaf9468..43d99e7 100644 --- a/JuceLibraryCode/modules/juce_graphics/colour/juce_Colour.cpp +++ b/JuceLibraryCode/modules/juce_graphics/colour/juce_Colour.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -136,7 +136,7 @@ namespace ColourHelpers //============================================================================== Colour::Colour() noexcept - : argb (0) + : argb (0, 0, 0, 0) { } @@ -151,11 +151,12 @@ Colour& Colour::operator= (const Colour& other) noexcept return *this; } -bool Colour::operator== (const Colour& other) const noexcept { return argb.getARGB() == other.argb.getARGB(); } -bool Colour::operator!= (const Colour& other) const noexcept { return argb.getARGB() != other.argb.getARGB(); } +bool Colour::operator== (const Colour& other) const noexcept { return argb.getNativeARGB() == other.argb.getNativeARGB(); } +bool Colour::operator!= (const Colour& other) const noexcept { return argb.getNativeARGB() != other.argb.getNativeARGB(); } //============================================================================== -Colour::Colour (const uint32 col) noexcept : argb (col) +Colour::Colour (const uint32 col) noexcept + : argb ((col >> 24) & 0xff, (col >> 16) & 0xff, (col >> 8) & 0xff, col & 0xff) { } @@ -206,10 +207,26 @@ Colour::Colour (const float hue, const float saturation, const float brightness, { } +Colour::Colour (PixelARGB argb_) noexcept + : argb (argb_) +{ +} + +Colour::Colour (PixelRGB rgb) noexcept + : argb (Colour (rgb.getInARGBMaskOrder()).argb) +{ +} + +Colour::Colour (PixelAlpha alpha) noexcept + : argb (Colour (alpha.getInARGBMaskOrder()).argb) +{ +} + Colour::~Colour() noexcept { } + //============================================================================== const PixelARGB Colour::getPixelARGB() const noexcept { @@ -220,7 +237,7 @@ const PixelARGB Colour::getPixelARGB() const noexcept uint32 Colour::getARGB() const noexcept { - return argb.getARGB(); + return argb.getInARGBMaskOrder(); } //============================================================================== @@ -238,7 +255,7 @@ Colour Colour::withAlpha (const uint8 newAlpha) const noexcept { PixelARGB newCol (argb); newCol.setAlpha (newAlpha); - return Colour (newCol.getARGB()); + return Colour (newCol); } Colour Colour::withAlpha (const float newAlpha) const noexcept @@ -247,7 +264,7 @@ Colour Colour::withAlpha (const float newAlpha) const noexcept PixelARGB newCol (argb); newCol.setAlpha (ColourHelpers::floatToUInt8 (newAlpha)); - return Colour (newCol.getARGB()); + return Colour (newCol); } Colour Colour::withMultipliedAlpha (const float alphaMultiplier) const noexcept @@ -256,7 +273,7 @@ Colour Colour::withMultipliedAlpha (const float alphaMultiplier) const noexcept PixelARGB newCol (argb); newCol.setAlpha ((uint8) jmin (0xff, roundToInt (alphaMultiplier * newCol.getAlpha()))); - return Colour (newCol.getARGB()); + return Colour (newCol); } //============================================================================== @@ -294,7 +311,7 @@ Colour Colour::interpolatedWith (Colour other, float proportionOfOther) const no c1.tween (c2, (uint32) roundToInt (proportionOfOther * 255.0f)); c1.unpremultiply(); - return Colour (c1.getARGB()); + return Colour (c1); } //============================================================================== @@ -428,7 +445,7 @@ Colour Colour::contrasting (Colour colour1, //============================================================================== String Colour::toString() const { - return String::toHexString ((int) argb.getARGB()); + return String::toHexString ((int) argb.getInARGBMaskOrder()); } Colour Colour::fromString (StringRef encodedColourString) @@ -438,7 +455,7 @@ Colour Colour::fromString (StringRef encodedColourString) String Colour::toDisplayString (const bool includeAlphaValue) const { - return String::toHexString ((int) (argb.getARGB() & (includeAlphaValue ? 0xffffffff : 0xffffff))) + return String::toHexString ((int) (argb.getInARGBMaskOrder() & (includeAlphaValue ? 0xffffffff : 0xffffff))) .paddedLeft ('0', includeAlphaValue ? 8 : 6) .toUpperCase(); } diff --git a/JuceLibraryCode/modules/juce_graphics/colour/juce_Colour.h b/JuceLibraryCode/modules/juce_graphics/colour/juce_Colour.h index 4d84504..885eaa3 100644 --- a/JuceLibraryCode/modules/juce_graphics/colour/juce_Colour.h +++ b/JuceLibraryCode/modules/juce_graphics/colour/juce_Colour.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -115,6 +115,19 @@ public: float brightness, float alpha) noexcept; + /** Creates a colour using a PixelARGB object. This function assumes that the argb pixel is + not premultiplied. + */ + Colour (PixelARGB argb) noexcept; + + /** Creates a colour using a PixelRGB object. + */ + Colour (PixelRGB rgb) noexcept; + + /** Creates a colour using a PixelAlpha object. + */ + Colour (PixelAlpha alpha) noexcept; + /** Creates a colour using floating point hue, saturation and brightness values, and an 8-bit alpha. The floating point values must be between 0.0 and 1.0. diff --git a/JuceLibraryCode/modules/juce_graphics/colour/juce_ColourGradient.cpp b/JuceLibraryCode/modules/juce_graphics/colour/juce_ColourGradient.cpp index 75d1712..87ccb56 100644 --- a/JuceLibraryCode/modules/juce_graphics/colour/juce_ColourGradient.cpp +++ b/JuceLibraryCode/modules/juce_graphics/colour/juce_ColourGradient.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -32,12 +32,12 @@ ColourGradient::ColourGradient() noexcept #endif } -ColourGradient::ColourGradient (Colour colour1, const float x1_, const float y1_, - Colour colour2, const float x2_, const float y2_, - const bool isRadial_) - : point1 (x1_, y1_), - point2 (x2_, y2_), - isRadial (isRadial_) +ColourGradient::ColourGradient (Colour colour1, const float x1, const float y1, + Colour colour2, const float x2, const float y2, + const bool radial) + : point1 (x1, y1), + point2 (x2, y2), + isRadial (radial) { colours.add (ColourPoint (0.0, colour1)); colours.add (ColourPoint (1.0, colour2)); diff --git a/JuceLibraryCode/modules/juce_graphics/colour/juce_ColourGradient.h b/JuceLibraryCode/modules/juce_graphics/colour/juce_ColourGradient.h index 73e6631..9349d82 100644 --- a/JuceLibraryCode/modules/juce_graphics/colour/juce_ColourGradient.h +++ b/JuceLibraryCode/modules/juce_graphics/colour/juce_ColourGradient.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_graphics/colour/juce_Colours.cpp b/JuceLibraryCode/modules/juce_graphics/colour/juce_Colours.cpp index fbde0ba..f79d528 100644 --- a/JuceLibraryCode/modules/juce_graphics/colour/juce_Colours.cpp +++ b/JuceLibraryCode/modules/juce_graphics/colour/juce_Colours.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_graphics/colour/juce_Colours.h b/JuceLibraryCode/modules/juce_graphics/colour/juce_Colours.h index 90e4aa5..86f3828 100644 --- a/JuceLibraryCode/modules/juce_graphics/colour/juce_Colours.h +++ b/JuceLibraryCode/modules/juce_graphics/colour/juce_Colours.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_graphics/colour/juce_FillType.cpp b/JuceLibraryCode/modules/juce_graphics/colour/juce_FillType.cpp index 5e5db56..c477f71 100644 --- a/JuceLibraryCode/modules/juce_graphics/colour/juce_FillType.cpp +++ b/JuceLibraryCode/modules/juce_graphics/colour/juce_FillType.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_graphics/colour/juce_FillType.h b/JuceLibraryCode/modules/juce_graphics/colour/juce_FillType.h index 19401d6..3cf037d 100644 --- a/JuceLibraryCode/modules/juce_graphics/colour/juce_FillType.h +++ b/JuceLibraryCode/modules/juce_graphics/colour/juce_FillType.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_graphics/colour/juce_PixelFormats.h b/JuceLibraryCode/modules/juce_graphics/colour/juce_PixelFormats.h index 2715cb2..0df5987 100644 --- a/JuceLibraryCode/modules/juce_graphics/colour/juce_PixelFormats.h +++ b/JuceLibraryCode/modules/juce_graphics/colour/juce_PixelFormats.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -46,7 +46,7 @@ inline uint32 clampPixelComponents (uint32 x) noexcept //============================================================================== /** - Represents a 32-bit ARGB pixel with premultiplied alpha, and can perform compositing + Represents a 32-bit INTERNAL pixel with premultiplied alpha, and can perform compositing operations with it. This is used internally by the imaging classes. @@ -60,13 +60,6 @@ public: PixelARGB() noexcept {} ~PixelARGB() noexcept {} - /** Creates a pixel from a 32-bit argb value. - */ - PixelARGB (const uint32 argbValue) noexcept - : argb (argbValue) - { - } - PixelARGB (const uint8 a, const uint8 r, const uint8 g, const uint8 b) noexcept { components.b = b; @@ -75,30 +68,81 @@ public: components.a = a; } - forcedinline uint32 getARGB() const noexcept { return argb; } - forcedinline uint32 getUnpremultipliedARGB() const noexcept { PixelARGB p (argb); p.unpremultiply(); return p.getARGB(); } + //============================================================================== + /** Returns a uint32 which represents the pixel in a platform dependent format. */ + forcedinline uint32 getNativeARGB() const noexcept { return internal; } - forcedinline uint32 getRB() const noexcept { return 0x00ff00ff & argb; } - forcedinline uint32 getAG() const noexcept { return 0x00ff00ff & (argb >> 8); } + /** Returns a uint32 which will be in argb order as if constructed with the following mask operation + ((alpha << 24) | (red << 16) | (green << 8) | blue). */ + forcedinline uint32 getInARGBMaskOrder() const noexcept + { + #if JUCE_ANDROID + return (uint32) ((components.a << 24) | (components.r << 16) | (components.g << 8) | (components.b << 0)); + #else + return getNativeARGB(); + #endif + } - forcedinline uint8 getAlpha() const noexcept { return components.a; } - forcedinline uint8 getRed() const noexcept { return components.r; } - forcedinline uint8 getGreen() const noexcept { return components.g; } - forcedinline uint8 getBlue() const noexcept { return components.b; } + /** Returns a uint32 which when written to memory, will be in the order a, r, g, b. In other words, + if the return-value is read as a uint8 array then the elements will be in the order of a, r, g, b*/ + inline uint32 getInARGBMemoryOrder() const noexcept + { + #if JUCE_BIG_ENDIAN + return getInARGBMaskOrder(); + #else + return (uint32) ((components.b << 24) | (components.g << 16) | (components.r << 8) | components.a); + #endif + } + + /** Return channels with an even index and insert zero bytes between them. This is useful for blending + operations. The exact channels which are returned is platform dependent. */ + forcedinline uint32 getEvenBytes() const noexcept { return 0x00ff00ff & internal; } + + /** Return channels with an odd index and insert zero bytes between them. This is useful for blending + operations. The exact channels which are returned is platform dependent. */ + forcedinline uint32 getOddBytes() const noexcept { return 0x00ff00ff & (internal >> 8); } + + //============================================================================== + forcedinline uint8 getAlpha() const noexcept { return components.a; } + forcedinline uint8 getRed() const noexcept { return components.r; } + forcedinline uint8 getGreen() const noexcept { return components.g; } + forcedinline uint8 getBlue() const noexcept { return components.b; } #if JUCE_GCC && ! JUCE_CLANG // NB these are here as a workaround because GCC refuses to bind to packed values. - forcedinline uint8& getAlpha() noexcept { return comps [indexA]; } - forcedinline uint8& getRed() noexcept { return comps [indexR]; } - forcedinline uint8& getGreen() noexcept { return comps [indexG]; } - forcedinline uint8& getBlue() noexcept { return comps [indexB]; } + forcedinline uint8& getAlpha() noexcept { return comps [indexA]; } + forcedinline uint8& getRed() noexcept { return comps [indexR]; } + forcedinline uint8& getGreen() noexcept { return comps [indexG]; } + forcedinline uint8& getBlue() noexcept { return comps [indexB]; } #else - forcedinline uint8& getAlpha() noexcept { return components.a; } - forcedinline uint8& getRed() noexcept { return components.r; } - forcedinline uint8& getGreen() noexcept { return components.g; } - forcedinline uint8& getBlue() noexcept { return components.b; } + forcedinline uint8& getAlpha() noexcept { return components.a; } + forcedinline uint8& getRed() noexcept { return components.r; } + forcedinline uint8& getGreen() noexcept { return components.g; } + forcedinline uint8& getBlue() noexcept { return components.b; } #endif + //============================================================================== + /** Copies another pixel colour over this one. + + This doesn't blend it - this colour is simply replaced by the other one. + */ + template + forcedinline void set (const Pixel& src) noexcept + { + internal = src.getNativeARGB(); + } + + //============================================================================== + /** Sets the pixel's colour from individual components. */ + void setARGB (const uint8 a, const uint8 r, const uint8 g, const uint8 b) noexcept + { + components.b = b; + components.g = g; + components.r = r; + components.a = a; + } + + //============================================================================== /** Blends another pixel onto this one. This takes into account the opacity of the pixel being overlaid, and blends @@ -107,10 +151,15 @@ public: template forcedinline void blend (const Pixel& src) noexcept { - const uint32 alpha = 0x100 - src.getAlpha(); - uint32 rb = src.getRB() + maskPixelComponents (getRB() * alpha); - uint32 ag = src.getAG() + maskPixelComponents (getAG() * alpha); - argb = clampPixelComponents (rb) + (clampPixelComponents (ag) << 8); + uint32 rb = src.getEvenBytes(); + uint32 ag = src.getOddBytes(); + + const uint32 alpha = 0x100 - (ag >> 16); + + rb += maskPixelComponents (getEvenBytes() * alpha); + ag += maskPixelComponents (getOddBytes() * alpha); + + internal = clampPixelComponents (rb) | (clampPixelComponents (ag) << 8); } /** Blends another pixel onto this one. @@ -129,14 +178,15 @@ public: template forcedinline void blend (const Pixel& src, uint32 extraAlpha) noexcept { - uint32 ag = maskPixelComponents (extraAlpha * src.getAG()); + uint32 rb = maskPixelComponents (extraAlpha * src.getEvenBytes()); + uint32 ag = maskPixelComponents (extraAlpha * src.getOddBytes()); + const uint32 alpha = 0x100 - (ag >> 16); - ag += maskPixelComponents (getAG() * alpha); - uint32 rb = maskPixelComponents (extraAlpha * src.getRB()) - + maskPixelComponents (getRB() * alpha); + rb += maskPixelComponents (getEvenBytes() * alpha); + ag += maskPixelComponents (getOddBytes() * alpha); - argb = clampPixelComponents(rb) + (clampPixelComponents (ag) << 8); + internal = clampPixelComponents (rb) | (clampPixelComponents (ag) << 8); } /** Blends another pixel with this one, creating a colour that is somewhere @@ -145,29 +195,20 @@ public: template forcedinline void tween (const Pixel& src, const uint32 amount) noexcept { - uint32 drb = getRB(); - drb += (((src.getRB() - drb) * amount) >> 8); - drb &= 0x00ff00ff; + uint32 dEvenBytes = getEvenBytes(); + dEvenBytes += (((src.getEvenBytes() - dEvenBytes) * amount) >> 8); + dEvenBytes &= 0x00ff00ff; - uint32 dag = getAG(); - dag += (((src.getAG() - dag) * amount) >> 8); - dag &= 0x00ff00ff; - dag <<= 8; + uint32 dOddBytes = getOddBytes(); + dOddBytes += (((src.getOddBytes() - dOddBytes) * amount) >> 8); + dOddBytes &= 0x00ff00ff; + dOddBytes <<= 8; - dag |= drb; - argb = dag; - } - - /** Copies another pixel colour over this one. - - This doesn't blend it - this colour is simply replaced by the other one. - */ - template - forcedinline void set (const Pixel& src) noexcept - { - argb = src.getARGB(); + dOddBytes |= dEvenBytes; + internal = dOddBytes; } + //============================================================================== /** Replaces the colour's alpha value with another one. */ forcedinline void setAlpha (const uint8 newAlpha) noexcept { @@ -177,10 +218,12 @@ public: /** Multiplies the colour's alpha value with another one. */ forcedinline void multiplyAlpha (int multiplier) noexcept { + // increment alpha by 1, so that if multiplier == 255 (full alpha), + // this function will not change the values. ++multiplier; - argb = ((((uint32) multiplier) * getAG()) & 0xff00ff00) - | (((((uint32) multiplier) * getRB()) >> 8) & 0x00ff00ff); + internal = ((((uint32) multiplier) * getOddBytes()) & 0xff00ff00) + | (((((uint32) multiplier) * getEvenBytes()) >> 8) & 0x00ff00ff); } forcedinline void multiplyAlpha (const float multiplier) noexcept @@ -188,14 +231,8 @@ public: multiplyAlpha ((int) (multiplier * 255.0f)); } - /** Sets the pixel's colour from individual components. */ - void setARGB (const uint8 a, const uint8 r, const uint8 g, const uint8 b) noexcept - { - components.b = b; - components.g = g; - components.r = r; - components.a = a; - } + + inline PixelARGB getUnpremultiplied() const noexcept { PixelARGB p (internal); p.unpremultiply(); return p; } /** Premultiplies the pixel's RGB values by its alpha. */ forcedinline void premultiply() noexcept @@ -234,9 +271,9 @@ public: } else { - components.b = (uint8) jmin ((uint32) 0xff, (components.b * 0xff) / alpha); - components.g = (uint8) jmin ((uint32) 0xff, (components.g * 0xff) / alpha); - components.r = (uint8) jmin ((uint32) 0xff, (components.r * 0xff) / alpha); + components.b = (uint8) jmin ((uint32) 0xffu, (components.b * 0xffu) / alpha); + components.g = (uint8) jmin ((uint32) 0xffu, (components.g * 0xffu) / alpha); + components.r = (uint8) jmin ((uint32) 0xffu, (components.r * 0xffu) / alpha); } } } @@ -257,41 +294,53 @@ public: } } - /** Returns a uint32 which when written to memory, will be in the order r, g, b, a. */ - inline uint32 getInRGBAMemoryOrder() const noexcept - { - #if JUCE_BIG_ENDIAN - return (((uint32) components.r) << 24) | (((uint32) components.g) << 16) | (((uint32) components.b) << 8) | components.a; - #else - return (((uint32) components.a) << 24) | (((uint32) components.b) << 16) | (((uint32) components.g) << 8) | components.r; - #endif - } - //============================================================================== /** The indexes of the different components in the byte layout of this type of colour. */ + #if JUCE_ANDROID + #if JUCE_BIG_ENDIAN + enum { indexA = 0, indexR = 3, indexG = 2, indexB = 1 }; + #else + enum { indexA = 3, indexR = 0, indexG = 1, indexB = 2 }; + #endif + #else #if JUCE_BIG_ENDIAN enum { indexA = 0, indexR = 1, indexG = 2, indexB = 3 }; #else enum { indexA = 3, indexR = 2, indexG = 1, indexB = 0 }; #endif + #endif private: + //============================================================================== + PixelARGB (const uint32 internalValue) noexcept + : internal (internalValue) + { + } + //============================================================================== struct Components { + #if JUCE_ANDROID + #if JUCE_BIG_ENDIAN + uint8 a, b, g, r; + #else + uint8 r, g, b, a; + #endif + #else #if JUCE_BIG_ENDIAN uint8 a, r, g, b; #else uint8 b, g, r, a; #endif + #endif } JUCE_PACKED; union { - uint32 argb; + uint32 internal; Components components; #if JUCE_GCC - uint8 comps[4]; + uint8 comps[4]; // helper struct needed because gcc does not allow references to packed union members #endif }; } @@ -316,23 +365,64 @@ public: PixelRGB() noexcept {} ~PixelRGB() noexcept {} - /** Creates a pixel from a 32-bit argb value. + //============================================================================== + /** Returns a uint32 which represents the pixel in a platform dependent format which is compatible + with the native format of a PixelARGB. - (The argb format is that used by PixelARGB) - */ - PixelRGB (const uint32 argb) noexcept + @see PixelARGB::getNativeARGB */ + forcedinline uint32 getNativeARGB() const noexcept { - r = (uint8) (argb >> 16); - g = (uint8) (argb >> 8); - b = (uint8) (argb); + #if JUCE_ANDROID + return (uint32) ((0xff << 24) | r | (g << 8) | (b << 16)); + #else + return (uint32) ((0xff << 24) | b | (g << 8) | (r << 16)); + #endif } - forcedinline uint32 getARGB() const noexcept { return 0xff000000 | b | (((uint32) g) << 8) | (((uint32) r) << 16); } - forcedinline uint32 getUnpremultipliedARGB() const noexcept { return getARGB(); } + /** Returns a uint32 which will be in argb order as if constructed with the following mask operation + ((alpha << 24) | (red << 16) | (green << 8) | blue). */ + forcedinline uint32 getInARGBMaskOrder() const noexcept + { + #if JUCE_ANDROID + return (uint32) ((0xff << 24) | (r << 16) | (g << 8) | (b << 0)); + #else + return getNativeARGB(); + #endif + } - forcedinline uint32 getRB() const noexcept { return b | (uint32) (r << 16); } - forcedinline uint32 getAG() const noexcept { return (uint32) (0xff0000 | g); } + /** Returns a uint32 which when written to memory, will be in the order a, r, g, b. In other words, + if the return-value is read as a uint8 array then the elements will be in the order of a, r, g, b*/ + inline uint32 getInARGBMemoryOrder() const noexcept + { + #if JUCE_BIG_ENDIAN + return getInARGBMaskOrder(); + #else + return (uint32) ((b << 24) | (g << 16) | (r << 8) | 0xff); + #endif + } + /** Return channels with an even index and insert zero bytes between them. This is useful for blending + operations. The exact channels which are returned is platform dependent but compatible with the + return value of getEvenBytes of the PixelARGB class. + + @see PixelARGB::getEvenBytes */ + forcedinline uint32 getEvenBytes() const noexcept + { + #if JUCE_ANDROID + return (uint32) (r | (b << 16)); + #else + return (uint32) (b | (r << 16)); + #endif + } + + /** Return channels with an odd index and insert zero bytes between them. This is useful for blending + operations. The exact channels which are returned is platform dependent but compatible with the + return value of getOddBytes of the PixelARGB class. + + @see PixelARGB::getOddBytes */ + forcedinline uint32 getOddBytes() const noexcept { return (uint32)0xff0000 | g; } + + //============================================================================== forcedinline uint8 getAlpha() const noexcept { return 0xff; } forcedinline uint8 getRed() const noexcept { return r; } forcedinline uint8 getGreen() const noexcept { return g; } @@ -342,6 +432,30 @@ public: forcedinline uint8& getGreen() noexcept { return g; } forcedinline uint8& getBlue() noexcept { return b; } + //============================================================================== + /** Copies another pixel colour over this one. + + This doesn't blend it - this colour is simply replaced by the other one. + Because PixelRGB has no alpha channel, any alpha value in the source pixel + is thrown away. + */ + template + forcedinline void set (const Pixel& src) noexcept + { + b = src.getBlue(); + g = src.getGreen(); + r = src.getRed(); + } + + /** Sets the pixel's colour from individual components. */ + void setARGB (const uint8, const uint8 red, const uint8 green, const uint8 blue) noexcept + { + r = red; + g = green; + b = blue; + } + + //============================================================================== /** Blends another pixel onto this one. This takes into account the opacity of the pixel being overlaid, and blends @@ -350,14 +464,22 @@ public: template forcedinline void blend (const Pixel& src) noexcept { - const uint32 alpha = 0x100 - src.getAlpha(); + const uint32 alpha = (uint32) (0x100 - src.getAlpha()); - uint32 rb = clampPixelComponents (src.getRB() + maskPixelComponents (getRB() * alpha)); - uint32 ag = src.getAG() + (g * alpha >> 8); + // getEvenBytes returns 0x00rr00bb on non-android + uint32 rb = clampPixelComponents (src.getEvenBytes() + maskPixelComponents (getEvenBytes() * alpha)); + // getOddBytes returns 0x00aa00gg on non-android + uint32 ag = clampPixelComponents (src.getOddBytes() + ((g * alpha) >> 8)); + g = (uint8) (ag & 0xff); + + #if JUCE_ANDROID + b = (uint8) (rb >> 16); + r = (uint8) (rb & 0xff); + #else r = (uint8) (rb >> 16); - g = (uint8) clampPixelComponents (ag); - b = (uint8) rb; + b = (uint8) (rb & 0xff); + #endif } forcedinline void blend (const PixelRGB src) noexcept @@ -373,16 +495,23 @@ public: template forcedinline void blend (const Pixel& src, uint32 extraAlpha) noexcept { - uint32 ag = maskPixelComponents (extraAlpha * src.getAG()); + uint32 ag = maskPixelComponents (extraAlpha * src.getOddBytes()); + uint32 rb = maskPixelComponents (extraAlpha * src.getEvenBytes()); + const uint32 alpha = 0x100 - (ag >> 16); - ag += g * alpha >> 8; - uint32 rb = clampPixelComponents (maskPixelComponents (extraAlpha * src.getRB()) - + maskPixelComponents (getRB() * alpha)); + ag = clampPixelComponents (ag + (g * alpha >> 8)); + rb = clampPixelComponents (rb + maskPixelComponents (getEvenBytes() * alpha)); - b = (uint8) rb; - g = (uint8) clampPixelComponents (ag); + g = (uint8) (ag & 0xff); + + #if JUCE_ANDROID + b = (uint8) (rb >> 16); + r = (uint8) (rb & 0xff); + #else r = (uint8) (rb >> 16); + b = (uint8) (rb & 0xff); + #endif } /** Blends another pixel with this one, creating a colour that is somewhere @@ -391,31 +520,24 @@ public: template forcedinline void tween (const Pixel& src, const uint32 amount) noexcept { - uint32 drb = getRB(); - drb += (((src.getRB() - drb) * amount) >> 8); + uint32 dEvenBytes = getEvenBytes(); + dEvenBytes += (((src.getEvenBytes() - dEvenBytes) * amount) >> 8); - uint32 dag = getAG(); - dag += (((src.getAG() - dag) * amount) >> 8); + uint32 dOddBytes = getOddBytes(); + dOddBytes += (((src.getOddBytes() - dOddBytes) * amount) >> 8); - b = (uint8) drb; - g = (uint8) dag; - r = (uint8) (drb >> 16); - } - - /** Copies another pixel colour over this one. - - This doesn't blend it - this colour is simply replaced by the other one. - Because PixelRGB has no alpha channel, any alpha value in the source pixel - is thrown away. - */ - template - forcedinline void set (const Pixel& src) noexcept - { - b = src.getBlue(); - g = src.getGreen(); - r = src.getRed(); + g = (uint8) (dOddBytes & 0xff); // dOddBytes = 0x00aa00gg + + #if JUCE_ANDROID + r = (uint8) (dEvenBytes & 0xff); // dEvenBytes = 0x00bb00rr + b = (uint8) (dEvenBytes >> 16); + #else + b = (uint8) (dEvenBytes & 0xff); // dEvenBytes = 0x00rr00bb + r = (uint8) (dEvenBytes >> 16); + #endif } + //============================================================================== /** This method is included for compatibility with the PixelARGB class. */ forcedinline void setAlpha (const uint8) noexcept {} @@ -425,14 +547,6 @@ public: /** Multiplies the colour's alpha value with another one. */ forcedinline void multiplyAlpha (float) noexcept {} - /** Sets the pixel's colour from individual components. */ - void setARGB (const uint8, const uint8 red, const uint8 green, const uint8 blue) noexcept - { - r = red; - g = green; - b = blue; - } - /** Premultiplies the pixel's RGB values by its alpha. */ forcedinline void premultiply() noexcept {} @@ -454,6 +568,20 @@ public: private: //============================================================================== + PixelRGB (const uint32 internal) noexcept + { + #if JUCE_ANDROID + b = (uint8) (internal >> 16); + g = (uint8) (internal >> 8); + r = (uint8) (internal); + #else + r = (uint8) (internal >> 16); + g = (uint8) (internal >> 8); + b = (uint8) (internal); + #endif + } + + //============================================================================== #if JUCE_MAC uint8 r, g, b; #else @@ -486,21 +614,36 @@ public: PixelAlpha() noexcept {} ~PixelAlpha() noexcept {} - /** Creates a pixel from a 32-bit argb value. + //============================================================================== + /** Returns a uint32 which represents the pixel in a platform dependent format which is compatible + with the native format of a PixelARGB. - (The argb format is that used by PixelARGB) - */ - PixelAlpha (const uint32 argb) noexcept - { - a = (uint8) (argb >> 24); - } + @see PixelARGB::getNativeARGB */ + forcedinline uint32 getNativeARGB() const noexcept { return (uint32) ((a << 24) | (a << 16) | (a << 8) | a); } - forcedinline uint32 getARGB() const noexcept { return (((uint32) a) << 24) | (((uint32) a) << 16) | (((uint32) a) << 8) | a; } - forcedinline uint32 getUnpremultipliedARGB() const noexcept { return (((uint32) a) << 24) | 0xffffff; } + /** Returns a uint32 which will be in argb order as if constructed with the following mask operation + ((alpha << 24) | (red << 16) | (green << 8) | blue). */ + forcedinline uint32 getInARGBMaskOrder() const noexcept { return getNativeARGB(); } - forcedinline uint32 getRB() const noexcept { return (((uint32) a) << 16) | a; } - forcedinline uint32 getAG() const noexcept { return (((uint32) a) << 16) | a; } + /** Returns a uint32 which when written to memory, will be in the order a, r, g, b. In other words, + if the return-value is read as a uint8 array then the elements will be in the order of a, r, g, b*/ + inline uint32 getInARGBMemoryOrder() const noexcept { return getNativeARGB(); } + /** Return channels with an even index and insert zero bytes between them. This is useful for blending + operations. The exact channels which are returned is platform dependent but compatible with the + return value of getEvenBytes of the PixelARGB class. + + @see PixelARGB::getEvenBytes */ + forcedinline uint32 getEvenBytes() const noexcept { return (uint32) ((a << 16) | a); } + + /** Return channels with an odd index and insert zero bytes between them. This is useful for blending + operations. The exact channels which are returned is platform dependent but compatible with the + return value of getOddBytes of the PixelARGB class. + + @see PixelARGB::getOddBytes */ + forcedinline uint32 getOddBytes() const noexcept { return (uint32) ((a << 16) | a); } + + //============================================================================== forcedinline uint8 getAlpha() const noexcept { return a; } forcedinline uint8& getAlpha() noexcept { return a; } @@ -508,6 +651,24 @@ public: forcedinline uint8 getGreen() const noexcept { return 0; } forcedinline uint8 getBlue() const noexcept { return 0; } + //============================================================================== + /** Copies another pixel colour over this one. + + This doesn't blend it - this colour is simply replaced by the other one. + */ + template + forcedinline void set (const Pixel& src) noexcept + { + a = src.getAlpha(); + } + + /** Sets the pixel's colour from individual components. */ + forcedinline void setARGB (const uint8 a_, const uint8 /*r*/, const uint8 /*g*/, const uint8 /*b*/) noexcept + { + a = a_; + } + + //============================================================================== /** Blends another pixel onto this one. This takes into account the opacity of the pixel being overlaid, and blends @@ -542,16 +703,7 @@ public: a += ((src.getAlpha() - a) * amount) >> 8; } - /** Copies another pixel colour over this one. - - This doesn't blend it - this colour is simply replaced by the other one. - */ - template - forcedinline void set (const Pixel& src) noexcept - { - a = src.getAlpha(); - } - + //============================================================================== /** Replaces the colour's alpha value with another one. */ forcedinline void setAlpha (const uint8 newAlpha) noexcept { @@ -570,12 +722,6 @@ public: a = (uint8) (a * multiplier); } - /** Sets the pixel's colour from individual components. */ - forcedinline void setARGB (const uint8 a_, const uint8 /*r*/, const uint8 /*g*/, const uint8 /*b*/) noexcept - { - a = a_; - } - /** Premultiplies the pixel's RGB values by its alpha. */ forcedinline void premultiply() noexcept {} @@ -589,6 +735,12 @@ public: enum { indexA = 0 }; private: + //============================================================================== + PixelAlpha (const uint32 internal) noexcept + { + a = (uint8) (internal >> 24); + } + //============================================================================== uint8 a; } diff --git a/JuceLibraryCode/modules/juce_graphics/contexts/juce_GraphicsContext.cpp b/JuceLibraryCode/modules/juce_graphics/contexts/juce_GraphicsContext.cpp index a0dcd80..c6747f7 100644 --- a/JuceLibraryCode/modules/juce_graphics/contexts/juce_GraphicsContext.cpp +++ b/JuceLibraryCode/modules/juce_graphics/contexts/juce_GraphicsContext.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -32,8 +32,8 @@ namespace jassert ((int) x >= -maxVal && (int) x <= maxVal && (int) y >= -maxVal && (int) y <= maxVal - && (int) w >= -maxVal && (int) w <= maxVal - && (int) h >= -maxVal && (int) h <= maxVal); + && (int) w >= 0 && (int) w <= maxVal + && (int) h >= 0 && (int) h <= maxVal); #endif return Rectangle (x, y, w, h); @@ -427,6 +427,8 @@ void Graphics::drawRect (const Rectangle& r, int lineThickness) const void Graphics::drawRect (Rectangle r, const float lineThickness) const { + jassert (r.getWidth() >= 0.0f && r.getHeight() >= 0.0f); + RectangleList rects; rects.addWithoutMerging (r.removeFromTop (lineThickness)); rects.addWithoutMerging (r.removeFromBottom (lineThickness)); diff --git a/JuceLibraryCode/modules/juce_graphics/contexts/juce_GraphicsContext.h b/JuceLibraryCode/modules/juce_graphics/contexts/juce_GraphicsContext.h index d59bcd2..bf54581 100644 --- a/JuceLibraryCode/modules/juce_graphics/contexts/juce_GraphicsContext.h +++ b/JuceLibraryCode/modules/juce_graphics/contexts/juce_GraphicsContext.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -158,7 +158,7 @@ public: void drawText (const String& text, int x, int y, int width, int height, Justification justificationType, - bool useEllipsesIfTooBig) const; + bool useEllipsesIfTooBig = true) const; /** Draws a line of text within a specified rectangle. @@ -172,7 +172,7 @@ public: void drawText (const String& text, const Rectangle& area, Justification justificationType, - bool useEllipsesIfTooBig) const; + bool useEllipsesIfTooBig = true) const; /** Draws a line of text within a specified rectangle. @@ -186,7 +186,7 @@ public: void drawText (const String& text, const Rectangle& area, Justification justificationType, - bool useEllipsesIfTooBig) const; + bool useEllipsesIfTooBig = true) const; /** Tries to draw a text string inside a given space. @@ -203,7 +203,7 @@ public: The minimumHorizontalScale parameter specifies how much the text can be squashed horizontally to try to squeeze it into the space. If you don't want any horizontal scaling to occur, you - can set this value to 1.0f. + can set this value to 1.0f. Pass 0 if you want it to use a default value. @see GlyphArrangement::addFittedText */ @@ -211,7 +211,7 @@ public: int x, int y, int width, int height, Justification justificationFlags, int maximumNumberOfLines, - float minimumHorizontalScale = 0.7f) const; + float minimumHorizontalScale = 0.0f) const; /** Tries to draw a text string inside a given space. @@ -228,7 +228,7 @@ public: The minimumHorizontalScale parameter specifies how much the text can be squashed horizontally to try to squeeze it into the space. If you don't want any horizontal scaling to occur, you - can set this value to 1.0f. + can set this value to 1.0f. Pass 0 if you want it to use a default value. @see GlyphArrangement::addFittedText */ @@ -236,7 +236,7 @@ public: const Rectangle& area, Justification justificationFlags, int maximumNumberOfLines, - float minimumHorizontalScale = 0.7f) const; + float minimumHorizontalScale = 0.0f) const; //============================================================================== /** Fills the context's entire clip region with the current colour or brush. @@ -374,21 +374,29 @@ public: //============================================================================== /** Draws a line between two points. The line is 1 pixel wide and drawn with the current colour or brush. + TIP: If you're trying to draw horizontal or vertical lines, don't use this - + it's better to use fillRect() instead unless you really need an angled line. */ void drawLine (float startX, float startY, float endX, float endY) const; /** Draws a line between two points with a given thickness. + TIP: If you're trying to draw horizontal or vertical lines, don't use this - + it's better to use fillRect() instead unless you really need an angled line. @see Path::addLineSegment */ void drawLine (float startX, float startY, float endX, float endY, float lineThickness) const; /** Draws a line between two points. The line is 1 pixel wide and drawn with the current colour or brush. + TIP: If you're trying to draw horizontal or vertical lines, don't use this - + it's better to use fillRect() instead unless you really need an angled line. */ void drawLine (const Line& line) const; /** Draws a line between two points with a given thickness. @see Path::addLineSegment + TIP: If you're trying to draw horizontal or vertical lines, don't use this - + it's better to use fillRect() instead unless you really need an angled line. */ void drawLine (const Line& line, float lineThickness) const; diff --git a/JuceLibraryCode/modules/juce_graphics/contexts/juce_LowLevelGraphicsContext.h b/JuceLibraryCode/modules/juce_graphics/contexts/juce_LowLevelGraphicsContext.h index 8a0176f..30a305e 100644 --- a/JuceLibraryCode/modules/juce_graphics/contexts/juce_LowLevelGraphicsContext.h +++ b/JuceLibraryCode/modules/juce_graphics/contexts/juce_LowLevelGraphicsContext.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_graphics/contexts/juce_LowLevelGraphicsPostScriptRenderer.cpp b/JuceLibraryCode/modules/juce_graphics/contexts/juce_LowLevelGraphicsPostScriptRenderer.cpp index be4329c..d2d6a1e 100644 --- a/JuceLibraryCode/modules/juce_graphics/contexts/juce_LowLevelGraphicsPostScriptRenderer.cpp +++ b/JuceLibraryCode/modules/juce_graphics/contexts/juce_LowLevelGraphicsPostScriptRenderer.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -51,7 +51,7 @@ LowLevelGraphicsPostScriptRenderer::LowLevelGraphicsPostScriptRenderer (OutputSt out << "%!PS-Adobe-3.0 EPSF-3.0" "\n%%BoundingBox: 0 0 600 824" "\n%%Pages: 0" - "\n%%Creator: Raw Material Software JUCE" + "\n%%Creator: ROLI Ltd. JUCE" "\n%%Title: " << documentTitle << "\n%%CreationDate: none" "\n%%LanguageLevel: 2" @@ -384,7 +384,7 @@ void LowLevelGraphicsPostScriptRenderer::fillPath (const Path& path, const Affin { // this doesn't work correctly yet - it could be improved to handle solid gradients, but // postscript can't do semi-transparent ones. - notPossibleInPostscriptAssert // you can disable this warning by setting the WARN_ABOUT_NON_POSTSCRIPT_OPERATIONS flag at the top of this file + notPossibleInPostscriptAssert; // you can disable this warning by setting the WARN_ABOUT_NON_POSTSCRIPT_OPERATIONS flag at the top of this file writeClip(); out << "gsave "; @@ -433,11 +433,11 @@ void LowLevelGraphicsPostScriptRenderer::writeImage (const Image& im, { PixelARGB p (*(const PixelARGB*) pixelData); p.unpremultiply(); - pixel = Colours::white.overlaidWith (Colour (p.getARGB())); + pixel = Colours::white.overlaidWith (Colour (p)); } else if (im.isRGB()) { - pixel = Colour (((const PixelRGB*) pixelData)->getARGB()); + pixel = Colour (*((const PixelRGB*) pixelData)); } else { diff --git a/JuceLibraryCode/modules/juce_graphics/contexts/juce_LowLevelGraphicsPostScriptRenderer.h b/JuceLibraryCode/modules/juce_graphics/contexts/juce_LowLevelGraphicsPostScriptRenderer.h index 2b893a3..94364f6 100644 --- a/JuceLibraryCode/modules/juce_graphics/contexts/juce_LowLevelGraphicsPostScriptRenderer.h +++ b/JuceLibraryCode/modules/juce_graphics/contexts/juce_LowLevelGraphicsPostScriptRenderer.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_graphics/contexts/juce_LowLevelGraphicsSoftwareRenderer.cpp b/JuceLibraryCode/modules/juce_graphics/contexts/juce_LowLevelGraphicsSoftwareRenderer.cpp index a57e4d6..535f74e 100644 --- a/JuceLibraryCode/modules/juce_graphics/contexts/juce_LowLevelGraphicsSoftwareRenderer.cpp +++ b/JuceLibraryCode/modules/juce_graphics/contexts/juce_LowLevelGraphicsSoftwareRenderer.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_graphics/contexts/juce_LowLevelGraphicsSoftwareRenderer.h b/JuceLibraryCode/modules/juce_graphics/contexts/juce_LowLevelGraphicsSoftwareRenderer.h index 9928092..14f14a6 100644 --- a/JuceLibraryCode/modules/juce_graphics/contexts/juce_LowLevelGraphicsSoftwareRenderer.h +++ b/JuceLibraryCode/modules/juce_graphics/contexts/juce_LowLevelGraphicsSoftwareRenderer.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_graphics/effects/juce_DropShadowEffect.cpp b/JuceLibraryCode/modules/juce_graphics/effects/juce_DropShadowEffect.cpp index 448fab8..2a2eaa0 100644 --- a/JuceLibraryCode/modules/juce_graphics/effects/juce_DropShadowEffect.cpp +++ b/JuceLibraryCode/modules/juce_graphics/effects/juce_DropShadowEffect.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -116,11 +116,11 @@ void DropShadow::drawForPath (Graphics& g, const Path& path) const } } -static void drawShadowSection (Graphics& g, ColourGradient& cg, const Rectangle& area, +static void drawShadowSection (Graphics& g, ColourGradient& cg, Rectangle area, bool isCorner, float centreX, float centreY, float edgeX, float edgeY) { - cg.point1 = area.getRelativePoint (centreX, centreY).toFloat(); - cg.point2 = area.getRelativePoint (edgeX, edgeY).toFloat(); + cg.point1 = area.getRelativePoint (centreX, centreY); + cg.point2 = area.getRelativePoint (edgeX, edgeY); cg.isRadial = isCorner; g.setGradientFill (cg); @@ -134,14 +134,14 @@ void DropShadow::drawForRectangle (Graphics& g, const Rectangle& targetArea for (float i = 0.05f; i < 1.0f; i += 0.1f) cg.addColour (1.0 - i, colour.withMultipliedAlpha (i * i)); - const int radiusInset = (radius + 1) / 2; - const int expandedRadius = radius + radiusInset; + const float radiusInset = (radius + 1) / 2.0f; + const float expandedRadius = radius + radiusInset; - const Rectangle area (targetArea.reduced (radiusInset) + offset); + const Rectangle area (targetArea.toFloat().reduced (radiusInset) + offset.toFloat()); - Rectangle r (area.expanded (expandedRadius)); - Rectangle top (r.removeFromTop (expandedRadius)); - Rectangle bottom (r.removeFromBottom (expandedRadius)); + Rectangle r (area.expanded (expandedRadius)); + Rectangle top (r.removeFromTop (expandedRadius)); + Rectangle bottom (r.removeFromBottom (expandedRadius)); drawShadowSection (g, cg, top.removeFromLeft (expandedRadius), true, 1.0f, 1.0f, 0, 1.0f); drawShadowSection (g, cg, top.removeFromRight (expandedRadius), true, 0, 1.0f, 1.0f, 1.0f); diff --git a/JuceLibraryCode/modules/juce_graphics/effects/juce_DropShadowEffect.h b/JuceLibraryCode/modules/juce_graphics/effects/juce_DropShadowEffect.h index 1f9362a..f8b0d8c 100644 --- a/JuceLibraryCode/modules/juce_graphics/effects/juce_DropShadowEffect.h +++ b/JuceLibraryCode/modules/juce_graphics/effects/juce_DropShadowEffect.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_graphics/effects/juce_GlowEffect.cpp b/JuceLibraryCode/modules/juce_graphics/effects/juce_GlowEffect.cpp index 7db7ef5..83a8d75 100644 --- a/JuceLibraryCode/modules/juce_graphics/effects/juce_GlowEffect.cpp +++ b/JuceLibraryCode/modules/juce_graphics/effects/juce_GlowEffect.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_graphics/effects/juce_GlowEffect.h b/JuceLibraryCode/modules/juce_graphics/effects/juce_GlowEffect.h index ab9ce3b..df2fa3e 100644 --- a/JuceLibraryCode/modules/juce_graphics/effects/juce_GlowEffect.h +++ b/JuceLibraryCode/modules/juce_graphics/effects/juce_GlowEffect.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_graphics/effects/juce_ImageEffectFilter.h b/JuceLibraryCode/modules/juce_graphics/effects/juce_ImageEffectFilter.h index 84d6b0b..84a5aaa 100644 --- a/JuceLibraryCode/modules/juce_graphics/effects/juce_ImageEffectFilter.h +++ b/JuceLibraryCode/modules/juce_graphics/effects/juce_ImageEffectFilter.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_graphics/fonts/juce_AttributedString.cpp b/JuceLibraryCode/modules/juce_graphics/fonts/juce_AttributedString.cpp index 43b6318..a5c5849 100644 --- a/JuceLibraryCode/modules/juce_graphics/fonts/juce_AttributedString.cpp +++ b/JuceLibraryCode/modules/juce_graphics/fonts/juce_AttributedString.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_graphics/fonts/juce_AttributedString.h b/JuceLibraryCode/modules/juce_graphics/fonts/juce_AttributedString.h index 8c33d75..6f46e1f 100644 --- a/JuceLibraryCode/modules/juce_graphics/fonts/juce_AttributedString.h +++ b/JuceLibraryCode/modules/juce_graphics/fonts/juce_AttributedString.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_graphics/fonts/juce_CustomTypeface.cpp b/JuceLibraryCode/modules/juce_graphics/fonts/juce_CustomTypeface.cpp index a2adb04..bb869b0 100644 --- a/JuceLibraryCode/modules/juce_graphics/fonts/juce_CustomTypeface.cpp +++ b/JuceLibraryCode/modules/juce_graphics/fonts/juce_CustomTypeface.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_graphics/fonts/juce_CustomTypeface.h b/JuceLibraryCode/modules/juce_graphics/fonts/juce_CustomTypeface.h index 25db68b..1d71834 100644 --- a/JuceLibraryCode/modules/juce_graphics/fonts/juce_CustomTypeface.h +++ b/JuceLibraryCode/modules/juce_graphics/fonts/juce_CustomTypeface.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_graphics/fonts/juce_Font.cpp b/JuceLibraryCode/modules/juce_graphics/fonts/juce_Font.cpp index bc3f850..671f98c 100644 --- a/JuceLibraryCode/modules/juce_graphics/fonts/juce_Font.cpp +++ b/JuceLibraryCode/modules/juce_graphics/fonts/juce_Font.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -30,6 +30,7 @@ namespace FontValues } const float defaultFontHeight = 14.0f; + float minimumHorizontalScale = 0.7f; String fallbackFont; String fallbackFontStyle; } @@ -37,6 +38,9 @@ namespace FontValues typedef Typeface::Ptr (*GetTypefaceForFont) (const Font&); GetTypefaceForFont juce_getTypefaceForFont = nullptr; +float Font::getDefaultMinimumHorizontalScaleFactor() noexcept { return FontValues::minimumHorizontalScale; } +void Font::setDefaultMinimumHorizontalScaleFactor (float newValue) noexcept { FontValues::minimumHorizontalScale = newValue; } + //============================================================================== class TypefaceCache : private DeletedAtShutdown { @@ -51,7 +55,7 @@ public: clearSingletonInstance(); } - juce_DeclareSingleton (TypefaceCache, false); + juce_DeclareSingleton (TypefaceCache, false) void setSize (const int numToCache) { @@ -278,13 +282,13 @@ Font& Font::operator= (const Font& other) noexcept #if JUCE_COMPILER_SUPPORTS_MOVE_SEMANTICS Font::Font (Font&& other) noexcept - : font (static_cast &&> (other.font)) + : font (static_cast&&> (other.font)) { } Font& Font::operator= (Font&& other) noexcept { - font = static_cast &&> (other.font); + font = static_cast&&> (other.font); return *this; } #endif @@ -640,7 +644,7 @@ float Font::getStringWidthFloat (const String& text) const return w * font->height * font->horizontalScale; } -void Font::getGlyphPositions (const String& text, Array & glyphs, Array & xOffsets) const +void Font::getGlyphPositions (const String& text, Array& glyphs, Array& xOffsets) const { getTypeface()->getGlyphPositions (text, glyphs, xOffsets); diff --git a/JuceLibraryCode/modules/juce_graphics/fonts/juce_Font.h b/JuceLibraryCode/modules/juce_graphics/fonts/juce_Font.h index 6649d36..3fc11bb 100644 --- a/JuceLibraryCode/modules/juce_graphics/fonts/juce_Font.h +++ b/JuceLibraryCode/modules/juce_graphics/fonts/juce_Font.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -279,8 +279,12 @@ public: //============================================================================== /** Makes the font bold or non-bold. */ void setBold (bool shouldBeBold); - /** Returns a copy of this font with the bold attribute set. */ + + /** Returns a copy of this font with the bold attribute set. + If the font does not have a bold version, this will return the default font. + */ Font boldened() const; + /** Returns true if the font is bold. */ bool isBold() const noexcept; @@ -319,6 +323,18 @@ public: */ void setHorizontalScale (float scaleFactor); + /** Returns the minimum horizontal scale to which fonts may be squashed when trying to + create a layout. + @see setDefaultMinimumHorizontalScaleFactor + */ + static float getDefaultMinimumHorizontalScaleFactor() noexcept; + + /** Sets the minimum horizontal scale to which fonts may be squashed when trying to + create a text layout. + @see getDefaultMinimumHorizontalScaleFactor + */ + static void setDefaultMinimumHorizontalScaleFactor (float newMinimumScaleFactor) noexcept; + /** Returns the font's kerning. This is the extra space added between adjacent characters, as a proportion @@ -449,7 +465,7 @@ public: private: //============================================================================== class SharedFontInternal; - ReferenceCountedObjectPtr font; + ReferenceCountedObjectPtr font; void dupeInternalIfShared(); void checkTypefaceSuitability(); float getHeightToPointsFactor() const; diff --git a/JuceLibraryCode/modules/juce_graphics/fonts/juce_GlyphArrangement.cpp b/JuceLibraryCode/modules/juce_graphics/fonts/juce_GlyphArrangement.cpp index d2d9ff7..66a3ca1 100644 --- a/JuceLibraryCode/modules/juce_graphics/fonts/juce_GlyphArrangement.cpp +++ b/JuceLibraryCode/modules/juce_graphics/fonts/juce_GlyphArrangement.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -40,6 +40,27 @@ PositionedGlyph::PositionedGlyph (const PositionedGlyph& other) { } +#if JUCE_COMPILER_SUPPORTS_MOVE_SEMANTICS +PositionedGlyph::PositionedGlyph (PositionedGlyph&& other) noexcept + : font (static_cast (other.font)), + character (other.character), glyph (other.glyph), + x (other.x), y (other.y), w (other.w), whitespace (other.whitespace) +{ +} + +PositionedGlyph& PositionedGlyph::operator= (PositionedGlyph&& other) noexcept +{ + font = static_cast (other.font); + character = other.character; + glyph = other.glyph; + x = other.x; + y = other.y; + w = other.w; + whitespace = other.whitespace; + return *this; +} +#endif + PositionedGlyph::~PositionedGlyph() {} PositionedGlyph& PositionedGlyph::operator= (const PositionedGlyph& other) @@ -54,20 +75,20 @@ PositionedGlyph& PositionedGlyph::operator= (const PositionedGlyph& other) return *this; } -static inline void drawGlyphWithFont (const Graphics& g, int glyph, const Font& font, const AffineTransform& t) +static inline void drawGlyphWithFont (Graphics& g, int glyph, const Font& font, const AffineTransform& t) { LowLevelGraphicsContext& context = g.getInternalContext(); context.setFont (font); context.drawGlyph (glyph, t); } -void PositionedGlyph::draw (const Graphics& g) const +void PositionedGlyph::draw (Graphics& g) const { if (! isWhitespace()) drawGlyphWithFont (g, glyph, font, AffineTransform::translation (x, y)); } -void PositionedGlyph::draw (const Graphics& g, const AffineTransform& transform) const +void PositionedGlyph::draw (Graphics& g, const AffineTransform& transform) const { if (! isWhitespace()) drawGlyphWithFont (g, glyph, font, AffineTransform::translation (x, y).followedBy (transform)); @@ -182,8 +203,8 @@ void GlyphArrangement::addCurtailedLineOfText (const Font& font, { if (text.isNotEmpty()) { - Array newGlyphs; - Array xOffsets; + Array newGlyphs; + Array xOffsets; font.getGlyphPositions (text, newGlyphs, xOffsets); const int textLen = newGlyphs.size(); glyphs.ensureStorageAllocated (glyphs.size() + textLen); @@ -202,16 +223,14 @@ void GlyphArrangement::addCurtailedLineOfText (const Font& font, break; } - else - { - const float thisX = xOffsets.getUnchecked (i); - const bool isWhitespace = t.isWhitespace(); - glyphs.add (PositionedGlyph (font, t.getAndAdvance(), - newGlyphs.getUnchecked(i), - xOffset + thisX, yOffset, - nextX - thisX, isWhitespace)); - } + const float thisX = xOffsets.getUnchecked (i); + const bool isWhitespace = t.isWhitespace(); + + glyphs.add (PositionedGlyph (font, t.getAndAdvance(), + newGlyphs.getUnchecked(i), + xOffset + thisX, yOffset, + nextX - thisX, isWhitespace)); } } } @@ -295,7 +314,8 @@ void GlyphArrangement::addJustifiedText (const Font& font, break; } - else if (pg.isWhitespace()) + + if (pg.isWhitespace()) { lastWordBreakIndex = i + 1; } @@ -346,181 +366,50 @@ void GlyphArrangement::addFittedText (const Font& f, const float width, const float height, Justification layout, int maximumLines, - const float minimumHorizontalScale) + float minimumHorizontalScale) { + if (minimumHorizontalScale == 0.0f) + minimumHorizontalScale = Font::getDefaultMinimumHorizontalScaleFactor(); + // doesn't make much sense if this is outside a sensible range of 0.5 to 1.0 jassert (minimumHorizontalScale > 0 && minimumHorizontalScale <= 1.0f); if (text.containsAnyOf ("\r\n")) { - GlyphArrangement ga; - ga.addJustifiedText (f, text, x, y, width, layout); - - const Rectangle bb (ga.getBoundingBox (0, -1, false)); - - float dy = y - bb.getY(); - - if (layout.testFlags (Justification::verticallyCentred)) dy += (height - bb.getHeight()) * 0.5f; - else if (layout.testFlags (Justification::bottom)) dy += (height - bb.getHeight()); - - ga.moveRangeOfGlyphs (0, -1, 0.0f, dy); - - glyphs.addArray (ga.glyphs); - return; + addLinesWithLineBreaks (text, f, x, y, width, height, layout); } - - int startIndex = glyphs.size(); - addLineOfText (f, text.trim(), x, y); - - if (glyphs.size() > startIndex) + else { - float lineWidth = glyphs.getReference (glyphs.size() - 1).getRight() - - glyphs.getReference (startIndex).getLeft(); + const int startIndex = glyphs.size(); + const String trimmed (text.trim()); + addLineOfText (f, trimmed, x, y); + const int numGlyphs = glyphs.size() - startIndex; - if (lineWidth <= 0) - return; - - if (lineWidth * minimumHorizontalScale < width) + if (numGlyphs > 0) { - if (lineWidth > width) - stretchRangeOfGlyphs (startIndex, glyphs.size() - startIndex, - width / lineWidth); + const float lineWidth = glyphs.getReference (glyphs.size() - 1).getRight() + - glyphs.getReference (startIndex).getLeft(); - justifyGlyphs (startIndex, glyphs.size() - startIndex, - x, y, width, height, layout); - } - else if (maximumLines <= 1) - { - fitLineIntoSpace (startIndex, glyphs.size() - startIndex, - x, y, width, height, f, layout, minimumHorizontalScale); - } - else - { - Font font (f); - String txt (text.trim()); - const int length = txt.length(); - const int originalStartIndex = startIndex; - int numLines = 1; - - if (length <= 12 && ! txt.containsAnyOf (" -\t\r\n")) - maximumLines = 1; - - maximumLines = jmin (maximumLines, length); - - while (numLines < maximumLines) + if (lineWidth > 0) { - ++numLines; - - const float newFontHeight = height / (float) numLines; - - if (newFontHeight < font.getHeight()) + if (lineWidth * minimumHorizontalScale < width) { - font.setHeight (jmax (8.0f, newFontHeight)); + if (lineWidth > width) + stretchRangeOfGlyphs (startIndex, numGlyphs, width / lineWidth); - removeRangeOfGlyphs (startIndex, -1); - addLineOfText (font, txt, x, y); - - lineWidth = glyphs.getReference (glyphs.size() - 1).getRight() - - glyphs.getReference (startIndex).getLeft(); + justifyGlyphs (startIndex, numGlyphs, x, y, width, height, layout); } - - if (numLines > lineWidth / width || newFontHeight < 8.0f) - break; - } - - if (numLines < 1) - numLines = 1; - - float lineY = y; - float widthPerLine = lineWidth / numLines; - - for (int line = 0; line < numLines; ++line) - { - int i = startIndex; - float lineStartX = glyphs.getReference (startIndex).getLeft(); - - if (line == numLines - 1) + else if (maximumLines <= 1) { - widthPerLine = width; - i = glyphs.size(); + fitLineIntoSpace (startIndex, numGlyphs, x, y, width, height, + f, layout, minimumHorizontalScale); } else { - while (i < glyphs.size()) - { - lineWidth = (glyphs.getReference (i).getRight() - lineStartX); - - if (lineWidth > widthPerLine) - { - // got to a point where the line's too long, so skip forward to find a - // good place to break it.. - const int searchStartIndex = i; - - while (i < glyphs.size()) - { - if ((glyphs.getReference (i).getRight() - lineStartX) * minimumHorizontalScale < width) - { - if (glyphs.getReference (i).isWhitespace() - || glyphs.getReference (i).getCharacter() == '-') - { - ++i; - break; - } - } - else - { - // can't find a suitable break, so try looking backwards.. - i = searchStartIndex; - - for (int back = 1; back < jmin (7, i - startIndex - 1); ++back) - { - if (glyphs.getReference (i - back).isWhitespace() - || glyphs.getReference (i - back).getCharacter() == '-') - { - i -= back - 1; - break; - } - } - - break; - } - - ++i; - } - - break; - } - - ++i; - } - - int wsStart = i; - while (wsStart > 0 && glyphs.getReference (wsStart - 1).isWhitespace()) - --wsStart; - - int wsEnd = i; - - while (wsEnd < glyphs.size() && glyphs.getReference (wsEnd).isWhitespace()) - ++wsEnd; - - removeRangeOfGlyphs (wsStart, wsEnd - wsStart); - i = jmax (wsStart, startIndex + 1); + splitLines (trimmed, f, startIndex, x, y, width, height, + maximumLines, lineWidth, layout, minimumHorizontalScale); } - - i -= fitLineIntoSpace (startIndex, i - startIndex, - x, lineY, width, font.getHeight(), font, - layout.getOnlyHorizontalFlags() | Justification::verticallyCentred, - minimumHorizontalScale); - - startIndex = i; - lineY += font.getHeight(); - - if (startIndex >= glyphs.size()) - break; } - - justifyGlyphs (originalStartIndex, glyphs.size() - originalStartIndex, - x, y, width, height, layout.getFlags() & ~Justification::horizontallyJustified); } } } @@ -540,6 +429,24 @@ void GlyphArrangement::moveRangeOfGlyphs (int startIndex, int num, const float d } } +void GlyphArrangement::addLinesWithLineBreaks (const String& text, const Font& f, + float x, float y, float width, float height, Justification layout) +{ + GlyphArrangement ga; + ga.addJustifiedText (f, text, x, y, width, layout); + + const Rectangle bb (ga.getBoundingBox (0, -1, false)); + + float dy = y - bb.getY(); + + if (layout.testFlags (Justification::verticallyCentred)) dy += (height - bb.getHeight()) * 0.5f; + else if (layout.testFlags (Justification::bottom)) dy += (height - bb.getHeight()); + + ga.moveRangeOfGlyphs (0, -1, 0.0f, dy); + + glyphs.addArray (ga.glyphs); +} + int GlyphArrangement::fitLineIntoSpace (int start, int numGlyphs, float x, float y, float w, float h, const Font& font, Justification justification, float minimumHorizontalScale) { @@ -702,9 +609,142 @@ void GlyphArrangement::spreadOutLine (const int start, const int num, const floa } } + +void GlyphArrangement::splitLines (const String& text, Font font, int startIndex, + float x, float y, float width, float height, int maximumLines, + float lineWidth, Justification layout, float minimumHorizontalScale) +{ + const int length = text.length(); + const int originalStartIndex = startIndex; + int numLines = 1; + + if (length <= 12 && ! text.containsAnyOf (" -\t\r\n")) + maximumLines = 1; + + maximumLines = jmin (maximumLines, length); + + while (numLines < maximumLines) + { + ++numLines; + + const float newFontHeight = height / (float) numLines; + + if (newFontHeight < font.getHeight()) + { + font.setHeight (jmax (8.0f, newFontHeight)); + + removeRangeOfGlyphs (startIndex, -1); + addLineOfText (font, text, x, y); + + lineWidth = glyphs.getReference (glyphs.size() - 1).getRight() + - glyphs.getReference (startIndex).getLeft(); + } + + // Try to estimate the point at which there are enough lines to fit the text, + // allowing for unevenness in the lengths due to differently sized words. + const float lineLengthUnevennessAllowance = 80.0f; + + if (numLines > (lineWidth + lineLengthUnevennessAllowance) / width || newFontHeight < 8.0f) + break; + } + + if (numLines < 1) + numLines = 1; + + float lineY = y; + float widthPerLine = lineWidth / numLines; + + for (int line = 0; line < numLines; ++line) + { + int i = startIndex; + float lineStartX = glyphs.getReference (startIndex).getLeft(); + + if (line == numLines - 1) + { + widthPerLine = width; + i = glyphs.size(); + } + else + { + while (i < glyphs.size()) + { + lineWidth = (glyphs.getReference (i).getRight() - lineStartX); + + if (lineWidth > widthPerLine) + { + // got to a point where the line's too long, so skip forward to find a + // good place to break it.. + const int searchStartIndex = i; + + while (i < glyphs.size()) + { + if ((glyphs.getReference (i).getRight() - lineStartX) * minimumHorizontalScale < width) + { + if (glyphs.getReference (i).isWhitespace() + || glyphs.getReference (i).getCharacter() == '-') + { + ++i; + break; + } + } + else + { + // can't find a suitable break, so try looking backwards.. + i = searchStartIndex; + + for (int back = 1; back < jmin (7, i - startIndex - 1); ++back) + { + if (glyphs.getReference (i - back).isWhitespace() + || glyphs.getReference (i - back).getCharacter() == '-') + { + i -= back - 1; + break; + } + } + + break; + } + + ++i; + } + + break; + } + + ++i; + } + + int wsStart = i; + while (wsStart > 0 && glyphs.getReference (wsStart - 1).isWhitespace()) + --wsStart; + + int wsEnd = i; + while (wsEnd < glyphs.size() && glyphs.getReference (wsEnd).isWhitespace()) + ++wsEnd; + + removeRangeOfGlyphs (wsStart, wsEnd - wsStart); + i = jmax (wsStart, startIndex + 1); + } + + i -= fitLineIntoSpace (startIndex, i - startIndex, + x, lineY, width, font.getHeight(), font, + layout.getOnlyHorizontalFlags() | Justification::verticallyCentred, + minimumHorizontalScale); + + startIndex = i; + lineY += font.getHeight(); + + if (startIndex >= glyphs.size()) + break; + } + + justifyGlyphs (originalStartIndex, glyphs.size() - originalStartIndex, + x, y, width, height, layout.getFlags() & ~Justification::horizontallyJustified); +} + //============================================================================== -inline void GlyphArrangement::drawGlyphUnderline (const Graphics& g, const PositionedGlyph& pg, - const int i, const AffineTransform& transform) const +void GlyphArrangement::drawGlyphUnderline (const Graphics& g, const PositionedGlyph& pg, + const int i, const AffineTransform& transform) const { const float lineThickness = (pg.font.getDescent()) * 0.3f; @@ -720,19 +760,15 @@ inline void GlyphArrangement::drawGlyphUnderline (const Graphics& g, const Posit void GlyphArrangement::draw (const Graphics& g) const { - for (int i = 0; i < glyphs.size(); ++i) - { - const PositionedGlyph& pg = glyphs.getReference(i); - - if (pg.font.isUnderlined()) - drawGlyphUnderline (g, pg, i, AffineTransform::identity); - - pg.draw (g); - } + draw (g, AffineTransform()); } void GlyphArrangement::draw (const Graphics& g, const AffineTransform& transform) const { + LowLevelGraphicsContext& context = g.getInternalContext(); + Font lastFont (context.getFont()); + bool needToRestore = false; + for (int i = 0; i < glyphs.size(); ++i) { const PositionedGlyph& pg = glyphs.getReference(i); @@ -740,8 +776,27 @@ void GlyphArrangement::draw (const Graphics& g, const AffineTransform& transform if (pg.font.isUnderlined()) drawGlyphUnderline (g, pg, i, transform); - pg.draw (g, transform); + if (! pg.isWhitespace()) + { + if (lastFont != pg.font) + { + lastFont = pg.font; + + if (! needToRestore) + { + needToRestore = true; + context.saveState(); + } + + context.setFont (lastFont); + } + + context.drawGlyph (pg.glyph, AffineTransform::translation (pg.x, pg.y).followedBy (transform)); + } } + + if (needToRestore) + context.restoreState(); } void GlyphArrangement::createPath (Path& path) const diff --git a/JuceLibraryCode/modules/juce_graphics/fonts/juce_GlyphArrangement.h b/JuceLibraryCode/modules/juce_graphics/fonts/juce_GlyphArrangement.h index f11894d..6f4243d 100644 --- a/JuceLibraryCode/modules/juce_graphics/fonts/juce_GlyphArrangement.h +++ b/JuceLibraryCode/modules/juce_graphics/fonts/juce_GlyphArrangement.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -46,6 +46,12 @@ public: PositionedGlyph (const PositionedGlyph&); PositionedGlyph& operator= (const PositionedGlyph&); + + #if JUCE_COMPILER_SUPPORTS_MOVE_SEMANTICS + PositionedGlyph (PositionedGlyph&&) noexcept; + PositionedGlyph& operator= (PositionedGlyph&&) noexcept; + #endif + ~PositionedGlyph(); /** Returns the character the glyph represents. */ @@ -71,14 +77,17 @@ public: void moveBy (float deltaX, float deltaY); //============================================================================== - /** Draws the glyph into a graphics context. */ - void draw (const Graphics& g) const; + /** Draws the glyph into a graphics context. + (Note that this may change the context's currently selected font). + */ + void draw (Graphics& g) const; - /** Draws the glyph into a graphics context, with an extra transform applied to it. */ - void draw (const Graphics& g, const AffineTransform& transform) const; + /** Draws the glyph into a graphics context, with an extra transform applied to it. + (Note that this may change the context's currently selected font). + */ + void draw (Graphics& g, const AffineTransform& transform) const; /** Returns the path for this glyph. - @param path the glyph's outline will be appended to this path */ void createPath (Path& path) const; @@ -199,6 +208,10 @@ public: A Justification parameter lets you specify how the text is laid out within the rectangle, both horizontally and vertically. + The minimumHorizontalScale parameter specifies how much the text can be squashed horizontally + to try to squeeze it into the space. If you don't want any horizontal scaling to occur, you + can set this value to 1.0f. Pass 0 if you want it to use the default value. + @see Graphics::drawFittedText */ void addFittedText (const Font& font, @@ -206,7 +219,7 @@ public: float x, float y, float width, float height, Justification layout, int maximumLinesToUse, - float minimumHorizontalScale = 0.7f); + float minimumHorizontalScale = 0.0f); /** Appends another glyph arrangement to this one. */ void addGlyphArrangement (const GlyphArrangement&); @@ -295,12 +308,15 @@ public: private: //============================================================================== - Array glyphs; + Array glyphs; int insertEllipsis (const Font&, float maxXPos, int startIndex, int endIndex); int fitLineIntoSpace (int start, int numGlyphs, float x, float y, float w, float h, const Font&, Justification, float minimumHorizontalScale); void spreadOutLine (int start, int numGlyphs, float targetWidth); + void splitLines (const String&, Font, int start, float x, float y, float w, float h, int maxLines, + float lineWidth, Justification, float minimumHorizontalScale); + void addLinesWithLineBreaks (const String&, const Font&, float x, float y, float width, float height, Justification); void drawGlyphUnderline (const Graphics&, const PositionedGlyph&, int, const AffineTransform&) const; JUCE_LEAK_DETECTOR (GlyphArrangement) diff --git a/JuceLibraryCode/modules/juce_graphics/fonts/juce_TextLayout.cpp b/JuceLibraryCode/modules/juce_graphics/fonts/juce_TextLayout.cpp index 526cac1..322b8e6 100644 --- a/JuceLibraryCode/modules/juce_graphics/fonts/juce_TextLayout.cpp +++ b/JuceLibraryCode/modules/juce_graphics/fonts/juce_TextLayout.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -22,8 +22,8 @@ ============================================================================== */ -TextLayout::Glyph::Glyph (const int glyphCode_, Point anchor_, float width_) noexcept - : glyphCode (glyphCode_), anchor (anchor_), width (width_) +TextLayout::Glyph::Glyph (const int glyph, Point anch, float w) noexcept + : glyphCode (glyph), anchor (anch), width (w) { } @@ -70,11 +70,10 @@ TextLayout::Line::Line() noexcept { } -TextLayout::Line::Line (Range stringRange_, Point lineOrigin_, - const float ascent_, const float descent_, const float leading_, - const int numRunsToPreallocate) - : stringRange (stringRange_), lineOrigin (lineOrigin_), - ascent (ascent_), descent (descent_), leading (leading_) +TextLayout::Line::Line (Range range, Point o, float asc, float desc, + float lead, int numRunsToPreallocate) + : stringRange (range), lineOrigin (o), + ascent (asc), descent (desc), leading (lead) { runs.ensureStorageAllocated (numRunsToPreallocate); } @@ -127,14 +126,28 @@ Range TextLayout::Line::getLineBoundsX() const noexcept return range + lineOrigin.x; } +Range TextLayout::Line::getLineBoundsY() const noexcept +{ + return Range (lineOrigin.y - ascent, + lineOrigin.y + descent); +} + +Rectangle TextLayout::Line::getLineBounds() const noexcept +{ + const Range x (getLineBoundsX()), + y (getLineBoundsY()); + + return Rectangle (x.getStart(), y.getStart(), x.getLength(), y.getLength()); +} + //============================================================================== TextLayout::TextLayout() - : width (0), justification (Justification::topLeft) + : width (0), height (0), justification (Justification::topLeft) { } TextLayout::TextLayout (const TextLayout& other) - : width (other.width), + : width (other.width), height (other.height), justification (other.justification) { lines.addCopiesOf (other.lines); @@ -142,16 +155,17 @@ TextLayout::TextLayout (const TextLayout& other) #if JUCE_COMPILER_SUPPORTS_MOVE_SEMANTICS TextLayout::TextLayout (TextLayout&& other) noexcept - : lines (static_cast &&> (other.lines)), - width (other.width), + : lines (static_cast&&> (other.lines)), + width (other.width), height (other.height), justification (other.justification) { } TextLayout& TextLayout::operator= (TextLayout&& other) noexcept { - lines = static_cast &&> (other.lines); + lines = static_cast&&> (other.lines); width = other.width; + height = other.height; justification = other.justification; return *this; } @@ -160,6 +174,7 @@ TextLayout& TextLayout::operator= (TextLayout&& other) noexcept TextLayout& TextLayout::operator= (const TextLayout& other) { width = other.width; + height = other.height; justification = other.justification; lines.clear(); lines.addCopiesOf (other.lines); @@ -170,17 +185,9 @@ TextLayout::~TextLayout() { } -float TextLayout::getHeight() const noexcept -{ - if (const Line* const lastLine = lines.getLast()) - return lastLine->lineOrigin.y + lastLine->descent; - - return 0.0f; -} - TextLayout::Line& TextLayout::getLine (const int index) const { - return *lines[index]; + return *lines.getUnchecked (index); } void TextLayout::ensureStorageAllocated (int numLinesNeeded) @@ -199,7 +206,7 @@ void TextLayout::draw (Graphics& g, const Rectangle& area) const LowLevelGraphicsContext& context = g.getInternalContext(); - for (int i = 0; i < getNumLines(); ++i) + for (int i = 0; i < lines.size(); ++i) { const Line& line = getLine (i); const Point lineOrigin (origin + line.lineOrigin); @@ -221,15 +228,60 @@ void TextLayout::draw (Graphics& g, const Rectangle& area) const } void TextLayout::createLayout (const AttributedString& text, float maxWidth) +{ + createLayout (text, maxWidth, 1.0e7f); +} + +void TextLayout::createLayout (const AttributedString& text, float maxWidth, float maxHeight) { lines.clear(); width = maxWidth; + height = maxHeight; justification = text.getJustification(); if (! createNativeLayout (text)) createStandardLayout (text); - recalculateWidth (text); + recalculateSize (text); +} + +void TextLayout::createLayoutWithBalancedLineLengths (const AttributedString& text, float maxWidth) +{ + createLayoutWithBalancedLineLengths (text, maxWidth, 1.0e7f); +} + +void TextLayout::createLayoutWithBalancedLineLengths (const AttributedString& text, float maxWidth, float maxHeight) +{ + const float minimumWidth = maxWidth / 2.0f; + float bestWidth = maxWidth; + float bestLineProportion = 0.0f; + + while (maxWidth > minimumWidth) + { + createLayout (text, maxWidth, maxHeight); + + if (getNumLines() < 2) + return; + + const float line1 = lines.getUnchecked (lines.size() - 1)->getLineBoundsX().getLength(); + const float line2 = lines.getUnchecked (lines.size() - 2)->getLineBoundsX().getLength(); + const float shortestLine = jmin (line1, line2); + const float prop = (shortestLine > 0) ? jmax (line1, line2) / shortestLine : 1.0f; + + if (prop > 0.9f) + return; + + if (prop > bestLineProportion) + { + bestLineProportion = prop; + bestWidth = maxWidth; + } + + maxWidth -= 10.0f; + } + + if (bestWidth != maxWidth) + createLayout (text, bestWidth, maxHeight); } //============================================================================== @@ -305,8 +357,8 @@ namespace TextLayoutHelpers { const Token& t = *tokens.getUnchecked (i); - Array newGlyphs; - Array xOffsets; + Array newGlyphs; + Array xOffsets; t.font.getGlyphPositions (getTrimmedEndIfNotAllWhitespace (t.text), newGlyphs, xOffsets); if (currentRun == nullptr) currentRun = new TextLayout::Run(); @@ -561,41 +613,6 @@ namespace TextLayoutHelpers }; } -//============================================================================== -void TextLayout::createLayoutWithBalancedLineLengths (const AttributedString& text, float maxWidth) -{ - const float minimumWidth = maxWidth / 2.0f; - float bestWidth = maxWidth; - float bestLineProportion = 0.0f; - - while (maxWidth > minimumWidth) - { - createLayout (text, maxWidth); - - if (getNumLines() < 2) - return; - - const float line1 = lines.getUnchecked (lines.size() - 1)->getLineBoundsX().getLength(); - const float line2 = lines.getUnchecked (lines.size() - 2)->getLineBoundsX().getLength(); - const float shortestLine = jmin (line1, line2); - const float prop = (shortestLine > 0) ? jmax (line1, line2) / shortestLine : 1.0f; - - if (prop > 0.9f) - return; - - if (prop > bestLineProportion) - { - bestLineProportion = prop; - bestWidth = maxWidth; - } - - maxWidth -= 10.0f; - } - - if (bestWidth != maxWidth) - createLayout (text, bestWidth); -} - //============================================================================== void TextLayout::createStandardLayout (const AttributedString& text) { @@ -603,18 +620,24 @@ void TextLayout::createStandardLayout (const AttributedString& text) l.createLayout (text, *this); } -void TextLayout::recalculateWidth (const AttributedString& text) +void TextLayout::recalculateSize (const AttributedString& text) { if (lines.size() > 0 && text.getReadingDirection() != AttributedString::rightToLeft) { - Range range (lines.getFirst()->getLineBoundsX()); + Rectangle bounds (lines.getFirst()->getLineBounds()); for (int i = lines.size(); --i > 0;) - range = range.getUnionWith (lines.getUnchecked(i)->getLineBoundsX()); + bounds = bounds.getUnion (lines.getUnchecked(i)->getLineBounds()); for (int i = lines.size(); --i >= 0;) - lines.getUnchecked(i)->lineOrigin.x -= range.getStart(); + lines.getUnchecked(i)->lineOrigin.x -= bounds.getX(); - width = range.getLength(); + width = bounds.getWidth(); + height = bounds.getHeight(); + } + else + { + width = 0; + height = 0; } } diff --git a/JuceLibraryCode/modules/juce_graphics/fonts/juce_TextLayout.h b/JuceLibraryCode/modules/juce_graphics/fonts/juce_TextLayout.h index b5f9eea..0aaa073 100644 --- a/JuceLibraryCode/modules/juce_graphics/fonts/juce_TextLayout.h +++ b/JuceLibraryCode/modules/juce_graphics/fonts/juce_TextLayout.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -46,7 +46,7 @@ public: TextLayout (const TextLayout&); TextLayout& operator= (const TextLayout&); #if JUCE_COMPILER_SUPPORTS_MOVE_SEMANTICS - TextLayout (TextLayout&& other) noexcept; + TextLayout (TextLayout&&) noexcept; TextLayout& operator= (TextLayout&&) noexcept; #endif @@ -57,7 +57,12 @@ public: /** Creates a layout from the given attributed string. This will replace any data that is currently stored in the layout. */ - void createLayout (const AttributedString& text, float maxWidth); + void createLayout (const AttributedString&, float maxWidth); + + /** Creates a layout from the given attributed string, given some size constraints. + This will replace any data that is currently stored in the layout. + */ + void createLayout (const AttributedString&, float maxWidth, float maxHeight); /** Creates a layout, attempting to choose a width which results in lines of a similar length. @@ -65,13 +70,21 @@ public: This will be slower than the normal createLayout method, but produces a tidier result. */ - void createLayoutWithBalancedLineLengths (const AttributedString& text, float maxWidth); + void createLayoutWithBalancedLineLengths (const AttributedString&, float maxWidth); + + /** Creates a layout, attempting to choose a width which results in lines + of a similar length. + + This will be slower than the normal createLayout method, but produces a + tidier result. + */ + void createLayoutWithBalancedLineLengths (const AttributedString&, float maxWidth, float maxHeight); /** Draws the layout within the specified area. The position of the text within the rectangle is controlled by the justification flags set in the original AttributedString that was used to create this layout. */ - void draw (Graphics& g, const Rectangle& area) const; + void draw (Graphics&, const Rectangle& area) const; //============================================================================== /** A positioned glyph. */ @@ -131,6 +144,12 @@ public: /** Returns the X position range which contains all the glyphs in this line. */ Range getLineBoundsX() const noexcept; + /** Returns the Y position range which contains all the glyphs in this line. */ + Range getLineBoundsY() const noexcept; + + /** Returns the smallest rectangle which contains all the glyphs in this line. */ + Rectangle getLineBounds() const noexcept; + OwnedArray runs; /**< The glyph-runs in this line. */ Range stringRange; /**< The character range that this line represents in the original string that was used to create it. */ @@ -147,7 +166,7 @@ public: float getWidth() const noexcept { return width; } /** Returns the maximum height of the content. */ - float getHeight() const noexcept; + float getHeight() const noexcept { return height; } /** Returns the number of lines in the layout. */ int getNumLines() const noexcept { return lines.size(); } @@ -157,19 +176,19 @@ public: /** Adds a line to the layout. The layout will take ownership of this line object and will delete it when it is no longer needed. */ - void addLine (Line* line); + void addLine (Line*); /** Pre-allocates space for the specified number of lines. */ void ensureStorageAllocated (int numLinesNeeded); private: OwnedArray lines; - float width; + float width, height; Justification justification; void createStandardLayout (const AttributedString&); bool createNativeLayout (const AttributedString&); - void recalculateWidth (const AttributedString&); + void recalculateSize (const AttributedString&); JUCE_LEAK_DETECTOR (TextLayout) }; diff --git a/JuceLibraryCode/modules/juce_graphics/fonts/juce_Typeface.cpp b/JuceLibraryCode/modules/juce_graphics/fonts/juce_Typeface.cpp index 4eda6b0..2077cd7 100644 --- a/JuceLibraryCode/modules/juce_graphics/fonts/juce_Typeface.cpp +++ b/JuceLibraryCode/modules/juce_graphics/fonts/juce_Typeface.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_graphics/fonts/juce_Typeface.h b/JuceLibraryCode/modules/juce_graphics/fonts/juce_Typeface.h index a392fb7..0646305 100644 --- a/JuceLibraryCode/modules/juce_graphics/fonts/juce_Typeface.h +++ b/JuceLibraryCode/modules/juce_graphics/fonts/juce_Typeface.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_graphics/geometry/juce_AffineTransform.cpp b/JuceLibraryCode/modules/juce_graphics/geometry/juce_AffineTransform.cpp index 59ebde3..3f17bb9 100644 --- a/JuceLibraryCode/modules/juce_graphics/geometry/juce_AffineTransform.cpp +++ b/JuceLibraryCode/modules/juce_graphics/geometry/juce_AffineTransform.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -193,9 +193,9 @@ AffineTransform AffineTransform::sheared (const float shearX, const float shearY return AffineTransform (mat00 + shearX * mat10, mat01 + shearX * mat11, mat02 + shearX * mat12, - shearY * mat00 + mat10, - shearY * mat01 + mat11, - shearY * mat02 + mat12); + mat10 + shearY * mat00, + mat11 + shearY * mat01, + mat12 + shearY * mat02); } AffineTransform AffineTransform::verticalFlip (const float height) noexcept @@ -211,10 +211,10 @@ AffineTransform AffineTransform::inverted() const noexcept { determinant = 1.0 / determinant; - const float dst00 = (float) (mat11 * determinant); + const float dst00 = (float) ( mat11 * determinant); const float dst10 = (float) (-mat10 * determinant); const float dst01 = (float) (-mat01 * determinant); - const float dst11 = (float) (mat00 * determinant); + const float dst11 = (float) ( mat00 * determinant); return AffineTransform (dst00, dst01, -mat02 * dst00 - mat12 * dst01, dst10, dst11, -mat02 * dst10 - mat12 * dst11); @@ -258,5 +258,5 @@ bool AffineTransform::isOnlyTranslation() const noexcept float AffineTransform::getScaleFactor() const noexcept { - return (mat00 + mat11) / 2.0f; + return (std::abs (mat00) + std::abs (mat11)) / 2.0f; } diff --git a/JuceLibraryCode/modules/juce_graphics/geometry/juce_AffineTransform.h b/JuceLibraryCode/modules/juce_graphics/geometry/juce_AffineTransform.h index dfc3a29..0d24ef0 100644 --- a/JuceLibraryCode/modules/juce_graphics/geometry/juce_AffineTransform.h +++ b/JuceLibraryCode/modules/juce_graphics/geometry/juce_AffineTransform.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -83,8 +83,8 @@ public: void transformPoint (ValueType& x, ValueType& y) const noexcept { const ValueType oldX = x; - x = static_cast (mat00 * oldX + mat01 * y + mat02); - y = static_cast (mat10 * oldX + mat11 * y + mat12); + x = static_cast (mat00 * oldX + mat01 * y + mat02); + y = static_cast (mat10 * oldX + mat11 * y + mat12); } /** Transforms two 2D coordinates using this matrix. @@ -97,10 +97,10 @@ public: ValueType& x2, ValueType& y2) const noexcept { const ValueType oldX1 = x1, oldX2 = x2; - x1 = static_cast (mat00 * oldX1 + mat01 * y1 + mat02); - y1 = static_cast (mat10 * oldX1 + mat11 * y1 + mat12); - x2 = static_cast (mat00 * oldX2 + mat01 * y2 + mat02); - y2 = static_cast (mat10 * oldX2 + mat11 * y2 + mat12); + x1 = static_cast (mat00 * oldX1 + mat01 * y1 + mat02); + y1 = static_cast (mat10 * oldX1 + mat11 * y1 + mat12); + x2 = static_cast (mat00 * oldX2 + mat01 * y2 + mat02); + y2 = static_cast (mat10 * oldX2 + mat11 * y2 + mat12); } /** Transforms three 2D coordinates using this matrix. @@ -114,12 +114,12 @@ public: ValueType& x3, ValueType& y3) const noexcept { const ValueType oldX1 = x1, oldX2 = x2, oldX3 = x3; - x1 = static_cast (mat00 * oldX1 + mat01 * y1 + mat02); - y1 = static_cast (mat10 * oldX1 + mat11 * y1 + mat12); - x2 = static_cast (mat00 * oldX2 + mat01 * y2 + mat02); - y2 = static_cast (mat10 * oldX2 + mat11 * y2 + mat12); - x3 = static_cast (mat00 * oldX3 + mat01 * y3 + mat02); - y3 = static_cast (mat10 * oldX3 + mat11 * y3 + mat12); + x1 = static_cast (mat00 * oldX1 + mat01 * y1 + mat02); + y1 = static_cast (mat10 * oldX1 + mat11 * y1 + mat12); + x2 = static_cast (mat00 * oldX2 + mat01 * y2 + mat02); + y2 = static_cast (mat10 * oldX2 + mat11 * y2 + mat12); + x3 = static_cast (mat00 * oldX3 + mat01 * y3 + mat02); + y3 = static_cast (mat10 * oldX3 + mat11 * y3 + mat12); } //============================================================================== @@ -231,8 +231,7 @@ public: float x10, float y10, float x01, float y01) noexcept; - /** Returns the transform that will map three specified points onto three target points. - */ + /** Returns the transform that will map three specified points onto three target points. */ static AffineTransform fromTargetPoints (float sourceX1, float sourceY1, float targetX1, float targetY1, float sourceX2, float sourceY2, float targetX2, float targetY2, float sourceX3, float sourceY3, float targetX3, float targetY3) noexcept; diff --git a/JuceLibraryCode/modules/juce_graphics/geometry/juce_BorderSize.h b/JuceLibraryCode/modules/juce_graphics/geometry/juce_BorderSize.h index b6a6686..1d2436f 100644 --- a/JuceLibraryCode/modules/juce_graphics/geometry/juce_BorderSize.h +++ b/JuceLibraryCode/modules/juce_graphics/geometry/juce_BorderSize.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_graphics/geometry/juce_EdgeTable.cpp b/JuceLibraryCode/modules/juce_graphics/geometry/juce_EdgeTable.cpp index 73ee1c3..edefa73 100644 --- a/JuceLibraryCode/modules/juce_graphics/geometry/juce_EdgeTable.cpp +++ b/JuceLibraryCode/modules/juce_graphics/geometry/juce_EdgeTable.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_graphics/geometry/juce_EdgeTable.h b/JuceLibraryCode/modules/juce_graphics/geometry/juce_EdgeTable.h index d8b6d66..9f3d5eb 100644 --- a/JuceLibraryCode/modules/juce_graphics/geometry/juce_EdgeTable.h +++ b/JuceLibraryCode/modules/juce_graphics/geometry/juce_EdgeTable.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_graphics/geometry/juce_Line.h b/JuceLibraryCode/modules/juce_graphics/geometry/juce_Line.h index 95665c5..02f9169 100644 --- a/JuceLibraryCode/modules/juce_graphics/geometry/juce_Line.h +++ b/JuceLibraryCode/modules/juce_graphics/geometry/juce_Line.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -224,8 +224,8 @@ public: if (length <= 0) return start; - return Point (start.x + static_cast ((delta.x * distanceFromStart - delta.y * perpendicularDistance) / length), - start.y + static_cast ((delta.y * distanceFromStart + delta.x * perpendicularDistance) / length)); + return Point (start.x + static_cast ((delta.x * distanceFromStart - delta.y * perpendicularDistance) / length), + start.y + static_cast ((delta.y * distanceFromStart + delta.x * perpendicularDistance) / length)); } /** Returns the location of the point which is a given distance along this line @@ -267,7 +267,7 @@ public: if (prop >= 0 && prop <= 1.0) { - pointOnLine = start + delta * static_cast (prop); + pointOnLine = start + delta * static_cast (prop); return targetPoint.getDistanceFrom (pointOnLine); } } @@ -301,9 +301,9 @@ public: const double length = delta.x * delta.x + delta.y * delta.y; return length <= 0 ? 0 - : jlimit (ValueType(), static_cast (1), - static_cast ((((point.x - start.x) * delta.x - + (point.y - start.y) * delta.y) / length))); + : jlimit (ValueType(), static_cast (1), + static_cast ((((point.x - start.x) * delta.x + + (point.y - start.y) * delta.y) / length))); } /** Finds the point on this line which is nearest to a given point. @@ -375,40 +375,40 @@ private: { const ValueType along = (p1.y - p3.y) / d2.y; intersection = p1.withX (p3.x + along * d2.x); - return along >= 0 && along <= static_cast (1); + return along >= 0 && along <= static_cast (1); } else if (d2.y == 0 && d1.y != 0) { const ValueType along = (p3.y - p1.y) / d1.y; intersection = p3.withX (p1.x + along * d1.x); - return along >= 0 && along <= static_cast (1); + return along >= 0 && along <= static_cast (1); } else if (d1.x == 0 && d2.x != 0) { const ValueType along = (p1.x - p3.x) / d2.x; intersection = p1.withY (p3.y + along * d2.y); - return along >= 0 && along <= static_cast (1); + return along >= 0 && along <= static_cast (1); } else if (d2.x == 0 && d1.x != 0) { const ValueType along = (p3.x - p1.x) / d1.x; intersection = p3.withY (p1.y + along * d1.y); - return along >= 0 && along <= static_cast (1); + return along >= 0 && along <= static_cast (1); } } - intersection = (p2 + p3) / static_cast (2); + intersection = (p2 + p3) / static_cast (2); return false; } const ValueType along1 = ((p1.y - p3.y) * d2.x - (p1.x - p3.x) * d2.y) / divisor; intersection = p1 + d1 * along1; - if (along1 < 0 || along1 > static_cast (1)) + if (along1 < 0 || along1 > static_cast (1)) return false; const ValueType along2 = ((p1.y - p3.y) * d1.x - (p1.x - p3.x) * d1.y) / divisor; - return along2 >= 0 && along2 <= static_cast (1); + return along2 >= 0 && along2 <= static_cast (1); } }; diff --git a/JuceLibraryCode/modules/juce_graphics/geometry/juce_Path.cpp b/JuceLibraryCode/modules/juce_graphics/geometry/juce_Path.cpp index 5a6b2f8..48c78aa 100644 --- a/JuceLibraryCode/modules/juce_graphics/geometry/juce_Path.cpp +++ b/JuceLibraryCode/modules/juce_graphics/geometry/juce_Path.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -501,13 +501,20 @@ void Path::addRoundedRectangle (float x, float y, float w, float h, float cs) addRoundedRectangle (x, y, w, h, cs, cs); } -void Path::addTriangle (const float x1, const float y1, - const float x2, const float y2, - const float x3, const float y3) +void Path::addTriangle (float x1, float y1, + float x2, float y2, + float x3, float y3) { - startNewSubPath (x1, y1); - lineTo (x2, y2); - lineTo (x3, y3); + addTriangle (Point (x1, y1), + Point (x2, y2), + Point (x3, y3)); +} + +void Path::addTriangle (Point p1, Point p2, Point p3) +{ + startNewSubPath (p1); + lineTo (p2); + lineTo (p3); closeSubPath(); } @@ -649,6 +656,20 @@ void Path::addPieSegment (const float x, const float y, closeSubPath(); } +void Path::addPieSegment (Rectangle segmentBounds, + const float fromRadians, + const float toRadians, + const float innerCircleProportionalSize) +{ + addPieSegment (segmentBounds.getX(), + segmentBounds.getY(), + segmentBounds.getWidth(), + segmentBounds.getHeight(), + fromRadians, + toRadians, + innerCircleProportionalSize); +} + //============================================================================== void Path::addLineSegment (const Line& line, float lineThickness) { @@ -1546,17 +1567,17 @@ void Path::restoreFromString (StringRef stringVersion) } //============================================================================== -Path::Iterator::Iterator (const Path& path_) - : path (path_), - index (0) +Path::Iterator::Iterator (const Path& p) noexcept + : x1 (0), y1 (0), x2 (0), y2 (0), x3 (0), y3 (0), + path (p), index (0) { } -Path::Iterator::~Iterator() +Path::Iterator::~Iterator() noexcept { } -bool Path::Iterator::next() +bool Path::Iterator::next() noexcept { const float* const elements = path.data.elements; diff --git a/JuceLibraryCode/modules/juce_graphics/geometry/juce_Path.h b/JuceLibraryCode/modules/juce_graphics/geometry/juce_Path.h index ac319f9..50d2e0f 100644 --- a/JuceLibraryCode/modules/juce_graphics/geometry/juce_Path.h +++ b/JuceLibraryCode/modules/juce_graphics/geometry/juce_Path.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -377,6 +377,18 @@ public: float x2, float y2, float x3, float y3); + /** Adds a triangle to the path. + + The triangle is added as a new closed sub-path. (Any currently open paths will be left open). + + Note that whether the vertices are specified in clockwise or anticlockwise + order will affect how the triangle is filled when it overlaps other + shapes (the winding order setting will affect this of course). + */ + void addTriangle (Point point1, + Point point2, + Point point3); + /** Adds a quadrilateral to the path. The quad is added as a new closed sub-path. (Any currently open paths will be left open). @@ -477,7 +489,6 @@ public: @param innerCircleProportionalSize if this is > 0, then the pie will be drawn as a curved band around a hollow ellipse at its centre, where this value indicates the inner ellipse's size with respect to the outer one. - @see addArc */ void addPieSegment (float x, float y, @@ -486,6 +497,29 @@ public: float toRadians, float innerCircleProportionalSize); + /** Adds a "pie-chart" shape to the path. + + The shape is added as a new sub-path. (Any currently open paths will be left open). + + Note that when specifying the start and end angles, the curve will be drawn either clockwise + or anti-clockwise according to whether the end angle is greater than the start. This means + that sometimes you may need to use values greater than 2*Pi for the end angle. + + @param segmentBounds the outer rectangle in which the elliptical outline fits + @param fromRadians the angle (clockwise) in radians at which to start the arc segment (where 0 is the + top-centre of the ellipse) + @param toRadians the angle (clockwise) in radians at which to end the arc segment (where 0 is the + top-centre of the ellipse) + @param innerCircleProportionalSize if this is > 0, then the pie will be drawn as a curved band around a hollow + ellipse at its centre, where this value indicates the inner ellipse's size with + respect to the outer one. + @see addArc + */ + void addPieSegment (Rectangle segmentBounds, + float fromRadians, + float toRadians, + float innerCircleProportionalSize); + /** Adds a line with a specified thickness. The line is added as a new closed sub-path. (Any currently open paths will be @@ -683,8 +717,8 @@ public: { public: //============================================================================== - Iterator (const Path& path); - ~Iterator(); + Iterator (const Path& path) noexcept; + ~Iterator() noexcept; //============================================================================== /** Moves onto the next element in the path. @@ -693,7 +727,7 @@ public: the elementType variable will be set to the type of the current element, and some of the x and y variables will be filled in with values. */ - bool next(); + bool next() noexcept; //============================================================================== enum PathElementType diff --git a/JuceLibraryCode/modules/juce_graphics/geometry/juce_PathIterator.cpp b/JuceLibraryCode/modules/juce_graphics/geometry/juce_PathIterator.cpp index 0a15581..ce3c463 100644 --- a/JuceLibraryCode/modules/juce_graphics/geometry/juce_PathIterator.cpp +++ b/JuceLibraryCode/modules/juce_graphics/geometry/juce_PathIterator.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_graphics/geometry/juce_PathIterator.h b/JuceLibraryCode/modules/juce_graphics/geometry/juce_PathIterator.h index dcb8b90..0c1e5a1 100644 --- a/JuceLibraryCode/modules/juce_graphics/geometry/juce_PathIterator.h +++ b/JuceLibraryCode/modules/juce_graphics/geometry/juce_PathIterator.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_graphics/geometry/juce_PathStrokeType.cpp b/JuceLibraryCode/modules/juce_graphics/geometry/juce_PathStrokeType.cpp index bdac333..a762aab 100644 --- a/JuceLibraryCode/modules/juce_graphics/geometry/juce_PathStrokeType.cpp +++ b/JuceLibraryCode/modules/juce_graphics/geometry/juce_PathStrokeType.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_graphics/geometry/juce_PathStrokeType.h b/JuceLibraryCode/modules/juce_graphics/geometry/juce_PathStrokeType.h index 6374741..b390838 100644 --- a/JuceLibraryCode/modules/juce_graphics/geometry/juce_PathStrokeType.h +++ b/JuceLibraryCode/modules/juce_graphics/geometry/juce_PathStrokeType.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_graphics/geometry/juce_Point.h b/JuceLibraryCode/modules/juce_graphics/geometry/juce_Point.h index ffe80fe..33dc1c7 100644 --- a/JuceLibraryCode/modules/juce_graphics/geometry/juce_Point.h +++ b/JuceLibraryCode/modules/juce_graphics/geometry/juce_Point.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -58,6 +58,9 @@ public: /** Returns true if the point is (0, 0). */ bool isOrigin() const noexcept { return x == ValueType() && y == ValueType(); } + /** Returns true if the coordinates are finite values. */ + inline bool isFinite() const noexcept { return juce_isfinite(x) && juce_isfinite(y); } + /** Returns the point's x coordinate. */ inline ValueType getX() const noexcept { return x; } @@ -213,6 +216,9 @@ public: /** Casts this point to a Point object. */ Point toDouble() const noexcept { return Point (static_cast (x), static_cast (y)); } + /** Casts this point to a Point object using roundToInt() to convert the values. */ + Point roundToInt() const noexcept { return Point (juce::roundToInt (x), juce::roundToInt (y)); } + /** Returns the point as a string in the form "x, y". */ String toString() const { return String (x) + ", " + String (y); } diff --git a/JuceLibraryCode/modules/juce_graphics/geometry/juce_Rectangle.h b/JuceLibraryCode/modules/juce_graphics/geometry/juce_Rectangle.h index 6191d1a..ac9df0e 100644 --- a/JuceLibraryCode/modules/juce_graphics/geometry/juce_Rectangle.h +++ b/JuceLibraryCode/modules/juce_graphics/geometry/juce_Rectangle.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -52,21 +52,21 @@ public: } /** Creates a rectangle with a given position and size. */ - Rectangle (const ValueType initialX, const ValueType initialY, - const ValueType width, const ValueType height) noexcept + Rectangle (ValueType initialX, ValueType initialY, + ValueType width, ValueType height) noexcept : pos (initialX, initialY), w (width), h (height) { } /** Creates a rectangle with a given size, and a position of (0, 0). */ - Rectangle (const ValueType width, const ValueType height) noexcept + Rectangle (ValueType width, ValueType height) noexcept : w (width), h (height) { } /** Creates a Rectangle from the positions of two opposite corners. */ - Rectangle (const Point corner1, const Point corner2) noexcept + Rectangle (Point corner1, Point corner2) noexcept : pos (jmin (corner1.x, corner2.x), jmin (corner1.y, corner2.y)), w (corner1.x - corner2.x), @@ -80,8 +80,8 @@ public: The right and bottom values must be larger than the left and top ones, or the resulting rectangle will have a negative size. */ - static Rectangle leftTopRightBottom (const ValueType left, const ValueType top, - const ValueType right, const ValueType bottom) noexcept + static Rectangle leftTopRightBottom (ValueType left, ValueType top, + ValueType right, ValueType bottom) noexcept { return Rectangle (left, top, right - left, bottom - top); } @@ -100,6 +100,9 @@ public: /** Returns true if the rectangle's width or height are zero or less */ bool isEmpty() const noexcept { return w <= ValueType() || h <= ValueType(); } + /** Returns true if the rectangle's values are all finite numbers, i.e. not NaN or infinity. */ + inline bool isFinite() const noexcept { return pos.isFinite() && juce_isfinite(w) && juce_isfinite(h); } + /** Returns the x coordinate of the rectangle's left-hand-side. */ inline ValueType getX() const noexcept { return pos.x; } @@ -131,17 +134,17 @@ public: /** Returns the aspect ratio of the rectangle's width / height. If widthOverHeight is true, it returns width / height; if widthOverHeight is false, it returns height / width. */ - ValueType getAspectRatio (const bool widthOverHeight = true) const noexcept { return widthOverHeight ? w / h : h / w; } + ValueType getAspectRatio (bool widthOverHeight = true) const noexcept { return widthOverHeight ? w / h : h / w; } //============================================================================== /** Returns the rectangle's top-left position as a Point. */ inline Point getPosition() const noexcept { return pos; } /** Changes the position of the rectangle's top-left corner (leaving its size unchanged). */ - inline void setPosition (const Point newPos) noexcept { pos = newPos; } + inline void setPosition (Point newPos) noexcept { pos = newPos; } /** Changes the position of the rectangle's top-left corner (leaving its size unchanged). */ - inline void setPosition (const ValueType newX, const ValueType newY) noexcept { pos.setXY (newX, newY); } + inline void setPosition (ValueType newX, ValueType newY) noexcept { pos.setXY (newX, newY); } /** Returns the rectangle's top-left position as a Point. */ Point getTopLeft() const noexcept { return pos; } @@ -155,62 +158,75 @@ public: /** Returns the rectangle's bottom-right position as a Point. */ Point getBottomRight() const noexcept { return Point (pos.x + w, pos.y + h); } + /** Returns the rectangle's left and right positions as a Range. */ + Range getHorizontalRange() const noexcept { return Range::withStartAndLength (pos.x, w); } + + /** Returns the rectangle's top and bottom positions as a Range. */ + Range getVerticalRange() const noexcept { return Range::withStartAndLength (pos.y, h); } + /** Changes the rectangle's size, leaving the position of its top-left corner unchanged. */ - void setSize (const ValueType newWidth, const ValueType newHeight) noexcept { w = newWidth; h = newHeight; } + void setSize (ValueType newWidth, ValueType newHeight) noexcept { w = newWidth; h = newHeight; } /** Changes all the rectangle's coordinates. */ - void setBounds (const ValueType newX, const ValueType newY, - const ValueType newWidth, const ValueType newHeight) noexcept { pos.x = newX; pos.y = newY; w = newWidth; h = newHeight; } + void setBounds (ValueType newX, ValueType newY, + ValueType newWidth, ValueType newHeight) noexcept { pos.x = newX; pos.y = newY; w = newWidth; h = newHeight; } /** Changes the rectangle's X coordinate */ - inline void setX (const ValueType newX) noexcept { pos.x = newX; } + inline void setX (ValueType newX) noexcept { pos.x = newX; } /** Changes the rectangle's Y coordinate */ - inline void setY (const ValueType newY) noexcept { pos.y = newY; } + inline void setY (ValueType newY) noexcept { pos.y = newY; } /** Changes the rectangle's width */ - inline void setWidth (const ValueType newWidth) noexcept { w = newWidth; } + inline void setWidth (ValueType newWidth) noexcept { w = newWidth; } /** Changes the rectangle's height */ - inline void setHeight (const ValueType newHeight) noexcept { h = newHeight; } + inline void setHeight (ValueType newHeight) noexcept { h = newHeight; } /** Changes the position of the rectangle's centre (leaving its size unchanged). */ - inline void setCentre (const ValueType newCentreX, const ValueType newCentreY) noexcept { pos.x = newCentreX - w / (ValueType) 2; pos.y = newCentreY - h / (ValueType) 2; } + inline void setCentre (ValueType newCentreX, ValueType newCentreY) noexcept { pos.x = newCentreX - w / (ValueType) 2; + pos.y = newCentreY - h / (ValueType) 2; } /** Changes the position of the rectangle's centre (leaving its size unchanged). */ - inline void setCentre (const Point newCentre) noexcept { setCentre (newCentre.x, newCentre.y); } + inline void setCentre (Point newCentre) noexcept { setCentre (newCentre.x, newCentre.y); } + + /** Changes the position of the rectangle's left and right edges. */ + void setHorizontalRange (Range range) noexcept { pos.x = range.getStart(); w = range.getLength(); } + + /** Changes the position of the rectangle's top and bottom edges. */ + void setVerticalRange (Range range) noexcept { pos.y = range.getStart(); h = range.getLength(); } /** Returns a rectangle which has the same size and y-position as this one, but with a different x-position. */ - Rectangle withX (const ValueType newX) const noexcept { return Rectangle (newX, pos.y, w, h); } + Rectangle withX (ValueType newX) const noexcept { return Rectangle (newX, pos.y, w, h); } /** Returns a rectangle which has the same size and x-position as this one, but with a different y-position. */ - Rectangle withY (const ValueType newY) const noexcept { return Rectangle (pos.x, newY, w, h); } + Rectangle withY (ValueType newY) const noexcept { return Rectangle (pos.x, newY, w, h); } /** Returns a rectangle with the same size as this one, but a new position. */ - Rectangle withPosition (const ValueType newX, const ValueType newY) const noexcept { return Rectangle (newX, newY, w, h); } + Rectangle withPosition (ValueType newX, ValueType newY) const noexcept { return Rectangle (newX, newY, w, h); } /** Returns a rectangle with the same size as this one, but a new position. */ - Rectangle withPosition (const Point newPos) const noexcept { return Rectangle (newPos.x, newPos.y, w, h); } + Rectangle withPosition (Point newPos) const noexcept { return Rectangle (newPos.x, newPos.y, w, h); } /** Returns a rectangle whose size is the same as this one, but whose top-left position is (0, 0). */ - Rectangle withZeroOrigin() const noexcept { return Rectangle (w, h); } + Rectangle withZeroOrigin() const noexcept { return Rectangle (w, h); } /** Returns a rectangle with the same size as this one, but a new centre position. */ - Rectangle withCentre (const Point newCentre) const noexcept { return Rectangle (newCentre.x - w / (ValueType) 2, - newCentre.y - h / (ValueType) 2, w, h); } + Rectangle withCentre (Point newCentre) const noexcept { return Rectangle (newCentre.x - w / (ValueType) 2, + newCentre.y - h / (ValueType) 2, w, h); } /** Returns a rectangle which has the same position and height as this one, but with a different width. */ - Rectangle withWidth (ValueType newWidth) const noexcept { return Rectangle (pos.x, pos.y, newWidth, h); } + Rectangle withWidth (ValueType newWidth) const noexcept { return Rectangle (pos.x, pos.y, newWidth, h); } /** Returns a rectangle which has the same position and width as this one, but with a different height. */ - Rectangle withHeight (ValueType newHeight) const noexcept { return Rectangle (pos.x, pos.y, w, newHeight); } + Rectangle withHeight (ValueType newHeight) const noexcept { return Rectangle (pos.x, pos.y, w, newHeight); } /** Returns a rectangle with the same top-left position as this one, but a new size. */ - Rectangle withSize (ValueType newWidth, ValueType newHeight) const noexcept { return Rectangle (pos.x, pos.y, newWidth, newHeight); } + Rectangle withSize (ValueType newWidth, ValueType newHeight) const noexcept { return Rectangle (pos.x, pos.y, newWidth, newHeight); } /** Returns a rectangle with the same centre position as this one, but a new size. */ - Rectangle withSizeKeepingCentre (ValueType newWidth, ValueType newHeight) const noexcept { return Rectangle (pos.x + (w - newWidth) / (ValueType) 2, - pos.y + (h - newHeight) / (ValueType) 2, newWidth, newHeight); } + Rectangle withSizeKeepingCentre (ValueType newWidth, ValueType newHeight) const noexcept { return Rectangle (pos.x + (w - newWidth) / (ValueType) 2, + pos.y + (h - newHeight) / (ValueType) 2, newWidth, newHeight); } /** Moves the x position, adjusting the width so that the right-hand edge remains in the same place. If the x is moved to be on the right of the current right-hand edge, the width will be set to zero. @@ -274,41 +290,41 @@ public: //============================================================================== /** Moves the rectangle's position by adding amount to its x and y coordinates. */ - void translate (const ValueType deltaX, - const ValueType deltaY) noexcept + void translate (ValueType deltaX, + ValueType deltaY) noexcept { pos.x += deltaX; pos.y += deltaY; } /** Returns a rectangle which is the same as this one moved by a given amount. */ - Rectangle translated (const ValueType deltaX, - const ValueType deltaY) const noexcept + Rectangle translated (ValueType deltaX, + ValueType deltaY) const noexcept { return Rectangle (pos.x + deltaX, pos.y + deltaY, w, h); } /** Returns a rectangle which is the same as this one moved by a given amount. */ - Rectangle operator+ (const Point deltaPosition) const noexcept + Rectangle operator+ (Point deltaPosition) const noexcept { return Rectangle (pos.x + deltaPosition.x, pos.y + deltaPosition.y, w, h); } /** Moves this rectangle by a given amount. */ - Rectangle& operator+= (const Point deltaPosition) noexcept + Rectangle& operator+= (Point deltaPosition) noexcept { pos += deltaPosition; return *this; } /** Returns a rectangle which is the same as this one moved by a given amount. */ - Rectangle operator- (const Point deltaPosition) const noexcept + Rectangle operator- (Point deltaPosition) const noexcept { return Rectangle (pos.x - deltaPosition.x, pos.y - deltaPosition.y, w, h); } /** Moves this rectangle by a given amount. */ - Rectangle& operator-= (const Point deltaPosition) noexcept + Rectangle& operator-= (Point deltaPosition) noexcept { pos -= deltaPosition; return *this; @@ -393,8 +409,8 @@ public: Effectively, its new size is (x - deltaX, y - deltaY, w + deltaX * 2, h + deltaY * 2). @see expanded, reduce, reduced */ - void expand (const ValueType deltaX, - const ValueType deltaY) noexcept + void expand (ValueType deltaX, + ValueType deltaY) noexcept { const ValueType nw = jmax (ValueType(), w + deltaX * 2); const ValueType nh = jmax (ValueType(), h + deltaY * 2); @@ -406,8 +422,8 @@ public: Effectively, the rectangle returned is (x - deltaX, y - deltaY, w + deltaX * 2, h + deltaY * 2). @see expand, reduce, reduced */ - Rectangle expanded (const ValueType deltaX, - const ValueType deltaY) const noexcept + Rectangle expanded (ValueType deltaX, + ValueType deltaY) const noexcept { const ValueType nw = jmax (ValueType(), w + deltaX * 2); const ValueType nh = jmax (ValueType(), h + deltaY * 2); @@ -419,7 +435,7 @@ public: Effectively, the rectangle returned is (x - delta, y - delta, w + delta * 2, h + delta * 2). @see expand, reduce, reduced */ - Rectangle expanded (const ValueType delta) const noexcept + Rectangle expanded (ValueType delta) const noexcept { return expanded (delta, delta); } @@ -429,8 +445,8 @@ public: Effectively, its new size is (x + deltaX, y + deltaY, w - deltaX * 2, h - deltaY * 2). @see reduced, expand, expanded */ - void reduce (const ValueType deltaX, - const ValueType deltaY) noexcept + void reduce (ValueType deltaX, + ValueType deltaY) noexcept { expand (-deltaX, -deltaY); } @@ -440,8 +456,8 @@ public: Effectively, the rectangle returned is (x + deltaX, y + deltaY, w - deltaX * 2, h - deltaY * 2). @see reduce, expand, expanded */ - Rectangle reduced (const ValueType deltaX, - const ValueType deltaY) const noexcept + Rectangle reduced (ValueType deltaX, + ValueType deltaY) const noexcept { return expanded (-deltaX, -deltaY); } @@ -451,7 +467,7 @@ public: Effectively, the rectangle returned is (x + delta, y + delta, w - delta * 2, h - delta * 2). @see reduce, expand, expanded */ - Rectangle reduced (const ValueType delta) const noexcept + Rectangle reduced (ValueType delta) const noexcept { return reduced (delta, delta); } @@ -465,7 +481,7 @@ public: If amountToRemove is greater than the height of this rectangle, it'll be clipped to that value. */ - Rectangle removeFromTop (const ValueType amountToRemove) noexcept + Rectangle removeFromTop (ValueType amountToRemove) noexcept { const Rectangle r (pos.x, pos.y, w, jmin (amountToRemove, h)); pos.y += r.h; h -= r.h; @@ -481,7 +497,7 @@ public: If amountToRemove is greater than the width of this rectangle, it'll be clipped to that value. */ - Rectangle removeFromLeft (const ValueType amountToRemove) noexcept + Rectangle removeFromLeft (ValueType amountToRemove) noexcept { const Rectangle r (pos.x, pos.y, jmin (amountToRemove, w), h); pos.x += r.w; w -= r.w; @@ -530,13 +546,13 @@ public: bool operator!= (const Rectangle& other) const noexcept { return pos != other.pos || w != other.w || h != other.h; } /** Returns true if this coordinate is inside the rectangle. */ - bool contains (const ValueType xCoord, const ValueType yCoord) const noexcept + bool contains (ValueType xCoord, ValueType yCoord) const noexcept { return xCoord >= pos.x && yCoord >= pos.y && xCoord < pos.x + w && yCoord < pos.y + h; } /** Returns true if this coordinate is inside the rectangle. */ - bool contains (const Point point) const noexcept + bool contains (Point point) const noexcept { return point.x >= pos.x && point.y >= pos.y && point.x < pos.x + w && point.y < pos.y + h; } @@ -549,7 +565,7 @@ public: } /** Returns the nearest point to the specified point that lies within this rectangle. */ - Point getConstrainedPoint (const Point point) const noexcept + Point getConstrainedPoint (Point point) const noexcept { return Point (jlimit (pos.x, pos.x + w, point.x), jlimit (pos.y, pos.y + h, point.y)); diff --git a/JuceLibraryCode/modules/juce_graphics/geometry/juce_RectangleList.h b/JuceLibraryCode/modules/juce_graphics/geometry/juce_RectangleList.h index 3637f6a..8863a0e 100644 --- a/JuceLibraryCode/modules/juce_graphics/geometry/juce_RectangleList.h +++ b/JuceLibraryCode/modules/juce_graphics/geometry/juce_RectangleList.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -101,9 +101,14 @@ public: The rectangle being added will first be clipped to remove any parts of it that overlap existing rectangles in the list, and adjacent rectangles will be merged into it. + + The rectangle can have any size and may be empty, but if it's floating point + then it's expected to not contain any INF values. */ void add (const RectangleType& rect) { + jassert (rect.isFinite()); // You must provide a valid rectangle to this method! + if (! rect.isEmpty()) { if (rects.size() == 0) @@ -168,9 +173,14 @@ public: This simply adds the rectangle to the end, it doesn't merge it or remove any overlapping bits. + + The rectangle can have any size and may be empty, but if it's floating point + then it's expected to not contain any INF values. */ void addWithoutMerging (const RectangleType& rect) { + jassert (rect.isFinite()); // You must provide a valid rectangle to this method! + if (! rect.isEmpty()) rects.add (rect); } @@ -300,6 +310,8 @@ public: */ bool clipTo (const RectangleType& rect) { + jassert (rect.isFinite()); // You must provide a valid rectangle to this method! + bool notEmpty = false; if (rect.isEmpty()) @@ -367,6 +379,8 @@ public: */ bool getIntersectionWith (const RectangleType& rect, RectangleList& destRegion) const { + jassert (rect.isFinite()); // You must provide a valid rectangle to this method! + destRegion.clear(); if (! rect.isEmpty()) @@ -628,6 +642,17 @@ public: /** Standard method for iterating the rectangles in the list. */ const RectangleType* end() const noexcept { return rects.end(); } + /** Increases the internal storage to hold a minimum number of rectangles. + Calling this before adding a large number of rectangles means that + the array won't have to keep dynamically resizing itself as the elements + are added, and it'll therefore be more efficient. + @see Array::ensureStorageAllocated + */ + void ensureStorageAllocated (int minNumRectangles) + { + rects.ensureStorageAllocated (minNumRectangles); + } + private: //============================================================================== Array rects; diff --git a/JuceLibraryCode/modules/juce_graphics/image_formats/jpglib/jinclude.h b/JuceLibraryCode/modules/juce_graphics/image_formats/jpglib/jinclude.h index ab66008..bccfd54 100644 --- a/JuceLibraryCode/modules/juce_graphics/image_formats/jpglib/jinclude.h +++ b/JuceLibraryCode/modules/juce_graphics/image_formats/jpglib/jinclude.h @@ -180,11 +180,16 @@ static const int extend_test[16] = /* entry n is 2**(n-1) */ { 0, 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080, 0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000 }; +#define SHIFTED_BITS_PLUS_ONE(n) (int) (((unsigned int) -1) << n) + 1 + static const int extend_offset[16] = /* entry n is (-1 << n) + 1 */ - { 0, ((-1)<<1) + 1, ((-1)<<2) + 1, ((-1)<<3) + 1, ((-1)<<4) + 1, - ((-1)<<5) + 1, ((-1)<<6) + 1, ((-1)<<7) + 1, ((-1)<<8) + 1, - ((-1)<<9) + 1, ((-1)<<10) + 1, ((-1)<<11) + 1, ((-1)<<12) + 1, - ((-1)<<13) + 1, ((-1)<<14) + 1, ((-1)<<15) + 1 }; + { 0, + SHIFTED_BITS_PLUS_ONE (1), SHIFTED_BITS_PLUS_ONE (2), SHIFTED_BITS_PLUS_ONE (3), SHIFTED_BITS_PLUS_ONE (4), + SHIFTED_BITS_PLUS_ONE (5), SHIFTED_BITS_PLUS_ONE (6), SHIFTED_BITS_PLUS_ONE (7), SHIFTED_BITS_PLUS_ONE (8), + SHIFTED_BITS_PLUS_ONE (9), SHIFTED_BITS_PLUS_ONE (10), SHIFTED_BITS_PLUS_ONE (11), SHIFTED_BITS_PLUS_ONE (12), + SHIFTED_BITS_PLUS_ONE (13), SHIFTED_BITS_PLUS_ONE (14), SHIFTED_BITS_PLUS_ONE (15) }; + +#undef SHIFTED_BITS_PLUS_ONE #endif /* AVOID_TABLES */ diff --git a/JuceLibraryCode/modules/juce_graphics/image_formats/juce_GIFLoader.cpp b/JuceLibraryCode/modules/juce_graphics/image_formats/juce_GIFLoader.cpp index 2c9066f..ff5cd8f 100644 --- a/JuceLibraryCode/modules/juce_graphics/image_formats/juce_GIFLoader.cpp +++ b/JuceLibraryCode/modules/juce_graphics/image_formats/juce_GIFLoader.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_graphics/image_formats/juce_JPEGLoader.cpp b/JuceLibraryCode/modules/juce_graphics/image_formats/juce_JPEGLoader.cpp index 0f56e32..1f98a97 100644 --- a/JuceLibraryCode/modules/juce_graphics/image_formats/juce_JPEGLoader.cpp +++ b/JuceLibraryCode/modules/juce_graphics/image_formats/juce_JPEGLoader.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_graphics/image_formats/juce_PNGLoader.cpp b/JuceLibraryCode/modules/juce_graphics/image_formats/juce_PNGLoader.cpp index 4ee36ab..fa3b887 100644 --- a/JuceLibraryCode/modules/juce_graphics/image_formats/juce_PNGLoader.cpp +++ b/JuceLibraryCode/modules/juce_graphics/image_formats/juce_PNGLoader.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -488,12 +488,13 @@ bool PNGImageFormat::writeImageToStream (const Image& image, OutputStream& out) PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); - HeapBlock rowData ((size_t) width * 4); + HeapBlock rowData ((size_t) width * 4); png_color_8 sig_bit; - sig_bit.red = 8; + sig_bit.red = 8; sig_bit.green = 8; - sig_bit.blue = 8; + sig_bit.blue = 8; + sig_bit.gray = 0; sig_bit.alpha = 8; png_set_sBIT (pngWriteStruct, pngInfoStruct, &sig_bit); diff --git a/JuceLibraryCode/modules/juce_graphics/image_formats/pnglib/pngread.c b/JuceLibraryCode/modules/juce_graphics/image_formats/pnglib/pngread.c index 85a7d61..f7bde96 100644 --- a/JuceLibraryCode/modules/juce_graphics/image_formats/pnglib/pngread.c +++ b/JuceLibraryCode/modules/juce_graphics/image_formats/pnglib/pngread.c @@ -1026,7 +1026,7 @@ png_read_png(png_structrp png_ptr, png_inforp info_ptr, if ((transforms & PNG_TRANSFORM_SHIFT) && png_get_valid(png_ptr, info_ptr, PNG_INFO_sBIT)) { - png_color_8p sig_bit; + png_color_8p sig_bit = 0; png_get_sBIT(png_ptr, info_ptr, &sig_bit); png_set_shift(png_ptr, sig_bit); diff --git a/JuceLibraryCode/modules/juce_graphics/images/juce_Image.cpp b/JuceLibraryCode/modules/juce_graphics/images/juce_Image.cpp index d9aa0c4..4299852 100644 --- a/JuceLibraryCode/modules/juce_graphics/images/juce_Image.cpp +++ b/JuceLibraryCode/modules/juce_graphics/images/juce_Image.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -39,6 +39,11 @@ void ImagePixelData::sendDataChangeMessage() listeners.call (&Listener::imageDataChanged, this); } +int ImagePixelData::getSharedCount() const noexcept +{ + return getReferenceCount(); +} + //============================================================================== ImageType::ImageType() {} ImageType::~ImageType() {} @@ -177,9 +182,13 @@ public: return newImage.getPixelData(); } - ImageType* createType() const override { return image->createType(); } + ImageType* createType() const override { return image->createType(); } + + /* as we always hold a reference to image, don't double count */ + int getSharedCount() const noexcept override { return getReferenceCount() + image->getSharedCount() - 1; } private: + friend class Image; const ImagePixelData::Ptr image; const Rectangle area; @@ -197,11 +206,11 @@ Image Image::getClippedImage (const Rectangle& area) const //============================================================================== -Image::Image() +Image::Image() noexcept { } -Image::Image (ImagePixelData* const instance) +Image::Image (ImagePixelData* const instance) noexcept : image (instance) { } @@ -216,7 +225,7 @@ Image::Image (const PixelFormat format, int width, int height, bool clearImage, { } -Image::Image (const Image& other) +Image::Image (const Image& other) noexcept : image (other.image) { } @@ -246,7 +255,7 @@ Image::~Image() const Image Image::null; -int Image::getReferenceCount() const noexcept { return image == nullptr ? 0 : image->getReferenceCount(); } +int Image::getReferenceCount() const noexcept { return image == nullptr ? 0 : image->getSharedCount(); } int Image::getWidth() const noexcept { return image == nullptr ? 0 : image->width; } int Image::getHeight() const noexcept { return image == nullptr ? 0 : image->height; } Rectangle Image::getBounds() const noexcept { return image == nullptr ? Rectangle() : Rectangle (image->width, image->height); } @@ -263,7 +272,7 @@ LowLevelGraphicsContext* Image::createLowLevelContext() const void Image::duplicateIfShared() { - if (image != nullptr && image->getReferenceCount() > 1) + if (getReferenceCount() > 1) image = image->clone(); } @@ -398,9 +407,9 @@ Colour Image::BitmapData::getPixelColour (const int x, const int y) const noexce switch (pixelFormat) { - case Image::ARGB: return Colour (((const PixelARGB*) pixel)->getUnpremultipliedARGB()); - case Image::RGB: return Colour (((const PixelRGB*) pixel)->getUnpremultipliedARGB()); - case Image::SingleChannel: return Colour (((const PixelAlpha*) pixel)->getUnpremultipliedARGB()); + case Image::ARGB: return Colour ( ((const PixelARGB*) pixel)->getUnpremultiplied()); + case Image::RGB: return Colour (*((const PixelRGB*) pixel)); + case Image::SingleChannel: return Colour (*((const PixelAlpha*) pixel)); default: jassertfalse; break; } diff --git a/JuceLibraryCode/modules/juce_graphics/images/juce_Image.h b/JuceLibraryCode/modules/juce_graphics/images/juce_Image.h index 3580f9f..189094c 100644 --- a/JuceLibraryCode/modules/juce_graphics/images/juce_Image.h +++ b/JuceLibraryCode/modules/juce_graphics/images/juce_Image.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -67,7 +67,7 @@ public: //============================================================================== /** Creates a null image. */ - Image(); + Image() noexcept; /** Creates an image with a specified size and format. @@ -106,7 +106,7 @@ public: point to the same shared image data. To make sure that an Image object has its own unique, unshared internal data, call duplicateIfShared(). */ - Image (const Image&); + Image (const Image&) noexcept; /** Makes this image refer to the same underlying image as another object. @@ -408,7 +408,7 @@ public: ImagePixelData* getPixelData() const noexcept { return image; } /** @internal */ - explicit Image (ImagePixelData*); + explicit Image (ImagePixelData*) noexcept; private: //============================================================================== @@ -443,6 +443,11 @@ public: virtual ImageType* createType() const = 0; /** Initialises a BitmapData object. */ virtual void initialiseBitmapData (Image::BitmapData&, int x, int y, Image::BitmapData::ReadWriteMode) = 0; + /** Returns the number of Image objects which are currently referring to the same internal + shared image data. This is different to the reference count as an instance of ImagePixelData + can internally depend on another ImagePixelData via it's member variables. */ + virtual int getSharedCount() const noexcept; + /** The pixel format of the image data. */ const Image::PixelFormat pixelFormat; diff --git a/JuceLibraryCode/modules/juce_graphics/images/juce_ImageCache.cpp b/JuceLibraryCode/modules/juce_graphics/images/juce_ImageCache.cpp index 992ff32..797c796 100644 --- a/JuceLibraryCode/modules/juce_graphics/images/juce_ImageCache.cpp +++ b/JuceLibraryCode/modules/juce_graphics/images/juce_ImageCache.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -110,7 +110,7 @@ public: unsigned int cacheTimeout; - juce_DeclareSingleton_SingleThreaded_Minimal (ImageCache::Pimpl); + juce_DeclareSingleton_SingleThreaded_Minimal (ImageCache::Pimpl) private: OwnedArray images; @@ -119,7 +119,7 @@ private: JUCE_DECLARE_NON_COPYABLE (Pimpl) }; -juce_ImplementSingleton_SingleThreaded (ImageCache::Pimpl); +juce_ImplementSingleton_SingleThreaded (ImageCache::Pimpl) //============================================================================== diff --git a/JuceLibraryCode/modules/juce_graphics/images/juce_ImageCache.h b/JuceLibraryCode/modules/juce_graphics/images/juce_ImageCache.h index c424395..77bdc60 100644 --- a/JuceLibraryCode/modules/juce_graphics/images/juce_ImageCache.h +++ b/JuceLibraryCode/modules/juce_graphics/images/juce_ImageCache.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_graphics/images/juce_ImageConvolutionKernel.cpp b/JuceLibraryCode/modules/juce_graphics/images/juce_ImageConvolutionKernel.cpp index 78e4fb8..95a184c 100644 --- a/JuceLibraryCode/modules/juce_graphics/images/juce_ImageConvolutionKernel.cpp +++ b/JuceLibraryCode/modules/juce_graphics/images/juce_ImageConvolutionKernel.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_graphics/images/juce_ImageConvolutionKernel.h b/JuceLibraryCode/modules/juce_graphics/images/juce_ImageConvolutionKernel.h index 885dc6b..67d55d6 100644 --- a/JuceLibraryCode/modules/juce_graphics/images/juce_ImageConvolutionKernel.h +++ b/JuceLibraryCode/modules/juce_graphics/images/juce_ImageConvolutionKernel.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_graphics/images/juce_ImageFileFormat.cpp b/JuceLibraryCode/modules/juce_graphics/images/juce_ImageFileFormat.cpp index a1cfd6a..3ce2dc6 100644 --- a/JuceLibraryCode/modules/juce_graphics/images/juce_ImageFileFormat.cpp +++ b/JuceLibraryCode/modules/juce_graphics/images/juce_ImageFileFormat.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_graphics/images/juce_ImageFileFormat.h b/JuceLibraryCode/modules/juce_graphics/images/juce_ImageFileFormat.h index 76a13d2..e54ede6 100644 --- a/JuceLibraryCode/modules/juce_graphics/images/juce_ImageFileFormat.h +++ b/JuceLibraryCode/modules/juce_graphics/images/juce_ImageFileFormat.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_graphics/juce_graphics.cpp b/JuceLibraryCode/modules/juce_graphics/juce_graphics.cpp index 627d565..2d5a096 100644 --- a/JuceLibraryCode/modules/juce_graphics/juce_graphics.cpp +++ b/JuceLibraryCode/modules/juce_graphics/juce_graphics.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -73,17 +73,17 @@ #ifndef JUCE_USE_FREETYPE #define JUCE_USE_FREETYPE 1 #endif +#endif - #if ! JUCE_USE_FREETYPE_AMALGAMATED +#if JUCE_USE_FREETYPE + #if JUCE_USE_FREETYPE_AMALGAMATED + #include "native/freetype/FreeTypeAmalgam.h" + #else #include #include FT_FREETYPE_H #endif #endif -#if JUCE_USE_FREETYPE && JUCE_USE_FREETYPE_AMALGAMATED - #include "native/freetype/FreeTypeAmalgam.h" -#endif - #undef SIZEOF #if (JUCE_MAC || JUCE_IOS) && USE_COREGRAPHICS_RENDERING && JUCE_USE_COREIMAGE_LOADER diff --git a/JuceLibraryCode/modules/juce_graphics/juce_graphics.h b/JuceLibraryCode/modules/juce_graphics/juce_graphics.h index 9a5a015..a792131 100644 --- a/JuceLibraryCode/modules/juce_graphics/juce_graphics.h +++ b/JuceLibraryCode/modules/juce_graphics/juce_graphics.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_graphics/juce_graphics.mm b/JuceLibraryCode/modules/juce_graphics/juce_graphics.mm index b36b0ed..6e033f6 100644 --- a/JuceLibraryCode/modules/juce_graphics/juce_graphics.mm +++ b/JuceLibraryCode/modules/juce_graphics/juce_graphics.mm @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_graphics/juce_module_info b/JuceLibraryCode/modules/juce_graphics/juce_module_info index 29c06b2..053c947 100644 --- a/JuceLibraryCode/modules/juce_graphics/juce_module_info +++ b/JuceLibraryCode/modules/juce_graphics/juce_module_info @@ -1,7 +1,7 @@ { "id": "juce_graphics", "name": "JUCE graphics classes", - "version": "3.0.6", + "version": "3.2.0", "description": "Classes for 2D vector graphics, image loading/saving, font handling, etc.", "website": "http://www.juce.com/juce", "license": "GPL/Commercial", diff --git a/JuceLibraryCode/modules/juce_graphics/native/juce_RenderingHelpers.h b/JuceLibraryCode/modules/juce_graphics/native/juce_RenderingHelpers.h index 533d002..cd8cd36 100644 --- a/JuceLibraryCode/modules/juce_graphics/native/juce_RenderingHelpers.h +++ b/JuceLibraryCode/modules/juce_graphics/native/juce_RenderingHelpers.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -162,15 +162,6 @@ public: } //============================================================================== - void drawGlyph (RenderTargetType& target, const Font& font, const int glyphNumber, Point pos) - { - if (ReferenceCountedObjectPtr glyph = findOrCreateGlyph (font, glyphNumber)) - { - glyph->lastAccessCount = ++accessCounter; - glyph->draw (target, pos); - } - } - void reset() { const ScopedLock sl (lock); @@ -180,11 +171,14 @@ public: misses.set (0); } -private: - friend struct ContainerDeletePolicy; - ReferenceCountedArray glyphs; - Atomic accessCounter, hits, misses; - CriticalSection lock; + void drawGlyph (RenderTargetType& target, const Font& font, const int glyphNumber, Point pos) + { + if (ReferenceCountedObjectPtr glyph = findOrCreateGlyph (font, glyphNumber)) + { + glyph->lastAccessCount = ++accessCounter; + glyph->draw (target, pos); + } + } ReferenceCountedObjectPtr findOrCreateGlyph (const Font& font, int glyphNumber) { @@ -203,6 +197,12 @@ private: return g; } +private: + friend struct ContainerDeletePolicy; + ReferenceCountedArray glyphs; + Atomic accessCounter, hits, misses; + CriticalSection lock; + CachedGlyphType* findExistingGlyph (const Font& font, int glyphNumber) const { for (int i = 0; i < glyphs.size(); ++i) @@ -302,12 +302,10 @@ public: } Font font; + ScopedPointer edgeTable; int glyph, lastAccessCount; bool snapToIntegerCoordinate; -private: - ScopedPointer edgeTable; - JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (CachedGlyphEdgeTable) }; @@ -435,12 +433,12 @@ namespace GradientPixelIterators if (vertical) { scale = roundToInt ((numEntries << (int) numScaleBits) / (double) (p2.y - p1.y)); - start = roundToInt (p1.y * scale); + start = roundToInt (p1.y * (float) scale); } else if (horizontal) { scale = roundToInt ((numEntries << (int) numScaleBits) / (double) (p2.x - p1.x)); - start = roundToInt (p1.x * scale); + start = roundToInt (p1.x * (float) scale); } else { @@ -536,8 +534,9 @@ namespace GradientPixelIterators forcedinline void setY (const int y) noexcept { - lineYM01 = inverseTransform.mat01 * y + inverseTransform.mat02 - gx1; - lineYM11 = inverseTransform.mat11 * y + inverseTransform.mat12 - gy1; + const float floatY = (float) y; + lineYM01 = inverseTransform.mat01 * floatY + inverseTransform.mat02 - gx1; + lineYM11 = inverseTransform.mat11 * floatY + inverseTransform.mat12 - gy1; } inline PixelARGB getPixel (const int px) const noexcept @@ -589,6 +588,10 @@ namespace EdgeTableFillers filler[2].set (sourceColour); filler[3].set (sourceColour); } + else + { + areRGBComponentsEqual = false; + } } forcedinline void setEdgeTableYPos (const int y) noexcept @@ -1299,7 +1302,7 @@ namespace EdgeTableFillers sx += pixelOffset; sy += pixelOffset; float x1 = sx, y1 = sy; - sx += numPixels; + sx += (float) numPixels; inverseTransform.transformPoints (x1, y1, sx, sy); xBresenham.set ((int) (x1 * 256.0f), (int) (sx * 256.0f), numPixels, pixelOffsetInt); diff --git a/JuceLibraryCode/modules/juce_graphics/native/juce_android_Fonts.cpp b/JuceLibraryCode/modules/juce_graphics/native/juce_android_Fonts.cpp index 29702a2..78d2b49 100644 --- a/JuceLibraryCode/modules/juce_graphics/native/juce_android_Fonts.cpp +++ b/JuceLibraryCode/modules/juce_graphics/native/juce_android_Fonts.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -138,22 +138,47 @@ public: { JNIEnv* const env = getEnv(); - const bool isBold = style.contains ("Bold"); - const bool isItalic = style.contains ("Italic"); + // First check whether there's an embedded asset with this font name: + typeface = GlobalRef (android.activity.callObjectMethod (JuceAppActivity.getTypeFaceFromAsset, + javaString ("fonts/" + name).get())); - File fontFile (getFontFile (name, style)); + if (typeface.get() == nullptr) + { + const bool isBold = style.contains ("Bold"); + const bool isItalic = style.contains ("Italic"); - if (! fontFile.exists()) - fontFile = findFontFile (name, isBold, isItalic); + File fontFile (getFontFile (name, style)); - if (fontFile.exists()) - typeface = GlobalRef (env->CallStaticObjectMethod (TypefaceClass, TypefaceClass.createFromFile, - javaString (fontFile.getFullPathName()).get())); - else - typeface = GlobalRef (env->CallStaticObjectMethod (TypefaceClass, TypefaceClass.create, - javaString (getName()).get(), - (isBold ? 1 : 0) + (isItalic ? 2 : 0))); + if (! fontFile.exists()) + fontFile = findFontFile (name, isBold, isItalic); + if (fontFile.exists()) + typeface = GlobalRef (env->CallStaticObjectMethod (TypefaceClass, TypefaceClass.createFromFile, + javaString (fontFile.getFullPathName()).get())); + else + typeface = GlobalRef (env->CallStaticObjectMethod (TypefaceClass, TypefaceClass.create, + javaString (getName()).get(), + (isBold ? 1 : 0) + (isItalic ? 2 : 0))); + } + + initialise (env); + } + + AndroidTypeface (const void* data, size_t size) + : Typeface (String(), String()) + { + JNIEnv* const env = getEnv(); + + LocalRef bytes (env->NewByteArray (size)); + env->SetByteArrayRegion (bytes, 0, size, (const jbyte*) data); + + typeface = GlobalRef (android.activity.callObjectMethod (JuceAppActivity.getTypeFaceFromByteArray, bytes.get())); + + initialise (env); + } + + void initialise (JNIEnv* const env) + { rect = GlobalRef (env->NewObject (RectClass, RectClass.constructor, 0, 0, 0, 0)); paint = GlobalRef (GraphicsHelpers::createPaint (Graphics::highResamplingQuality)); @@ -315,10 +340,9 @@ Typeface::Ptr Typeface::createSystemTypefaceFor (const Font& font) return new AndroidTypeface (font); } -Typeface::Ptr Typeface::createSystemTypefaceFor (const void*, size_t) +Typeface::Ptr Typeface::createSystemTypefaceFor (const void* data, size_t size) { - jassertfalse; // not yet implemented! - return nullptr; + return new AndroidTypeface (data, size); } void Typeface::scanFolderForFonts (const File&) diff --git a/JuceLibraryCode/modules/juce_graphics/native/juce_android_GraphicsContext.cpp b/JuceLibraryCode/modules/juce_graphics/native/juce_android_GraphicsContext.cpp index 9382c1d..4c48812 100644 --- a/JuceLibraryCode/modules/juce_graphics/native/juce_android_GraphicsContext.cpp +++ b/JuceLibraryCode/modules/juce_graphics/native/juce_android_GraphicsContext.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_graphics/native/juce_freetype_Fonts.cpp b/JuceLibraryCode/modules/juce_graphics/native/juce_freetype_Fonts.cpp index 43a6436..cc87924 100644 --- a/JuceLibraryCode/modules/juce_graphics/native/juce_freetype_Fonts.cpp +++ b/JuceLibraryCode/modules/juce_graphics/native/juce_freetype_Fonts.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -224,7 +224,7 @@ public: sansSerif.addIfNotAlreadyThere (faces.getUnchecked(i)->family); } - juce_DeclareSingleton_SingleThreaded_Minimal (FTTypefaceList); + juce_DeclareSingleton_SingleThreaded_Minimal (FTTypefaceList) private: FTLibWrapper::Ptr library; @@ -244,7 +244,7 @@ private: if (face.face != 0) { if (faceIndex == 0) - numFaces = face.face->num_faces; + numFaces = (int) face.face->num_faces; if ((face.face->face_flags & FT_FACE_FLAG_SCALABLE) != 0) faces.add (new KnownTypeface (file, faceIndex, face)); @@ -307,9 +307,9 @@ public: faceWrapper->face->style_name); } - void initialiseCharacteristics (const String& name, const String& style) + void initialiseCharacteristics (const String& fontName, const String& fontStyle) { - setCharacteristics (name, style, + setCharacteristics (fontName, fontStyle, faceWrapper->face->ascender / (float) (faceWrapper->face->ascender - faceWrapper->face->descender), L' '); } @@ -319,7 +319,7 @@ public: if (faceWrapper != nullptr) { FT_Face face = faceWrapper->face; - const unsigned int glyphIndex = FT_Get_Char_Index (face, character); + const unsigned int glyphIndex = FT_Get_Char_Index (face, (FT_ULong) character); if (FT_Load_Glyph (face, glyphIndex, FT_LOAD_NO_SCALE | FT_LOAD_NO_BITMAP | FT_LOAD_IGNORE_TRANSFORM | FT_LOAD_NO_HINTING) == 0 && face->glyph->format == ft_glyph_format_outline) @@ -332,7 +332,7 @@ public: addGlyph (character, destShape, face->glyph->metrics.horiAdvance * scale); if ((face->face_flags & FT_FACE_FLAG_KERNING) != 0) - addKerning (face, character, glyphIndex); + addKerning (face, (uint32) character, glyphIndex); return true; } @@ -437,7 +437,7 @@ private: const float height = (float) (face->ascender - face->descender); uint32 rightGlyphIndex; - uint32 rightCharCode = FT_Get_First_Char (face, &rightGlyphIndex); + FT_ULong rightCharCode = FT_Get_First_Char (face, &rightGlyphIndex); while (rightGlyphIndex != 0) { @@ -445,7 +445,7 @@ private: if (FT_Get_Kerning (face, glyphIndex, rightGlyphIndex, ft_kerning_unscaled, &kerning) == 0 && kerning.x != 0) - addKerningPair (character, rightCharCode, kerning.x / height); + addKerningPair ((juce_wchar) character, (juce_wchar) rightCharCode, kerning.x / height); rightCharCode = FT_Get_Next_Char (face, rightCharCode, &rightGlyphIndex); } diff --git a/JuceLibraryCode/modules/juce_graphics/native/juce_linux_Fonts.cpp b/JuceLibraryCode/modules/juce_graphics/native/juce_linux_Fonts.cpp index 0869ec7..39dd384 100644 --- a/JuceLibraryCode/modules/juce_graphics/native/juce_linux_Fonts.cpp +++ b/JuceLibraryCode/modules/juce_graphics/native/juce_linux_Fonts.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_graphics/native/juce_mac_CoreGraphicsContext.h b/JuceLibraryCode/modules/juce_graphics/native/juce_mac_CoreGraphicsContext.h index bf26ce8..df34033 100644 --- a/JuceLibraryCode/modules/juce_graphics/native/juce_mac_CoreGraphicsContext.h +++ b/JuceLibraryCode/modules/juce_graphics/native/juce_mac_CoreGraphicsContext.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -77,7 +77,6 @@ private: const CGFloat flipHeight; float targetScale; CGColorSpaceRef rgbColourSpace, greyColourSpace; - CGFunctionCallbacks gradientCallbacks; mutable Rectangle lastClipRect; mutable bool lastClipRectIsValid; @@ -87,24 +86,17 @@ private: SavedState (const SavedState&); ~SavedState(); - void setFill (const FillType& newFill); - CGShadingRef getShading (CoreGraphicsContext& owner); - - static void gradientCallback (void* info, const CGFloat* inData, CGFloat* outData); + void setFill (const FillType&); FillType fillType; Font font; CGFontRef fontRef; CGAffineTransform fontTransform; - - private: - CGShadingRef shading; - HeapBlock gradientLookupTable; - int numGradientLookupEntries; + CGGradientRef gradient; }; - ScopedPointer state; - OwnedArray stateStack; + ScopedPointer state; + OwnedArray stateStack; void drawGradient(); void createPath (const Path&) const; diff --git a/JuceLibraryCode/modules/juce_graphics/native/juce_mac_CoreGraphicsContext.mm b/JuceLibraryCode/modules/juce_graphics/native/juce_mac_CoreGraphicsContext.mm index 44e344f..a6f9874 100644 --- a/JuceLibraryCode/modules/juce_graphics/native/juce_mac_CoreGraphicsContext.mm +++ b/JuceLibraryCode/modules/juce_graphics/native/juce_mac_CoreGraphicsContext.mm @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -25,7 +25,7 @@ #include "juce_mac_CoreGraphicsContext.h" //============================================================================== -class CoreGraphicsImage : public ImagePixelData +class CoreGraphicsImage : public ImagePixelData { public: CoreGraphicsImage (const Image::PixelFormat format, const int w, const int h, const bool clearImage) @@ -174,13 +174,11 @@ CoreGraphicsContext::CoreGraphicsContext (CGContextRef c, const float h, const f CGContextRetain (context); CGContextSaveGState(context); CGContextSetShouldSmoothFonts (context, true); + CGContextSetAllowsFontSmoothing (context, true); CGContextSetShouldAntialias (context, true); CGContextSetBlendMode (context, kCGBlendModeNormal); rgbColourSpace = CGColorSpaceCreateDeviceRGB(); greyColourSpace = CGColorSpaceCreateDeviceGray(); - gradientCallbacks.version = 0; - gradientCallbacks.evaluate = SavedState::gradientCallback; - gradientCallbacks.releaseInfo = 0; setFont (Font()); } @@ -218,8 +216,6 @@ float CoreGraphicsContext::getPhysicalPixelScaleFactor() const CGAffineTransform t = CGContextGetCTM (context); return targetScale * (float) (juce_hypot (t.a, t.c) + juce_hypot (t.b, t.d)) / 2.0f; - -// return targetScale * (float) (t.a + t.d) / 2.0f; } bool CoreGraphicsContext::clipToRectangle (const Rectangle& r) @@ -248,19 +244,17 @@ bool CoreGraphicsContext::clipToRectangleListWithoutTest (const RectangleList(); return false; } - else - { - const size_t numRects = (size_t) clipRegion.getNumRectangles(); - HeapBlock rects (numRects); - int i = 0; - for (const Rectangle* r = clipRegion.begin(), * const e = clipRegion.end(); r != e; ++r) - rects[i++] = CGRectMake (r->getX(), flipHeight - r->getBottom(), r->getWidth(), r->getHeight()); + const size_t numRects = (size_t) clipRegion.getNumRectangles(); + HeapBlock rects (numRects); - CGContextClipToRects (context, rects, numRects); - lastClipRectIsValid = false; - return true; - } + int i = 0; + for (const Rectangle* r = clipRegion.begin(), * const e = clipRegion.end(); r != e; ++r) + rects[i++] = CGRectMake (r->getX(), flipHeight - r->getBottom(), r->getWidth(), r->getHeight()); + + CGContextClipToRects (context, rects, numRects); + lastClipRectIsValid = false; + return true; } bool CoreGraphicsContext::clipToRectangleList (const RectangleList& clipRegion) @@ -411,7 +405,9 @@ void CoreGraphicsContext::fillCGRect (const CGRect& cgRect, const bool replaceEx { if (replaceExistingContents) { - #if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_5 + #if JUCE_IOS + CGContextSetBlendMode (context, kCGBlendModeCopy); + #elif MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_5 CGContextClearRect (context, cgRect); #else #if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5 @@ -507,7 +503,7 @@ void CoreGraphicsContext::drawImage (const Image& sourceImage, const AffineTrans #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 // There's a bug in CGContextDrawTiledImage that makes it incredibly slow // if it's doing a transformation - it's quicker to just draw lots of images manually - if (CGContextDrawTiledImage != 0 && transform.isOnlyTranslation()) + if (&CGContextDrawTiledImage != 0 && transform.isOnlyTranslation()) CGContextDrawTiledImage (context, imageRect, image); else #endif @@ -519,7 +515,7 @@ void CoreGraphicsContext::drawImage (const Image& sourceImage, const AffineTrans while (x > clip.origin.x) x -= iw; while (y > clip.origin.y) y -= ih; - const int right = (int) (clip.origin.x + clip.size.width); + const int right = (int) (clip.origin.x + clip.size.width); const int bottom = (int) (clip.origin.y + clip.size.height); while (y < bottom) @@ -600,7 +596,7 @@ void CoreGraphicsContext::setFont (const Font& newFont) state->fontRef = 0; state->font = newFont; - if (OSXTypeface* osxTypeface = dynamic_cast (state->font.getTypeface())) + if (OSXTypeface* osxTypeface = dynamic_cast (state->font.getTypeface())) { state->fontRef = osxTypeface->fontRef; CGContextSetFont (context, state->fontRef); @@ -678,97 +674,85 @@ bool CoreGraphicsContext::drawTextLayout (const AttributedString& text, const Re } CoreGraphicsContext::SavedState::SavedState() - : font (1.0f), fontRef (0), fontTransform (CGAffineTransformIdentity), - shading (0), numGradientLookupEntries (0) + : font (1.0f), fontRef (0), fontTransform (CGAffineTransformIdentity), gradient (0) { } CoreGraphicsContext::SavedState::SavedState (const SavedState& other) : fillType (other.fillType), font (other.font), fontRef (other.fontRef), - fontTransform (other.fontTransform), shading (0), - gradientLookupTable ((size_t) other.numGradientLookupEntries), - numGradientLookupEntries (other.numGradientLookupEntries) + fontTransform (other.fontTransform), gradient (other.gradient) { - memcpy (gradientLookupTable, other.gradientLookupTable, sizeof (PixelARGB) * (size_t) numGradientLookupEntries); + if (gradient != 0) + CGGradientRetain (gradient); } CoreGraphicsContext::SavedState::~SavedState() { - if (shading != 0) - CGShadingRelease (shading); + if (gradient != 0) + CGGradientRelease (gradient); } void CoreGraphicsContext::SavedState::setFill (const FillType& newFill) { fillType = newFill; - if (fillType.isGradient() && shading != 0) + if (gradient != 0) { - CGShadingRelease (shading); - shading = 0; + CGGradientRelease (gradient); + gradient = 0; } } -CGShadingRef CoreGraphicsContext::SavedState::getShading (CoreGraphicsContext& owner) +static CGGradientRef createGradient (const ColourGradient& g, CGColorSpaceRef colourSpace) { - if (shading == 0) + const int numColours = g.getNumColours(); + CGFloat* const data = (CGFloat*) alloca ((size_t) numColours * 5 * sizeof (CGFloat)); + CGFloat* const locations = data; + CGFloat* const components = data + numColours; + CGFloat* comps = components; + + for (int i = 0; i < numColours; ++i) { - ColourGradient& g = *(fillType.gradient); - numGradientLookupEntries = g.createLookupTable (fillType.transform, gradientLookupTable) - 1; - - CGFunctionRef function = CGFunctionCreate (this, 1, 0, 4, 0, &(owner.gradientCallbacks)); - CGPoint p1 (convertToCGPoint (g.point1)); - - if (g.isRadial) - { - shading = CGShadingCreateRadial (owner.rgbColourSpace, p1, 0, - p1, g.point1.getDistanceFrom (g.point2), - function, true, true); - } - else - { - shading = CGShadingCreateAxial (owner.rgbColourSpace, p1, - convertToCGPoint (g.point2), - function, true, true); - } - - CGFunctionRelease (function); + const Colour colour (g.getColour (i)); + *comps++ = (CGFloat) colour.getFloatRed(); + *comps++ = (CGFloat) colour.getFloatGreen(); + *comps++ = (CGFloat) colour.getFloatBlue(); + *comps++ = (CGFloat) colour.getFloatAlpha(); + locations[i] = (CGFloat) g.getColourPosition (i); } - return shading; -} - -void CoreGraphicsContext::SavedState::gradientCallback (void* info, const CGFloat* inData, CGFloat* outData) -{ - const SavedState* const s = static_cast (info); - - const int index = roundToInt (s->numGradientLookupEntries * inData[0]); - PixelARGB colour (s->gradientLookupTable [jlimit (0, s->numGradientLookupEntries, index)]); - colour.unpremultiply(); - - outData[0] = colour.getRed() / 255.0f; - outData[1] = colour.getGreen() / 255.0f; - outData[2] = colour.getBlue() / 255.0f; - outData[3] = colour.getAlpha() / 255.0f; + return CGGradientCreateWithColorComponents (colourSpace, components, locations, (size_t) numColours); } void CoreGraphicsContext::drawGradient() { flip(); applyTransform (state->fillType.transform); - - CGContextSetInterpolationQuality (context, kCGInterpolationDefault); // (This is required for 10.4, where there's a crash if - // you draw a gradient with high quality interp enabled). CGContextSetAlpha (context, state->fillType.getOpacity()); - CGContextDrawShading (context, state->getShading (*this)); + + const ColourGradient& g = *state->fillType.gradient; + + CGPoint p1 (convertToCGPoint (g.point1)); + CGPoint p2 (convertToCGPoint (g.point2)); + + state->fillType.transform.transformPoints (p1.x, p1.y, p2.x, p2.y); + + if (state->gradient == 0) + state->gradient = createGradient (g, rgbColourSpace); + + if (g.isRadial) + CGContextDrawRadialGradient (context, state->gradient, p1, 0, p1, g.point1.getDistanceFrom (g.point2), + kCGGradientDrawsBeforeStartLocation | kCGGradientDrawsAfterEndLocation); + else + CGContextDrawLinearGradient (context, state->gradient, p1, p2, + kCGGradientDrawsBeforeStartLocation | kCGGradientDrawsAfterEndLocation); } void CoreGraphicsContext::createPath (const Path& path) const { CGContextBeginPath (context); - Path::Iterator i (path); - while (i.next()) + for (Path::Iterator i (path); i.next();) { switch (i.elementType) { @@ -785,9 +769,8 @@ void CoreGraphicsContext::createPath (const Path& path) const void CoreGraphicsContext::createPath (const Path& path, const AffineTransform& transform) const { CGContextBeginPath (context); - Path::Iterator i (path); - while (i.next()) + for (Path::Iterator i (path); i.next();) { switch (i.elementType) { @@ -917,7 +900,7 @@ CGImageRef juce_createCoreGraphicsImage (const Image& juceImage, CGColorSpaceRef CGContextRef juce_getImageContext (const Image& image) { - if (CoreGraphicsImage* const cgi = dynamic_cast (image.getPixelData())) + if (CoreGraphicsImage* const cgi = dynamic_cast (image.getPixelData())) return cgi->context; jassertfalse; diff --git a/JuceLibraryCode/modules/juce_graphics/native/juce_mac_CoreGraphicsHelpers.h b/JuceLibraryCode/modules/juce_graphics/native/juce_mac_CoreGraphicsHelpers.h index ca6f699..1982ea3 100644 --- a/JuceLibraryCode/modules/juce_graphics/native/juce_mac_CoreGraphicsHelpers.h +++ b/JuceLibraryCode/modules/juce_graphics/native/juce_mac_CoreGraphicsHelpers.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -30,25 +30,25 @@ namespace { template - Rectangle convertToRectInt (const RectType& r) noexcept + Rectangle convertToRectInt (RectType r) noexcept { return Rectangle ((int) r.origin.x, (int) r.origin.y, (int) r.size.width, (int) r.size.height); } template - Rectangle convertToRectFloat (const RectType& r) noexcept + Rectangle convertToRectFloat (RectType r) noexcept { return Rectangle (r.origin.x, r.origin.y, r.size.width, r.size.height); } template - CGRect convertToCGRect (const RectType& r) noexcept + CGRect convertToCGRect (RectType r) noexcept { return CGRectMake ((CGFloat) r.getX(), (CGFloat) r.getY(), (CGFloat) r.getWidth(), (CGFloat) r.getHeight()); } template - CGPoint convertToCGPoint (const PointType& p) noexcept + CGPoint convertToCGPoint (PointType p) noexcept { return CGPointMake ((CGFloat) p.x, (CGFloat) p.y); } diff --git a/JuceLibraryCode/modules/juce_graphics/native/juce_mac_Fonts.mm b/JuceLibraryCode/modules/juce_graphics/native/juce_mac_Fonts.mm index 81a29a8..b5c6918 100644 --- a/JuceLibraryCode/modules/juce_graphics/native/juce_mac_Fonts.mm +++ b/JuceLibraryCode/modules/juce_graphics/native/juce_mac_Fonts.mm @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -385,7 +385,7 @@ namespace CoreTextTypeLayout static void createLayout (TextLayout& glyphLayout, const AttributedString& text) { - const CGFloat boundsHeight = 1.0e6f; + const CGFloat boundsHeight = glyphLayout.getHeight(); CTFrameRef frame = createCTFrame (text, CGRectMake (0, 0, glyphLayout.getWidth(), boundsHeight)); CFArrayRef lines = CTFrameGetLines (frame); diff --git a/JuceLibraryCode/modules/juce_graphics/native/juce_win32_Direct2DGraphicsContext.cpp b/JuceLibraryCode/modules/juce_graphics/native/juce_win32_Direct2DGraphicsContext.cpp index e4356b7..ba1d339 100644 --- a/JuceLibraryCode/modules/juce_graphics/native/juce_win32_Direct2DGraphicsContext.cpp +++ b/JuceLibraryCode/modules/juce_graphics/native/juce_win32_Direct2DGraphicsContext.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_graphics/native/juce_win32_DirectWriteTypeLayout.cpp b/JuceLibraryCode/modules/juce_graphics/native/juce_win32_DirectWriteTypeLayout.cpp index 89ab8f6..ca74b90 100644 --- a/JuceLibraryCode/modules/juce_graphics/native/juce_win32_DirectWriteTypeLayout.cpp +++ b/JuceLibraryCode/modules/juce_graphics/native/juce_win32_DirectWriteTypeLayout.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -29,8 +29,9 @@ namespace DirectWriteTypeLayout class CustomDirectWriteTextRenderer : public ComBaseClassHelper { public: - CustomDirectWriteTextRenderer (IDWriteFontCollection* const fonts) + CustomDirectWriteTextRenderer (IDWriteFontCollection* const fonts, const AttributedString& as) : ComBaseClassHelper (0), + attributedString (as), fontCollection (fonts), currentLine (-1), lastOriginY (-10000.0f) @@ -89,20 +90,16 @@ namespace DirectWriteTypeLayout glyphLine.ascent = jmax (glyphLine.ascent, scaledFontSize (dwFontMetrics.ascent, dwFontMetrics, glyphRun)); glyphLine.descent = jmax (glyphLine.descent, scaledFontSize (dwFontMetrics.descent, dwFontMetrics, glyphRun)); - String fontFamily, fontStyle; - getFontFamilyAndStyle (glyphRun, fontFamily, fontStyle); - TextLayout::Run* const glyphRunLayout = new TextLayout::Run (Range (runDescription->textPosition, runDescription->textPosition + runDescription->stringLength), glyphRun->glyphCount); glyphLine.runs.add (glyphRunLayout); glyphRun->fontFace->GetMetrics (&dwFontMetrics); - const float totalHeight = std::abs ((float) dwFontMetrics.ascent) + std::abs ((float) dwFontMetrics.descent); const float fontHeightToEmSizeFactor = (float) dwFontMetrics.designUnitsPerEm / totalHeight; - glyphRunLayout->font = Font (fontFamily, fontStyle, glyphRun->fontEmSize / fontHeightToEmSizeFactor); + glyphRunLayout->font = getFontForRun (glyphRun, glyphRun->fontEmSize / fontHeightToEmSizeFactor); glyphRunLayout->colour = getColourOf (static_cast (clientDrawingEffect)); const Point lineOrigin (layout->getLine (currentLine).lineOrigin); @@ -127,6 +124,7 @@ namespace DirectWriteTypeLayout } private: + const AttributedString& attributedString; IDWriteFontCollection* const fontCollection; int currentLine; float lastOriginY; @@ -145,19 +143,22 @@ namespace DirectWriteTypeLayout return Colour::fromFloatRGBA (colour.r, colour.g, colour.b, colour.a); } - void getFontFamilyAndStyle (DWRITE_GLYPH_RUN const* glyphRun, String& family, String& style) const + Font getFontForRun (DWRITE_GLYPH_RUN const* glyphRun, float fontHeight) { + for (int i = 0; i < attributedString.getNumAttributes(); ++i) + if (const Font* font = attributedString.getAttribute(i)->getFont()) + if (WindowsDirectWriteTypeface* wt = dynamic_cast (font->getTypeface())) + if (wt->getIDWriteFontFace() == glyphRun->fontFace) + return font->withHeight (fontHeight); + ComSmartPtr dwFont; HRESULT hr = fontCollection->GetFontFromFontFace (glyphRun->fontFace, dwFont.resetAndGetPointerAddress()); jassert (dwFont != nullptr); - { - ComSmartPtr dwFontFamily; - hr = dwFont->GetFontFamily (dwFontFamily.resetAndGetPointerAddress()); - family = getFontFamilyName (dwFontFamily); - } + ComSmartPtr dwFontFamily; + hr = dwFont->GetFontFamily (dwFontFamily.resetAndGetPointerAddress()); - style = getFontFaceName (dwFont); + return Font (getFontFamilyName (dwFontFamily), getFontFaceName (dwFont), fontHeight); } JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (CustomDirectWriteTextRenderer) @@ -310,6 +311,13 @@ namespace DirectWriteTypeLayout setTextFormatProperties (text, dwTextFormat); + { + DWRITE_TRIMMING trimming = { DWRITE_TRIMMING_GRANULARITY_CHARACTER, 0, 0 }; + ComSmartPtr trimmingSign; + hr = directWriteFactory->CreateEllipsisTrimmingSign (dwTextFormat, trimmingSign.resetAndGetPointerAddress()); + hr = dwTextFormat->SetTrimming (&trimming, trimmingSign); + } + const int textLen = text.getText().length(); hr = directWriteFactory->CreateTextLayout (text.getText().toWideCharPointer(), textLen, dwTextFormat, @@ -343,7 +351,8 @@ namespace DirectWriteTypeLayout ComSmartPtr dwTextLayout; - if (! setupLayout (text, layout.getWidth(), 1.0e7f, renderTarget, directWriteFactory, fontCollection, dwTextLayout)) + if (! setupLayout (text, layout.getWidth(), layout.getHeight(), renderTarget, + directWriteFactory, fontCollection, dwTextLayout)) return; UINT32 actualLineCount = 0; @@ -352,11 +361,11 @@ namespace DirectWriteTypeLayout layout.ensureStorageAllocated (actualLineCount); { - ComSmartPtr textRenderer (new CustomDirectWriteTextRenderer (fontCollection)); + ComSmartPtr textRenderer (new CustomDirectWriteTextRenderer (fontCollection, text)); hr = dwTextLayout->Draw (&layout, textRenderer, 0, 0); } - HeapBlock dwLineMetrics (actualLineCount); + HeapBlock dwLineMetrics (actualLineCount); hr = dwTextLayout->GetLineMetrics (dwLineMetrics, actualLineCount, &actualLineCount); int lastLocation = 0; const int numLines = jmin ((int) actualLineCount, layout.getNumLines()); @@ -373,7 +382,8 @@ namespace DirectWriteTypeLayout { ComSmartPtr dwTextLayout; - if (setupLayout (text, area.getWidth(), area.getHeight(), renderTarget, directWriteFactory, fontCollection, dwTextLayout)) + if (setupLayout (text, area.getWidth(), area.getHeight(), renderTarget, + directWriteFactory, fontCollection, dwTextLayout)) { ComSmartPtr d2dBrush; renderTarget->CreateSolidColorBrush (D2D1::ColorF (D2D1::ColorF (0.0f, 0.0f, 0.0f, 1.0f)), @@ -384,11 +394,27 @@ namespace DirectWriteTypeLayout } } } + +static bool canAllTypefacesBeUsedInLayout (const AttributedString& text) +{ + const int numCharacterAttributes = text.getNumAttributes(); + + for (int i = 0; i < numCharacterAttributes; ++i) + if (const Font* const font = text.getAttribute (i)->getFont()) + if (dynamic_cast (font->getTypeface()) == nullptr) + return false; + + return true; +} + #endif bool TextLayout::createNativeLayout (const AttributedString& text) { #if JUCE_USE_DIRECTWRITE + if (! canAllTypefacesBeUsedInLayout (text)) + return false; + SharedResourcePointer factories; if (factories->d2dFactory != nullptr && factories->systemFonts != nullptr) diff --git a/JuceLibraryCode/modules/juce_graphics/native/juce_win32_DirectWriteTypeface.cpp b/JuceLibraryCode/modules/juce_graphics/native/juce_win32_DirectWriteTypeface.cpp index 7240142..dcf6606 100644 --- a/JuceLibraryCode/modules/juce_graphics/native/juce_win32_DirectWriteTypeface.cpp +++ b/JuceLibraryCode/modules/juce_graphics/native/juce_win32_DirectWriteTypeface.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -139,27 +139,27 @@ public: hr = fontCollection->GetFontFamily (fontIndex, dwFontFamily.resetAndGetPointerAddress()); // Get a specific font in the font family using typeface style - ComSmartPtr dwFont; - uint32 fontFacesCount = 0; - fontFacesCount = dwFontFamily->GetFontCount(); - - for (int i = fontFacesCount; --i >= 0;) { - hr = dwFontFamily->GetFont (i, dwFont.resetAndGetPointerAddress()); + ComSmartPtr dwFont; - if (i == 0) - break; + for (int i = (int) dwFontFamily->GetFontCount(); --i >= 0;) + { + hr = dwFontFamily->GetFont (i, dwFont.resetAndGetPointerAddress()); - ComSmartPtr faceNames; - hr = dwFont->GetFaceNames (faceNames.resetAndGetPointerAddress()); + if (i == 0) + break; - if (font.getTypefaceStyle() == getLocalisedName (faceNames)) - break; + ComSmartPtr faceNames; + hr = dwFont->GetFaceNames (faceNames.resetAndGetPointerAddress()); + + if (font.getTypefaceStyle() == getLocalisedName (faceNames)) + break; + } + + jassert (dwFont != nullptr); + hr = dwFont->CreateFontFace (dwFontFace.resetAndGetPointerAddress()); } - jassert (dwFont != nullptr); - hr = dwFont->CreateFontFace (dwFontFace.resetAndGetPointerAddress()); - if (dwFontFace != nullptr) { DWRITE_FONT_METRICS dwFontMetrics; diff --git a/JuceLibraryCode/modules/juce_graphics/native/juce_win32_Fonts.cpp b/JuceLibraryCode/modules/juce_graphics/native/juce_win32_Fonts.cpp index ab5dbe8..dc54efe 100644 --- a/JuceLibraryCode/modules/juce_graphics/native/juce_win32_Fonts.cpp +++ b/JuceLibraryCode/modules/juce_graphics/native/juce_win32_Fonts.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -506,8 +506,8 @@ private: lf.lfOutPrecision = OUT_OUTLINE_PRECIS; lf.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE; lf.lfQuality = PROOF_QUALITY; - lf.lfItalic = (BYTE) (style == "Italic" ? TRUE : FALSE); - lf.lfWeight = style == "Bold" ? FW_BOLD : FW_NORMAL; + lf.lfItalic = (BYTE) (style.contains ("Italic") ? TRUE : FALSE); + lf.lfWeight = style.contains ("Bold") ? FW_BOLD : FW_NORMAL; lf.lfHeight = -256; name.copyToUTF16 (lf.lfFaceName, sizeof (lf.lfFaceName)); diff --git a/JuceLibraryCode/modules/juce_graphics/placement/juce_Justification.h b/JuceLibraryCode/modules/juce_graphics/placement/juce_Justification.h index f80fa21..c48ab71 100644 --- a/JuceLibraryCode/modules/juce_graphics/placement/juce_Justification.h +++ b/JuceLibraryCode/modules/juce_graphics/placement/juce_Justification.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_graphics/placement/juce_RectanglePlacement.cpp b/JuceLibraryCode/modules/juce_graphics/placement/juce_RectanglePlacement.cpp index 031048e..c13e505 100644 --- a/JuceLibraryCode/modules/juce_graphics/placement/juce_RectanglePlacement.cpp +++ b/JuceLibraryCode/modules/juce_graphics/placement/juce_RectanglePlacement.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_graphics/placement/juce_RectanglePlacement.h b/JuceLibraryCode/modules/juce_graphics/placement/juce_RectanglePlacement.h index 9341e67..fd5b24e 100644 --- a/JuceLibraryCode/modules/juce_graphics/placement/juce_RectanglePlacement.h +++ b/JuceLibraryCode/modules/juce_graphics/placement/juce_RectanglePlacement.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_gui_basics/application/juce_Application.cpp b/JuceLibraryCode/modules/juce_gui_basics/application/juce_Application.cpp index 4e21873..47c4ee2 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/application/juce_Application.cpp +++ b/JuceLibraryCode/modules/juce_gui_basics/application/juce_Application.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_gui_basics/application/juce_Application.h b/JuceLibraryCode/modules/juce_gui_basics/application/juce_Application.h index 1ffb27e..b5c3f28 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/application/juce_Application.h +++ b/JuceLibraryCode/modules/juce_gui_basics/application/juce_Application.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -53,24 +53,24 @@ MyJUCEApp() {} ~MyJUCEApp() {} - void initialise (const String& commandLine) + void initialise (const String& commandLine) override { myMainWindow = new MyApplicationWindow(); myMainWindow->setBounds (100, 100, 400, 500); myMainWindow->setVisible (true); } - void shutdown() + void shutdown() override { myMainWindow = nullptr; } - const String getApplicationName() + const String getApplicationName() override { return "Super JUCE-o-matic"; } - const String getApplicationVersion() + const String getApplicationVersion() override { return "1.0"; } @@ -111,11 +111,13 @@ public: static JUCEApplication* JUCE_CALLTYPE getInstance() noexcept; //============================================================================== + #if DOXYGEN /** Returns the application's name. */ virtual const String getApplicationName() = 0; /** Returns the application's version number. */ virtual const String getApplicationVersion() = 0; + #endif /** Checks whether multiple instances of the app are allowed. @@ -172,13 +174,13 @@ public: //============================================================================== /** @internal */ - ApplicationCommandTarget* getNextCommandTarget(); + ApplicationCommandTarget* getNextCommandTarget() override; /** @internal */ - void getCommandInfo (CommandID, ApplicationCommandInfo&); + void getCommandInfo (CommandID, ApplicationCommandInfo&) override; /** @internal */ - void getAllCommands (Array&); + void getAllCommands (Array&) override; /** @internal */ - bool perform (const InvocationInfo&); + bool perform (const InvocationInfo&) override; private: bool initialiseApp() override; diff --git a/JuceLibraryCode/modules/juce_gui_basics/buttons/juce_ArrowButton.cpp b/JuceLibraryCode/modules/juce_gui_basics/buttons/juce_ArrowButton.cpp index 75f8590..5ff5411 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/buttons/juce_ArrowButton.cpp +++ b/JuceLibraryCode/modules/juce_gui_basics/buttons/juce_ArrowButton.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_gui_basics/buttons/juce_ArrowButton.h b/JuceLibraryCode/modules/juce_gui_basics/buttons/juce_ArrowButton.h index 5d64123..17efd6f 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/buttons/juce_ArrowButton.h +++ b/JuceLibraryCode/modules/juce_gui_basics/buttons/juce_ArrowButton.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_gui_basics/buttons/juce_Button.cpp b/JuceLibraryCode/modules/juce_gui_basics/buttons/juce_Button.cpp index be7e55c..3debe03 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/buttons/juce_Button.cpp +++ b/JuceLibraryCode/modules/juce_gui_basics/buttons/juce_Button.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -125,11 +125,12 @@ void Button::setTooltip (const String& newTooltip) generateTooltip = false; } -String Button::getTooltip() +void Button::updateAutomaticTooltip (const ApplicationCommandInfo& info) { - if (generateTooltip && commandManagerToUse != nullptr && commandID != 0) + if (generateTooltip && commandManagerToUse != nullptr) { - String tt (commandManagerToUse->getDescriptionOfCommand (commandID)); + String tt (info.description.isNotEmpty() ? info.description + : info.shortName); Array keyPresses (commandManagerToUse->getKeyMappings()->getKeyPressesAssignedToCommand (commandID)); @@ -145,10 +146,8 @@ String Button::getTooltip() tt << key << ']'; } - return tt; + SettableTooltipClient::setTooltip (tt); } - - return SettableTooltipClient::getTooltip(); } void Button::setConnectedEdges (const int newFlags) @@ -542,6 +541,7 @@ void Button::applicationCommandListChangeCallback() if (commandManagerToUse->getTargetForCommand (commandID, info) != nullptr) { + updateAutomaticTooltip (info); setEnabled ((info.flags & ApplicationCommandInfo::isDisabled) == 0); setToggleState ((info.flags & ApplicationCommandInfo::isTicked) != 0, dontSendNotification); } diff --git a/JuceLibraryCode/modules/juce_gui_basics/buttons/juce_Button.h b/JuceLibraryCode/modules/juce_gui_basics/buttons/juce_Button.h index 2ed85c2..8704e6c 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/buttons/juce_Button.h +++ b/JuceLibraryCode/modules/juce_gui_basics/buttons/juce_Button.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -277,12 +277,6 @@ public: */ void setTooltip (const String& newTooltip) override; - /** Returns the tooltip set by setTooltip(), or the description corresponding to - the currently mapped command if one is enabled (see setCommandToTrigger). - */ - String getTooltip() override; - - //============================================================================== /** A combination of these flags are used by setConnectedEdges(). */ enum ConnectedEdgeFlags @@ -349,6 +343,9 @@ public: */ void setState (ButtonState newState); + /** Returns the button's current over/down/up state. */ + ButtonState getState() const noexcept { return buttonState; } + // This method's parameters have changed - see the new version. JUCE_DEPRECATED (void setToggleState (bool, bool)); @@ -495,6 +492,7 @@ private: void repeatTimerCallback(); bool keyStateChangedCallback(); void applicationCommandListChangeCallback(); + void updateAutomaticTooltip (const ApplicationCommandInfo&); ButtonState updateState(); ButtonState updateState (bool isOver, bool isDown); diff --git a/JuceLibraryCode/modules/juce_gui_basics/buttons/juce_DrawableButton.cpp b/JuceLibraryCode/modules/juce_gui_basics/buttons/juce_DrawableButton.cpp index 23225cf..6bbfc20 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/buttons/juce_DrawableButton.cpp +++ b/JuceLibraryCode/modules/juce_gui_basics/buttons/juce_DrawableButton.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -59,6 +59,7 @@ void DrawableButton::setImages (const Drawable* normal, overImageOn = copyDrawableIfNotNull (overOn); downImageOn = copyDrawableIfNotNull (downOn); disabledImageOn = copyDrawableIfNotNull (disabledOn); + currentImage = nullptr; buttonStateChanged(); } @@ -80,6 +81,31 @@ void DrawableButton::setEdgeIndent (const int numPixelsIndent) resized(); } +Rectangle DrawableButton::getImageBounds() const +{ + Rectangle r (getLocalBounds()); + + if (style != ImageStretched) + { + int indentX = jmin (edgeIndent, proportionOfWidth (0.3f)); + int indentY = jmin (edgeIndent, proportionOfHeight (0.3f)); + + if (style == ImageOnButtonBackground) + { + indentX = jmax (getWidth() / 4, indentX); + indentY = jmax (getHeight() / 4, indentY); + } + else if (style == ImageAboveTextLabel) + { + r = r.withTrimmedBottom (jmin (16, proportionOfHeight (0.25f))); + } + + r = r.reduced (indentX, indentY); + } + + return r.toFloat(); +} + void DrawableButton::resized() { Button::resized(); @@ -87,36 +113,11 @@ void DrawableButton::resized() if (currentImage != nullptr) { if (style == ImageRaw) - { currentImage->setOriginWithOriginalSize (Point()); - } - else if (style == ImageStretched) - { - currentImage->setTransformToFit (getLocalBounds().toFloat(), RectanglePlacement::stretchToFit); - } else - { - Rectangle imageSpace; - - const int indentX = jmin (edgeIndent, proportionOfWidth (0.3f)); - const int indentY = jmin (edgeIndent, proportionOfHeight (0.3f)); - - if (style == ImageOnButtonBackground) - { - imageSpace = getLocalBounds().reduced (jmax (getWidth() / 4, indentX), - jmax (getHeight() / 4, indentY)); - } - else - { - const int textH = (style == ImageAboveTextLabel) ? jmin (16, proportionOfHeight (0.25f)) : 0; - - imageSpace.setBounds (indentX, indentY, - getWidth() - indentX * 2, - getHeight() - indentY * 2 - textH); - } - - currentImage->setTransformToFit (imageSpace.toFloat(), RectanglePlacement::centred); - } + currentImage->setTransformToFit (getImageBounds(), + style == ImageStretched ? RectanglePlacement::stretchToFit + : RectanglePlacement::centred); } } @@ -152,7 +153,7 @@ void DrawableButton::buttonStateChanged() { currentImage->setInterceptsMouseClicks (false, false); addAndMakeVisible (currentImage); - DrawableButton::resized(); + resized(); } } diff --git a/JuceLibraryCode/modules/juce_gui_basics/buttons/juce_DrawableButton.h b/JuceLibraryCode/modules/juce_gui_basics/buttons/juce_DrawableButton.h index 7f9116a..072cbbf 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/buttons/juce_DrawableButton.h +++ b/JuceLibraryCode/modules/juce_gui_basics/buttons/juce_DrawableButton.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -132,6 +132,9 @@ public: /** Returns the image that the button will use when the mouse is held down on it. */ Drawable* getDownImage() const noexcept; + /** Can be overridden to specify a custom position for the image within the button. */ + virtual Rectangle getImageBounds() const; + //============================================================================== /** A set of colour IDs to use to change the colour of various aspects of the link. @@ -173,8 +176,8 @@ public: private: //============================================================================== ButtonStyle style; - ScopedPointer normalImage, overImage, downImage, disabledImage, - normalImageOn, overImageOn, downImageOn, disabledImageOn; + ScopedPointer normalImage, overImage, downImage, disabledImage, + normalImageOn, overImageOn, downImageOn, disabledImageOn; Drawable* currentImage; int edgeIndent; diff --git a/JuceLibraryCode/modules/juce_gui_basics/buttons/juce_HyperlinkButton.cpp b/JuceLibraryCode/modules/juce_gui_basics/buttons/juce_HyperlinkButton.cpp index 8274f4c..f448a1e 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/buttons/juce_HyperlinkButton.cpp +++ b/JuceLibraryCode/modules/juce_gui_basics/buttons/juce_HyperlinkButton.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_gui_basics/buttons/juce_HyperlinkButton.h b/JuceLibraryCode/modules/juce_gui_basics/buttons/juce_HyperlinkButton.h index 4cd3f52..e40dae5 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/buttons/juce_HyperlinkButton.h +++ b/JuceLibraryCode/modules/juce_gui_basics/buttons/juce_HyperlinkButton.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_gui_basics/buttons/juce_ImageButton.cpp b/JuceLibraryCode/modules/juce_gui_basics/buttons/juce_ImageButton.cpp index 3170d05..41a8504 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/buttons/juce_ImageButton.cpp +++ b/JuceLibraryCode/modules/juce_gui_basics/buttons/juce_ImageButton.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_gui_basics/buttons/juce_ImageButton.h b/JuceLibraryCode/modules/juce_gui_basics/buttons/juce_ImageButton.h index 64db59d..fed3cad 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/buttons/juce_ImageButton.h +++ b/JuceLibraryCode/modules/juce_gui_basics/buttons/juce_ImageButton.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_gui_basics/buttons/juce_ShapeButton.cpp b/JuceLibraryCode/modules/juce_gui_basics/buttons/juce_ShapeButton.cpp index 28cd8de..0894e80 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/buttons/juce_ShapeButton.cpp +++ b/JuceLibraryCode/modules/juce_gui_basics/buttons/juce_ShapeButton.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_gui_basics/buttons/juce_ShapeButton.h b/JuceLibraryCode/modules/juce_gui_basics/buttons/juce_ShapeButton.h index ddc4625..624a231 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/buttons/juce_ShapeButton.h +++ b/JuceLibraryCode/modules/juce_gui_basics/buttons/juce_ShapeButton.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_gui_basics/buttons/juce_TextButton.cpp b/JuceLibraryCode/modules/juce_gui_basics/buttons/juce_TextButton.cpp index b51ea65..534a9f4 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/buttons/juce_TextButton.cpp +++ b/JuceLibraryCode/modules/juce_gui_basics/buttons/juce_TextButton.cpp @@ -1,7 +1,8 @@ /* ============================================================================== - file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + + This file is part of the JUCE library. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_gui_basics/buttons/juce_TextButton.h b/JuceLibraryCode/modules/juce_gui_basics/buttons/juce_TextButton.h index b9093b2..161b389 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/buttons/juce_TextButton.h +++ b/JuceLibraryCode/modules/juce_gui_basics/buttons/juce_TextButton.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -102,7 +102,7 @@ public: private: #if JUCE_CATCH_DEPRECATED_CODE_MISUSE - // Note that this method has been removed - instead, see LookAndFeel::getTextButtonWidthToFitText() + // Note that this method has been removed - instead, see LookAndFeel::getTextButtonFont() virtual int getFont() { return 0; } #endif diff --git a/JuceLibraryCode/modules/juce_gui_basics/buttons/juce_ToggleButton.cpp b/JuceLibraryCode/modules/juce_gui_basics/buttons/juce_ToggleButton.cpp index edaf7ab..c9a68d7 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/buttons/juce_ToggleButton.cpp +++ b/JuceLibraryCode/modules/juce_gui_basics/buttons/juce_ToggleButton.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_gui_basics/buttons/juce_ToggleButton.h b/JuceLibraryCode/modules/juce_gui_basics/buttons/juce_ToggleButton.h index 911bc59..8c10fd0 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/buttons/juce_ToggleButton.h +++ b/JuceLibraryCode/modules/juce_gui_basics/buttons/juce_ToggleButton.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_gui_basics/buttons/juce_ToolbarButton.cpp b/JuceLibraryCode/modules/juce_gui_basics/buttons/juce_ToolbarButton.cpp index f7ef1b0..f398f33 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/buttons/juce_ToolbarButton.cpp +++ b/JuceLibraryCode/modules/juce_gui_basics/buttons/juce_ToolbarButton.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_gui_basics/buttons/juce_ToolbarButton.h b/JuceLibraryCode/modules/juce_gui_basics/buttons/juce_ToolbarButton.h index 1f2548f..9721aa8 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/buttons/juce_ToolbarButton.h +++ b/JuceLibraryCode/modules/juce_gui_basics/buttons/juce_ToolbarButton.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_gui_basics/commands/juce_ApplicationCommandID.h b/JuceLibraryCode/modules/juce_gui_basics/commands/juce_ApplicationCommandID.h index 9a00cbc..d24d49e 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/commands/juce_ApplicationCommandID.h +++ b/JuceLibraryCode/modules/juce_gui_basics/commands/juce_ApplicationCommandID.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_gui_basics/commands/juce_ApplicationCommandInfo.cpp b/JuceLibraryCode/modules/juce_gui_basics/commands/juce_ApplicationCommandInfo.cpp index 174ec80..e86ff44 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/commands/juce_ApplicationCommandInfo.cpp +++ b/JuceLibraryCode/modules/juce_gui_basics/commands/juce_ApplicationCommandInfo.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_gui_basics/commands/juce_ApplicationCommandInfo.h b/JuceLibraryCode/modules/juce_gui_basics/commands/juce_ApplicationCommandInfo.h index f906f43..04604f7 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/commands/juce_ApplicationCommandInfo.h +++ b/JuceLibraryCode/modules/juce_gui_basics/commands/juce_ApplicationCommandInfo.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_gui_basics/commands/juce_ApplicationCommandManager.cpp b/JuceLibraryCode/modules/juce_gui_basics/commands/juce_ApplicationCommandManager.cpp index 4f4ff46..0d3a1d0 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/commands/juce_ApplicationCommandManager.cpp +++ b/JuceLibraryCode/modules/juce_gui_basics/commands/juce_ApplicationCommandManager.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -51,7 +51,20 @@ void ApplicationCommandManager::registerCommand (const ApplicationCommandInfo& n // the name isn't optional! jassert (newCommand.shortName.isNotEmpty()); - if (getCommandForID (newCommand.commandID) == 0) + if (ApplicationCommandInfo* command = getMutableCommandForID (newCommand.commandID)) + { + // Trying to re-register the same command ID with different parameters can often indicate a typo. + // This assertion is here because I've found it useful catching some mistakes, but it may also cause + // false alarms if you're deliberately updating some flags for a command. + jassert (newCommand.shortName == getCommandForID (newCommand.commandID)->shortName + && newCommand.categoryName == getCommandForID (newCommand.commandID)->categoryName + && newCommand.defaultKeypresses == getCommandForID (newCommand.commandID)->defaultKeypresses + && (newCommand.flags & (ApplicationCommandInfo::wantsKeyUpDownCallbacks | ApplicationCommandInfo::hiddenFromKeyEditor | ApplicationCommandInfo::readOnlyInKeyEditor)) + == (getCommandForID (newCommand.commandID)->flags & (ApplicationCommandInfo::wantsKeyUpDownCallbacks | ApplicationCommandInfo::hiddenFromKeyEditor | ApplicationCommandInfo::readOnlyInKeyEditor))); + + *command = newCommand; + } + else { ApplicationCommandInfo* const newInfo = new ApplicationCommandInfo (newCommand); newInfo->flags &= ~ApplicationCommandInfo::isTicked; @@ -61,16 +74,6 @@ void ApplicationCommandManager::registerCommand (const ApplicationCommandInfo& n triggerAsyncUpdate(); } - else - { - // trying to re-register the same command ID with different parameters? - jassert (newCommand.shortName == getCommandForID (newCommand.commandID)->shortName - && (newCommand.description == getCommandForID (newCommand.commandID)->description || newCommand.description.isEmpty()) - && newCommand.categoryName == getCommandForID (newCommand.commandID)->categoryName - && newCommand.defaultKeypresses == getCommandForID (newCommand.commandID)->defaultKeypresses - && (newCommand.flags & (ApplicationCommandInfo::wantsKeyUpDownCallbacks | ApplicationCommandInfo::hiddenFromKeyEditor | ApplicationCommandInfo::readOnlyInKeyEditor)) - == (getCommandForID (newCommand.commandID)->flags & (ApplicationCommandInfo::wantsKeyUpDownCallbacks | ApplicationCommandInfo::hiddenFromKeyEditor | ApplicationCommandInfo::readOnlyInKeyEditor))); - } } void ApplicationCommandManager::registerAllCommandsForTarget (ApplicationCommandTarget* target) @@ -113,7 +116,7 @@ void ApplicationCommandManager::commandStatusChanged() } //============================================================================== -const ApplicationCommandInfo* ApplicationCommandManager::getCommandForID (const CommandID commandID) const noexcept +ApplicationCommandInfo* ApplicationCommandManager::getMutableCommandForID (CommandID commandID) const noexcept { for (int i = commands.size(); --i >= 0;) if (commands.getUnchecked(i)->commandID == commandID) @@ -122,6 +125,11 @@ const ApplicationCommandInfo* ApplicationCommandManager::getCommandForID (const return nullptr; } +const ApplicationCommandInfo* ApplicationCommandManager::getCommandForID (const CommandID commandID) const noexcept +{ + return getMutableCommandForID (commandID); +} + String ApplicationCommandManager::getNameOfCommand (const CommandID commandID) const noexcept { if (const ApplicationCommandInfo* const ci = getCommandForID (commandID)) @@ -215,7 +223,10 @@ ApplicationCommandTarget* ApplicationCommandManager::getTargetForCommand (const target = target->getTargetForCommand (commandID); if (target != nullptr) + { + upToDateInfo.commandID = commandID; target->getCommandInfo (commandID, upToDateInfo); + } return target; } @@ -223,7 +234,7 @@ ApplicationCommandTarget* ApplicationCommandManager::getTargetForCommand (const //============================================================================== ApplicationCommandTarget* ApplicationCommandManager::findTargetForComponent (Component* c) { - ApplicationCommandTarget* target = dynamic_cast (c); + ApplicationCommandTarget* target = dynamic_cast (c); if (target == nullptr && c != nullptr) target = c->findParentComponentOfClass(); @@ -263,7 +274,7 @@ ApplicationCommandTarget* ApplicationCommandManager::findDefaultComponentTarget( // component that really should get the event. And if not, the event will // still be passed up to the top level window anyway, so let's send it to the // content comp. - if (ResizableWindow* const resizableWindow = dynamic_cast (c)) + if (ResizableWindow* const resizableWindow = dynamic_cast (c)) if (Component* const content = resizableWindow->getContentComponent()) c = content; diff --git a/JuceLibraryCode/modules/juce_gui_basics/commands/juce_ApplicationCommandManager.h b/JuceLibraryCode/modules/juce_gui_basics/commands/juce_ApplicationCommandManager.h index 1d6158e..4ace284 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/commands/juce_ApplicationCommandManager.h +++ b/JuceLibraryCode/modules/juce_gui_basics/commands/juce_ApplicationCommandManager.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -154,7 +154,7 @@ public: This will search the list of registered commands for one with the given command ID number, and return its associated info. If no matching command is found, this - will return 0. + will return nullptr. */ const ApplicationCommandInfo* getCommandForID (CommandID commandID) const noexcept; @@ -308,6 +308,7 @@ private: void sendListenerInvokeCallback (const ApplicationCommandTarget::InvocationInfo&); void handleAsyncUpdate() override; void globalFocusChanged (Component*) override; + ApplicationCommandInfo* getMutableCommandForID (CommandID) const noexcept; #if JUCE_CATCH_DEPRECATED_CODE_MISUSE // This is just here to cause a compile error in old code that hasn't been changed to use the new diff --git a/JuceLibraryCode/modules/juce_gui_basics/commands/juce_ApplicationCommandTarget.cpp b/JuceLibraryCode/modules/juce_gui_basics/commands/juce_ApplicationCommandTarget.cpp index c31d187..734def2 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/commands/juce_ApplicationCommandTarget.cpp +++ b/JuceLibraryCode/modules/juce_gui_basics/commands/juce_ApplicationCommandTarget.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_gui_basics/commands/juce_ApplicationCommandTarget.h b/JuceLibraryCode/modules/juce_gui_basics/commands/juce_ApplicationCommandTarget.h index c14faa8..b65218d 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/commands/juce_ApplicationCommandTarget.h +++ b/JuceLibraryCode/modules/juce_gui_basics/commands/juce_ApplicationCommandTarget.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_gui_basics/commands/juce_KeyPressMappingSet.cpp b/JuceLibraryCode/modules/juce_gui_basics/commands/juce_KeyPressMappingSet.cpp index b37a981..aa52f0c 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/commands/juce_KeyPressMappingSet.cpp +++ b/JuceLibraryCode/modules/juce_gui_basics/commands/juce_KeyPressMappingSet.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -252,7 +252,7 @@ bool KeyPressMappingSet::restoreFromXml (const XmlElement& xmlVersion) XmlElement* KeyPressMappingSet::createXml (const bool saveDifferencesFromDefaultSet) const { - ScopedPointer defaultSet; + ScopedPointer defaultSet; if (saveDifferencesFromDefaultSet) { diff --git a/JuceLibraryCode/modules/juce_gui_basics/commands/juce_KeyPressMappingSet.h b/JuceLibraryCode/modules/juce_gui_basics/commands/juce_KeyPressMappingSet.h index d3351ac..315de8f 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/commands/juce_KeyPressMappingSet.h +++ b/JuceLibraryCode/modules/juce_gui_basics/commands/juce_KeyPressMappingSet.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_gui_basics/components/juce_CachedComponentImage.h b/JuceLibraryCode/modules/juce_gui_basics/components/juce_CachedComponentImage.h index 3f273cb..e9be2c6 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/components/juce_CachedComponentImage.h +++ b/JuceLibraryCode/modules/juce_gui_basics/components/juce_CachedComponentImage.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_gui_basics/components/juce_Component.cpp b/JuceLibraryCode/modules/juce_gui_basics/components/juce_Component.cpp index 8734ad7..1f00cac 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/components/juce_Component.cpp +++ b/JuceLibraryCode/modules/juce_gui_basics/components/juce_Component.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -22,12 +22,6 @@ ============================================================================== */ -#define CHECK_MESSAGE_MANAGER_IS_LOCKED \ - jassert (MessageManager::getInstance()->currentThreadHasLockedMessageManager()); - -#define CHECK_MESSAGE_MANAGER_IS_LOCKED_OR_OFFSCREEN \ - jassert (MessageManager::getInstance()->currentThreadHasLockedMessageManager() || getPeer() == nullptr); - Component* Component::currentlyFocusedComponent = nullptr; @@ -147,7 +141,7 @@ public: } private: - Array listeners; + Array listeners; int numDeepMouseListeners; class BailOutChecker2 @@ -160,7 +154,7 @@ private: bool shouldBailOut() const noexcept { - return checker.shouldBailOut() || safePointer == 0; + return checker.shouldBailOut() || safePointer == nullptr; } private: @@ -206,7 +200,7 @@ struct ScalingHelpers // For these, we need to avoid getSmallestIntegerContainer being used, which causes // judder when moving windows - static Rectangle unscaledScreenPosToScaled (float scale, const Rectangle& pos) noexcept + static Rectangle unscaledScreenPosToScaled (float scale, Rectangle pos) noexcept { return scale != 1.0f ? Rectangle (roundToInt (pos.getX() / scale), roundToInt (pos.getY() / scale), @@ -214,7 +208,7 @@ struct ScalingHelpers roundToInt (pos.getHeight() / scale)) : pos; } - static Rectangle scaledScreenPosToUnscaled (float scale, Rectangle& pos) noexcept + static Rectangle scaledScreenPosToUnscaled (float scale, Rectangle pos) noexcept { return scale != 1.0f ? Rectangle (roundToInt (pos.getX() * scale), roundToInt (pos.getY() * scale), @@ -245,6 +239,15 @@ struct ScalingHelpers { return scaledScreenPosToUnscaled (comp.getDesktopScaleFactor(), pos); } + + static Point addPosition (Point p, const Component& c) noexcept { return p + c.getPosition(); } + static Rectangle addPosition (Rectangle p, const Component& c) noexcept { return p + c.getPosition(); } + static Point addPosition (Point p, const Component& c) noexcept { return p + c.getPosition().toFloat(); } + static Rectangle addPosition (Rectangle p, const Component& c) noexcept { return p + c.getPosition().toFloat(); } + static Point subtractPosition (Point p, const Component& c) noexcept { return p - c.getPosition(); } + static Rectangle subtractPosition (Rectangle p, const Component& c) noexcept { return p - c.getPosition(); } + static Point subtractPosition (Point p, const Component& c) noexcept { return p - c.getPosition().toFloat(); } + static Rectangle subtractPosition (Rectangle p, const Component& c) noexcept { return p - c.getPosition().toFloat(); } }; //============================================================================== @@ -253,7 +256,7 @@ struct Component::ComponentHelpers #if JUCE_MODAL_LOOPS_PERMITTED static void* runModalLoopCallback (void* userData) { - return (void*) (pointer_sized_int) static_cast (userData)->runModalLoop(); + return (void*) (pointer_sized_int) static_cast (userData)->runModalLoop(); } #endif @@ -327,7 +330,7 @@ struct Component::ComponentHelpers } else { - pointInParentSpace -= comp.getPosition(); + pointInParentSpace = ScalingHelpers::subtractPosition (pointInParentSpace, comp); } return pointInParentSpace; @@ -346,7 +349,7 @@ struct Component::ComponentHelpers } else { - pointInLocalSpace += comp.getPosition(); + pointInLocalSpace = ScalingHelpers::addPosition (pointInLocalSpace, comp); } if (comp.affineTransform != nullptr) @@ -396,17 +399,7 @@ struct Component::ComponentHelpers return convertFromDistantParentSpace (topLevelComp, *target, p); } - static Rectangle getUnclippedArea (const Component& comp) - { - Rectangle r (comp.getLocalBounds()); - - if (Component* const p = comp.getParentComponent()) - r = r.getIntersection (convertFromParentSpace (comp, getUnclippedArea (*p))); - - return r; - } - - static bool clipObscuredRegions (const Component& comp, Graphics& g, const Rectangle& clipRect, Point delta) + static bool clipObscuredRegions (const Component& comp, Graphics& g, const Rectangle clipRect, Point delta) { bool nothingChanged = true; @@ -438,35 +431,6 @@ struct Component::ComponentHelpers return nothingChanged; } - static void subtractObscuredRegions (const Component& comp, RectangleList& result, - Point delta, const Rectangle& clipRect, - const Component* const compToAvoid) - { - for (int i = comp.childComponentList.size(); --i >= 0;) - { - const Component* const c = comp.childComponentList.getUnchecked(i); - - if (c != compToAvoid && c->isVisible()) - { - if (c->isOpaque() && c->componentTransparency == 0) - { - Rectangle childBounds (c->bounds.getIntersection (clipRect)); - childBounds.translate (delta.x, delta.y); - - result.subtract (childBounds); - } - else - { - Rectangle newClip (clipRect.getIntersection (c->bounds)); - newClip.translate (-c->getX(), -c->getY()); - - subtractObscuredRegions (*c, result, c->getPosition() + delta, - newClip, compToAvoid); - } - } - } - } - static Rectangle getParentOrMainMonitorBounds (const Component& comp) { if (Component* p = comp.getParentComponent()) @@ -477,7 +441,7 @@ struct Component::ComponentHelpers }; //============================================================================== -Component::Component() +Component::Component() noexcept : parentComponent (nullptr), lookAndFeel (nullptr), effect (nullptr), @@ -486,7 +450,7 @@ Component::Component() { } -Component::Component (const String& name) +Component::Component (const String& name) noexcept : componentName (name), parentComponent (nullptr), lookAndFeel (nullptr), @@ -524,7 +488,7 @@ void Component::setName (const String& name) { // if component methods are being called from threads other than the message // thread, you'll need to use a MessageManagerLock object to make sure it's thread-safe. - CHECK_MESSAGE_MANAGER_IS_LOCKED_OR_OFFSCREEN + ASSERT_MESSAGE_MANAGER_IS_LOCKED_OR_OFFSCREEN if (componentName != name) { @@ -550,7 +514,7 @@ void Component::setVisible (bool shouldBeVisible) { // if component methods are being called from threads other than the message // thread, you'll need to use a MessageManagerLock object to make sure it's thread-safe. - CHECK_MESSAGE_MANAGER_IS_LOCKED_OR_OFFSCREEN + ASSERT_MESSAGE_MANAGER_IS_LOCKED_OR_OFFSCREEN const WeakReference safePointer (this); flags.visibleFlag = shouldBeVisible; @@ -617,7 +581,6 @@ bool Component::isShowing() const return false; } - //============================================================================== void* Component::getWindowHandle() const { @@ -632,7 +595,7 @@ void Component::addToDesktop (int styleWanted, void* nativeWindowToAttachTo) { // if component methods are being called from threads other than the message // thread, you'll need to use a MessageManagerLock object to make sure it's thread-safe. - CHECK_MESSAGE_MANAGER_IS_LOCKED + ASSERT_MESSAGE_MANAGER_IS_LOCKED if (isOpaque()) styleWanted &= ~ComponentPeer::windowIsSemiTransparent; @@ -732,7 +695,7 @@ void Component::removeFromDesktop() { // if component methods are being called from threads other than the message // thread, you'll need to use a MessageManagerLock object to make sure it's thread-safe. - CHECK_MESSAGE_MANAGER_IS_LOCKED_OR_OFFSCREEN + ASSERT_MESSAGE_MANAGER_IS_LOCKED_OR_OFFSCREEN if (flags.hasHeavyweightPeerFlag) { @@ -821,6 +784,7 @@ public: validArea.clear(); } + if (! validArea.containsRectangle (compBounds)) { Graphics imG (image); LowLevelGraphicsContext& lg = imG.getInternalContext(); @@ -828,18 +792,15 @@ public: for (const Rectangle* i = validArea.begin(), * const e = validArea.end(); i != e; ++i) lg.excludeClipRectangle (*i); - if (! lg.isClipEmpty()) + if (! owner.isOpaque()) { - if (! owner.isOpaque()) - { - lg.setFill (Colours::transparentBlack); - lg.fillRect (imageBounds, true); - lg.setFill (Colours::black); - } - - lg.addTransform (AffineTransform::scale (scale)); - owner.paintEntireComponent (imG, true); + lg.setFill (Colours::transparentBlack); + lg.fillRect (imageBounds, true); + lg.setFill (Colours::black); } + + lg.addTransform (AffineTransform::scale (scale)); + owner.paintEntireComponent (imG, true); } validArea = imageBounds; @@ -877,7 +838,7 @@ void Component::setBufferedToImage (const bool shouldBeBuffered) // so by calling setBufferedToImage, you'll be deleting the custom one - this is almost certainly // not what you wanted to happen... If you really do know what you're doing here, and want to // avoid this assertion, just call setCachedComponentImage (nullptr) before setBufferedToImage(). - jassert (cachedImage == nullptr || dynamic_cast (cachedImage.get()) != nullptr); + jassert (cachedImage == nullptr || dynamic_cast (cachedImage.get()) != nullptr); if (shouldBeBuffered) { @@ -910,7 +871,7 @@ void Component::toFront (const bool setAsForeground) { // if component methods are being called from threads other than the message // thread, you'll need to use a MessageManagerLock object to make sure it's thread-safe. - CHECK_MESSAGE_MANAGER_IS_LOCKED_OR_OFFSCREEN + ASSERT_MESSAGE_MANAGER_IS_LOCKED_OR_OFFSCREEN if (flags.hasHeavyweightPeerFlag) { @@ -1092,6 +1053,11 @@ Point Component::getLocalPoint (const Component* source, Point point) return ComponentHelpers::convertCoordinate (this, source, point); } +Point Component::getLocalPoint (const Component* source, Point point) const +{ + return ComponentHelpers::convertCoordinate (this, source, point); +} + Rectangle Component::getLocalArea (const Component* source, const Rectangle& area) const { return ComponentHelpers::convertCoordinate (this, source, area); @@ -1102,6 +1068,11 @@ Point Component::localPointToGlobal (Point point) const return ComponentHelpers::convertCoordinate (nullptr, this, point); } +Point Component::localPointToGlobal (Point point) const +{ + return ComponentHelpers::convertCoordinate (nullptr, this, point); +} + Rectangle Component::localAreaToGlobal (const Rectangle& area) const { return ComponentHelpers::convertCoordinate (nullptr, this, area); @@ -1130,7 +1101,7 @@ void Component::setBounds (const int x, const int y, int w, int h) { // if component methods are being called from threads other than the message // thread, you'll need to use a MessageManagerLock object to make sure it's thread-safe. - CHECK_MESSAGE_MANAGER_IS_LOCKED_OR_OFFSCREEN + ASSERT_MESSAGE_MANAGER_IS_LOCKED_OR_OFFSCREEN if (w < 0) w = 0; if (h < 0) h = 0; @@ -1169,10 +1140,27 @@ void Component::setBounds (const int x, const int y, int w, int h) cachedImage->invalidateAll(); } + flags.isMoveCallbackPending = wasMoved; + flags.isResizeCallbackPending = wasResized; + if (flags.hasHeavyweightPeerFlag) if (ComponentPeer* const peer = getPeer()) peer->updateBounds(); + sendMovedResizedMessagesIfPending(); + } +} + +void Component::sendMovedResizedMessagesIfPending() +{ + const bool wasMoved = flags.isMoveCallbackPending; + const bool wasResized = flags.isResizeCallbackPending; + + if (wasMoved || wasResized) + { + flags.isMoveCallbackPending = false; + flags.isResizeCallbackPending = false; + sendMovedResizedMessages (wasMoved, wasResized); } } @@ -1463,7 +1451,7 @@ void Component::addChildComponent (Component& child, int zOrder) { // if component methods are being called from threads other than the message // thread, you'll need to use a MessageManagerLock object to make sure it's thread-safe. - CHECK_MESSAGE_MANAGER_IS_LOCKED_OR_OFFSCREEN + ASSERT_MESSAGE_MANAGER_IS_LOCKED_OR_OFFSCREEN if (child.parentComponent != this) { @@ -1539,7 +1527,7 @@ Component* Component::removeChildComponent (const int index, bool sendParentEven { // if component methods are being called from threads other than the message // thread, you'll need to use a MessageManagerLock object to make sure it's thread-safe. - CHECK_MESSAGE_MANAGER_IS_LOCKED_OR_OFFSCREEN + ASSERT_MESSAGE_MANAGER_IS_LOCKED_OR_OFFSCREEN Component* const child = childComponentList [index]; @@ -1616,7 +1604,7 @@ Component* Component::getChildComponent (const int index) const noexcept int Component::getIndexOfChildComponent (const Component* const child) const noexcept { - return childComponentList.indexOf (const_cast (child)); + return childComponentList.indexOf (const_cast (child)); } Component* Component::findChildWithID (StringRef targetID) const noexcept @@ -1638,7 +1626,7 @@ Component* Component::getTopLevelComponent() const noexcept while (comp->parentComponent != nullptr) comp = comp->parentComponent; - return const_cast (comp); + return const_cast (comp); } bool Component::isParentOf (const Component* possibleChild) const noexcept @@ -1730,7 +1718,7 @@ void Component::enterModalState (const bool shouldTakeKeyboardFocus, { // if component methods are being called from threads other than the message // thread, you'll need to use a MessageManagerLock object to make sure it's thread-safe. - CHECK_MESSAGE_MANAGER_IS_LOCKED + ASSERT_MESSAGE_MANAGER_IS_LOCKED // Check for an attempt to make a component modal when it already is! // This can cause nasty problems.. @@ -1896,15 +1884,15 @@ void Component::repaintParent() parentComponent->internalRepaint (ComponentHelpers::convertToParentSpace (*this, getLocalBounds())); } -void Component::internalRepaint (const Rectangle& area) +void Component::internalRepaint (Rectangle area) { - const Rectangle r (area.getIntersection (getLocalBounds())); + area = area.getIntersection (getLocalBounds()); - if (! r.isEmpty()) - internalRepaintUnchecked (r, false); + if (! area.isEmpty()) + internalRepaintUnchecked (area, false); } -void Component::internalRepaintUnchecked (const Rectangle& area, const bool isEntireComponent) +void Component::internalRepaintUnchecked (Rectangle area, const bool isEntireComponent) { if (flags.visibleFlag) { @@ -1917,7 +1905,7 @@ void Component::internalRepaintUnchecked (const Rectangle& area, const bool { // if component methods are being called from threads other than the message // thread, you'll need to use a MessageManagerLock object to make sure it's thread-safe. - CHECK_MESSAGE_MANAGER_IS_LOCKED + ASSERT_MESSAGE_MANAGER_IS_LOCKED if (ComponentPeer* const peer = getPeer()) { @@ -2034,6 +2022,14 @@ void Component::paintComponentAndChildren (Graphics& g) void Component::paintEntireComponent (Graphics& g, const bool ignoreAlphaLevel) { + // If sizing a top-level-window and the OS paint message is delivered synchronously + // before resized() is called, then we'll invoke the callback here, to make sure + // the components inside have had a chance to sort their sizes out.. + #if JUCE_DEBUG + if (! flags.isInsidePaintCall) // (avoids an assertion in plugins hosted in WaveLab) + #endif + sendMovedResizedMessagesIfPending(); + #if JUCE_DEBUG flags.isInsidePaintCall = true; #endif @@ -2170,7 +2166,7 @@ void Component::sendLookAndFeelChange() Colour Component::findColour (const int colourId, const bool inheritFromParent) const { if (const var* const v = properties.getVarPointer (ComponentHelpers::getColourPropertyId (colourId))) - return Colour ((uint32) static_cast (*v)); + return Colour ((uint32) static_cast (*v)); if (inheritFromParent && parentComponent != nullptr && (lookAndFeel == nullptr || ! lookAndFeel->isColourSpecified (colourId))) @@ -2249,28 +2245,6 @@ Rectangle Component::getBoundsInParent() const noexcept : bounds.transformedBy (*affineTransform); } -void Component::getVisibleArea (RectangleList& result, const bool includeSiblings) const -{ - result.clear(); - const Rectangle unclipped (ComponentHelpers::getUnclippedArea (*this)); - - if (! unclipped.isEmpty()) - { - result.add (unclipped); - - if (includeSiblings) - { - const Component* const c = getTopLevelComponent(); - - ComponentHelpers::subtractObscuredRegions (*c, result, getLocalPoint (c, Point()), - c->getLocalBounds(), this); - } - - ComponentHelpers::subtractObscuredRegions (*this, result, Point(), unclipped, nullptr); - result.consolidate(); - } -} - //============================================================================== void Component::mouseEnter (const MouseEvent&) {} void Component::mouseExit (const MouseEvent&) {} @@ -2306,7 +2280,7 @@ void Component::addComponentListener (ComponentListener* const newListener) // thread, you'll need to use a MessageManagerLock object to make sure it's thread-safe. #if JUCE_DEBUG || JUCE_LOG_ASSERTIONS if (getParentComponent() != nullptr) - CHECK_MESSAGE_MANAGER_IS_LOCKED; + ASSERT_MESSAGE_MANAGER_IS_LOCKED; #endif componentListeners.add (newListener); @@ -2338,16 +2312,15 @@ void Component::internalModalInputAttempt() //============================================================================== void Component::postCommandMessage (const int commandId) { - class CustomCommandMessage : public CallbackMessage + struct CustomCommandMessage : public CallbackMessage { - public: CustomCommandMessage (Component* const c, const int command) : target (c), commandId (command) {} void messageCallback() override { - if (target.get() != nullptr) // (get() required for VS2003 bug) - target->handleCommandMessage (commandId); + if (Component* c = target.get()) + c->handleCommandMessage (commandId); } private: @@ -2369,7 +2342,7 @@ void Component::addMouseListener (MouseListener* const newListener, { // if component methods are being called from threads other than the message // thread, you'll need to use a MessageManagerLock object to make sure it's thread-safe. - CHECK_MESSAGE_MANAGER_IS_LOCKED + ASSERT_MESSAGE_MANAGER_IS_LOCKED // If you register a component as a mouselistener for itself, it'll receive all the events // twice - once via the direct callback that all components get anyway, and then again as a listener! @@ -2385,14 +2358,14 @@ void Component::removeMouseListener (MouseListener* const listenerToRemove) { // if component methods are being called from threads other than the message // thread, you'll need to use a MessageManagerLock object to make sure it's thread-safe. - CHECK_MESSAGE_MANAGER_IS_LOCKED + ASSERT_MESSAGE_MANAGER_IS_LOCKED if (mouseListeners != nullptr) mouseListeners->removeListener (listenerToRemove); } //============================================================================== -void Component::internalMouseEnter (MouseInputSource source, Point relativePos, Time time) +void Component::internalMouseEnter (MouseInputSource source, Point relativePos, Time time) { if (isCurrentlyBlockedByAnotherModalComponent()) { @@ -2418,7 +2391,7 @@ void Component::internalMouseEnter (MouseInputSource source, Point relative MouseListenerList::sendMouseEvent (*this, checker, &MouseListener::mouseEnter, me); } -void Component::internalMouseExit (MouseInputSource source, Point relativePos, Time time) +void Component::internalMouseExit (MouseInputSource source, Point relativePos, Time time) { if (flags.repaintOnMouseActivityFlag) repaint(); @@ -2438,7 +2411,7 @@ void Component::internalMouseExit (MouseInputSource source, Point relativeP MouseListenerList::sendMouseEvent (*this, checker, &MouseListener::mouseExit, me); } -void Component::internalMouseDown (MouseInputSource source, Point relativePos, Time time) +void Component::internalMouseDown (MouseInputSource source, Point relativePos, Time time) { Desktop& desktop = Desktop::getInstance(); BailOutChecker checker (this); @@ -2502,7 +2475,7 @@ void Component::internalMouseDown (MouseInputSource source, Point relativeP MouseListenerList::sendMouseEvent (*this, checker, &MouseListener::mouseDown, me); } -void Component::internalMouseUp (MouseInputSource source, Point relativePos, +void Component::internalMouseUp (MouseInputSource source, Point relativePos, Time time, const ModifierKeys oldModifiers) { if (flags.mouseDownWasBlocked && isCurrentlyBlockedByAnotherModalComponent()) @@ -2545,7 +2518,7 @@ void Component::internalMouseUp (MouseInputSource source, Point relativePos } } -void Component::internalMouseDrag (MouseInputSource source, Point relativePos, Time time) +void Component::internalMouseDrag (MouseInputSource source, Point relativePos, Time time) { if (! isCurrentlyBlockedByAnotherModalComponent()) { @@ -2568,7 +2541,7 @@ void Component::internalMouseDrag (MouseInputSource source, Point relativeP } } -void Component::internalMouseMove (MouseInputSource source, Point relativePos, Time time) +void Component::internalMouseMove (MouseInputSource source, Point relativePos, Time time) { Desktop& desktop = Desktop::getInstance(); @@ -2594,7 +2567,7 @@ void Component::internalMouseMove (MouseInputSource source, Point relativeP } } -void Component::internalMouseWheel (MouseInputSource source, Point relativePos, +void Component::internalMouseWheel (MouseInputSource source, Point relativePos, Time time, const MouseWheelDetails& wheel) { Desktop& desktop = Desktop::getInstance(); @@ -2622,7 +2595,7 @@ void Component::internalMouseWheel (MouseInputSource source, Point relative } } -void Component::internalMagnifyGesture (MouseInputSource source, Point relativePos, +void Component::internalMagnifyGesture (MouseInputSource source, Point relativePos, Time time, float amount) { if (! isCurrentlyBlockedByAnotherModalComponent()) @@ -2821,7 +2794,7 @@ void Component::grabFocusInternal (const FocusChangeType cause, const bool canTr else { // find the default child component.. - ScopedPointer traverser (createFocusTraverser()); + ScopedPointer traverser (createFocusTraverser()); if (traverser != nullptr) { @@ -2850,7 +2823,7 @@ void Component::grabKeyboardFocus() { // if component methods are being called from threads other than the message // thread, you'll need to use a MessageManagerLock object to make sure it's thread-safe. - CHECK_MESSAGE_MANAGER_IS_LOCKED + ASSERT_MESSAGE_MANAGER_IS_LOCKED grabFocusInternal (focusChangedDirectly, true); } @@ -2859,11 +2832,11 @@ void Component::moveKeyboardFocusToSibling (const bool moveToNext) { // if component methods are being called from threads other than the message // thread, you'll need to use a MessageManagerLock object to make sure it's thread-safe. - CHECK_MESSAGE_MANAGER_IS_LOCKED + ASSERT_MESSAGE_MANAGER_IS_LOCKED if (parentComponent != nullptr) { - ScopedPointer traverser (createFocusTraverser()); + ScopedPointer traverser (createFocusTraverser()); if (traverser != nullptr) { @@ -2972,7 +2945,7 @@ bool Component::isMouseOver (const bool includeChildren) const Component* const c = mi->getComponentUnderMouse(); if ((c == this || (includeChildren && isParentOf (c))) - && c->reallyContains (c->getLocalPoint (nullptr, mi->getScreenPosition()), false) + && c->reallyContains (c->getLocalPoint (nullptr, mi->getScreenPosition()).roundToInt(), false) && (mi->isMouse() || mi->isDragging())) return true; } @@ -3017,7 +2990,7 @@ Point Component::getMouseXYRelative() const void Component::addKeyListener (KeyListener* const newListener) { if (keyListeners == nullptr) - keyListeners = new Array (); + keyListeners = new Array(); keyListeners->addIfNotAlreadyThere (newListener); } diff --git a/JuceLibraryCode/modules/juce_gui_basics/components/juce_Component.h b/JuceLibraryCode/modules/juce_gui_basics/components/juce_Component.h index 1bc092e..f510e5c 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/components/juce_Component.h +++ b/JuceLibraryCode/modules/juce_gui_basics/components/juce_Component.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -46,7 +46,7 @@ public: subclass of Component or use one of the other types of component from the library. */ - Component(); + Component() noexcept; /** Destructor. @@ -66,7 +66,7 @@ public: /** Creates a component, setting its name at the same time. @see getName, setName */ - explicit Component (const String& componentName); + explicit Component (const String& componentName) noexcept; /** Returns the name of this component. @see setName @@ -315,16 +315,6 @@ public: */ Rectangle getBoundsInParent() const noexcept; - /** Returns the region of this component that's not obscured by other, opaque components. - - The RectangleList that is returned represents the area of this component - which isn't covered by opaque child components. - - If includeSiblings is true, it will also take into account any siblings - that may be overlapping the component. - */ - void getVisibleArea (RectangleList& result, bool includeSiblings) const; - //============================================================================== /** Returns this component's x coordinate relative the screen's top-left origin. @see getX, localPointToGlobal @@ -355,6 +345,15 @@ public: Point getLocalPoint (const Component* sourceComponent, Point pointRelativeToSourceComponent) const; + /** Converts a point to be relative to this component's coordinate space. + + This takes a point relative to a different component, and returns its position relative to this + component. If the sourceComponent parameter is null, the source point is assumed to be a global + screen coordinate. + */ + Point getLocalPoint (const Component* sourceComponent, + Point pointRelativeToSourceComponent) const; + /** Converts a rectangle to be relative to this component's coordinate space. This takes a rectangle that is relative to a different component, and returns its position relative @@ -373,6 +372,11 @@ public: */ Point localPointToGlobal (Point localPoint) const; + /** Converts a point relative to this component's top-left into a screen coordinate. + @see getLocalPoint, localAreaToGlobal + */ + Point localPointToGlobal (Point localPoint) const; + /** Converts a rectangle from this component's coordinate space to a screen coordinate. If you've used setTransform() to apply one or more transforms to components, then the source rectangle @@ -439,7 +443,7 @@ public: /** Changes the component's position and size. The coordinates are relative to the top-left of the component's parent, or relative - to the origin of the screen is the component is on the desktop. + to the origin of the screen if the component is on the desktop. If this method changes the component's top-left position, it will make a synchronous call to moved(). If it changes the size, it will also make a call to resized(). @@ -455,7 +459,7 @@ public: /** Changes the component's position and size. The coordinates are relative to the top-left of the component's parent, or relative - to the origin of the screen is the component is on the desktop. + to the origin of the screen if the component is on the desktop. If this method changes the component's top-left position, it will make a synchronous call to moved(). If it changes the size, it will also make a call to resized(). @@ -476,42 +480,10 @@ public: component's bounds when the source values change. See RelativeRectangle::applyToComponent() for more details. - When using relative expressions, the following symbols are available: - - "left", "right", "top", "bottom" refer to the position of those edges in this component, so - e.g. for a component whose width is always 100, you might set the right edge to the "left + 100". - - "[id].left", "[id].right", "[id].top", "[id].bottom", "[id].width", "[id].height", where [id] is - the identifier of one of this component's siblings. A component's identifier is set with - Component::setComponentID(). So for example if you want your component to always be 50 pixels to the - right of the one called "xyz", you could set your left edge to be "xyz.right + 50". - - Instead of an [id], you can use the name "parent" to refer to this component's parent. Like - any other component, these values are relative to their component's parent, so "parent.right" won't be - very useful for positioning a component because it refers to a position with the parent's parent.. but - "parent.width" can be used for setting positions relative to the parent's size. E.g. to make a 10x10 - component which remains 1 pixel away from its parent's bottom-right, you could use - "right - 10, bottom - 10, parent.width - 1, parent.height - 1". - - The name of one of the parent component's markers can also be used as a symbol. For markers to be - used, the parent component must implement its Component::getMarkers() method, and return at least one - valid MarkerList. So if you want your component's top edge to be 10 pixels below the - marker called "foobar", you'd set it to "foobar + 10". + For the syntax of the expressions that are allowed in the string, see the notes + for the RelativeCoordinate class. - See the Expression class for details about the operators that are supported, but for example - if you wanted to make your component remain centred within its parent with a size of 100, 100, - you could express it as: - @code myComp.setBounds (RelativeBounds ("parent.width / 2 - 50, parent.height / 2 - 50, left + 100, top + 100")); - @endcode - ..or an alternative way to achieve the same thing: - @code myComp.setBounds (RelativeBounds ("right - 100, bottom - 100, parent.width / 2 + 50, parent.height / 2 + 50")); - @endcode - - Or if you wanted a 100x100 component whose top edge is lined up to a marker called "topMarker" and - which is positioned 50 pixels to the right of another component called "otherComp", you could write: - @code myComp.setBounds (RelativeBounds ("otherComp.right + 50, topMarker, left + 100, top + 100")); - @endcode - - Be careful not to make your coordinate expressions recursive, though, or exceptions and assertions will - be thrown! - - @see setBounds, RelativeRectangle::applyToComponent(), Expression + @see RelativeCoordinate, setBounds, RelativeRectangle::applyToComponent(), Expression */ void setBounds (const RelativeRectangle& newBounds); @@ -771,7 +743,13 @@ public: */ void removeAllChildren(); - /** Removes all this component's children, and deletes them. + /** Removes and deletes all of this component's children. + My advice is to avoid this method! It's an old function that is only kept here for + backwards-compatibility with legacy code, and should be viewed with extreme + suspicion by anyone attempting to write modern C++. In almost all cases, it's much + smarter to manage the lifetimes of your child components via modern RAII techniques + such as simply making them member variables, or using ScopedPointer, OwnedArray, etc + to manage their lifetimes appropriately. @see removeAllChildren */ void deleteAllChildren(); @@ -786,14 +764,14 @@ public: /** Searches the parent components for a component of a specified class. For example findParentComponentOfClass \() would return the first parent - component that can be dynamically cast to a MyComp, or will return 0 if none + component that can be dynamically cast to a MyComp, or will return nullptr if none of the parents are suitable. */ template TargetClass* findParentComponentOfClass() const { for (Component* p = parentComponent; p != nullptr; p = p->parentComponent) - if (TargetClass* const target = dynamic_cast (p)) + if (TargetClass* const target = dynamic_cast (p)) return target; return nullptr; @@ -834,7 +812,7 @@ public: virtual void childrenChanged(); //============================================================================== - /** Tests whether a given point inside the component. + /** Tests whether a given point is inside the component. Overriding this method allows you to create components which only intercept mouse-clicks within a user-defined area. @@ -1003,17 +981,12 @@ public: /** Makes the component use an internal buffer to optimise its redrawing. Setting this flag to true will cause the component to allocate an - internal buffer into which it paints itself, so that when asked to - redraw itself, it can use this buffer rather than actually calling the - paint() method. + internal buffer into which it paints itself and all its child components, so that + when asked to redraw itself, it can use this buffer rather than actually calling + the paint() method. - The buffer is kept until the repaint() method is called directly on - this component (or until it is resized), when the image is invalidated - and then redrawn the next time the component is painted. - - Note that only the drawing that happens within the component's paint() - method is drawn into the buffer, it's child components are not buffered, and - nor is the paintOverChildren() method. + Parts of the buffer are invalidated when repaint() is called on this component + or its children. The buffer is then repainted at the next paint() callback. @see repaint, paint, createComponentSnapshot */ @@ -1152,7 +1125,7 @@ public: By default, components are considered transparent, unless this is used to make it otherwise. - @see isOpaque, getVisibleArea + @see isOpaque */ void setOpaque (bool shouldBeOpaque); @@ -1743,11 +1716,14 @@ public: */ virtual void focusLost (FocusChangeType cause); - /** Called to indicate that one of this component's children has been focused or unfocused. + /** Called to indicate a change in whether or not this component is the parent of the + currently-focused component. - Essentially this means that the return value of a call to hasKeyboardFocus (true) has + Essentially this is called when the return value of a call to hasKeyboardFocus (true) has changed. It happens when focus moves from one of this component's children (at any depth) to a component that isn't contained in this one, (or vice-versa). + Note that this method does NOT get called to when focus simply moves from one of its + child components to another. @see focusGained, setWantsKeyboardFocus, getCurrentlyFocusedComponent, hasKeyboardFocus */ @@ -1782,9 +1758,7 @@ public: bool isMouseButtonDown() const; /** True if the mouse is over this component, or if it's being dragged in this component. - This is a handy equivalent to (isMouseOver() || isMouseButtonDown()). - @see isMouseOver, isMouseButtonDown, isMouseButtonDownAnywhere */ bool isMouseOverOrDragging() const; @@ -2122,31 +2096,31 @@ public: SafePointer() noexcept {} /** Creates a SafePointer that points at the given component. */ - SafePointer (ComponentType* const component) : weakRef (component) {} + SafePointer (ComponentType* component) : weakRef (component) {} /** Creates a copy of another SafePointer. */ - SafePointer (const SafePointer& other) noexcept : weakRef (other.weakRef) {} + SafePointer (const SafePointer& other) noexcept : weakRef (other.weakRef) {} /** Copies another pointer to this one. */ - SafePointer& operator= (const SafePointer& other) { weakRef = other.weakRef; return *this; } + SafePointer& operator= (const SafePointer& other) { weakRef = other.weakRef; return *this; } /** Copies another pointer to this one. */ - SafePointer& operator= (ComponentType* const newComponent) { weakRef = newComponent; return *this; } + SafePointer& operator= (ComponentType* newComponent) { weakRef = newComponent; return *this; } /** Returns the component that this pointer refers to, or null if the component no longer exists. */ - ComponentType* getComponent() const noexcept { return dynamic_cast (weakRef.get()); } + ComponentType* getComponent() const noexcept { return dynamic_cast (weakRef.get()); } /** Returns the component that this pointer refers to, or null if the component no longer exists. */ - operator ComponentType*() const noexcept { return getComponent(); } + operator ComponentType*() const noexcept { return getComponent(); } /** Returns the component that this pointer refers to, or null if the component no longer exists. */ - ComponentType* operator->() noexcept { return getComponent(); } + ComponentType* operator->() noexcept { return getComponent(); } /** Returns the component that this pointer refers to, or null if the component no longer exists. */ - const ComponentType* operator->() const noexcept { return getComponent(); } + const ComponentType* operator->() const noexcept { return getComponent(); } /** If the component is valid, this deletes it and sets this pointer to null. */ - void deleteAndZero() { delete getComponent(); } + void deleteAndZero() { delete getComponent(); } bool operator== (ComponentType* component) const noexcept { return weakRef == component; } bool operator!= (ComponentType* component) const noexcept { return weakRef != component; } @@ -2254,20 +2228,20 @@ private: String componentName, componentID; Component* parentComponent; Rectangle bounds; - ScopedPointer positioner; - ScopedPointer affineTransform; - Array childComponentList; + ScopedPointer positioner; + ScopedPointer affineTransform; + Array childComponentList; LookAndFeel* lookAndFeel; MouseCursor cursor; ImageEffectFilter* effect; - ScopedPointer cachedImage; + ScopedPointer cachedImage; class MouseListenerList; friend class MouseListenerList; friend struct ContainerDeletePolicy; - ScopedPointer mouseListeners; - ScopedPointer > keyListeners; - ListenerList componentListeners; + ScopedPointer mouseListeners; + ScopedPointer > keyListeners; + ListenerList componentListeners; NamedValueSet properties; friend class WeakReference; @@ -2292,9 +2266,11 @@ private: bool childCompFocusedFlag : 1; bool dontClipGraphicsFlag : 1; bool mouseDownWasBlocked : 1; - #if JUCE_DEBUG + bool isMoveCallbackPending : 1; + bool isResizeCallbackPending : 1; + #if JUCE_DEBUG bool isInsidePaintCall : 1; - #endif + #endif }; union @@ -2306,30 +2282,31 @@ private: uint8 componentTransparency; //============================================================================== - void internalMouseEnter (MouseInputSource, Point, Time); - void internalMouseExit (MouseInputSource, Point, Time); - void internalMouseDown (MouseInputSource, Point, Time); - void internalMouseUp (MouseInputSource, Point, Time, const ModifierKeys oldModifiers); - void internalMouseDrag (MouseInputSource, Point, Time); - void internalMouseMove (MouseInputSource, Point, Time); - void internalMouseWheel (MouseInputSource, Point, Time, const MouseWheelDetails&); - void internalMagnifyGesture (MouseInputSource, Point, Time, float); + void internalMouseEnter (MouseInputSource, Point, Time); + void internalMouseExit (MouseInputSource, Point, Time); + void internalMouseDown (MouseInputSource, Point, Time); + void internalMouseUp (MouseInputSource, Point, Time, const ModifierKeys oldModifiers); + void internalMouseDrag (MouseInputSource, Point, Time); + void internalMouseMove (MouseInputSource, Point, Time); + void internalMouseWheel (MouseInputSource, Point, Time, const MouseWheelDetails&); + void internalMagnifyGesture (MouseInputSource, Point, Time, float); void internalBroughtToFront(); - void internalFocusGain (const FocusChangeType, const WeakReference&); - void internalFocusGain (const FocusChangeType); - void internalFocusLoss (const FocusChangeType); + void internalFocusGain (FocusChangeType, const WeakReference&); + void internalFocusGain (FocusChangeType); + void internalFocusLoss (FocusChangeType); void internalChildFocusChange (FocusChangeType, const WeakReference&); void internalModalInputAttempt(); void internalModifierKeysChanged(); void internalChildrenChanged(); void internalHierarchyChanged(); - void internalRepaint (const Rectangle&); - void internalRepaintUnchecked (const Rectangle&, bool); + void internalRepaint (Rectangle); + void internalRepaintUnchecked (Rectangle, bool); Component* removeChildComponent (int index, bool sendParentEvents, bool sendChildEvents); void reorderChildInternal (int sourceIndex, int destIndex); void paintComponentAndChildren (Graphics&); void paintWithinParentContext (Graphics&); void sendMovedResizedMessages (bool wasMoved, bool wasResized); + void sendMovedResizedMessagesIfPending(); void repaintParent(); void sendFakeMouseMove() const; void takeKeyboardFocus (const FocusChangeType); diff --git a/JuceLibraryCode/modules/juce_gui_basics/components/juce_ComponentListener.cpp b/JuceLibraryCode/modules/juce_gui_basics/components/juce_ComponentListener.cpp index 3e5cd35..b5968d9 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/components/juce_ComponentListener.cpp +++ b/JuceLibraryCode/modules/juce_gui_basics/components/juce_ComponentListener.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_gui_basics/components/juce_ComponentListener.h b/JuceLibraryCode/modules/juce_gui_basics/components/juce_ComponentListener.h index 56c0631..39e5b37 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/components/juce_ComponentListener.h +++ b/JuceLibraryCode/modules/juce_gui_basics/components/juce_ComponentListener.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_gui_basics/components/juce_Desktop.cpp b/JuceLibraryCode/modules/juce_gui_basics/components/juce_Desktop.cpp index 5dedd42..a80c580 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/components/juce_Desktop.cpp +++ b/JuceLibraryCode/modules/juce_gui_basics/components/juce_Desktop.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -68,6 +68,8 @@ Component* Desktop::getComponent (const int index) const noexcept Component* Desktop::findComponentAt (Point screenPosition) const { + ASSERT_MESSAGE_MANAGER_IS_LOCKED + for (int i = desktopComponents.size(); --i >= 0;) { Component* const c = desktopComponents.getUnchecked(i); @@ -100,6 +102,7 @@ LookAndFeel& Desktop::getDefaultLookAndFeel() noexcept void Desktop::setDefaultLookAndFeel (LookAndFeel* newDefaultLookAndFeel) { + ASSERT_MESSAGE_MANAGER_IS_LOCKED currentLookAndFeel = newDefaultLookAndFeel; for (int i = getNumComponents(); --i >= 0;) @@ -145,18 +148,23 @@ void Desktop::componentBroughtToFront (Component* const c) //============================================================================== Point Desktop::getMousePosition() +{ + return getMousePositionFloat().roundToInt(); +} + +Point Desktop::getMousePositionFloat() { return getInstance().getMainMouseSource().getScreenPosition(); } void Desktop::setMousePosition (Point newPosition) { - getInstance().getMainMouseSource().setScreenPosition (newPosition); + getInstance().getMainMouseSource().setScreenPosition (newPosition.toFloat()); } Point Desktop::getLastMouseDownPosition() { - return getInstance().getMainMouseSource().getLastMouseDownPosition(); + return getInstance().getMainMouseSource().getLastMouseDownPosition().roundToInt(); } int Desktop::getMouseButtonClickCounter() const noexcept { return mouseClickCounter; } @@ -194,10 +202,10 @@ void Desktop::resetTimer() else startTimer (100); - lastFakeMouseMove = getMousePosition(); + lastFakeMouseMove = getMousePositionFloat(); } -ListenerList & Desktop::getMouseListeners() +ListenerList& Desktop::getMouseListeners() { resetTimer(); return mouseListeners; @@ -205,19 +213,21 @@ ListenerList & Desktop::getMouseListeners() void Desktop::addGlobalMouseListener (MouseListener* const listener) { + ASSERT_MESSAGE_MANAGER_IS_LOCKED mouseListeners.add (listener); resetTimer(); } void Desktop::removeGlobalMouseListener (MouseListener* const listener) { + ASSERT_MESSAGE_MANAGER_IS_LOCKED mouseListeners.remove (listener); resetTimer(); } void Desktop::timerCallback() { - if (lastFakeMouseMove != getMousePosition()) + if (lastFakeMouseMove != getMousePositionFloat()) sendMouseMove(); } @@ -227,12 +237,12 @@ void Desktop::sendMouseMove() { startTimer (20); - lastFakeMouseMove = getMousePosition(); + lastFakeMouseMove = getMousePositionFloat(); - if (Component* const target = findComponentAt (lastFakeMouseMove)) + if (Component* const target = findComponentAt (lastFakeMouseMove.roundToInt())) { Component::BailOutChecker checker (target); - const Point pos (target->getLocalPoint (nullptr, lastFakeMouseMove)); + const Point pos (target->getLocalPoint (nullptr, lastFakeMouseMove)); const Time now (Time::getCurrentTime()); const MouseEvent me (getMainMouseSource(), pos, ModifierKeys::getCurrentModifiers(), @@ -253,12 +263,14 @@ Desktop::Displays::~Displays() {} const Desktop::Displays::Display& Desktop::Displays::getMainDisplay() const noexcept { + ASSERT_MESSAGE_MANAGER_IS_LOCKED jassert (displays.getReference(0).isMain); return displays.getReference(0); } const Desktop::Displays::Display& Desktop::Displays::getDisplayContaining (Point position) const noexcept { + ASSERT_MESSAGE_MANAGER_IS_LOCKED const Display* best = &displays.getReference(0); double bestDistance = 1.0e10; @@ -286,6 +298,7 @@ const Desktop::Displays::Display& Desktop::Displays::getDisplayContaining (Point RectangleList Desktop::Displays::getRectangleList (bool userAreasOnly) const { + ASSERT_MESSAGE_MANAGER_IS_LOCKED RectangleList rl; for (int i = 0; i < displays.size(); ++i) @@ -320,7 +333,6 @@ bool operator!= (const Desktop::Displays::Display& d1, const Desktop::Displays:: void Desktop::Displays::init (Desktop& desktop) { findDisplays (desktop.getGlobalScaleFactor()); - jassert (displays.size() > 0); } void Desktop::Displays::refresh() @@ -391,6 +403,8 @@ bool Desktop::isOrientationEnabled (const DisplayOrientation orientation) const void Desktop::setGlobalScaleFactor (float newScaleFactor) noexcept { + ASSERT_MESSAGE_MANAGER_IS_LOCKED + if (masterScaleFactor != newScaleFactor) { masterScaleFactor = newScaleFactor; diff --git a/JuceLibraryCode/modules/juce_gui_basics/components/juce_Desktop.h b/JuceLibraryCode/modules/juce_gui_basics/components/juce_Desktop.h index 0591162..a31d71e 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/components/juce_Desktop.h +++ b/JuceLibraryCode/modules/juce_gui_basics/components/juce_Desktop.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -414,7 +414,7 @@ private: ScopedPointer displays; - Point lastFakeMouseMove; + Point lastFakeMouseMove; void sendMouseMove(); int mouseClickCounter, mouseWheelCounter; @@ -441,11 +441,13 @@ private: void removeDesktopComponent (Component*); void componentBroughtToFront (Component*); - void setKioskComponent (Component*, bool enableOrDisable, bool allowMenusAndBars); + void setKioskComponent (Component*, bool shouldBeEnabled, bool allowMenusAndBars); void triggerFocusCallback(); void handleAsyncUpdate() override; + static Point getMousePositionFloat(); + static double getDefaultMasterScale(); Desktop(); diff --git a/JuceLibraryCode/modules/juce_gui_basics/components/juce_ModalComponentManager.cpp b/JuceLibraryCode/modules/juce_gui_basics/components/juce_ModalComponentManager.cpp index a6e7b07..cc46ac0 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/components/juce_ModalComponentManager.cpp +++ b/JuceLibraryCode/modules/juce_gui_basics/components/juce_ModalComponentManager.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -89,7 +89,7 @@ ModalComponentManager::~ModalComponentManager() clearSingletonInstance(); } -juce_ImplementSingleton_SingleThreaded (ModalComponentManager); +juce_ImplementSingleton_SingleThreaded (ModalComponentManager) //============================================================================== diff --git a/JuceLibraryCode/modules/juce_gui_basics/components/juce_ModalComponentManager.h b/JuceLibraryCode/modules/juce_gui_basics/components/juce_ModalComponentManager.h index b21421e..df8b7b2 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/components/juce_ModalComponentManager.h +++ b/JuceLibraryCode/modules/juce_gui_basics/components/juce_ModalComponentManager.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -72,6 +72,9 @@ public: virtual void modalStateFinished (int returnValue) = 0; }; + //============================================================================== + juce_DeclareSingleton_SingleThreaded_Minimal (ModalComponentManager) + //============================================================================== /** Returns the number of components currently being shown modally. @see getModalComponent @@ -119,9 +122,6 @@ public: int runEventLoopForCurrentComponent(); #endif - //============================================================================== - juce_DeclareSingleton_SingleThreaded_Minimal (ModalComponentManager); - protected: /** Creates a ModalComponentManager. You shouldn't ever call the constructor - it's a singleton, so use ModalComponentManager::getInstance() diff --git a/JuceLibraryCode/modules/juce_gui_basics/drawables/juce_Drawable.cpp b/JuceLibraryCode/modules/juce_gui_basics/drawables/juce_Drawable.cpp index 3e88318..fb00b93 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/drawables/juce_Drawable.cpp +++ b/JuceLibraryCode/modules/juce_gui_basics/drawables/juce_Drawable.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_gui_basics/drawables/juce_Drawable.h b/JuceLibraryCode/modules/juce_gui_basics/drawables/juce_Drawable.h index b8956d5..f297d9c 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/drawables/juce_Drawable.h +++ b/JuceLibraryCode/modules/juce_gui_basics/drawables/juce_Drawable.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -227,14 +227,15 @@ protected: owner (c) {} - bool registerCoordinates() { return owner.registerCoordinates (*this); } - void applyToComponentBounds() + bool registerCoordinates() override { return owner.registerCoordinates (*this); } + + void applyToComponentBounds() override { ComponentScope scope (getComponent()); owner.recalculateCoordinates (&scope); } - void applyNewBounds (const Rectangle&) + void applyNewBounds (const Rectangle&) override { jassertfalse; // drawables can't be resized directly! } diff --git a/JuceLibraryCode/modules/juce_gui_basics/drawables/juce_DrawableComposite.cpp b/JuceLibraryCode/modules/juce_gui_basics/drawables/juce_DrawableComposite.cpp index 688507f..fa21d92 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/drawables/juce_DrawableComposite.cpp +++ b/JuceLibraryCode/modules/juce_gui_basics/drawables/juce_DrawableComposite.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_gui_basics/drawables/juce_DrawableComposite.h b/JuceLibraryCode/modules/juce_gui_basics/drawables/juce_DrawableComposite.h index 1de9111..1436b1f 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/drawables/juce_DrawableComposite.h +++ b/JuceLibraryCode/modules/juce_gui_basics/drawables/juce_DrawableComposite.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -92,15 +92,15 @@ public: //============================================================================== /** @internal */ - Drawable* createCopy() const; + Drawable* createCopy() const override; /** @internal */ - void refreshFromValueTree (const ValueTree& tree, ComponentBuilder& builder); + void refreshFromValueTree (const ValueTree&, ComponentBuilder&); /** @internal */ - ValueTree createValueTree (ComponentBuilder::ImageProvider* imageProvider) const; + ValueTree createValueTree (ComponentBuilder::ImageProvider* imageProvider) const override; /** @internal */ static const Identifier valueTreeType; /** @internal */ - Rectangle getDrawableBounds() const; + Rectangle getDrawableBounds() const override; /** @internal */ void childBoundsChanged (Component*) override; /** @internal */ diff --git a/JuceLibraryCode/modules/juce_gui_basics/drawables/juce_DrawableImage.cpp b/JuceLibraryCode/modules/juce_gui_basics/drawables/juce_DrawableImage.cpp index 7c29dee..8eb51d2 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/drawables/juce_DrawableImage.cpp +++ b/JuceLibraryCode/modules/juce_gui_basics/drawables/juce_DrawableImage.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -37,6 +37,7 @@ DrawableImage::DrawableImage (const DrawableImage& other) overlayColour (other.overlayColour), bounds (other.bounds) { + setBounds (other.getBounds()); } DrawableImage::~DrawableImage() diff --git a/JuceLibraryCode/modules/juce_gui_basics/drawables/juce_DrawableImage.h b/JuceLibraryCode/modules/juce_gui_basics/drawables/juce_DrawableImage.h index 6089dee..56814a8 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/drawables/juce_DrawableImage.h +++ b/JuceLibraryCode/modules/juce_gui_basics/drawables/juce_DrawableImage.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_gui_basics/drawables/juce_DrawablePath.cpp b/JuceLibraryCode/modules/juce_gui_basics/drawables/juce_DrawablePath.cpp index 6dc46ba..bb1b7ff 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/drawables/juce_DrawablePath.cpp +++ b/JuceLibraryCode/modules/juce_gui_basics/drawables/juce_DrawablePath.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -83,7 +83,7 @@ public: { } - bool registerCoordinates() + bool registerCoordinates() override { bool ok = true; @@ -104,7 +104,7 @@ public: return ok; } - void applyToComponentBounds() + void applyToComponentBounds() override { jassert (owner.relativePath != nullptr); @@ -112,7 +112,7 @@ public: owner.applyRelativePath (*owner.relativePath, &scope); } - void applyNewBounds (const Rectangle&) + void applyNewBounds (const Rectangle&) override { jassertfalse; // drawables can't be resized directly! } diff --git a/JuceLibraryCode/modules/juce_gui_basics/drawables/juce_DrawablePath.h b/JuceLibraryCode/modules/juce_gui_basics/drawables/juce_DrawablePath.h index bed3895..34842ec 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/drawables/juce_DrawablePath.h +++ b/JuceLibraryCode/modules/juce_gui_basics/drawables/juce_DrawablePath.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_gui_basics/drawables/juce_DrawableRectangle.cpp b/JuceLibraryCode/modules/juce_gui_basics/drawables/juce_DrawableRectangle.cpp index 5a8c1c8..034953b 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/drawables/juce_DrawableRectangle.cpp +++ b/JuceLibraryCode/modules/juce_gui_basics/drawables/juce_DrawableRectangle.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_gui_basics/drawables/juce_DrawableRectangle.h b/JuceLibraryCode/modules/juce_gui_basics/drawables/juce_DrawableRectangle.h index 9bae02e..b136b8d 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/drawables/juce_DrawableRectangle.h +++ b/JuceLibraryCode/modules/juce_gui_basics/drawables/juce_DrawableRectangle.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_gui_basics/drawables/juce_DrawableShape.cpp b/JuceLibraryCode/modules/juce_gui_basics/drawables/juce_DrawableShape.cpp index 5813493..16aad5e 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/drawables/juce_DrawableShape.cpp +++ b/JuceLibraryCode/modules/juce_gui_basics/drawables/juce_DrawableShape.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -53,14 +53,14 @@ public: { } - bool registerCoordinates() + bool registerCoordinates() override { bool ok = addPoint (fill.gradientPoint1); ok = addPoint (fill.gradientPoint2) && ok; return addPoint (fill.gradientPoint3) && ok; } - void applyToComponentBounds() + void applyToComponentBounds() override { ComponentScope scope (owner); if (isMainFill ? owner.mainFill.recalculateCoords (&scope) @@ -68,7 +68,7 @@ public: owner.repaint(); } - void applyNewBounds (const Rectangle&) + void applyNewBounds (const Rectangle&) override { jassertfalse; // drawables can't be resized directly! } diff --git a/JuceLibraryCode/modules/juce_gui_basics/drawables/juce_DrawableShape.h b/JuceLibraryCode/modules/juce_gui_basics/drawables/juce_DrawableShape.h index ed893f1..5fa5b3e 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/drawables/juce_DrawableShape.h +++ b/JuceLibraryCode/modules/juce_gui_basics/drawables/juce_DrawableShape.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_gui_basics/drawables/juce_DrawableText.cpp b/JuceLibraryCode/modules/juce_gui_basics/drawables/juce_DrawableText.cpp index e9c9802..d142881 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/drawables/juce_DrawableText.cpp +++ b/JuceLibraryCode/modules/juce_gui_basics/drawables/juce_DrawableText.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_gui_basics/drawables/juce_DrawableText.h b/JuceLibraryCode/modules/juce_gui_basics/drawables/juce_DrawableText.h index ac44fb4..16b801b 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/drawables/juce_DrawableText.h +++ b/JuceLibraryCode/modules/juce_gui_basics/drawables/juce_DrawableText.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_gui_basics/drawables/juce_SVGParser.cpp b/JuceLibraryCode/modules/juce_gui_basics/drawables/juce_SVGParser.cpp index a61f0ac..7fbe798 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/drawables/juce_SVGParser.cpp +++ b/JuceLibraryCode/modules/juce_gui_basics/drawables/juce_SVGParser.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -54,7 +54,7 @@ public: DrawableComposite* const drawable = new DrawableComposite(); - drawable->setName (xml->getStringAttribute ("id")); + setCommonAttributes (*drawable, xml); SVGState newState (*this); @@ -85,31 +85,13 @@ public: newState.viewBoxW = vwh.x; newState.viewBoxH = vwh.y; - int placementFlags = 0; + const int placementFlags = parsePlacementFlags (xml->getStringAttribute ("preserveAspectRatio").trim()); - const String aspect (xml->getStringAttribute ("preserveAspectRatio")); - - if (aspect.containsIgnoreCase ("none")) - { - placementFlags = RectanglePlacement::stretchToFit; - } - else - { - if (aspect.containsIgnoreCase ("slice")) placementFlags |= RectanglePlacement::fillDestination; - - if (aspect.containsIgnoreCase ("xMin")) placementFlags |= RectanglePlacement::xLeft; - else if (aspect.containsIgnoreCase ("xMax")) placementFlags |= RectanglePlacement::xRight; - else placementFlags |= RectanglePlacement::xMid; - - if (aspect.containsIgnoreCase ("yMin")) placementFlags |= RectanglePlacement::yTop; - else if (aspect.containsIgnoreCase ("yMax")) placementFlags |= RectanglePlacement::yBottom; - else placementFlags |= RectanglePlacement::yMid; - } - - newState.transform = RectanglePlacement (placementFlags) - .getTransformToFit (Rectangle (viewboxXY.x, viewboxXY.y, vwh.x, vwh.y), - Rectangle (newState.width, newState.height)) - .followedBy (newState.transform); + if (placementFlags != 0) + newState.transform = RectanglePlacement (placementFlags) + .getTransformToFit (Rectangle (viewboxXY.x, viewboxXY.y, vwh.x, vwh.y), + Rectangle (newState.width, newState.height)) + .followedBy (newState.transform); } } else @@ -290,7 +272,7 @@ public: if (parseNextNumber (d, num, false)) { - const float angle = num.getFloatValue() * (180.0f / float_Pi); + const float angle = degreesToRadians (num.getFloatValue()); if (parseNextNumber (d, num, false)) { @@ -363,6 +345,16 @@ private: AffineTransform transform; String cssStyleText; + static void setCommonAttributes (Drawable& d, const XmlPath& xml) + { + String compID (xml->getStringAttribute ("id")); + d.setName (compID); + d.setComponentID (compID); + + if (xml->getStringAttribute ("display") == "none") + d.setVisible (false); + } + //============================================================================== void parseSubElements (const XmlPath& xml, DrawableComposite& parentDrawable) { @@ -383,7 +375,7 @@ private: if (tag == "line") return parseLine (xml); if (tag == "polyline") return parsePolygon (xml, true); if (tag == "polygon") return parsePolygon (xml, false); - if (tag == "text") return parseText (xml); + if (tag == "text") return parseText (xml, true); if (tag == "switch") return parseSwitch (xml); if (tag == "style") parseCSSStyle (xml); @@ -402,7 +394,7 @@ private: { DrawableComposite* const drawable = new DrawableComposite(); - drawable->setName (xml->getStringAttribute ("id")); + setCommonAttributes (*drawable, xml); if (xml->hasAttribute ("transform")) { @@ -547,30 +539,18 @@ private: } DrawablePath* dp = new DrawablePath(); - dp->setName (xml->getStringAttribute ("id")); + setCommonAttributes (*dp, xml); dp->setFill (Colours::transparentBlack); path.applyTransform (transform); dp->setPath (path); - Path::Iterator iter (path); - - bool containsClosedSubPath = false; - while (iter.next()) - { - if (iter.elementType == Path::Iterator::closePath) - { - containsClosedSubPath = true; - break; - } - } - dp->setFill (getPathFillType (path, getStyleAttribute (xml, "fill"), getStyleAttribute (xml, "fill-opacity"), getStyleAttribute (xml, "opacity"), - containsClosedSubPath ? Colours::black - : Colours::transparentBlack)); + pathContainsClosedSubPath (path) ? Colours::black + : Colours::transparentBlack)); const String strokeType (getStyleAttribute (xml, "stroke")); @@ -587,6 +567,15 @@ private: return dp; } + static bool pathContainsClosedSubPath (const Path& path) noexcept + { + for (Path::Iterator iter (path); iter.next();) + if (iter.elementType == Path::Iterator::closePath) + return true; + + return false; + } + struct SetGradientStopsOp { const SVGState* state; @@ -789,69 +778,105 @@ private: return parseColour (fill, i, defaultColour).withMultipliedAlpha (opacity); } + static PathStrokeType::JointStyle getJointStyle (const String& join) noexcept + { + if (join.equalsIgnoreCase ("round")) return PathStrokeType::curved; + if (join.equalsIgnoreCase ("bevel")) return PathStrokeType::beveled; + + return PathStrokeType::mitered; + } + + static PathStrokeType::EndCapStyle getEndCapStyle (const String& cap) noexcept + { + if (cap.equalsIgnoreCase ("round")) return PathStrokeType::rounded; + if (cap.equalsIgnoreCase ("square")) return PathStrokeType::square; + + return PathStrokeType::butt; + } + + float getStrokeWidth (const String& strokeWidth) const noexcept + { + return transform.getScaleFactor() * getCoordLength (strokeWidth, viewBoxW); + } + PathStrokeType getStrokeFor (const XmlPath& xml) const { - const String strokeWidth (getStyleAttribute (xml, "stroke-width")); - const String cap (getStyleAttribute (xml, "stroke-linecap")); - const String join (getStyleAttribute (xml, "stroke-linejoin")); - - //const String mitreLimit (getStyleAttribute (xml, "stroke-miterlimit")); - //const String dashArray (getStyleAttribute (xml, "stroke-dasharray")); - //const String dashOffset (getStyleAttribute (xml, "stroke-dashoffset")); - - PathStrokeType::JointStyle joinStyle = PathStrokeType::mitered; - PathStrokeType::EndCapStyle capStyle = PathStrokeType::butt; - - if (join.equalsIgnoreCase ("round")) - joinStyle = PathStrokeType::curved; - else if (join.equalsIgnoreCase ("bevel")) - joinStyle = PathStrokeType::beveled; - - if (cap.equalsIgnoreCase ("round")) - capStyle = PathStrokeType::rounded; - else if (cap.equalsIgnoreCase ("square")) - capStyle = PathStrokeType::square; - - float ox = 0.0f, oy = 0.0f; - float x = getCoordLength (strokeWidth, viewBoxW), y = 0.0f; - transform.transformPoints (ox, oy, x, y); - - return PathStrokeType (strokeWidth.isNotEmpty() ? juce_hypot (x - ox, y - oy) : 1.0f, - joinStyle, capStyle); + return PathStrokeType (getStrokeWidth (getStyleAttribute (xml, "stroke-width", "1")), + getJointStyle (getStyleAttribute (xml, "stroke-linejoin")), + getEndCapStyle (getStyleAttribute (xml, "stroke-linecap"))); } //============================================================================== - Drawable* parseText (const XmlPath& xml) + Drawable* parseText (const XmlPath& xml, bool shouldParseTransform) { - Array xCoords, yCoords, dxCoords, dyCoords; + if (shouldParseTransform && xml->hasAttribute ("transform")) + { + SVGState newState (*this); + newState.addTransform (xml); - getCoordList (xCoords, getInheritedAttribute (xml, "x"), true, true); - getCoordList (yCoords, getInheritedAttribute (xml, "y"), true, false); + return newState.parseText (xml, false); + } + + Array xCoords, yCoords, dxCoords, dyCoords; + + getCoordList (xCoords, getInheritedAttribute (xml, "x"), true, true); + getCoordList (yCoords, getInheritedAttribute (xml, "y"), true, false); getCoordList (dxCoords, getInheritedAttribute (xml, "dx"), true, true); getCoordList (dyCoords, getInheritedAttribute (xml, "dy"), true, false); + const Font font (getFont (xml)); + const String anchorStr = getStyleAttribute(xml, "text-anchor"); - //xxx not done text yet! - + DrawableComposite* dc = new DrawableComposite(); + setCommonAttributes (*dc, xml); forEachXmlChildElement (*xml, e) { if (e->isTextElement()) { - const String text (e->getText()); + const String text (e->getText().trim()); - Path path; - Drawable* s = parseShape (xml.getChild (e), path); - delete s; // xxx not finished! + DrawableText* dt = new DrawableText(); + dc->addAndMakeVisible (dt); + + dt->setText (text); + dt->setFont (font, true); + dt->setTransform (transform); + + int i = 0; + dt->setColour (parseColour (getStyleAttribute (xml, "fill"), i, Colours::black) + .withMultipliedAlpha (getStyleAttribute (xml, "fill-opacity", "1").getFloatValue())); + + Rectangle bounds (xCoords[0], yCoords[0] - font.getAscent(), + font.getStringWidthFloat (text), font.getHeight()); + + if (anchorStr == "middle") bounds.setX (bounds.getX() - bounds.getWidth() / 2.0f); + else if (anchorStr == "end") bounds.setX (bounds.getX() - bounds.getWidth()); + + dt->setBoundingBox (bounds); } else if (e->hasTagNameIgnoringNamespace ("tspan")) { - Drawable* s = parseText (xml.getChild (e)); - delete s; // xxx not finished! + dc->addAndMakeVisible (parseText (xml.getChild (e), true)); } } - return nullptr; + return dc; + } + + Font getFont (const XmlPath& xml) const + { + const float fontSize = getCoordLength (getStyleAttribute (xml, "font-size"), 1.0f); + + int style = getStyleAttribute (xml, "font-style").containsIgnoreCase ("italic") ? Font::italic : Font::plain; + + if (getStyleAttribute (xml, "font-weight").containsIgnoreCase ("bold")) + style |= Font::bold; + + const String family (getStyleAttribute (xml, "font-family")); + + return family.isEmpty() ? Font (fontSize, style) + : Font (family, fontSize, style); } //============================================================================== @@ -891,7 +916,7 @@ private: return false; } - float getCoordLength (const String& s, const float sizeForProportions) const + float getCoordLength (const String& s, const float sizeForProportions) const noexcept { float n = s.getFloatValue(); const int len = s.length(); @@ -913,13 +938,12 @@ private: return n; } - float getCoordLength (const XmlPath& xml, const char* attName, const float sizeForProportions) const + float getCoordLength (const XmlPath& xml, const char* attName, const float sizeForProportions) const noexcept { return getCoordLength (xml->getStringAttribute (attName), sizeForProportions); } - void getCoordList (Array & coords, const String& list, - const bool allowUnits, const bool isX) const + void getCoordList (Array& coords, const String& list, bool allowUnits, const bool isX) const { String::CharPointerType text (list.getCharPointer()); float value; @@ -953,7 +977,7 @@ private: return source; } - String getStyleAttribute (const XmlPath& xml, const String& attributeName, + String getStyleAttribute (const XmlPath& xml, StringRef attributeName, const String& defaultValue = String()) const { if (xml->hasAttribute (attributeName)) @@ -993,7 +1017,7 @@ private: return defaultValue; } - String getInheritedAttribute (const XmlPath& xml, const String& attributeName) const + String getInheritedAttribute (const XmlPath& xml, StringRef attributeName) const { if (xml->hasAttribute (attributeName)) return xml->getStringAttribute (attributeName); @@ -1004,13 +1028,30 @@ private: return String(); } + static int parsePlacementFlags (const String& align) noexcept + { + if (align.isEmpty()) + return 0; + + if (align.containsIgnoreCase ("none")) + return RectanglePlacement::stretchToFit; + + return (align.containsIgnoreCase ("slice") ? RectanglePlacement::fillDestination : 0) + | (align.containsIgnoreCase ("xMin") ? RectanglePlacement::xLeft + : (align.containsIgnoreCase ("xMax") ? RectanglePlacement::xRight + : RectanglePlacement::xMid)) + | (align.containsIgnoreCase ("yMin") ? RectanglePlacement::yTop + : (align.containsIgnoreCase ("yMax") ? RectanglePlacement::yBottom + : RectanglePlacement::yMid)); + } + //============================================================================== static bool isIdentifierChar (const juce_wchar c) { return CharacterFunctions::isLetter (c) || c == '-'; } - static String getAttributeFromStyleList (const String& list, const String& attributeName, const String& defaultValue) + static String getAttributeFromStyleList (const String& list, StringRef attributeName, const String& defaultValue) { int i = 0; @@ -1158,9 +1199,9 @@ private: tokens.removeEmptyStrings (true); - float numbers [6]; + float numbers[6]; - for (int i = 0; i < 6; ++i) + for (int i = 0; i < numElementsInArray (numbers); ++i) numbers[i] = tokens[i].getFloatValue(); AffineTransform trans; @@ -1172,33 +1213,23 @@ private: } else if (t.startsWithIgnoreCase ("translate")) { - jassert (tokens.size() == 2); trans = AffineTransform::translation (numbers[0], numbers[1]); } else if (t.startsWithIgnoreCase ("scale")) { - if (tokens.size() == 1) - trans = AffineTransform::scale (numbers[0]); - else - trans = AffineTransform::scale (numbers[0], numbers[1]); + trans = AffineTransform::scale (numbers[0], numbers[tokens.size() > 1 ? 1 : 0]); } else if (t.startsWithIgnoreCase ("rotate")) { - if (tokens.size() != 3) - trans = AffineTransform::rotation (numbers[0] / (180.0f / float_Pi)); - else - trans = AffineTransform::rotation (numbers[0] / (180.0f / float_Pi), - numbers[1], numbers[2]); + trans = AffineTransform::rotation (degreesToRadians (numbers[0]), numbers[1], numbers[2]); } else if (t.startsWithIgnoreCase ("skewX")) { - trans = AffineTransform (1.0f, std::tan (numbers[0] * (float_Pi / 180.0f)), 0.0f, - 0.0f, 1.0f, 0.0f); + trans = AffineTransform::shear (std::tan (degreesToRadians (numbers[0])), 0.0f); } else if (t.startsWithIgnoreCase ("skewY")) { - trans = AffineTransform (1.0f, 0.0f, 0.0f, - std::tan (numbers[0] * (float_Pi / 180.0f)), 1.0f, 0.0f); + trans = AffineTransform::shear (0.0f, std::tan (degreesToRadians (numbers[0]))); } result = trans.followedBy (result); @@ -1214,13 +1245,13 @@ private: const bool largeArc, const bool sweep, double& rx, double& ry, double& centreX, double& centreY, - double& startAngle, double& deltaAngle) + double& startAngle, double& deltaAngle) noexcept { const double midX = (x1 - x2) * 0.5; const double midY = (y1 - y2) * 0.5; - const double cosAngle = cos (angle); - const double sinAngle = sin (angle); + const double cosAngle = std::cos (angle); + const double sinAngle = std::sin (angle); const double xp = cosAngle * midX + sinAngle * midY; const double yp = cosAngle * midY - sinAngle * midX; const double xp2 = xp * xp; diff --git a/JuceLibraryCode/modules/juce_gui_basics/filebrowser/juce_DirectoryContentsDisplayComponent.cpp b/JuceLibraryCode/modules/juce_gui_basics/filebrowser/juce_DirectoryContentsDisplayComponent.cpp index 265df83..2871193 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/filebrowser/juce_DirectoryContentsDisplayComponent.cpp +++ b/JuceLibraryCode/modules/juce_gui_basics/filebrowser/juce_DirectoryContentsDisplayComponent.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_gui_basics/filebrowser/juce_DirectoryContentsDisplayComponent.h b/JuceLibraryCode/modules/juce_gui_basics/filebrowser/juce_DirectoryContentsDisplayComponent.h index ebe1680..0aa8235 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/filebrowser/juce_DirectoryContentsDisplayComponent.h +++ b/JuceLibraryCode/modules/juce_gui_basics/filebrowser/juce_DirectoryContentsDisplayComponent.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_gui_basics/filebrowser/juce_DirectoryContentsList.cpp b/JuceLibraryCode/modules/juce_gui_basics/filebrowser/juce_DirectoryContentsList.cpp index 97e9482..79d810f 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/filebrowser/juce_DirectoryContentsList.cpp +++ b/JuceLibraryCode/modules/juce_gui_basics/filebrowser/juce_DirectoryContentsList.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -115,8 +115,7 @@ void DirectoryContentsList::setFileFilter (const FileFilter* newFileFilter) } //============================================================================== -bool DirectoryContentsList::getFileInfo (const int index, - FileInfo& result) const +bool DirectoryContentsList::getFileInfo (const int index, FileInfo& result) const { const ScopedLock sl (fileListLock); @@ -222,7 +221,7 @@ struct FileInfoComparator return first->isDirectory ? -1 : 1; #endif - return first->filename.compareIgnoreCase (second->filename); + return first->filename.compareNatural (second->filename); } }; diff --git a/JuceLibraryCode/modules/juce_gui_basics/filebrowser/juce_DirectoryContentsList.h b/JuceLibraryCode/modules/juce_gui_basics/filebrowser/juce_DirectoryContentsList.h index b2e6a21..2c015de 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/filebrowser/juce_DirectoryContentsList.h +++ b/JuceLibraryCode/modules/juce_gui_basics/filebrowser/juce_DirectoryContentsList.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_gui_basics/filebrowser/juce_FileBrowserComponent.cpp b/JuceLibraryCode/modules/juce_gui_basics/filebrowser/juce_FileBrowserComponent.cpp index 4a2f023..e67215d 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/filebrowser/juce_FileBrowserComponent.cpp +++ b/JuceLibraryCode/modules/juce_gui_basics/filebrowser/juce_FileBrowserComponent.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -240,6 +240,9 @@ void FileBrowserComponent::setRoot (const File& newRootDirectory) currentRoot = newRootDirectory; fileList->setDirectory (currentRoot, true, true); + if (FileTreeComponent* tree = dynamic_cast (fileListComponent.get())) + tree->refresh(); + String currentRootName (currentRoot.getFullPathName()); if (currentRootName.isEmpty()) currentRootName = File::separatorString; @@ -384,7 +387,7 @@ void FileBrowserComponent::fileDoubleClicked (const File& f) { setRoot (f); - if ((flags & canSelectDirectories) != 0) + if ((flags & canSelectDirectories) != 0 && (flags & doNotClearFileNameOnRootChange) == 0) filenameBox.setText (String::empty); } else @@ -429,7 +432,9 @@ void FileBrowserComponent::textEditorReturnKeyPressed (TextEditor&) { setRoot (f); chosenFiles.clear(); - filenameBox.setText (String::empty); + + if ((flags & doNotClearFileNameOnRootChange) == 0) + filenameBox.setText (String()); } else { @@ -555,7 +560,7 @@ void FileBrowserComponent::getDefaultRoots (StringArray& rootNames, StringArray& rootPaths.add (String::empty); rootNames.add (String::empty); - Array volumes; + Array volumes; File vol ("/Volumes"); vol.findChildFiles (volumes, File::findDirectories, false); diff --git a/JuceLibraryCode/modules/juce_gui_basics/filebrowser/juce_FileBrowserComponent.h b/JuceLibraryCode/modules/juce_gui_basics/filebrowser/juce_FileBrowserComponent.h index a1151ef..3053fd5 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/filebrowser/juce_FileBrowserComponent.h +++ b/JuceLibraryCode/modules/juce_gui_basics/filebrowser/juce_FileBrowserComponent.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -51,18 +51,19 @@ public: */ enum FileChooserFlags { - openMode = 1, /**< specifies that the component should allow the user to - choose an existing file with the intention of opening it. */ - saveMode = 2, /**< specifies that the component should allow the user to specify - the name of a file that will be used to save something. */ - canSelectFiles = 4, /**< specifies that the user can select files (can be used in - conjunction with canSelectDirectories). */ - canSelectDirectories = 8, /**< specifies that the user can select directories (can be used in - conjuction with canSelectFiles). */ - canSelectMultipleItems = 16, /**< specifies that the user can select multiple items. */ - useTreeView = 32, /**< specifies that a tree-view should be shown instead of a file list. */ - filenameBoxIsReadOnly = 64, /**< specifies that the user can't type directly into the filename box. */ - warnAboutOverwriting = 128 /**< specifies that the dialog should warn about overwriting existing files (if possible). */ + openMode = 1, /**< specifies that the component should allow the user to + choose an existing file with the intention of opening it. */ + saveMode = 2, /**< specifies that the component should allow the user to specify + the name of a file that will be used to save something. */ + canSelectFiles = 4, /**< specifies that the user can select files (can be used in + conjunction with canSelectDirectories). */ + canSelectDirectories = 8, /**< specifies that the user can select directories (can be used in + conjuction with canSelectFiles). */ + canSelectMultipleItems = 16, /**< specifies that the user can select multiple items. */ + useTreeView = 32, /**< specifies that a tree-view should be shown instead of a file list. */ + filenameBoxIsReadOnly = 64, /**< specifies that the user can't type directly into the filename box. */ + warnAboutOverwriting = 128, /**< specifies that the dialog should warn about overwriting existing files (if possible). */ + doNotClearFileNameOnRootChange = 256 /**< specifies that the file name should not be cleared upon root change. */ }; //============================================================================== diff --git a/JuceLibraryCode/modules/juce_gui_basics/filebrowser/juce_FileBrowserListener.h b/JuceLibraryCode/modules/juce_gui_basics/filebrowser/juce_FileBrowserListener.h index bd206ae..8ff56ad 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/filebrowser/juce_FileBrowserListener.h +++ b/JuceLibraryCode/modules/juce_gui_basics/filebrowser/juce_FileBrowserListener.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_gui_basics/filebrowser/juce_FileChooser.cpp b/JuceLibraryCode/modules/juce_gui_basics/filebrowser/juce_FileChooser.cpp index 71c148d..40c6108 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/filebrowser/juce_FileChooser.cpp +++ b/JuceLibraryCode/modules/juce_gui_basics/filebrowser/juce_FileChooser.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -99,7 +99,7 @@ bool FileChooser::showDialog (const int flags, FilePreviewComponent* const previ #if JUCE_WINDOWS if (useNativeDialogBox && ! (selectsFiles && selectsDirectories)) #elif JUCE_MAC || JUCE_LINUX - if (useNativeDialogBox && (previewComp == nullptr)) + if (useNativeDialogBox) #else if (false) #endif diff --git a/JuceLibraryCode/modules/juce_gui_basics/filebrowser/juce_FileChooser.h b/JuceLibraryCode/modules/juce_gui_basics/filebrowser/juce_FileChooser.h index 7c6b69f..4dc44b3 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/filebrowser/juce_FileChooser.h +++ b/JuceLibraryCode/modules/juce_gui_basics/filebrowser/juce_FileChooser.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_gui_basics/filebrowser/juce_FileChooserDialogBox.cpp b/JuceLibraryCode/modules/juce_gui_basics/filebrowser/juce_FileChooserDialogBox.cpp index 29618a3..52fa007 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/filebrowser/juce_FileChooserDialogBox.cpp +++ b/JuceLibraryCode/modules/juce_gui_basics/filebrowser/juce_FileChooserDialogBox.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_gui_basics/filebrowser/juce_FileChooserDialogBox.h b/JuceLibraryCode/modules/juce_gui_basics/filebrowser/juce_FileChooserDialogBox.h index f63632e..2f1a993 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/filebrowser/juce_FileChooserDialogBox.h +++ b/JuceLibraryCode/modules/juce_gui_basics/filebrowser/juce_FileChooserDialogBox.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_gui_basics/filebrowser/juce_FileListComponent.cpp b/JuceLibraryCode/modules/juce_gui_basics/filebrowser/juce_FileListComponent.cpp index 3125267..f75e80e 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/filebrowser/juce_FileListComponent.cpp +++ b/JuceLibraryCode/modules/juce_gui_basics/filebrowser/juce_FileListComponent.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_gui_basics/filebrowser/juce_FileListComponent.h b/JuceLibraryCode/modules/juce_gui_basics/filebrowser/juce_FileListComponent.h index 7f074d2..e2a55cd 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/filebrowser/juce_FileListComponent.h +++ b/JuceLibraryCode/modules/juce_gui_basics/filebrowser/juce_FileListComponent.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -56,23 +56,23 @@ public: /** Returns the number of files the user has got selected. @see getSelectedFile */ - int getNumSelectedFiles() const; + int getNumSelectedFiles() const override; /** Returns one of the files that the user has currently selected. The index should be in the range 0 to (getNumSelectedFiles() - 1). @see getNumSelectedFiles */ - File getSelectedFile (int index = 0) const; + File getSelectedFile (int index = 0) const override; /** Deselects any files that are currently selected. */ - void deselectAllFiles(); + void deselectAllFiles() override; /** Scrolls to the top of the list. */ - void scrollToTop(); + void scrollToTop() override; /** If the specified file is in the list, it will become the only selected item (and if the file isn't in the list, all other items will be deselected). */ - void setSelectedFile (const File&); + void setSelectedFile (const File&) override; private: //============================================================================== @@ -84,7 +84,7 @@ private: int getNumRows() override; void paintListBoxItem (int, Graphics&, int, int, bool) override; - Component* refreshComponentForRow (int rowNumber, bool isRowSelected, Component* existingComponentToUpdate) override; + Component* refreshComponentForRow (int rowNumber, bool isRowSelected, Component*) override; void selectedRowsChanged (int lastRowSelected) override; void deleteKeyPressed (int currentSelectedRow) override; void returnKeyPressed (int currentSelectedRow) override; diff --git a/JuceLibraryCode/modules/juce_gui_basics/filebrowser/juce_FilePreviewComponent.h b/JuceLibraryCode/modules/juce_gui_basics/filebrowser/juce_FilePreviewComponent.h index 727f420..d09d563 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/filebrowser/juce_FilePreviewComponent.h +++ b/JuceLibraryCode/modules/juce_gui_basics/filebrowser/juce_FilePreviewComponent.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_gui_basics/filebrowser/juce_FileSearchPathListComponent.cpp b/JuceLibraryCode/modules/juce_gui_basics/filebrowser/juce_FileSearchPathListComponent.cpp index a2cad46..2adaa9a 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/filebrowser/juce_FileSearchPathListComponent.cpp +++ b/JuceLibraryCode/modules/juce_gui_basics/filebrowser/juce_FileSearchPathListComponent.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -152,6 +152,8 @@ void FileSearchPathListComponent::returnKeyPressed (int row) path.add (chooser.getResult(), row); changed(); } + #else + (void) row; #endif } diff --git a/JuceLibraryCode/modules/juce_gui_basics/filebrowser/juce_FileSearchPathListComponent.h b/JuceLibraryCode/modules/juce_gui_basics/filebrowser/juce_FileSearchPathListComponent.h index 25ffef7..17d4b9c 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/filebrowser/juce_FileSearchPathListComponent.h +++ b/JuceLibraryCode/modules/juce_gui_basics/filebrowser/juce_FileSearchPathListComponent.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_gui_basics/filebrowser/juce_FileTreeComponent.cpp b/JuceLibraryCode/modules/juce_gui_basics/filebrowser/juce_FileTreeComponent.cpp index 45963e8..51f20f3 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/filebrowser/juce_FileTreeComponent.cpp +++ b/JuceLibraryCode/modules/juce_gui_basics/filebrowser/juce_FileTreeComponent.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_gui_basics/filebrowser/juce_FileTreeComponent.h b/JuceLibraryCode/modules/juce_gui_basics/filebrowser/juce_FileTreeComponent.h index cf59151..833556f 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/filebrowser/juce_FileTreeComponent.h +++ b/JuceLibraryCode/modules/juce_gui_basics/filebrowser/juce_FileTreeComponent.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_gui_basics/filebrowser/juce_FilenameComponent.cpp b/JuceLibraryCode/modules/juce_gui_basics/filebrowser/juce_FilenameComponent.cpp index 4e5036e..2a69425 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/filebrowser/juce_FilenameComponent.cpp +++ b/JuceLibraryCode/modules/juce_gui_basics/filebrowser/juce_FilenameComponent.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -162,9 +162,14 @@ void FilenameComponent::fileDragExit (const StringArray&) } //============================================================================== +String FilenameComponent::getCurrentFileText() const +{ + return filenameBox.getText(); +} + File FilenameComponent::getCurrentFile() const { - File f (File::getCurrentWorkingDirectory().getChildFile (filenameBox.getText())); + File f (File::getCurrentWorkingDirectory().getChildFile (getCurrentFileText())); if (enforcedSuffix.isNotEmpty()) f = f.withFileExtension (enforcedSuffix); diff --git a/JuceLibraryCode/modules/juce_gui_basics/filebrowser/juce_FilenameComponent.h b/JuceLibraryCode/modules/juce_gui_basics/filebrowser/juce_FilenameComponent.h index bbae76e..0385e9e 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/filebrowser/juce_FilenameComponent.h +++ b/JuceLibraryCode/modules/juce_gui_basics/filebrowser/juce_FilenameComponent.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -103,6 +103,9 @@ public: /** Returns the currently displayed filename. */ File getCurrentFile() const; + /** Returns the raw text that the user has entered. */ + String getCurrentFileText() const; + /** Changes the current filename. @param newFile the new filename to use diff --git a/JuceLibraryCode/modules/juce_gui_basics/filebrowser/juce_ImagePreviewComponent.cpp b/JuceLibraryCode/modules/juce_gui_basics/filebrowser/juce_ImagePreviewComponent.cpp index 537aae3..d679089 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/filebrowser/juce_ImagePreviewComponent.cpp +++ b/JuceLibraryCode/modules/juce_gui_basics/filebrowser/juce_ImagePreviewComponent.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_gui_basics/filebrowser/juce_ImagePreviewComponent.h b/JuceLibraryCode/modules/juce_gui_basics/filebrowser/juce_ImagePreviewComponent.h index 6887a78..50347d0 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/filebrowser/juce_ImagePreviewComponent.h +++ b/JuceLibraryCode/modules/juce_gui_basics/filebrowser/juce_ImagePreviewComponent.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_gui_basics/juce_gui_basics.cpp b/JuceLibraryCode/modules/juce_gui_basics/juce_gui_basics.cpp index 71f0554..00eea12 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/juce_gui_basics.cpp +++ b/JuceLibraryCode/modules/juce_gui_basics/juce_gui_basics.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -49,7 +49,7 @@ #import #import - #if JUCE_SUPPORT_CARBON + #if JUCE_SUPPORT_CARBON && ! (defined (MAC_OS_X_VERSION_10_6) && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_6) #define Point CarbonDummyPointName #define Component CarbonDummyCompName #import // still needed for SetSystemUIMode() @@ -105,6 +105,11 @@ #include #include + #if JUCE_USE_XRANDR + /* If you're trying to use Xrandr, you'll need to install the "libxrandr-dev" package.. */ + #include + #endif + #if JUCE_USE_XINERAMA /* If you're trying to use Xinerama, you'll need to install the "libxinerama-dev" package.. */ #include @@ -135,6 +140,12 @@ namespace juce { +#define ASSERT_MESSAGE_MANAGER_IS_LOCKED \ + jassert (MessageManager::getInstance()->currentThreadHasLockedMessageManager()); + +#define ASSERT_MESSAGE_MANAGER_IS_LOCKED_OR_OFFSCREEN \ + jassert (MessageManager::getInstance()->currentThreadHasLockedMessageManager() || getPeer() == nullptr); + extern bool juce_areThereAnyAlwaysOnTopWindows(); #include "components/juce_Component.cpp" diff --git a/JuceLibraryCode/modules/juce_gui_basics/juce_gui_basics.h b/JuceLibraryCode/modules/juce_gui_basics/juce_gui_basics.h index dedd3a0..e34640e 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/juce_gui_basics.h +++ b/JuceLibraryCode/modules/juce_gui_basics/juce_gui_basics.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -38,8 +38,20 @@ #define JUCE_ENABLE_REPAINT_DEBUGGING 0 #endif +/** JUCE_USE_XRANDR: Enables Xrandr multi-monitor support (Linux only). + Unless you specifically want to disable this, it's best to leave this option turned on. + Note that your users do not need to have Xrandr installed for your JUCE app to run, as + the availability of Xrandr is queried during runtime. +*/ +#ifndef JUCE_USE_XRANDR + #define JUCE_USE_XRANDR 1 +#endif + /** JUCE_USE_XINERAMA: Enables Xinerama multi-monitor support (Linux only). Unless you specifically want to disable this, it's best to leave this option turned on. + This will be used as a fallback if JUCE_USE_XRANDR not set or libxrandr cannot be found. + Note that your users do not need to have Xrandr installed for your JUCE app to run, as + the availability of Xinerama is queried during runtime. */ #ifndef JUCE_USE_XINERAMA #define JUCE_USE_XINERAMA 1 diff --git a/JuceLibraryCode/modules/juce_gui_basics/juce_gui_basics.mm b/JuceLibraryCode/modules/juce_gui_basics/juce_gui_basics.mm index fd6808c..c20b080 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/juce_gui_basics.mm +++ b/JuceLibraryCode/modules/juce_gui_basics/juce_gui_basics.mm @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_gui_basics/juce_module_info b/JuceLibraryCode/modules/juce_gui_basics/juce_module_info index 9ec7c1a..41a3e9c 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/juce_module_info +++ b/JuceLibraryCode/modules/juce_gui_basics/juce_module_info @@ -1,7 +1,7 @@ { "id": "juce_gui_basics", "name": "JUCE GUI core classes", - "version": "3.0.6", + "version": "3.2.0", "description": "Basic user-interface components and related classes.", "website": "http://www.juce.com/juce", "license": "GPL/Commercial", diff --git a/JuceLibraryCode/modules/juce_gui_basics/keyboard/juce_CaretComponent.cpp b/JuceLibraryCode/modules/juce_gui_basics/keyboard/juce_CaretComponent.cpp index 67e8155..5cc5966 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/keyboard/juce_CaretComponent.cpp +++ b/JuceLibraryCode/modules/juce_gui_basics/keyboard/juce_CaretComponent.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_gui_basics/keyboard/juce_CaretComponent.h b/JuceLibraryCode/modules/juce_gui_basics/keyboard/juce_CaretComponent.h index 2ae0ec1..4c4077f 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/keyboard/juce_CaretComponent.h +++ b/JuceLibraryCode/modules/juce_gui_basics/keyboard/juce_CaretComponent.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_gui_basics/keyboard/juce_KeyListener.cpp b/JuceLibraryCode/modules/juce_gui_basics/keyboard/juce_KeyListener.cpp index 76ea686..5ad9025 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/keyboard/juce_KeyListener.cpp +++ b/JuceLibraryCode/modules/juce_gui_basics/keyboard/juce_KeyListener.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_gui_basics/keyboard/juce_KeyListener.h b/JuceLibraryCode/modules/juce_gui_basics/keyboard/juce_KeyListener.h index fb30138..15a966d 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/keyboard/juce_KeyListener.h +++ b/JuceLibraryCode/modules/juce_gui_basics/keyboard/juce_KeyListener.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_gui_basics/keyboard/juce_KeyPress.cpp b/JuceLibraryCode/modules/juce_gui_basics/keyboard/juce_KeyPress.cpp index f833f11..29e2f4e 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/keyboard/juce_KeyPress.cpp +++ b/JuceLibraryCode/modules/juce_gui_basics/keyboard/juce_KeyPress.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_gui_basics/keyboard/juce_KeyPress.h b/JuceLibraryCode/modules/juce_gui_basics/keyboard/juce_KeyPress.h index 1269b38..938230e 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/keyboard/juce_KeyPress.h +++ b/JuceLibraryCode/modules/juce_gui_basics/keyboard/juce_KeyPress.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_gui_basics/keyboard/juce_KeyboardFocusTraverser.cpp b/JuceLibraryCode/modules/juce_gui_basics/keyboard/juce_KeyboardFocusTraverser.cpp index b84e903..5630667 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/keyboard/juce_KeyboardFocusTraverser.cpp +++ b/JuceLibraryCode/modules/juce_gui_basics/keyboard/juce_KeyboardFocusTraverser.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_gui_basics/keyboard/juce_KeyboardFocusTraverser.h b/JuceLibraryCode/modules/juce_gui_basics/keyboard/juce_KeyboardFocusTraverser.h index 94ef5f7..c1ece1e 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/keyboard/juce_KeyboardFocusTraverser.h +++ b/JuceLibraryCode/modules/juce_gui_basics/keyboard/juce_KeyboardFocusTraverser.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_gui_basics/keyboard/juce_ModifierKeys.cpp b/JuceLibraryCode/modules/juce_gui_basics/keyboard/juce_ModifierKeys.cpp index f3bab25..37a33b8 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/keyboard/juce_ModifierKeys.cpp +++ b/JuceLibraryCode/modules/juce_gui_basics/keyboard/juce_ModifierKeys.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_gui_basics/keyboard/juce_ModifierKeys.h b/JuceLibraryCode/modules/juce_gui_basics/keyboard/juce_ModifierKeys.h index 123ffed..c44d77b 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/keyboard/juce_ModifierKeys.h +++ b/JuceLibraryCode/modules/juce_gui_basics/keyboard/juce_ModifierKeys.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_gui_basics/keyboard/juce_SystemClipboard.h b/JuceLibraryCode/modules/juce_gui_basics/keyboard/juce_SystemClipboard.h index 29e323b..d21b78e 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/keyboard/juce_SystemClipboard.h +++ b/JuceLibraryCode/modules/juce_gui_basics/keyboard/juce_SystemClipboard.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_gui_basics/keyboard/juce_TextEditorKeyMapper.h b/JuceLibraryCode/modules/juce_gui_basics/keyboard/juce_TextEditorKeyMapper.h index f09dc9b..5f1da82 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/keyboard/juce_TextEditorKeyMapper.h +++ b/JuceLibraryCode/modules/juce_gui_basics/keyboard/juce_TextEditorKeyMapper.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -85,12 +85,6 @@ struct TextEditorKeyMapper if (key.isKeyCode (KeyPress::pageDownKey)) return target.pageDown (isShiftDown); } - if (numCtrlAltCommandKeys < 2) - { - if (key.isKeyCode (KeyPress::backspaceKey)) return target.deleteBackwards (ctrlOrAltDown); - if (key.isKeyCode (KeyPress::deleteKey)) return target.deleteForwards (ctrlOrAltDown); - } - if (key == KeyPress ('c', ModifierKeys::commandModifier, 0) || key == KeyPress (KeyPress::insertKey, ModifierKeys::ctrlModifier, 0)) return target.copyToClipboard(); @@ -103,6 +97,13 @@ struct TextEditorKeyMapper || key == KeyPress (KeyPress::insertKey, ModifierKeys::shiftModifier, 0)) return target.pasteFromClipboard(); + // NB: checking for delete must happen after the earlier check for shift + delete + if (numCtrlAltCommandKeys < 2) + { + if (key.isKeyCode (KeyPress::backspaceKey)) return target.deleteBackwards (ctrlOrAltDown); + if (key.isKeyCode (KeyPress::deleteKey)) return target.deleteForwards (ctrlOrAltDown); + } + if (key == KeyPress ('a', ModifierKeys::commandModifier, 0)) return target.selectAll(); diff --git a/JuceLibraryCode/modules/juce_gui_basics/keyboard/juce_TextInputTarget.h b/JuceLibraryCode/modules/juce_gui_basics/keyboard/juce_TextInputTarget.h index 9770f5d..9021fb6 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/keyboard/juce_TextInputTarget.h +++ b/JuceLibraryCode/modules/juce_gui_basics/keyboard/juce_TextInputTarget.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -79,6 +79,7 @@ public: { textKeyboard = 0, numericKeyboard, + decimalKeyboard, urlKeyboard, emailAddressKeyboard, phoneNumberKeyboard diff --git a/JuceLibraryCode/modules/juce_gui_basics/layout/juce_AnimatedPosition.h b/JuceLibraryCode/modules/juce_gui_basics/layout/juce_AnimatedPosition.h index dac6ce1..60c2501 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/layout/juce_AnimatedPosition.h +++ b/JuceLibraryCode/modules/juce_gui_basics/layout/juce_AnimatedPosition.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -94,7 +94,7 @@ public: */ void endDrag() { - startTimer (1000 / 60); + startTimerHz (60); } /** Called outside of a drag operation to cause a nudge in the specified direction. @@ -102,7 +102,7 @@ public: */ void nudge (double deltaFromCurrentPosition) { - startTimer (100); + startTimerHz (10); moveTo (position + deltaFromCurrentPosition); } @@ -197,7 +197,7 @@ private: if (behaviour.isStopped (newPos)) stopTimer(); else - startTimer (1000 / 60); + startTimerHz (60); setPositionAndSendChange (newPos); } diff --git a/JuceLibraryCode/modules/juce_gui_basics/layout/juce_AnimatedPositionBehaviours.h b/JuceLibraryCode/modules/juce_gui_basics/layout/juce_AnimatedPositionBehaviours.h index 026f36e..6eca4a4 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/layout/juce_AnimatedPositionBehaviours.h +++ b/JuceLibraryCode/modules/juce_gui_basics/layout/juce_AnimatedPositionBehaviours.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_gui_basics/layout/juce_ComponentAnimator.cpp b/JuceLibraryCode/modules/juce_gui_basics/layout/juce_ComponentAnimator.cpp index b7d052c..d2929f8 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/layout/juce_ComponentAnimator.cpp +++ b/JuceLibraryCode/modules/juce_gui_basics/layout/juce_ComponentAnimator.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -25,16 +25,13 @@ class ComponentAnimator::AnimationTask { public: - AnimationTask (Component* const comp) - : component (comp) - { - } + AnimationTask (Component* c) noexcept : component (c) {} void reset (const Rectangle& finalBounds, float finalAlpha, int millisecondsToSpendMoving, bool useProxyComponent, - double startSpeed_, double endSpeed_) + double startSpd, double endSpd) { msElapsed = 0; msTotal = jmax (1, millisecondsToSpendMoving); @@ -51,10 +48,10 @@ public: bottom = component->getBottom(); alpha = component->getAlpha(); - const double invTotalDistance = 4.0 / (startSpeed_ + endSpeed_ + 2.0); - startSpeed = jmax (0.0, startSpeed_ * invTotalDistance); + const double invTotalDistance = 4.0 / (startSpd + endSpd + 2.0); + startSpeed = jmax (0.0, startSpd * invTotalDistance); midSpeed = invTotalDistance; - endSpeed = jmax (0.0, endSpeed_ * invTotalDistance); + endSpeed = jmax (0.0, endSpd * invTotalDistance); if (useProxyComponent) proxy = new ProxyComponent (*component); @@ -66,8 +63,8 @@ public: bool useTimeslice (const int elapsed) { - if (Component* const c = proxy != nullptr ? static_cast (proxy) - : static_cast (component)) + if (Component* const c = proxy != nullptr ? static_cast (proxy) + : static_cast (component)) { msElapsed += elapsed; double newProgress = msElapsed / (double) msTotal; @@ -150,7 +147,10 @@ public: else jassertfalse; // seem to be trying to animate a component that's not visible.. - image = c.createComponentSnapshot (c.getLocalBounds(), false, getDesktopScaleFactor()); + const float scale = (float) Desktop::getInstance().getDisplays() + .getDisplayContaining (getScreenBounds().getCentre()).scale; + + image = c.createComponentSnapshot (c.getLocalBounds(), false, scale); setVisible (true); toBehind (&c); @@ -190,14 +190,8 @@ private: }; //============================================================================== -ComponentAnimator::ComponentAnimator() - : lastTime (0) -{ -} - -ComponentAnimator::~ComponentAnimator() -{ -} +ComponentAnimator::ComponentAnimator() : lastTime (0) {} +ComponentAnimator::~ComponentAnimator() {} //============================================================================== ComponentAnimator::AnimationTask* ComponentAnimator::findTaskFor (Component* const component) const noexcept @@ -218,7 +212,7 @@ void ComponentAnimator::animateComponent (Component* const component, const double endSpeed) { // the speeds must be 0 or greater! - jassert (startSpeed >= 0 && endSpeed >= 0) + jassert (startSpeed >= 0 && endSpeed >= 0); if (component != nullptr) { @@ -237,7 +231,7 @@ void ComponentAnimator::animateComponent (Component* const component, if (! isTimerRunning()) { lastTime = Time::getMillisecondCounter(); - startTimer (1000 / 50); + startTimerHz (50); } } } diff --git a/JuceLibraryCode/modules/juce_gui_basics/layout/juce_ComponentAnimator.h b/JuceLibraryCode/modules/juce_gui_basics/layout/juce_ComponentAnimator.h index f8ef6c6..966863e 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/layout/juce_ComponentAnimator.h +++ b/JuceLibraryCode/modules/juce_gui_basics/layout/juce_ComponentAnimator.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -148,10 +148,10 @@ public: private: //============================================================================== class AnimationTask; - OwnedArray tasks; + OwnedArray tasks; uint32 lastTime; - AnimationTask* findTaskFor (Component* component) const noexcept; + AnimationTask* findTaskFor (Component*) const noexcept; void timerCallback(); JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ComponentAnimator) diff --git a/JuceLibraryCode/modules/juce_gui_basics/layout/juce_ComponentBoundsConstrainer.cpp b/JuceLibraryCode/modules/juce_gui_basics/layout/juce_ComponentBoundsConstrainer.cpp index 4f1fd4a..e012e85 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/layout/juce_ComponentBoundsConstrainer.cpp +++ b/JuceLibraryCode/modules/juce_gui_basics/layout/juce_ComponentBoundsConstrainer.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_gui_basics/layout/juce_ComponentBoundsConstrainer.h b/JuceLibraryCode/modules/juce_gui_basics/layout/juce_ComponentBoundsConstrainer.h index 65f5ee4..0031e41 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/layout/juce_ComponentBoundsConstrainer.h +++ b/JuceLibraryCode/modules/juce_gui_basics/layout/juce_ComponentBoundsConstrainer.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_gui_basics/layout/juce_ComponentBuilder.cpp b/JuceLibraryCode/modules/juce_gui_basics/layout/juce_ComponentBuilder.cpp index 82519ea..4c5c565 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/layout/juce_ComponentBuilder.cpp +++ b/JuceLibraryCode/modules/juce_gui_basics/layout/juce_ComponentBuilder.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -200,12 +200,12 @@ void ComponentBuilder::valueTreeChildAdded (ValueTree& tree, ValueTree&) ComponentBuilderHelpers::updateComponent (*this, tree); } -void ComponentBuilder::valueTreeChildRemoved (ValueTree& tree, ValueTree&) +void ComponentBuilder::valueTreeChildRemoved (ValueTree& tree, ValueTree&, int) { ComponentBuilderHelpers::updateComponent (*this, tree); } -void ComponentBuilder::valueTreeChildOrderChanged (ValueTree& tree) +void ComponentBuilder::valueTreeChildOrderChanged (ValueTree& tree, int, int) { ComponentBuilderHelpers::updateComponent (*this, tree); } @@ -238,7 +238,7 @@ void ComponentBuilder::updateChildComponents (Component& parent, const ValueTree const int numExistingChildComps = parent.getNumChildComponents(); - Array componentsInOrder; + Array componentsInOrder; componentsInOrder.ensureStorageAllocated (numExistingChildComps); { diff --git a/JuceLibraryCode/modules/juce_gui_basics/layout/juce_ComponentBuilder.h b/JuceLibraryCode/modules/juce_gui_basics/layout/juce_ComponentBuilder.h index 9a4e0cb..e87fe80 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/layout/juce_ComponentBuilder.h +++ b/JuceLibraryCode/modules/juce_gui_basics/layout/juce_ComponentBuilder.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -226,7 +226,7 @@ public: private: //============================================================================= - OwnedArray types; + OwnedArray types; ScopedPointer component; ImageProvider* imageProvider; #if JUCE_DEBUG @@ -235,8 +235,8 @@ private: void valueTreePropertyChanged (ValueTree&, const Identifier&) override; void valueTreeChildAdded (ValueTree&, ValueTree&) override; - void valueTreeChildRemoved (ValueTree&, ValueTree&) override; - void valueTreeChildOrderChanged (ValueTree&) override; + void valueTreeChildRemoved (ValueTree&, ValueTree&, int) override; + void valueTreeChildOrderChanged (ValueTree&, int, int) override; void valueTreeParentChanged (ValueTree&) override; JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ComponentBuilder) diff --git a/JuceLibraryCode/modules/juce_gui_basics/layout/juce_ComponentMovementWatcher.cpp b/JuceLibraryCode/modules/juce_gui_basics/layout/juce_ComponentMovementWatcher.cpp index 235baeb..32e8a0c 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/layout/juce_ComponentMovementWatcher.cpp +++ b/JuceLibraryCode/modules/juce_gui_basics/layout/juce_ComponentMovementWatcher.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_gui_basics/layout/juce_ComponentMovementWatcher.h b/JuceLibraryCode/modules/juce_gui_basics/layout/juce_ComponentMovementWatcher.h index c2ca30e..8c91598 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/layout/juce_ComponentMovementWatcher.h +++ b/JuceLibraryCode/modules/juce_gui_basics/layout/juce_ComponentMovementWatcher.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_gui_basics/layout/juce_ConcertinaPanel.cpp b/JuceLibraryCode/modules/juce_gui_basics/layout/juce_ConcertinaPanel.cpp index 21d44cc..a6358cf 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/layout/juce_ConcertinaPanel.cpp +++ b/JuceLibraryCode/modules/juce_gui_basics/layout/juce_ConcertinaPanel.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -282,6 +282,11 @@ ConcertinaPanel::ConcertinaPanel() ConcertinaPanel::~ConcertinaPanel() {} +int ConcertinaPanel::getNumPanels() const noexcept +{ + return holders.size(); +} + Component* ConcertinaPanel::getPanel (int index) const noexcept { if (PanelHolder* h = holders[index]) diff --git a/JuceLibraryCode/modules/juce_gui_basics/layout/juce_ConcertinaPanel.h b/JuceLibraryCode/modules/juce_gui_basics/layout/juce_ConcertinaPanel.h index b340a8b..33f60d4 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/layout/juce_ConcertinaPanel.h +++ b/JuceLibraryCode/modules/juce_gui_basics/layout/juce_ConcertinaPanel.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -85,7 +85,7 @@ public: expanded to that size. Otherwise, it'll fill as much of the total space as possible. */ - bool expandPanelFully (Component* panelComponent, const bool animate); + bool expandPanelFully (Component* panelComponent, bool animate); /** Sets a maximum size for one of the panels. */ void setMaximumPanelSize (Component* panelComponent, int maximumSize); @@ -100,7 +100,8 @@ public: virtual ~LookAndFeelMethods() {} virtual void drawConcertinaPanelHeader (Graphics&, const Rectangle& area, - bool isMouseOver, bool isMouseDown, ConcertinaPanel&, Component&) = 0; + bool isMouseOver, bool isMouseDown, + ConcertinaPanel&, Component&) = 0; }; private: diff --git a/JuceLibraryCode/modules/juce_gui_basics/layout/juce_GroupComponent.cpp b/JuceLibraryCode/modules/juce_gui_basics/layout/juce_GroupComponent.cpp index 5932487..7f9e5e9 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/layout/juce_GroupComponent.cpp +++ b/JuceLibraryCode/modules/juce_gui_basics/layout/juce_GroupComponent.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_gui_basics/layout/juce_GroupComponent.h b/JuceLibraryCode/modules/juce_gui_basics/layout/juce_GroupComponent.h index 6f111e0..02ba492 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/layout/juce_GroupComponent.h +++ b/JuceLibraryCode/modules/juce_gui_basics/layout/juce_GroupComponent.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_gui_basics/layout/juce_MultiDocumentPanel.cpp b/JuceLibraryCode/modules/juce_gui_basics/layout/juce_MultiDocumentPanel.cpp index 01238d9..60ba157 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/layout/juce_MultiDocumentPanel.cpp +++ b/JuceLibraryCode/modules/juce_gui_basics/layout/juce_MultiDocumentPanel.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_gui_basics/layout/juce_MultiDocumentPanel.h b/JuceLibraryCode/modules/juce_gui_basics/layout/juce_MultiDocumentPanel.h index 959e3fb..e6e6311 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/layout/juce_MultiDocumentPanel.h +++ b/JuceLibraryCode/modules/juce_gui_basics/layout/juce_MultiDocumentPanel.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_gui_basics/layout/juce_ResizableBorderComponent.cpp b/JuceLibraryCode/modules/juce_gui_basics/layout/juce_ResizableBorderComponent.cpp index ea05c3a..7653f8b 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/layout/juce_ResizableBorderComponent.cpp +++ b/JuceLibraryCode/modules/juce_gui_basics/layout/juce_ResizableBorderComponent.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_gui_basics/layout/juce_ResizableBorderComponent.h b/JuceLibraryCode/modules/juce_gui_basics/layout/juce_ResizableBorderComponent.h index 3aa7e55..bd7b578 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/layout/juce_ResizableBorderComponent.h +++ b/JuceLibraryCode/modules/juce_gui_basics/layout/juce_ResizableBorderComponent.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_gui_basics/layout/juce_ResizableCornerComponent.cpp b/JuceLibraryCode/modules/juce_gui_basics/layout/juce_ResizableCornerComponent.cpp index 1e04c48..1b2be73 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/layout/juce_ResizableCornerComponent.cpp +++ b/JuceLibraryCode/modules/juce_gui_basics/layout/juce_ResizableCornerComponent.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_gui_basics/layout/juce_ResizableCornerComponent.h b/JuceLibraryCode/modules/juce_gui_basics/layout/juce_ResizableCornerComponent.h index f5e87eb..5049bea 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/layout/juce_ResizableCornerComponent.h +++ b/JuceLibraryCode/modules/juce_gui_basics/layout/juce_ResizableCornerComponent.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_gui_basics/layout/juce_ResizableEdgeComponent.cpp b/JuceLibraryCode/modules/juce_gui_basics/layout/juce_ResizableEdgeComponent.cpp index 739c25c..d23088b 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/layout/juce_ResizableEdgeComponent.cpp +++ b/JuceLibraryCode/modules/juce_gui_basics/layout/juce_ResizableEdgeComponent.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_gui_basics/layout/juce_ResizableEdgeComponent.h b/JuceLibraryCode/modules/juce_gui_basics/layout/juce_ResizableEdgeComponent.h index db9c494..23c3689 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/layout/juce_ResizableEdgeComponent.h +++ b/JuceLibraryCode/modules/juce_gui_basics/layout/juce_ResizableEdgeComponent.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_gui_basics/layout/juce_ScrollBar.cpp b/JuceLibraryCode/modules/juce_gui_basics/layout/juce_ScrollBar.cpp index 6184306..30182c8 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/layout/juce_ScrollBar.cpp +++ b/JuceLibraryCode/modules/juce_gui_basics/layout/juce_ScrollBar.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -60,6 +60,7 @@ ScrollBar::ScrollBar (const bool vertical_) thumbAreaSize (0), thumbStart (0), thumbSize (0), + minimumScrollBarThumbSize (0), initialDelayInMillisecs (100), repeatDelayInMillisecs (50), minimumDelayInMillisecs (10), @@ -67,6 +68,8 @@ ScrollBar::ScrollBar (const bool vertical_) isDraggingThumb (false), autohides (true) { + minimumScrollBarThumbSize = getLookAndFeel().getMinimumScrollbarThumbSize (*this); + setRepaintsOnMouseActivity (true); setFocusContainer (true); } @@ -190,10 +193,8 @@ void ScrollBar::updateThumbPosition() int newThumbSize = roundToInt (totalRange.getLength() > 0 ? (visibleRange.getLength() * thumbAreaSize) / totalRange.getLength() : thumbAreaSize); - LookAndFeel& lf = getLookAndFeel(); - - if (newThumbSize < lf.getMinimumScrollbarThumbSize (*this)) - newThumbSize = jmin (lf.getMinimumScrollbarThumbSize (*this), thumbAreaSize - 1); + if (newThumbSize < minimumScrollBarThumbSize) + newThumbSize = jmin (minimumScrollBarThumbSize, thumbAreaSize - 1); if (newThumbSize > thumbAreaSize) newThumbSize = thumbAreaSize; @@ -280,6 +281,7 @@ void ScrollBar::resized() const int length = vertical ? getHeight() : getWidth(); LookAndFeel& lf = getLookAndFeel(); + minimumScrollBarThumbSize = lf.getMinimumScrollbarThumbSize (*this); const bool buttonsVisible = lf.areScrollbarButtonsVisible(); int buttonSize = 0; @@ -329,6 +331,11 @@ void ScrollBar::resized() updateThumbPosition(); } +void ScrollBar::parentHierarchyChanged() +{ + lookAndFeelChanged(); +} + void ScrollBar::mouseDown (const MouseEvent& e) { isDraggingThumb = false; diff --git a/JuceLibraryCode/modules/juce_gui_basics/layout/juce_ScrollBar.h b/JuceLibraryCode/modules/juce_gui_basics/layout/juce_ScrollBar.h index 2731af0..b59fed2 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/layout/juce_ScrollBar.h +++ b/JuceLibraryCode/modules/juce_gui_basics/layout/juce_ScrollBar.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -376,12 +376,15 @@ public: void paint (Graphics&) override; /** @internal */ void resized() override; + /** @internal */ + void parentHierarchyChanged() override; private: //============================================================================== Range totalRange, visibleRange; double singleStepSize, dragStartRange; int thumbAreaStart, thumbAreaSize, thumbStart, thumbSize; + int minimumScrollBarThumbSize; int dragStartMousePos, lastMousePos; int initialDelayInMillisecs, repeatDelayInMillisecs, minimumDelayInMillisecs; bool vertical, isDraggingThumb, autohides; diff --git a/JuceLibraryCode/modules/juce_gui_basics/layout/juce_StretchableLayoutManager.cpp b/JuceLibraryCode/modules/juce_gui_basics/layout/juce_StretchableLayoutManager.cpp index ee7ff14..14141bd 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/layout/juce_StretchableLayoutManager.cpp +++ b/JuceLibraryCode/modules/juce_gui_basics/layout/juce_StretchableLayoutManager.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_gui_basics/layout/juce_StretchableLayoutManager.h b/JuceLibraryCode/modules/juce_gui_basics/layout/juce_StretchableLayoutManager.h index 318a5cb..1de508e 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/layout/juce_StretchableLayoutManager.h +++ b/JuceLibraryCode/modules/juce_gui_basics/layout/juce_StretchableLayoutManager.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_gui_basics/layout/juce_StretchableLayoutResizerBar.cpp b/JuceLibraryCode/modules/juce_gui_basics/layout/juce_StretchableLayoutResizerBar.cpp index 10bd717..8737377 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/layout/juce_StretchableLayoutResizerBar.cpp +++ b/JuceLibraryCode/modules/juce_gui_basics/layout/juce_StretchableLayoutResizerBar.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_gui_basics/layout/juce_StretchableLayoutResizerBar.h b/JuceLibraryCode/modules/juce_gui_basics/layout/juce_StretchableLayoutResizerBar.h index f1aae0c..28de39f 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/layout/juce_StretchableLayoutResizerBar.h +++ b/JuceLibraryCode/modules/juce_gui_basics/layout/juce_StretchableLayoutResizerBar.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_gui_basics/layout/juce_StretchableObjectResizer.cpp b/JuceLibraryCode/modules/juce_gui_basics/layout/juce_StretchableObjectResizer.cpp index 08d04df..9deeb90 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/layout/juce_StretchableObjectResizer.cpp +++ b/JuceLibraryCode/modules/juce_gui_basics/layout/juce_StretchableObjectResizer.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_gui_basics/layout/juce_StretchableObjectResizer.h b/JuceLibraryCode/modules/juce_gui_basics/layout/juce_StretchableObjectResizer.h index f4cf399..9bf11f0 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/layout/juce_StretchableObjectResizer.h +++ b/JuceLibraryCode/modules/juce_gui_basics/layout/juce_StretchableObjectResizer.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_gui_basics/layout/juce_TabbedButtonBar.cpp b/JuceLibraryCode/modules/juce_gui_basics/layout/juce_TabbedButtonBar.cpp index 67f46bc..d16528c 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/layout/juce_TabbedButtonBar.cpp +++ b/JuceLibraryCode/modules/juce_gui_basics/layout/juce_TabbedButtonBar.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -287,7 +287,7 @@ void TabbedButtonBar::setTabName (const int tabIndex, const String& newName) } } -void TabbedButtonBar::removeTab (const int tabIndex) +void TabbedButtonBar::removeTab (const int tabIndex, const bool animate) { const int oldIndex = currentTabIndex; if (tabIndex == currentTabIndex) @@ -296,7 +296,7 @@ void TabbedButtonBar::removeTab (const int tabIndex) tabs.remove (tabIndex); setCurrentTabIndex (oldIndex); - resized(); + updateTabPositions (animate); } void TabbedButtonBar::moveTab (const int currentIndex, const int newIndex, const bool animate) diff --git a/JuceLibraryCode/modules/juce_gui_basics/layout/juce_TabbedButtonBar.h b/JuceLibraryCode/modules/juce_gui_basics/layout/juce_TabbedButtonBar.h index a9b2561..9622a23 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/layout/juce_TabbedButtonBar.h +++ b/JuceLibraryCode/modules/juce_gui_basics/layout/juce_TabbedButtonBar.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -212,7 +212,7 @@ public: void setTabName (int tabIndex, const String& newName); /** Gets rid of one of the tabs. */ - void removeTab (int tabIndex); + void removeTab (int tabIndex, bool animate = false); /** Moves a tab to a new index in the list. Pass -1 as the index to move it to the end of the list. diff --git a/JuceLibraryCode/modules/juce_gui_basics/layout/juce_TabbedComponent.cpp b/JuceLibraryCode/modules/juce_gui_basics/layout/juce_TabbedComponent.cpp index a2f4680..1682cf7 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/layout/juce_TabbedComponent.cpp +++ b/JuceLibraryCode/modules/juce_gui_basics/layout/juce_TabbedComponent.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_gui_basics/layout/juce_TabbedComponent.h b/JuceLibraryCode/modules/juce_gui_basics/layout/juce_TabbedComponent.h index b7bc85a..944ff83 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/layout/juce_TabbedComponent.h +++ b/JuceLibraryCode/modules/juce_gui_basics/layout/juce_TabbedComponent.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_gui_basics/layout/juce_Viewport.cpp b/JuceLibraryCode/modules/juce_gui_basics/layout/juce_Viewport.cpp index 04064ed..909eb2c 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/layout/juce_Viewport.cpp +++ b/JuceLibraryCode/modules/juce_gui_basics/layout/juce_Viewport.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -30,6 +30,7 @@ Viewport::Viewport (const String& name) showHScrollbar (true), showVScrollbar (true), deleteContent (true), + customScrollBarThickness (false), allowScrollingWithoutScrollbarV (false), allowScrollingWithoutScrollbarH (false), verticalScrollBar (true), @@ -39,6 +40,8 @@ Viewport::Viewport (const String& name) addAndMakeVisible (contentHolder); contentHolder.setInterceptsMouseClicks (false, true); + scrollBarThickness = getLookAndFeel().getDefaultScrollbarWidth(); + addChildComponent (verticalScrollBar); addChildComponent (horizontalScrollBar); @@ -173,6 +176,12 @@ void Viewport::componentMovedOrResized (Component&, bool, bool) updateVisibleArea(); } +void Viewport::lookAndFeelChanged() +{ + if (! customScrollBarThickness) + scrollBarThickness = getLookAndFeel().getDefaultScrollbarWidth(); +} + void Viewport::resized() { updateVisibleArea(); @@ -313,17 +322,32 @@ void Viewport::setScrollBarsShown (const bool showVerticalScrollbarIfNeeded, void Viewport::setScrollBarThickness (const int thickness) { - if (scrollBarThickness != thickness) + int newThickness; + + // To stay compatible with the previous code: use the + // default thickness if thickness parameter is zero + // or negative + if (thickness <= 0) { - scrollBarThickness = thickness; + customScrollBarThickness = false; + newThickness = getLookAndFeel().getDefaultScrollbarWidth(); + } + else + { + customScrollBarThickness = true; + newThickness = thickness; + } + + if (scrollBarThickness != newThickness) + { + scrollBarThickness = newThickness; updateVisibleArea(); } } int Viewport::getScrollBarThickness() const { - return scrollBarThickness > 0 ? scrollBarThickness - : getLookAndFeel().getDefaultScrollbarWidth(); + return scrollBarThickness; } void Viewport::scrollBarMoved (ScrollBar* scrollBarThatHasMoved, double newRangeStart) @@ -346,15 +370,15 @@ void Viewport::mouseWheelMove (const MouseEvent& e, const MouseWheelDetails& whe Component::mouseWheelMove (e, wheel); } -static float rescaleMouseWheelDistance (float distance, int singleStepSize) noexcept +static int rescaleMouseWheelDistance (float distance, int singleStepSize) noexcept { if (distance == 0) return 0; distance *= 14.0f * singleStepSize; - return distance < 0 ? jmin (distance, -1.0f) - : jmax (distance, 1.0f); + return roundToInt (distance < 0 ? jmin (distance, -1.0f) + : jmax (distance, 1.0f)); } bool Viewport::useMouseWheelMoveIfNeeded (const MouseEvent& e, const MouseWheelDetails& wheel) @@ -366,26 +390,23 @@ bool Viewport::useMouseWheelMoveIfNeeded (const MouseEvent& e, const MouseWheelD if (canScrollHorz || canScrollVert) { - float wheelIncrementX = rescaleMouseWheelDistance (wheel.deltaX, singleStepX); - float wheelIncrementY = rescaleMouseWheelDistance (wheel.deltaY, singleStepY); + const int deltaX = rescaleMouseWheelDistance (wheel.deltaX, singleStepX); + const int deltaY = rescaleMouseWheelDistance (wheel.deltaY, singleStepY); Point pos (getViewPosition()); - if (wheelIncrementX != 0 && wheelIncrementY != 0 && canScrollHorz && canScrollVert) + if (deltaX != 0 && deltaY != 0 && canScrollHorz && canScrollVert) { - pos.setX (pos.x - roundToInt (wheelIncrementX)); - pos.setY (pos.y - roundToInt (wheelIncrementY)); + pos.x -= deltaX; + pos.y -= deltaY; } - else if (canScrollHorz && (wheelIncrementX != 0 || e.mods.isShiftDown() || ! canScrollVert)) + else if (canScrollHorz && (deltaX != 0 || e.mods.isShiftDown() || ! canScrollVert)) { - if (wheelIncrementX == 0 && ! canScrollVert) - wheelIncrementX = wheelIncrementY; - - pos.setX (pos.x - roundToInt (wheelIncrementX)); + pos.x -= deltaX != 0 ? deltaX : deltaY; } - else if (canScrollVert && wheelIncrementY != 0) + else if (canScrollVert && deltaY != 0) { - pos.setY (pos.y - roundToInt (wheelIncrementY)); + pos.y -= deltaY; } if (pos != getViewPosition()) diff --git a/JuceLibraryCode/modules/juce_gui_basics/layout/juce_Viewport.h b/JuceLibraryCode/modules/juce_gui_basics/layout/juce_Viewport.h index baeb42a..9873c4c 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/layout/juce_Viewport.h +++ b/JuceLibraryCode/modules/juce_gui_basics/layout/juce_Viewport.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -253,6 +253,8 @@ public: /** @internal */ void componentMovedOrResized (Component&, bool wasMoved, bool wasResized) override; /** @internal */ + void lookAndFeelChanged() override; + /** @internal */ bool useMouseWheelMoveIfNeeded (const MouseEvent&, const MouseWheelDetails&); /** @internal */ static bool respondsToKey (const KeyPress&); @@ -264,9 +266,11 @@ private: int scrollBarThickness; int singleStepX, singleStepY; bool showHScrollbar, showVScrollbar, deleteContent; + bool customScrollBarThickness; bool allowScrollingWithoutScrollbarV, allowScrollingWithoutScrollbarH; Component contentHolder; ScrollBar verticalScrollBar, horizontalScrollBar; + Point viewportPosToCompPos (Point) const; void updateVisibleArea(); diff --git a/JuceLibraryCode/modules/juce_gui_basics/lookandfeel/juce_LookAndFeel.cpp b/JuceLibraryCode/modules/juce_gui_basics/lookandfeel/juce_LookAndFeel.cpp index a457169..005c05b 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/lookandfeel/juce_LookAndFeel.cpp +++ b/JuceLibraryCode/modules/juce_gui_basics/lookandfeel/juce_LookAndFeel.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_gui_basics/lookandfeel/juce_LookAndFeel.h b/JuceLibraryCode/modules/juce_gui_basics/lookandfeel/juce_LookAndFeel.h index ef5c416..3de56b3 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/lookandfeel/juce_LookAndFeel.h +++ b/JuceLibraryCode/modules/juce_gui_basics/lookandfeel/juce_LookAndFeel.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_gui_basics/lookandfeel/juce_LookAndFeel_V1.cpp b/JuceLibraryCode/modules/juce_gui_basics/lookandfeel/juce_LookAndFeel_V1.cpp index 2aa2c1d..927873c 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/lookandfeel/juce_LookAndFeel_V1.cpp +++ b/JuceLibraryCode/modules/juce_gui_basics/lookandfeel/juce_LookAndFeel_V1.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_gui_basics/lookandfeel/juce_LookAndFeel_V1.h b/JuceLibraryCode/modules/juce_gui_basics/lookandfeel/juce_LookAndFeel_V1.h index bc2b6db..c875326 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/lookandfeel/juce_LookAndFeel_V1.h +++ b/JuceLibraryCode/modules/juce_gui_basics/lookandfeel/juce_LookAndFeel_V1.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_gui_basics/lookandfeel/juce_LookAndFeel_V2.cpp b/JuceLibraryCode/modules/juce_gui_basics/lookandfeel/juce_LookAndFeel_V2.cpp index ac9cd44..13c821f 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/lookandfeel/juce_LookAndFeel_V2.cpp +++ b/JuceLibraryCode/modules/juce_gui_basics/lookandfeel/juce_LookAndFeel_V2.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -111,6 +111,9 @@ LookAndFeel_V2::LookAndFeel_V2() TextPropertyComponent::textColourId, 0xff000000, TextPropertyComponent::outlineColourId, standardOutlineColour, + BooleanPropertyComponent::backgroundColourId, 0xffffffff, + BooleanPropertyComponent::outlineColourId, standardOutlineColour, + ListBox::backgroundColourId, 0xffffffff, ListBox::outlineColourId, standardOutlineColour, ListBox::textColourId, 0xff000000, @@ -487,6 +490,12 @@ int LookAndFeel_V2::getAlertWindowButtonHeight() return 28; } +Font LookAndFeel_V2::getAlertWindowTitleFont() +{ + Font messageFont = getAlertWindowMessageFont(); + return messageFont.withHeight (messageFont.getHeight() * 1.1f).boldened(); +} + Font LookAndFeel_V2::getAlertWindowMessageFont() { return Font (15.0f); @@ -1001,6 +1010,16 @@ void LookAndFeel_V2::drawPopupMenuItem (Graphics& g, const Rectangle& area, } } +void LookAndFeel_V2::drawPopupMenuSectionHeader (Graphics& g, const Rectangle& area, const String& sectionName) +{ + g.setFont (getPopupMenuFont().boldened()); + g.setColour (findColour (PopupMenu::headerTextColourId)); + + g.drawFittedText (sectionName, + area.getX() + 12, area.getY(), area.getWidth() - 16, (int) (area.getHeight() * 0.8f), + Justification::bottomLeft, 1); +} + //============================================================================== int LookAndFeel_V2::getMenuWindowFlags() { @@ -1384,7 +1403,6 @@ void LookAndFeel_V2::drawRotarySlider (Graphics& g, int x, int y, int width, int g.fillPath (filledArc); } - if (thickness > 0) { const float innerRadius = radius * 0.2f; Path p; @@ -1443,24 +1461,20 @@ Label* LookAndFeel_V2::createSliderTextBox (Slider& slider) Label* const l = new SliderLabelComp(); l->setJustificationType (Justification::centred); + l->setKeyboardType (TextInputTarget::decimalKeyboard); l->setColour (Label::textColourId, slider.findColour (Slider::textBoxTextColourId)); - l->setColour (Label::backgroundColourId, (slider.getSliderStyle() == Slider::LinearBar || slider.getSliderStyle() == Slider::LinearBarVertical) ? Colours::transparentBlack : slider.findColour (Slider::textBoxBackgroundColourId)); l->setColour (Label::outlineColourId, slider.findColour (Slider::textBoxOutlineColourId)); - l->setColour (TextEditor::textColourId, slider.findColour (Slider::textBoxTextColourId)); - l->setColour (TextEditor::backgroundColourId, slider.findColour (Slider::textBoxBackgroundColourId) .withAlpha ((slider.getSliderStyle() == Slider::LinearBar || slider.getSliderStyle() == Slider::LinearBarVertical) ? 0.7f : 1.0f)); - l->setColour (TextEditor::outlineColourId, slider.findColour (Slider::textBoxOutlineColourId)); - l->setColour (TextEditor::highlightColourId, slider.findColour (Slider::textBoxHighlightColourId)); return l; @@ -1485,12 +1499,86 @@ int LookAndFeel_V2::getSliderPopupPlacement (Slider&) } //============================================================================== -void LookAndFeel_V2::getTooltipSize (const String& tipText, int& width, int& height) +Slider::SliderLayout LookAndFeel_V2::getSliderLayout (Slider& slider) +{ + // 1. compute the actually visible textBox size from the slider textBox size and some additional constraints + + int minXSpace = 0; + int minYSpace = 0; + + Slider::TextEntryBoxPosition textBoxPos = slider.getTextBoxPosition(); + + if (textBoxPos == Slider::TextBoxLeft || textBoxPos == Slider::TextBoxRight) + minXSpace = 30; + else + minYSpace = 15; + + Rectangle localBounds = slider.getLocalBounds(); + + const int textBoxWidth = jmax (0, jmin (slider.getTextBoxWidth(), localBounds.getWidth() - minXSpace)); + const int textBoxHeight = jmax (0, jmin (slider.getTextBoxHeight(), localBounds.getHeight() - minYSpace)); + + Slider::SliderLayout layout; + + // 2. set the textBox bounds + + if (textBoxPos != Slider::NoTextBox) + { + if (slider.isBar()) + { + layout.textBoxBounds = localBounds; + } + else + { + layout.textBoxBounds.setWidth (textBoxWidth); + layout.textBoxBounds.setHeight (textBoxHeight); + + if (textBoxPos == Slider::TextBoxLeft) layout.textBoxBounds.setX (0); + else if (textBoxPos == Slider::TextBoxRight) layout.textBoxBounds.setX (localBounds.getWidth() - textBoxWidth); + else /* above or below -> centre horizontally */ layout.textBoxBounds.setX ((localBounds.getWidth() - textBoxWidth) / 2); + + if (textBoxPos == Slider::TextBoxAbove) layout.textBoxBounds.setY (0); + else if (textBoxPos == Slider::TextBoxBelow) layout.textBoxBounds.setY (localBounds.getHeight() - textBoxHeight); + else /* left or right -> centre vertically */ layout.textBoxBounds.setY ((localBounds.getHeight() - textBoxHeight) / 2); + } + } + + // 3. set the slider bounds + + layout.sliderBounds = localBounds; + + if (slider.isBar()) + { + layout.sliderBounds.reduce (1, 1); // bar border + } + else + { + if (textBoxPos == Slider::TextBoxLeft) layout.sliderBounds.removeFromLeft (textBoxWidth); + else if (textBoxPos == Slider::TextBoxRight) layout.sliderBounds.removeFromRight (textBoxWidth); + else if (textBoxPos == Slider::TextBoxAbove) layout.sliderBounds.removeFromTop (textBoxHeight); + else if (textBoxPos == Slider::TextBoxBelow) layout.sliderBounds.removeFromBottom (textBoxHeight); + + const int thumbIndent = getSliderThumbRadius (slider); + + if (slider.isHorizontal()) layout.sliderBounds.reduce (thumbIndent, 0); + else if (slider.isVertical()) layout.sliderBounds.reduce (0, thumbIndent); + } + + return layout; +} + +//============================================================================== +Rectangle LookAndFeel_V2::getTooltipBounds (const String& tipText, Point screenPos, Rectangle parentArea) { const TextLayout tl (LookAndFeelHelpers::layoutTooltipText (tipText, Colours::black)); - width = (int) (tl.getWidth() + 14.0f); - height = (int) (tl.getHeight() + 6.0f); + const int w = (int) (tl.getWidth() + 14.0f); + const int h = (int) (tl.getHeight() + 6.0f); + + return Rectangle (screenPos.x > parentArea.getCentreX() ? screenPos.x - (w + 12) : screenPos.x + 24, + screenPos.y > parentArea.getCentreY() ? screenPos.y - (h + 6) : screenPos.y + 6, + w, h) + .constrainedWithin (parentArea); } void LookAndFeel_V2::drawTooltip (Graphics& g, const String& text, int width, int height) @@ -2357,6 +2445,10 @@ void LookAndFeel_V2::drawCallOutBoxBackground (CallOutBox& box, Graphics& g, g.strokePath (path, PathStrokeType (2.0f)); } +int LookAndFeel_V2::getCallOutBoxBorderSize (const CallOutBox&) +{ + return 20; +} //============================================================================== AttributedString LookAndFeel_V2::createFileChooserHeaderText (const String& title, @@ -2492,7 +2584,7 @@ void LookAndFeel_V2::layoutFileBrowserComponent (FileBrowserComponent& browserCo filenameBox->setBounds (x + 50, y, w - 50, controlsHeight); } -// Pulls a drawable out of compressed valuetree data.. +// Pulls a drawable out of compressed ValueTree data.. static Drawable* loadDrawableFromData (const void* data, size_t numBytes) { MemoryInputStream m (data, numBytes, false); diff --git a/JuceLibraryCode/modules/juce_gui_basics/lookandfeel/juce_LookAndFeel_V2.h b/JuceLibraryCode/modules/juce_gui_basics/lookandfeel/juce_LookAndFeel_V2.h index eb9395b..aea4539 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/lookandfeel/juce_LookAndFeel_V2.h +++ b/JuceLibraryCode/modules/juce_gui_basics/lookandfeel/juce_LookAndFeel_V2.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -67,7 +67,22 @@ public: void drawAlertBox (Graphics&, AlertWindow&, const Rectangle& textArea, TextLayout&) override; int getAlertBoxWindowFlags() override; int getAlertWindowButtonHeight() override; + + /** Override this function to supply a custom font for the alert window title. + This default implementation will use a boldened and slightly larger version + of the alert window message font. + + @see getAlertWindowMessageFont. + */ + Font getAlertWindowTitleFont() override; + + /** Override this function to supply a custom font for the alert window message. + This default implementation will use the default font with height set to 15.0f. + + @see getAlertWindowTitleFont + */ Font getAlertWindowMessageFont() override; + Font getAlertWindowFont() override; //============================================================================== @@ -137,6 +152,9 @@ public: const String& text, const String& shortcutKeyText, const Drawable* icon, const Colour* textColour) override; + void drawPopupMenuSectionHeader (Graphics&, const Rectangle& area, + const String& sectionName) override; + Font getPopupMenuFont() override; void drawPopupMenuUpDownArrow (Graphics&, int width, int height, bool isScrollUpArrow) override; @@ -190,9 +208,10 @@ public: ImageEffectFilter* getSliderEffect (Slider&) override; Font getSliderPopupFont (Slider&) override; int getSliderPopupPlacement (Slider&) override; + Slider::SliderLayout getSliderLayout (Slider&) override; //============================================================================== - void getTooltipSize (const String& tipText, int& width, int& height) override; + Rectangle getTooltipBounds (const String& tipText, Point screenPos, Rectangle parentArea) override; void drawTooltip (Graphics&, const String& text, int width, int height) override; //============================================================================== @@ -285,6 +304,7 @@ public: //============================================================================== void drawCallOutBoxBackground (CallOutBox&, Graphics&, const Path& path, Image& cachedImage) override; + int getCallOutBoxBorderSize (const CallOutBox&) override; //============================================================================== void drawLevelMeter (Graphics&, int width, int height, float level) override; diff --git a/JuceLibraryCode/modules/juce_gui_basics/lookandfeel/juce_LookAndFeel_V3.cpp b/JuceLibraryCode/modules/juce_gui_basics/lookandfeel/juce_LookAndFeel_V3.cpp index e64288e..3e8e135 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/lookandfeel/juce_LookAndFeel_V3.cpp +++ b/JuceLibraryCode/modules/juce_gui_basics/lookandfeel/juce_LookAndFeel_V3.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_gui_basics/lookandfeel/juce_LookAndFeel_V3.h b/JuceLibraryCode/modules/juce_gui_basics/lookandfeel/juce_LookAndFeel_V3.h index ad97552..2a47425 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/lookandfeel/juce_LookAndFeel_V3.h +++ b/JuceLibraryCode/modules/juce_gui_basics/lookandfeel/juce_LookAndFeel_V3.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_gui_basics/menus/juce_MenuBarComponent.cpp b/JuceLibraryCode/modules/juce_gui_basics/menus/juce_MenuBarComponent.cpp index 5a22fc7..8d746c4 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/menus/juce_MenuBarComponent.cpp +++ b/JuceLibraryCode/modules/juce_gui_basics/menus/juce_MenuBarComponent.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -22,7 +22,7 @@ ============================================================================== */ -MenuBarComponent::MenuBarComponent (MenuBarModel* model_) +MenuBarComponent::MenuBarComponent (MenuBarModel* m) : model (nullptr), itemUnderMouse (-1), currentPopupIndex (-1), @@ -32,7 +32,7 @@ MenuBarComponent::MenuBarComponent (MenuBarModel* model_) setWantsKeyboardFocus (false); setMouseClickGrabsKeyboardFocus (false); - setModel (model_); + setModel (m); } MenuBarComponent::~MenuBarComponent() @@ -284,22 +284,26 @@ void MenuBarComponent::mouseMove (const MouseEvent& e) bool MenuBarComponent::keyPressed (const KeyPress& key) { - bool used = false; const int numMenus = menuNames.size(); - const int currentIndex = jlimit (0, menuNames.size() - 1, currentPopupIndex); - if (key.isKeyCode (KeyPress::leftKey)) + if (numMenus > 0) { - showMenu ((currentIndex + numMenus - 1) % numMenus); - used = true; - } - else if (key.isKeyCode (KeyPress::rightKey)) - { - showMenu ((currentIndex + 1) % numMenus); - used = true; + const int currentIndex = jlimit (0, numMenus - 1, currentPopupIndex); + + if (key.isKeyCode (KeyPress::leftKey)) + { + showMenu ((currentIndex + numMenus - 1) % numMenus); + return true; + } + + if (key.isKeyCode (KeyPress::rightKey)) + { + showMenu ((currentIndex + 1) % numMenus); + return true; + } } - return used; + return false; } void MenuBarComponent::menuBarItemsChanged (MenuBarModel* /*menuBarModel*/) diff --git a/JuceLibraryCode/modules/juce_gui_basics/menus/juce_MenuBarComponent.h b/JuceLibraryCode/modules/juce_gui_basics/menus/juce_MenuBarComponent.h index b8fc2c3..22be75b 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/menus/juce_MenuBarComponent.h +++ b/JuceLibraryCode/modules/juce_gui_basics/menus/juce_MenuBarComponent.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -40,11 +40,11 @@ public: //============================================================================== /** Creates a menu bar. - @param model the model object to use to control this bar. You can - pass 0 into this if you like, and set the model later - using the setModel() method + @param model the model object to use to control this bar. You can + pass omit the parameter or pass nullptr into this if you like, + and set the model later using the setModel() method. */ - MenuBarComponent (MenuBarModel* model); + MenuBarComponent (MenuBarModel* model = nullptr); /** Destructor. */ ~MenuBarComponent(); @@ -57,8 +57,7 @@ public: */ void setModel (MenuBarModel* newModel); - /** Returns the current menu bar model being used. - */ + /** Returns the current menu bar model being used. */ MenuBarModel* getModel() const noexcept; //============================================================================== diff --git a/JuceLibraryCode/modules/juce_gui_basics/menus/juce_MenuBarModel.cpp b/JuceLibraryCode/modules/juce_gui_basics/menus/juce_MenuBarModel.cpp index c72de96..d93642f 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/menus/juce_MenuBarModel.cpp +++ b/JuceLibraryCode/modules/juce_gui_basics/menus/juce_MenuBarModel.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_gui_basics/menus/juce_MenuBarModel.h b/JuceLibraryCode/modules/juce_gui_basics/menus/juce_MenuBarModel.h index ceac89a..cf9c42f 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/menus/juce_MenuBarModel.h +++ b/JuceLibraryCode/modules/juce_gui_basics/menus/juce_MenuBarModel.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -80,8 +80,7 @@ public: virtual ~Listener() {} //============================================================================== - /** This callback is made when items are changed in the menu bar model. - */ + /** This callback is made when items are changed in the menu bar model. */ virtual void menuBarItemsChanged (MenuBarModel* menuBarModel) = 0; /** This callback is made when an application command is invoked that @@ -101,7 +100,6 @@ public: void addListener (Listener* listenerToAdd) noexcept; /** Removes a listener. - @see addListener */ void removeListener (Listener* listenerToRemove) noexcept; @@ -130,7 +128,7 @@ public: //============================================================================== #if JUCE_MAC || DOXYGEN - /** MAC ONLY - Sets the model that is currently being shown as the main + /** OSX ONLY - Sets the model that is currently being shown as the main menu bar at the top of the screen on the Mac. You can pass 0 to stop the current model being displayed. Be careful @@ -151,12 +149,12 @@ public: const PopupMenu* extraAppleMenuItems = nullptr, const String& recentItemsMenuName = String::empty); - /** MAC ONLY - Returns the menu model that is currently being shown as + /** OSX ONLY - Returns the menu model that is currently being shown as the main menu bar. */ static MenuBarModel* getMacMainMenu(); - /** MAC ONLY - Returns the menu that was last passed as the extraAppleMenuItems + /** OSX ONLY - Returns the menu that was last passed as the extraAppleMenuItems argument to setMacMainMenu(), or nullptr if none was specified. */ static const PopupMenu* getMacExtraAppleItemsMenu(); @@ -164,7 +162,7 @@ public: //============================================================================== /** @internal */ - void applicationCommandInvoked (const ApplicationCommandTarget::InvocationInfo& info) override; + void applicationCommandInvoked (const ApplicationCommandTarget::InvocationInfo&) override; /** @internal */ void applicationCommandListChanged() override; /** @internal */ @@ -172,7 +170,7 @@ public: private: ApplicationCommandManager* manager; - ListenerList listeners; + ListenerList listeners; JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MenuBarModel) }; diff --git a/JuceLibraryCode/modules/juce_gui_basics/menus/juce_PopupMenu.cpp b/JuceLibraryCode/modules/juce_gui_basics/menus/juce_PopupMenu.cpp index abfc922..143de11 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/menus/juce_PopupMenu.cpp +++ b/JuceLibraryCode/modules/juce_gui_basics/menus/juce_PopupMenu.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -740,7 +740,7 @@ public: void ensureItemIsVisible (const int itemID, int wantedY) { - jassert (itemID != 0) + jassert (itemID != 0); for (int i = items.size(); --i >= 0;) { @@ -980,12 +980,12 @@ public: void timerCallback() override { if (window.windowIsStillValid()) - handleMousePosition (source.getScreenPosition()); + handleMousePosition (source.getScreenPosition().roundToInt()); } bool isOver() const { - return window.reallyContains (window.getLocalPoint (nullptr, source.getScreenPosition()), true); + return window.reallyContains (window.getLocalPoint (nullptr, source.getScreenPosition()).roundToInt(), true); } MenuWindow& window; @@ -1216,15 +1216,10 @@ public: void paint (Graphics& g) override { - g.setFont (getLookAndFeel().getPopupMenuFont().boldened()); - g.setColour (findColour (PopupMenu::headerTextColourId)); - - g.drawFittedText (getName(), - 12, 0, getWidth() - 16, proportionOfHeight (0.8f), - Justification::bottomLeft, 1); + getLookAndFeel().drawPopupMenuSectionHeader (g, getLocalBounds(), getName()); } - void getIdealSize (int& idealWidth, int& idealHeight) + void getIdealSize (int& idealWidth, int& idealHeight) override { getLookAndFeel().getIdealPopupMenuItemSize (getName(), false, -1, idealWidth, idealHeight); idealHeight += idealHeight / 2; @@ -1548,6 +1543,7 @@ int PopupMenu::showWithOptionalCallback (const Options& options, ModalComponentM if (userCallback == nullptr && canBeModal) return window->runModalLoop(); #else + (void) canBeModal; jassert (! (userCallback == nullptr && canBeModal)); #endif } @@ -1702,9 +1698,9 @@ void PopupMenu::CustomComponent::setHighlighted (bool shouldBeHighlighted) void PopupMenu::CustomComponent::triggerMenuItem() { - if (HelperClasses::ItemComponent* const mic = dynamic_cast (getParentComponent())) + if (HelperClasses::ItemComponent* const mic = findParentComponentOfClass()) { - if (HelperClasses::MenuWindow* const pmw = dynamic_cast (mic->getParentComponent())) + if (HelperClasses::MenuWindow* const pmw = mic->findParentComponentOfClass()) { pmw->dismissMenu (&mic->itemInfo); } diff --git a/JuceLibraryCode/modules/juce_gui_basics/menus/juce_PopupMenu.h b/JuceLibraryCode/modules/juce_gui_basics/menus/juce_PopupMenu.h index 82545a3..a14b2de 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/menus/juce_PopupMenu.h +++ b/JuceLibraryCode/modules/juce_gui_basics/menus/juce_PopupMenu.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -562,6 +562,9 @@ public: const Drawable* icon, const Colour* textColour) = 0; + virtual void drawPopupMenuSectionHeader (Graphics&, const Rectangle& area, + const String& sectionName) = 0; + /** Returns the size and style of font to use in popup menus. */ virtual Font getPopupMenuFont() = 0; diff --git a/JuceLibraryCode/modules/juce_gui_basics/misc/juce_BubbleComponent.cpp b/JuceLibraryCode/modules/juce_gui_basics/misc/juce_BubbleComponent.cpp index 920a222..f45c93e 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/misc/juce_BubbleComponent.cpp +++ b/JuceLibraryCode/modules/juce_gui_basics/misc/juce_BubbleComponent.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_gui_basics/misc/juce_BubbleComponent.h b/JuceLibraryCode/modules/juce_gui_basics/misc/juce_BubbleComponent.h index 200d272..c6c758a 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/misc/juce_BubbleComponent.h +++ b/JuceLibraryCode/modules/juce_gui_basics/misc/juce_BubbleComponent.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_gui_basics/misc/juce_DropShadower.cpp b/JuceLibraryCode/modules/juce_gui_basics/misc/juce_DropShadower.cpp index c6d0d77..d46f137 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/misc/juce_DropShadower.cpp +++ b/JuceLibraryCode/modules/juce_gui_basics/misc/juce_DropShadower.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_gui_basics/misc/juce_DropShadower.h b/JuceLibraryCode/modules/juce_gui_basics/misc/juce_DropShadower.h index 484ed63..584f548 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/misc/juce_DropShadower.h +++ b/JuceLibraryCode/modules/juce_gui_basics/misc/juce_DropShadower.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_gui_basics/mouse/juce_ComponentDragger.cpp b/JuceLibraryCode/modules/juce_gui_basics/mouse/juce_ComponentDragger.cpp index 3b85495..139ae26 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/mouse/juce_ComponentDragger.cpp +++ b/JuceLibraryCode/modules/juce_gui_basics/mouse/juce_ComponentDragger.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -49,7 +49,7 @@ void ComponentDragger::dragComponent (Component* const componentToDrag, const Mo // so their coordinates become wrong after the first one moves the window, so in that case, we'll use // the current mouse position instead of the one that the event contains... if (componentToDrag->isOnDesktop()) - bounds += componentToDrag->getLocalPoint (nullptr, e.source.getScreenPosition()) - mouseDownWithinTarget; + bounds += componentToDrag->getLocalPoint (nullptr, e.source.getScreenPosition()).roundToInt() - mouseDownWithinTarget; else bounds += e.getEventRelativeTo (componentToDrag).getPosition() - mouseDownWithinTarget; diff --git a/JuceLibraryCode/modules/juce_gui_basics/mouse/juce_ComponentDragger.h b/JuceLibraryCode/modules/juce_gui_basics/mouse/juce_ComponentDragger.h index 0bb5cbe..7475710 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/mouse/juce_ComponentDragger.h +++ b/JuceLibraryCode/modules/juce_gui_basics/mouse/juce_ComponentDragger.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_gui_basics/mouse/juce_DragAndDropContainer.cpp b/JuceLibraryCode/modules/juce_gui_basics/mouse/juce_DragAndDropContainer.cpp index 0806461..e7c88ee 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/mouse/juce_DragAndDropContainer.cpp +++ b/JuceLibraryCode/modules/juce_gui_basics/mouse/juce_DragAndDropContainer.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -43,7 +43,7 @@ public: imageOffset (offset), hasCheckedForExternalDrag (false) { - setSize (im.getWidth(), im.getHeight()); + updateSize(); if (mouseDragSource == nullptr) mouseDragSource = sourceComponent; @@ -69,6 +69,8 @@ public: if (current->isInterestedInDragSource (sourceDetails)) current->itemDragExit (sourceDetails); } + + owner.dragOperationEnded(); } void paint (Graphics& g) override @@ -158,20 +160,27 @@ public: forceMouseCursorUpdate(); } + void updateImage (const Image& newImage) + { + image = newImage; + updateSize(); + repaint(); + } + void timerCallback() override { forceMouseCursorUpdate(); if (sourceDetails.sourceComponent == nullptr) { - delete this; + deleteSelf(); } else if (! isMouseButtonDownAnywhere()) { if (mouseDragSource != nullptr) mouseDragSource->removeMouseListener (this); - delete this; + deleteSelf(); } } @@ -180,7 +189,7 @@ public: if (key == KeyPress::escapeKey) { dismissWithAnimation (true); - delete this; + deleteSelf(); return true; } @@ -205,6 +214,11 @@ private: bool hasCheckedForExternalDrag; Time lastTimeOverTarget; + void updateSize() + { + setSize (image.getWidth(), image.getHeight()); + } + void forceMouseCursorUpdate() { Desktop::getInstance().getMainMouseSource().forceMouseCursorUpdate(); @@ -212,7 +226,22 @@ private: DragAndDropTarget* getCurrentlyOver() const noexcept { - return dynamic_cast (currentlyOverComp.get()); + return dynamic_cast (currentlyOverComp.get()); + } + + static Component* findDesktopComponentBelow (Point screenPos) + { + Desktop& desktop = Desktop::getInstance(); + + for (int i = desktop.getNumComponents(); --i >= 0;) + { + Component* c = desktop.getComponent(i); + + if (Component* hit = c->getComponentAt (c->getLocalPoint (nullptr, screenPos))) + return hit; + } + + return nullptr; } DragAndDropTarget* findTarget (Point screenPos, Point& relativePos, @@ -221,7 +250,7 @@ private: Component* hit = getParentComponent(); if (hit == nullptr) - hit = Desktop::getInstance().findComponentAt (screenPos); + hit = findDesktopComponentBelow (screenPos); else hit = hit->getComponentAt (hit->getLocalPoint (nullptr, screenPos)); @@ -231,7 +260,7 @@ private: while (hit != nullptr) { - if (DragAndDropTarget* const ddt = dynamic_cast (hit)) + if (DragAndDropTarget* const ddt = dynamic_cast (hit)) { if (ddt->isInterestedInDragSource (details)) { @@ -296,12 +325,17 @@ private: && ModifierKeys::getCurrentModifiersRealtime().isAnyMouseButtonDown()) { (new ExternalDragAndDropMessage (files, canMoveFiles))->post(); - delete this; + deleteSelf(); } } } } + void deleteSelf() + { + delete this; + } + void dismissWithAnimation (const bool shouldSnapBack) { setVisible (true); @@ -353,7 +387,7 @@ void DragAndDropContainer::startDragging (const var& sourceDescription, return; } - const Point lastMouseDown (draggingSource->getLastMouseDownPosition()); + const Point lastMouseDown (draggingSource->getLastMouseDownPosition().roundToInt()); Point imageOffset; if (dragImage.isNull()) @@ -383,7 +417,7 @@ void DragAndDropContainer::startDragging (const var& sourceDescription, { const float alpha = (distance > hi) ? 0 : (hi - distance) / (float) (hi - lo) - + random.nextFloat() * 0.008f; + + random.nextFloat() * 0.008f; dragImage.multiplyAlphaAt (x, y, alpha); } @@ -414,7 +448,7 @@ void DragAndDropContainer::startDragging (const var& sourceDescription, } else { - if (Component* const thisComp = dynamic_cast (this)) + if (Component* const thisComp = dynamic_cast (this)) { thisComp->addChildComponent (dragImageComponent); } @@ -425,8 +459,7 @@ void DragAndDropContainer::startDragging (const var& sourceDescription, } } - static_cast (dragImageComponent.get())->updateLocation (false, lastMouseDown); - dragImageComponent->setVisible (true); + static_cast (dragImageComponent.get())->updateLocation (false, lastMouseDown); dragImageComponent->enterModalState(); #if JUCE_WINDOWS @@ -435,6 +468,8 @@ void DragAndDropContainer::startDragging (const var& sourceDescription, if (ComponentPeer* const peer = dragImageComponent->getPeer()) peer->performAnyPendingRepaintsNow(); #endif + + dragOperationStarted(); } } @@ -449,6 +484,12 @@ var DragAndDropContainer::getCurrentDragDescription() const : var(); } +void DragAndDropContainer::setCurrentDragImage (const Image& newImage) +{ + if (dragImageComponent != nullptr) + dragImageComponent->updateImage (newImage); +} + DragAndDropContainer* DragAndDropContainer::findParentDragContainerFor (Component* c) { return c != nullptr ? c->findParentComponentOfClass() : nullptr; @@ -459,6 +500,9 @@ bool DragAndDropContainer::shouldDropFilesWhenDraggedExternally (const DragAndDr return false; } +void DragAndDropContainer::dragOperationStarted() {} +void DragAndDropContainer::dragOperationEnded() {} + //============================================================================== DragAndDropTarget::SourceDetails::SourceDetails (const var& desc, Component* comp, Point pos) noexcept : description (desc), diff --git a/JuceLibraryCode/modules/juce_gui_basics/mouse/juce_DragAndDropContainer.h b/JuceLibraryCode/modules/juce_gui_basics/mouse/juce_DragAndDropContainer.h index 9843753..cc8d4fb 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/mouse/juce_DragAndDropContainer.h +++ b/JuceLibraryCode/modules/juce_gui_basics/mouse/juce_DragAndDropContainer.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -102,6 +102,9 @@ public: */ var getCurrentDragDescription() const; + /** If a drag is in progress, this allows the image being shown to be dynamically updated. */ + void setCurrentDragImage (const Image& newImage); + /** Utility to find the DragAndDropContainer for a given Component. This will search up this component's parent hierarchy looking for the first @@ -165,6 +168,12 @@ protected: virtual bool shouldDropFilesWhenDraggedExternally (const DragAndDropTarget::SourceDetails& sourceDetails, StringArray& files, bool& canMoveFiles); + /** Subclasses can override this to be told when a drag starts. */ + virtual void dragOperationStarted(); + + /** Subclasses can override this to be told when a drag finishes. */ + virtual void dragOperationEnded(); + private: //============================================================================== class DragImageComponent; diff --git a/JuceLibraryCode/modules/juce_gui_basics/mouse/juce_DragAndDropTarget.h b/JuceLibraryCode/modules/juce_gui_basics/mouse/juce_DragAndDropTarget.h index d08b085..7d81841 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/mouse/juce_DragAndDropTarget.h +++ b/JuceLibraryCode/modules/juce_gui_basics/mouse/juce_DragAndDropTarget.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_gui_basics/mouse/juce_FileDragAndDropTarget.h b/JuceLibraryCode/modules/juce_gui_basics/mouse/juce_FileDragAndDropTarget.h index 0e3fadf..e949ea3 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/mouse/juce_FileDragAndDropTarget.h +++ b/JuceLibraryCode/modules/juce_gui_basics/mouse/juce_FileDragAndDropTarget.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_gui_basics/mouse/juce_LassoComponent.h b/JuceLibraryCode/modules/juce_gui_basics/mouse/juce_LassoComponent.h index 786ca07..347cd4c 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/mouse/juce_LassoComponent.h +++ b/JuceLibraryCode/modules/juce_gui_basics/mouse/juce_LassoComponent.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_gui_basics/mouse/juce_MouseCursor.cpp b/JuceLibraryCode/modules/juce_gui_basics/mouse/juce_MouseCursor.cpp index 7aef739..f1b834c 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/mouse/juce_MouseCursor.cpp +++ b/JuceLibraryCode/modules/juce_gui_basics/mouse/juce_MouseCursor.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -128,7 +128,7 @@ private: SpinLock MouseCursor::SharedCursorHandle::lock; //============================================================================== -MouseCursor::MouseCursor() +MouseCursor::MouseCursor() noexcept : cursorHandle (nullptr) { } diff --git a/JuceLibraryCode/modules/juce_gui_basics/mouse/juce_MouseCursor.h b/JuceLibraryCode/modules/juce_gui_basics/mouse/juce_MouseCursor.h index 45bf3a6..36b6433 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/mouse/juce_MouseCursor.h +++ b/JuceLibraryCode/modules/juce_gui_basics/mouse/juce_MouseCursor.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -72,10 +72,10 @@ public: //============================================================================== /** Creates the standard arrow cursor. */ - MouseCursor(); + MouseCursor() noexcept; /** Creates one of the standard mouse cursor */ - MouseCursor (StandardCursorType type); + MouseCursor (StandardCursorType); /** Creates a custom cursor from an image. diff --git a/JuceLibraryCode/modules/juce_gui_basics/mouse/juce_MouseEvent.cpp b/JuceLibraryCode/modules/juce_gui_basics/mouse/juce_MouseEvent.cpp index db1ad12..517b198 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/mouse/juce_MouseEvent.cpp +++ b/JuceLibraryCode/modules/juce_gui_basics/mouse/juce_MouseEvent.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -23,17 +23,18 @@ */ MouseEvent::MouseEvent (MouseInputSource inputSource, - Point position, + Point pos, ModifierKeys modKeys, Component* const eventComp, Component* const originator, Time time, - Point downPos, + Point downPos, Time downTime, const int numClicks, const bool mouseWasDragged) noexcept - : x (position.x), - y (position.y), + : position (pos), + x (roundToInt (pos.x)), + y (roundToInt (pos.y)), mods (modKeys), eventComponent (eventComp), originalComponent (originator), @@ -55,19 +56,26 @@ MouseEvent MouseEvent::getEventRelativeTo (Component* const otherComponent) cons { jassert (otherComponent != nullptr); - return MouseEvent (source, otherComponent->getLocalPoint (eventComponent, getPosition()), + return MouseEvent (source, otherComponent->getLocalPoint (eventComponent, position), mods, otherComponent, originalComponent, eventTime, otherComponent->getLocalPoint (eventComponent, mouseDownPos), mouseDownTime, numberOfClicks, wasMovedSinceMouseDown != 0); } -MouseEvent MouseEvent::withNewPosition (Point newPosition) const noexcept +MouseEvent MouseEvent::withNewPosition (Point newPosition) const noexcept { return MouseEvent (source, newPosition, mods, eventComponent, originalComponent, eventTime, mouseDownPos, mouseDownTime, numberOfClicks, wasMovedSinceMouseDown != 0); } +MouseEvent MouseEvent::withNewPosition (Point newPosition) const noexcept +{ + return MouseEvent (source, newPosition.toFloat(), mods, eventComponent, originalComponent, + eventTime, mouseDownPos, mouseDownTime, + numberOfClicks, wasMovedSinceMouseDown != 0); +} + //============================================================================== bool MouseEvent::mouseWasClicked() const noexcept { @@ -86,17 +94,17 @@ int MouseEvent::getLengthOfMousePress() const noexcept Point MouseEvent::getPosition() const noexcept { return Point (x, y); } Point MouseEvent::getScreenPosition() const { return eventComponent->localPointToGlobal (getPosition()); } -Point MouseEvent::getMouseDownPosition() const noexcept { return mouseDownPos; } -Point MouseEvent::getMouseDownScreenPosition() const { return eventComponent->localPointToGlobal (mouseDownPos); } +Point MouseEvent::getMouseDownPosition() const noexcept { return mouseDownPos.roundToInt(); } +Point MouseEvent::getMouseDownScreenPosition() const { return eventComponent->localPointToGlobal (mouseDownPos).roundToInt(); } -Point MouseEvent::getOffsetFromDragStart() const noexcept { return getPosition() - mouseDownPos; } -int MouseEvent::getDistanceFromDragStart() const noexcept { return mouseDownPos.getDistanceFrom (getPosition()); } +Point MouseEvent::getOffsetFromDragStart() const noexcept { return (position - mouseDownPos).roundToInt(); } +int MouseEvent::getDistanceFromDragStart() const noexcept { return roundToInt (mouseDownPos.getDistanceFrom (position)); } -int MouseEvent::getMouseDownX() const noexcept { return mouseDownPos.x; } -int MouseEvent::getMouseDownY() const noexcept { return mouseDownPos.y; } +int MouseEvent::getMouseDownX() const noexcept { return roundToInt (mouseDownPos.x); } +int MouseEvent::getMouseDownY() const noexcept { return roundToInt (mouseDownPos.y); } -int MouseEvent::getDistanceFromDragStartX() const noexcept { return x - mouseDownPos.x; } -int MouseEvent::getDistanceFromDragStartY() const noexcept { return y - mouseDownPos.y; } +int MouseEvent::getDistanceFromDragStartX() const noexcept { return getOffsetFromDragStart().x; } +int MouseEvent::getDistanceFromDragStartY() const noexcept { return getOffsetFromDragStart().y; } int MouseEvent::getScreenX() const { return getScreenPosition().x; } int MouseEvent::getScreenY() const { return getScreenPosition().y; } diff --git a/JuceLibraryCode/modules/juce_gui_basics/mouse/juce_MouseEvent.h b/JuceLibraryCode/modules/juce_gui_basics/mouse/juce_MouseEvent.h index 87328b1..5cc6c78 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/mouse/juce_MouseEvent.h +++ b/JuceLibraryCode/modules/juce_gui_basics/mouse/juce_MouseEvent.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -57,12 +57,12 @@ public: @param mouseWasDragged whether the mouse has been dragged significantly since the previous mouse-down */ MouseEvent (MouseInputSource source, - Point position, + Point position, ModifierKeys modifiers, Component* eventComponent, Component* originator, Time eventTime, - Point mouseDownPos, + Point mouseDownPos, Time mouseDownTime, int numberOfClicks, bool mouseWasDragged) noexcept; @@ -71,10 +71,22 @@ public: ~MouseEvent() noexcept; //============================================================================== + /** The position of the mouse when the event occurred. + + This value is relative to the top-left of the component to which the + event applies (as indicated by the MouseEvent::eventComponent field). + + This is a more accurate floating-point version of the position returned by + getPosition() and the integer x and y member variables. + */ + const Point position; + /** The x-position of the mouse when the event occurred. This value is relative to the top-left of the component to which the event applies (as indicated by the MouseEvent::eventComponent field). + + For a floating-point coordinate, see MouseEvent::position */ const int x; @@ -82,6 +94,8 @@ public: This value is relative to the top-left of the component to which the event applies (as indicated by the MouseEvent::eventComponent field). + + For a floating-point coordinate, see MouseEvent::position */ const int y; @@ -130,25 +144,19 @@ public: //============================================================================== /** Returns the x coordinate of the last place that a mouse was pressed. - The coordinate is relative to the component specified in MouseEvent::component. - @see getDistanceFromDragStart, getDistanceFromDragStartX, mouseWasClicked */ int getMouseDownX() const noexcept; /** Returns the y coordinate of the last place that a mouse was pressed. - The coordinate is relative to the component specified in MouseEvent::component. - @see getDistanceFromDragStart, getDistanceFromDragStartX, mouseWasClicked */ int getMouseDownY() const noexcept; /** Returns the coordinates of the last place that a mouse was pressed. - The coordinates are relative to the component specified in MouseEvent::component. - @see getDistanceFromDragStart, getDistanceFromDragStartX, mouseWasClicked */ Point getMouseDownPosition() const noexcept; @@ -221,6 +229,8 @@ public: This position is relative to the top-left of the component to which the event applies (as indicated by the MouseEvent::eventComponent field). + + For a floating-point position, see MouseEvent::position */ Point getPosition() const noexcept; @@ -269,6 +279,12 @@ public: */ MouseEvent getEventRelativeTo (Component* newComponent) const noexcept; + /** Creates a copy of this event with a different position. + All other members of the event object are the same, but the x and y are + replaced with these new values. + */ + MouseEvent withNewPosition (Point newPosition) const noexcept; + /** Creates a copy of this event with a different position. All other members of the event object are the same, but the x and y are replaced with these new values. @@ -297,7 +313,7 @@ public: private: //============================================================================== - const Point mouseDownPos; + const Point mouseDownPos; const uint8 numberOfClicks, wasMovedSinceMouseDown; MouseEvent& operator= (const MouseEvent&); @@ -338,6 +354,10 @@ struct MouseWheelDetails /** If true, then the wheel has continuous, un-stepped motion. */ bool isSmooth; + + /** If true, then this event is part of the intertial momentum phase that follows + the wheel being released. */ + bool isInertial; }; diff --git a/JuceLibraryCode/modules/juce_gui_basics/mouse/juce_MouseInactivityDetector.cpp b/JuceLibraryCode/modules/juce_gui_basics/mouse/juce_MouseInactivityDetector.cpp index b450181..03aa87c 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/mouse/juce_MouseInactivityDetector.cpp +++ b/JuceLibraryCode/modules/juce_gui_basics/mouse/juce_MouseInactivityDetector.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -23,7 +23,7 @@ */ MouseInactivityDetector::MouseInactivityDetector (Component& c) - : targetComp (c), delayMs (1500), isActive (true) + : targetComp (c), delayMs (1500), toleranceDistance (15), isActive (true) { targetComp.addMouseListener (this, true); } @@ -33,11 +33,8 @@ MouseInactivityDetector::~MouseInactivityDetector() targetComp.removeMouseListener (this); } -void MouseInactivityDetector::setDelay (int newDelayMilliseconds) -{ - delayMs = newDelayMilliseconds; -} - +void MouseInactivityDetector::setDelay (int newDelay) noexcept { delayMs = newDelay; } +void MouseInactivityDetector::setMouseMoveTolerance (int newDistance) noexcept { toleranceDistance = newDistance; } void MouseInactivityDetector::addListener (Listener* l) { listenerList.add (l); } void MouseInactivityDetector::removeListener (Listener* l) { listenerList.remove (l); } @@ -51,7 +48,7 @@ void MouseInactivityDetector::wakeUp (const MouseEvent& e, bool alwaysWake) { const Point newPos (e.getEventRelativeTo (&targetComp).getPosition()); - if ((! isActive) && (alwaysWake || e.source.isTouch() || newPos.getDistanceFrom (lastMousePos) > 15)) + if ((! isActive) && (alwaysWake || e.source.isTouch() || newPos.getDistanceFrom (lastMousePos) > toleranceDistance)) setActive (true); if (lastMousePos != newPos) diff --git a/JuceLibraryCode/modules/juce_gui_basics/mouse/juce_MouseInactivityDetector.h b/JuceLibraryCode/modules/juce_gui_basics/mouse/juce_MouseInactivityDetector.h index a2f6533..949f059 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/mouse/juce_MouseInactivityDetector.h +++ b/JuceLibraryCode/modules/juce_gui_basics/mouse/juce_MouseInactivityDetector.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -54,7 +54,12 @@ public: /** Sets the time for which the mouse must be still before the callback is triggered. */ - void setDelay (int newDelayMilliseconds); + void setDelay (int newDelayMilliseconds) noexcept; + + /** Sets the number of pixels by which the cursor is allowed to drift before it is + considered to be actively moved. + */ + void setMouseMoveTolerance (int pixelsNeededToTrigger) noexcept; //============================================================================== /** Classes should implement this to receive callbacks from a MouseInactivityDetector @@ -84,7 +89,7 @@ private: Component& targetComp; ListenerList listenerList; Point lastMousePos; - int delayMs; + int delayMs, toleranceDistance; bool isActive; void timerCallback() override; diff --git a/JuceLibraryCode/modules/juce_gui_basics/mouse/juce_MouseInputSource.cpp b/JuceLibraryCode/modules/juce_gui_basics/mouse/juce_MouseInputSource.cpp index 42df454..77be371 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/mouse/juce_MouseInputSource.cpp +++ b/JuceLibraryCode/modules/juce_gui_basics/mouse/juce_MouseInputSource.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -58,7 +58,7 @@ public: return lastPeer; } - static Point screenPosToLocalPos (Component& comp, Point pos) + static Point screenPosToLocalPos (Component& comp, Point pos) { if (ComponentPeer* const peer = comp.getPeer()) { @@ -70,23 +70,25 @@ public: return comp.getLocalPoint (nullptr, ScalingHelpers::unscaledScreenPosToScaled (comp, pos)); } - Component* findComponentAt (Point screenPos) + Component* findComponentAt (Point screenPos) { if (ComponentPeer* const peer = getPeer()) { - Point relativePos (ScalingHelpers::unscaledScreenPosToScaled (peer->getComponent(), - peer->globalToLocal (screenPos))); + Point relativePos (ScalingHelpers::unscaledScreenPosToScaled (peer->getComponent(), + peer->globalToLocal (screenPos))); Component& comp = peer->getComponent(); + const Point pos (relativePos.roundToInt()); + // (the contains() call is needed to test for overlapping desktop windows) - if (comp.contains (relativePos)) - return comp.getComponentAt (relativePos); + if (comp.contains (pos)) + return comp.getComponentAt (pos); } return nullptr; } - Point getScreenPosition() const + Point getScreenPosition() const { // This needs to return the live position if possible, but it mustn't update the lastScreenPos // value, because that can cause continuity problems. @@ -95,7 +97,7 @@ public: : lastScreenPos)); } - void setScreenPosition (Point p) + void setScreenPosition (Point p) { MouseInputSource::setRawMousePosition (ScalingHelpers::scaledScreenPosToUnscaled (p)); } @@ -109,49 +111,49 @@ public: #define JUCE_MOUSE_EVENT_DBG(desc) #endif - void sendMouseEnter (Component& comp, Point screenPos, Time time) + void sendMouseEnter (Component& comp, Point screenPos, Time time) { JUCE_MOUSE_EVENT_DBG ("enter") comp.internalMouseEnter (MouseInputSource (this), screenPosToLocalPos (comp, screenPos), time); } - void sendMouseExit (Component& comp, Point screenPos, Time time) + void sendMouseExit (Component& comp, Point screenPos, Time time) { JUCE_MOUSE_EVENT_DBG ("exit") comp.internalMouseExit (MouseInputSource (this), screenPosToLocalPos (comp, screenPos), time); } - void sendMouseMove (Component& comp, Point screenPos, Time time) + void sendMouseMove (Component& comp, Point screenPos, Time time) { JUCE_MOUSE_EVENT_DBG ("move") comp.internalMouseMove (MouseInputSource (this), screenPosToLocalPos (comp, screenPos), time); } - void sendMouseDown (Component& comp, Point screenPos, Time time) + void sendMouseDown (Component& comp, Point screenPos, Time time) { JUCE_MOUSE_EVENT_DBG ("down") comp.internalMouseDown (MouseInputSource (this), screenPosToLocalPos (comp, screenPos), time); } - void sendMouseDrag (Component& comp, Point screenPos, Time time) + void sendMouseDrag (Component& comp, Point screenPos, Time time) { JUCE_MOUSE_EVENT_DBG ("drag") comp.internalMouseDrag (MouseInputSource (this), screenPosToLocalPos (comp, screenPos), time); } - void sendMouseUp (Component& comp, Point screenPos, Time time, const ModifierKeys oldMods) + void sendMouseUp (Component& comp, Point screenPos, Time time, const ModifierKeys oldMods) { JUCE_MOUSE_EVENT_DBG ("up") comp.internalMouseUp (MouseInputSource (this), screenPosToLocalPos (comp, screenPos), time, oldMods); } - void sendMouseWheel (Component& comp, Point screenPos, Time time, const MouseWheelDetails& wheel) + void sendMouseWheel (Component& comp, Point screenPos, Time time, const MouseWheelDetails& wheel) { JUCE_MOUSE_EVENT_DBG ("wheel") comp.internalMouseWheel (MouseInputSource (this), screenPosToLocalPos (comp, screenPos), time, wheel); } - void sendMagnifyGesture (Component& comp, Point screenPos, Time time, const float amount) + void sendMagnifyGesture (Component& comp, Point screenPos, Time time, const float amount) { JUCE_MOUSE_EVENT_DBG ("magnify") comp.internalMagnifyGesture (MouseInputSource (this), screenPosToLocalPos (comp, screenPos), time, amount); @@ -159,7 +161,7 @@ public: //============================================================================== // (returns true if the button change caused a modal event loop) - bool setButtons (Point screenPos, Time time, const ModifierKeys newButtonState) + bool setButtons (Point screenPos, Time time, const ModifierKeys newButtonState) { if (buttonState == newButtonState) return false; @@ -209,7 +211,7 @@ public: return lastCounter != mouseEventCounter; } - void setComponentUnderMouse (Component* const newComponent, Point screenPos, Time time) + void setComponentUnderMouse (Component* const newComponent, Point screenPos, Time time) { Component* current = getComponentUnderMouse(); @@ -242,7 +244,7 @@ public: } } - void setPeer (ComponentPeer& newPeer, Point screenPos, Time time) + void setPeer (ComponentPeer& newPeer, Point screenPos, Time time) { ModifierKeys::updateCurrentModifiers(); @@ -254,7 +256,7 @@ public: } } - void setScreenPos (Point newScreenPos, Time time, const bool forceUpdate) + void setScreenPos (Point newScreenPos, Time time, const bool forceUpdate) { if (! isDragging()) setComponentUnderMouse (findComponentAt (newScreenPos), newScreenPos, time); @@ -272,7 +274,7 @@ public: sendMouseDrag (*current, newScreenPos + unboundedMouseOffset, time); if (isUnboundedMouseModeOn) - handleUnboundedDrag (current); + handleUnboundedDrag (*current); } else { @@ -285,11 +287,11 @@ public: } //============================================================================== - void handleEvent (ComponentPeer& newPeer, Point positionWithinPeer, Time time, const ModifierKeys newMods) + void handleEvent (ComponentPeer& newPeer, Point positionWithinPeer, Time time, const ModifierKeys newMods) { lastTime = time; ++mouseEventCounter; - const Point screenPos (newPeer.localToGlobal (positionWithinPeer)); + const Point screenPos (newPeer.localToGlobal (positionWithinPeer)); if (isDragging() && newMods.isAnyMouseButtonDown()) { @@ -311,8 +313,8 @@ public: } } - Component* getTargetForGesture (ComponentPeer& peer, Point positionWithinPeer, - Time time, Point& screenPos) + Component* getTargetForGesture (ComponentPeer& peer, Point positionWithinPeer, + Time time, Point& screenPos) { lastTime = time; ++mouseEventCounter; @@ -325,37 +327,41 @@ public: return isDragging() ? nullptr : getComponentUnderMouse(); } - void handleWheel (ComponentPeer& peer, Point positionWithinPeer, + void handleWheel (ComponentPeer& peer, Point positionWithinPeer, Time time, const MouseWheelDetails& wheel) { Desktop::getInstance().incrementMouseWheelCounter(); + Point screenPos; - Point screenPos; - if (Component* current = getTargetForGesture (peer, positionWithinPeer, time, screenPos)) - sendMouseWheel (*current, screenPos, time, wheel); + // This will make sure that when the wheel spins in its inertial phase, any events + // continue to be sent to the last component that the mouse was over when it was being + // actively controlled by the user. This avoids confusion when scrolling through nested + // scrollable components. + if (lastNonInertialWheelTarget == nullptr || ! wheel.isInertial) + lastNonInertialWheelTarget = getTargetForGesture (peer, positionWithinPeer, time, screenPos); + + if (Component* target = lastNonInertialWheelTarget) + sendMouseWheel (*target, screenPos, time, wheel); } - void handleMagnifyGesture (ComponentPeer& peer, Point positionWithinPeer, + void handleMagnifyGesture (ComponentPeer& peer, Point positionWithinPeer, Time time, const float scaleFactor) { - Point screenPos; + Point screenPos; if (Component* current = getTargetForGesture (peer, positionWithinPeer, time, screenPos)) sendMagnifyGesture (*current, screenPos, time, scaleFactor); } //============================================================================== Time getLastMouseDownTime() const noexcept { return mouseDowns[0].time; } - Point getLastMouseDownPosition() const noexcept { return ScalingHelpers::unscaledScreenPosToScaled (mouseDowns[0].position); } + Point getLastMouseDownPosition() const noexcept { return ScalingHelpers::unscaledScreenPosToScaled (mouseDowns[0].position); } int getNumberOfMultipleClicks() const noexcept { - int numClicks = 0; + int numClicks = 1; - if (mouseDowns[0].time != Time()) + if (! hasMouseMovedSignificantlySincePressed()) { - if (! mouseMovedSignificantlySincePressed) - ++numClicks; - for (int i = 1; i < numElementsInArray (mouseDowns); ++i) { if (mouseDowns[0].canBePartOfMultipleClickWith (mouseDowns[i], MouseEvent::getDoubleClickTimeout() * jmin (i, 2))) @@ -397,33 +403,34 @@ public: { // when released, return the mouse to within the component's bounds if (Component* current = getComponentUnderMouse()) - Desktop::setMousePosition (current->getScreenBounds() - .getConstrainedPoint (lastScreenPos)); + setScreenPosition (current->getScreenBounds().toFloat() + .getConstrainedPoint (ScalingHelpers::unscaledScreenPosToScaled (lastScreenPos))); } isUnboundedMouseModeOn = enable; - unboundedMouseOffset = Point(); + unboundedMouseOffset = Point(); revealCursor (true); } } - void handleUnboundedDrag (Component* current) + void handleUnboundedDrag (Component& current) { - const Rectangle screenArea (current->getParentMonitorArea().expanded (-2, -2)); + const Rectangle componentScreenBounds + = ScalingHelpers::scaledScreenPosToUnscaled (current.getParentMonitorArea().reduced (2, 2).toFloat()); - if (! screenArea.contains (lastScreenPos)) + if (! componentScreenBounds.contains (lastScreenPos)) { - const Point componentCentre (current->getScreenBounds().getCentre()); - unboundedMouseOffset += (lastScreenPos - componentCentre); - Desktop::setMousePosition (componentCentre); + const Point componentCentre (current.getScreenBounds().toFloat().getCentre()); + unboundedMouseOffset += (lastScreenPos - ScalingHelpers::scaledScreenPosToUnscaled (componentCentre)); + setScreenPosition (componentCentre); } else if (isCursorVisibleUntilOffscreen && (! unboundedMouseOffset.isOrigin()) - && screenArea.contains (lastScreenPos + unboundedMouseOffset)) + && componentScreenBounds.contains (lastScreenPos + unboundedMouseOffset)) { - Desktop::setMousePosition (lastScreenPos + unboundedMouseOffset); - unboundedMouseOffset = Point(); + MouseInputSource::setRawMousePosition (lastScreenPos + unboundedMouseOffset); + unboundedMouseOffset = Point(); } } @@ -461,14 +468,13 @@ public: //============================================================================== const int index; const bool isMouseDevice; - Point lastScreenPos; + Point lastScreenPos, unboundedMouseOffset; // NB: these are unscaled coords ModifierKeys buttonState; - Point unboundedMouseOffset; bool isUnboundedMouseModeOn, isCursorVisibleUntilOffscreen; private: - WeakReference componentUnderMouse; + WeakReference componentUnderMouse, lastNonInertialWheelTarget; ComponentPeer* lastPeer; void* currentCursorHandle; @@ -478,7 +484,7 @@ private: { RecentMouseDown() noexcept : peerID (0) {} - Point position; + Point position; Time time; ModifierKeys buttons; uint32 peerID; @@ -486,8 +492,8 @@ private: bool canBePartOfMultipleClickWith (const RecentMouseDown& other, const int maxTimeBetweenMs) const { return time - other.time < RelativeTime::milliseconds (maxTimeBetweenMs) - && abs (position.x - other.position.x) < 8 - && abs (position.y - other.position.y) < 8 + && std::abs (position.x - other.position.x) < 8 + && std::abs (position.y - other.position.y) < 8 && buttons == other.buttons && peerID == other.peerID; } @@ -497,7 +503,7 @@ private: Time lastTime; bool mouseMovedSignificantlySincePressed; - void registerMouseDown (Point screenPos, Time time, + void registerMouseDown (Point screenPos, Time time, Component& component, const ModifierKeys modifiers) noexcept { for (int i = numElementsInArray (mouseDowns); --i > 0;) @@ -513,9 +519,10 @@ private: mouseDowns[0].peerID = 0; mouseMovedSignificantlySincePressed = false; + lastNonInertialWheelTarget = nullptr; } - void registerMouseDrag (Point screenPos) noexcept + void registerMouseDrag (Point screenPos) noexcept { mouseMovedSignificantlySincePressed = mouseMovedSignificantlySincePressed || mouseDowns[0].position.getDistanceFrom (screenPos) >= 4; @@ -535,47 +542,44 @@ MouseInputSource& MouseInputSource::operator= (const MouseInputSource& other) no return *this; } -bool MouseInputSource::isMouse() const { return pimpl->isMouseDevice; } -bool MouseInputSource::isTouch() const { return ! isMouse(); } -bool MouseInputSource::canHover() const { return isMouse(); } -bool MouseInputSource::hasMouseWheel() const { return isMouse(); } -int MouseInputSource::getIndex() const { return pimpl->index; } -bool MouseInputSource::isDragging() const { return pimpl->isDragging(); } -Point MouseInputSource::getScreenPosition() const { return pimpl->getScreenPosition(); } -ModifierKeys MouseInputSource::getCurrentModifiers() const { return pimpl->getCurrentModifiers(); } -Component* MouseInputSource::getComponentUnderMouse() const { return pimpl->getComponentUnderMouse(); } -void MouseInputSource::triggerFakeMove() const { pimpl->triggerFakeMove(); } -int MouseInputSource::getNumberOfMultipleClicks() const noexcept { return pimpl->getNumberOfMultipleClicks(); } -Time MouseInputSource::getLastMouseDownTime() const noexcept { return pimpl->getLastMouseDownTime(); } -Point MouseInputSource::getLastMouseDownPosition() const noexcept { return pimpl->getLastMouseDownPosition(); } +bool MouseInputSource::isMouse() const { return pimpl->isMouseDevice; } +bool MouseInputSource::isTouch() const { return ! isMouse(); } +bool MouseInputSource::canHover() const { return isMouse(); } +bool MouseInputSource::hasMouseWheel() const { return isMouse(); } +int MouseInputSource::getIndex() const { return pimpl->index; } +bool MouseInputSource::isDragging() const { return pimpl->isDragging(); } +Point MouseInputSource::getScreenPosition() const { return pimpl->getScreenPosition(); } +ModifierKeys MouseInputSource::getCurrentModifiers() const { return pimpl->getCurrentModifiers(); } +Component* MouseInputSource::getComponentUnderMouse() const { return pimpl->getComponentUnderMouse(); } +void MouseInputSource::triggerFakeMove() const { pimpl->triggerFakeMove(); } +int MouseInputSource::getNumberOfMultipleClicks() const noexcept { return pimpl->getNumberOfMultipleClicks(); } +Time MouseInputSource::getLastMouseDownTime() const noexcept { return pimpl->getLastMouseDownTime(); } +Point MouseInputSource::getLastMouseDownPosition() const noexcept { return pimpl->getLastMouseDownPosition(); } bool MouseInputSource::hasMouseMovedSignificantlySincePressed() const noexcept { return pimpl->hasMouseMovedSignificantlySincePressed(); } -bool MouseInputSource::canDoUnboundedMovement() const noexcept { return isMouse(); } +bool MouseInputSource::canDoUnboundedMovement() const noexcept { return isMouse(); } void MouseInputSource::enableUnboundedMouseMovement (bool isEnabled, bool keepCursorVisibleUntilOffscreen) const - { pimpl->enableUnboundedMouseMovement (isEnabled, keepCursorVisibleUntilOffscreen); } -bool MouseInputSource::isUnboundedMouseMovementEnabled() const { return pimpl->isUnboundedMouseModeOn; } -bool MouseInputSource::hasMouseCursor() const noexcept { return isMouse(); } -void MouseInputSource::showMouseCursor (const MouseCursor& cursor) { pimpl->showMouseCursor (cursor, false); } -void MouseInputSource::hideCursor() { pimpl->hideCursor(); } -void MouseInputSource::revealCursor() { pimpl->revealCursor (false); } -void MouseInputSource::forceMouseCursorUpdate() { pimpl->revealCursor (true); } -void MouseInputSource::setScreenPosition (Point p) { pimpl->setScreenPosition (p); } + { pimpl->enableUnboundedMouseMovement (isEnabled, keepCursorVisibleUntilOffscreen); } +bool MouseInputSource::isUnboundedMouseMovementEnabled() const { return pimpl->isUnboundedMouseModeOn; } +bool MouseInputSource::hasMouseCursor() const noexcept { return isMouse(); } +void MouseInputSource::showMouseCursor (const MouseCursor& cursor) { pimpl->showMouseCursor (cursor, false); } +void MouseInputSource::hideCursor() { pimpl->hideCursor(); } +void MouseInputSource::revealCursor() { pimpl->revealCursor (false); } +void MouseInputSource::forceMouseCursorUpdate() { pimpl->revealCursor (true); } +void MouseInputSource::setScreenPosition (Point p) { pimpl->setScreenPosition (p); } -void MouseInputSource::handleEvent (ComponentPeer& peer, Point positionWithinPeer, - const int64 time, const ModifierKeys mods) +void MouseInputSource::handleEvent (ComponentPeer& peer, Point pos, int64 time, ModifierKeys mods) { - pimpl->handleEvent (peer, positionWithinPeer, Time (time), mods.withOnlyMouseButtons()); + pimpl->handleEvent (peer, pos, Time (time), mods.withOnlyMouseButtons()); } -void MouseInputSource::handleWheel (ComponentPeer& peer, Point positionWithinPeer, - const int64 time, const MouseWheelDetails& wheel) +void MouseInputSource::handleWheel (ComponentPeer& peer, Point pos, int64 time, const MouseWheelDetails& wheel) { - pimpl->handleWheel (peer, positionWithinPeer, Time (time), wheel); + pimpl->handleWheel (peer, pos, Time (time), wheel); } -void MouseInputSource::handleMagnifyGesture (ComponentPeer& peer, Point positionWithinPeer, - const int64 time, const float scaleFactor) +void MouseInputSource::handleMagnifyGesture (ComponentPeer& peer, Point pos, int64 time, float scaleFactor) { - pimpl->handleMagnifyGesture (peer, positionWithinPeer, Time (time), scaleFactor); + pimpl->handleMagnifyGesture (peer, pos, Time (time), scaleFactor); } //============================================================================== diff --git a/JuceLibraryCode/modules/juce_gui_basics/mouse/juce_MouseInputSource.h b/JuceLibraryCode/modules/juce_gui_basics/mouse/juce_MouseInputSource.h index c8ab0df..7bf19c5 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/mouse/juce_MouseInputSource.h +++ b/JuceLibraryCode/modules/juce_gui_basics/mouse/juce_MouseInputSource.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -88,7 +88,7 @@ public: bool isDragging() const; /** Returns the last-known screen position of this source. */ - Point getScreenPosition() const; + Point getScreenPosition() const; /** Returns a set of modifiers that indicate which buttons are currently held down on this device. @@ -114,7 +114,7 @@ public: Time getLastMouseDownTime() const noexcept; /** Returns the screen position at which the last mouse-down occurred. */ - Point getLastMouseDownPosition() const noexcept; + Point getLastMouseDownPosition() const noexcept; /** Returns true if this mouse is currently down, and if it has been dragged more than a couple of pixels from the place it was pressed. @@ -162,7 +162,7 @@ public: bool isUnboundedMouseMovementEnabled() const; /** Attempts to set this mouse pointer's screen position. */ - void setScreenPosition (Point newPosition); + void setScreenPosition (Point newPosition); private: //============================================================================== @@ -174,12 +174,12 @@ private: struct SourceList; explicit MouseInputSource (MouseInputSourceInternal*) noexcept; - void handleEvent (ComponentPeer&, Point, int64 time, const ModifierKeys); - void handleWheel (ComponentPeer&, Point, int64 time, const MouseWheelDetails&); - void handleMagnifyGesture (ComponentPeer&, Point, int64 time, float scaleFactor); + void handleEvent (ComponentPeer&, Point, int64 time, ModifierKeys); + void handleWheel (ComponentPeer&, Point, int64 time, const MouseWheelDetails&); + void handleMagnifyGesture (ComponentPeer&, Point, int64 time, float scaleFactor); - static Point getCurrentRawMousePosition(); - static void setRawMousePosition (Point); + static Point getCurrentRawMousePosition(); + static void setRawMousePosition (Point); JUCE_LEAK_DETECTOR (MouseInputSource) }; diff --git a/JuceLibraryCode/modules/juce_gui_basics/mouse/juce_MouseListener.cpp b/JuceLibraryCode/modules/juce_gui_basics/mouse/juce_MouseListener.cpp index f1ad122..3021bcb 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/mouse/juce_MouseListener.cpp +++ b/JuceLibraryCode/modules/juce_gui_basics/mouse/juce_MouseListener.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_gui_basics/mouse/juce_MouseListener.h b/JuceLibraryCode/modules/juce_gui_basics/mouse/juce_MouseListener.h index 54069c5..5aab50b 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/mouse/juce_MouseListener.h +++ b/JuceLibraryCode/modules/juce_gui_basics/mouse/juce_MouseListener.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_gui_basics/mouse/juce_SelectedItemSet.h b/JuceLibraryCode/modules/juce_gui_basics/mouse/juce_SelectedItemSet.h index 20f1f7b..2905dbd 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/mouse/juce_SelectedItemSet.h +++ b/JuceLibraryCode/modules/juce_gui_basics/mouse/juce_SelectedItemSet.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -38,8 +38,6 @@ To be informed when items are selected/deselected, register a ChangeListener with this object. - - @see SelectableObject */ template class SelectedItemSet : public ChangeBroadcaster diff --git a/JuceLibraryCode/modules/juce_gui_basics/mouse/juce_TextDragAndDropTarget.h b/JuceLibraryCode/modules/juce_gui_basics/mouse/juce_TextDragAndDropTarget.h index 60fa491..90e1713 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/mouse/juce_TextDragAndDropTarget.h +++ b/JuceLibraryCode/modules/juce_gui_basics/mouse/juce_TextDragAndDropTarget.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_gui_basics/mouse/juce_TooltipClient.h b/JuceLibraryCode/modules/juce_gui_basics/mouse/juce_TooltipClient.h index 9fc0118..06cd315 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/mouse/juce_TooltipClient.h +++ b/JuceLibraryCode/modules/juce_gui_basics/mouse/juce_TooltipClient.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_gui_basics/native/juce_MultiTouchMapper.h b/JuceLibraryCode/modules/juce_gui_basics/native/juce_MultiTouchMapper.h index 66187e9..dd866b5 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/native/juce_MultiTouchMapper.h +++ b/JuceLibraryCode/modules/juce_gui_basics/native/juce_MultiTouchMapper.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_gui_basics/native/juce_android_FileChooser.cpp b/JuceLibraryCode/modules/juce_gui_basics/native/juce_android_FileChooser.cpp index 78f157e..f563fea 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/native/juce_android_FileChooser.cpp +++ b/JuceLibraryCode/modules/juce_gui_basics/native/juce_android_FileChooser.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_gui_basics/native/juce_android_Windowing.cpp b/JuceLibraryCode/modules/juce_gui_basics/native/juce_android_Windowing.cpp index 02353be..94e69f5 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/native/juce_android_Windowing.cpp +++ b/JuceLibraryCode/modules/juce_gui_basics/native/juce_android_Windowing.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -41,9 +41,15 @@ JUCE_JNI_CALLBACK (JUCE_ANDROID_ACTIVITY_CLASSNAME, launchApp, void, (JNIEnv* en initialiseJuce_GUI(); - JUCEApplicationBase* app = JUCEApplicationBase::createInstance(); - if (! app->initialiseApp()) - exit (0); + if (JUCEApplicationBase* app = JUCEApplicationBase::createInstance()) + { + if (! app->initialiseApp()) + exit (app->shutdownApp()); + } + else + { + jassertfalse; // you must supply an application object for an android app! + } jassert (MessageManager::getInstance()->isThisTheMessageThread()); } @@ -106,12 +112,14 @@ public: : ComponentPeer (comp, windowStyleFlags), usingAndroidGraphics (false), fullScreen (false), - sizeAllocated (0) + sizeAllocated (0), + scale ((float) Desktop::getInstance().getDisplays().getMainDisplay().scale) { // NB: must not put this in the initialiser list, as it invokes a callback, // which will fail if the peer is only half-constructed. view = GlobalRef (android.activity.callObjectMethod (JuceAppActivity.createNewView, - component.isOpaque(), (jlong) this)); + (jboolean) component.isOpaque(), + (jlong) this)); if (isFocused()) handleFocusGain(); @@ -182,8 +190,10 @@ public: view.callVoidMethod (ComponentPeerView.setViewName, javaString (title).get()); } - void setBounds (const Rectangle& r, bool isNowFullScreen) override + void setBounds (const Rectangle& userRect, bool isNowFullScreen) override { + Rectangle r = userRect * scale; + if (MessageManager::getInstance()->isThisTheMessageThread()) { fullScreen = isNowFullScreen; @@ -217,7 +227,7 @@ public: return Rectangle (view.callIntMethod (ComponentPeerView.getLeft), view.callIntMethod (ComponentPeerView.getTop), view.callIntMethod (ComponentPeerView.getWidth), - view.callIntMethod (ComponentPeerView.getHeight)); + view.callIntMethod (ComponentPeerView.getHeight)) / scale; } void handleScreenSizeChange() @@ -231,17 +241,17 @@ public: Point getScreenPosition() const { return Point (view.callIntMethod (ComponentPeerView.getLeft), - view.callIntMethod (ComponentPeerView.getTop)); + view.callIntMethod (ComponentPeerView.getTop)) / scale; } - Point localToGlobal (Point relativePosition) override + Point localToGlobal (Point relativePosition) override { - return relativePosition + getScreenPosition(); + return relativePosition + getScreenPosition().toFloat(); } - Point globalToLocal (Point screenPosition) override + Point globalToLocal (Point screenPosition) override { - return screenPosition - getScreenPosition(); + return screenPosition - getScreenPosition().toFloat(); } void setMinimised (bool shouldBeMinimised) override @@ -284,7 +294,8 @@ public: return isPositiveAndBelow (localPos.x, component.getWidth()) && isPositiveAndBelow (localPos.y, component.getHeight()) && ((! trueIfInAChildWindow) || view.callBooleanMethod (ComponentPeerView.containsPoint, - localPos.x, localPos.y)); + localPos.x * scale, + localPos.y * scale)); } BorderSize getFrameSize() const override @@ -315,30 +326,33 @@ public: } //============================================================================== - void handleMouseDownCallback (int index, Point pos, int64 time) + void handleMouseDownCallback (int index, Point sysPos, int64 time) { + Point pos = sysPos / scale; lastMousePos = pos; // this forces a mouse-enter/up event, in case for some reason we didn't get a mouse-up before. - handleMouseEvent (index, pos.toInt(), currentModifiers.withoutMouseButtons(), time); + handleMouseEvent (index, pos, currentModifiers.withoutMouseButtons(), time); if (isValidPeer (this)) - handleMouseDragCallback (index, pos, time); + handleMouseDragCallback (index, sysPos, time); } void handleMouseDragCallback (int index, Point pos, int64 time) { + pos /= scale; lastMousePos = pos; jassert (index < 64); touchesDown = (touchesDown | (1 << (index & 63))); currentModifiers = currentModifiers.withoutMouseButtons().withFlags (ModifierKeys::leftButtonModifier); - handleMouseEvent (index, pos.toInt(), currentModifiers.withoutMouseButtons() - .withFlags (ModifierKeys::leftButtonModifier), time); + handleMouseEvent (index, pos, currentModifiers.withoutMouseButtons() + .withFlags (ModifierKeys::leftButtonModifier), time); } void handleMouseUpCallback (int index, Point pos, int64 time) { + pos /= scale; lastMousePos = pos; jassert (index < 64); @@ -347,7 +361,7 @@ public: if (touchesDown == 0) currentModifiers = currentModifiers.withoutMouseButtons(); - handleMouseEvent (index, pos.toInt(), currentModifiers.withoutMouseButtons(), time); + handleMouseEvent (index, pos, currentModifiers.withoutMouseButtons(), time); } void handleKeyDownCallback (int k, int kc) @@ -384,6 +398,7 @@ public: { case TextInputTarget::textKeyboard: return "text"; case TextInputTarget::numericKeyboard: return "number"; + case TextInputTarget::decimalKeyboard: return "numberDecimal"; case TextInputTarget::urlKeyboard: return "textUri"; case TextInputTarget::emailAddressKeyboard: return "textEmailAddress"; case TextInputTarget::phoneNumberKeyboard: return "phone"; @@ -405,7 +420,7 @@ public: } //============================================================================== - void handlePaintCallback (JNIEnv* env, jobject canvas) + void handlePaintCallback (JNIEnv* env, jobject canvas, jobject paint) { jobject rect = env->CallObjectMethod (canvas, CanvasMinimal.getClipBounds); const int left = env->GetIntField (rect, RectClass.left); @@ -433,6 +448,7 @@ public: { LowLevelGraphicsSoftwareRenderer g (temp); g.setOrigin (-clip.getPosition()); + g.addTransform (AffineTransform::scale (scale)); handlePaint (g); } } @@ -441,12 +457,14 @@ public: env->CallVoidMethod (canvas, CanvasMinimal.drawBitmap, (jintArray) buffer.get(), 0, clip.getWidth(), (jfloat) clip.getX(), (jfloat) clip.getY(), - clip.getWidth(), clip.getHeight(), true, (jobject) 0); + clip.getWidth(), clip.getHeight(), true, paint); } } - void repaint (const Rectangle& area) override + void repaint (const Rectangle& userArea) override { + Rectangle area = userArea * scale; + if (MessageManager::getInstance()->isThisTheMessageThread()) { view.callVoidMethod (ComponentPeerView.invalidate, area.getX(), area.getY(), area.getRight(), area.getBottom()); @@ -499,6 +517,7 @@ private: GlobalRef buffer; bool usingAndroidGraphics, fullScreen; int sizeAllocated; + float scale; class PreallocatedImage : public ImagePixelData { @@ -567,7 +586,7 @@ int64 AndroidComponentPeer::touchesDown = 0; peer->juceMethodInvocation; \ } -JUCE_VIEW_CALLBACK (void, handlePaint, (JNIEnv* env, jobject view, jlong host, jobject canvas), handlePaintCallback (env, canvas)) +JUCE_VIEW_CALLBACK (void, handlePaint, (JNIEnv* env, jobject view, jlong host, jobject canvas, jobject paint), handlePaintCallback (env, canvas, paint)) JUCE_VIEW_CALLBACK (void, handleMouseDown, (JNIEnv* env, jobject view, jlong host, jint i, jfloat x, jfloat y, jlong time), handleMouseDownCallback (i, Point ((float) x, (float) y), (int64) time)) JUCE_VIEW_CALLBACK (void, handleMouseDrag, (JNIEnv* env, jobject view, jlong host, jint i, jfloat x, jfloat y, jlong time), handleMouseDragCallback (i, Point ((float) x, (float) y), (int64) time)) JUCE_VIEW_CALLBACK (void, handleMouseUp, (JNIEnv* env, jobject view, jlong host, jint i, jfloat x, jfloat y, jlong time), handleMouseUpCallback (i, Point ((float) x, (float) y), (int64) time)) @@ -584,7 +603,7 @@ ComponentPeer* Component::createNewPeer (int styleFlags, void*) jobject createOpenGLView (ComponentPeer* peer) { - jobject parentView = static_cast (peer->getNativeHandle()); + jobject parentView = static_cast (peer->getNativeHandle()); return getEnv()->CallObjectMethod (parentView, ComponentPeerView.createGLView); } @@ -611,12 +630,12 @@ bool MouseInputSource::SourceList::addSource() return true; } -Point MouseInputSource::getCurrentRawMousePosition() +Point MouseInputSource::getCurrentRawMousePosition() { - return AndroidComponentPeer::lastMousePos.toInt(); + return AndroidComponentPeer::lastMousePos; } -void MouseInputSource::setRawMousePosition (Point) +void MouseInputSource::setRawMousePosition (Point) { // not needed } @@ -715,11 +734,12 @@ bool juce_areThereAnyAlwaysOnTopWindows() void Desktop::Displays::findDisplays (float masterScale) { Display d; - d.userArea = d.totalArea = Rectangle (android.screenWidth, - android.screenHeight) / masterScale; + d.isMain = true; - d.scale = masterScale; d.dpi = android.dpi; + d.scale = masterScale * (d.dpi / 150.); + d.userArea = d.totalArea = Rectangle (android.screenWidth, + android.screenHeight) / d.scale; displays.add (d); } diff --git a/JuceLibraryCode/modules/juce_gui_basics/native/juce_ios_UIViewComponentPeer.mm b/JuceLibraryCode/modules/juce_gui_basics/native/juce_ios_UIViewComponentPeer.mm index 7919586..6e55d4c 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/native/juce_ios_UIViewComponentPeer.mm +++ b/JuceLibraryCode/modules/juce_gui_basics/native/juce_ios_UIViewComponentPeer.mm @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -24,6 +24,14 @@ class UIViewComponentPeer; +// The way rotation works changed in iOS8.. +static bool isUsingOldRotationMethod() noexcept +{ + static bool isPreV8 = ([[[UIDevice currentDevice] systemVersion] compare: @"8.0" + options: NSNumericSearch] == NSOrderedAscending); + return isPreV8; +} + namespace Orientations { static Desktop::DisplayOrientation convertToJuce (UIInterfaceOrientation orientation) @@ -42,12 +50,15 @@ namespace Orientations static CGAffineTransform getCGTransformFor (const Desktop::DisplayOrientation orientation) noexcept { - switch (orientation) + if (isUsingOldRotationMethod()) { - case Desktop::upsideDown: return CGAffineTransformMake (-1, 0, 0, -1, 0, 0); - case Desktop::rotatedClockwise: return CGAffineTransformMake (0, -1, 1, 0, 0, 0); - case Desktop::rotatedAntiClockwise: return CGAffineTransformMake (0, 1, -1, 0, 0, 0); - default: break; + switch (orientation) + { + case Desktop::upsideDown: return CGAffineTransformMake (-1, 0, 0, -1, 0, 0); + case Desktop::rotatedClockwise: return CGAffineTransformMake (0, -1, 1, 0, 0, 0); + case Desktop::rotatedAntiClockwise: return CGAffineTransformMake (0, 1, -1, 0, 0, 0); + default: break; + } } return CGAffineTransformIdentity; @@ -85,10 +96,10 @@ using namespace juce; - (void) drawRect: (CGRect) r; -- (void) touchesBegan: (NSSet*) touches withEvent: (UIEvent*) event; -- (void) touchesMoved: (NSSet*) touches withEvent: (UIEvent*) event; -- (void) touchesEnded: (NSSet*) touches withEvent: (UIEvent*) event; -- (void) touchesCancelled: (NSSet*) touches withEvent: (UIEvent*) event; +- (void) touchesBegan: (NSSet*) touches withEvent: (UIEvent*) event; +- (void) touchesMoved: (NSSet*) touches withEvent: (UIEvent*) event; +- (void) touchesEnded: (NSSet*) touches withEvent: (UIEvent*) event; +- (void) touchesCancelled: (NSSet*) touches withEvent: (UIEvent*) event; - (BOOL) becomeFirstResponder; - (BOOL) resignFirstResponder; @@ -106,6 +117,7 @@ using namespace juce; - (BOOL) shouldAutorotateToInterfaceOrientation: (UIInterfaceOrientation) interfaceOrientation; - (void) willRotateToInterfaceOrientation: (UIInterfaceOrientation) toInterfaceOrientation duration: (NSTimeInterval) duration; - (void) didRotateFromInterfaceOrientation: (UIInterfaceOrientation) fromInterfaceOrientation; +- (void) viewWillTransitionToSize: (CGSize) size withTransitionCoordinator: (id) coordinator; - (void) viewDidLoad; - (void) viewWillAppear: (BOOL) animated; @@ -145,8 +157,8 @@ public: Rectangle getBounds() const override { return getBounds (! isSharedWindow); } Rectangle getBounds (bool global) const; - Point localToGlobal (Point relativePosition) override; - Point globalToLocal (Point screenPosition) override; + Point localToGlobal (Point relativePosition) override; + Point globalToLocal (Point screenPosition) override; void setAlpha (float newAlpha) override; void setMinimised (bool) override {} bool isMinimised() const override { return false; } @@ -189,7 +201,7 @@ public: bool isSharedWindow, fullScreen, insideDrawRect; static ModifierKeys currentModifiers; - static int64 getMouseTime (UIEvent* e) + static int64 getMouseTime (UIEvent* e) noexcept { return (Time::currentTimeMillis() - Time::getMillisecondCounter()) + (int64) ([e timestamp] * 1000.0); @@ -197,26 +209,29 @@ public: static Rectangle rotatedScreenPosToReal (const Rectangle& r) { - const Rectangle screen (convertToRectInt ([UIScreen mainScreen].bounds)); - - switch ([[UIApplication sharedApplication] statusBarOrientation]) + if (isUsingOldRotationMethod()) { - case UIInterfaceOrientationPortrait: - return r; + const Rectangle screen (convertToRectInt ([UIScreen mainScreen].bounds)); - case UIInterfaceOrientationPortraitUpsideDown: - return Rectangle (screen.getWidth() - r.getRight(), screen.getHeight() - r.getBottom(), - r.getWidth(), r.getHeight()); + switch ([[UIApplication sharedApplication] statusBarOrientation]) + { + case UIInterfaceOrientationPortrait: + return r; - case UIInterfaceOrientationLandscapeLeft: - return Rectangle (r.getY(), screen.getHeight() - r.getRight(), - r.getHeight(), r.getWidth()); + case UIInterfaceOrientationPortraitUpsideDown: + return Rectangle (screen.getWidth() - r.getRight(), screen.getHeight() - r.getBottom(), + r.getWidth(), r.getHeight()); - case UIInterfaceOrientationLandscapeRight: - return Rectangle (screen.getWidth() - r.getBottom(), r.getX(), - r.getHeight(), r.getWidth()); + case UIInterfaceOrientationLandscapeLeft: + return Rectangle (r.getY(), screen.getHeight() - r.getRight(), + r.getHeight(), r.getWidth()); - default: jassertfalse; // unknown orientation! + case UIInterfaceOrientationLandscapeRight: + return Rectangle (screen.getWidth() - r.getBottom(), r.getX(), + r.getHeight(), r.getWidth()); + + default: jassertfalse; // unknown orientation! + } } return r; @@ -224,26 +239,29 @@ public: static Rectangle realScreenPosToRotated (const Rectangle& r) { - const Rectangle screen (convertToRectInt ([UIScreen mainScreen].bounds)); - - switch ([[UIApplication sharedApplication] statusBarOrientation]) + if (isUsingOldRotationMethod()) { - case UIInterfaceOrientationPortrait: - return r; + const Rectangle screen (convertToRectInt ([UIScreen mainScreen].bounds)); - case UIInterfaceOrientationPortraitUpsideDown: - return Rectangle (screen.getWidth() - r.getRight(), screen.getHeight() - r.getBottom(), - r.getWidth(), r.getHeight()); + switch ([[UIApplication sharedApplication] statusBarOrientation]) + { + case UIInterfaceOrientationPortrait: + return r; - case UIInterfaceOrientationLandscapeLeft: - return Rectangle (screen.getHeight() - r.getBottom(), r.getX(), - r.getHeight(), r.getWidth()); + case UIInterfaceOrientationPortraitUpsideDown: + return Rectangle (screen.getWidth() - r.getRight(), screen.getHeight() - r.getBottom(), + r.getWidth(), r.getHeight()); - case UIInterfaceOrientationLandscapeRight: - return Rectangle (r.getY(), screen.getWidth() - r.getRight(), - r.getHeight(), r.getWidth()); + case UIInterfaceOrientationLandscapeLeft: + return Rectangle (screen.getHeight() - r.getBottom(), r.getX(), + r.getHeight(), r.getWidth()); - default: jassertfalse; // unknown orientation! + case UIInterfaceOrientationLandscapeRight: + return Rectangle (r.getY(), screen.getWidth() - r.getRight(), + r.getHeight(), r.getWidth()); + + default: jassertfalse; // unknown orientation! + } } return r; @@ -273,6 +291,13 @@ private: }; }; +static void sendScreenBoundsUpdate (JuceUIViewController* c) +{ + JuceUIView* juceView = (JuceUIView*) [c view]; + jassert (juceView != nil && juceView->owner != nullptr); + juceView->owner->updateTransformAndScreenBounds(); +} + } // (juce namespace) //============================================================================== @@ -301,19 +326,23 @@ private: - (void) didRotateFromInterfaceOrientation: (UIInterfaceOrientation) fromInterfaceOrientation { (void) fromInterfaceOrientation; - - JuceUIView* juceView = (JuceUIView*) [self view]; - jassert (juceView != nil && juceView->owner != nullptr); - juceView->owner->updateTransformAndScreenBounds(); - + sendScreenBoundsUpdate (self); [UIView setAnimationsEnabled: YES]; } +- (void) viewWillTransitionToSize: (CGSize) size withTransitionCoordinator: (id) coordinator +{ + [super viewWillTransitionToSize: size withTransitionCoordinator: coordinator]; + sendScreenBoundsUpdate (self); + + // On some devices the screen-size isn't yet updated at this point, so also trigger another + // async update to double-check.. + MessageManager::callAsync ([=]() { sendScreenBoundsUpdate (self); }); +} + - (void) viewDidLoad { - JuceUIView* juceView = (JuceUIView*) [self view]; - jassert (juceView != nil && juceView->owner != nullptr); - juceView->owner->updateTransformAndScreenBounds(); + sendScreenBoundsUpdate (self); } - (void) viewWillAppear: (BOOL) animated @@ -477,7 +506,7 @@ void ModifierKeys::updateCurrentModifiers() noexcept currentModifiers = UIViewComponentPeer::currentModifiers; } -Point juce_lastMousePos; +Point juce_lastMousePos; //============================================================================== UIViewComponentPeer::UIViewComponentPeer (Component& comp, const int windowStyleFlags, UIView* viewToAttachTo) @@ -603,14 +632,14 @@ Rectangle UIViewComponentPeer::getBounds (const bool global) const return convertToRectInt (r); } -Point UIViewComponentPeer::localToGlobal (Point relativePosition) +Point UIViewComponentPeer::localToGlobal (Point relativePosition) { - return relativePosition + getBounds (true).getPosition(); + return relativePosition + getBounds (true).getPosition().toFloat(); } -Point UIViewComponentPeer::globalToLocal (Point screenPosition) +Point UIViewComponentPeer::globalToLocal (Point screenPosition) { - return screenPosition - getBounds (true).getPosition(); + return screenPosition - getBounds (true).getPosition().toFloat(); } void UIViewComponentPeer::setAlpha (float newAlpha) @@ -737,8 +766,8 @@ void UIViewComponentPeer::handleTouches (UIEvent* event, const bool isDown, cons continue; CGPoint p = [touch locationInView: view]; - const Point pos ((int) p.x, (int) p.y); - juce_lastMousePos = pos + getBounds (true).getPosition(); + const Point pos (p.x, p.y); + juce_lastMousePos = pos + getBounds (true).getPosition().toFloat(); const int64 time = getMouseTime (event); const int touchIndex = currentTouches.getIndexOfTouch (touch); @@ -782,7 +811,7 @@ void UIViewComponentPeer::handleTouches (UIEvent* event, const bool isDown, cons if (isUp || isCancel) { - handleMouseEvent (touchIndex, Point (-1, -1), modsToSend, time); + handleMouseEvent (touchIndex, Point (-1.0f, -1.0f), modsToSend, time); if (! isValidPeer (this)) return; } @@ -833,12 +862,18 @@ void UIViewComponentPeer::textInputRequired (Point, TextInputTarget&) { } +static bool isIOS4_1() noexcept +{ + return [[[UIDevice currentDevice] systemVersion] doubleValue] >= 4.1; +} + static UIKeyboardType getUIKeyboardType (TextInputTarget::VirtualKeyboardType type) noexcept { switch (type) { case TextInputTarget::textKeyboard: return UIKeyboardTypeAlphabet; - case TextInputTarget::numericKeyboard: return UIKeyboardTypeNumbersAndPunctuation; + case TextInputTarget::numericKeyboard: return isIOS4_1() ? UIKeyboardTypeNumberPad : UIKeyboardTypeNumbersAndPunctuation; + case TextInputTarget::decimalKeyboard: return isIOS4_1() ? UIKeyboardTypeDecimalPad : UIKeyboardTypeNumbersAndPunctuation; case TextInputTarget::urlKeyboard: return UIKeyboardTypeURL; case TextInputTarget::emailAddressKeyboard: return UIKeyboardTypeEmailAddress; case TextInputTarget::phoneNumberKeyboard: return UIKeyboardTypePhonePad; @@ -852,7 +887,7 @@ void UIViewComponentPeer::updateHiddenTextContent (TextInputTarget* target) { view->hiddenTextView.keyboardType = getUIKeyboardType (target->getKeyboardType()); view->hiddenTextView.text = juceStringToNS (target->getTextInRange (Range (0, target->getHighlightedRegion().getStart()))); - view->hiddenTextView.selectedRange = NSMakeRange (target->getHighlightedRegion().getStart(), 0); + view->hiddenTextView.selectedRange = NSMakeRange ((NSUInteger) target->getHighlightedRegion().getStart(), 0); } BOOL UIViewComponentPeer::textViewReplaceCharacters (Range range, const String& text) diff --git a/JuceLibraryCode/modules/juce_gui_basics/native/juce_ios_Windowing.mm b/JuceLibraryCode/modules/juce_gui_basics/native/juce_ios_Windowing.mm index 6b9031f..4200e34 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/native/juce_ios_Windowing.mm +++ b/JuceLibraryCode/modules/juce_gui_basics/native/juce_ios_Windowing.mm @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -43,44 +43,51 @@ extern bool isIOSAppActive; - (void) applicationDidFinishLaunching: (UIApplication*) application { - (void) application; + ignoreUnused (application); initialiseJuce_GUI(); - JUCEApplicationBase* app = JUCEApplicationBase::createInstance(); - - if (! app->initialiseApp()) - exit (0); + if (JUCEApplicationBase* app = JUCEApplicationBase::createInstance()) + { + if (! app->initialiseApp()) + exit (app->shutdownApp()); + } + else + { + jassertfalse; // you must supply an application object for an iOS app! + } } - (void) applicationWillTerminate: (UIApplication*) application { - (void) application; + ignoreUnused (application); JUCEApplicationBase::appWillTerminateByForce(); } - (void) applicationDidEnterBackground: (UIApplication*) application { - (void) application; + ignoreUnused (application); + if (JUCEApplicationBase* const app = JUCEApplicationBase::getInstance()) app->suspended(); } - (void) applicationWillEnterForeground: (UIApplication*) application { - (void) application; + ignoreUnused (application); + if (JUCEApplicationBase* const app = JUCEApplicationBase::getInstance()) app->resumed(); } - (void) applicationDidBecomeActive: (UIApplication*) application { - (void) application; + ignoreUnused (application); isIOSAppActive = true; } - (void) applicationWillResignActive: (UIApplication*) application { - (void) application; + ignoreUnused (application); isIOSAppActive = false; } @@ -207,7 +214,7 @@ void JUCE_CALLTYPE NativeMessageBox::showMessageBox (AlertWindow::AlertIconType JUCE_AUTORELEASEPOOL { iOSMessageBox mb (title, message, @"OK", nil, nil, nullptr, false); - (void) mb.getResult(); + ignoreUnused (mb.getResult()); } } #endif @@ -294,10 +301,10 @@ void SystemClipboard::copyTextToClipboard (const String& text) String SystemClipboard::getTextFromClipboard() { - NSString* text = [[UIPasteboard generalPasteboard] valueForPasteboardType: @"public.text"]; + if (NSString* text = [[UIPasteboard generalPasteboard] valueForPasteboardType: @"public.text"]) + return nsStringToJuce (text); - return text == nil ? String::empty - : nsStringToJuce (text); + return String(); } //============================================================================== @@ -312,12 +319,12 @@ bool Desktop::canUseSemiTransparentWindows() noexcept return true; } -Point MouseInputSource::getCurrentRawMousePosition() +Point MouseInputSource::getCurrentRawMousePosition() { return juce_lastMousePos; } -void MouseInputSource::setRawMousePosition (Point) +void MouseInputSource::setRawMousePosition (Point) { } diff --git a/JuceLibraryCode/modules/juce_gui_basics/native/juce_linux_Clipboard.cpp b/JuceLibraryCode/modules/juce_gui_basics/native/juce_linux_Clipboard.cpp index b64c85c..a629187 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/native/juce_linux_Clipboard.cpp +++ b/JuceLibraryCode/modules/juce_gui_basics/native/juce_linux_Clipboard.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -22,8 +22,8 @@ ============================================================================== */ -extern Display* display; -extern Window juce_messageWindowHandle; +extern ::Display* display; +extern ::Window juce_messageWindowHandle; namespace ClipboardHelpers { @@ -36,8 +36,11 @@ namespace ClipboardHelpers static void initSelectionAtoms() { static bool isInitialised = false; + if (! isInitialised) { + isInitialised = true; + atom_UTF8_STRING = XInternAtom (display, "UTF8_STRING", False); atom_CLIPBOARD = XInternAtom (display, "CLIPBOARD", False); atom_TARGETS = XInternAtom (display, "TARGETS", False); @@ -50,29 +53,34 @@ namespace ClipboardHelpers static String readWindowProperty (Window window, Atom prop) { String returnData; - char* clipData; - Atom actualType; - int actualFormat; - unsigned long numItems, bytesLeft; - if (XGetWindowProperty (display, window, prop, - 0L /* offset */, 1000000 /* length (max) */, False, - AnyPropertyType /* format */, - &actualType, &actualFormat, &numItems, &bytesLeft, - (unsigned char**) &clipData) == Success) + if (display != nullptr) { - if (actualType == atom_UTF8_STRING && actualFormat == 8) - returnData = String::fromUTF8 (clipData, numItems); - else if (actualType == XA_STRING && actualFormat == 8) - returnData = String (clipData, numItems); + char* clipData; + Atom actualType; + int actualFormat; + unsigned long numItems, bytesLeft; - if (clipData != nullptr) - XFree (clipData); + if (XGetWindowProperty (display, window, prop, + 0L /* offset */, 1000000 /* length (max) */, False, + AnyPropertyType /* format */, + &actualType, &actualFormat, &numItems, &bytesLeft, + (unsigned char**) &clipData) == Success) + { + if (actualType == atom_UTF8_STRING && actualFormat == 8) + returnData = String::fromUTF8 (clipData, (int) numItems); + else if (actualType == XA_STRING && actualFormat == 8) + returnData = String (clipData, numItems); - jassert (bytesLeft == 0 || numItems == 1000000); + if (clipData != nullptr) + XFree (clipData); + + jassert (bytesLeft == 0 || numItems == 1000000); + } + + XDeleteProperty (display, window, prop); } - XDeleteProperty (display, window, prop); return returnData; } @@ -92,6 +100,7 @@ namespace ClipboardHelpers while (--count >= 0) { XEvent event; + if (XCheckTypedWindowEvent (display, juce_messageWindowHandle, SelectionNotify, &event)) { if (event.xselection.property == property_name) @@ -102,10 +111,8 @@ namespace ClipboardHelpers event.xselection.property); return true; } - else - { - return false; // the format we asked for was denied.. (event.xselection.property == None) - } + + return false; // the format we asked for was denied.. (event.xselection.property == None) } // not very elegant.. we could do a select() or something like that... @@ -121,66 +128,69 @@ namespace ClipboardHelpers // Called from the event loop in juce_linux_Messaging in response to SelectionRequest events static void handleSelection (XSelectionRequestEvent& evt) { - ClipboardHelpers::initSelectionAtoms(); - - // the selection content is sent to the target window as a window property - XSelectionEvent reply; - reply.type = SelectionNotify; - reply.display = evt.display; - reply.requestor = evt.requestor; - reply.selection = evt.selection; - reply.target = evt.target; - reply.property = None; // == "fail" - reply.time = evt.time; - - HeapBlock data; - int propertyFormat = 0; - size_t numDataItems = 0; - - if (evt.selection == XA_PRIMARY || evt.selection == ClipboardHelpers::atom_CLIPBOARD) + if (display != nullptr) { - if (evt.target == XA_STRING || evt.target == ClipboardHelpers::atom_UTF8_STRING) + ClipboardHelpers::initSelectionAtoms(); + + // the selection content is sent to the target window as a window property + XSelectionEvent reply; + reply.type = SelectionNotify; + reply.display = evt.display; + reply.requestor = evt.requestor; + reply.selection = evt.selection; + reply.target = evt.target; + reply.property = None; // == "fail" + reply.time = evt.time; + + HeapBlock data; + int propertyFormat = 0; + size_t numDataItems = 0; + + if (evt.selection == XA_PRIMARY || evt.selection == ClipboardHelpers::atom_CLIPBOARD) { - // translate to utf8 - numDataItems = ClipboardHelpers::localClipboardContent.getNumBytesAsUTF8() + 1; - data.calloc (numDataItems + 1); - ClipboardHelpers::localClipboardContent.copyToUTF8 (data, numDataItems); - propertyFormat = 8; // bits/item + if (evt.target == XA_STRING || evt.target == ClipboardHelpers::atom_UTF8_STRING) + { + // translate to utf8 + numDataItems = ClipboardHelpers::localClipboardContent.getNumBytesAsUTF8() + 1; + data.calloc (numDataItems + 1); + ClipboardHelpers::localClipboardContent.copyToUTF8 (data, numDataItems); + propertyFormat = 8; // bits/item + } + else if (evt.target == ClipboardHelpers::atom_TARGETS) + { + // another application wants to know what we are able to send + numDataItems = 2; + propertyFormat = 32; // atoms are 32-bit + data.calloc (numDataItems * 4); + Atom* atoms = reinterpret_cast (data.getData()); + atoms[0] = ClipboardHelpers::atom_UTF8_STRING; + atoms[1] = XA_STRING; + + evt.target = XA_ATOM; + } } - else if (evt.target == ClipboardHelpers::atom_TARGETS) + else { - // another application wants to know what we are able to send - numDataItems = 2; - propertyFormat = 32; // atoms are 32-bit - data.calloc (numDataItems * 4); - Atom* atoms = reinterpret_cast (data.getData()); - atoms[0] = ClipboardHelpers::atom_UTF8_STRING; - atoms[1] = XA_STRING; - - evt.target = XA_ATOM; + DBG ("requested unsupported clipboard"); } - } - else - { - DBG ("requested unsupported clipboard"); - } - if (data != nullptr) - { - const size_t maxReasonableSelectionSize = 1000000; - - // for very big chunks of data, we should use the "INCR" protocol , which is a pain in the *ss - if (evt.property != None && numDataItems < maxReasonableSelectionSize) + if (data != nullptr) { - XChangeProperty (evt.display, evt.requestor, - evt.property, evt.target, - propertyFormat /* 8 or 32 */, PropModeReplace, - reinterpret_cast (data.getData()), numDataItems); - reply.property = evt.property; // " == success" - } - } + const size_t maxReasonableSelectionSize = 1000000; - XSendEvent (evt.display, evt.requestor, 0, NoEventMask, (XEvent*) &reply); + // for very big chunks of data, we should use the "INCR" protocol , which is a pain in the *ss + if (evt.property != None && numDataItems < maxReasonableSelectionSize) + { + XChangeProperty (evt.display, evt.requestor, + evt.property, evt.target, + propertyFormat /* 8 or 32 */, PropModeReplace, + reinterpret_cast (data.getData()), (int) numDataItems); + reply.property = evt.property; // " == success" + } + } + + XSendEvent (evt.display, evt.requestor, 0, NoEventMask, (XEvent*) &reply); + } } } @@ -201,51 +211,58 @@ static ClipboardCallbackInitialiser clipboardInitialiser; //============================================================================== void SystemClipboard::copyTextToClipboard (const String& clipText) { - ClipboardHelpers::initSelectionAtoms(); - ClipboardHelpers::localClipboardContent = clipText; + if (display != nullptr) + { + ClipboardHelpers::initSelectionAtoms(); + ClipboardHelpers::localClipboardContent = clipText; - XSetSelectionOwner (display, XA_PRIMARY, juce_messageWindowHandle, CurrentTime); - XSetSelectionOwner (display, ClipboardHelpers::atom_CLIPBOARD, juce_messageWindowHandle, CurrentTime); + XSetSelectionOwner (display, XA_PRIMARY, juce_messageWindowHandle, CurrentTime); + XSetSelectionOwner (display, ClipboardHelpers::atom_CLIPBOARD, juce_messageWindowHandle, CurrentTime); + } } String SystemClipboard::getTextFromClipboard() { - ClipboardHelpers::initSelectionAtoms(); - - /* 1) try to read from the "CLIPBOARD" selection first (the "high - level" clipboard that is supposed to be filled by ctrl-C - etc). When a clipboard manager is running, the content of this - selection is preserved even when the original selection owner - exits. - - 2) and then try to read from "PRIMARY" selection (the "legacy" selection - filled by good old x11 apps such as xterm) - */ String content; - Atom selection = XA_PRIMARY; - Window selectionOwner = None; - if ((selectionOwner = XGetSelectionOwner (display, selection)) == None) + if (display != nullptr) { - selection = ClipboardHelpers::atom_CLIPBOARD; - selectionOwner = XGetSelectionOwner (display, selection); - } + ClipboardHelpers::initSelectionAtoms(); - if (selectionOwner != None) - { - if (selectionOwner == juce_messageWindowHandle) + /* 1) try to read from the "CLIPBOARD" selection first (the "high + level" clipboard that is supposed to be filled by ctrl-C + etc). When a clipboard manager is running, the content of this + selection is preserved even when the original selection owner + exits. + + 2) and then try to read from "PRIMARY" selection (the "legacy" selection + filled by good old x11 apps such as xterm) + */ + Atom selection = XA_PRIMARY; + Window selectionOwner = None; + + if ((selectionOwner = XGetSelectionOwner (display, selection)) == None) { - content = ClipboardHelpers::localClipboardContent; + selection = ClipboardHelpers::atom_CLIPBOARD; + selectionOwner = XGetSelectionOwner (display, selection); } - else - { - // first try: we want an utf8 string - bool ok = ClipboardHelpers::requestSelectionContent (content, selection, ClipboardHelpers::atom_UTF8_STRING); - if (! ok) + if (selectionOwner != None) + { + if (selectionOwner == juce_messageWindowHandle) { - // second chance, ask for a good old locale-dependent string .. - ok = ClipboardHelpers::requestSelectionContent (content, selection, XA_STRING); + content = ClipboardHelpers::localClipboardContent; + } + else + { + // first try: we want an utf8 string + bool ok = ClipboardHelpers::requestSelectionContent (content, selection, ClipboardHelpers::atom_UTF8_STRING); + + if (! ok) + { + // second chance, ask for a good old locale-dependent string .. + ok = ClipboardHelpers::requestSelectionContent (content, selection, XA_STRING); + } } } } diff --git a/JuceLibraryCode/modules/juce_gui_basics/native/juce_linux_FileChooser.cpp b/JuceLibraryCode/modules/juce_gui_basics/native/juce_linux_FileChooser.cpp index fb5a411..a24b14b 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/native/juce_linux_FileChooser.cpp +++ b/JuceLibraryCode/modules/juce_gui_basics/native/juce_linux_FileChooser.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -42,99 +42,134 @@ bool FileChooser::isPlatformDialogAvailable() #endif } -void FileChooser::showPlatformDialog (Array& results, - const String& title, - const File& file, - const String& filters, - bool isDirectory, - bool /* selectsFiles */, - bool isSave, - bool /* warnAboutOverwritingExistingFiles */, - bool selectMultipleFiles, - FilePreviewComponent* /* previewComponent */) +static uint64 getTopWindowID() noexcept { - String separator; - StringArray args; + if (TopLevelWindow* top = TopLevelWindow::getActiveTopLevelWindow()) + return (uint64) (pointer_sized_uint) top->getWindowHandle(); - const File previousWorkingDirectory (File::getCurrentWorkingDirectory()); - const bool isKdeFullSession = SystemStats::getEnvironmentVariable ("KDE_FULL_SESSION", String::empty) - .equalsIgnoreCase ("true"); + return 0; +} - if (exeIsAvailable ("kdialog") && (isKdeFullSession || ! exeIsAvailable ("zenity"))) +static bool isKdeFullSession() +{ + return SystemStats::getEnvironmentVariable ("KDE_FULL_SESSION", String()) + .equalsIgnoreCase ("true"); +} + +static void addKDialogArgs (StringArray& args, String& separator, + const String& title, const File& file, const String& filters, + bool isDirectory, bool isSave, bool selectMultipleFiles) +{ + args.add ("kdialog"); + + if (title.isNotEmpty()) + args.add ("--title=" + title); + + if (uint64 topWindowID = getTopWindowID()) { - // use kdialog for KDE sessions or if zenity is missing - args.add ("kdialog"); + args.add ("--attach"); + args.add (String (topWindowID)); + } - if (title.isNotEmpty()) - args.add ("--title=" + title); - - if (selectMultipleFiles) - { - separator = "\n"; - args.add ("--multiple"); - args.add ("--separate-output"); - args.add ("--getopenfilename"); - } - else - { - if (isSave) args.add ("--getsavefilename"); - else if (isDirectory) args.add ("--getexistingdirectory"); - else args.add ("--getopenfilename"); - } - - String startPath; - - if (file.exists()) - { - startPath = file.getFullPathName(); - } - else if (file.getParentDirectory().exists()) - { - startPath = file.getParentDirectory().getFullPathName(); - } - else - { - startPath = File::getSpecialLocation (File::userHomeDirectory).getFullPathName(); - - if (isSave) - startPath += "/" + file.getFileName(); - } - - args.add (startPath); - args.add (filters.replaceCharacter (';', ' ')); + if (selectMultipleFiles) + { + separator = "\n"; + args.add ("--multiple"); + args.add ("--separate-output"); + args.add ("--getopenfilename"); } else { - // zenity - args.add ("zenity"); - args.add ("--file-selection"); - - if (title.isNotEmpty()) - args.add ("--title=" + title); - - if (selectMultipleFiles) - { - separator = ":"; - args.add ("--multiple"); - args.add ("--separator=" + separator); - } - else - { - if (isDirectory) args.add ("--directory"); - if (isSave) args.add ("--save"); - } - - if (file.isDirectory()) - file.setAsCurrentWorkingDirectory(); - else if (file.getParentDirectory().exists()) - file.getParentDirectory().setAsCurrentWorkingDirectory(); - else - File::getSpecialLocation (File::userHomeDirectory).setAsCurrentWorkingDirectory(); - - if (! file.getFileName().isEmpty()) - args.add ("--filename=" + file.getFileName()); + if (isSave) args.add ("--getsavefilename"); + else if (isDirectory) args.add ("--getexistingdirectory"); + else args.add ("--getopenfilename"); } + File startPath; + + if (file.exists()) + { + startPath = file; + } + else if (file.getParentDirectory().exists()) + { + startPath = file.getParentDirectory(); + } + else + { + startPath = File::getSpecialLocation (File::userHomeDirectory); + + if (isSave) + startPath = startPath.getChildFile (file.getFileName()); + } + + args.add (startPath.getFullPathName()); + args.add (filters.replaceCharacter (';', ' ')); +} + +static void addZenityArgs (StringArray& args, String& separator, + const String& title, const File& file, const String& filters, + bool isDirectory, bool isSave, bool selectMultipleFiles) +{ + args.add ("zenity"); + args.add ("--file-selection"); + + if (title.isNotEmpty()) + args.add ("--title=" + title); + + if (selectMultipleFiles) + { + separator = ":"; + args.add ("--multiple"); + args.add ("--separator=" + separator); + } + else + { + if (isDirectory) args.add ("--directory"); + if (isSave) args.add ("--save"); + } + + if (filters.isNotEmpty() && filters != "*" && filters != "*.*") + { + StringArray tokens; + tokens.addTokens (filters, ";,|", "\""); + + for (int i = 0; i < tokens.size(); ++i) + args.add ("--file-filter=" + tokens[i]); + } + + if (file.isDirectory()) + file.setAsCurrentWorkingDirectory(); + else if (file.getParentDirectory().exists()) + file.getParentDirectory().setAsCurrentWorkingDirectory(); + else + File::getSpecialLocation (File::userHomeDirectory).setAsCurrentWorkingDirectory(); + + if (! file.getFileName().isEmpty()) + args.add ("--filename=" + file.getFileName()); + + // supplying the window ID of the topmost window makes sure that Zenity pops up.. + if (uint64 topWindowID = getTopWindowID()) + setenv ("WINDOWID", String (topWindowID).toRawUTF8(), true); +} + +void FileChooser::showPlatformDialog (Array& results, + const String& title, const File& file, const String& filters, + bool isDirectory, bool /* selectsFiles */, + bool isSave, bool /* warnAboutOverwritingExistingFiles */, + bool selectMultipleFiles, FilePreviewComponent*) +{ + const File previousWorkingDirectory (File::getCurrentWorkingDirectory()); + + StringArray args; + String separator; + + // use kdialog for KDE sessions or if zenity is missing + if (exeIsAvailable ("kdialog") && (isKdeFullSession() || ! exeIsAvailable ("zenity"))) + addKDialogArgs (args, separator, title, file, filters, isDirectory, isSave, selectMultipleFiles); + else + addZenityArgs (args, separator, title, file, filters, isDirectory, isSave, selectMultipleFiles); + args.add ("2>/dev/null"); // (to avoid logging info ending up in the results) ChildProcess child; diff --git a/JuceLibraryCode/modules/juce_gui_basics/native/juce_linux_Windowing.cpp b/JuceLibraryCode/modules/juce_gui_basics/native/juce_linux_Windowing.cpp index 91746d2..e4e66f0 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/native/juce_linux_Windowing.cpp +++ b/JuceLibraryCode/modules/juce_gui_basics/native/juce_linux_Windowing.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -22,7 +22,7 @@ ============================================================================== */ -extern Display* display; +extern ::Display* display; extern XContext windowHandleXContext; typedef void (*WindowMessageReceiveCallback) (XEvent&); extern WindowMessageReceiveCallback dispatchWindowMessage; @@ -33,17 +33,18 @@ struct Atoms { Atoms() { - Protocols = getIfExists ("WM_PROTOCOLS"); - ProtocolList [TAKE_FOCUS] = getIfExists ("WM_TAKE_FOCUS"); - ProtocolList [DELETE_WINDOW] = getIfExists ("WM_DELETE_WINDOW"); - ProtocolList [PING] = getIfExists ("_NET_WM_PING"); - ChangeState = getIfExists ("WM_CHANGE_STATE"); - State = getIfExists ("WM_STATE"); - UserTime = getCreating ("_NET_WM_USER_TIME"); - ActiveWin = getCreating ("_NET_ACTIVE_WINDOW"); - Pid = getCreating ("_NET_WM_PID"); - WindowType = getIfExists ("_NET_WM_WINDOW_TYPE"); - WindowState = getIfExists ("_NET_WM_STATE"); + protocols = getIfExists ("WM_PROTOCOLS"); + protocolList [TAKE_FOCUS] = getIfExists ("WM_TAKE_FOCUS"); + protocolList [DELETE_WINDOW] = getIfExists ("WM_DELETE_WINDOW"); + protocolList [PING] = getIfExists ("_NET_WM_PING"); + changeState = getIfExists ("WM_CHANGE_STATE"); + state = getIfExists ("WM_STATE"); + userTime = getCreating ("_NET_WM_USER_TIME"); + activeWin = getCreating ("_NET_ACTIVE_WINDOW"); + pid = getCreating ("_NET_WM_PID"); + windowType = getIfExists ("_NET_WM_WINDOW_TYPE"); + windowState = getIfExists ("_NET_WM_STATE"); + compositingManager = getCreating ("_NET_WM_CM_S0"); XdndAware = getCreating ("XdndAware"); XdndEnter = getCreating ("XdndEnter"); @@ -88,8 +89,8 @@ struct Atoms PING = 2 }; - Atom Protocols, ProtocolList[3], ChangeState, State, UserTime, - ActiveWin, Pid, WindowType, WindowState, + Atom protocols, protocolList[3], changeState, state, userTime, + activeWin, pid, windowType, windowState, compositingManager, XdndAware, XdndEnter, XdndLeave, XdndPosition, XdndStatus, XdndDrop, XdndFinished, XdndSelection, XdndTypeList, XdndActionList, XdndActionDescription, XdndActionCopy, XdndActionPrivate, @@ -164,6 +165,9 @@ namespace Keys bool KeyPress::isKeyCurrentlyDown (const int keyCode) { + if (display == nullptr) + return false; + int keysym; if (keyCode & Keys::extendedKeyModifier) @@ -185,7 +189,7 @@ bool KeyPress::isKeyCurrentlyDown (const int keyCode) ScopedXLock xlock; - const int keycode = XKeysymToKeycode (display, keysym); + const int keycode = XKeysymToKeycode (display, (KeySym) keysym); const int keybyte = keycode >> 3; const int keybit = (1 << (keycode & 7)); @@ -211,54 +215,58 @@ namespace XSHMHelpers if (! isChecked) { isChecked = true; - int major, minor; - Bool pixmaps; - ScopedXLock xlock; - - if (XShmQueryVersion (display, &major, &minor, &pixmaps)) + if (display != nullptr) { - trappedErrorCode = 0; - XErrorHandler oldHandler = XSetErrorHandler (errorTrapHandler); + int major, minor; + Bool pixmaps; - XShmSegmentInfo segmentInfo; - zerostruct (segmentInfo); + ScopedXLock xlock; - XImage* xImage = XShmCreateImage (display, DefaultVisual (display, DefaultScreen (display)), - 24, ZPixmap, 0, &segmentInfo, 50, 50); - - if ((segmentInfo.shmid = shmget (IPC_PRIVATE, - xImage->bytes_per_line * xImage->height, - IPC_CREAT | 0777)) >= 0) + if (XShmQueryVersion (display, &major, &minor, &pixmaps)) { - segmentInfo.shmaddr = (char*) shmat (segmentInfo.shmid, 0, 0); + trappedErrorCode = 0; + XErrorHandler oldHandler = XSetErrorHandler (errorTrapHandler); - if (segmentInfo.shmaddr != (void*) -1) + XShmSegmentInfo segmentInfo; + zerostruct (segmentInfo); + + XImage* xImage = XShmCreateImage (display, DefaultVisual (display, DefaultScreen (display)), + 24, ZPixmap, 0, &segmentInfo, 50, 50); + + if ((segmentInfo.shmid = shmget (IPC_PRIVATE, + (size_t) (xImage->bytes_per_line * xImage->height), + IPC_CREAT | 0777)) >= 0) { - segmentInfo.readOnly = False; - xImage->data = segmentInfo.shmaddr; - XSync (display, False); + segmentInfo.shmaddr = (char*) shmat (segmentInfo.shmid, 0, 0); - if (XShmAttach (display, &segmentInfo) != 0) + if (segmentInfo.shmaddr != (void*) -1) { + segmentInfo.readOnly = False; + xImage->data = segmentInfo.shmaddr; XSync (display, False); - XShmDetach (display, &segmentInfo); - isAvailable = true; + if (XShmAttach (display, &segmentInfo) != 0) + { + XSync (display, False); + XShmDetach (display, &segmentInfo); + + isAvailable = true; + } } + + XFlush (display); + XDestroyImage (xImage); + + shmdt (segmentInfo.shmaddr); } - XFlush (display); - XDestroyImage (xImage); + shmctl (segmentInfo.shmid, IPC_RMID, 0); - shmdt (segmentInfo.shmaddr); + XSetErrorHandler (oldHandler); + if (trappedErrorCode != 0) + isAvailable = false; } - - shmctl (segmentInfo.shmid, IPC_RMID, 0); - - XSetErrorHandler (oldHandler); - if (trappedErrorCode != 0) - isAvailable = false; } } @@ -287,25 +295,29 @@ namespace XRender if (! hasLoaded) { - ScopedXLock xlock; - hasLoaded = true; - - if (void* h = dlopen ("libXrender.so", RTLD_GLOBAL | RTLD_NOW)) + if (display != nullptr) { - xRenderQueryVersion = (tXRenderQueryVersion) dlsym (h, "XRenderQueryVersion"); - xRenderFindStandardFormat = (tXRenderFindStandardFormat) dlsym (h, "XRenderFindStandardFormat"); - xRenderFindFormat = (tXRenderFindFormat) dlsym (h, "XRenderFindFormat"); - xRenderFindVisualFormat = (tXRenderFindVisualFormat) dlsym (h, "XRenderFindVisualFormat"); - } + hasLoaded = true; - if (xRenderQueryVersion != nullptr - && xRenderFindStandardFormat != nullptr - && xRenderFindFormat != nullptr - && xRenderFindVisualFormat != nullptr) - { - int major, minor; - if (xRenderQueryVersion (display, &major, &minor)) - return true; + ScopedXLock xlock; + + if (void* h = dlopen ("libXrender.so", RTLD_GLOBAL | RTLD_NOW)) + { + xRenderQueryVersion = (tXRenderQueryVersion) dlsym (h, "XRenderQueryVersion"); + xRenderFindStandardFormat = (tXRenderFindStandardFormat) dlsym (h, "XRenderFindStandardFormat"); + xRenderFindFormat = (tXRenderFindFormat) dlsym (h, "XRenderFindFormat"); + xRenderFindVisualFormat = (tXRenderFindVisualFormat) dlsym (h, "XRenderFindVisualFormat"); + } + + if (xRenderQueryVersion != nullptr + && xRenderFindStandardFormat != nullptr + && xRenderFindFormat != nullptr + && xRenderFindVisualFormat != nullptr) + { + int major, minor; + if (xRenderQueryVersion (display, &major, &minor)) + return true; + } } xRenderQueryVersion = nullptr; @@ -314,6 +326,11 @@ namespace XRender return xRenderQueryVersion != nullptr; } + static bool hasCompositingWindowManager() + { + return display != nullptr && XGetSelectionOwner (display, Atoms::get().compositingManager) != 0; + } + static XRenderPictFormat* findPictureFormat() { ScopedXLock xlock; @@ -488,7 +505,7 @@ class XBitmapImage : public ImagePixelData { public: XBitmapImage (const Image::PixelFormat format, const int w, const int h, - const bool clearImage, const int imageDepth_, Visual* visual) + const bool clearImage, const unsigned int imageDepth_, Visual* visual) : ImagePixelData (format, w, h), imageDepth (imageDepth_), gc (None) @@ -511,12 +528,13 @@ public: segmentInfo.shmaddr = (char *) -1; segmentInfo.readOnly = False; - xImage = XShmCreateImage (display, visual, imageDepth, ZPixmap, 0, &segmentInfo, w, h); + xImage = XShmCreateImage (display, visual, imageDepth, ZPixmap, 0, + &segmentInfo, (unsigned int) w, (unsigned int) h); if (xImage != nullptr) { if ((segmentInfo.shmid = shmget (IPC_PRIVATE, - xImage->bytes_per_line * xImage->height, + (size_t) (xImage->bytes_per_line * xImage->height), IPC_CREAT | 0777)) >= 0) { if (segmentInfo.shmid != -1) @@ -544,10 +562,10 @@ public: } } - if (! usingXShm) + if (! isUsingXShm()) #endif { - imageDataAllocated.allocate (lineStride * h, format == Image::ARGB && clearImage); + imageDataAllocated.allocate ((size_t) (lineStride * h), format == Image::ARGB && clearImage); imageData = imageDataAllocated; xImage = (XImage*) ::calloc (1, sizeof (XImage)); @@ -570,15 +588,15 @@ public: if (imageDepth == 16) { - const int pixelStride = 2; - const int lineStride = ((w * pixelStride + 3) & ~3); + const int pixStride = 2; + const int stride = ((w * pixStride + 3) & ~3); - imageData16Bit.malloc (lineStride * h); + imageData16Bit.malloc ((size_t) (stride * h)); xImage->data = imageData16Bit; xImage->bitmap_pad = 16; - xImage->depth = pixelStride * 8; - xImage->bytes_per_line = lineStride; - xImage->bits_per_pixel = pixelStride * 8; + xImage->depth = pixStride * 8; + xImage->bytes_per_line = stride; + xImage->bits_per_pixel = pixStride * 8; xImage->red_mask = visual->red_mask; xImage->green_mask = visual->green_mask; xImage->blue_mask = visual->blue_mask; @@ -597,7 +615,7 @@ public: XFreeGC (display, gc); #if JUCE_USE_XSHM - if (usingXShm) + if (isUsingXShm()) { XShmDetach (display, &segmentInfo); @@ -640,7 +658,7 @@ public: ImageType* createType() const override { return new NativeImageType(); } - void blitToWindow (Window window, int dx, int dy, int dw, int dh, int sx, int sy) + void blitToWindow (Window window, int dx, int dy, unsigned int dw, unsigned int dh, int sx, int sy) { ScopedXLock xlock; @@ -661,50 +679,54 @@ public: if (imageDepth == 16) { - const uint32 rMask = xImage->red_mask; - const uint32 gMask = xImage->green_mask; - const uint32 bMask = xImage->blue_mask; - const uint32 rShiftL = jmax (0, getShiftNeeded (rMask)); - const uint32 rShiftR = jmax (0, -getShiftNeeded (rMask)); - const uint32 gShiftL = jmax (0, getShiftNeeded (gMask)); - const uint32 gShiftR = jmax (0, -getShiftNeeded (gMask)); - const uint32 bShiftL = jmax (0, getShiftNeeded (bMask)); - const uint32 bShiftR = jmax (0, -getShiftNeeded (bMask)); + const uint32 rMask = (uint32) xImage->red_mask; + const uint32 gMask = (uint32) xImage->green_mask; + const uint32 bMask = (uint32) xImage->blue_mask; + const uint32 rShiftL = (uint32) jmax (0, getShiftNeeded (rMask)); + const uint32 rShiftR = (uint32) jmax (0, -getShiftNeeded (rMask)); + const uint32 gShiftL = (uint32) jmax (0, getShiftNeeded (gMask)); + const uint32 gShiftR = (uint32) jmax (0, -getShiftNeeded (gMask)); + const uint32 bShiftL = (uint32) jmax (0, getShiftNeeded (bMask)); + const uint32 bShiftR = (uint32) jmax (0, -getShiftNeeded (bMask)); const Image::BitmapData srcData (Image (this), Image::BitmapData::readOnly); - for (int y = sy; y < sy + dh; ++y) + for (int y = sy; y < sy + (int)dh; ++y) { const uint8* p = srcData.getPixelPointer (sx, y); - for (int x = sx; x < sx + dw; ++x) + for (int x = sx; x < sx + (int)dw; ++x) { const PixelRGB* const pixel = (const PixelRGB*) p; p += srcData.pixelStride; XPutPixel (xImage, x, y, - (((((uint32) pixel->getRed()) << rShiftL) >> rShiftR) & rMask) + (((((uint32) pixel->getRed()) << rShiftL) >> rShiftR) & rMask) | (((((uint32) pixel->getGreen()) << gShiftL) >> gShiftR) & gMask) - | (((((uint32) pixel->getBlue()) << bShiftL) >> bShiftR) & bMask)); + | (((((uint32) pixel->getBlue()) << bShiftL) >> bShiftR) & bMask)); } } } // blit results to screen. #if JUCE_USE_XSHM - if (usingXShm) + if (isUsingXShm()) XShmPutImage (display, (::Drawable) window, gc, xImage, sx, sy, dx, dy, dw, dh, True); else #endif XPutImage (display, (::Drawable) window, gc, xImage, sx, sy, dx, dy, dw, dh); } + #if JUCE_USE_XSHM + bool isUsingXShm() const noexcept { return usingXShm; } + #endif + private: //============================================================================== XImage* xImage; - const int imageDepth; - HeapBlock imageDataAllocated; - HeapBlock imageData16Bit; + const unsigned int imageDepth; + HeapBlock imageDataAllocated; + HeapBlock imageData16Bit; int pixelStride, lineStride; uint8* imageData; GC gc; @@ -727,6 +749,674 @@ private: JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (XBitmapImage) }; +//============================================================================== +#if JUCE_USE_XRANDR +template <> +struct ContainerDeletePolicy +{ + static void destroy (XRRScreenResources* object); +}; + +template <> +struct ContainerDeletePolicy +{ + static void destroy (XRROutputInfo* object); +}; + +template <> +struct ContainerDeletePolicy +{ + static void destroy (XRRCrtcInfo* object); +}; +#endif + +//============================================================================== +class DisplayGeometry +{ +private: + //============================================================================== + DisplayGeometry (::Display* dpy, double masterScale) + { + jassert (instance == nullptr); + instance = this; + + queryDisplayInfos (dpy, masterScale); + updatePositions(); + } + +public: + //============================================================================== + struct ExtendedInfo + { + // Unlike Desktop::Displays::Display, the following is in + // physical pixels, i.e. the area is not scaled + Rectangle totalBounds; + // Usable bounds is the usable area in local coordinates + // with respect to the above totalBounds + Rectangle usableBounds; + // top-left point of display in scaled coordinates. This + // is different from totalBounds.getTopLeft() / scale, + // because the neighbouring display may have a different + // scale factor + Point topLeftScaled; + double dpi, scale; + bool isMain; + }; + + Array infos; + + //============================================================================== + ExtendedInfo& findDisplayForRect (const Rectangle& bounds, bool isScaledBounds) + { + int maxArea = -1; + ExtendedInfo* retval = nullptr; + + for (int i = 0; i < infos.size(); ++i) + { + ExtendedInfo& dpy = infos.getReference (i); + + Rectangle displayBounds = dpy.totalBounds; + + if (isScaledBounds) + displayBounds = (displayBounds.withZeroOrigin() / dpy.scale) + dpy.topLeftScaled; + + displayBounds = displayBounds.getIntersection (bounds); + int area = displayBounds.getWidth() * displayBounds.getHeight(); + + if (area >= maxArea) + { + maxArea = area; + retval = &dpy; + } + } + + return *retval; + } + + ExtendedInfo& findDisplayForPoint (Point pt, bool isScaledPoint) + { + int minDistance = (int) ((((unsigned int)(-1)) >> 1) - 1); + ExtendedInfo* retval = nullptr; + + for (int i = 0; i < infos.size(); ++i) + { + ExtendedInfo& dpy = infos.getReference (i); + + Rectangle displayBounds = dpy.totalBounds; + + if (isScaledPoint) + displayBounds = (displayBounds.withZeroOrigin() / dpy.scale) + dpy.topLeftScaled; + + if (displayBounds.contains (pt)) + return dpy; + + int distance = displayBounds.getCentre().getDistanceFrom (pt); + if (distance <= minDistance) + { + minDistance = distance; + retval = &dpy; + } + } + + return *retval; + } + + //============================================================================== + static Rectangle physicalToScaled (const Rectangle& physicalBounds) + { + // first find with which display physicalBounds has the most overlap + ExtendedInfo& dpy = getInstance().findDisplayForRect (physicalBounds, false); + + // convert to local screen bounds + Rectangle retval = physicalBounds - dpy.totalBounds.getTopLeft(); + + // now we can safely scale the coordinates and convert to global again + return (retval / dpy.scale) + dpy.topLeftScaled; + } + + static Rectangle scaledToPhysical (const Rectangle& scaledBounds) + { + // first find with which display physicalBounds has the most overlap + ExtendedInfo& dpy = getInstance().findDisplayForRect (scaledBounds, true); + + // convert to local screen bounds + Rectangle retval = scaledBounds - dpy.topLeftScaled; + + // now we can safely scale the coordinates and convert to global again + return (retval * dpy.scale) + dpy.totalBounds.getTopLeft(); + } + + //============================================================================== + template + static Point physicalToScaled (const Point& physicalPoint) + { + ExtendedInfo& dpy = getInstance().findDisplayForPoint (physicalPoint.roundToInt(), false); + Point scaledTopLeft = + Point (dpy.topLeftScaled.getX(), dpy.topLeftScaled.getY()); + Point physicalTopLeft = + Point (dpy.totalBounds.getX(), dpy.totalBounds.getY()); + + return ((physicalPoint - physicalTopLeft) / dpy.scale) + scaledTopLeft; + } + + template + static Point scaledToPhysical (const Point& scaledPoint) + { + ExtendedInfo& dpy = getInstance().findDisplayForPoint (scaledPoint.roundToInt(), true); + Point scaledTopLeft = + Point (dpy.topLeftScaled.getX(), dpy.topLeftScaled.getY()); + Point physicalTopLeft = + Point (dpy.totalBounds.getX(), dpy.totalBounds.getY()); + + return ((scaledPoint - scaledTopLeft) * dpy.scale) + physicalTopLeft; + } + + //============================================================================== + static DisplayGeometry& getInstance() + { + jassert (instance != nullptr); + return *instance; + } + + static DisplayGeometry& getOrCreateInstance (::Display* dpy, double masterScale) + { + if (instance == nullptr) + new DisplayGeometry (dpy, masterScale); + + return getInstance(); + } + +private: + //============================================================================== + static DisplayGeometry* instance; + + //============================================================================== + #if JUCE_USE_XINERAMA + static Array XineramaQueryDisplays (::Display* dpy) + { + typedef Bool (*tXineramaIsActive) (::Display*); + typedef XineramaScreenInfo* (*tXineramaQueryScreens) (::Display*, int*); + + int major_opcode, first_event, first_error; + + if (XQueryExtension (dpy, "XINERAMA", &major_opcode, &first_event, &first_error)) + { + static void* libXinerama = nullptr; + static tXineramaIsActive isActiveFuncPtr = nullptr; + static tXineramaQueryScreens xineramaQueryScreens = nullptr; + + if (libXinerama == nullptr) + { + libXinerama = dlopen ("libXinerama.so", RTLD_GLOBAL | RTLD_NOW); + + if (libXinerama == nullptr) + libXinerama = dlopen ("libXinerama.so.1", RTLD_GLOBAL | RTLD_NOW); + + if (libXinerama != nullptr) + { + isActiveFuncPtr = (tXineramaIsActive) dlsym (libXinerama, "XineramaIsActive"); + xineramaQueryScreens = (tXineramaQueryScreens) dlsym (libXinerama, "XineramaQueryScreens"); + } + } + + if (isActiveFuncPtr != nullptr && xineramaQueryScreens != nullptr && isActiveFuncPtr (dpy) != 0) + { + int numScreens; + if (XineramaScreenInfo* xinfo = xineramaQueryScreens (dpy, &numScreens)) + { + Array infos (xinfo, numScreens); + XFree (xinfo); + + return infos; + } + } + } + + return Array(); + } + #endif + + //============================================================================== + #if JUCE_USE_XRANDR + friend struct ContainerDeletePolicy; + friend struct ContainerDeletePolicy; + friend struct ContainerDeletePolicy; + + class XRandrWrapper + { + private: + XRandrWrapper() + : libXrandr (nullptr), + getScreenResourcesPtr (nullptr), + freeScreenResourcesPtr (nullptr), + getOutputInfoPtr (nullptr), + freeOutputInfoPtr (nullptr), + getCrtcInfoPtr (nullptr), + freeCrtcInfoPtr (nullptr), + getOutputPrimaryPtr (nullptr) + { + if (libXrandr == nullptr) + { + libXrandr = dlopen ("libXrandr.so", RTLD_GLOBAL | RTLD_NOW); + + if (libXrandr == nullptr) + libXrandr = dlopen ("libXinerama.so.2", RTLD_GLOBAL | RTLD_NOW); + + if (libXrandr != nullptr) + { + getScreenResourcesPtr = (tXRRGetScreenResources) dlsym (libXrandr, "XRRGetScreenResources"); + freeScreenResourcesPtr = (tXRRFreeScreenResources) dlsym (libXrandr, "XRRFreeScreenResources"); + getOutputInfoPtr = (tXRRGetOutputInfo) dlsym (libXrandr, "XRRGetOutputInfo"); + freeOutputInfoPtr = (tXRRFreeOutputInfo) dlsym (libXrandr, "XRRFreeOutputInfo"); + getCrtcInfoPtr = (tXRRGetCrtcInfo) dlsym (libXrandr, "XRRGetCrtcInfo"); + freeCrtcInfoPtr = (tXRRFreeCrtcInfo) dlsym (libXrandr, "XRRFreeCrtcInfo"); + getOutputPrimaryPtr = (tXRRGetOutputPrimary) dlsym (libXrandr, "XRRGetOutputPrimary"); + } + } + + instance = this; + } + + public: + //============================================================================== + static XRandrWrapper& getInstance() + { + if (instance == nullptr) + instance = new XRandrWrapper(); + + return *instance; + } + + //============================================================================== + XRRScreenResources* getScreenResources (::Display* dpy, ::Window window) + { + if (getScreenResourcesPtr != nullptr) + return getScreenResourcesPtr (dpy, window); + + return nullptr; + } + + XRROutputInfo* getOutputInfo (::Display* dpy, XRRScreenResources* resources, RROutput output) + { + if (getOutputInfoPtr != nullptr) + return getOutputInfoPtr (dpy, resources, output); + + return nullptr; + } + + XRRCrtcInfo* getCrtcInfo (::Display* dpy, XRRScreenResources* resources, RRCrtc crtc) + { + if (getCrtcInfoPtr != nullptr) + return getCrtcInfoPtr (dpy, resources, crtc); + + return nullptr; + } + + RROutput getOutputPrimary (::Display* dpy, ::Window window) + { + if (getOutputPrimaryPtr != nullptr) + return getOutputPrimaryPtr (dpy, window); + + return 0; + } + + private: + //============================================================================== + friend struct ContainerDeletePolicy; + friend struct ContainerDeletePolicy; + friend struct ContainerDeletePolicy; + + void freeScreenResources (XRRScreenResources* ptr) + { + if (freeScreenResourcesPtr != nullptr) + freeScreenResourcesPtr (ptr); + } + + void freeOutputInfo (XRROutputInfo* ptr) + { + if (freeOutputInfoPtr != nullptr) + freeOutputInfoPtr (ptr); + } + + void freeCrtcInfo (XRRCrtcInfo* ptr) + { + if (freeCrtcInfoPtr != nullptr) + freeCrtcInfoPtr (ptr); + } + private: + static XRandrWrapper* instance; + + typedef XRRScreenResources* (*tXRRGetScreenResources) (::Display*, ::Window); + typedef void (*tXRRFreeScreenResources) (XRRScreenResources*); + typedef XRROutputInfo* (*tXRRGetOutputInfo) (::Display*, XRRScreenResources*, RROutput); + typedef void (*tXRRFreeOutputInfo) (XRROutputInfo*); + typedef XRRCrtcInfo* (*tXRRGetCrtcInfo) (::Display*, XRRScreenResources*, RRCrtc); + typedef void (*tXRRFreeCrtcInfo) (XRRCrtcInfo*); + typedef RROutput (*tXRRGetOutputPrimary) (::Display*, ::Window); + + void* libXrandr; + tXRRGetScreenResources getScreenResourcesPtr; + tXRRFreeScreenResources freeScreenResourcesPtr; + tXRRGetOutputInfo getOutputInfoPtr; + tXRRFreeOutputInfo freeOutputInfoPtr; + tXRRGetCrtcInfo getCrtcInfoPtr; + tXRRFreeCrtcInfo freeCrtcInfoPtr; + tXRRGetOutputPrimary getOutputPrimaryPtr; + }; + #endif + + + static double getDisplayDPI (int index) + { + double dpiX = (DisplayWidth (display, index) * 25.4) / DisplayWidthMM (display, index); + double dpiY = (DisplayHeight (display, index) * 25.4) / DisplayHeightMM (display, index); + return (dpiX + dpiY) / 2.0; + } + + static double getScaleForDisplay (const String& name, const ExtendedInfo& info) + { + if (! name.isEmpty()) + { + // Ubuntu and derived distributions now save a per-display scale factor as a configuration + // variable. This can be changed in the Monitor system settings panel. + ChildProcess dconf; + if (File ("/usr/bin/dconf").existsAsFile() && + dconf.start ("/usr/bin/dconf read /com/ubuntu/user-interface/scale-factor", ChildProcess::wantStdOut)) + { + if (dconf.waitForProcessToFinish (200)) + { + String jsonOutput = dconf.readAllProcessOutput().replaceCharacter ('\'', '"'); + + if (dconf.getExitCode() == 0 && jsonOutput.isNotEmpty()) + { + var jsonVar = JSON::parse (jsonOutput); + + if (DynamicObject* object = jsonVar.getDynamicObject()) + { + var scaleFactorVar = object->getProperty (name); + if (! scaleFactorVar.isVoid()) + { + double scaleFactor = ((double) scaleFactorVar) / 8.0; + + if (scaleFactor > 0.0) + return scaleFactor; + } + } + } + } + } + } + + { + // Other gnome based distros now use gsettings for a global scale factor + ChildProcess gsettings; + if (File ("/usr/bin/gsettings").existsAsFile() && + gsettings.start ("/usr/bin/gsettings get org.gnome.desktop.interface scaling-factor", ChildProcess::wantStdOut)) + { + if (gsettings.waitForProcessToFinish (200)) + { + StringArray gsettingsOutput = StringArray::fromTokens (gsettings.readAllProcessOutput(), true); + if (gsettingsOutput.size() >= 2 && gsettingsOutput[1].length() > 0) + { + double scaleFactor = gsettingsOutput[1].getDoubleValue(); + + if (scaleFactor > 0.0) + return scaleFactor; + } + } + } + } + + // If no scale factor is set by GNOME or Ubuntu then calculate from monitor dpi + // We use the same approach as chromium which simply divides the dpi by 96 + // and then rounds the result + return round (info.dpi / 150.0); + } + + //============================================================================== + void queryDisplayInfos (::Display* dpy, double masterScale) noexcept + { + ScopedXLock xlock; + + #if JUCE_USE_XRANDR + { + int major_opcode, first_event, first_error; + + if (XQueryExtension (dpy, "RANDR", &major_opcode, &first_event, &first_error)) + { + XRandrWrapper& xrandr = XRandrWrapper::getInstance(); + + ScopedPointer screens; + + const int numMonitors = ScreenCount (dpy); + RROutput mainDisplay = xrandr.getOutputPrimary (dpy, RootWindow (dpy, 0)); + + for (int i = 0; i < numMonitors; ++i) + { + if ((screens = xrandr.getScreenResources (dpy, RootWindow (dpy, i))).get()) + { + for (int j = 0; j < screens->noutput; ++j) + { + if (! screens->outputs[j]) + continue; + + // Xrandr on the raspberry pi fails to determine the main display (mainDisplay == 0)! + // Detect this edge case and make the first found display the main display + if (! mainDisplay) + mainDisplay = screens->outputs[j]; + + ScopedPointer output; + + if ((output = xrandr.getOutputInfo (dpy, screens.get(), screens->outputs[j])).get()) + { + if (! output->crtc) + continue; + + ScopedPointer crtc; + + if ((crtc = xrandr.getCrtcInfo (dpy, screens.get(), output->crtc)).get()) + { + ExtendedInfo e; + e.totalBounds = Rectangle (crtc->x, crtc->y, + (int) crtc->width, (int) crtc->height); + e.usableBounds = e.totalBounds.withZeroOrigin(); // Support for usable area is not implemented in JUCE yet + e.topLeftScaled = e.totalBounds.getTopLeft(); + e.isMain = (mainDisplay == screens->outputs[j]) && (i == 0); + e.dpi = getDisplayDPI (0); + + // The raspberry pi returns a zero sized display, so we need to guard for divide-by-zero + if (output->mm_width > 0 && output->mm_height > 0) + e.dpi = ((static_cast (crtc->width) * 25.4 * 0.5) / static_cast (output->mm_width)) + + ((static_cast (crtc->height) * 25.4 * 0.5) / static_cast (output->mm_height)); + + e.scale = masterScale * getScaleForDisplay (output->name, e); + + infos.add (e); + } + } + } + } + } + } + } + if (infos.size() == 0) + #endif + #if JUCE_USE_XINERAMA + { + Array screens = XineramaQueryDisplays (dpy); + int numMonitors = screens.size(); + + for (int index = 0; index < numMonitors; ++index) + { + for (int j = numMonitors; --j >= 0;) + { + if (screens[j].screen_number == index) + { + ExtendedInfo e; + e.totalBounds = Rectangle (screens[j].x_org, + screens[j].y_org, + screens[j].width, + screens[j].height); + e.usableBounds = e.totalBounds.withZeroOrigin(); // Support for usable area is not implemented in JUCE yet + e.topLeftScaled = e.totalBounds.getTopLeft(); // this will be overwritten by updatePositions later + e.isMain = (index == 0); + e.scale = masterScale; + e.dpi = getDisplayDPI (0); // (all screens share the same DPI) + + infos.add (e); + } + } + } + } + + if (infos.size() == 0) + #endif + { + Atom hints = Atoms::getIfExists ("_NET_WORKAREA"); + + if (hints != None) + { + const int numMonitors = ScreenCount (dpy); + + for (int i = 0; i < numMonitors; ++i) + { + GetXProperty prop (RootWindow (dpy, i), hints, 0, 4, false, XA_CARDINAL); + + if (prop.success && prop.actualType == XA_CARDINAL && prop.actualFormat == 32 && prop.numItems == 4) + { + const long* const position = (const long*) prop.data; + + ExtendedInfo e; + e.totalBounds = Rectangle ((int) position[0], (int) position[1], + (int) position[2], (int) position[3]); + e.usableBounds = e.totalBounds.withZeroOrigin(); // Support for usable area is not implemented in JUCE yet + e.topLeftScaled = e.totalBounds.getTopLeft(); // this will be overwritten by updatePositions later + e.isMain = (infos.size() == 0); + e.scale = masterScale; + e.dpi = getDisplayDPI (i); + + infos.add (e); + } + } + } + + if (infos.size() == 0) + { + ExtendedInfo e; + e.totalBounds = Rectangle (DisplayWidth (dpy, DefaultScreen (dpy)), + DisplayHeight (dpy, DefaultScreen (dpy))); + e.usableBounds = e.totalBounds; // Support for usable area is not implemented in JUCE yet + e.topLeftScaled = e.totalBounds.getTopLeft(); // this will be overwritten by updatePositions later + e.isMain = true; + e.scale = masterScale; + e.dpi = getDisplayDPI (0); + + infos.add (e); + } + } + } + + //============================================================================== + struct SortByCoordinate + { + bool sortByYCoordinate; + + SortByCoordinate (bool byYCoordinate) + : sortByYCoordinate (byYCoordinate) + { + } + + int compareElements (const ExtendedInfo* a, const ExtendedInfo* b) + { + int coordinateA, coordinateB; + + if (sortByYCoordinate) + { + coordinateA = a->totalBounds.getY(); + coordinateB = b->totalBounds.getY(); + } + else + { + coordinateA = a->totalBounds.getX(); + coordinateB = b->totalBounds.getX(); + } + + return coordinateA - coordinateB; + } + }; + + //============================================================================== + void updateScaledDisplayCoordinate(bool updateYCoordinates) + { + if (infos.size() < 2) + return; + + Array copy; + { + SortByCoordinate sorter (updateYCoordinates); + for (int i = 0; i < infos.size(); ++i) + copy.addSorted (sorter, &infos.getReference (i)); + } + + for (int i = 1; i < copy.size(); ++i) + { + ExtendedInfo& current = *copy[i]; + + // Is this screen's position aligned to any other previous display? + for (int j = i - 1; j >= 0; --j) + { + ExtendedInfo& other = *copy[j]; + int prevCoordinate = updateYCoordinates ? other.totalBounds.getBottom() : other.totalBounds.getRight(); + int curCoordinate = updateYCoordinates ? current.totalBounds.getY() : current.totalBounds.getX(); + if (prevCoordinate == curCoordinate) + { + // both displays are aligned! As "other" comes before "current" in the array, it must already + // have a valid topLeftScaled which we can use + Point topLeftScaled = other.topLeftScaled; + topLeftScaled += Point (other.totalBounds.getWidth(), other.totalBounds.getHeight()) / other.scale; + + if (updateYCoordinates) + current.topLeftScaled.setY (topLeftScaled.getY()); + else + current.topLeftScaled.setX (topLeftScaled.getX()); + + break; + } + } + } + } + + void updatePositions() + { + updateScaledDisplayCoordinate (false); + updateScaledDisplayCoordinate (true); + } +}; + +DisplayGeometry* DisplayGeometry::instance = nullptr; + +#if JUCE_USE_XRANDR +DisplayGeometry::XRandrWrapper* DisplayGeometry::XRandrWrapper::instance = nullptr; + +void ContainerDeletePolicy::destroy (XRRScreenResources* ptr) +{ + if (ptr != nullptr) + DisplayGeometry::XRandrWrapper::getInstance().freeScreenResources (ptr); +} + +void ContainerDeletePolicy::destroy (XRROutputInfo* ptr) +{ + if (ptr != nullptr) + DisplayGeometry::XRandrWrapper::getInstance().freeOutputInfo (ptr); +} + +void ContainerDeletePolicy::destroy (XRRCrtcInfo* ptr) +{ + if (ptr != nullptr) + DisplayGeometry::XRandrWrapper::getInstance().freeCrtcInfo (ptr); +} +#endif + //============================================================================== namespace PixmapHelpers { @@ -734,13 +1424,13 @@ namespace PixmapHelpers { ScopedXLock xlock; - const int width = image.getWidth(); - const int height = image.getHeight(); - HeapBlock colour (width * height); + const unsigned int width = (unsigned int) image.getWidth(); + const unsigned int height = (unsigned int) image.getHeight(); + HeapBlock colour (width * height); int index = 0; - for (int y = 0; y < height; ++y) - for (int x = 0; x < width; ++x) + for (int y = 0; y < (int) height; ++y) + for (int x = 0; x < (int) width; ++x) colour[index++] = image.getPixelAt (x, y).getARGB(); XImage* ximage = XCreateImage (display, CopyFromParent, 24, ZPixmap, @@ -761,21 +1451,21 @@ namespace PixmapHelpers { ScopedXLock xlock; - const int width = image.getWidth(); - const int height = image.getHeight(); - const int stride = (width + 7) >> 3; - HeapBlock mask; + const unsigned int width = (unsigned int) image.getWidth(); + const unsigned int height = (unsigned int) image.getHeight(); + const unsigned int stride = (width + 7) >> 3; + HeapBlock mask; mask.calloc (stride * height); const bool msbfirst = (BitmapBitOrder (display) == MSBFirst); - for (int y = 0; y < height; ++y) + for (unsigned int y = 0; y < height; ++y) { - for (int x = 0; x < width; ++x) + for (unsigned int x = 0; x < width; ++x) { const char bit = (char) (1 << (msbfirst ? (7 - (x & 7)) : (x & 7))); - const int offset = y * stride + (x >> 3); + const unsigned int offset = y * stride + (x >> 3); - if (image.getPixelAt (x, y).getAlpha() >= 128) + if (image.getPixelAt ((int) x, (int) y).getAlpha() >= 128) mask[offset] |= bit; } } @@ -812,7 +1502,8 @@ public: windowH (0), parentWindow (0), fullScreen (false), mapped (false), visual (nullptr), depth (0), - isAlwaysOnTop (comp.isAlwaysOnTop()) + isAlwaysOnTop (comp.isAlwaysOnTop()), + currentScaleFactor (1.0) { // it's dangerous to create a window on a thread other than the message thread.. jassert (MessageManager::getInstance()->currentThreadHasLockedMessageManager()); @@ -866,17 +1557,22 @@ public: { XPointer peer = nullptr; - ScopedXLock xlock; - if (! XFindContext (display, (XID) windowHandle, windowHandleXContext, &peer)) - if (peer != nullptr && ! ComponentPeer::isValidPeer (reinterpret_cast (peer))) - peer = nullptr; + if (display != nullptr) + { + ScopedXLock xlock; - return reinterpret_cast (peer); + if (! XFindContext (display, (XID) windowHandle, windowHandleXContext, &peer)) + if (peer != nullptr && ! ComponentPeer::isValidPeer (reinterpret_cast (peer))) + peer = nullptr; + } + + return reinterpret_cast (peer); } void setVisible (bool shouldBeVisible) override { ScopedXLock xlock; + if (shouldBeVisible) XMapWindow (display, windowH); else @@ -886,7 +1582,7 @@ public: void setTitle (const String& title) override { XTextProperty nameProperty; - char* strings[] = { const_cast (title.toRawUTF8()) }; + char* strings[] = { const_cast (title.toRawUTF8()) }; ScopedXLock xlock; if (XStringListToTextProperty (strings, 1, &nameProperty)) @@ -915,9 +1611,9 @@ public: clientMsg.window = windowH; clientMsg.type = ClientMessage; clientMsg.format = 32; - clientMsg.message_type = Atoms::get().WindowState; + clientMsg.message_type = Atoms::get().windowState; clientMsg.data.l[0] = 0; // Remove - clientMsg.data.l[1] = fs; + clientMsg.data.l[1] = (long) fs; clientMsg.data.l[2] = 0; clientMsg.data.l[3] = 1; // Normal Source @@ -935,17 +1631,22 @@ public: bounds = newBounds.withSize (jmax (1, newBounds.getWidth()), jmax (1, newBounds.getHeight())); + currentScaleFactor = DisplayGeometry::getInstance().findDisplayForRect (bounds, true).scale; + + Rectangle physicalBounds = + DisplayGeometry::scaledToPhysical (bounds); + WeakReference deletionChecker (&component); ScopedXLock xlock; XSizeHints* const hints = XAllocSizeHints(); hints->flags = USSize | USPosition; - hints->x = bounds.getX(); - hints->y = bounds.getY(); - hints->width = bounds.getWidth(); - hints->height = bounds.getHeight(); + hints->x = physicalBounds.getX(); + hints->y = physicalBounds.getY(); + hints->width = physicalBounds.getWidth(); + hints->height = physicalBounds.getHeight(); - if ((getStyleFlags() & (windowHasTitleBar | windowIsResizable)) == windowHasTitleBar) + if ((getStyleFlags() & windowIsResizable) == 0) { hints->min_width = hints->max_width = hints->width; hints->min_height = hints->max_height = hints->height; @@ -956,10 +1657,10 @@ public: XFree (hints); XMoveResizeWindow (display, windowH, - bounds.getX() - windowBorder.getLeft(), - bounds.getY() - windowBorder.getTop(), - bounds.getWidth(), - bounds.getHeight()); + physicalBounds.getX() - windowBorder.getLeft(), + physicalBounds.getY() - windowBorder.getTop(), + (unsigned int) physicalBounds.getWidth(), + (unsigned int) physicalBounds.getHeight()); if (deletionChecker != nullptr) { @@ -971,14 +1672,14 @@ public: Rectangle getBounds() const override { return bounds; } - Point localToGlobal (Point relativePosition) override + Point localToGlobal (Point relativePosition) override { - return relativePosition + bounds.getPosition(); + return relativePosition + bounds.getPosition().toFloat(); } - Point globalToLocal (Point screenPosition) override + Point globalToLocal (Point screenPosition) override { - return screenPosition - bounds.getPosition(); + return screenPosition - bounds.getPosition().toFloat(); } void setAlpha (float /* newAlpha */) override @@ -1002,7 +1703,7 @@ public: clientMsg.window = windowH; clientMsg.type = ClientMessage; clientMsg.format = 32; - clientMsg.message_type = Atoms::get().ChangeState; + clientMsg.message_type = Atoms::get().changeState; clientMsg.data.l[0] = IconicState; ScopedXLock xlock; @@ -1018,10 +1719,10 @@ public: { ScopedXLock xlock; const Atoms& atoms = Atoms::get(); - GetXProperty prop (windowH, atoms.State, 0, 64, false, atoms.State); + GetXProperty prop (windowH, atoms.state, 0, 64, false, atoms.state); return prop.success - && prop.actualType == atoms.State + && prop.actualType == atoms.state && prop.actualFormat == 32 && prop.numItems > 0 && ((unsigned long*) prop.data)[0] == IconicState; @@ -1039,7 +1740,7 @@ public: r = Desktop::getInstance().getDisplays().getMainDisplay().userArea; if (! r.isEmpty()) - setBounds (r, shouldBeFullScreen); + setBounds (ScalingHelpers::scaledScreenPosToUnscaled (component, r), shouldBeFullScreen); component.repaint(); } @@ -1079,11 +1780,9 @@ public: if (XQueryTree (display, root, &root, &parent, &windowList, &windowListSize) != 0) { - for (int i = windowListSize; --i >= 0;) + for (int i = (int) windowListSize; --i >= 0;) { - LinuxComponentPeer* const peer = LinuxComponentPeer::getPeerFor (windowList[i]); - - if (peer != 0) + if (LinuxComponentPeer* const peer = LinuxComponentPeer::getPeerFor (windowList[i])) { result = (peer == this); break; @@ -1109,9 +1808,9 @@ public: if (c == &component) break; - // TODO: needs scaling correctly - if (c->contains (localPos + bounds.getPosition() - c->getScreenPosition())) - return false; + if (ComponentPeer* peer = c->getPeer()) + if (peer->contains (localPos + bounds.getPosition() - peer->getBounds().getPosition(), true)) + return false; } if (trueIfInAChildWindow) @@ -1119,11 +1818,13 @@ public: ::Window root, child; int wx, wy; - unsigned int ww, wh, bw, depth; + unsigned int ww, wh, bw, bitDepth; ScopedXLock xlock; - return XGetGeometry (display, (::Drawable) windowH, &root, &wx, &wy, &ww, &wh, &bw, &depth) + localPos *= currentScaleFactor; + + return XGetGeometry (display, (::Drawable) windowH, &root, &wx, &wy, &ww, &wh, &bw, &bitDepth) && XTranslateCoordinates (display, windowH, windowH, localPos.getX(), localPos.getY(), &wx, &wy, &child) && child == None; } @@ -1152,7 +1853,7 @@ public: ev.xclient.type = ClientMessage; ev.xclient.serial = 0; ev.xclient.send_event = True; - ev.xclient.message_type = Atoms::get().ActiveWin; + ev.xclient.message_type = Atoms::get().activeWin; ev.xclient.window = windowH; ev.xclient.format = 32; ev.xclient.data.l[0] = 2; @@ -1178,10 +1879,7 @@ public: void toBehind (ComponentPeer* other) override { - LinuxComponentPeer* const otherPeer = dynamic_cast (other); - jassert (otherPeer != nullptr); // wrong type of window? - - if (otherPeer != nullptr) + if (LinuxComponentPeer* const otherPeer = dynamic_cast (other)) { setMinimised (false); @@ -1190,6 +1888,8 @@ public: ScopedXLock xlock; XRestackWindows (display, newStack, 2); } + else + jassertfalse; // wrong type of window? } bool isFocused() const override @@ -1212,7 +1912,7 @@ public: && atts.map_state == IsViewable && ! isFocused()) { - XSetInputFocus (display, windowH, RevertToParent, getUserTime()); + XSetInputFocus (display, windowH, RevertToParent, (::Time) getUserTime()); isActiveApplication = true; } } @@ -1221,7 +1921,7 @@ public: void repaint (const Rectangle& area) override { - repainter->repaint (area.getIntersection (component.getLocalBounds())); + repainter->repaint (area.getIntersection (bounds.withZeroOrigin())); } void performAnyPendingRepaintsNow() override @@ -1232,7 +1932,7 @@ public: void setIcon (const Image& newIcon) override { const int dataSize = newIcon.getWidth() * newIcon.getHeight() + 2; - HeapBlock data (dataSize); + HeapBlock data ((size_t) dataSize); int index = 0; data[index++] = (unsigned long) newIcon.getWidth(); @@ -1340,6 +2040,8 @@ public: void handleKeyPressEvent (XKeyEvent& keyEvent) { + const ModifierKeys oldMods (currentModifiers); + char utf8 [64] = { 0 }; juce_wchar unicodeChar = 0; int keyCode = 0; @@ -1348,7 +2050,7 @@ public: { ScopedXLock xlock; - updateKeyStates (keyEvent.keycode, true); + updateKeyStates ((int) keyEvent.keycode, true); String oldLocale (::setlocale (LC_ALL, 0)); ::setlocale (LC_ALL, ""); @@ -1361,15 +2063,14 @@ public: keyCode = (int) unicodeChar; if (keyCode < 0x20) - keyCode = XkbKeycodeToKeysym (display, keyEvent.keycode, 0, currentModifiers.isShiftDown() ? 1 : 0); + keyCode = (int) XkbKeycodeToKeysym (display, (::KeyCode) keyEvent.keycode, 0, currentModifiers.isShiftDown() ? 1 : 0); keyDownChange = (sym != NoSymbol) && ! updateKeyModifiersFromSym (sym, true); } - const ModifierKeys oldMods (currentModifiers); bool keyPressed = false; - if ((sym & 0xff00) == 0xff00 || sym == XK_ISO_Left_Tab) + if ((sym & 0xff00) == 0xff00 || keyCode == XK_ISO_Left_Tab) { switch (sym) // Translate keypad { @@ -1428,6 +2129,11 @@ public: keyCode &= 0xff; break; + case XK_ISO_Left_Tab: + keyPressed = true; + keyCode = XK_Tab & 0xff; + break; + default: if (sym >= XK_F1 && sym <= XK_F16) { @@ -1471,12 +2177,12 @@ public: { if (! isKeyReleasePartOfAutoRepeat (keyEvent)) { - updateKeyStates (keyEvent.keycode, false); + updateKeyStates ((int) keyEvent.keycode, false); KeySym sym; { ScopedXLock xlock; - sym = XkbKeycodeToKeysym (display, keyEvent.keycode, 0, 0); + sym = XkbKeycodeToKeysym (display, (::KeyCode) keyEvent.keycode, 0, 0); } const ModifierKeys oldMods (currentModifiers); @@ -1491,9 +2197,9 @@ public: } template - static Point getMousePos (const EventType& e) noexcept + Point getMousePos (const EventType& e) noexcept { - return Point (e.x, e.y); + return Point ((float) e.x, (float) e.y) / currentScaleFactor; } void handleWheelEvent (const XButtonPressedEvent& buttonPressEvent, const float amount) @@ -1503,6 +2209,7 @@ public: wheel.deltaY = amount; wheel.isReversed = false; wheel.isSmooth = false; + wheel.isInertial = false; handleMouseWheel (0, getMousePos (buttonPressEvent), getEventTime (buttonPressEvent), wheel); } @@ -1516,7 +2223,7 @@ public: void handleButtonPressEvent (const XButtonPressedEvent& buttonPressEvent) { - updateKeyModifiers (buttonPressEvent.state); + updateKeyModifiers ((int) buttonPressEvent.state); switch (pointerMap [buttonPressEvent.button - Button1]) { @@ -1533,7 +2240,7 @@ public: void handleButtonReleaseEvent (const XButtonReleasedEvent& buttonRelEvent) { - updateKeyModifiers (buttonRelEvent.state); + updateKeyModifiers ((int) buttonRelEvent.state); if (parentWindow != 0) updateWindowBounds(); @@ -1556,7 +2263,7 @@ public: void handleMotionNotifyEvent (const XPointerMovedEvent& movedEvent) { - updateKeyModifiers (movedEvent.state); + updateKeyModifiers ((int) movedEvent.state); lastMousePos = Point (movedEvent.x_root, movedEvent.y_root); @@ -1575,7 +2282,7 @@ public: if (! currentModifiers.isAnyMouseButtonDown()) { - updateKeyModifiers (enterEvent.state); + updateKeyModifiers ((int) enterEvent.state); handleMouseEvent (0, getMousePos (enterEvent), currentModifiers, getEventTime (enterEvent)); } } @@ -1588,7 +2295,7 @@ public: if (((! currentModifiers.isAnyMouseButtonDown()) && leaveEvent.mode == NotifyNormal) || leaveEvent.mode == NotifyUngrab) { - updateKeyModifiers (leaveEvent.state); + updateKeyModifiers ((int) leaveEvent.state); handleMouseEvent (0, getMousePos (leaveEvent), currentModifiers, getEventTime (leaveEvent)); } } @@ -1613,6 +2320,10 @@ public: XEvent nextEvent; ScopedXLock xlock; + // if we have opengl contexts then just repaint them all + // regardless if this is really necessary + repaintOpenGLContexts (); + if (exposeEvent.window != windowH) { Window child; @@ -1621,8 +2332,10 @@ public: &child); } + // exposeEvent is in local window local coordinates so do not convert with + // physicalToScaled, but rather use currentScaleFactor repaint (Rectangle (exposeEvent.x, exposeEvent.y, - exposeEvent.width, exposeEvent.height)); + exposeEvent.width, exposeEvent.height) / currentScaleFactor); while (XEventsQueued (display, QueuedAfterFlush) > 0) { @@ -1633,7 +2346,7 @@ public: XNextEvent (display, &nextEvent); const XExposeEvent& nextExposeEvent = (const XExposeEvent&) nextEvent.xexpose; repaint (Rectangle (nextExposeEvent.x, nextExposeEvent.y, - nextExposeEvent.width, nextExposeEvent.height)); + nextExposeEvent.width, nextExposeEvent.height) / currentScaleFactor); } } @@ -1699,11 +2412,11 @@ public: { const Atoms& atoms = Atoms::get(); - if (clientMsg.message_type == atoms.Protocols && clientMsg.format == 32) + if (clientMsg.message_type == atoms.protocols && clientMsg.format == 32) { const Atom atom = (Atom) clientMsg.data.l[0]; - if (atom == atoms.ProtocolList [Atoms::PING]) + if (atom == atoms.protocolList [Atoms::PING]) { Window root = RootWindow (display, DefaultScreen (display)); @@ -1712,7 +2425,7 @@ public: XSendEvent (display, root, False, NoEventMask, &event); XFlush (display); } - else if (atom == atoms.ProtocolList [Atoms::TAKE_FOCUS]) + else if (atom == atoms.protocolList [Atoms::TAKE_FOCUS]) { if ((getStyleFlags() & juce::ComponentPeer::windowIgnoresKeyPresses) == 0) { @@ -1723,11 +2436,11 @@ public: && XGetWindowAttributes (display, clientMsg.window, &atts)) { if (atts.map_state == IsViewable) - XSetInputFocus (display, clientMsg.window, RevertToParent, clientMsg.data.l[1]); + XSetInputFocus (display, clientMsg.window, RevertToParent, (::Time) clientMsg.data.l[1]); } } } - else if (atom == atoms.ProtocolList [Atoms::DELETE_WINDOW]) + else if (atom == atoms.protocolList [Atoms::DELETE_WINDOW]) { handleUserClosingWindow(); } @@ -1794,6 +2507,34 @@ public: XDefineCursor (display, windowH, cursor); } + //============================================================================== + double getCurrentScale() noexcept + { + return currentScaleFactor; + } + + //=============================================================================== + void addOpenGLRepaintListener (Component* dummy) + { + if (dummy != nullptr) + glRepaintListeners.addIfNotAlreadyThere (dummy); + } + + void removeOpenGLRepaintListener (Component* dummy) + { + if (dummy != nullptr) + glRepaintListeners.removeAllInstancesOf (dummy); + } + + void repaintOpenGLContexts() + { + for (int i = 0; i < glRepaintListeners.size(); ++i) + { + if (Component* c = glRepaintListeners [i]) + c->handleCommandMessage (0); + } + } + //============================================================================== bool dontRepaint; @@ -1852,7 +2593,7 @@ private: if (! isTimerRunning()) startTimer (repaintTimerPeriod); - regionsNeedingRepaint.add (area); + regionsNeedingRepaint.add (area * peer.currentScaleFactor); } void performAnyPendingRepaintsNow() @@ -1882,7 +2623,7 @@ private: #endif (totalArea.getWidth() + 31) & ~31, (totalArea.getHeight() + 31) & ~31, - false, peer.depth, peer.visual)); + false, (unsigned int) peer.depth, peer.visual)); } startTimer (repaintTimerPeriod); @@ -1897,20 +2638,24 @@ private: { ScopedPointer context (peer.getComponent().getLookAndFeel() .createGraphicsContext (image, -totalArea.getPosition(), adjustedList)); + context->addTransform (AffineTransform::scale ((float) peer.currentScaleFactor)); peer.handlePaint (*context); } for (const Rectangle* i = originalRepaintRegion.begin(), * const e = originalRepaintRegion.end(); i != e; ++i) { + XBitmapImage* xbitmap = static_cast (image.getPixelData()); #if JUCE_USE_XSHM - if (XSHMHelpers::isShmAvailable()) + if (xbitmap->isUsingXShm()) ++shmPaintsPending; #endif - static_cast (image.getPixelData()) - ->blitToWindow (peer.windowH, - i->getX(), i->getY(), i->getWidth(), i->getHeight(), - i->getX() - totalArea.getX(), i->getY() - totalArea.getY()); + + xbitmap->blitToWindow (peer.windowH, + i->getX(), i->getY(), + (unsigned int) i->getWidth(), + (unsigned int) i->getHeight(), + i->getX() - totalArea.getX(), i->getY() - totalArea.getY()); } } @@ -1937,7 +2682,7 @@ private: JUCE_DECLARE_NON_COPYABLE (LinuxRepaintManager) }; - ScopedPointer repainter; + ScopedPointer repainter; friend class LinuxRepaintManager; Window windowH, parentWindow; @@ -1948,6 +2693,8 @@ private: int depth; BorderSize windowBorder; bool isAlwaysOnTop; + double currentScaleFactor; + Array glRepaintListeners; enum { KeyPressEventType = 2 }; struct MotifWmHints @@ -2168,7 +2915,7 @@ private: netHints[1] = Atoms::getIfExists ("_KDE_NET_WM_WINDOW_TYPE_OVERRIDE"); - xchangeProperty (windowH, Atoms::get().WindowType, XA_ATOM, 32, &netHints, 2); + xchangeProperty (windowH, Atoms::get().windowType, XA_ATOM, 32, &netHints, 2); int numHints = 0; @@ -2179,7 +2926,7 @@ private: netHints [numHints++] = Atoms::getIfExists ("_NET_WM_STATE_ABOVE"); if (numHints > 0) - xchangeProperty (windowH, Atoms::get().WindowState, XA_ATOM, 32, &netHints, numHints); + xchangeProperty (windowH, Atoms::get().windowState, XA_ATOM, 32, &netHints, numHints); } void createWindow (Window parentToAddTo) @@ -2191,6 +2938,8 @@ private: const int screen = DefaultScreen (display); Window root = RootWindow (display, screen); + parentWindow = parentToAddTo; + // Try to obtain a 32-bit visual or fallback to 24 or 16 visual = Visuals::findVisualFormat ((styleFlags & windowIsSemiTransparent) ? 32 : 24, depth); @@ -2255,11 +3004,11 @@ private: const Atoms& atoms = Atoms::get(); // Associate the PID, allowing to be shut down when something goes wrong - unsigned long pid = getpid(); - xchangeProperty (windowH, atoms.Pid, XA_CARDINAL, 32, &pid, 1); + unsigned long pid = (unsigned long) getpid(); + xchangeProperty (windowH, atoms.pid, XA_CARDINAL, 32, &pid, 1); // Set window manager protocols - xchangeProperty (windowH, atoms.Protocols, XA_ATOM, 32, atoms.ProtocolList, 2); + xchangeProperty (windowH, atoms.protocols, XA_ATOM, 32, atoms.protocolList, 2); // Set drag and drop flags xchangeProperty (windowH, atoms.XdndTypeList, XA_ATOM, 32, atoms.allowedMimeTypes, numElementsInArray (atoms.allowedMimeTypes)); @@ -2306,7 +3055,7 @@ private: static int64 getEventTime (::Time t) { static int64 eventTimeOffset = 0x12345678; - const int64 thisMessageTime = t; + const int64 thisMessageTime = (int64) t; if (eventTimeOffset == 0x12345678) eventTimeOffset = Time::currentTimeMillis() - thisMessageTime; @@ -2316,7 +3065,7 @@ private: long getUserTime() const { - GetXProperty prop (windowH, Atoms::get().UserTime, 0, 65536, false, XA_CARDINAL); + GetXProperty prop (windowH, Atoms::get().userTime, 0, 65536, false, XA_CARDINAL); return prop.success ? *(long*) prop.data : 0; } @@ -2353,15 +3102,20 @@ private: { Window root, child; int wx = 0, wy = 0; - unsigned int ww = 0, wh = 0, bw, depth; + unsigned int ww = 0, wh = 0, bw, bitDepth; ScopedXLock xlock; - if (XGetGeometry (display, (::Drawable) windowH, &root, &wx, &wy, &ww, &wh, &bw, &depth)) + if (XGetGeometry (display, (::Drawable) windowH, &root, &wx, &wy, &ww, &wh, &bw, &bitDepth)) if (! XTranslateCoordinates (display, windowH, root, 0, 0, &wx, &wy, &child)) wx = wy = 0; - bounds.setBounds (wx, wy, ww, wh); + Rectangle physicalBounds (wx, wy, (int) ww, (int) wh); + + currentScaleFactor = + DisplayGeometry::getInstance().findDisplayForRect (physicalBounds, false).scale; + + bounds = DisplayGeometry::physicalToScaled (physicalBounds); } } @@ -2421,7 +3175,7 @@ private: msg.display = display; msg.window = dragAndDropSourceWindow; msg.format = 32; - msg.data.l[0] = windowH; + msg.data.l[0] = (long) windowH; ScopedXLock xlock; XSendEvent (display, dragAndDropSourceWindow, False, 0, (XEvent*) &msg); @@ -2433,7 +3187,7 @@ private: msg.display = display; msg.window = targetWindow; msg.format = 32; - msg.data.l[0] = windowH; + msg.data.l[0] = (long) windowH; ScopedXLock xlock; return XSendEvent (display, targetWindow, False, 0, (XEvent*) &msg) != 0; @@ -2461,9 +3215,9 @@ private: const int numMimeTypes = dragState.getNumMimeTypes(); msg.data.l[1] = (dragState.xdndVersion << 24) | (numMimeTypes > 3); - msg.data.l[2] = numMimeTypes > 0 ? mimeTypes[0] : 0; - msg.data.l[3] = numMimeTypes > 1 ? mimeTypes[1] : 0; - msg.data.l[4] = numMimeTypes > 2 ? mimeTypes[2] : 0; + msg.data.l[2] = numMimeTypes > 0 ? (long) mimeTypes[0] : 0; + msg.data.l[3] = numMimeTypes > 1 ? (long) mimeTypes[1] : 0; + msg.data.l[4] = numMimeTypes > 2 ? (long) mimeTypes[2] : 0; sendExternalDragAndDropMessage (msg, targetWindow); } @@ -2475,15 +3229,16 @@ private: msg.message_type = Atoms::get().XdndPosition; - const Point mousePos (Desktop::getInstance().getMousePosition()); + Point mousePos (Desktop::getInstance().getMousePosition()); if (dragState.silentRect.contains (mousePos)) // we've been asked to keep silent return; + mousePos = DisplayGeometry::scaledToPhysical (mousePos); msg.data.l[1] = 0; msg.data.l[2] = (mousePos.x << 16) | mousePos.y; msg.data.l[3] = CurrentTime; - msg.data.l[4] = Atoms::get().XdndActionCopy; // this is all JUCE currently supports + msg.data.l[4] = (long) Atoms::get().XdndActionCopy; // this is all JUCE currently supports dragState.expectingStatus = sendExternalDragAndDropMessage (msg, targetWindow); } @@ -2495,7 +3250,7 @@ private: msg.message_type = Atoms::get().XdndStatus; msg.data.l[1] = (acceptDrop ? 1 : 0) | 2; // 2 indicates that we want to receive position messages - msg.data.l[4] = dropAction; + msg.data.l[4] = (long) dropAction; sendDragAndDropMessage (msg); } @@ -2544,7 +3299,7 @@ private: evt.xselectionrequest.property, targetType, 8, dragState.textOrFiles.toRawUTF8(), - dragState.textOrFiles.getNumBytesAsUTF8()); + (int) dragState.textOrFiles.getNumBytesAsUTF8()); } XSendEvent (display, evt.xselectionrequest.requestor, True, 0, &s); @@ -2563,10 +3318,10 @@ private: || (Atom) clientMsg.data.l[4] == Atoms::get().XdndActionPrivate)) { if ((clientMsg.data.l[1] & 2) == 0) // target requests silent rectangle - dragState.silentRect.setBounds (clientMsg.data.l[2] >> 16, - clientMsg.data.l[2] & 0xffff, - clientMsg.data.l[3] >> 16, - clientMsg.data.l[3] & 0xffff); + dragState.silentRect.setBounds ((int) clientMsg.data.l[2] >> 16, + (int) clientMsg.data.l[2] & 0xffff, + (int) clientMsg.data.l[3] >> 16, + (int) clientMsg.data.l[3] & 0xffff); dragState.canDrop = true; } @@ -2633,7 +3388,7 @@ private: if (dragAndDropSourceWindow == 0) return; - dragAndDropSourceWindow = clientMsg.data.l[0]; + dragAndDropSourceWindow = (::Window) clientMsg.data.l[0]; Point dropPos ((int) clientMsg.data.l[2] >> 16, (int) clientMsg.data.l[2] & 0xffff); @@ -2696,7 +3451,7 @@ private: srcMimeTypeAtomList.clear(); dragAndDropCurrentMimeType = 0; - const unsigned long dndCurrentVersion = static_cast (clientMsg.data.l[1] & 0xff000000) >> 24; + const unsigned long dndCurrentVersion = static_cast (clientMsg.data.l[1] & 0xff000000) >> 24; if (dndCurrentVersion < 3 || dndCurrentVersion > Atoms::DndVersion) { @@ -2704,7 +3459,7 @@ private: return; } - dragAndDropSourceWindow = clientMsg.data.l[0]; + dragAndDropSourceWindow = (::Window) clientMsg.data.l[0]; if ((clientMsg.data.l[1] & 1) != 0) { @@ -2728,7 +3483,7 @@ private: { for (int i = 2; i < 5; ++i) if (clientMsg.data.l[i] != None) - srcMimeTypeAtomList.add (clientMsg.data.l[i]); + srcMimeTypeAtomList.add ((unsigned long) clientMsg.data.l[i]); if (srcMimeTypeAtomList.size() == 0) { @@ -2765,7 +3520,7 @@ private: if (! prop.success) break; - dropData.append (prop.data, prop.numItems * prop.actualFormat / 8); + dropData.append (prop.data, prop.numItems * (size_t) prop.actualFormat / 8); if (prop.bytesLeft <= 0) break; @@ -2805,7 +3560,7 @@ private: dragAndDropCurrentMimeType, Atoms::getCreating ("JXSelectionWindowProperty"), windowH, - clientMsg.data.l[2]); + (::Time) clientMsg.data.l[2]); } } @@ -2893,7 +3648,7 @@ private: Window dragAndDropSourceWindow; bool finishAfterDropDataReceived; - Array srcMimeTypeAtomList; + Array srcMimeTypeAtomList; int pointerMap[5]; @@ -2953,31 +3708,35 @@ void ModifierKeys::updateCurrentModifiers() noexcept ModifierKeys ModifierKeys::getCurrentModifiersRealtime() noexcept { - Window root, child; - int x, y, winx, winy; - unsigned int mask; - int mouseMods = 0; - - ScopedXLock xlock; - - if (XQueryPointer (display, RootWindow (display, DefaultScreen (display)), - &root, &child, &x, &y, &winx, &winy, &mask) != False) + if (display != nullptr) { - if ((mask & Button1Mask) != 0) mouseMods |= ModifierKeys::leftButtonModifier; - if ((mask & Button2Mask) != 0) mouseMods |= ModifierKeys::middleButtonModifier; - if ((mask & Button3Mask) != 0) mouseMods |= ModifierKeys::rightButtonModifier; + Window root, child; + int x, y, winx, winy; + unsigned int mask; + int mouseMods = 0; + + ScopedXLock xlock; + + if (XQueryPointer (display, RootWindow (display, DefaultScreen (display)), + &root, &child, &x, &y, &winx, &winy, &mask) != False) + { + if ((mask & Button1Mask) != 0) mouseMods |= ModifierKeys::leftButtonModifier; + if ((mask & Button2Mask) != 0) mouseMods |= ModifierKeys::middleButtonModifier; + if ((mask & Button3Mask) != 0) mouseMods |= ModifierKeys::rightButtonModifier; + } + + LinuxComponentPeer::currentModifiers = LinuxComponentPeer::currentModifiers.withoutMouseButtons().withFlags (mouseMods); } - LinuxComponentPeer::currentModifiers = LinuxComponentPeer::currentModifiers.withoutMouseButtons().withFlags (mouseMods); return LinuxComponentPeer::currentModifiers; } //============================================================================== -void Desktop::setKioskComponent (Component* kioskModeComponent, bool enableOrDisable, bool /* allowMenusAndBars */) +void Desktop::setKioskComponent (Component* comp, bool enableOrDisable, bool /* allowMenusAndBars */) { if (enableOrDisable) - kioskModeComponent->setBounds (getDisplays().getMainDisplay().totalArea); + comp->setBounds (getDisplays().getMainDisplay().totalArea); } //============================================================================== @@ -2987,118 +3746,56 @@ ComponentPeer* Component::createNewPeer (int styleFlags, void* nativeWindowToAtt } //============================================================================== -static double getDisplayDPI (int index) -{ - double dpiX = (DisplayWidth (display, index) * 25.4) / DisplayWidthMM (display, index); - double dpiY = (DisplayHeight (display, index) * 25.4) / DisplayHeightMM (display, index); - return (dpiX + dpiY) / 2.0; -} - void Desktop::Displays::findDisplays (float masterScale) { - if (display == 0) - return; + DisplayGeometry& geometry = DisplayGeometry::getOrCreateInstance (display, masterScale); - ScopedXLock xlock; - - #if JUCE_USE_XINERAMA - int major_opcode, first_event, first_error; - - if (XQueryExtension (display, "XINERAMA", &major_opcode, &first_event, &first_error)) + // add the main display first + int mainDisplayIdx; + for (mainDisplayIdx = 0; mainDisplayIdx < geometry.infos.size(); ++mainDisplayIdx) { - typedef Bool (*tXineramaIsActive) (::Display*); - typedef XineramaScreenInfo* (*tXineramaQueryScreens) (::Display*, int*); - - static tXineramaIsActive xineramaIsActive = nullptr; - static tXineramaQueryScreens xineramaQueryScreens = nullptr; - - if (xineramaIsActive == nullptr || xineramaQueryScreens == nullptr) - { - void* h = dlopen ("libXinerama.so", RTLD_GLOBAL | RTLD_NOW); - - if (h == nullptr) - h = dlopen ("libXinerama.so.1", RTLD_GLOBAL | RTLD_NOW); - - if (h != nullptr) - { - xineramaIsActive = (tXineramaIsActive) dlsym (h, "XineramaIsActive"); - xineramaQueryScreens = (tXineramaQueryScreens) dlsym (h, "XineramaQueryScreens"); - } - } - - if (xineramaIsActive != nullptr - && xineramaQueryScreens != nullptr - && xineramaIsActive (display)) - { - int numMonitors = 0; - - if (XineramaScreenInfo* const screens = xineramaQueryScreens (display, &numMonitors)) - { - for (int index = 0; index < numMonitors; ++index) - { - for (int j = numMonitors; --j >= 0;) - { - if (screens[j].screen_number == index) - { - Display d; - d.userArea = d.totalArea = Rectangle (screens[j].x_org, - screens[j].y_org, - screens[j].width, - screens[j].height) * masterScale; - d.isMain = (index == 0); - d.scale = masterScale; - d.dpi = getDisplayDPI (0); // (all screens share the same DPI) - - displays.add (d); - } - } - } - - XFree (screens); - } - } + const DisplayGeometry::ExtendedInfo& info = geometry.infos.getReference (mainDisplayIdx); + if (info.isMain) + break; } - if (displays.size() == 0) - #endif + // no main display found then use the first + if (mainDisplayIdx >= geometry.infos.size()) + mainDisplayIdx = 0; + + // add the main display { - Atom hints = Atoms::getIfExists ("_NET_WORKAREA"); + const DisplayGeometry::ExtendedInfo& info = + geometry.infos.getReference (mainDisplayIdx); + Desktop::Displays::Display d; - if (hints != None) - { - const int numMonitors = ScreenCount (display); + d.isMain = true; + d.scale = masterScale * info.scale; + d.dpi = info.dpi; - for (int i = 0; i < numMonitors; ++i) - { - GetXProperty prop (RootWindow (display, i), hints, 0, 4, false, XA_CARDINAL); + d.totalArea = DisplayGeometry::physicalToScaled (info.totalBounds); + d.userArea = (info.usableBounds / d.scale) + info.topLeftScaled; - if (prop.success && prop.actualType == XA_CARDINAL && prop.actualFormat == 32 && prop.numItems == 4) - { - const long* const position = (const long*) prop.data; + displays.add (d); + } - Display d; - d.userArea = d.totalArea = Rectangle (position[0], position[1], - position[2], position[3]) / masterScale; - d.isMain = (displays.size() == 0); - d.scale = masterScale; - d.dpi = getDisplayDPI (i); + for (int i = 0; i < geometry.infos.size(); ++i) + { + // don't add the main display a second time + if (i == mainDisplayIdx) + continue; - displays.add (d); - } - } - } + const DisplayGeometry::ExtendedInfo& info = geometry.infos.getReference (i); + Desktop::Displays::Display d; - if (displays.size() == 0) - { - Display d; - d.userArea = d.totalArea = Rectangle (DisplayWidth (display, DefaultScreen (display)), - DisplayHeight (display, DefaultScreen (display))) * masterScale; - d.isMain = true; - d.scale = masterScale; - d.dpi = getDisplayDPI (0); + d.isMain = false; + d.scale = masterScale * info.scale; + d.dpi = info.dpi; - displays.add (d); - } + d.totalArea = DisplayGeometry::physicalToScaled (info.totalBounds); + d.userArea = (info.usableBounds / d.scale) + info.topLeftScaled; + + displays.add (d); } } @@ -3116,15 +3813,24 @@ bool MouseInputSource::SourceList::addSource() bool Desktop::canUseSemiTransparentWindows() noexcept { - int matchedDepth = 0; - const int desiredDepth = 32; + #if JUCE_USE_XRENDER + if (XRender::hasCompositingWindowManager()) + { + int matchedDepth = 0, desiredDepth = 32; - return Visuals::findVisualFormat (desiredDepth, matchedDepth) != 0 - && (matchedDepth == desiredDepth); + return Visuals::findVisualFormat (desiredDepth, matchedDepth) != 0 + && matchedDepth == desiredDepth; + } + #endif + + return false; } -Point MouseInputSource::getCurrentRawMousePosition() +Point MouseInputSource::getCurrentRawMousePosition() { + if (display == nullptr) + return Point(); + Window root, child; int x, y, winx, winy; unsigned int mask; @@ -3140,14 +3846,18 @@ Point MouseInputSource::getCurrentRawMousePosition() x = y = -1; } - return Point (x, y); + return DisplayGeometry::physicalToScaled (Point ((float) x, (float) y)); } -void MouseInputSource::setRawMousePosition (Point newPosition) +void MouseInputSource::setRawMousePosition (Point newPosition) { - ScopedXLock xlock; - Window root = RootWindow (display, DefaultScreen (display)); - XWarpPointer (display, None, root, 0, 0, 0, 0, newPosition.getX(), newPosition.getY()); + if (display != nullptr) + { + ScopedXLock xlock; + Window root = RootWindow (display, DefaultScreen (display)); + newPosition = DisplayGeometry::scaledToPhysical (newPosition); + XWarpPointer (display, None, root, 0, 0, 0, 0, roundToInt (newPosition.getX()), roundToInt (newPosition.getY())); + } } double Desktop::getDefaultMasterScale() @@ -3169,16 +3879,19 @@ void Desktop::setScreenSaverEnabled (const bool isEnabled) { screenSaverAllowed = isEnabled; - typedef void (*tXScreenSaverSuspend) (Display*, Bool); - static tXScreenSaverSuspend xScreenSaverSuspend = nullptr; + if (display != nullptr) + { + typedef void (*tXScreenSaverSuspend) (Display*, Bool); + static tXScreenSaverSuspend xScreenSaverSuspend = nullptr; - if (xScreenSaverSuspend == nullptr) - if (void* h = dlopen ("libXss.so", RTLD_GLOBAL | RTLD_NOW)) - xScreenSaverSuspend = (tXScreenSaverSuspend) dlsym (h, "XScreenSaverSuspend"); + if (xScreenSaverSuspend == nullptr) + if (void* h = dlopen ("libXss.so", RTLD_GLOBAL | RTLD_NOW)) + xScreenSaverSuspend = (tXScreenSaverSuspend) dlsym (h, "XScreenSaverSuspend"); - ScopedXLock xlock; - if (xScreenSaverSuspend != nullptr) - xScreenSaverSuspend (display, ! isEnabled); + ScopedXLock xlock; + if (xScreenSaverSuspend != nullptr) + xScreenSaverSuspend (display, ! isEnabled); + } } } @@ -3190,9 +3903,12 @@ bool Desktop::isScreenSaverEnabled() //============================================================================== void* CustomMouseCursorInfo::create() const { + if (display == nullptr) + return nullptr; + ScopedXLock xlock; - const unsigned int imageW = image.getWidth(); - const unsigned int imageH = image.getHeight(); + const unsigned int imageW = (unsigned int) image.getWidth(); + const unsigned int imageH = (unsigned int) image.getHeight(); int hotspotX = hotspot.x; int hotspotY = hotspot.y; @@ -3229,10 +3945,10 @@ void* CustomMouseCursorInfo::create() const if (xcursorSupportsARGB != nullptr) { - if (XcursorImage* xcImage = xcursorImageCreate (imageW, imageH)) + if (XcursorImage* xcImage = xcursorImageCreate ((int) imageW, (int) imageH)) { - xcImage->xhot = hotspotX; - xcImage->yhot = hotspotY; + xcImage->xhot = (XcursorDim) hotspotX; + xcImage->yhot = (XcursorDim) hotspotY; XcursorPixel* dest = xcImage->pixels; for (int y = 0; y < (int) imageH; ++y) @@ -3254,17 +3970,17 @@ void* CustomMouseCursorInfo::create() const if (! XQueryBestCursor (display, root, imageW, imageH, &cursorW, &cursorH)) return nullptr; - Image im (Image::ARGB, cursorW, cursorH, true); + Image im (Image::ARGB, (int) cursorW, (int) cursorH, true); { Graphics g (im); if (imageW > cursorW || imageH > cursorH) { - hotspotX = (hotspotX * cursorW) / imageW; - hotspotY = (hotspotY * cursorH) / imageH; + hotspotX = (hotspotX * (int) cursorW) / (int) imageW; + hotspotY = (hotspotY * (int) cursorH) / (int) imageH; - g.drawImageWithin (image, 0, 0, imageW, imageH, + g.drawImageWithin (image, 0, 0, (int) imageW, (int) imageH, RectanglePlacement::xLeft | RectanglePlacement::yTop | RectanglePlacement::onlyReduceInSize, false); } @@ -3274,19 +3990,19 @@ void* CustomMouseCursorInfo::create() const } } - const int stride = (cursorW + 7) >> 3; - HeapBlock maskPlane, sourcePlane; + const unsigned int stride = (cursorW + 7) >> 3; + HeapBlock maskPlane, sourcePlane; maskPlane.calloc (stride * cursorH); sourcePlane.calloc (stride * cursorH); const bool msbfirst = (BitmapBitOrder (display) == MSBFirst); - for (int y = cursorH; --y >= 0;) + for (int y = (int) cursorH; --y >= 0;) { - for (int x = cursorW; --x >= 0;) + for (int x = (int) cursorW; --x >= 0;) { const char mask = (char) (1 << (msbfirst ? (7 - (x & 7)) : (x & 7))); - const int offset = y * stride + (x >> 3); + const unsigned int offset = (unsigned int) y * stride + ((unsigned int) x >> 3); const Colour c (im.getPixelAt (x, y)); @@ -3302,7 +4018,8 @@ void* CustomMouseCursorInfo::create() const black.red = black.green = black.blue = 0; white.red = white.green = white.blue = 0xffff; - void* result = (void*) XCreatePixmapCursor (display, sourcePixmap, maskPixmap, &white, &black, hotspotX, hotspotY); + void* result = (void*) XCreatePixmapCursor (display, sourcePixmap, maskPixmap, &white, &black, + (unsigned int) hotspotX, (unsigned int) hotspotY); XFreePixmap (display, sourcePixmap); XFreePixmap (display, maskPixmap); @@ -3312,13 +4029,18 @@ void* CustomMouseCursorInfo::create() const void MouseCursor::deleteMouseCursor (void* const cursorHandle, const bool) { - ScopedXLock xlock; - if (cursorHandle != nullptr) + if (cursorHandle != nullptr && display != nullptr) + { + ScopedXLock xlock; XFreeCursor (display, (Cursor) cursorHandle); + } } void* MouseCursor::createStandardMouseCursor (MouseCursor::StandardCursorType type) { + if (display == nullptr) + return None; + unsigned int shape; switch (type) @@ -3366,7 +4088,7 @@ void* MouseCursor::createStandardMouseCursor (MouseCursor::StandardCursorType ty void MouseCursor::showInWindow (ComponentPeer* peer) const { - if (LinuxComponentPeer* const lp = dynamic_cast (peer)) + if (LinuxComponentPeer* const lp = dynamic_cast (peer)) lp->showMouseCursor ((Cursor) getHandle()); } @@ -3390,7 +4112,7 @@ bool DragAndDropContainer::performExternalDragDropOfFiles (const StringArray& fi if (MouseInputSource* draggingSource = Desktop::getInstance().getDraggingMouseSource(0)) if (Component* sourceComp = draggingSource->getComponentUnderMouse()) - if (LinuxComponentPeer* const lp = dynamic_cast (sourceComp->getPeer())) + if (LinuxComponentPeer* const lp = dynamic_cast (sourceComp->getPeer())) return lp->externalDragFileInit (files, canMoveFiles); // This method must be called in response to a component's mouseDown or mouseDrag event! @@ -3405,7 +4127,7 @@ bool DragAndDropContainer::performExternalDragDropOfText (const String& text) if (MouseInputSource* draggingSource = Desktop::getInstance().getDraggingMouseSource(0)) if (Component* sourceComp = draggingSource->getComponentUnderMouse()) - if (LinuxComponentPeer* const lp = dynamic_cast (sourceComp->getPeer())) + if (LinuxComponentPeer* const lp = dynamic_cast (sourceComp->getPeer())) return lp->externalDragTextInit (text); // This method must be called in response to a component's mouseDown or mouseDrag event! @@ -3418,7 +4140,28 @@ void LookAndFeel::playAlertSound() { std::cout << "\a" << std::flush; } +//============================================================================== +Rectangle juce_LinuxScaledToPhysicalBounds(ComponentPeer* peer, const Rectangle& bounds) +{ + Rectangle retval = bounds; + if (LinuxComponentPeer* linuxPeer = dynamic_cast (peer)) + retval *= linuxPeer->getCurrentScale(); + + return retval; +} + +void juce_LinuxAddRepaintListener (ComponentPeer* peer, Component* dummy) +{ + if (LinuxComponentPeer* linuxPeer = dynamic_cast (peer)) + linuxPeer->addOpenGLRepaintListener (dummy); +} + +void juce_LinuxRemoveRepaintListener (ComponentPeer* peer, Component* dummy) +{ + if (LinuxComponentPeer* linuxPeer = dynamic_cast (peer)) + linuxPeer->removeOpenGLRepaintListener (dummy); +} //============================================================================== #if JUCE_MODAL_LOOPS_PERMITTED @@ -3508,7 +4251,7 @@ const int KeyPress::numberPadSeparator = (XK_KP_Separator & 0xff)| Keys::ex const int KeyPress::numberPadDecimalPoint = (XK_KP_Decimal & 0xff)| Keys::extendedKeyModifier; const int KeyPress::numberPadEquals = (XK_KP_Equal & 0xff)| Keys::extendedKeyModifier; const int KeyPress::numberPadDelete = (XK_KP_Delete & 0xff)| Keys::extendedKeyModifier; -const int KeyPress::playKey = (0xffeeff00) | Keys::extendedKeyModifier; -const int KeyPress::stopKey = (0xffeeff01) | Keys::extendedKeyModifier; -const int KeyPress::fastForwardKey = (0xffeeff02) | Keys::extendedKeyModifier; -const int KeyPress::rewindKey = (0xffeeff03) | Keys::extendedKeyModifier; +const int KeyPress::playKey = ((int) 0xffeeff00) | Keys::extendedKeyModifier; +const int KeyPress::stopKey = ((int) 0xffeeff01) | Keys::extendedKeyModifier; +const int KeyPress::fastForwardKey = ((int) 0xffeeff02) | Keys::extendedKeyModifier; +const int KeyPress::rewindKey = ((int) 0xffeeff03) | Keys::extendedKeyModifier; diff --git a/JuceLibraryCode/modules/juce_gui_basics/native/juce_mac_FileChooser.mm b/JuceLibraryCode/modules/juce_gui_basics/native/juce_mac_FileChooser.mm index 2075903..8097620 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/native/juce_mac_FileChooser.mm +++ b/JuceLibraryCode/modules/juce_gui_basics/native/juce_mac_FileChooser.mm @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -29,9 +29,11 @@ struct FileChooserDelegateClass : public ObjCClass FileChooserDelegateClass() : ObjCClass ("JUCEFileChooser_") { addIvar ("filters"); + addIvar ("filePreviewComponent"); - addMethod (@selector (dealloc), dealloc, "v@:"); - addMethod (@selector (panel:shouldShowFilename:), shouldShowFilename, "c@:@@"); + addMethod (@selector (dealloc), dealloc, "v@:"); + addMethod (@selector (panel:shouldShowFilename:), shouldShowFilename, "c@:@@"); + addMethod (@selector (panelSelectionDidChange:), panelSelectionDidChange, "c@"); #if defined (MAC_OS_X_VERSION_10_6) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 addProtocol (@protocol (NSOpenSavePanelDelegate)); @@ -40,21 +42,21 @@ struct FileChooserDelegateClass : public ObjCClass registerClass(); } - static void setFilters (id self, StringArray* filters) - { - object_setInstanceVariable (self, "filters", filters); - } + static void setFilters (id self, StringArray* filters) { object_setInstanceVariable (self, "filters", filters); } + static void setFilePreviewComponent (id self, FilePreviewComponent* comp) { object_setInstanceVariable (self, "filePreviewComponent", comp); } + static StringArray* getFilters (id self) { return getIvar (self, "filters"); } + static FilePreviewComponent* getFilePreviewComponent (id self) { return getIvar (self, "filePreviewComponent"); } private: static void dealloc (id self, SEL) { - delete getIvar (self, "filters"); - //sendSuperclassMessage (self, @selector (dealloc)); + delete getFilters (self); + sendSuperclassMessage (self, @selector (dealloc)); } static BOOL shouldShowFilename (id self, SEL, id /*sender*/, NSString* filename) { - StringArray* const filters = getIvar (self, "filters"); + StringArray* const filters = getFilters (self); const File f (nsStringToJuce (filename)); @@ -81,6 +83,32 @@ private: return f.isDirectory() && ! [[NSWorkspace sharedWorkspace] isFilePackageAtPath: filename]; } + + static StringArray getSelectedPaths (id sender) + { + StringArray paths; + + if ([sender isKindOfClass: [NSOpenPanel class]]) + { + NSArray* urls = [(NSOpenPanel*) sender URLs]; + + for (NSUInteger i = 0; i < [urls count]; ++i) + paths.add (nsStringToJuce ([[urls objectAtIndex: i] path])); + } + else if ([sender isKindOfClass: [NSSavePanel class]]) + { + paths.add (nsStringToJuce ([[(NSSavePanel*) sender URL] path])); + } + + return paths; + } + + static void panelSelectionDidChange (id self, SEL, id sender) + { + // NB: would need to extend FilePreviewComponent to handle the full list rather than just the first one + if (FilePreviewComponent* const previewComp = getFilePreviewComponent (self)) + previewComp->selectedFileChanged (File (getSelectedPaths (sender)[0])); + } }; static NSMutableArray* createAllowedTypesArray (const StringArray& filters) @@ -113,7 +141,7 @@ void FileChooser::showPlatformDialog (Array& results, bool isSaveDialogue, bool /*warnAboutOverwritingExistingFiles*/, bool selectMultipleFiles, - FilePreviewComponent* /*extraInfoComponent*/) + FilePreviewComponent* extraInfoComponent) { JUCE_AUTORELEASEPOOL { @@ -151,6 +179,16 @@ void FileChooser::showPlatformDialog (Array& results, [openPanel setResolvesAliases: YES]; } + if (extraInfoComponent != nullptr) + { + NSView* view = [[[NSView alloc] initWithFrame: makeNSRect (extraInfoComponent->getLocalBounds())] autorelease]; + extraInfoComponent->addToDesktop (0, (void*) view); + extraInfoComponent->setVisible (true); + FileChooserDelegateClass::setFilePreviewComponent (delegate, extraInfoComponent); + + [panel setAccessoryView: view]; + } + [panel setDelegate: delegate]; if (isSaveDialogue || selectsDirectory) @@ -172,10 +210,10 @@ void FileChooser::showPlatformDialog (Array& results, [panel setDirectoryURL: [NSURL fileURLWithPath: juceStringToNS (directory)]]; [panel setNameFieldStringValue: juceStringToNS (filename)]; - if ([panel runModal] == NSOKButton) + if ([panel runModal] == 1 /*NSModalResponseOK*/) #else if ([panel runModalForDirectory: juceStringToNS (directory) - file: juceStringToNS (filename)] == NSOKButton) + file: juceStringToNS (filename)] == 1 /*NSModalResponseOK*/) #endif { if (isSaveDialogue) diff --git a/JuceLibraryCode/modules/juce_gui_basics/native/juce_mac_MainMenu.mm b/JuceLibraryCode/modules/juce_gui_basics/native/juce_mac_MainMenu.mm index ea3406e..c511b44 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/native/juce_mac_MainMenu.mm +++ b/JuceLibraryCode/modules/juce_gui_basics/native/juce_mac_MainMenu.mm @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_gui_basics/native/juce_mac_MouseCursor.mm b/JuceLibraryCode/modules/juce_gui_basics/native/juce_mac_MouseCursor.mm index 4811607..09a63d8 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/native/juce_mac_MouseCursor.mm +++ b/JuceLibraryCode/modules/juce_gui_basics/native/juce_mac_MouseCursor.mm @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -50,34 +50,62 @@ namespace MouseCursorHelpers } } - static void* fromWebKitFile (const char* filename, float hx, float hy) + static NSCursor* fromNSImage (NSImage* im, NSPoint hotspot) { - FileInputStream fileStream (File ("/System/Library/Frameworks/WebKit.framework/Frameworks/WebCore.framework/Resources") - .getChildFile (filename)); + NSCursor* c = [[NSCursor alloc] initWithImage: im + hotSpot: hotspot]; + [im release]; + return c; + } - if (fileStream.openedOk()) + static void* fromHIServices (const char* filename) + { + JUCE_AUTORELEASEPOOL { - BufferedInputStream buf (fileStream, 4096); + const String cursorPath (String ("/System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/" + "HIServices.framework/Versions/A/Resources/cursors/") + + filename); - PNGImageFormat pngFormat; - Image im (pngFormat.decodeImage (buf)); + NSImage* originalImage = [[NSImage alloc] initByReferencingFile: juceStringToNS (cursorPath + "/cursor.pdf")]; + NSSize originalSize = [originalImage size]; + NSImage* resultImage = [[NSImage alloc] initWithSize: originalSize]; - if (im.isValid()) - return CustomMouseCursorInfo (im, (int) (hx * im.getWidth()), - (int) (hy * im.getHeight())).create(); + for (int scale = 1; scale <= 4; ++scale) + { + NSAffineTransform* scaleTransform = [NSAffineTransform transform]; + [scaleTransform scaleBy: (float) scale]; + + if (CGImageRef rasterCGImage = [originalImage CGImageForProposedRect: nil + context: nil + hints: [NSDictionary dictionaryWithObjectsAndKeys: + NSImageHintCTM, scaleTransform, nil]]) + { + NSBitmapImageRep* imageRep = [[NSBitmapImageRep alloc] initWithCGImage: rasterCGImage]; + [imageRep setSize: originalSize]; + + [resultImage addRepresentation: imageRep]; + [imageRep release]; + } + else + { + return nil; + } + } + + NSDictionary* info = [NSDictionary dictionaryWithContentsOfFile: juceStringToNS (cursorPath + "/info.plist")]; + + const float hotspotX = (float) [[info valueForKey: nsStringLiteral ("hotx")] doubleValue]; + const float hotspotY = (float) [[info valueForKey: nsStringLiteral ("hoty")] doubleValue]; + + return fromNSImage (resultImage, NSMakePoint (hotspotX, hotspotY)); } - - return nullptr; } } void* CustomMouseCursorInfo::create() const { - NSImage* im = MouseCursorHelpers::createNSImage (image); - NSCursor* c = [[NSCursor alloc] initWithImage: im - hotSpot: NSMakePoint (hotspot.x, hotspot.y)]; - [im release]; - return c; + return MouseCursorHelpers::fromNSImage (MouseCursorHelpers::createNSImage (image), + NSMakePoint (hotspot.x, hotspot.y)); } void* MouseCursor::createStandardMouseCursor (MouseCursor::StandardCursorType type) @@ -102,9 +130,10 @@ void* MouseCursor::createStandardMouseCursor (MouseCursor::StandardCursorType ty case CopyingCursor: { #if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_6 - if (void* m = MouseCursorHelpers::fromWebKitFile ("copyCursor.png", 0, 0)) + if (void* m = MouseCursorHelpers::fromHIServices ("copy")) return m; #endif + c = [NSCursor dragCopyCursor]; // added in 10.6 break; } @@ -112,10 +141,14 @@ void* MouseCursor::createStandardMouseCursor (MouseCursor::StandardCursorType ty case UpDownResizeCursor: case TopEdgeResizeCursor: case BottomEdgeResizeCursor: - return MouseCursorHelpers::fromWebKitFile ("northSouthResizeCursor.png", 0.5f, 0.5f); + if (void* m = MouseCursorHelpers::fromHIServices ("resizenorthsouth")) + return m; + + c = [NSCursor resizeUpDownCursor]; + break; case LeftRightResizeCursor: - if (void* m = MouseCursorHelpers::fromWebKitFile ("eastWestResizeCursor.png", 0.5f, 0.5f)) + if (void* m = MouseCursorHelpers::fromHIServices ("resizeeastwest")) return m; c = [NSCursor resizeLeftRightCursor]; @@ -123,14 +156,14 @@ void* MouseCursor::createStandardMouseCursor (MouseCursor::StandardCursorType ty case TopLeftCornerResizeCursor: case BottomRightCornerResizeCursor: - return MouseCursorHelpers::fromWebKitFile ("northWestSouthEastResizeCursor.png", 0.5f, 0.5f); + return MouseCursorHelpers::fromHIServices ("resizenorthwestsoutheast"); case TopRightCornerResizeCursor: case BottomLeftCornerResizeCursor: - return MouseCursorHelpers::fromWebKitFile ("northEastSouthWestResizeCursor.png", 0.5f, 0.5f); + return MouseCursorHelpers::fromHIServices ("resizenortheastsouthwest"); case UpDownLeftRightResizeCursor: - return MouseCursorHelpers::fromWebKitFile ("moveCursor.png", 0.5f, 0.5f); + return MouseCursorHelpers::fromHIServices ("move"); default: jassertfalse; diff --git a/JuceLibraryCode/modules/juce_gui_basics/native/juce_mac_NSViewComponentPeer.mm b/JuceLibraryCode/modules/juce_gui_basics/native/juce_mac_NSViewComponentPeer.mm index f770119..d0fc1b4 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/native/juce_mac_NSViewComponentPeer.mm +++ b/JuceLibraryCode/modules/juce_gui_basics/native/juce_mac_NSViewComponentPeer.mm @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -295,14 +295,14 @@ public: return getBounds (! isSharedWindow); } - Point localToGlobal (Point relativePosition) override + Point localToGlobal (Point relativePosition) override { - return relativePosition + getBounds (true).getPosition(); + return relativePosition + getBounds (true).getPosition().toFloat(); } - Point globalToLocal (Point screenPosition) override + Point globalToLocal (Point screenPosition) override { - return screenPosition - getBounds (true).getPosition(); + return screenPosition - getBounds (true).getPosition().toFloat(); } void setAlpha (float newAlpha) override @@ -369,7 +369,7 @@ public: // (can't call the component's setBounds method because that'll reset our fullscreen flag) if (r != component.getBounds() && ! r.isEmpty()) - setBounds (r, shouldBeFullScreen); + setBounds (ScalingHelpers::scaledScreenPosToUnscaled (component, r), shouldBeFullScreen); } } } @@ -390,16 +390,37 @@ public: return ComponentPeer::isKioskMode(); } + static bool isWindowAtPoint (NSWindow* w, NSPoint screenPoint) + { + #if defined (MAC_OS_X_VERSION_10_6) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 + if ([NSWindow respondsToSelector: @selector (windowNumberAtPoint:belowWindowWithWindowNumber:)]) + return [NSWindow windowNumberAtPoint: screenPoint belowWindowWithWindowNumber: 0] == [w windowNumber]; + #endif + + return true; + } + bool contains (Point localPos, bool trueIfInAChildWindow) const override { - NSRect frameRect = [view frame]; + NSRect viewFrame = [view frame]; - if (! (isPositiveAndBelow (localPos.getX(), (int) frameRect.size.width) - && isPositiveAndBelow (localPos.getY(), (int) frameRect.size.height))) + if (! (isPositiveAndBelow (localPos.getX(), (int) viewFrame.size.width) + && isPositiveAndBelow (localPos.getY(), (int) viewFrame.size.height))) return false; - NSView* v = [view hitTest: NSMakePoint (frameRect.origin.x + localPos.getX(), - frameRect.origin.y + frameRect.size.height - localPos.getY())]; + if (NSWindow* const viewWindow = [view window]) + { + const NSRect windowFrame = [viewWindow frame]; + const NSPoint windowPoint = [view convertPoint: NSMakePoint (localPos.x, viewFrame.size.height - localPos.y) toView: nil]; + const NSPoint screenPoint = NSMakePoint (windowFrame.origin.x + windowPoint.x, + windowFrame.origin.y + windowPoint.y); + + if (! isWindowAtPoint (viewWindow, screenPoint)) + return false; + } + + NSView* v = [view hitTest: NSMakePoint (viewFrame.origin.x + localPos.getX(), + viewFrame.origin.y + viewFrame.size.height - localPos.getY())]; return trueIfInAChildWindow ? (v != nil) : (v == view); @@ -476,10 +497,7 @@ public: void toBehind (ComponentPeer* other) override { - NSViewComponentPeer* const otherPeer = dynamic_cast (other); - jassert (otherPeer != nullptr); // wrong type of window? - - if (otherPeer != nullptr) + if (NSViewComponentPeer* const otherPeer = dynamic_cast (other)) { if (isSharedWindow) { @@ -493,6 +511,10 @@ public: relativeTo: [otherPeer->window windowNumber]]; } } + else + { + jassertfalse; // wrong type of window? + } } void setIcon (const Image&) override @@ -553,19 +575,19 @@ public: { currentModifiers = currentModifiers.withoutMouseButtons(); - #if defined (MAC_OS_X_VERSION_10_6) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 - if ([NSWindow respondsToSelector: @selector (windowNumberAtPoint:belowWindowWithWindowNumber:)] - && [NSWindow windowNumberAtPoint: [[ev window] convertBaseToScreen: [ev locationInWindow]] - belowWindowWithWindowNumber: 0] != [window windowNumber]) - { - // moved into another window which overlaps this one, so trigger an exit - handleMouseEvent (0, Point (-1, -1), currentModifiers, getMouseTime (ev)); - } - else + NSPoint windowPos = [ev locationInWindow]; + + #if defined (MAC_OS_X_VERSION_10_7) && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_7 + NSPoint screenPos = [[ev window] convertRectToScreen: NSMakeRect (windowPos.x, windowPos.y, 1.0f, 1.0f)].origin; + #else + NSPoint screenPos = [[ev window] convertBaseToScreen: windowPos]; #endif - { + + if (isWindowAtPoint ([ev window], screenPos)) sendMouseEvent (ev); - } + else + // moved into another window which overlaps this one, so trigger an exit + handleMouseEvent (0, Point (-1.0f, -1.0f), currentModifiers, getMouseTime (ev)); showArrowCursorIfNeeded(); } @@ -599,6 +621,7 @@ public: wheel.deltaY = 0; wheel.isReversed = false; wheel.isSmooth = false; + wheel.isInertial = false; #if ! JUCE_PPC @try @@ -607,6 +630,8 @@ public: if ([ev respondsToSelector: @selector (isDirectionInvertedFromDevice)]) wheel.isReversed = [ev isDirectionInvertedFromDevice]; + wheel.isInertial = ([ev momentumPhase] != NSEventPhaseNone); + if ([ev respondsToSelector: @selector (hasPreciseScrollingDeltas)]) { if ([ev hasPreciseScrollingDeltas]) @@ -621,8 +646,8 @@ public: #endif if ([ev respondsToSelector: @selector (deviceDeltaX)]) { - wheel.deltaX = checkDeviceDeltaReturnValue ((float) objc_msgSend_fpret (ev, @selector (deviceDeltaX))); - wheel.deltaY = checkDeviceDeltaReturnValue ((float) objc_msgSend_fpret (ev, @selector (deviceDeltaY))); + wheel.deltaX = checkDeviceDeltaReturnValue ((float) getMsgSendFPRetFn() (ev, @selector (deviceDeltaX))); + wheel.deltaY = checkDeviceDeltaReturnValue ((float) getMsgSendFPRetFn() (ev, @selector (deviceDeltaY))); } } @catch (...) @@ -644,7 +669,7 @@ public: #if defined (MAC_OS_X_VERSION_10_6) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 const float invScale = 1.0f - (float) [ev magnification]; - if (invScale != 0.0f) + if (invScale > 0.0f) handleMagnifyGesture (0, getMousePos (ev, view), getMouseTime (ev), 1.0f / invScale); #endif (void) ev; @@ -857,6 +882,13 @@ public: return (getStyleFlags() & juce::ComponentPeer::windowIgnoresKeyPresses) == 0; } + bool canBecomeMainWindow() + { + Component* owner = &juce::ComponentPeer::getComponent(); + + return dynamic_cast (owner) != nullptr; + } + void becomeKeyWindow() { handleBroughtToFront(); @@ -936,7 +968,7 @@ public: MouseInputSource mouse = desktop.getMainMouseSource(); if (mouse.getComponentUnderMouse() == nullptr - && desktop.findComponentAt (mouse.getScreenPosition()) == nullptr) + && desktop.findComponentAt (mouse.getScreenPosition().roundToInt()) == nullptr) { [[NSCursor arrowCursor] set]; } @@ -1010,10 +1042,10 @@ public: + (int64) ([e timestamp] * 1000.0); } - static Point getMousePos (NSEvent* e, NSView* view) + static Point getMousePos (NSEvent* e, NSView* view) { NSPoint p = [view convertPoint: [e locationInWindow] fromView: nil]; - return Point ((int) p.x, (int) ([view frame].size.height - p.y)); + return Point ((float) p.x, (float) ([view frame].size.height - p.y)); } static int getModifierForButtonNumber (const NSInteger num) @@ -1136,7 +1168,9 @@ public: bool isFocused() const override { - return this == currentlyFocusedPeer; + return (isSharedWindow || ! JUCEApplication::isStandaloneApp()) + ? this == currentlyFocusedPeer + : [window isKeyWindow]; } void grabFocus() override @@ -1220,6 +1254,8 @@ private: const Rectangle clipBounds (clipW, clipH); const CGFloat viewH = [view frame].size.height; + clip.ensureStorageAllocated ((int) numRects); + for (int i = 0; i < numRects; ++i) clip.addWithoutMerging (clipBounds.getIntersection (Rectangle (roundToInt (rects[i].origin.x) + offset.x, roundToInt (viewH - (rects[i].origin.y + rects[i].size.height)) + offset.y, @@ -1466,7 +1502,7 @@ private: if ((! owner->textWasInserted) && (owner == nullptr || ! owner->redirectKeyDown (ev))) { objc_super s = { self, [NSView class] }; - objc_msgSendSuper (&s, @selector (keyDown:), ev); + getMsgSendSuperFn() (&s, @selector (keyDown:), ev); } } } @@ -1478,7 +1514,7 @@ private: if (owner == nullptr || ! owner->redirectKeyUp (ev)) { objc_super s = { self, [NSView class] }; - objc_msgSendSuper (&s, @selector (keyUp:), ev); + getMsgSendSuperFn() (&s, @selector (keyUp:), ev); } } @@ -1619,7 +1655,7 @@ private: return true; objc_super s = { self, [NSView class] }; - return objc_msgSendSuper (&s, @selector (performKeyEquivalent:), ev) != nil; + return getMsgSendSuperFn() (&s, @selector (performKeyEquivalent:), ev) != nil; } #endif @@ -1686,21 +1722,23 @@ private: }; //============================================================================== -struct JuceNSWindowClass : public ObjCClass +struct JuceNSWindowClass : public ObjCClass { - JuceNSWindowClass() : ObjCClass ("JUCEWindow_") + JuceNSWindowClass() : ObjCClass ("JUCEWindow_") { addIvar ("owner"); - addMethod (@selector (canBecomeKeyWindow), canBecomeKeyWindow, "c@:"); - addMethod (@selector (becomeKeyWindow), becomeKeyWindow, "v@:"); - addMethod (@selector (windowShouldClose:), windowShouldClose, "c@:@"); - addMethod (@selector (constrainFrameRect:toScreen:), constrainFrameRect, @encode (NSRect), "@:", @encode (NSRect), "@"); - addMethod (@selector (windowWillResize:toSize:), windowWillResize, @encode (NSSize), "@:@", @encode (NSSize)); - addMethod (@selector (zoom:), zoom, "v@:@"); - addMethod (@selector (windowWillMove:), windowWillMove, "v@:@"); + addMethod (@selector (canBecomeKeyWindow), canBecomeKeyWindow, "c@:"); + addMethod (@selector (canBecomeMainWindow), canBecomeMainWindow, "c@:"); + addMethod (@selector (becomeKeyWindow), becomeKeyWindow, "v@:"); + addMethod (@selector (windowShouldClose:), windowShouldClose, "c@:@"); + addMethod (@selector (constrainFrameRect:toScreen:), constrainFrameRect, @encode (NSRect), "@:", @encode (NSRect), "@"); + addMethod (@selector (windowWillResize:toSize:), windowWillResize, @encode (NSSize), "@:@", @encode (NSSize)); + addMethod (@selector (windowDidExitFullScreen:), windowDidExitFullScreen, "v@:@"); + addMethod (@selector (zoom:), zoom, "v@:@"); + addMethod (@selector (windowWillMove:), windowWillMove, "v@:@"); addMethod (@selector (windowWillStartLiveResize:), windowWillStartLiveResize, "v@:@"); - addMethod (@selector (windowDidEndLiveResize:), windowDidEndLiveResize, "v@:@"); + addMethod (@selector (windowDidEndLiveResize:), windowDidEndLiveResize, "v@:@"); #if defined (MAC_OS_X_VERSION_10_6) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 addProtocol (@protocol (NSWindowDelegate)); @@ -1725,9 +1763,18 @@ private: && ! owner->sendModalInputAttemptIfBlocked(); } + static BOOL canBecomeMainWindow (id self, SEL) + { + NSViewComponentPeer* const owner = getOwner (self); + + return owner != nullptr + && owner->canBecomeMainWindow() + && ! owner->sendModalInputAttemptIfBlocked(); + } + static void becomeKeyWindow (id self, SEL) { - //sendSuperclassMessage (self, @selector (becomeKeyWindow)); + sendSuperclassMessage (self, @selector (becomeKeyWindow)); if (NSViewComponentPeer* const owner = getOwner (self)) owner->becomeKeyWindow(); @@ -1766,13 +1813,20 @@ private: return frameRect.size; } + static void windowDidExitFullScreen (id, SEL, NSNotification*) + { + #if defined (MAC_OS_X_VERSION_10_6) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 + [NSApp setPresentationOptions: NSApplicationPresentationDefault]; + #endif + } + static void zoom (id self, SEL, id sender) { if (NSViewComponentPeer* const owner = getOwner (self)) { owner->isZooming = true; objc_super s = { self, [NSWindow class] }; - objc_msgSendSuper (&s, @selector (zoom:), sender); + getMsgSendSuperFn() (&s, @selector (zoom:), sender); owner->isZooming = false; owner->redirectMovedOrResized(); @@ -1864,7 +1918,7 @@ bool MouseInputSource::SourceList::addSource() } //============================================================================== -void Desktop::setKioskComponent (Component* kioskComp, bool enableOrDisable, bool allowMenusAndBars) +void Desktop::setKioskComponent (Component* kioskComp, bool shouldBeEnabled, bool allowMenusAndBars) { #if defined (MAC_OS_X_VERSION_10_6) && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_6 @@ -1875,13 +1929,15 @@ void Desktop::setKioskComponent (Component* kioskComp, bool enableOrDisable, boo if (peer->hasNativeTitleBar() && [peer->window respondsToSelector: @selector (toggleFullScreen:)]) { - [peer->window performSelector: @selector (toggleFullScreen:) - withObject: [NSNumber numberWithBool: (BOOL) enableOrDisable]]; + if (shouldBeEnabled && ! allowMenusAndBars) + [NSApp setPresentationOptions: NSApplicationPresentationHideDock | NSApplicationPresentationHideMenuBar]; + + [peer->window performSelector: @selector (toggleFullScreen:) withObject: nil]; } else #endif { - if (enableOrDisable) + if (shouldBeEnabled) { if (peer->hasNativeTitleBar()) [peer->window setStyleMask: NSBorderlessWindowMask]; @@ -1903,9 +1959,7 @@ void Desktop::setKioskComponent (Component* kioskComp, bool enableOrDisable, boo } } #elif JUCE_SUPPORT_CARBON - (void) kioskComp; (void) enableOrDisable; (void) allowMenusAndBars; - - if (enableOrDisable) + if (shouldBeEnabled) { SetSystemUIMode (kUIModeAllSuppressed, allowMenusAndBars ? kUIOptionAutoShowMenuBar : 0); kioskComp->setBounds (Desktop::getInstance().getDisplays().getMainDisplay().totalArea); @@ -1915,7 +1969,7 @@ void Desktop::setKioskComponent (Component* kioskComp, bool enableOrDisable, boo SetSystemUIMode (kUIModeNormal, 0); } #else - (void) kioskComp; (void) enableOrDisable; (void) allowMenusAndBars; + (void) kioskComp; (void) shouldBeEnabled; (void) allowMenusAndBars; // If you're targeting OSes earlier than 10.6 and want to use this feature, // you'll need to enable JUCE_SUPPORT_CARBON. diff --git a/JuceLibraryCode/modules/juce_gui_basics/native/juce_mac_Windowing.mm b/JuceLibraryCode/modules/juce_gui_basics/native/juce_mac_Windowing.mm index 7744d03..103f4b1 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/native/juce_mac_Windowing.mm +++ b/JuceLibraryCode/modules/juce_gui_basics/native/juce_mac_Windowing.mm @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -45,9 +45,9 @@ public: { switch (getRawResult()) { - case NSAlertDefaultReturn: return 1; - case NSAlertOtherReturn: return 2; - default: return 0; + case NSAlertFirstButtonReturn: return 1; + case NSAlertThirdButtonReturn: return 2; + default: return 0; } } @@ -82,25 +82,26 @@ private: delete this; } - static NSString* translateIfNotNull (const char* s) - { - return s != nullptr ? juceStringToNS (TRANS (s)) : nil; - } - NSInteger getRawResult() const { - NSString* msg = juceStringToNS (message); - NSString* ttl = juceStringToNS (title); - NSString* b1 = translateIfNotNull (button1); - NSString* b2 = translateIfNotNull (button2); - NSString* b3 = translateIfNotNull (button3); + NSAlert* alert = [[[NSAlert alloc] init] autorelease]; - switch (iconType) - { - case AlertWindow::InfoIcon: return NSRunInformationalAlertPanel (ttl, msg, b1, b2, b3); - case AlertWindow::WarningIcon: return NSRunCriticalAlertPanel (ttl, msg, b1, b2, b3); - default: return NSRunAlertPanel (ttl, msg, b1, b2, b3); - } + [alert setMessageText: juceStringToNS (title)]; + [alert setInformativeText: juceStringToNS (message)]; + + [alert setAlertStyle: iconType == AlertWindow::WarningIcon ? NSCriticalAlertStyle + : NSInformationalAlertStyle]; + addButton (alert, button1); + addButton (alert, button2); + addButton (alert, button3); + + return [alert runModal]; + } + + static void addButton (NSAlert* alert, const char* button) + { + if (button != nullptr) + [alert addButtonWithTitle: juceStringToNS (TRANS (button))]; } }; @@ -164,37 +165,29 @@ bool DragAndDropContainer::performExternalDragDropOfFiles (const StringArray& fi JUCE_AUTORELEASEPOOL { - NSView* view = (NSView*) sourceComp->getWindowHandle(); + if (NSView* view = (NSView*) sourceComp->getWindowHandle()) + { + if (NSEvent* event = [[view window] currentEvent]) + { + NSPoint eventPos = [event locationInWindow]; + NSRect dragRect = [view convertRect: NSMakeRect (eventPos.x - 16.0f, eventPos.y - 16.0f, 32.0f, 32.0f) + fromView: nil]; - if (view == nil) - return false; + for (int i = 0; i < files.size(); ++i) + { + if (! [view dragFile: juceStringToNS (files[i]) + fromRect: dragRect + slideBack: YES + event: event]) + 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; + return false; } bool DragAndDropContainer::performExternalDragDropOfText (const String& /*text*/) @@ -209,16 +202,16 @@ bool Desktop::canUseSemiTransparentWindows() noexcept return true; } -Point MouseInputSource::getCurrentRawMousePosition() +Point MouseInputSource::getCurrentRawMousePosition() { JUCE_AUTORELEASEPOOL { const NSPoint p ([NSEvent mouseLocation]); - return Point (roundToInt (p.x), roundToInt (getMainScreenHeight() - p.y)); + return Point ((float) p.x, (float) (getMainScreenHeight() - p.y)); } } -void MouseInputSource::setRawMousePosition (Point newPosition) +void MouseInputSource::setRawMousePosition (Point newPosition) { // this rubbish needs to be done around the warp call, to avoid causing a // bizarre glitch.. @@ -340,13 +333,13 @@ public: const_cast (Desktop::getInstance().getDisplays()).refresh(); } - juce_DeclareSingleton_SingleThreaded_Minimal (DisplaySettingsChangeCallback); + juce_DeclareSingleton_SingleThreaded_Minimal (DisplaySettingsChangeCallback) private: JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (DisplaySettingsChangeCallback) }; -juce_ImplementSingleton_SingleThreaded (DisplaySettingsChangeCallback); +juce_ImplementSingleton_SingleThreaded (DisplaySettingsChangeCallback) static Rectangle convertDisplayRect (NSRect r, CGFloat mainScreenBottom) { @@ -354,6 +347,30 @@ static Rectangle convertDisplayRect (NSRect r, CGFloat mainScreenBottom) return convertToRectInt (r); } +static Desktop::Displays::Display getDisplayFromScreen (NSScreen* s, CGFloat& mainScreenBottom, const float masterScale) +{ + Desktop::Displays::Display d; + + d.isMain = (mainScreenBottom == 0); + + if (d.isMain) + mainScreenBottom = [s frame].size.height; + + d.userArea = convertDisplayRect ([s visibleFrame], mainScreenBottom) / masterScale; + d.totalArea = convertDisplayRect ([s frame], mainScreenBottom) / masterScale; + d.scale = masterScale; + + #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; + #endif + + NSSize dpi = [[[s deviceDescription] objectForKey: NSDeviceResolution] sizeValue]; + d.dpi = (dpi.width + dpi.height) / 2.0; + + return d; +} + void Desktop::Displays::findDisplays (const float masterScale) { JUCE_AUTORELEASEPOOL @@ -363,30 +380,7 @@ void Desktop::Displays::findDisplays (const float masterScale) CGFloat mainScreenBottom = 0; for (NSScreen* s in [NSScreen screens]) - { - Display d; - d.isMain = false; - - if (mainScreenBottom == 0) - { - mainScreenBottom = [s frame].size.height; - d.isMain = true; - } - - d.userArea = convertDisplayRect ([s visibleFrame], mainScreenBottom) / masterScale; - d.totalArea = convertDisplayRect ([s frame], mainScreenBottom) / masterScale; - d.scale = masterScale; - - #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; - #endif - - NSSize dpi = [[[s deviceDescription] objectForKey: NSDeviceResolution] sizeValue]; - d.dpi = (dpi.width + dpi.height) / 2.0; - - displays.add (d); - } + displays.add (getDisplayFromScreen (s, mainScreenBottom, masterScale)); } } diff --git a/JuceLibraryCode/modules/juce_gui_basics/native/juce_win32_DragAndDrop.cpp b/JuceLibraryCode/modules/juce_gui_basics/native/juce_win32_DragAndDrop.cpp index 51def83..253364e 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/native/juce_win32_DragAndDrop.cpp +++ b/JuceLibraryCode/modules/juce_gui_basics/native/juce_win32_DragAndDrop.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_gui_basics/native/juce_win32_FileChooser.cpp b/JuceLibraryCode/modules/juce_gui_basics/native/juce_win32_FileChooser.cpp index 2f7044a..0e5d3ab 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/native/juce_win32_FileChooser.cpp +++ b/JuceLibraryCode/modules/juce_gui_basics/native/juce_win32_FileChooser.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -225,6 +225,10 @@ void FileChooser::showPlatformDialog (Array& results, const String& title_ filter.copyToUTF16 (filters + (bytesWritten / sizeof (WCHAR)), ((filterSpaceNumChars - 1) * sizeof (WCHAR) - bytesWritten)); + for (int i = 0; i < filterSpaceNumChars; ++i) + if (filters[i] == '|') + filters[i] = 0; + OPENFILENAMEW of = { 0 }; String localPath (info.initialPath); diff --git a/JuceLibraryCode/modules/juce_gui_basics/native/juce_win32_Windowing.cpp b/JuceLibraryCode/modules/juce_gui_basics/native/juce_win32_Windowing.cpp index 94878cf..ce986a3 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/native/juce_win32_Windowing.cpp +++ b/JuceLibraryCode/modules/juce_gui_basics/native/juce_win32_Windowing.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -177,6 +177,7 @@ static void setWindowZOrder (HWND hwnd, HWND insertAfter) //============================================================================== static void setDPIAwareness() { + #if ! JUCE_DISABLE_WIN32_DPI_AWARENESS if (JUCEApplicationBase::isStandaloneApp()) { if (setProcessDPIAwareness == nullptr) @@ -203,6 +204,7 @@ static void setDPIAwareness() } } } + #endif } static double getGlobalDPI() @@ -704,8 +706,8 @@ public: r.top + windowBorder.getTop()); } - Point localToGlobal (Point relativePosition) override { return relativePosition + getScreenPosition(); } - Point globalToLocal (Point screenPosition) override { return screenPosition - getScreenPosition(); } + Point localToGlobal (Point relativePosition) override { return relativePosition + getScreenPosition().toFloat(); } + Point globalToLocal (Point screenPosition) override { return screenPosition - getScreenPosition().toFloat(); } void setAlpha (float newAlpha) override { @@ -763,7 +765,7 @@ public: ShowWindow (hwnd, SW_SHOWNORMAL); if (! boundsCopy.isEmpty()) - setBounds (boundsCopy, false); + setBounds (ScalingHelpers::scaledScreenPosToUnscaled (component, boundsCopy), false); } else { @@ -845,7 +847,7 @@ public: void toBehind (ComponentPeer* other) override { - if (HWNDComponentPeer* const otherPeer = dynamic_cast (other)) + if (HWNDComponentPeer* const otherPeer = dynamic_cast (other)) { setMinimised (false); @@ -960,7 +962,7 @@ public: static ModifierKeys modifiersAtLastCallback; //============================================================================== - class JuceDropTarget : public ComBaseClassHelper + class JuceDropTarget : public ComBaseClassHelper { public: JuceDropTarget (HWNDComponentPeer& p) : ownerInfo (new OwnerInfo (p)) {} @@ -993,7 +995,7 @@ public: if (ownerInfo == nullptr) return S_FALSE; - ownerInfo->dragInfo.position = ownerInfo->getMousePos (mousePos); + ownerInfo->dragInfo.position = ownerInfo->getMousePos (mousePos).roundToInt(); const bool wasWanted = ownerInfo->owner.handleDragMove (ownerInfo->dragInfo); *pdwEffect = wasWanted ? (DWORD) DROPEFFECT_COPY : (DWORD) DROPEFFECT_NONE; return S_OK; @@ -1004,7 +1006,7 @@ public: HRESULT hr = updateFileList (pDataObject); if (SUCCEEDED (hr)) { - ownerInfo->dragInfo.position = ownerInfo->getMousePos (mousePos); + ownerInfo->dragInfo.position = ownerInfo->getMousePos (mousePos).roundToInt(); const bool wasWanted = ownerInfo->owner.handleDragDrop (ownerInfo->dragInfo); *pdwEffect = wasWanted ? (DWORD) DROPEFFECT_COPY : (DWORD) DROPEFFECT_NONE; hr = S_OK; @@ -1018,9 +1020,10 @@ public: { OwnerInfo (HWNDComponentPeer& p) : owner (p) {} - Point getMousePos (const POINTL& mousePos) const + Point getMousePos (const POINTL& mousePos) const { - return owner.globalToLocal (Point (mousePos.x, mousePos.y)); + return owner.globalToLocal (Point (static_cast (mousePos.x), + static_cast (mousePos.y))); } template @@ -1098,13 +1101,13 @@ public: if (SUCCEEDED (fileData.error)) { - const LPDROPFILES dropFiles = static_cast (fileData.data); + const LPDROPFILES dropFiles = static_cast (fileData.data); const void* const names = addBytesToPointer (dropFiles, sizeof (DROPFILES)); if (dropFiles->fWide) - ownerInfo->parseFileList (static_cast (names), fileData.dataSize); + ownerInfo->parseFileList (static_cast (names), fileData.dataSize); else - ownerInfo->parseFileList (static_cast (names), fileData.dataSize); + ownerInfo->parseFileList (static_cast (names), fileData.dataSize); } else { @@ -1223,7 +1226,7 @@ private: LPCTSTR getWindowClassName() const noexcept { return (LPCTSTR) MAKELONG (atom, 0); } - juce_DeclareSingleton_SingleThreaded_Minimal (WindowClassHolder); + juce_DeclareSingleton_SingleThreaded_Minimal (WindowClassHolder) private: ATOM atom; @@ -1299,7 +1302,7 @@ private: //============================================================================== static void* createWindowCallback (void* userData) { - static_cast (userData)->createWindow(); + static_cast (userData)->createWindow(); return nullptr; } @@ -1527,10 +1530,14 @@ private: // if something in a paint handler calls, e.g. a message box, this can become reentrant and // corrupt the image it's using to paint into, so do a check here. static bool reentrant = false; - if (! (reentrant || dontRepaint)) + if (! reentrant) { const ScopedValueSetter setter (reentrant, true, false); - performPaint (dc, rgn, regionType, paintStruct); + + if (dontRepaint) + component.handleCommandMessage (0); // (this triggers a repaint in the openGL context) + else + performPaint (dc, rgn, regionType, paintStruct); } DeleteObject (rgn); @@ -1638,7 +1645,7 @@ private: handlePaint (*context); } - static_cast (offscreenImage.getPixelData()) + static_cast (offscreenImage.getPixelData()) ->blitToWindow (hwnd, dc, transparent, x, y, updateLayeredWindowAlpha); } @@ -1648,7 +1655,7 @@ private: } //============================================================================== - void doMouseEvent (Point position) + void doMouseEvent (Point position) { handleMouseEvent (0, position, currentModifiers, getMouseEventTime()); } @@ -1699,7 +1706,7 @@ private: return 1000 / 60; // Throttling the incoming mouse-events seems to still be needed in XP.. } - void doMouseMove (Point position) + void doMouseMove (Point position) { if (! isMouseOver) { @@ -1720,7 +1727,7 @@ private: } else if (! isDragging) { - if (! contains (position, false)) + if (! contains (position.roundToInt(), false)) return; } @@ -1735,20 +1742,23 @@ private: } } - void doMouseDown (Point position, const WPARAM wParam) + void doMouseDown (Point position, const WPARAM wParam) { if (GetCapture() != hwnd) SetCapture (hwnd); doMouseMove (position); - updateModifiersFromWParam (wParam); - isDragging = true; + if (isValidPeer (this)) + { + updateModifiersFromWParam (wParam); + isDragging = true; - doMouseEvent (position); + doMouseEvent (position); + } } - void doMouseUp (Point position, const WPARAM wParam) + void doMouseUp (Point position, const WPARAM wParam) { updateModifiersFromWParam (wParam); const bool wasDragging = isDragging; @@ -1784,9 +1794,9 @@ private: doMouseEvent (getCurrentMousePos()); } - ComponentPeer* findPeerUnderMouse (Point& localPos) + ComponentPeer* findPeerUnderMouse (Point& localPos) { - const Point globalPos (getCurrentMousePosGlobal()); + const Point globalPos (getCurrentMousePosGlobal().roundToInt()); // Because Windows stupidly sends all wheel events to the window with the keyboard // focus, we have to redirect them here according to the mouse pos.. @@ -1796,7 +1806,7 @@ private: if (peer == nullptr) peer = this; - localPos = peer->globalToLocal (globalPos); + localPos = peer->globalToLocal (globalPos.toFloat()); return peer; } @@ -1810,8 +1820,9 @@ private: wheel.deltaY = isVertical ? amount / 256.0f : 0.0f; wheel.isReversed = false; wheel.isSmooth = false; + wheel.isInertial = false; - Point localPos; + Point localPos; if (ComponentPeer* const peer = findPeerUnderMouse (localPos)) peer->handleMouseWheel (0, localPos, getMouseEventTime(), wheel); } @@ -1825,7 +1836,7 @@ private: if (getGestureInfo != nullptr && getGestureInfo ((HGESTUREINFO) lParam, &gi)) { updateKeyModifiers(); - Point localPos; + Point localPos; if (ComponentPeer* const peer = findPeerUnderMouse (localPos)) { @@ -1883,8 +1894,8 @@ private: bool isCancel = false; const int touchIndex = currentTouches.getIndexOfTouch (touch.dwID); const int64 time = getMouseEventTime(); - const Point pos (globalToLocal (Point ((int) TOUCH_COORD_TO_PIXEL (touch.x), - (int) TOUCH_COORD_TO_PIXEL (touch.y)))); + const Point pos (globalToLocal (Point (static_cast (TOUCH_COORD_TO_PIXEL (touch.x)), + static_cast (TOUCH_COORD_TO_PIXEL (touch.y))))); ModifierKeys modsToSend (currentModifiers); if (isDown) @@ -1895,7 +1906,7 @@ private: if (! isPrimary) { // this forces a mouse-enter/up event, in case for some reason we didn't get a mouse-up before. - handleMouseEvent (touchIndex, pos, modsToSend.withoutMouseButtons(), time); + handleMouseEvent (touchIndex, pos.toFloat(), modsToSend.withoutMouseButtons(), time); if (! isValidPeer (this)) // (in case this component was deleted by the event) return false; } @@ -1921,14 +1932,14 @@ private: if (! isPrimary) { - handleMouseEvent (touchIndex, pos, modsToSend, time); + handleMouseEvent (touchIndex, pos.toFloat(), modsToSend, time); if (! isValidPeer (this)) // (in case this component was deleted by the event) return false; } if ((isUp || isCancel) && ! isPrimary) { - handleMouseEvent (touchIndex, Point (-10, -10), currentModifiers, time); + handleMouseEvent (touchIndex, Point (-10.0f, -10.0f), currentModifiers, time); if (! isValidPeer (this)) return false; } @@ -2208,6 +2219,22 @@ private: return 0; } + bool handlePositionChanged() + { + const Point pos (getCurrentMousePos()); + + if (contains (pos.roundToInt(), false)) + { + doMouseEvent (pos); + + if (! isValidPeer (this)) + return true; + } + + handleMovedOrResized(); + return ! dontRepaint; // to allow non-accelerated openGL windows to draw themselves correctly.. + } + void handleAppActivation (const WPARAM wParam) { modifiersAtLastCallback = -1; @@ -2218,7 +2245,7 @@ private: component.repaint(); handleMovedOrResized(); - if (! ComponentPeer::isValidPeer (this)) + if (! isValidPeer (this)) return; } @@ -2240,6 +2267,24 @@ private: } } + void handlePowerBroadcast (WPARAM wParam) + { + if (JUCEApplicationBase* const app = JUCEApplicationBase::getInstance()) + { + switch (wParam) + { + case PBT_APMSUSPEND: app->suspended(); break; + + case PBT_APMQUERYSUSPENDFAILED: + case PBT_APMRESUMECRITICAL: + case PBT_APMRESUMESUSPEND: + case PBT_APMRESUMEAUTOMATIC: app->resumed(); break; + + default: break; + } + } + } + void handleLeftClickInNCArea (WPARAM wParam) { if (! sendInputAttemptWhenModalMessage()) @@ -2288,7 +2333,7 @@ private: { Desktop& desktop = Desktop::getInstance(); - const_cast (desktop.getDisplays()).refresh(); + const_cast (desktop.getDisplays()).refresh(); if (fullScreen && ! isMinimised()) { @@ -2326,17 +2371,18 @@ private: return MessageManager::getInstance()->callFunctionOnMessageThread (callback, userData); } - static Point getPointFromLParam (LPARAM lParam) noexcept + static Point getPointFromLParam (LPARAM lParam) noexcept { - return Point (GET_X_LPARAM (lParam), GET_Y_LPARAM (lParam)); + return Point (static_cast (GET_X_LPARAM (lParam)), + static_cast (GET_Y_LPARAM (lParam))); } - static Point getCurrentMousePosGlobal() noexcept + static Point getCurrentMousePosGlobal() noexcept { return getPointFromLParam (GetMessagePos()); } - Point getCurrentMousePos() noexcept + Point getCurrentMousePos() noexcept { return globalToLocal (getCurrentMousePosGlobal()); } @@ -2416,18 +2462,10 @@ private: case WM_WINDOWPOSCHANGING: return handlePositionChanging (*(WINDOWPOS*) lParam); case WM_WINDOWPOSCHANGED: - { - const Point pos (getCurrentMousePos()); - if (contains (pos, false)) - doMouseEvent (pos); - } + if (handlePositionChanged()) + return 0; - handleMovedOrResized(); - - if (dontRepaint) - break; // needed for non-accelerated openGL windows to draw themselves correctly.. - - return 0; + break; //============================================================================== case WM_KEYDOWN: @@ -2536,6 +2574,10 @@ private: } return TRUE; + case WM_POWERBROADCAST: + handlePowerBroadcast (wParam); + break; + case WM_SYNCPAINT: return 0; @@ -2865,7 +2907,7 @@ private: void moveCandidateWindowToLeftAlignWithSelection (HIMC hImc, ComponentPeer& peer, TextInputTarget* target) const { - if (Component* const targetComp = dynamic_cast (target)) + if (Component* const targetComp = dynamic_cast (target)) { const Rectangle area (peer.getComponent().getLocalArea (targetComp, target->getCaretRectangle())); @@ -2886,22 +2928,19 @@ private: ModifierKeys HWNDComponentPeer::currentModifiers; ModifierKeys HWNDComponentPeer::modifiersAtLastCallback; -ComponentPeer* Component::createNewPeer (int styleFlags, void* nativeWindowToAttachTo) +ComponentPeer* Component::createNewPeer (int styleFlags, void* parentHWND) { - return new HWNDComponentPeer (*this, styleFlags, - (HWND) nativeWindowToAttachTo, false); + return new HWNDComponentPeer (*this, styleFlags, (HWND) parentHWND, false); } -ComponentPeer* createNonRepaintingEmbeddedWindowsPeer (Component* component, void* parent) +ComponentPeer* createNonRepaintingEmbeddedWindowsPeer (Component& component, void* parentHWND) { - jassert (component != nullptr); - - return new HWNDComponentPeer (*component, ComponentPeer::windowIgnoresMouseClicks, - (HWND) parent, true); + return new HWNDComponentPeer (component, ComponentPeer::windowIgnoresMouseClicks, + (HWND) parentHWND, true); } -juce_ImplementSingleton_SingleThreaded (HWNDComponentPeer::WindowClassHolder); +juce_ImplementSingleton_SingleThreaded (HWNDComponentPeer::WindowClassHolder) //============================================================================== @@ -2930,24 +2969,27 @@ bool KeyPress::isKeyCurrentlyDown (const int keyCode) { SHORT k = (SHORT) keyCode; - if ((keyCode & extendedKeyModifier) == 0 - && (k >= (SHORT) 'a' && k <= (SHORT) 'z')) - k += (SHORT) 'A' - (SHORT) 'a'; + if ((keyCode & extendedKeyModifier) == 0) + { + if (k >= (SHORT) 'a' && k <= (SHORT) 'z') + k += (SHORT) 'A' - (SHORT) 'a'; - const SHORT translatedValues[] = { (SHORT) ',', VK_OEM_COMMA, - (SHORT) '+', VK_OEM_PLUS, - (SHORT) '-', VK_OEM_MINUS, - (SHORT) '.', VK_OEM_PERIOD, - (SHORT) ';', VK_OEM_1, - (SHORT) ':', VK_OEM_1, - (SHORT) '/', VK_OEM_2, - (SHORT) '?', VK_OEM_2, - (SHORT) '[', VK_OEM_4, - (SHORT) ']', VK_OEM_6 }; + // Only translate if extendedKeyModifier flag is not set + const SHORT translatedValues[] = { (SHORT) ',', VK_OEM_COMMA, + (SHORT) '+', VK_OEM_PLUS, + (SHORT) '-', VK_OEM_MINUS, + (SHORT) '.', VK_OEM_PERIOD, + (SHORT) ';', VK_OEM_1, + (SHORT) ':', VK_OEM_1, + (SHORT) '/', VK_OEM_2, + (SHORT) '?', VK_OEM_2, + (SHORT) '[', VK_OEM_4, + (SHORT) ']', VK_OEM_6 }; - for (int i = 0; i < numElementsInArray (translatedValues); i += 2) - if (k == translatedValues [i]) - k = translatedValues [i + 1]; + for (int i = 0; i < numElementsInArray (translatedValues); i += 2) + if (k == translatedValues [i]) + k = translatedValues [i + 1]; + } return HWNDComponentPeer::isKeyDown (k); } @@ -2970,7 +3012,7 @@ bool JUCE_CALLTYPE Process::isForegroundProcess() fg = GetAncestor (fg, GA_ROOT); for (int i = ComponentPeer::getNumPeers(); --i >= 0;) - if (HWNDComponentPeer* const wp = dynamic_cast (ComponentPeer::getPeer (i))) + if (HWNDComponentPeer* const wp = dynamic_cast (ComponentPeer::getPeer (i))) if (wp->isInside (fg)) return true; @@ -2996,7 +3038,7 @@ static BOOL CALLBACK enumAlwaysOnTopWindows (HWND hwnd, LPARAM lParam) if (GetWindowInfo (hwnd, &info) && (info.dwExStyle & WS_EX_TOPMOST) != 0) { - *reinterpret_cast (lParam) = true; + *reinterpret_cast (lParam) = true; return FALSE; } } @@ -3131,16 +3173,17 @@ bool MouseInputSource::SourceList::addSource() return false; } -Point MouseInputSource::getCurrentRawMousePosition() +Point MouseInputSource::getCurrentRawMousePosition() { POINT mousePos; GetCursorPos (&mousePos); - return Point (mousePos.x, mousePos.y); + return Point ((float) mousePos.x, (float) mousePos.y); } -void MouseInputSource::setRawMousePosition (Point newPosition) +void MouseInputSource::setRawMousePosition (Point newPosition) { - SetCursorPos (newPosition.x, newPosition.y); + SetCursorPos (roundToInt (newPosition.x), + roundToInt (newPosition.y)); } //============================================================================== @@ -3200,7 +3243,7 @@ void SystemClipboard::copyTextToClipboard (const String& text) { if (HGLOBAL bufH = GlobalAlloc (GMEM_MOVEABLE | GMEM_DDESHARE | GMEM_ZEROINIT, bytesNeeded + sizeof (WCHAR))) { - if (WCHAR* const data = static_cast (GlobalLock (bufH))) + if (WCHAR* const data = static_cast (GlobalLock (bufH))) { text.copyToUTF16 (data, bytesNeeded); GlobalUnlock (bufH); @@ -3390,7 +3433,6 @@ void* MouseCursor::createStandardMouseCursor (const MouseCursor::StandardCursorT case IBeamCursor: cursorName = IDC_IBEAM; break; case PointingHandCursor: cursorName = MAKEINTRESOURCE(32649); break; case CrosshairCursor: cursorName = IDC_CROSS; break; - case CopyingCursor: break; // can't seem to find one of these in the system list.. case LeftRightResizeCursor: case LeftEdgeResizeCursor: @@ -3425,6 +3467,24 @@ void* MouseCursor::createStandardMouseCursor (const MouseCursor::StandardCursorT return dragHandCursor; } + case CopyingCursor: + { + static void* copyCursor = nullptr; + + if (copyCursor == nullptr) + { + static unsigned char copyCursorData[] = { 71,73,70,56,57,97,21,0,21,0,145,0,0,0,0,0,255,255,255,0, + 128,128,255,255,255,33,249,4,1,0,0,3,0,44,0,0,0,0,21,0, 21,0,0,2,72,4,134,169,171,16,199,98,11,79,90,71,161,93,56,111, + 78,133,218,215,137,31,82,154,100,200,86,91,202,142,12,108,212,87,235,174, 15,54,214,126,237,226,37,96,59,141,16,37,18,201,142,157,230,204,51,112, + 252,114,147,74,83,5,50,68,147,208,217,16,71,149,252,124,5,0,59,0,0 }; + const int copyCursorSize = 119; + + copyCursor = CustomMouseCursorInfo (ImageFileFormat::loadFrom (copyCursorData, copyCursorSize), 1, 3).create(); + } + + return copyCursor; + } + default: jassertfalse; break; } diff --git a/JuceLibraryCode/modules/juce_gui_basics/positioning/juce_MarkerList.cpp b/JuceLibraryCode/modules/juce_gui_basics/positioning/juce_MarkerList.cpp index 751bcab..0e3495a 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/positioning/juce_MarkerList.cpp +++ b/JuceLibraryCode/modules/juce_gui_basics/positioning/juce_MarkerList.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_gui_basics/positioning/juce_MarkerList.h b/JuceLibraryCode/modules/juce_gui_basics/positioning/juce_MarkerList.h index 05131e4..a19a348 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/positioning/juce_MarkerList.h +++ b/JuceLibraryCode/modules/juce_gui_basics/positioning/juce_MarkerList.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_gui_basics/positioning/juce_RelativeCoordinate.cpp b/JuceLibraryCode/modules/juce_gui_basics/positioning/juce_RelativeCoordinate.cpp index 7482f57..c08f7dd 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/positioning/juce_RelativeCoordinate.cpp +++ b/JuceLibraryCode/modules/juce_gui_basics/positioning/juce_RelativeCoordinate.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_gui_basics/positioning/juce_RelativeCoordinate.h b/JuceLibraryCode/modules/juce_gui_basics/positioning/juce_RelativeCoordinate.h index c1f4eb4..91b901d 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/positioning/juce_RelativeCoordinate.h +++ b/JuceLibraryCode/modules/juce_gui_basics/positioning/juce_RelativeCoordinate.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -30,6 +30,41 @@ /** Expresses a coordinate as a dynamically evaluated expression. + When using relative coordinates to position components, the following symbols are available: + - "left", "right", "top", "bottom" refer to the position of those edges in this component, so + e.g. for a component whose width is always 100, you might set the right edge to the "left + 100". + - "[id].left", "[id].right", "[id].top", "[id].bottom", "[id].width", "[id].height", where [id] is + the identifier of one of this component's siblings. A component's identifier is set with + Component::setComponentID(). So for example if you want your component to always be 50 pixels to the + right of the one called "xyz", you could set your left edge to be "xyz.right + 50". + - Instead of an [id], you can use the name "parent" to refer to this component's parent. Like + any other component, these values are relative to their component's parent, so "parent.right" won't be + very useful for positioning a component because it refers to a position with the parent's parent.. but + "parent.width" can be used for setting positions relative to the parent's size. E.g. to make a 10x10 + component which remains 1 pixel away from its parent's bottom-right, you could use + "right - 10, bottom - 10, parent.width - 1, parent.height - 1". + - The name of one of the parent component's markers can also be used as a symbol. For markers to be + used, the parent component must implement its Component::getMarkers() method, and return at least one + valid MarkerList. So if you want your component's top edge to be 10 pixels below the + marker called "foobar", you'd set it to "foobar + 10". + + See the Expression class for details about the operators that are supported, but for example + if you wanted to make your component remains centred within its parent with a size of 100, 100, + you could express it as: + @code myComp.setBounds (RelativeBounds ("parent.width / 2 - 50, parent.height / 2 - 50, left + 100, top + 100")); + @endcode + ..or an alternative way to achieve the same thing: + @code myComp.setBounds (RelativeBounds ("right - 100, bottom - 100, parent.width / 2 + 50, parent.height / 2 + 50")); + @endcode + + Or if you wanted a 100x100 component whose top edge is lined up to a marker called "topMarker" and + which is positioned 50 pixels to the right of another component called "otherComp", you could write: + @code myComp.setBounds (RelativeBounds ("otherComp.right + 50, topMarker, left + 100, top + 100")); + @endcode + + Be careful not to make your coordinate expressions recursive, though, or exceptions and assertions will + be thrown! + @see RelativePoint, RelativeRectangle */ class JUCE_API RelativeCoordinate diff --git a/JuceLibraryCode/modules/juce_gui_basics/positioning/juce_RelativeCoordinatePositioner.cpp b/JuceLibraryCode/modules/juce_gui_basics/positioning/juce_RelativeCoordinatePositioner.cpp index 589eb26..fc6772b 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/positioning/juce_RelativeCoordinatePositioner.cpp +++ b/JuceLibraryCode/modules/juce_gui_basics/positioning/juce_RelativeCoordinatePositioner.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_gui_basics/positioning/juce_RelativeCoordinatePositioner.h b/JuceLibraryCode/modules/juce_gui_basics/positioning/juce_RelativeCoordinatePositioner.h index 35213e9..2febd31 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/positioning/juce_RelativeCoordinatePositioner.h +++ b/JuceLibraryCode/modules/juce_gui_basics/positioning/juce_RelativeCoordinatePositioner.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_gui_basics/positioning/juce_RelativeParallelogram.cpp b/JuceLibraryCode/modules/juce_gui_basics/positioning/juce_RelativeParallelogram.cpp index 77e3a75..330dd41 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/positioning/juce_RelativeParallelogram.cpp +++ b/JuceLibraryCode/modules/juce_gui_basics/positioning/juce_RelativeParallelogram.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_gui_basics/positioning/juce_RelativeParallelogram.h b/JuceLibraryCode/modules/juce_gui_basics/positioning/juce_RelativeParallelogram.h index ee426d2..cef4d47 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/positioning/juce_RelativeParallelogram.h +++ b/JuceLibraryCode/modules/juce_gui_basics/positioning/juce_RelativeParallelogram.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_gui_basics/positioning/juce_RelativePoint.cpp b/JuceLibraryCode/modules/juce_gui_basics/positioning/juce_RelativePoint.cpp index 307b2ec..c1c7cf2 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/positioning/juce_RelativePoint.cpp +++ b/JuceLibraryCode/modules/juce_gui_basics/positioning/juce_RelativePoint.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_gui_basics/positioning/juce_RelativePoint.h b/JuceLibraryCode/modules/juce_gui_basics/positioning/juce_RelativePoint.h index 43f7c44..c50ce2f 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/positioning/juce_RelativePoint.h +++ b/JuceLibraryCode/modules/juce_gui_basics/positioning/juce_RelativePoint.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_gui_basics/positioning/juce_RelativePointPath.cpp b/JuceLibraryCode/modules/juce_gui_basics/positioning/juce_RelativePointPath.cpp index 29f6816..14b1aa3 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/positioning/juce_RelativePointPath.cpp +++ b/JuceLibraryCode/modules/juce_gui_basics/positioning/juce_RelativePointPath.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_gui_basics/positioning/juce_RelativePointPath.h b/JuceLibraryCode/modules/juce_gui_basics/positioning/juce_RelativePointPath.h index d705b44..6de294d 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/positioning/juce_RelativePointPath.h +++ b/JuceLibraryCode/modules/juce_gui_basics/positioning/juce_RelativePointPath.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_gui_basics/positioning/juce_RelativeRectangle.cpp b/JuceLibraryCode/modules/juce_gui_basics/positioning/juce_RelativeRectangle.cpp index 27f3eb6..6f39912 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/positioning/juce_RelativeRectangle.cpp +++ b/JuceLibraryCode/modules/juce_gui_basics/positioning/juce_RelativeRectangle.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -192,7 +192,7 @@ public: { } - bool registerCoordinates() + bool registerCoordinates() override { bool ok = addCoordinate (rectangle.left); ok = addCoordinate (rectangle.right) && ok; @@ -206,9 +206,9 @@ public: return rectangle == other; } - void applyToComponentBounds() + void applyToComponentBounds() override { - for (int i = 4; --i >= 0;) + for (int i = 32; --i >= 0;) { ComponentScope scope (getComponent()); const Rectangle newBounds (rectangle.resolve (&scope).getSmallestIntegerContainer()); @@ -222,7 +222,7 @@ public: jassertfalse; // Seems to be a recursive reference! } - void applyNewBounds (const Rectangle& newBounds) + void applyNewBounds (const Rectangle& newBounds) override { if (newBounds != getComponent().getBounds()) { diff --git a/JuceLibraryCode/modules/juce_gui_basics/positioning/juce_RelativeRectangle.h b/JuceLibraryCode/modules/juce_gui_basics/positioning/juce_RelativeRectangle.h index b8afbe0..0e04e2c 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/positioning/juce_RelativeRectangle.h +++ b/JuceLibraryCode/modules/juce_gui_basics/positioning/juce_RelativeRectangle.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -28,7 +28,7 @@ //============================================================================== /** - An rectangle stored as a set of RelativeCoordinate values. + A rectangle stored as a set of RelativeCoordinate values. The rectangle's top, left, bottom and right edge positions are each stored as a RelativeCoordinate. @@ -81,8 +81,9 @@ public: bool isDynamic() const; /** Returns a string which represents this point. - This returns a comma-separated list of coordinates, in the order left, top, right, bottom. For details of - the string syntax used by the coordinates, see the RelativeCoordinate constructor notes. + This returns a comma-separated list of coordinates, in the order left, top, right, bottom. + If you're using this to position a Component, then see the notes for + Component::setBounds (const RelativeRectangle&) for details of the syntax used. The string that is returned can be passed to the RelativeRectangle constructor to recreate the rectangle. */ String toString() const; diff --git a/JuceLibraryCode/modules/juce_gui_basics/properties/juce_BooleanPropertyComponent.cpp b/JuceLibraryCode/modules/juce_gui_basics/properties/juce_BooleanPropertyComponent.cpp index 6f0d458..d5095bb 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/properties/juce_BooleanPropertyComponent.cpp +++ b/JuceLibraryCode/modules/juce_gui_basics/properties/juce_BooleanPropertyComponent.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -66,7 +66,7 @@ void BooleanPropertyComponent::paint (Graphics& g) { PropertyComponent::paint (g); - g.setColour (Colours::white); + g.setColour (findColour (backgroundColourId)); g.fillRect (button.getBounds()); g.setColour (findColour (ComboBox::outlineColourId)); diff --git a/JuceLibraryCode/modules/juce_gui_basics/properties/juce_BooleanPropertyComponent.h b/JuceLibraryCode/modules/juce_gui_basics/properties/juce_BooleanPropertyComponent.h index 958428f..08ad78c 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/properties/juce_BooleanPropertyComponent.h +++ b/JuceLibraryCode/modules/juce_gui_basics/properties/juce_BooleanPropertyComponent.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -56,6 +56,10 @@ protected: public: /** Creates a button component. + Note that if you call this constructor then you must use the Value to interact with the + button state, and you can't override the class with your own setState or getState methods. + If you want to use getState and setState, call the other constructor instead. + @param valueToControl a Value object that this property should refer to. @param propertyName the property name to be passed to the PropertyComponent @param buttonText the text shown in the ToggleButton component @@ -74,6 +78,20 @@ public: /** Must return the current value of the property. */ virtual bool getState() const; + //============================================================================== + /** A set of colour IDs to use to change the colour of various aspects of the component. + + These constants can be used either via the Component::setColour(), or LookAndFeel::setColour() + methods. + + @see Component::setColour, Component::findColour, LookAndFeel::setColour, LookAndFeel::findColour + */ + enum ColourIds + { + backgroundColourId = 0x100e801, /**< The colour to fill the background of the button area. */ + outlineColourId = 0x100e803, /**< The colour to use to draw an outline around the text area. */ + }; + //============================================================================== /** @internal */ void paint (Graphics&) override; diff --git a/JuceLibraryCode/modules/juce_gui_basics/properties/juce_ButtonPropertyComponent.cpp b/JuceLibraryCode/modules/juce_gui_basics/properties/juce_ButtonPropertyComponent.cpp index cf03191..c8e99d7 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/properties/juce_ButtonPropertyComponent.cpp +++ b/JuceLibraryCode/modules/juce_gui_basics/properties/juce_ButtonPropertyComponent.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_gui_basics/properties/juce_ButtonPropertyComponent.h b/JuceLibraryCode/modules/juce_gui_basics/properties/juce_ButtonPropertyComponent.h index 5f70def..e6b82f5 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/properties/juce_ButtonPropertyComponent.h +++ b/JuceLibraryCode/modules/juce_gui_basics/properties/juce_ButtonPropertyComponent.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_gui_basics/properties/juce_ChoicePropertyComponent.cpp b/JuceLibraryCode/modules/juce_gui_basics/properties/juce_ChoicePropertyComponent.cpp index 60b66d9..9145918 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/properties/juce_ChoicePropertyComponent.cpp +++ b/JuceLibraryCode/modules/juce_gui_basics/properties/juce_ChoicePropertyComponent.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_gui_basics/properties/juce_ChoicePropertyComponent.h b/JuceLibraryCode/modules/juce_gui_basics/properties/juce_ChoicePropertyComponent.h index 2956ae6..6f97d5b 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/properties/juce_ChoicePropertyComponent.h +++ b/JuceLibraryCode/modules/juce_gui_basics/properties/juce_ChoicePropertyComponent.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -50,15 +50,17 @@ class JUCE_API ChoicePropertyComponent : public PropertyComponent, { protected: /** Creates the component. - - Your subclass's constructor must add a list of options to the choices - member variable. + Your subclass's constructor must add a list of options to the choices member variable. */ ChoicePropertyComponent (const String& propertyName); public: /** Creates the component. + Note that if you call this constructor then you must use the Value to interact with the + index, and you can't override the class with your own setIndex or getIndex methods. + If you want to use those methods, call the other constructor instead. + @param valueToControl the value that the combo box will read and control @param propertyName the name of the property @param choices the list of possible values that the drop-down list will contain diff --git a/JuceLibraryCode/modules/juce_gui_basics/properties/juce_PropertyComponent.cpp b/JuceLibraryCode/modules/juce_gui_basics/properties/juce_PropertyComponent.cpp index 96fd868..aada118 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/properties/juce_PropertyComponent.cpp +++ b/JuceLibraryCode/modules/juce_gui_basics/properties/juce_PropertyComponent.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_gui_basics/properties/juce_PropertyComponent.h b/JuceLibraryCode/modules/juce_gui_basics/properties/juce_PropertyComponent.h index 2fd3d7a..8b1856b 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/properties/juce_PropertyComponent.h +++ b/JuceLibraryCode/modules/juce_gui_basics/properties/juce_PropertyComponent.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -108,8 +108,6 @@ public: These constants can be used either via the Component::setColour(), or LookAndFeel::setColour() methods. - To change the colours of the menu that pops up - @see Component::setColour, Component::findColour, LookAndFeel::setColour, LookAndFeel::findColour */ enum ColourIds diff --git a/JuceLibraryCode/modules/juce_gui_basics/properties/juce_PropertyPanel.cpp b/JuceLibraryCode/modules/juce_gui_basics/properties/juce_PropertyPanel.cpp index dc93d7c..99eccbd 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/properties/juce_PropertyPanel.cpp +++ b/JuceLibraryCode/modules/juce_gui_basics/properties/juce_PropertyPanel.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -22,15 +22,14 @@ ============================================================================== */ -class PropertyPanel::SectionComponent : public Component +struct PropertyPanel::SectionComponent : public Component { -public: SectionComponent (const String& sectionTitle, - const Array & newProperties, - const bool sectionIsOpen_) + const Array& newProperties, + const bool sectionIsOpen) : Component (sectionTitle), titleHeight (sectionTitle.isNotEmpty() ? 22 : 0), - sectionIsOpen (sectionIsOpen_) + isOpen (sectionIsOpen) { propertyComps.addArray (newProperties); @@ -49,7 +48,7 @@ public: void paint (Graphics& g) override { if (titleHeight > 0) - getLookAndFeel().drawPropertyPanelSectionHeader (g, getName(), isOpen(), getWidth(), titleHeight); + getLookAndFeel().drawPropertyPanelSectionHeader (g, getName(), isOpen, getWidth(), titleHeight); } void resized() override @@ -68,20 +67,18 @@ public: { int y = titleHeight; - if (isOpen()) - { + if (isOpen) for (int i = propertyComps.size(); --i >= 0;) y += propertyComps.getUnchecked(i)->getPreferredHeight(); - } return y; } void setOpen (const bool open) { - if (sectionIsOpen != open) + if (isOpen != open) { - sectionIsOpen = open; + isOpen = open; for (int i = propertyComps.size(); --i >= 0;) propertyComps.getUnchecked(i)->setVisible (open); @@ -91,11 +88,6 @@ public: } } - bool isOpen() const - { - return sectionIsOpen; - } - void refreshAll() const { for (int i = propertyComps.size(); --i >= 0;) @@ -105,32 +97,27 @@ public: void mouseUp (const MouseEvent& e) override { if (e.getMouseDownX() < titleHeight - && e.x < titleHeight - && e.y < titleHeight - && e.getNumberOfClicks() != 2) - { - setOpen (! isOpen()); - } + && e.x < titleHeight + && e.getNumberOfClicks() != 2) + mouseDoubleClick (e); } void mouseDoubleClick (const MouseEvent& e) override { if (e.y < titleHeight) - setOpen (! isOpen()); + setOpen (! isOpen); } -private: - OwnedArray propertyComps; - int titleHeight; - bool sectionIsOpen; + OwnedArray propertyComps; + const int titleHeight; + bool isOpen; JUCE_DECLARE_NON_COPYABLE (SectionComponent) }; //============================================================================== -class PropertyPanel::PropertyHolderComponent : public Component +struct PropertyPanel::PropertyHolderComponent : public Component { -public: PropertyHolderComponent() {} void paint (Graphics&) override {} @@ -157,21 +144,26 @@ public: sections.getUnchecked(i)->refreshAll(); } - void clear() + void insertSection (int indexToInsertAt, SectionComponent* newSection) { - sections.clear(); - } - - void addSection (SectionComponent* newSection) - { - sections.add (newSection); + sections.insert (indexToInsertAt, newSection); addAndMakeVisible (newSection, 0); } - int getNumSections() const noexcept { return sections.size(); } - SectionComponent* getSection (const int index) const { return sections [index]; } + SectionComponent* getSectionWithNonEmptyName (const int targetIndex) const noexcept + { + for (int index = 0, i = 0; i < sections.size(); ++i) + { + SectionComponent* const section = sections.getUnchecked (i); + + if (section->getName().isNotEmpty()) + if (index++ == targetIndex) + return section; + } + + return nullptr; + } -private: OwnedArray sections; JUCE_DECLARE_NON_COPYABLE (PropertyHolderComponent) @@ -226,14 +218,14 @@ void PropertyPanel::clear() { if (! isEmpty()) { - propertyHolderComponent->clear(); + propertyHolderComponent->sections.clear(); updatePropHolderLayout(); } } bool PropertyPanel::isEmpty() const { - return propertyHolderComponent->getNumSections() == 0; + return propertyHolderComponent->sections.size() == 0; } int PropertyPanel::getTotalContentHeight() const @@ -241,25 +233,26 @@ int PropertyPanel::getTotalContentHeight() const return propertyHolderComponent->getHeight(); } -void PropertyPanel::addProperties (const Array & newProperties) +void PropertyPanel::addProperties (const Array& newProperties) { if (isEmpty()) repaint(); - propertyHolderComponent->addSection (new SectionComponent (String::empty, newProperties, true)); + propertyHolderComponent->insertSection (-1, new SectionComponent (String::empty, newProperties, true)); updatePropHolderLayout(); } void PropertyPanel::addSection (const String& sectionTitle, - const Array & newProperties, - const bool shouldBeOpen) + const Array& newProperties, + const bool shouldBeOpen, + const int indexToInsertAt) { jassert (sectionTitle.isNotEmpty()); if (isEmpty()) repaint(); - propertyHolderComponent->addSection (new SectionComponent (sectionTitle, newProperties, shouldBeOpen)); + propertyHolderComponent->insertSection (indexToInsertAt, new SectionComponent (sectionTitle, newProperties, shouldBeOpen)); updatePropHolderLayout(); } @@ -286,9 +279,9 @@ StringArray PropertyPanel::getSectionNames() const { StringArray s; - for (int i = 0; i < propertyHolderComponent->getNumSections(); ++i) + for (int i = 0; i < propertyHolderComponent->sections.size(); ++i) { - SectionComponent* const section = propertyHolderComponent->getSection (i); + SectionComponent* const section = propertyHolderComponent->sections.getUnchecked(i); if (section->getName().isNotEmpty()) s.add (section->getName()); @@ -299,63 +292,30 @@ StringArray PropertyPanel::getSectionNames() const bool PropertyPanel::isSectionOpen (const int sectionIndex) const { - int index = 0; - - for (int i = 0; i < propertyHolderComponent->getNumSections(); ++i) - { - SectionComponent* const section = propertyHolderComponent->getSection (i); - - if (section->getName().isNotEmpty()) - { - if (index == sectionIndex) - return section->isOpen(); - - ++index; - } - } + if (SectionComponent* s = propertyHolderComponent->getSectionWithNonEmptyName (sectionIndex)) + return s->isOpen; return false; } void PropertyPanel::setSectionOpen (const int sectionIndex, const bool shouldBeOpen) { - int index = 0; - - for (int i = 0; i < propertyHolderComponent->getNumSections(); ++i) - { - SectionComponent* const section = propertyHolderComponent->getSection (i); - - if (section->getName().isNotEmpty()) - { - if (index == sectionIndex) - { - section->setOpen (shouldBeOpen); - break; - } - - ++index; - } - } + if (SectionComponent* s = propertyHolderComponent->getSectionWithNonEmptyName (sectionIndex)) + s->setOpen (shouldBeOpen); } void PropertyPanel::setSectionEnabled (const int sectionIndex, const bool shouldBeEnabled) { - int index = 0; + if (SectionComponent* s = propertyHolderComponent->getSectionWithNonEmptyName (sectionIndex)) + s->setEnabled (shouldBeEnabled); +} - for (int i = 0; i < propertyHolderComponent->getNumSections(); ++i) +void PropertyPanel::removeSection (int sectionIndex) +{ + if (SectionComponent* s = propertyHolderComponent->getSectionWithNonEmptyName (sectionIndex)) { - SectionComponent* const section = propertyHolderComponent->getSection (i); - - if (section->getName().isNotEmpty()) - { - if (index == sectionIndex) - { - section->setEnabled (shouldBeEnabled); - break; - } - - ++index; - } + propertyHolderComponent->sections.removeObject (s); + updatePropHolderLayout(); } } @@ -408,7 +368,7 @@ void PropertyPanel::setMessageWhenEmpty (const String& newMessage) } } -const String& PropertyPanel::getMessageWhenEmpty() const +const String& PropertyPanel::getMessageWhenEmpty() const noexcept { return messageWhenEmpty; } diff --git a/JuceLibraryCode/modules/juce_gui_basics/properties/juce_PropertyPanel.h b/JuceLibraryCode/modules/juce_gui_basics/properties/juce_PropertyPanel.h index 3bd6115..43615b9 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/properties/juce_PropertyPanel.h +++ b/JuceLibraryCode/modules/juce_gui_basics/properties/juce_PropertyPanel.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -67,8 +67,9 @@ public: /** Adds a set of properties to the panel. - These properties are added at the bottom of the list, under a section heading with - a plus/minus button that allows it to be opened and closed. + These properties are added under a section heading with a plus/minus button that + allows it to be opened and closed. If indexToInsertAt is < 0 then it will be added + at the end of the list, or before the given index if the index is non-zero. The components in the list will be owned by this object and will be automatically deleted later on when no longer needed. @@ -77,7 +78,8 @@ public: */ void addSection (const String& sectionTitle, const Array& newPropertyComponents, - bool shouldSectionInitiallyBeOpen = true); + bool shouldSectionInitiallyBeOpen = true, + int indexToInsertAt = -1); /** Calls the refresh() method of all PropertyComponents in the panel */ void refreshAll() const; @@ -111,6 +113,11 @@ public: */ void setSectionEnabled (int sectionIndex, bool shouldBeEnabled); + /** Remove one of the sections using the section index. + The index is from 0 up to the number of items returned by getSectionNames(). + */ + void removeSection (int sectionIndex); + //============================================================================== /** Saves the current state of open/closed sections so it can be restored later. @@ -140,7 +147,7 @@ public: /** Returns the message that is displayed when there are no properties. @see setMessageWhenEmpty */ - const String& getMessageWhenEmpty() const; + const String& getMessageWhenEmpty() const noexcept; //============================================================================== /** @internal */ @@ -149,10 +156,9 @@ public: void resized() override; private: - class SectionComponent; - Viewport viewport; - class PropertyHolderComponent; + struct SectionComponent; + struct PropertyHolderComponent; PropertyHolderComponent* propertyHolderComponent; String messageWhenEmpty; diff --git a/JuceLibraryCode/modules/juce_gui_basics/properties/juce_SliderPropertyComponent.cpp b/JuceLibraryCode/modules/juce_gui_basics/properties/juce_SliderPropertyComponent.cpp index d1190ae..75c4581 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/properties/juce_SliderPropertyComponent.cpp +++ b/JuceLibraryCode/modules/juce_gui_basics/properties/juce_SliderPropertyComponent.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_gui_basics/properties/juce_SliderPropertyComponent.h b/JuceLibraryCode/modules/juce_gui_basics/properties/juce_SliderPropertyComponent.h index 99d85e3..35983df 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/properties/juce_SliderPropertyComponent.h +++ b/JuceLibraryCode/modules/juce_gui_basics/properties/juce_SliderPropertyComponent.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -58,6 +58,10 @@ public: If you need to customise the slider in other ways, your constructor can access the slider member variable and change it directly. + + Note that if you call this constructor then you must use the Value to interact with + the value, and you can't override the class with your own setValue or getValue methods. + If you want to use those methods, call the other constructor instead. */ SliderPropertyComponent (const Value& valueToControl, const String& propertyName, diff --git a/JuceLibraryCode/modules/juce_gui_basics/properties/juce_TextPropertyComponent.cpp b/JuceLibraryCode/modules/juce_gui_basics/properties/juce_TextPropertyComponent.cpp index e45941a..670cf7d 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/properties/juce_TextPropertyComponent.cpp +++ b/JuceLibraryCode/modules/juce_gui_basics/properties/juce_TextPropertyComponent.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_gui_basics/properties/juce_TextPropertyComponent.h b/JuceLibraryCode/modules/juce_gui_basics/properties/juce_TextPropertyComponent.h index 2b48496..da7d780 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/properties/juce_TextPropertyComponent.h +++ b/JuceLibraryCode/modules/juce_gui_basics/properties/juce_TextPropertyComponent.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) diff --git a/JuceLibraryCode/modules/juce_gui_basics/widgets/juce_ComboBox.cpp b/JuceLibraryCode/modules/juce_gui_basics/widgets/juce_ComboBox.cpp index ffdcfd1..409969e 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/widgets/juce_ComboBox.cpp +++ b/JuceLibraryCode/modules/juce_gui_basics/widgets/juce_ComboBox.cpp @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -56,10 +56,7 @@ ComboBox::ComboBox (const String& name) ComboBox::~ComboBox() { currentId.removeListener (this); - - if (menuActive) - PopupMenu::dismissAllActiveMenus(); - + hidePopup(); label = nullptr; } @@ -473,7 +470,7 @@ bool ComboBox::keyPressed (const KeyPress& key) if (key == KeyPress::returnKey) { - showPopup(); + showPopupIfNotActive(); return true; } @@ -501,51 +498,70 @@ void ComboBox::labelTextChanged (Label*) //============================================================================== -void ComboBox::popupMenuFinishedCallback (int result, ComboBox* box) +void ComboBox::showPopupIfNotActive() { - if (box != nullptr) + if (! menuActive) { - box->menuActive = false; + menuActive = true; + showPopup(); + } +} + +void ComboBox::hidePopup() +{ + if (menuActive) + { + menuActive = false; + PopupMenu::dismissAllActiveMenus(); + repaint(); + } +} + +static void comboBoxPopupMenuFinishedCallback (int result, ComboBox* combo) +{ + if (combo != nullptr) + { + combo->hidePopup(); if (result != 0) - box->setSelectedId (result); + combo->setSelectedId (result); } } void ComboBox::showPopup() { - if (! menuActive) + PopupMenu menu; + menu.setLookAndFeel (&getLookAndFeel()); + addItemsToMenu (menu); + + menu.showMenuAsync (PopupMenu::Options().withTargetComponent (this) + .withItemThatMustBeVisible (getSelectedId()) + .withMinimumWidth (getWidth()) + .withMaximumNumColumns (1) + .withStandardItemHeight (label->getHeight()), + ModalCallbackFunction::forComponent (comboBoxPopupMenuFinishedCallback, this)); +} + +void ComboBox::addItemsToMenu (PopupMenu& menu) const +{ + const int selectedId = getSelectedId(); + + for (int i = 0; i < items.size(); ++i) { - const int selectedId = getSelectedId(); + const ItemInfo* const item = items.getUnchecked(i); + jassert (item != nullptr); - PopupMenu menu; - menu.setLookAndFeel (&getLookAndFeel()); - - for (int i = 0; i < items.size(); ++i) - { - const ItemInfo* const item = items.getUnchecked(i); - - if (item->isSeparator()) - menu.addSeparator(); - else if (item->isHeading) - menu.addSectionHeader (item->name); - else - menu.addItem (item->itemId, item->name, - item->isEnabled, item->itemId == selectedId); - } - - if (items.size() == 0) - menu.addItem (1, noChoicesMessage, false); - - menuActive = true; - - menu.showMenuAsync (PopupMenu::Options().withTargetComponent (this) - .withItemThatMustBeVisible (selectedId) - .withMinimumWidth (getWidth()) - .withMaximumNumColumns (1) - .withStandardItemHeight (jlimit (12, 24, getHeight())), - ModalCallbackFunction::forComponent (popupMenuFinishedCallback, this)); + if (item->isSeparator()) + menu.addSeparator(); + else if (item->isHeading) + menu.addSectionHeader (item->name); + else + menu.addItem (item->itemId, item->name, + item->isEnabled, item->itemId == selectedId); } + + if (items.size() == 0) + menu.addItem (1, noChoicesMessage, false); } //============================================================================== @@ -556,7 +572,7 @@ void ComboBox::mouseDown (const MouseEvent& e) isButtonDown = isEnabled() && ! e.mods.isPopupMenu(); if (isButtonDown && (e.eventComponent == this || ! label->isEditable())) - showPopup(); + showPopupIfNotActive(); } void ComboBox::mouseDrag (const MouseEvent& e) @@ -564,7 +580,7 @@ void ComboBox::mouseDrag (const MouseEvent& e) beginDragAutoRepeat (50); if (isButtonDown && ! e.mouseWasClicked()) - showPopup(); + showPopupIfNotActive(); } void ComboBox::mouseUp (const MouseEvent& e2) @@ -579,7 +595,7 @@ void ComboBox::mouseUp (const MouseEvent& e2) if (reallyContains (e.getPosition(), true) && (e2.eventComponent == this || ! label->isEditable())) { - showPopup(); + showPopupIfNotActive(); } } } diff --git a/JuceLibraryCode/modules/juce_gui_basics/widgets/juce_ComboBox.h b/JuceLibraryCode/modules/juce_gui_basics/widgets/juce_ComboBox.h index 20e2e09..515e5d2 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/widgets/juce_ComboBox.h +++ b/JuceLibraryCode/modules/juce_gui_basics/widgets/juce_ComboBox.h @@ -2,7 +2,7 @@ ============================================================================== This file is part of the JUCE library. - Copyright (c) 2013 - Raw Material Software Ltd. + Copyright (c) 2015 - ROLI Ltd. Permission is granted to use this software under the terms of either: a) the GPL v2 (or any later version) @@ -63,7 +63,7 @@ public: ~ComboBox(); //============================================================================== - /** Sets whether the test in the combo-box is editable. + /** Sets whether the text in the combo-box is editable. The default state for a new ComboBox is non-editable, and can only be changed by choosing from the drop-down list. @@ -94,7 +94,7 @@ public: @param newItemId an associated ID number that can be set or retrieved - see getSelectedId() and setSelectedId(). Note that this value can not be 0! - @see setItemEnabled, addSeparator, addSectionHeading, removeItem, getNumItems, getItemText, getItemId + @see setItemEnabled, addSeparator, addSectionHeading, getNumItems, getItemText, getItemId */ void addItem (const String& newItemText, int newItemId); @@ -142,7 +142,7 @@ public: If this call causes the content to be cleared, and a change-message will be broadcast according to the notification parameter. - @see addItem, removeItem, getNumItems + @see addItem, getNumItems */ void clear (NotificationType notification = sendNotificationAsync); @@ -257,8 +257,20 @@ public: */ void showEditor(); - /** Pops up the combo box's list. */ - void showPopup(); + /** Pops up the combo box's list. + This is virtual so that you can override it with your own custom popup + mechanism if you need some really unusual behaviour. + */ + virtual void showPopup(); + + /** Hides the combo box's popup list, if it's currently visible. */ + void hidePopup(); + + /** Returns true if the popup menu is currently being shown. */ + bool isPopupActive() const noexcept { return menuActive; } + + /** Adds the items in this ComboBox to the given menu. */ + virtual void addItemsToMenu (PopupMenu&) const; //============================================================================== /** @@ -326,7 +338,7 @@ public: These constants can be used either via the Component::setColour(), or LookAndFeel::setColour() methods. - To change the colours of the menu that pops up + To change the colours of the menu that pops up, you can set the colour IDs in PopupMenu::ColourIDs. @see Component::setColour, Component::findColour, LookAndFeel::setColour, LookAndFeel::findColour */ @@ -415,12 +427,12 @@ private: bool isEnabled : 1, isHeading : 1; }; - OwnedArray items; + OwnedArray items; Value currentId; int lastCurrentId; bool isButtonDown, separatorPending, menuActive, scrollWheelEnabled; float mouseWheelAccumulator; - ListenerList listeners; + ListenerList listeners; ScopedPointer