diff --git a/JuceLibraryCode/JuceHeader.h b/JuceLibraryCode/JuceHeader.h index 95dfee3..4d0fc0c 100644 --- a/JuceLibraryCode/JuceHeader.h +++ b/JuceLibraryCode/JuceHeader.h @@ -34,11 +34,13 @@ using namespace juce; #endif +#if ! JUCE_DONT_DECLARE_PROJECTINFO namespace ProjectInfo { const char* const projectName = "RBM"; const char* const versionString = "1.0.0"; const int versionNumber = 0x10000; } +#endif #endif // __APPHEADERFILE_J0FH5E__ diff --git a/JuceLibraryCode/modules/juce_audio_basics/midi/juce_MidiBuffer.h b/JuceLibraryCode/modules/juce_audio_basics/midi/juce_MidiBuffer.h index 7dfc458..ecbc56a 100644 --- a/JuceLibraryCode/modules/juce_audio_basics/midi/juce_MidiBuffer.h +++ b/JuceLibraryCode/modules/juce_audio_basics/midi/juce_MidiBuffer.h @@ -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/synthesisers/juce_Synthesiser.cpp b/JuceLibraryCode/modules/juce_audio_basics/synthesisers/juce_Synthesiser.cpp index 7a72d00..6a38130 100644 --- a/JuceLibraryCode/modules/juce_audio_basics/synthesisers/juce_Synthesiser.cpp +++ b/JuceLibraryCode/modules/juce_audio_basics/synthesisers/juce_Synthesiser.cpp @@ -163,10 +163,7 @@ void Synthesiser::renderNextBlock (AudioSampleBuffer& outputBuffer, const MidiBu : numSamples; if (numThisTime > 0) - { - for (int i = voices.size(); --i >= 0;) - voices.getUnchecked (i)->renderNextBlock (outputBuffer, startSample, numThisTime); - } + renderVoices (outputBuffer, startSample, numThisTime); if (useEvent) handleMidiEvent (m); @@ -176,6 +173,12 @@ void Synthesiser::renderNextBlock (AudioSampleBuffer& outputBuffer, const MidiBu } } +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) { if (m.isNoteOn()) @@ -184,7 +187,7 @@ void Synthesiser::handleMidiEvent (const MidiMessage& m) } else if (m.isNoteOff()) { - noteOff (m.getChannel(), m.getNoteNumber(), true); + noteOff (m.getChannel(), m.getNoteNumber(), m.getFloatVelocity(), true); } else if (m.isAllNotesOff() || m.isAllSoundOff()) { @@ -230,7 +233,7 @@ 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), @@ -248,7 +251,7 @@ void Synthesiser::startVoice (SynthesiserVoice* const voice, if (voice != nullptr && sound != nullptr) { if (voice->currentlyPlayingSound != nullptr) - voice->stopNote (false); + voice->stopNote (0.0f, false); voice->startNote (midiNoteNumber, velocity, sound, lastPitchWheelValues [midiChannel - 1]); @@ -261,11 +264,11 @@ void Synthesiser::startVoice (SynthesiserVoice* const voice, } } -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 +276,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); @@ -291,7 +295,7 @@ void Synthesiser::noteOff (const int midiChannel, voice->keyIsDown = false; if (! (sustainPedalsDown [midiChannel] || voice->sostenutoPedalDown)) - stopVoice (voice, allowTailOff); + stopVoice (voice, velocity, allowTailOff); } } } @@ -307,7 +311,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(); @@ -379,7 +383,7 @@ void Synthesiser::handleSustainPedal (int midiChannel, bool isDown) SynthesiserVoice* const voice = voices.getUnchecked (i); if (voice->isPlayingChannel (midiChannel) && ! voice->keyIsDown) - stopVoice (voice, true); + stopVoice (voice, 1.0f, true); } sustainPedalsDown.clearBit (midiChannel); @@ -400,7 +404,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); } } } diff --git a/JuceLibraryCode/modules/juce_audio_basics/synthesisers/juce_Synthesiser.h b/JuceLibraryCode/modules/juce_audio_basics/synthesisers/juce_Synthesiser.h index e765697..a704b5f 100644 --- a/JuceLibraryCode/modules/juce_audio_basics/synthesisers/juce_Synthesiser.h +++ b/JuceLibraryCode/modules/juce_audio_basics/synthesisers/juce_Synthesiser.h @@ -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,7 @@ 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; /** 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. @@ -173,13 +175,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 +183,14 @@ 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. + */ + bool isPlayingChannel (int midiChannel) const; /** 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 @@ -235,6 +237,11 @@ private: SynthesiserSound::Ptr currentlyPlayingSound; bool keyIsDown, 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) }; @@ -365,6 +372,7 @@ public: */ virtual void noteOff (int midiChannel, int midiNoteNumber, + float velocity, bool allowTailOff); /** Turns off all notes. @@ -444,7 +452,7 @@ public: 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. @@ -474,6 +482,13 @@ protected: /** The last pitch-wheel values for each midi channel. */ int lastPitchWheelValues [16]; + /** 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. @@ -511,11 +526,12 @@ private: 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; } #endif JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Synthesiser) 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..53dc5df 100644 --- a/JuceLibraryCode/modules/juce_audio_devices/native/juce_android_OpenSL.cpp +++ b/JuceLibraryCode/modules/juce_audio_devices/native/juce_android_OpenSL.cpp @@ -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..70490aa 100644 --- a/JuceLibraryCode/modules/juce_audio_devices/native/juce_ios_Audio.cpp +++ b/JuceLibraryCode/modules/juce_audio_devices/native/juce_ios_Audio.cpp @@ -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..091ffba 100644 --- a/JuceLibraryCode/modules/juce_audio_devices/native/juce_linux_ALSA.cpp +++ b/JuceLibraryCode/modules/juce_audio_devices/native/juce_linux_ALSA.cpp @@ -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 diff --git a/JuceLibraryCode/modules/juce_audio_formats/codecs/juce_LAMEEncoderAudioFormat.cpp b/JuceLibraryCode/modules/juce_audio_formats/codecs/juce_LAMEEncoderAudioFormat.cpp index 5d30d44..8a5263c 100644 --- a/JuceLibraryCode/modules/juce_audio_formats/codecs/juce_LAMEEncoderAudioFormat.cpp +++ b/JuceLibraryCode/modules/juce_audio_formats/codecs/juce_LAMEEncoderAudioFormat.cpp @@ -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_WavAudioFormat.cpp b/JuceLibraryCode/modules/juce_audio_formats/codecs/juce_WavAudioFormat.cpp index 1da4e03..591b16a 100644 --- a/JuceLibraryCode/modules/juce_audio_formats/codecs/juce_WavAudioFormat.cpp +++ b/JuceLibraryCode/modules/juce_audio_formats/codecs/juce_WavAudioFormat.cpp @@ -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 @@ -481,6 +482,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 +523,65 @@ 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) + { + const String s = values[WavAudioFormat::tracktionLoopInfo]; + MemoryBlock data; + + if (s.isNotEmpty()) + { + MemoryOutputStream os (data, false); + os.writeString (s); + } + + return data; + } + }; + //============================================================================== namespace AXMLChunk { @@ -816,6 +884,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; @@ -919,6 +993,8 @@ public: instChunk = InstChunk::createFrom (metadataValues); cueChunk = CueChunk ::createFrom (metadataValues); listChunk = ListChunk::createFrom (metadataValues); + acidChunk = AcidChunk::createFrom (metadataValues); + trckChunk = TracktionChunk::createFrom (metadataValues); } headerPosition = out->getPosition(); @@ -981,7 +1057,7 @@ public: } private: - MemoryBlock tempBlock, bwavChunk, axmlChunk, smplChunk, instChunk, cueChunk, listChunk; + MemoryBlock tempBlock, bwavChunk, axmlChunk, smplChunk, instChunk, cueChunk, listChunk, acidChunk, trckChunk; uint64 lengthInSamples, bytesWritten; int64 headerPosition; bool writeFailed; @@ -1033,6 +1109,8 @@ private: + chunkSize (instChunk) + chunkSize (cueChunk) + chunkSize (listChunk) + + chunkSize (acidChunk) + + chunkSize (trckChunk) + (8 + 28)); // (ds64 chunk) riffChunkSize += (riffChunkSize & 1); @@ -1112,6 +1190,8 @@ private: writeChunk (instChunk, chunkName ("inst"), 7); writeChunk (cueChunk, chunkName ("cue ")); writeChunk (listChunk, chunkName ("LIST")); + writeChunk (acidChunk, chunkName ("acid")); + writeChunk (trckChunk, chunkName ("Trkn")); writeChunkHeader (chunkName ("data"), isRF64 ? -1 : (int) (lengthInSamples * bytesPerFrame)); diff --git a/JuceLibraryCode/modules/juce_audio_formats/codecs/juce_WavAudioFormat.h b/JuceLibraryCode/modules/juce_audio_formats/codecs/juce_WavAudioFormat.h index f80695c..62de05a 100644 --- a/JuceLibraryCode/modules/juce_audio_formats/codecs/juce_WavAudioFormat.h +++ b/JuceLibraryCode/modules/juce_audio_formats/codecs/juce_WavAudioFormat.h @@ -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/format/juce_AudioFormatReader.cpp b/JuceLibraryCode/modules/juce_audio_formats/format/juce_AudioFormatReader.cpp index 071f825..5db3149 100644 --- a/JuceLibraryCode/modules/juce_audio_formats/format/juce_AudioFormatReader.cpp +++ b/JuceLibraryCode/modules/juce_audio_formats/format/juce_AudioFormatReader.cpp @@ -173,35 +173,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,66 +228,20 @@ void AudioFormatReader::readMaxLevels (int64 startSampleInFile, int64 numSamples float& lowestLeft, float& highestLeft, float& lowestRight, float& highestRight) { - if (numSamples <= 0) + Range levels[2]; + readMaxLevels (startSampleInFile, numSamples, levels, jmin (2, (int) numChannels)); + lowestLeft = levels[0].getStart(); + highestLeft = levels[0].getEnd(); + + if (numChannels > 1) { - 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; + lowestRight = levels[1].getStart(); + highestRight = levels[1].getEnd(); } 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(); + lowestRight = lowestLeft; + highestRight = highestLeft; } } diff --git a/JuceLibraryCode/modules/juce_audio_formats/format/juce_AudioFormatReader.h b/JuceLibraryCode/modules/juce_audio_formats/format/juce_AudioFormatReader.h index d7cdd9c..065388a 100644 --- a/JuceLibraryCode/modules/juce_audio_formats/format/juce_AudioFormatReader.h +++ b/JuceLibraryCode/modules/juce_audio_formats/format/juce_AudioFormatReader.h @@ -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. diff --git a/JuceLibraryCode/modules/juce_audio_formats/sampler/juce_Sampler.cpp b/JuceLibraryCode/modules/juce_audio_formats/sampler/juce_Sampler.cpp index 9dbe7b3..4e7583e 100644 --- a/JuceLibraryCode/modules/juce_audio_formats/sampler/juce_Sampler.cpp +++ b/JuceLibraryCode/modules/juce_audio_formats/sampler/juce_Sampler.cpp @@ -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; } @@ -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..f801bf2 100644 --- a/JuceLibraryCode/modules/juce_audio_formats/sampler/juce_Sampler.h +++ b/JuceLibraryCode/modules/juce_audio_formats/sampler/juce_Sampler.h @@ -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,7 +124,7 @@ 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 controllerMoved (int controllerNumber, int newValue) override; 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 efb75b5..a741626 100644 --- a/JuceLibraryCode/modules/juce_audio_processors/format_types/juce_VST3PluginFormat.cpp +++ b/JuceLibraryCode/modules/juce_audio_processors/format_types/juce_VST3PluginFormat.cpp @@ -1446,7 +1446,7 @@ public: warnOnFailure (view->removed()); warnOnFailure (view->setFrame (nullptr)); - getAudioProcessor()->editorBeingDeleted (this); + processor.editorBeingDeleted (this); #if JUCE_MAC dummyComponent.setView (nullptr); @@ -2112,7 +2112,11 @@ 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; 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 c09d26f..5509e2c 100644 --- a/JuceLibraryCode/modules/juce_audio_processors/format_types/juce_VSTPluginFormat.cpp +++ b/JuceLibraryCode/modules/juce_audio_processors/format_types/juce_VSTPluginFormat.cpp @@ -787,7 +787,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; @@ -802,7 +802,7 @@ public: { char buffer [kVstMaxVendorStrLen + 8] = { 0 }; dispatch (effGetVendorString, 0, 0, buffer, 0); - desc.manufacturerName = buffer; + desc.manufacturerName = String::fromUTF8 (buffer); } desc.version = getVersion(); @@ -1197,7 +1197,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(); } } diff --git a/JuceLibraryCode/modules/juce_audio_processors/juce_audio_processors.cpp b/JuceLibraryCode/modules/juce_audio_processors/juce_audio_processors.cpp index 43934d6..d1f1679 100644 --- a/JuceLibraryCode/modules/juce_audio_processors/juce_audio_processors.cpp +++ b/JuceLibraryCode/modules/juce_audio_processors/juce_audio_processors.cpp @@ -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 diff --git a/JuceLibraryCode/modules/juce_audio_processors/processors/juce_AudioProcessor.cpp b/JuceLibraryCode/modules/juce_audio_processors/processors/juce_AudioProcessor.cpp index 45e1742..42f1c4d 100644 --- a/JuceLibraryCode/modules/juce_audio_processors/processors/juce_AudioProcessor.cpp +++ b/JuceLibraryCode/modules/juce_audio_processors/processors/juce_AudioProcessor.cpp @@ -128,7 +128,8 @@ String AudioProcessor::getParameterText (int parameterIndex, int maximumStringLe return getParameterText (parameterIndex).substring (0, maximumStringLength); } -int AudioProcessor::getParameterNumSteps (int /*parameterIndex*/) { return 0x7fffffff; } +int AudioProcessor::getDefaultNumParameterSteps() noexcept { return 0x7fffffff; } +int AudioProcessor::getParameterNumSteps (int /*parameterIndex*/) { return getDefaultNumParameterSteps(); } float AudioProcessor::getParameterDefaultValue (int /*parameterIndex*/) { return 0.0f; } AudioProcessorListener* AudioProcessor::getListenerLocked (const int index) 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 1dbaf46..33cd4e5 100644 --- a/JuceLibraryCode/modules/juce_audio_processors/processors/juce_AudioProcessor.h +++ b/JuceLibraryCode/modules/juce_audio_processors/processors/juce_AudioProcessor.h @@ -414,12 +414,18 @@ public: 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. */ virtual int getParameterNumSteps (int parameterIndex); + /** Returns the default number of steps for a parameter. + @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. diff --git a/JuceLibraryCode/modules/juce_audio_processors/processors/juce_AudioProcessorEditor.cpp b/JuceLibraryCode/modules/juce_audio_processors/processors/juce_AudioProcessorEditor.cpp index a4c9d29..a625411 100644 --- a/JuceLibraryCode/modules/juce_audio_processors/processors/juce_AudioProcessorEditor.cpp +++ b/JuceLibraryCode/modules/juce_audio_processors/processors/juce_AudioProcessorEditor.cpp @@ -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..1755497 100644 --- a/JuceLibraryCode/modules/juce_audio_processors/processors/juce_AudioProcessorEditor.h +++ b/JuceLibraryCode/modules/juce_audio_processors/processors/juce_AudioProcessorEditor.h @@ -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_PluginDescription.cpp b/JuceLibraryCode/modules/juce_audio_processors/processors/juce_PluginDescription.cpp index 8e1010f..5eafc07 100644 --- a/JuceLibraryCode/modules/juce_audio_processors/processors/juce_PluginDescription.cpp +++ b/JuceLibraryCode/modules/juce_audio_processors/processors/juce_PluginDescription.cpp @@ -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..24b17e5 100644 --- a/JuceLibraryCode/modules/juce_audio_processors/processors/juce_PluginDescription.h +++ b/JuceLibraryCode/modules/juce_audio_processors/processors/juce_PluginDescription.h @@ -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 fc3679c..081ba11 100644 --- a/JuceLibraryCode/modules/juce_audio_processors/scanning/juce_KnownPluginList.cpp +++ b/JuceLibraryCode/modules/juce_audio_processors/scanning/juce_KnownPluginList.cpp @@ -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; diff --git a/JuceLibraryCode/modules/juce_core/containers/juce_Array.h b/JuceLibraryCode/modules/juce_core/containers/juce_Array.h index 375576a..8e9cf3f 100644 --- a/JuceLibraryCode/modules/juce_core/containers/juce_Array.h +++ b/JuceLibraryCode/modules/juce_core/containers/juce_Array.h @@ -65,8 +65,7 @@ private: public: //============================================================================== /** Creates an empty array. */ - Array() noexcept - : numUsed (0) + Array() noexcept : numUsed (0) { } diff --git a/JuceLibraryCode/modules/juce_core/containers/juce_NamedValueSet.cpp b/JuceLibraryCode/modules/juce_core/containers/juce_NamedValueSet.cpp index c4e198d..504ab78 100644 --- a/JuceLibraryCode/modules/juce_core/containers/juce_NamedValueSet.cpp +++ b/JuceLibraryCode/modules/juce_core/containers/juce_NamedValueSet.cpp @@ -88,9 +88,8 @@ NamedValueSet& NamedValueSet::operator= (NamedValueSet&& other) noexcept } #endif -NamedValueSet::~NamedValueSet() +NamedValueSet::~NamedValueSet() noexcept { - clear(); } void NamedValueSet::clear() @@ -113,7 +112,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; @@ -170,7 +169,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..e4a98ed 100644 --- a/JuceLibraryCode/modules/juce_core/containers/juce_NamedValueSet.h +++ b/JuceLibraryCode/modules/juce_core/containers/juce_NamedValueSet.h @@ -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. @@ -89,7 +89,7 @@ public: #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..be7448c 100644 --- a/JuceLibraryCode/modules/juce_core/containers/juce_OwnedArray.h +++ b/JuceLibraryCode/modules/juce_core/containers/juce_OwnedArray.h @@ -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/files/juce_WildcardFileFilter.cpp b/JuceLibraryCode/modules/juce_core/files/juce_WildcardFileFilter.cpp index 1fef455..f18a2eb 100644 --- a/JuceLibraryCode/modules/juce_core/files/juce_WildcardFileFilter.cpp +++ b/JuceLibraryCode/modules/juce_core/files/juce_WildcardFileFilter.cpp @@ -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..fb398ce 100644 --- a/JuceLibraryCode/modules/juce_core/files/juce_WildcardFileFilter.h +++ b/JuceLibraryCode/modules/juce_core/files/juce_WildcardFileFilter.h @@ -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_Javascript.cpp b/JuceLibraryCode/modules/juce_core/javascript/juce_Javascript.cpp index af99a84..e74d610 100644 --- a/JuceLibraryCode/modules/juce_core/javascript/juce_Javascript.cpp +++ b/JuceLibraryCode/modules/juce_core/javascript/juce_Javascript.cpp @@ -544,7 +544,7 @@ struct JavascriptEngine::RootObject : public DynamicObject { DivideOp (const CodeLocation& l, ExpPtr& a, ExpPtr& b) noexcept : BinaryOperator (l, a, b, TokenTypes::divide) {} 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 / b) : var (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 @@ -1145,8 +1145,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(); } @@ -1555,6 +1561,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; } @@ -1587,6 +1594,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); } diff --git a/JuceLibraryCode/modules/juce_core/juce_core.cpp b/JuceLibraryCode/modules/juce_core/juce_core.cpp index c992d50..7cfc664 100644 --- a/JuceLibraryCode/modules/juce_core/juce_core.cpp +++ b/JuceLibraryCode/modules/juce_core/juce_core.cpp @@ -53,6 +53,8 @@ #if JUCE_WINDOWS #include + + #define _WINSOCK_DEPRECATED_NO_WARNINGS 1 #include #include @@ -79,6 +81,7 @@ #if JUCE_LINUX #include + #include #endif #include diff --git a/JuceLibraryCode/modules/juce_core/maths/juce_BigInteger.cpp b/JuceLibraryCode/modules/juce_core/maths/juce_BigInteger.cpp index b1c42b6..dd09616 100644 --- a/JuceLibraryCode/modules/juce_core/maths/juce_BigInteger.cpp +++ b/JuceLibraryCode/modules/juce_core/maths/juce_BigInteger.cpp @@ -307,7 +307,7 @@ 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 @@ -317,7 +317,7 @@ inline static int highestBitInInt (uint32 n) noexcept #if JUCE_GCC return 31 - __builtin_clz (n); - #elif JUCE_USE_INTRINSICS + #elif JUCE_USE_MSVC_INTRINSICS unsigned long highest; _BitScanReverse (&highest, n); return (int) highest; diff --git a/JuceLibraryCode/modules/juce_core/memory/juce_Atomic.h b/JuceLibraryCode/modules/juce_core/memory/juce_Atomic.h index d0dd6be..5e9d30c 100644 --- a/JuceLibraryCode/modules/juce_core/memory/juce_Atomic.h +++ b/JuceLibraryCode/modules/juce_core/memory/juce_Atomic.h @@ -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 0ecf2e4..fcd56bc 100644 --- a/JuceLibraryCode/modules/juce_core/memory/juce_ByteOrder.h +++ b/JuceLibraryCode/modules/juce_core/memory/juce_ByteOrder.h @@ -110,13 +110,13 @@ 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! + #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)); @@ -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,7 +150,7 @@ 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)); diff --git a/JuceLibraryCode/modules/juce_core/memory/juce_MemoryBlock.cpp b/JuceLibraryCode/modules/juce_core/memory/juce_MemoryBlock.cpp index a827037..6097c7e 100644 --- a/JuceLibraryCode/modules/juce_core/memory/juce_MemoryBlock.cpp +++ b/JuceLibraryCode/modules/juce_core/memory/juce_MemoryBlock.cpp @@ -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; } @@ -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_ScopedPointer.h b/JuceLibraryCode/modules/juce_core/memory/juce_ScopedPointer.h index a7fcff0..1aa8031 100644 --- a/JuceLibraryCode/modules/juce_core/memory/juce_ScopedPointer.h +++ b/JuceLibraryCode/modules/juce_core/memory/juce_ScopedPointer.h @@ -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_WeakReference.h b/JuceLibraryCode/modules/juce_core/memory/juce_WeakReference.h index b56808a..c11b19f 100644 --- a/JuceLibraryCode/modules/juce_core/memory/juce_WeakReference.h +++ b/JuceLibraryCode/modules/juce_core/memory/juce_WeakReference.h @@ -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/native/juce_android_Network.cpp b/JuceLibraryCode/modules/juce_core/native/juce_android_Network.cpp index 1b86dee..29a8cb5 100644 --- a/JuceLibraryCode/modules/juce_core/native/juce_android_Network.cpp +++ b/JuceLibraryCode/modules/juce_core/native/juce_android_Network.cpp @@ -166,7 +166,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_linux_Network.cpp b/JuceLibraryCode/modules/juce_core/native/juce_linux_Network.cpp index 7543a77..6871aa5 100644 --- a/JuceLibraryCode/modules/juce_core/native/juce_linux_Network.cpp +++ b/JuceLibraryCode/modules/juce_core/native/juce_linux_Network.cpp @@ -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); @@ -263,7 +263,7 @@ private: } } - String responseHeader (readResponse (socketHandle, timeOutTime)); + String responseHeader (readResponse (timeOutTime)); position = 0; if (responseHeader.isNotEmpty()) @@ -302,7 +302,7 @@ private: } //============================================================================== - String readResponse (const int socketHandle, const uint32 timeOutTime) + String readResponse (const uint32 timeOutTime) { int numConsecutiveLFs = 0; MemoryOutputStream buffer; @@ -338,7 +338,8 @@ 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; } diff --git a/JuceLibraryCode/modules/juce_core/native/juce_posix_SharedCode.h b/JuceLibraryCode/modules/juce_core/native/juce_posix_SharedCode.h index 2636cea..3bff639 100644 --- a/JuceLibraryCode/modules/juce_core/native/juce_posix_SharedCode.h +++ b/JuceLibraryCode/modules/juce_core/native/juce_posix_SharedCode.h @@ -234,7 +234,13 @@ namespace 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 (creationTime != nullptr) *creationTime = Time ((! statOk) ? 0 : (int64) (1000 * + #if JUCE_MAC || JUCE_IOS + info.st_birthtime)); + #else + info.st_ctime)); + #endif } if (isReadOnly != nullptr) @@ -664,6 +670,7 @@ int File::getVolumeSerialNumber() const } //============================================================================== +#if ! JUCE_IOS void juce_runSystemCommand (const String&); void juce_runSystemCommand (const String& command) { @@ -684,7 +691,7 @@ String juce_getOutputFromCommand (const String& command) tempFile.deleteFile(); return result; } - +#endif //============================================================================== #if JUCE_IOS diff --git a/JuceLibraryCode/modules/juce_core/native/juce_win32_SystemStats.cpp b/JuceLibraryCode/modules/juce_core/native/juce_win32_SystemStats.cpp index 901bc76..d98e323 100644 --- a/JuceLibraryCode/modules/juce_core/native/juce_win32_SystemStats.cpp +++ b/JuceLibraryCode/modules/juce_core/native/juce_win32_SystemStats.cpp @@ -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... @@ -313,7 +313,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..1421c10 100644 --- a/JuceLibraryCode/modules/juce_core/native/juce_win32_Threads.cpp +++ b/JuceLibraryCode/modules/juce_core/native/juce_win32_Threads.cpp @@ -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_Socket.cpp b/JuceLibraryCode/modules/juce_core/network/juce_Socket.cpp index 97d0e0f..618185b 100644 --- a/JuceLibraryCode/modules/juce_core/network/juce_Socket.cpp +++ b/JuceLibraryCode/modules/juce_core/network/juce_Socket.cpp @@ -418,8 +418,10 @@ bool StreamingSocket::createListener (const int newPortNumber, const String& loc if (handle < 0) return false; + #if ! JUCE_WINDOWS // on windows, adding this option produces behaviour different to posix const int reuse = 1; setsockopt (handle, SOL_SOCKET, SO_REUSEADDR, (const char*) &reuse, sizeof (reuse)); + #endif if (bind (handle, (struct sockaddr*) &servTmpAddr, sizeof (struct sockaddr_in)) < 0 || listen (handle, SOMAXCONN) < 0) diff --git a/JuceLibraryCode/modules/juce_core/network/juce_URL.cpp b/JuceLibraryCode/modules/juce_core/network/juce_URL.cpp index 49db1f9..76d2b1e 100644 --- a/JuceLibraryCode/modules/juce_core/network/juce_URL.cpp +++ b/JuceLibraryCode/modules/juce_core/network/juce_URL.cpp @@ -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 diff --git a/JuceLibraryCode/modules/juce_core/network/juce_URL.h b/JuceLibraryCode/modules/juce_core/network/juce_URL.h index 4f511d8..06d8fb7 100644 --- a/JuceLibraryCode/modules/juce_core/network/juce_URL.h +++ b/JuceLibraryCode/modules/juce_core/network/juce_URL.h @@ -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; diff --git a/JuceLibraryCode/modules/juce_core/system/juce_PlatformDefs.h b/JuceLibraryCode/modules/juce_core/system/juce_PlatformDefs.h index 6f59979..4086dfa 100644 --- a/JuceLibraryCode/modules/juce_core/system/juce_PlatformDefs.h +++ b/JuceLibraryCode/modules/juce_core/system/juce_PlatformDefs.h @@ -68,7 +68,7 @@ @see jassert() */ #define juce_breakDebugger { ::kill (0, SIGTRAP); } -#elif JUCE_USE_INTRINSICS +#elif JUCE_USE_MSVC_INTRINSICS #ifndef __INTEL_COMPILER #pragma intrinsic (__debugbreak) #endif @@ -211,6 +211,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 diff --git a/JuceLibraryCode/modules/juce_core/system/juce_StandardHeader.h b/JuceLibraryCode/modules/juce_core/system/juce_StandardHeader.h index 2f420e8..e87e565 100644 --- a/JuceLibraryCode/modules/juce_core/system/juce_StandardHeader.h +++ b/JuceLibraryCode/modules/juce_core/system/juce_StandardHeader.h @@ -73,7 +73,7 @@ #include #include -#if JUCE_USE_INTRINSICS +#if JUCE_USE_MSVC_INTRINSICS #include #endif diff --git a/JuceLibraryCode/modules/juce_core/system/juce_TargetPlatform.h b/JuceLibraryCode/modules/juce_core/system/juce_TargetPlatform.h index 86adc38..63470b6 100644 --- a/JuceLibraryCode/modules/juce_core/system/juce_TargetPlatform.h +++ b/JuceLibraryCode/modules/juce_core/system/juce_TargetPlatform.h @@ -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_String.h b/JuceLibraryCode/modules/juce_core/text/juce_String.h index 4873bd9..6a51107 100644 --- a/JuceLibraryCode/modules/juce_core/text/juce_String.h +++ b/JuceLibraryCode/modules/juce_core/text/juce_String.h @@ -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/xml/juce_XmlElement.cpp b/JuceLibraryCode/modules/juce_core/xml/juce_XmlElement.cpp index 000df15..0a9f054 100644 --- a/JuceLibraryCode/modules/juce_core/xml/juce_XmlElement.cpp +++ b/JuceLibraryCode/modules/juce_core/xml/juce_XmlElement.cpp @@ -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..2f03e93 100644 --- a/JuceLibraryCode/modules/juce_core/xml/juce_XmlElement.h +++ b/JuceLibraryCode/modules/juce_core/xml/juce_XmlElement.h @@ -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_cryptography/encryption/juce_RSAKey.cpp b/JuceLibraryCode/modules/juce_cryptography/encryption/juce_RSAKey.cpp index fdc588e..2c1e9d8 100644 --- a/JuceLibraryCode/modules/juce_cryptography/encryption/juce_RSAKey.cpp +++ b/JuceLibraryCode/modules/juce_cryptography/encryption/juce_RSAKey.cpp @@ -54,6 +54,11 @@ bool RSAKey::operator!= (const RSAKey& other) const noexcept return ! operator== (other); } +bool RSAKey::isValid() const noexcept +{ + return operator!= (RSAKey()); +} + String RSAKey::toString() const { return part1.toString (16) + "," + part2.toString (16); diff --git a/JuceLibraryCode/modules/juce_cryptography/encryption/juce_RSAKey.h b/JuceLibraryCode/modules/juce_cryptography/encryption/juce_RSAKey.h index 19ec1f3..8df7eec 100644 --- a/JuceLibraryCode/modules/juce_cryptography/encryption/juce_RSAKey.h +++ b/JuceLibraryCode/modules/juce_cryptography/encryption/juce_RSAKey.h @@ -113,11 +113,15 @@ public: //============================================================================== /** Turns the key into a string representation. - This can be reloaded using the constructor that takes a string. */ String toString() const; + /** Returns true if the object is a valid key, or false if it was created by + the default constructor. + */ + bool isValid() const noexcept; + //============================================================================== /** Encodes or decodes a value. diff --git a/JuceLibraryCode/modules/juce_data_structures/undomanager/juce_UndoManager.cpp b/JuceLibraryCode/modules/juce_data_structures/undomanager/juce_UndoManager.cpp index 3557b90..07948c6 100644 --- a/JuceLibraryCode/modules/juce_data_structures/undomanager/juce_UndoManager.cpp +++ b/JuceLibraryCode/modules/juce_data_structures/undomanager/juce_UndoManager.cpp @@ -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,31 @@ 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; } //============================================================================== 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 +285,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..a3b691b 100644 --- a/JuceLibraryCode/modules/juce_data_structures/undomanager/juce_UndoManager.h +++ b/JuceLibraryCode/modules/juce_data_structures/undomanager/juce_UndoManager.h @@ -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,15 @@ 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 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 +184,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 +206,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 +225,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/values/juce_ValueTree.h b/JuceLibraryCode/modules/juce_data_structures/values/juce_ValueTree.h index 1e37e0c..42dd778 100644 --- a/JuceLibraryCode/modules/juce_data_structures/values/juce_ValueTree.h +++ b/JuceLibraryCode/modules/juce_data_structures/values/juce_ValueTree.h @@ -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; diff --git a/JuceLibraryCode/modules/juce_events/broadcasters/juce_ActionBroadcaster.cpp b/JuceLibraryCode/modules/juce_events/broadcasters/juce_ActionBroadcaster.cpp index a7d56a6..33f232d 100644 --- a/JuceLibraryCode/modules/juce_events/broadcasters/juce_ActionBroadcaster.cpp +++ b/JuceLibraryCode/modules/juce_events/broadcasters/juce_ActionBroadcaster.cpp @@ -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/messages/juce_ApplicationBase.cpp b/JuceLibraryCode/modules/juce_events/messages/juce_ApplicationBase.cpp index 7a87fdb..dafc27e 100644 --- a/JuceLibraryCode/modules/juce_events/messages/juce_ApplicationBase.cpp +++ b/JuceLibraryCode/modules/juce_events/messages/juce_ApplicationBase.cpp @@ -232,7 +232,7 @@ int JUCEApplicationBase::main() jassert (app != nullptr); if (! app->initialiseApp()) - return 0; + return app->getApplicationReturnValue(); JUCE_TRY { diff --git a/JuceLibraryCode/modules/juce_events/messages/juce_ApplicationBase.h b/JuceLibraryCode/modules/juce_events/messages/juce_ApplicationBase.h index 51f098c..073e5d6 100644 --- a/JuceLibraryCode/modules/juce_events/messages/juce_ApplicationBase.h +++ b/JuceLibraryCode/modules/juce_events/messages/juce_ApplicationBase.h @@ -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"; } diff --git a/JuceLibraryCode/modules/juce_events/messages/juce_MessageManager.cpp b/JuceLibraryCode/modules/juce_events/messages/juce_MessageManager.cpp index 31e2710..1383f90 100644 --- a/JuceLibraryCode/modules/juce_events/messages/juce_MessageManager.cpp +++ b/JuceLibraryCode/modules/juce_events/messages/juce_MessageManager.cpp @@ -288,7 +288,10 @@ bool MessageManagerLock::attemptLock (Thread* const threadToCheck, ThreadPoolJob blockingMessage = new BlockingMessage(); if (! blockingMessage->post()) + { + blockingMessage = nullptr; return false; + } while (! blockingMessage->lockedEvent.wait (20)) { diff --git a/JuceLibraryCode/modules/juce_graphics/geometry/juce_AffineTransform.h b/JuceLibraryCode/modules/juce_graphics/geometry/juce_AffineTransform.h index dfc3a29..f30fdb8 100644 --- a/JuceLibraryCode/modules/juce_graphics/geometry/juce_AffineTransform.h +++ b/JuceLibraryCode/modules/juce_graphics/geometry/juce_AffineTransform.h @@ -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/image_formats/juce_PNGLoader.cpp b/JuceLibraryCode/modules/juce_graphics/image_formats/juce_PNGLoader.cpp index 4ee36ab..636b293 100644 --- a/JuceLibraryCode/modules/juce_graphics/image_formats/juce_PNGLoader.cpp +++ b/JuceLibraryCode/modules/juce_graphics/image_formats/juce_PNGLoader.cpp @@ -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..e7be9a3 100644 --- a/JuceLibraryCode/modules/juce_graphics/images/juce_Image.cpp +++ b/JuceLibraryCode/modules/juce_graphics/images/juce_Image.cpp @@ -197,11 +197,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 +216,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) { } diff --git a/JuceLibraryCode/modules/juce_graphics/images/juce_Image.h b/JuceLibraryCode/modules/juce_graphics/images/juce_Image.h index 3580f9f..0f67b4e 100644 --- a/JuceLibraryCode/modules/juce_graphics/images/juce_Image.h +++ b/JuceLibraryCode/modules/juce_graphics/images/juce_Image.h @@ -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: //============================================================================== diff --git a/JuceLibraryCode/modules/juce_graphics/native/juce_win32_Fonts.cpp b/JuceLibraryCode/modules/juce_graphics/native/juce_win32_Fonts.cpp index ab5dbe8..bc5bb35 100644 --- a/JuceLibraryCode/modules/juce_graphics/native/juce_win32_Fonts.cpp +++ b/JuceLibraryCode/modules/juce_graphics/native/juce_win32_Fonts.cpp @@ -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_gui_basics/application/juce_Application.h b/JuceLibraryCode/modules/juce_gui_basics/application/juce_Application.h index 1ffb27e..140cf9d 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/application/juce_Application.h +++ b/JuceLibraryCode/modules/juce_gui_basics/application/juce_Application.h @@ -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"; } diff --git a/JuceLibraryCode/modules/juce_gui_basics/commands/juce_KeyPressMappingSet.cpp b/JuceLibraryCode/modules/juce_gui_basics/commands/juce_KeyPressMappingSet.cpp index b37a981..bcfac4e 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/commands/juce_KeyPressMappingSet.cpp +++ b/JuceLibraryCode/modules/juce_gui_basics/commands/juce_KeyPressMappingSet.cpp @@ -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/components/juce_Component.cpp b/JuceLibraryCode/modules/juce_gui_basics/components/juce_Component.cpp index 0b5e592..7cbe59f 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/components/juce_Component.cpp +++ b/JuceLibraryCode/modules/juce_gui_basics/components/juce_Component.cpp @@ -141,7 +141,7 @@ public: } private: - Array listeners; + Array listeners; int numDeepMouseListeners; class BailOutChecker2 @@ -256,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 @@ -399,16 +399,6 @@ 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) { bool nothingChanged = true; @@ -441,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()) @@ -480,7 +441,7 @@ struct Component::ComponentHelpers }; //============================================================================== -Component::Component() +Component::Component() noexcept : parentComponent (nullptr), lookAndFeel (nullptr), effect (nullptr), @@ -489,7 +450,7 @@ Component::Component() { } -Component::Component (const String& name) +Component::Component (const String& name) noexcept : componentName (name), parentComponent (nullptr), lookAndFeel (nullptr), @@ -620,7 +581,6 @@ bool Component::isShowing() const return false; } - //============================================================================== void* Component::getWindowHandle() const { @@ -880,7 +840,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) { @@ -1643,7 +1603,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 @@ -1665,7 +1625,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 @@ -2205,7 +2165,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))) @@ -2284,28 +2244,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&) {} @@ -2856,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) { @@ -2898,7 +2836,7 @@ void Component::moveKeyboardFocusToSibling (const bool moveToNext) if (parentComponent != nullptr) { - ScopedPointer traverser (createFocusTraverser()); + ScopedPointer traverser (createFocusTraverser()); if (traverser != nullptr) { @@ -3052,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 85a9d03..edc1957 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/components/juce_Component.h +++ b/JuceLibraryCode/modules/juce_gui_basics/components/juce_Component.h @@ -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 @@ -807,7 +797,7 @@ public: 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; @@ -1166,7 +1156,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); @@ -1757,11 +1747,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 */ @@ -1796,9 +1789,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; @@ -2136,31 +2127,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; } @@ -2268,20 +2259,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; @@ -2308,9 +2299,9 @@ private: bool mouseDownWasBlocked : 1; bool isMoveCallbackPending : 1; bool isResizeCallbackPending : 1; - #if JUCE_DEBUG + #if JUCE_DEBUG bool isInsidePaintCall : 1; - #endif + #endif }; union diff --git a/JuceLibraryCode/modules/juce_gui_basics/drawables/juce_SVGParser.cpp b/JuceLibraryCode/modules/juce_gui_basics/drawables/juce_SVGParser.cpp index f5dbcd9..cfb6b7b 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/drawables/juce_SVGParser.cpp +++ b/JuceLibraryCode/modules/juce_gui_basics/drawables/juce_SVGParser.cpp @@ -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 @@ -560,24 +542,12 @@ private: 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")); @@ -594,6 +564,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; @@ -796,44 +775,41 @@ 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) { - Array xCoords, yCoords, dxCoords, dyCoords; + Array xCoords, yCoords, dxCoords, dyCoords; - getCoordList (xCoords, getInheritedAttribute (xml, "x"), true, true); - getCoordList (yCoords, getInheritedAttribute (xml, "y"), true, false); + 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); @@ -898,7 +874,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(); @@ -920,13 +896,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; @@ -960,7 +935,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)) @@ -1000,7 +975,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); @@ -1011,13 +986,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; @@ -1221,7 +1213,7 @@ 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; diff --git a/JuceLibraryCode/modules/juce_gui_basics/juce_gui_basics.cpp b/JuceLibraryCode/modules/juce_gui_basics/juce_gui_basics.cpp index 4451e10..d7f6fed 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/juce_gui_basics.cpp +++ b/JuceLibraryCode/modules/juce_gui_basics/juce_gui_basics.cpp @@ -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() diff --git a/JuceLibraryCode/modules/juce_gui_basics/layout/juce_ComponentAnimator.cpp b/JuceLibraryCode/modules/juce_gui_basics/layout/juce_ComponentAnimator.cpp index b7d052c..a22414b 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/layout/juce_ComponentAnimator.cpp +++ b/JuceLibraryCode/modules/juce_gui_basics/layout/juce_ComponentAnimator.cpp @@ -25,8 +25,7 @@ class ComponentAnimator::AnimationTask { public: - AnimationTask (Component* const comp) - : component (comp) + AnimationTask (Component* const comp) noexcept : component (comp) { } @@ -34,7 +33,7 @@ public: float finalAlpha, int millisecondsToSpendMoving, bool useProxyComponent, - double startSpeed_, double endSpeed_) + double startSpd, double endSpd) { msElapsed = 0; msTotal = jmax (1, millisecondsToSpendMoving); @@ -51,10 +50,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); diff --git a/JuceLibraryCode/modules/juce_gui_basics/layout/juce_ComponentAnimator.h b/JuceLibraryCode/modules/juce_gui_basics/layout/juce_ComponentAnimator.h index f8ef6c6..66c960b 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/layout/juce_ComponentAnimator.h +++ b/JuceLibraryCode/modules/juce_gui_basics/layout/juce_ComponentAnimator.h @@ -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_ComponentBuilder.cpp b/JuceLibraryCode/modules/juce_gui_basics/layout/juce_ComponentBuilder.cpp index 82519ea..433ddf8 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/layout/juce_ComponentBuilder.cpp +++ b/JuceLibraryCode/modules/juce_gui_basics/layout/juce_ComponentBuilder.cpp @@ -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..c524111 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/layout/juce_ComponentBuilder.h +++ b/JuceLibraryCode/modules/juce_gui_basics/layout/juce_ComponentBuilder.h @@ -226,7 +226,7 @@ public: private: //============================================================================= - OwnedArray types; + OwnedArray types; ScopedPointer component; ImageProvider* imageProvider; #if JUCE_DEBUG 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 37dc124..749db35 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/lookandfeel/juce_LookAndFeel_V2.cpp +++ b/JuceLibraryCode/modules/juce_gui_basics/lookandfeel/juce_LookAndFeel_V2.cpp @@ -1001,6 +1001,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() { 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 f728df3..2342b7c 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/lookandfeel/juce_LookAndFeel_V2.h +++ b/JuceLibraryCode/modules/juce_gui_basics/lookandfeel/juce_LookAndFeel_V2.h @@ -137,6 +137,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; diff --git a/JuceLibraryCode/modules/juce_gui_basics/menus/juce_MenuBarComponent.cpp b/JuceLibraryCode/modules/juce_gui_basics/menus/juce_MenuBarComponent.cpp index 5a22fc7..842fa59 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/menus/juce_MenuBarComponent.cpp +++ b/JuceLibraryCode/modules/juce_gui_basics/menus/juce_MenuBarComponent.cpp @@ -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..badd05a 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/menus/juce_MenuBarComponent.h +++ b/JuceLibraryCode/modules/juce_gui_basics/menus/juce_MenuBarComponent.h @@ -40,9 +40,9 @@ 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 nullptr into this if you like, and set the model + later using the setModel() method */ MenuBarComponent (MenuBarModel* model); @@ -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.h b/JuceLibraryCode/modules/juce_gui_basics/menus/juce_MenuBarModel.h index ceac89a..99b6985 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/menus/juce_MenuBarModel.h +++ b/JuceLibraryCode/modules/juce_gui_basics/menus/juce_MenuBarModel.h @@ -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 963b530..fdaadb2 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/menus/juce_PopupMenu.cpp +++ b/JuceLibraryCode/modules/juce_gui_basics/menus/juce_PopupMenu.cpp @@ -1216,12 +1216,7 @@ 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) diff --git a/JuceLibraryCode/modules/juce_gui_basics/menus/juce_PopupMenu.h b/JuceLibraryCode/modules/juce_gui_basics/menus/juce_PopupMenu.h index 82545a3..97ac596 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/menus/juce_PopupMenu.h +++ b/JuceLibraryCode/modules/juce_gui_basics/menus/juce_PopupMenu.h @@ -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/mouse/juce_DragAndDropContainer.cpp b/JuceLibraryCode/modules/juce_gui_basics/mouse/juce_DragAndDropContainer.cpp index e4ff98d..bea1a16 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/mouse/juce_DragAndDropContainer.cpp +++ b/JuceLibraryCode/modules/juce_gui_basics/mouse/juce_DragAndDropContainer.cpp @@ -215,13 +215,28 @@ private: 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, Component*& resultComponent) const { Component* hit = getParentComponent(); if (hit == nullptr) - hit = Desktop::getInstance().findComponentAt (screenPos); + hit = findDesktopComponentBelow (screenPos); else hit = hit->getComponentAt (hit->getLocalPoint (nullptr, screenPos)); diff --git a/JuceLibraryCode/modules/juce_gui_basics/mouse/juce_MouseCursor.cpp b/JuceLibraryCode/modules/juce_gui_basics/mouse/juce_MouseCursor.cpp index 7aef739..3f2c84f 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/mouse/juce_MouseCursor.cpp +++ b/JuceLibraryCode/modules/juce_gui_basics/mouse/juce_MouseCursor.cpp @@ -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..df540f0 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/mouse/juce_MouseCursor.h +++ b/JuceLibraryCode/modules/juce_gui_basics/mouse/juce_MouseCursor.h @@ -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/native/juce_android_Windowing.cpp b/JuceLibraryCode/modules/juce_gui_basics/native/juce_android_Windowing.cpp index b2d1ee7..200615f 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/native/juce_android_Windowing.cpp +++ b/JuceLibraryCode/modules/juce_gui_basics/native/juce_android_Windowing.cpp @@ -43,7 +43,7 @@ JUCE_JNI_CALLBACK (JUCE_ANDROID_ACTIVITY_CLASSNAME, launchApp, void, (JNIEnv* en JUCEApplicationBase* app = JUCEApplicationBase::createInstance(); if (! app->initialiseApp()) - exit (0); + exit (app->getApplicationReturnValue()); jassert (MessageManager::getInstance()->isThisTheMessageThread()); } 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 b9bd76b..4b6451e 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/native/juce_linux_Windowing.cpp +++ b/JuceLibraryCode/modules/juce_gui_basics/native/juce_linux_Windowing.cpp @@ -1087,9 +1087,7 @@ public: { for (int i = 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; 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 31e2dd1..cc729e8 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/native/juce_win32_Windowing.cpp +++ b/JuceLibraryCode/modules/juce_gui_basics/native/juce_win32_Windowing.cpp @@ -845,7 +845,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 +960,7 @@ public: static ModifierKeys modifiersAtLastCallback; //============================================================================== - class JuceDropTarget : public ComBaseClassHelper + class JuceDropTarget : public ComBaseClassHelper { public: JuceDropTarget (HWNDComponentPeer& p) : ownerInfo (new OwnerInfo (p)) {} @@ -1099,13 +1099,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 { @@ -1300,7 +1300,7 @@ private: //============================================================================== static void* createWindowCallback (void* userData) { - static_cast (userData)->createWindow(); + static_cast (userData)->createWindow(); return nullptr; } @@ -1528,10 +1528,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); @@ -1639,7 +1643,7 @@ private: handlePaint (*context); } - static_cast (offscreenImage.getPixelData()) + static_cast (offscreenImage.getPixelData()) ->blitToWindow (hwnd, dc, transparent, x, y, updateLayeredWindowAlpha); } @@ -2257,6 +2261,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()) @@ -2305,7 +2327,7 @@ private: { Desktop& desktop = Desktop::getInstance(); - const_cast (desktop.getDisplays()).refresh(); + const_cast (desktop.getDisplays()).refresh(); if (fullScreen && ! isMinimised()) { @@ -2546,6 +2568,10 @@ private: } return TRUE; + case WM_POWERBROADCAST: + handlePowerBroadcast (wParam); + break; + case WM_SYNCPAINT: return 0; @@ -2875,7 +2901,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())); @@ -2896,18 +2922,15 @@ 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); } @@ -2980,7 +3003,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; @@ -3006,7 +3029,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; } } @@ -3211,7 +3234,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); diff --git a/JuceLibraryCode/modules/juce_gui_basics/properties/juce_BooleanPropertyComponent.h b/JuceLibraryCode/modules/juce_gui_basics/properties/juce_BooleanPropertyComponent.h index 958428f..d791cf0 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/properties/juce_BooleanPropertyComponent.h +++ b/JuceLibraryCode/modules/juce_gui_basics/properties/juce_BooleanPropertyComponent.h @@ -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 diff --git a/JuceLibraryCode/modules/juce_gui_basics/properties/juce_ChoicePropertyComponent.h b/JuceLibraryCode/modules/juce_gui_basics/properties/juce_ChoicePropertyComponent.h index 2956ae6..78887a3 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/properties/juce_ChoicePropertyComponent.h +++ b/JuceLibraryCode/modules/juce_gui_basics/properties/juce_ChoicePropertyComponent.h @@ -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_SliderPropertyComponent.h b/JuceLibraryCode/modules/juce_gui_basics/properties/juce_SliderPropertyComponent.h index 99d85e3..832c399 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/properties/juce_SliderPropertyComponent.h +++ b/JuceLibraryCode/modules/juce_gui_basics/properties/juce_SliderPropertyComponent.h @@ -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/widgets/juce_ComboBox.h b/JuceLibraryCode/modules/juce_gui_basics/widgets/juce_ComboBox.h index 30cef78..11515ba 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/widgets/juce_ComboBox.h +++ b/JuceLibraryCode/modules/juce_gui_basics/widgets/juce_ComboBox.h @@ -418,7 +418,7 @@ private: bool isEnabled : 1, isHeading : 1; }; - OwnedArray items; + OwnedArray items; Value currentId; int lastCurrentId; bool isButtonDown, separatorPending, menuActive, scrollWheelEnabled; diff --git a/JuceLibraryCode/modules/juce_gui_basics/widgets/juce_Label.cpp b/JuceLibraryCode/modules/juce_gui_basics/widgets/juce_Label.cpp index 778425e..7ab3d5e 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/widgets/juce_Label.cpp +++ b/JuceLibraryCode/modules/juce_gui_basics/widgets/juce_Label.cpp @@ -460,5 +460,3 @@ void Label::textEditorFocusLost (TextEditor& ed) { textEditorTextChanged (ed); } - -void Label::Listener::editorShown (Label*, TextEditor&) {} diff --git a/JuceLibraryCode/modules/juce_gui_basics/widgets/juce_Label.h b/JuceLibraryCode/modules/juce_gui_basics/widgets/juce_Label.h index e47fb68..825b0a0 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/widgets/juce_Label.h +++ b/JuceLibraryCode/modules/juce_gui_basics/widgets/juce_Label.h @@ -184,7 +184,7 @@ public: virtual void labelTextChanged (Label* labelThatHasChanged) = 0; /** Called when a Label goes into editing mode and displays a TextEditor. */ - virtual void editorShown (Label*, TextEditor& textEditorShown); + virtual void editorShown (Label*, TextEditor&) {} }; /** Registers a listener that will be called when the label's text changes. */ diff --git a/JuceLibraryCode/modules/juce_gui_basics/widgets/juce_ListBox.h b/JuceLibraryCode/modules/juce_gui_basics/widgets/juce_ListBox.h index b9fb246..71679e9 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/widgets/juce_ListBox.h +++ b/JuceLibraryCode/modules/juce_gui_basics/widgets/juce_ListBox.h @@ -45,7 +45,10 @@ public: */ virtual int getNumRows() = 0; - /** This method must be implemented to draw a row of the list. */ + /** This method must be implemented to draw a row of the list. + Note that the rowNumber value may be greater than the number of rows in your + list, so be careful that you don't assume it's less than getNumRows(). + */ virtual void paintListBoxItem (int rowNumber, Graphics& g, int width, int height, diff --git a/JuceLibraryCode/modules/juce_gui_basics/widgets/juce_Slider.cpp b/JuceLibraryCode/modules/juce_gui_basics/widgets/juce_Slider.cpp index 0b5aa10..c3b141e 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/widgets/juce_Slider.cpp +++ b/JuceLibraryCode/modules/juce_gui_basics/widgets/juce_Slider.cpp @@ -464,9 +464,9 @@ public: const bool stopAtEnd) { // make sure the values are sensible.. - jassert (rotaryStart >= 0 && rotaryEnd >= 0); - jassert (rotaryStart < float_Pi * 4.0f && rotaryEnd < float_Pi * 4.0f); - jassert (rotaryStart < rotaryEnd); + jassert (startAngleRadians >= 0 && endAngleRadians >= 0); + jassert (startAngleRadians < float_Pi * 4.0f && endAngleRadians < float_Pi * 4.0f); + jassert (startAngleRadians < endAngleRadians); rotaryStart = startAngleRadians; rotaryEnd = endAngleRadians; @@ -566,6 +566,7 @@ public: valueBox->setWantsKeyboardFocus (false); valueBox->setText (previousTextBoxContent, dontSendNotification); + valueBox->setTooltip (owner.getTooltip()); if (valueBox->isEditable() != editableText) // (avoid overriding the single/double click flags unless we have to) valueBox->setEditable (editableText && owner.isEnabled()); @@ -577,10 +578,6 @@ public: valueBox->addMouseListener (&owner, false); valueBox->setMouseCursor (MouseCursor::ParentCursor); } - else - { - valueBox->setTooltip (owner.getTooltip()); - } } else { @@ -1009,9 +1006,9 @@ public: valueBox->hideEditor (false); const double value = (double) currentValue.getValue(); - const double delta = getMouseWheelDelta (value, (wheel.deltaX != 0 ? -wheel.deltaX : wheel.deltaY) - * (wheel.isReversed ? -1.0f : 1.0f)); - + const double delta = getMouseWheelDelta (value, (std::abs (wheel.deltaX) > std::abs (wheel.deltaY) + ? -wheel.deltaX : wheel.deltaY) + * (wheel.isReversed ? -1.0f : 1.0f)); if (delta != 0) { const double newValue = value + jmax (interval, std::abs (delta)) * (delta < 0 ? -1.0 : 1.0); diff --git a/JuceLibraryCode/modules/juce_gui_basics/widgets/juce_TableListBox.cpp b/JuceLibraryCode/modules/juce_gui_basics/widgets/juce_TableListBox.cpp index ce71feb..cedec8d 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/widgets/juce_TableListBox.cpp +++ b/JuceLibraryCode/modules/juce_gui_basics/widgets/juce_TableListBox.cpp @@ -26,7 +26,7 @@ class TableListBox::RowComp : public Component, public TooltipClient { public: - RowComp (TableListBox& tlb) : owner (tlb), row (-1), isSelected (false) + RowComp (TableListBox& tlb) noexcept : owner (tlb), row (-1), isSelected (false) { } @@ -192,7 +192,7 @@ public: if (TableListBoxModel* m = owner.getModel()) return m->getCellTooltip (row, columnId); - return String::empty; + return String(); } Component* findChildComponentForColumn (const int columnId) const @@ -275,7 +275,7 @@ void TableListBox::setHeader (TableHeaderComponent* newHeader) { jassert (newHeader != nullptr); // you need to supply a real header for a table! - Rectangle newBounds (0, 0, 100, 28); + Rectangle newBounds (100, 28); if (header != nullptr) newBounds = header->getBounds(); @@ -287,7 +287,7 @@ void TableListBox::setHeader (TableHeaderComponent* newHeader) header->addListener (this); } -int TableListBox::getHeaderHeight() const +int TableListBox::getHeaderHeight() const noexcept { return header->getHeight(); } @@ -312,16 +312,11 @@ void TableListBox::autoSizeAllColumns() autoSizeColumn (header->getColumnIdOfIndex (i, true)); } -void TableListBox::setAutoSizeMenuOptionShown (const bool shouldBeShown) +void TableListBox::setAutoSizeMenuOptionShown (const bool shouldBeShown) noexcept { autoSizeOptionsShown = shouldBeShown; } -bool TableListBox::isAutoSizeMenuOptionShown() const -{ - return autoSizeOptionsShown; -} - Rectangle TableListBox::getCellPosition (const int columnId, const int rowNumber, const bool relativeToComponentTopLeft) const { @@ -337,7 +332,7 @@ Rectangle TableListBox::getCellPosition (const int columnId, const int rowN Component* TableListBox::getCellComponent (int columnId, int rowNumber) const { - if (RowComp* const rowComp = dynamic_cast (getComponentForRowNumber (rowNumber))) + if (RowComp* const rowComp = dynamic_cast (getComponentForRowNumber (rowNumber))) return rowComp->findChildComponentForColumn (columnId); return nullptr; @@ -370,12 +365,12 @@ void TableListBox::paintListBoxItem (int, Graphics&, int, int, bool) { } -Component* TableListBox::refreshComponentForRow (int rowNumber, bool isRowSelected_, Component* existingComponentToUpdate) +Component* TableListBox::refreshComponentForRow (int rowNumber, bool rowSelected, Component* existingComponentToUpdate) { if (existingComponentToUpdate == nullptr) existingComponentToUpdate = new RowComp (*this); - static_cast (existingComponentToUpdate)->update (rowNumber, isRowSelected_); + static_cast (existingComponentToUpdate)->update (rowNumber, rowSelected); return existingComponentToUpdate; } @@ -450,7 +445,7 @@ void TableListBox::updateColumnComponents() const const int firstRow = getRowContainingPosition (0, 0); for (int i = firstRow + getNumRowsOnScreen() + 2; --i >= firstRow;) - if (RowComp* const rowComp = dynamic_cast (getComponentForRowNumber (i))) + if (RowComp* const rowComp = dynamic_cast (getComponentForRowNumber (i))) rowComp->resized(); } @@ -465,7 +460,7 @@ void TableListBoxModel::deleteKeyPressed (int) {} void TableListBoxModel::returnKeyPressed (int) {} void TableListBoxModel::listWasScrolled() {} -String TableListBoxModel::getCellTooltip (int /*rowNumber*/, int /*columnId*/) { return String::empty; } +String TableListBoxModel::getCellTooltip (int /*rowNumber*/, int /*columnId*/) { return String(); } var TableListBoxModel::getDragSourceDescription (const SparseSet&) { return var(); } Component* TableListBoxModel::refreshComponentForCell (int, int, bool, Component* existingComponentToUpdate) diff --git a/JuceLibraryCode/modules/juce_gui_basics/widgets/juce_TableListBox.h b/JuceLibraryCode/modules/juce_gui_basics/widgets/juce_TableListBox.h index 19096ae..d631125 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/widgets/juce_TableListBox.h +++ b/JuceLibraryCode/modules/juce_gui_basics/widgets/juce_TableListBox.h @@ -57,7 +57,7 @@ public: The graphics context has its origin at the row's top-left, and your method should fill the area specified by the width and height parameters. */ - virtual void paintRowBackground (Graphics& g, + virtual void paintRowBackground (Graphics&, int rowNumber, int width, int height, bool rowIsSelected) = 0; @@ -66,8 +66,11 @@ public: The graphics context's origin will already be set to the top-left of the cell, whose size is specified by (width, height). + + Note that the rowNumber value may be greater than the number of rows in your + list, so be careful that you don't assume it's less than getNumRows(). */ - virtual void paintCell (Graphics& g, + virtual void paintCell (Graphics&, int rowNumber, int columnId, int width, int height, @@ -142,25 +145,21 @@ public: */ virtual int getColumnAutoSizeWidth (int columnId); - /** Returns a tooltip for a particular cell in the table. - */ + /** Returns a tooltip for a particular cell in the table. */ virtual String getCellTooltip (int rowNumber, int columnId); //============================================================================== /** Override this to be informed when rows are selected or deselected. - @see ListBox::selectedRowsChanged() */ virtual void selectedRowsChanged (int lastRowSelected); /** Override this to be informed when the delete key is pressed. - @see ListBox::deleteKeyPressed() */ virtual void deleteKeyPressed (int lastRowSelected); /** Override this to be informed when the return key is pressed. - @see ListBox::returnKeyPressed() */ virtual void returnKeyPressed (int lastRowSelected); @@ -210,29 +209,34 @@ public: /** Creates a TableListBox. The model pointer passed-in can be null, in which case you can set it later - with setModel(). + with setModel(). The TableListBox does not take ownership of the model - it's + the caller's responsibility to manage its lifetime and make sure it + doesn't get deleted while still being used. */ - TableListBox (const String& componentName = String::empty, - TableListBoxModel* model = 0); + TableListBox (const String& componentName = String(), + TableListBoxModel* model = nullptr); /** Destructor. */ ~TableListBox(); //============================================================================== /** Changes the TableListBoxModel that is being used for this table. + The TableListBox does not take ownership of the model - it's the caller's responsibility + to manage its lifetime and make sure it doesn't get deleted while still being used. */ void setModel (TableListBoxModel* newModel); /** Returns the model currently in use. */ - TableListBoxModel* getModel() const { return model; } + TableListBoxModel* getModel() const noexcept { return model; } //============================================================================== /** Returns the header component being used in this table. */ - TableHeaderComponent& getHeader() const { return *header; } + TableHeaderComponent& getHeader() const noexcept { return *header; } /** Sets the header component to use for the table. The table will take ownership of the component that you pass in, and will delete it when it's no longer needed. + The pointer passed in may not be null. */ void setHeader (TableHeaderComponent* newHeader); @@ -244,7 +248,7 @@ public: /** Returns the height of the table header. @see setHeaderHeight */ - int getHeaderHeight() const; + int getHeaderHeight() const noexcept; //============================================================================== /** Resizes a column to fit its contents. @@ -260,15 +264,14 @@ public: void autoSizeAllColumns(); /** Enables or disables the auto size options on the popup menu. - By default, these are enabled. */ - void setAutoSizeMenuOptionShown (bool shouldBeShown); + void setAutoSizeMenuOptionShown (bool shouldBeShown) noexcept; /** True if the auto-size options should be shown on the menu. - @see setAutoSizeMenuOptionsShown + @see setAutoSizeMenuOptionShown */ - bool isAutoSizeMenuOptionShown() const; + bool isAutoSizeMenuOptionShown() const noexcept { return autoSizeOptionsShown; } /** Returns the position of one of the cells in the table. diff --git a/JuceLibraryCode/modules/juce_gui_basics/widgets/juce_Toolbar.cpp b/JuceLibraryCode/modules/juce_gui_basics/widgets/juce_Toolbar.cpp index fc7b4a2..9b2b7cb 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/widgets/juce_Toolbar.cpp +++ b/JuceLibraryCode/modules/juce_gui_basics/widgets/juce_Toolbar.cpp @@ -591,8 +591,8 @@ void Toolbar::itemDragMove (const SourceDetails& dragSourceDetails) { const Rectangle previousPos (animator.getComponentDestination (prev)); - if (abs (dragObjectLeft - (vertical ? previousPos.getY() : previousPos.getX()) - < abs (dragObjectRight - (vertical ? current.getBottom() : current.getRight())))) + if (std::abs (dragObjectLeft - (vertical ? previousPos.getY() : previousPos.getX())) + < std::abs (dragObjectRight - (vertical ? current.getBottom() : current.getRight()))) { newIndex = getIndexOfChildComponent (prev); } @@ -602,8 +602,8 @@ void Toolbar::itemDragMove (const SourceDetails& dragSourceDetails) { const Rectangle nextPos (animator.getComponentDestination (next)); - if (abs (dragObjectLeft - (vertical ? current.getY() : current.getX()) - > abs (dragObjectRight - (vertical ? nextPos.getBottom() : nextPos.getRight())))) + if (std::abs (dragObjectLeft - (vertical ? current.getY() : current.getX())) + > std::abs (dragObjectRight - (vertical ? nextPos.getBottom() : nextPos.getRight()))) { newIndex = getIndexOfChildComponent (next) + 1; } diff --git a/JuceLibraryCode/modules/juce_gui_basics/widgets/juce_TreeView.cpp b/JuceLibraryCode/modules/juce_gui_basics/widgets/juce_TreeView.cpp index c7bb76e..9360000 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/widgets/juce_TreeView.cpp +++ b/JuceLibraryCode/modules/juce_gui_basics/widgets/juce_TreeView.cpp @@ -1773,6 +1773,11 @@ TreeViewItem* TreeViewItem::getNextVisibleItem (const bool recurse) const noexce return nullptr; } +static String escapeSlashesInTreeViewItemName (const String& s) +{ + return s.replaceCharacter ('/', '\\'); +} + String TreeViewItem::getItemIdentifierString() const { String s; @@ -1780,12 +1785,12 @@ String TreeViewItem::getItemIdentifierString() const if (parentItem != nullptr) s = parentItem->getItemIdentifierString(); - return s + "/" + getUniqueName().replaceCharacter ('/', '\\'); + return s + "/" + escapeSlashesInTreeViewItemName (getUniqueName()); } TreeViewItem* TreeViewItem::findItemFromIdentifierString (const String& identifierString) { - const String thisId ("/" + getUniqueName()); + const String thisId ("/" + escapeSlashesInTreeViewItemName (getUniqueName())); if (thisId == identifierString) return this; diff --git a/JuceLibraryCode/modules/juce_gui_basics/windows/juce_AlertWindow.cpp b/JuceLibraryCode/modules/juce_gui_basics/windows/juce_AlertWindow.cpp index d9741fb..1ce0ae6 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/windows/juce_AlertWindow.cpp +++ b/JuceLibraryCode/modules/juce_gui_basics/windows/juce_AlertWindow.cpp @@ -404,7 +404,7 @@ void AlertWindow::updateLayout (const bool onlyIncreaseSize) for (int i = textBlocks.size(); --i >= 0;) { - const AlertTextComp* const ac = static_cast (textBlocks.getUnchecked(i)); + const AlertTextComp* const ac = static_cast (textBlocks.getUnchecked(i)); w = jmax (w, ac->getPreferredWidth()); } @@ -412,7 +412,7 @@ void AlertWindow::updateLayout (const bool onlyIncreaseSize) for (int i = textBlocks.size(); --i >= 0;) { - AlertTextComp* const ac = static_cast (textBlocks.getUnchecked(i)); + AlertTextComp* const ac = static_cast (textBlocks.getUnchecked(i)); ac->updateLayout ((int) (w * 0.8f)); h += ac->getHeight() + 10; } @@ -470,11 +470,11 @@ void AlertWindow::updateLayout (const bool onlyIncreaseSize) Component* const c = allComps.getUnchecked(i); h = 22; - const int comboIndex = comboBoxes.indexOf (dynamic_cast (c)); + const int comboIndex = comboBoxes.indexOf (dynamic_cast (c)); if (comboIndex >= 0 && comboBoxNames [comboIndex].isNotEmpty()) y += labelHeight; - const int tbIndex = textBoxes.indexOf (dynamic_cast (c)); + const int tbIndex = textBoxes.indexOf (dynamic_cast (c)); if (tbIndex >= 0 && textboxNames[tbIndex].isNotEmpty()) y += labelHeight; @@ -536,7 +536,8 @@ bool AlertWindow::keyPressed (const KeyPress& key) exitModalState (0); return true; } - else if (key.isKeyCode (KeyPress::returnKey) && buttons.size() == 1) + + if (key.isKeyCode (KeyPress::returnKey) && buttons.size() == 1) { buttons.getUnchecked(0)->triggerClick(); return true; @@ -592,8 +593,8 @@ private: LookAndFeel& lf = associatedComponent != nullptr ? associatedComponent->getLookAndFeel() : LookAndFeel::getDefaultLookAndFeel(); - ScopedPointer alertBox (lf.createAlertWindow (title, message, button1, button2, button3, - iconType, numButtons, associatedComponent)); + ScopedPointer alertBox (lf.createAlertWindow (title, message, button1, button2, button3, + iconType, numButtons, associatedComponent)); jassert (alertBox != nullptr); // you have to return one of these! @@ -614,7 +615,7 @@ private: static void* showCallback (void* userData) { - static_cast (userData)->show(); + static_cast (userData)->show(); return nullptr; } }; diff --git a/JuceLibraryCode/modules/juce_gui_basics/windows/juce_DialogWindow.h b/JuceLibraryCode/modules/juce_gui_basics/windows/juce_DialogWindow.h index 11e0697..01cbec1 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/windows/juce_DialogWindow.h +++ b/JuceLibraryCode/modules/juce_gui_basics/windows/juce_DialogWindow.h @@ -78,7 +78,7 @@ public: initialise its fields with the appropriate details, and then call its launchAsync() method to launch the dialog. */ - struct LaunchOptions + struct JUCE_API LaunchOptions { LaunchOptions() noexcept; diff --git a/JuceLibraryCode/modules/juce_gui_basics/windows/juce_TopLevelWindow.h b/JuceLibraryCode/modules/juce_gui_basics/windows/juce_TopLevelWindow.h index b982230..ce1b104 100644 --- a/JuceLibraryCode/modules/juce_gui_basics/windows/juce_TopLevelWindow.h +++ b/JuceLibraryCode/modules/juce_gui_basics/windows/juce_TopLevelWindow.h @@ -127,7 +127,7 @@ public: //============================================================================== /** @internal */ - virtual void addToDesktop (int windowStyleFlags, void* nativeWindowToAttachTo = nullptr) override; + void addToDesktop (int windowStyleFlags, void* nativeWindowToAttachTo = nullptr) override; protected: //============================================================================== diff --git a/JuceLibraryCode/modules/juce_gui_extra/code_editor/juce_CodeDocument.cpp b/JuceLibraryCode/modules/juce_gui_extra/code_editor/juce_CodeDocument.cpp index a52a20d..397b9f9 100644 --- a/JuceLibraryCode/modules/juce_gui_extra/code_editor/juce_CodeDocument.cpp +++ b/JuceLibraryCode/modules/juce_gui_extra/code_editor/juce_CodeDocument.cpp @@ -102,9 +102,7 @@ public: lineLength = 0; lineLengthWithoutNewLines = 0; - String::CharPointerType t (line.getCharPointer()); - - for (;;) + for (String::CharPointerType t (line.getCharPointer());;) { const juce_wchar c = t.getAndAdvance(); @@ -242,16 +240,16 @@ CodeDocument::Position::Position() noexcept } CodeDocument::Position::Position (const CodeDocument& ownerDocument, - const int line_, const int indexInLine_) noexcept - : owner (const_cast (&ownerDocument)), - characterPos (0), line (line_), - indexInLine (indexInLine_), positionMaintained (false) + const int lineNum, const int index) noexcept + : owner (const_cast (&ownerDocument)), + characterPos (0), line (lineNum), + indexInLine (index), positionMaintained (false) { - setLineAndIndex (line_, indexInLine_); + setLineAndIndex (lineNum, index); } CodeDocument::Position::Position (const CodeDocument& ownerDocument, const int characterPos_) noexcept - : owner (const_cast (&ownerDocument)), + : owner (const_cast (&ownerDocument)), positionMaintained (false) { setPosition (characterPos_); @@ -858,7 +856,7 @@ void CodeDocument::insert (const String& text, const int insertPos, const bool u } maximumLineLength = -1; - Array newLines; + Array newLines; CodeDocumentLine::createLines (newLines, textInsideOriginalLine); jassert (newLines.size() > 0); diff --git a/JuceLibraryCode/modules/juce_gui_extra/code_editor/juce_CodeEditorComponent.cpp b/JuceLibraryCode/modules/juce_gui_extra/code_editor/juce_CodeEditorComponent.cpp index b622452..b2f2673 100644 --- a/JuceLibraryCode/modules/juce_gui_extra/code_editor/juce_CodeEditorComponent.cpp +++ b/JuceLibraryCode/modules/juce_gui_extra/code_editor/juce_CodeEditorComponent.cpp @@ -35,7 +35,7 @@ public: const CodeDocument::Position& selStart, const CodeDocument::Position& selEnd) { - Array newTokens; + Array newTokens; newTokens.ensureStorageAllocated (8); if (tokeniser == nullptr) @@ -129,13 +129,13 @@ private: int tokenType; }; - Array tokens; + Array tokens; int highlightColumnStart, highlightColumnEnd; static void createTokens (int startPosition, const String& lineText, CodeDocument::Iterator& source, CodeTokeniser& tokeniser, - Array & newTokens) + Array& newTokens) { CodeDocument::Iterator lastIterator (source); const int lineLength = lineText.length(); @@ -168,7 +168,7 @@ private: source = lastIterator; } - static void replaceTabsWithSpaces (Array & tokens, const int spacesPerTab) + static void replaceTabsWithSpaces (Array& tokens, const int spacesPerTab) { int x = 0; for (int i = 0; i < tokens.size(); ++i) @@ -287,8 +287,8 @@ public: void paint (Graphics& g) override { - jassert (dynamic_cast (getParentComponent()) != nullptr); - const CodeEditorComponent& editor = *static_cast (getParentComponent()); + jassert (dynamic_cast (getParentComponent()) != nullptr); + const CodeEditorComponent& editor = *static_cast (getParentComponent()); g.fillAll (editor.findColour (CodeEditorComponent::backgroundColourId) .overlaidWith (editor.findColour (lineNumberBackgroundId))); @@ -412,7 +412,7 @@ bool CodeEditorComponent::isTextInputActive() const return true; } -void CodeEditorComponent::setTemporaryUnderlining (const Array >&) +void CodeEditorComponent::setTemporaryUnderlining (const Array >&) { jassertfalse; // TODO Windows IME not yet supported for this comp.. } @@ -1235,7 +1235,7 @@ ApplicationCommandTarget* CodeEditorComponent::getNextCommandTarget() return findFirstTargetParentComponent(); } -void CodeEditorComponent::getAllCommands (Array & commands) +void CodeEditorComponent::getAllCommands (Array& commands) { const CommandID ids[] = { StandardApplicationCommandIDs::cut, StandardApplicationCommandIDs::copy, @@ -1569,7 +1569,7 @@ void CodeEditorComponent::updateCachedIterators (int maxLineNum) CodeDocument::Iterator* t = new CodeDocument::Iterator (last); cachedIterators.add (t); - const int targetLine = last.getLine() + linesBetweenCachedSources; + const int targetLine = jmin (maxLineNum, last.getLine() + linesBetweenCachedSources); for (;;) { diff --git a/JuceLibraryCode/modules/juce_gui_extra/juce_gui_extra.cpp b/JuceLibraryCode/modules/juce_gui_extra/juce_gui_extra.cpp index a9fab23..4b80cc2 100644 --- a/JuceLibraryCode/modules/juce_gui_extra/juce_gui_extra.cpp +++ b/JuceLibraryCode/modules/juce_gui_extra/juce_gui_extra.cpp @@ -40,17 +40,12 @@ //============================================================================== #if JUCE_MAC - #define Point CarbonDummyPointName - #define Component CarbonDummyCompName #import #import #import #import #import #import - #import // still needed for SetSystemUIMode() - #undef Point - #undef Component #elif JUCE_IOS diff --git a/JuceLibraryCode/modules/juce_gui_extra/misc/juce_ColourSelector.h b/JuceLibraryCode/modules/juce_gui_extra/misc/juce_ColourSelector.h index 2e256bd..d16700c 100644 --- a/JuceLibraryCode/modules/juce_gui_extra/misc/juce_ColourSelector.h +++ b/JuceLibraryCode/modules/juce_gui_extra/misc/juce_ColourSelector.h @@ -145,7 +145,7 @@ private: ScopedPointer sliders[4]; ScopedPointer colourSpace; ScopedPointer hueSelector; - OwnedArray swatchComponents; + OwnedArray swatchComponents; const int flags; int edgeGap; Rectangle previewArea; diff --git a/JuceLibraryCode/modules/juce_gui_extra/native/juce_win32_WebBrowserComponent.cpp b/JuceLibraryCode/modules/juce_gui_extra/native/juce_win32_WebBrowserComponent.cpp index fdc6be7..273d790 100644 --- a/JuceLibraryCode/modules/juce_gui_extra/native/juce_win32_WebBrowserComponent.cpp +++ b/JuceLibraryCode/modules/juce_gui_extra/native/juce_win32_WebBrowserComponent.cpp @@ -226,6 +226,9 @@ void WebBrowserComponent::goToURL (const String& url, blankPageShown = false; + if (browser->browser == nullptr) + checkWindowAssociation(); + browser->goToURL (url, headers, postData); } @@ -262,7 +265,10 @@ void WebBrowserComponent::refresh() void WebBrowserComponent::paint (Graphics& g) { if (browser->browser == nullptr) + { g.fillAll (Colours::white); + checkWindowAssociation(); + } } void WebBrowserComponent::checkWindowAssociation() diff --git a/JuceLibraryCode/modules/juce_opengl/juce_opengl.h b/JuceLibraryCode/modules/juce_opengl/juce_opengl.h index 8a01f5d..bfeb599 100644 --- a/JuceLibraryCode/modules/juce_opengl/juce_opengl.h +++ b/JuceLibraryCode/modules/juce_opengl/juce_opengl.h @@ -63,17 +63,35 @@ #endif #elif JUCE_MAC #if defined (MAC_OS_X_VERSION_10_7) && (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_7) - #define JUCE_OPENGL3 1 + #define JUCE_OPENGL3 1 #include #include #else #include - #include "OpenGL/glext.h" + #include #endif #elif JUCE_ANDROID #include #endif +#if GL_ES_VERSION_3_0 + #define JUCE_OPENGL3 1 +#endif + +//============================================================================= +/** This macro is a helper for use in GLSL shader code which needs to compile on both OpenGL 2.1 and OpenGL 3.0. + It's mandatory in OpenGL 3.0 to specify the GLSL version. +*/ +#if JUCE_OPENGL3 + #if JUCE_OPENGL_ES + #define JUCE_GLSL_VERSION "#version 300 es" + #else + #define JUCE_GLSL_VERSION "#version 150" + #endif +#else + #define JUCE_GLSL_VERSION "" +#endif + //============================================================================= #if JUCE_OPENGL_ES || defined (DOXYGEN) /** This macro is a helper for use in GLSL shader code which needs to compile on both GLES and desktop GL. diff --git a/JuceLibraryCode/modules/juce_opengl/native/juce_OpenGL_ios.h b/JuceLibraryCode/modules/juce_opengl/native/juce_OpenGL_ios.h index 024de7d..93daac9 100644 --- a/JuceLibraryCode/modules/juce_opengl/native/juce_OpenGL_ios.h +++ b/JuceLibraryCode/modules/juce_opengl/native/juce_OpenGL_ios.h @@ -118,7 +118,7 @@ public: bool createdOk() const noexcept { return getRawContext() != nullptr; } void* getRawContext() const noexcept { return context; } - GLuint getFrameBufferID() const noexcept { return frameBufferHandle; } + GLuint getFrameBufferID() const noexcept { return useMSAA ? msaaBufferHandle : frameBufferHandle; } bool makeActive() const noexcept { @@ -142,6 +142,18 @@ public: void swapBuffers() { + if (useMSAA) + { + glBindFramebuffer (GL_DRAW_FRAMEBUFFER, frameBufferHandle); + glBindFramebuffer (GL_READ_FRAMEBUFFER, msaaBufferHandle); + + #if defined (__IPHONE_7_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_7_0 + glBlitFramebuffer (0, 0, lastWidth, lastHeight, 0, 0, lastWidth, lastHeight, GL_COLOR_BUFFER_BIT, GL_NEAREST); + #else + glResolveMultisampleFramebufferAPPLE(); + #endif + } + glBindRenderbuffer (GL_RENDERBUFFER, colorBufferHandle); [context presentRenderbuffer: GL_RENDERBUFFER]; @@ -189,7 +201,7 @@ private: int swapFrames; bool useDepthBuffer, useMSAA; - bool createContext (NSUInteger type, void* contextToShare) + bool createContext (EAGLRenderingAPI type, void* contextToShare) { jassert (context == nil); context = [EAGLContext alloc]; @@ -233,7 +245,7 @@ private: glBindFramebuffer (GL_FRAMEBUFFER, msaaBufferHandle); glBindRenderbuffer (GL_RENDERBUFFER, msaaColorHandle); - glRenderbufferStorageMultisampleAPPLE (GL_RENDERBUFFER, 4, GL_RGBA8_OES, width, height); + glRenderbufferStorageMultisample (GL_RENDERBUFFER, 4, GL_RGBA8, width, height); glFramebufferRenderbuffer (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, msaaColorHandle); } @@ -244,7 +256,7 @@ private: glBindRenderbuffer (GL_RENDERBUFFER, depthBufferHandle); if (useMSAA) - glRenderbufferStorageMultisampleAPPLE (GL_RENDERBUFFER, 4, GL_DEPTH_COMPONENT16, width, height); + glRenderbufferStorageMultisample (GL_RENDERBUFFER, 4, GL_DEPTH_COMPONENT16, width, height); else glRenderbufferStorage (GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, width, height); diff --git a/JuceLibraryCode/modules/juce_opengl/native/juce_OpenGL_win32.h b/JuceLibraryCode/modules/juce_opengl/native/juce_OpenGL_win32.h index c0999d0..5e38430 100644 --- a/JuceLibraryCode/modules/juce_opengl/native/juce_OpenGL_win32.h +++ b/JuceLibraryCode/modules/juce_opengl/native/juce_OpenGL_win32.h @@ -22,7 +22,7 @@ ============================================================================== */ -extern ComponentPeer* createNonRepaintingEmbeddedWindowsPeer (Component*, void* parent); +extern ComponentPeer* createNonRepaintingEmbeddedWindowsPeer (Component&, void* parent); //============================================================================== class OpenGLContext::NativeContext @@ -33,7 +33,9 @@ public: void* contextToShareWith, bool /*useMultisampling*/, OpenGLVersion) + : context (nullptr) { + dummyComponent = new DummyComponent (*this); createNativeWindow (component); PIXELFORMATDESCRIPTOR pfd; @@ -82,8 +84,8 @@ public: releaseDC(); } - void initialiseOnRenderThread (OpenGLContext&) {} - void shutdownOnRenderThread() { deactivateCurrentContext(); } + void initialiseOnRenderThread (OpenGLContext& c) { context = &c; } + void shutdownOnRenderThread() { deactivateCurrentContext(); context = nullptr; } static void deactivateCurrentContext() { wglMakeCurrent (0, 0); } bool makeActive() const noexcept { return isActive() || wglMakeCurrent (dc, renderContext) != FALSE; } @@ -114,13 +116,30 @@ public: void* getRawContext() const noexcept { return renderContext; } unsigned int getFrameBufferID() const noexcept { return 0; } + void triggerRepaint() + { + if (context != nullptr) + context->triggerRepaint(); + } + struct Locker { Locker (NativeContext&) {} }; private: - Component dummyComponent; + struct DummyComponent : public Component + { + DummyComponent (NativeContext& c) : context (c) {} + + // The windowing code will call this when a paint callback happens + void handleCommandMessage (int) override { context.triggerRepaint(); } + + NativeContext& context; + }; + + ScopedPointer dummyComponent; ScopedPointer nativeWindow; HGLRC renderContext; HDC dc; + OpenGLContext* context; #define JUCE_DECLARE_WGL_EXTENSION_FUNCTION(name, returnType, params) \ typedef returnType (__stdcall *type_ ## name) params; type_ ## name name; @@ -142,7 +161,7 @@ private: void createNativeWindow (Component& component) { Component* topComp = component.getTopLevelComponent(); - nativeWindow = createNonRepaintingEmbeddedWindowsPeer (&dummyComponent, topComp->getWindowHandle()); + nativeWindow = createNonRepaintingEmbeddedWindowsPeer (*dummyComponent, topComp->getWindowHandle()); if (ComponentPeer* peer = topComp->getPeer()) updateWindowPosition (peer->getAreaCoveredBy (component)); diff --git a/JuceLibraryCode/modules/juce_opengl/opengl/juce_OpenGLHelpers.cpp b/JuceLibraryCode/modules/juce_opengl/opengl/juce_OpenGLHelpers.cpp index 869f77e..4988318 100644 --- a/JuceLibraryCode/modules/juce_opengl/opengl/juce_OpenGLHelpers.cpp +++ b/JuceLibraryCode/modules/juce_opengl/opengl/juce_OpenGLHelpers.cpp @@ -81,8 +81,8 @@ String OpenGLHelpers::translateVertexShaderToV3 (const String& code) { #if JUCE_OPENGL3 if (OpenGLShaderProgram::getLanguageVersion() > 1.2) - return "#version 150\n" + code.replace ("attribute", "in") - .replace ("varying", "out"); + return JUCE_GLSL_VERSION "\n" + code.replace ("attribute", "in") + .replace ("varying", "out"); #endif return code; @@ -92,7 +92,7 @@ String OpenGLHelpers::translateFragmentShaderToV3 (const String& code) { #if JUCE_OPENGL3 if (OpenGLShaderProgram::getLanguageVersion() > 1.2) - return "#version 150\n" + return JUCE_GLSL_VERSION "\n" "out vec4 fragColor;\n" + code.replace ("varying", "in") .replace ("texture2D", "texture") diff --git a/JuceLibraryCode/modules/juce_video/native/juce_win32_DirectShowComponent.cpp b/JuceLibraryCode/modules/juce_video/native/juce_win32_DirectShowComponent.cpp index 7142bc6..5762459 100644 --- a/JuceLibraryCode/modules/juce_video/native/juce_win32_DirectShowComponent.cpp +++ b/JuceLibraryCode/modules/juce_video/native/juce_win32_DirectShowComponent.cpp @@ -359,6 +359,9 @@ public: return true; } + // Note that if you're trying to open a file and this method fails, you may + // just need to install a suitable codec. It seems that by default DirectShow + // doesn't support a very good range of formats. release(); return false; } diff --git a/RBM.jucer b/RBM.jucer index 7d05cdc..e022114 100644 --- a/RBM.jucer +++ b/RBM.jucer @@ -25,21 +25,44 @@ targetName="RBM"/> - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/DrawComponent.cpp b/Source/DrawComponent.cpp index 0b06103..6cbca49 100644 --- a/Source/DrawComponent.cpp +++ b/Source/DrawComponent.cpp @@ -18,8 +18,8 @@ */ //[Headers] You can add your own extra header files here... -#include #include "noise.h" +void mylog(const char* format, ...); //[/Headers] #include "DrawComponent.h" @@ -29,14 +29,16 @@ //[/MiscUserDefs] //============================================================================== -DrawComponent::DrawComponent (int width, int height, int scale) +DrawComponent::DrawComponent (int width, int height) { //[UserPreSize] noise_gen_t noise; m_width = width; m_height = height; - m_scale = scale; + m_scaleX = 1.0; + m_scaleY = 1.0; + m_pG = nullptr; //[/UserPreSize] @@ -44,21 +46,11 @@ DrawComponent::DrawComponent (int width, int height, int scale) //[Constructor] You can add your own custom stuff here.. - m_pImage = new Image(Image::RGB , scale*width, scale*height, true); - m_pG = new Graphics(*m_pImage); - setSize (scale*width, scale*height); +// m_pG = new Graphics(m_image); m_pData = new double[width*height]; - + memset(m_pData, 0, m_width*m_height*sizeof(double)); Noise_Init(&noise, 0x3231); - double *pData = m_pData; - for (int i=0; i < width; i++) - { - for (int j=0; j < height; j++) - { - *(pData++) = Noise_Gaussian(&noise, 0.5, 0.3); - } - } m_pG->setImageResamplingQuality(Graphics::lowResamplingQuality); //[/Constructor] } @@ -71,7 +63,6 @@ DrawComponent::~DrawComponent() //[Destructor]. You can add your own custom destruction code here.. - m_pImage = nullptr; m_pG = nullptr; m_pData = nullptr; //[/Destructor] @@ -83,7 +74,7 @@ void DrawComponent::paint (Graphics& g) //[UserPrePaint] Add your own custom painting code here.. AffineTransform t; - g.drawImage(*m_pImage, 0, 0, getWidth(), getHeight(), 0, 0, getWidth(), getHeight(), false); + g.drawImage(m_image, 0, 0, getWidth(), getHeight(), 0, 0, getWidth(), getHeight(), false); // g.drawImageTransformed(*m_pImage, t.rotated(8), false); return; //[/UserPrePaint] @@ -97,7 +88,13 @@ void DrawComponent::paint (Graphics& g) void DrawComponent::resized() { //[UserResized] Add your own custom resize handling here.. - printf("%s (%d,%d)\n", __func__, getWidth(), getHeight()); +// mylog("%s (%d,%d)\n", __func__, getWidth(), getHeight()); + m_scaleX = (float)getWidth()/m_width; + m_scaleY = (float)getHeight()/m_height; + m_image = Image(Image::RGB , getWidth(), getHeight(), true); + m_pG = nullptr; + m_pG = new Graphics(m_image); + repaint(); //[/UserResized] } @@ -105,101 +102,124 @@ void DrawComponent::resized() void DrawComponent::mouseMove (const MouseEvent& e) { //[UserCode_mouseMove] -- Add your code here... - printf("%s\n", __func__); +// mylogMessage(String("MouseMove")); //[/UserCode_mouseMove] } void DrawComponent::mouseEnter (const MouseEvent& e) { //[UserCode_mouseEnter] -- Add your code here... - printf("%s\n", __func__); +// mylog("%s\n", __func__); //[/UserCode_mouseEnter] } void DrawComponent::mouseExit (const MouseEvent& e) { //[UserCode_mouseExit] -- Add your code here... - printf("%s\n", __func__); +// mylog("%s\n", __func__); //[/UserCode_mouseExit] } void DrawComponent::mouseDown (const MouseEvent& e) { //[UserCode_mouseDown] -- Add your code here... - printf("%s\n", __func__); - m_pG->setColour (Colours::black); - m_pG->fillAll(); - repaint(); +// mylog("%s x:%d, y:%d\n", __func__, e.x, e.y); + if (e.mods.isRightButtonDown()) + { + clear(); + } + else + { + drawAt(e.x, e.y); + } //[/UserCode_mouseDown] } void DrawComponent::mouseDrag (const MouseEvent& e) { //[UserCode_mouseDrag] -- Add your code here... - int x, y; - x = e.x; - y = e.y; - - printf("%s x:%d, y:%d\n", __func__, x, y); - m_pG->setColour (Colours::white); - m_pG->fillRect(x, y, 5, 5); - repaint(); +// mylog("%s x:%d, y:%d\n", __func__, e.x, e.y); + if (e.mods.isLeftButtonDown()) + { + drawAt(e.x, e.y); + } //[/UserCode_mouseDrag] } void DrawComponent::mouseUp (const MouseEvent& e) { //[UserCode_mouseUp] -- Add your code here... - printf("%s\n", __func__); +// mylog("%s\n", __func__); //[/UserCode_mouseUp] } void DrawComponent::mouseDoubleClick (const MouseEvent& e) { //[UserCode_mouseDoubleClick] -- Add your code here... - printf("%s\n", __func__); +// mylog("%s\n", __func__); //[/UserCode_mouseDoubleClick] } void DrawComponent::mouseWheelMove (const MouseEvent& e, const MouseWheelDetails& wheel) { //[UserCode_mouseWheelMove] -- Add your code here... - printf("%s\n", __func__); +// mylog("%s\n", __func__); //[/UserCode_mouseWheelMove] } //[MiscUserCode] You can add your own definitions of your custom methods or any other code here... -void DrawComponent::drawGray (const double *pData) +void DrawComponent::drawAt(int x, int y) +{ + int index; + double fx = (double)x / m_scaleX; + double fy = (double)y / m_scaleY; + + index = (int)(x/m_scaleX) + m_width*(int)(y/m_scaleY); +// mylog("Write(%d)\n", index); + + if (index >= 0) + if (index < m_width*m_height) + m_pData[index] = 1.0; + + x = (int)fx * m_scaleX; + y = (int)fy * m_scaleY; + m_pG->setColour (Colours::white); + m_pG->fillRect((float)x, (float)y, m_scaleX, m_scaleY); + repaint(); +} + +void DrawComponent::clear() +{ + double *pData = m_pData; + for (int i=0; i < m_width*m_height; i++) + { + *(pData++) = 0; + } + setData(m_pData); +} + +const double* DrawComponent::getData () +{ + return m_pData; +} + +void DrawComponent::setData (const double *pData) { double a; - double min = +1E12; - double max = -1E12; - for (int i=0; i < m_width*m_height; i++) + for (int i=0; i < m_width*m_height; i++) { m_pData[i] = pData[i]; - min = std::min(min, pData[i]); - max = std::max(max, pData[i]); } - for (int i=0; i < m_width*m_height; i++) + for (int i=0; i < m_height; i++) { - m_pData[i] -= min; - } - for (int i=0; i < m_width*m_height; i++) - { - m_pData[i] /= (max-min); - } - - pData = m_pData; - for (int i=0; i < m_width; i++) - { - for (int j=0; j < m_height; j++) + for (int j=0; j < m_width; j++) { a = std::min(std::max(*pData, 0), 1); m_pG->setColour(Colour(Colours::white).greyLevel(a)); - m_pG->fillRect(m_scale*i, m_scale*j, m_scale, m_scale); + m_pG->fillRect(m_scaleX*j, m_scaleY*i, m_scaleX, m_scaleY); pData++; } } @@ -218,7 +238,7 @@ void DrawComponent::drawGray (const double *pData) BEGIN_JUCER_METADATA diff --git a/Source/DrawComponent.h b/Source/DrawComponent.h index 7357108..c37e75d 100644 --- a/Source/DrawComponent.h +++ b/Source/DrawComponent.h @@ -38,12 +38,15 @@ class DrawComponent : public Component { public: //============================================================================== - DrawComponent (int width, int height, int scale); + DrawComponent (int width, int height); ~DrawComponent(); //============================================================================== //[UserMethods] -- You can add your own custom methods in this section. - void drawGray(const double *pData); + void drawAt(int x, int y); + void setData(const double *pData); + const double* getData(); + void clear(); //[/UserMethods] void paint (Graphics& g); @@ -63,10 +66,11 @@ private: //[UserVariables] -- You can add your own custom variables in this section. int m_width; int m_height; - int m_scale; - ScopedPointerm_pImage; + float m_scaleX; + float m_scaleY; ScopedPointerm_pG; ScopedPointerm_pData; + Image m_image; //[/UserVariables] //============================================================================== diff --git a/Source/HiddenLayer.hpp b/Source/HiddenLayer.hpp new file mode 100644 index 0000000..29bc182 --- /dev/null +++ b/Source/HiddenLayer.hpp @@ -0,0 +1,54 @@ +/* + * HiddenLayer.hpp + * + * Created on: 21.09.2014 + * Author: jens + */ + +#ifndef HIDDENLAYER_HPP_ +#define HIDDENLAYER_HPP_ + +#include "Layer.hpp" +#include + +class HiddenLayer : public Layer +{ +public: + HiddenLayer(uint32_t numUnits = 0, const double *pStatesInit = nullptr) + : Layer(numUnits, pStatesInit) + { + } + + virtual ~HiddenLayer() + { + } + + double getEnergy(const Weights &weights) + { + uint32_t i; + double energy = 0; + + for (i=0; i < getNumUnits(); i++) + { + energy -= weights.getBiasHidden()[i] * getStates()[i]; + } + return energy; + } + +private: + double accum(const Layer &layer, const Weights &weights, uint32_t index) const + { + uint32_t i; + double sum = weights.getBiasVisible()[index]; + const double *pStates = layer.getStates(); + + for (i=0; i < layer.getNumUnits(); i++) + { + sum += pStates[i] * weights.getWeights()[index][i]; + } + + return sum; + } +}; + +#endif /* HIDDENLAYER_HPP_ */ diff --git a/Source/Layer.hpp b/Source/Layer.hpp index 0756e0c..5ed934b 100644 --- a/Source/Layer.hpp +++ b/Source/Layer.hpp @@ -10,165 +10,18 @@ #ifndef LAYER_HPP #define LAYER_HPP - +#include #include "noise.h" - -class Weights -{ -public: - Weights(uint32_t numVisible, uint32_t numHidden) - : m_ppW(nullptr) - , m_pBiasVisible(nullptr) - , m_pBiasHidden(nullptr) - , m_numVisible(numVisible) - , m_numHidden(numHidden) - { - alloc(); - Noise_Init(&m_noise, 0x32727155); - - shuffle(0); - } - - ~Weights() - { - Noise_Free(&m_noise); - free(); - } - - void shuffle(double stdDev) - { - uint32_t i, j; - double kdev = stdDev*sqrt(12.0); - - for (j=0; j < m_numVisible; j++) - { - m_pBiasVisible[j] = kdev*Noise_Uniform(&m_noise, 0.5); - } - - for (i=0; i < m_numHidden; i++) - { - m_pBiasHidden[i] = kdev*Noise_Uniform(&m_noise, 0.5); - } - - for (i=0; i < m_numHidden; i++) - { - for (j=0; j < m_numVisible; j++) - { - m_ppW[i][j] = kdev*Noise_Uniform(&m_noise, 0.5); - } - } - } - - double **getWeights() const - { - return m_ppW; - } - - double *getBiasVisible() const - { - return m_pBiasVisible; - } - - double *getBiasHidden() const - { - return m_pBiasHidden; - } - - void print() - { - uint32_t i, j; - double w; - - printf("\n"); - printf("w(v,h) = (v^, h>)\n"); - for (i=0; i < m_numVisible; i++) - { - for (j=0; j < m_numHidden; j++) - { - w = m_ppW[j][i]; - printf("%3.6f ", w); - } - printf("\n"); - } - printf("\n"); - - printf("bv = \n"); - for (i=0; i < m_numVisible; i++) - { - w = m_pBiasVisible[i]; - printf("%3.6f\n", w); - } - printf("\n"); - - printf("bh = \n"); - for (i=0; i < m_numHidden; i++) - { - w = m_pBiasHidden[i]; - printf("%3.6f\n", w); - } - printf("\n"); - } - -private: - double **m_ppW; - double *m_pBiasVisible; - double *m_pBiasHidden; - uint32_t m_numVisible; - uint32_t m_numHidden; - noise_gen_t m_noise; - - void alloc() - { - uint32_t i; - - if (m_ppW) - { - free(); - alloc(); - } - else - { - m_ppW = new double*[m_numHidden]; - for (i=0; i < m_numHidden; i++) - { - m_ppW[i] = new double[m_numVisible]; - } - m_pBiasVisible = new double[m_numVisible]; - m_pBiasHidden = new double[m_numHidden]; - } - } - - void free() - { - uint32_t i; - - - if (m_ppW) - { - for (i=0; i < m_numHidden; i++) - { - delete [] m_ppW[i]; - } - delete [] m_ppW; - m_ppW = nullptr; - } - - delete [] m_pBiasVisible; - m_pBiasVisible = nullptr; - - delete [] m_pBiasHidden; - m_pBiasHidden = nullptr; - } -}; +#include "Weights.hpp" class Layer { public: - Layer(uint32_t numUnits = 0) + Layer(uint32_t numUnits = 0, const double *pStatesInit = nullptr) : m_numUnits(numUnits) - , m_pInput(nullptr) , m_pProbs(nullptr) , m_pStates(nullptr) + , m_pStatesInit(pStatesInit) { setNumUnits(numUnits); Noise_Init(&m_noise, 0x12345677); @@ -204,6 +57,10 @@ public: { m_pStates[i] = 0.0; } + if (m_pStatesInit) + { + memcpy(m_pStates, m_pStatesInit, m_numUnits*sizeof(double)); + } } } @@ -211,11 +68,8 @@ public: { memcpy(m_pProbs, rhs.m_pProbs, m_numUnits*sizeof(double)); memcpy(m_pStates, rhs.m_pStates, m_numUnits*sizeof(double)); - } - void setInput(const double *pInput) - { - m_pInput = pInput; + return *this; } void probsUpdate(const Layer &layer, const Weights &weights) const @@ -228,14 +82,6 @@ public: } } - void statesAssignfromInput() - { - if (!m_pInput) - return; - - memcpy(m_pStates, m_pInput, m_numUnits*sizeof(double)); - } - void statesAssignfromProbs() { memcpy(m_pStates, m_pProbs, m_numUnits*sizeof(double)); @@ -272,7 +118,6 @@ public: private: uint32_t m_numUnits; - const double *m_pInput; noise_gen_t m_noise; inline double logSigmoid(double x) const @@ -283,6 +128,7 @@ private: protected: double *m_pProbs; double *m_pStates; + const double *m_pStatesInit; virtual double accum(const Layer &layer, const Weights &weights, uint32_t index) const = 0; diff --git a/Source/LayerArray.hpp b/Source/LayerArray.hpp new file mode 100644 index 0000000..4a08128 --- /dev/null +++ b/Source/LayerArray.hpp @@ -0,0 +1,241 @@ +/* + ============================================================================== + + LayerArray.hpp + Created: 21 Sep 2014 1:55:15pm + Author: jens + + ============================================================================== +*/ + +#ifndef LAYERARRAY_HPP +#define LAYERARRAY_HPP +#include +#include "VisibleLayer.hpp" + +class VisibleLayerArray; + +class VisibleLayerArrayListener +{ +public: + VisibleLayerArrayListener() {} + virtual~VisibleLayerArrayListener() {} + + virtual void onChanged(const VisibleLayerArray &obj) = 0; +}; + +class VisibleLayerArray +{ + class Entry : public VisibleLayer + { + public: + Entry(uint32_t numUnits, const double *pInit) + : VisibleLayer(numUnits, pInit) + , pPrev(nullptr) + , pNext(nullptr) + { + } + ~Entry() + { + } + Entry *pPrev; + Entry *pNext; + private: + }; + +public: + VisibleLayerArray(VisibleLayerArrayListener *pListener = nullptr) + : m_size(0) + , m_pRoot(nullptr) + , m_ppIndex(nullptr) + , m_pListener(pListener) + { + } + + virtual ~VisibleLayerArray() + { + clear(); + } + + void add(const double *pData, uint32_t size) + { + Entry *pL = m_pRoot; + + if (!m_pRoot) + { + m_pRoot = new Entry(size, pData); + } + else + { + pL = m_pRoot; + while(pL->pNext) + { + pL = pL->pNext; + } + pL->pNext = new Entry(size, pData); + pL->pNext->pPrev = pL; + } + rebuildIndex(); + if (m_pListener) + m_pListener->onChanged(*this); + } + + void clear() + { +// rebuildIndex(); + if (m_ppIndex) + { + for (int i=0; i < m_size; i++) + { + if (m_ppIndex[i]) + delete m_ppIndex[i]; + + m_ppIndex[i] = nullptr; + } + } + m_ppIndex = nullptr; + m_pRoot = nullptr; + m_size = 0; + allocIndex(0); + if (m_pListener) + m_pListener->onChanged(*this); + } + + VisibleLayer& getAt(uint32_t index) + { + return *m_ppIndex[index]; + } + + void removeAt(uint32_t index) + { + if (m_ppIndex[index]->pPrev) + { + m_ppIndex[index]->pPrev->pNext = m_ppIndex[index]->pNext; + } + else + { + m_pRoot = m_ppIndex[index]->pNext; + m_ppIndex[index]->pNext->pPrev = nullptr; + } + delete m_ppIndex[index]; + m_ppIndex[index] = nullptr; + rebuildIndex(); + if (m_pListener) + m_pListener->onChanged(*this); + } + + uint32_t getSize() const + { + return m_size; + } + + void save(const char *pFilename) + { + FILE *pFile; + + pFile = fopen(pFilename,"w"); + + if (!pFile) + return; + + + fprintf(pFile, "%d\n", m_size); + + uint32_t i, j; + + for (i=0; i < m_size; i++) + { + uint32_t numUnits = ((VisibleLayer*)m_ppIndex[i])->getNumUnits(); + fprintf(pFile, "%d\n", numUnits); + + for (j=0; j < numUnits; j++) + { + fprintf(pFile, "%3.6f\n", ((VisibleLayer*)m_ppIndex[i])->getStates()[j]); + } + } + + fclose(pFile); + } + + void load(const char *pFilename) + { + uint32_t size = 0; + FILE *pFile; + + pFile = fopen(pFilename,"r"); + + if (!pFile) + return; + + fscanf(pFile, "%d\n", &size); + + uint32_t i, j; + float v; + double *pData; + for (i=0; i < size; i++) + { + uint32_t numUnits; + fscanf(pFile, "%d\n", &numUnits); + pData = new double[numUnits]; + + for (j=0; j < numUnits; j++) + { + fscanf(pFile, "%f", &v); + pData[j] = v; + } + add(pData, numUnits); + delete [] pData; + } + + fclose(pFile); + } + +private: + uint32_t m_size; + Entry *m_pRoot; + Entry **m_ppIndex; + VisibleLayerArrayListener *m_pListener; + void allocIndex(size_t size) + { + if (m_ppIndex) + { + delete [] m_ppIndex; + m_ppIndex = nullptr; + allocIndex(size); + } + else + { + if (size) + { + m_ppIndex = new Entry*[size]; + } + } + } + + void rebuildIndex() + { + Entry *pL; + uint32_t size; + + size = 0; + pL = m_pRoot; + while(pL) + { + size++; + pL = pL->pNext; + } + allocIndex(size); + + size = 0; + pL = m_pRoot; + while(pL) + { + m_ppIndex[size++] = pL; + pL = pL->pNext; + } + m_size = size; + + } +}; + +#endif // LAYERARRAY_HPP diff --git a/Source/MainComponent.cpp b/Source/MainComponent.cpp index 5900139..783161c 100644 --- a/Source/MainComponent.cpp +++ b/Source/MainComponent.cpp @@ -18,30 +18,174 @@ */ //[Headers] You can add your own extra header files here... +#include //[/Headers] #include "MainComponent.h" //[MiscUserDefs] You can add your own user definitions and misc code here... +void mylog(const char* format, ...) +{ + char log_buf[257]; + va_list argptr; + va_start(argptr, format); + vsprintf(log_buf, format, argptr); + va_end(argptr); + OutputDebugStringA (log_buf); +} //[/MiscUserDefs] //============================================================================== MainComponent::MainComponent () + : m_layers(this), + m_pRbm(nullptr), + Draw(nullptr), + Draw2(nullptr), + DrawWeights(nullptr) { - addAndMakeVisible (textButton = new TextButton ("new button")); - textButton->addListener (this); + addAndMakeVisible (trainButton = new TextButton ("Train button")); + trainButton->setButtonText (TRANS("Train")); + trainButton->addListener (this); + + addAndMakeVisible (addButton = new TextButton ("Add button")); + addButton->setButtonText (TRANS("Add")); + addButton->addListener (this); + + addAndMakeVisible (patterSlider = new Slider ("Pattern slider")); + patterSlider->setRange (0, 10, 1); + patterSlider->setSliderStyle (Slider::LinearHorizontal); + patterSlider->setTextBoxStyle (Slider::TextBoxLeft, false, 80, 20); + patterSlider->addListener (this); + + addAndMakeVisible (reconstructButton = new TextButton ("Reconstruct button")); + reconstructButton->setButtonText (TRANS("Reconstruct")); + reconstructButton->addListener (this); + + addAndMakeVisible (ShakeButton = new TextButton ("Shake button")); + ShakeButton->setButtonText (TRANS("Shake")); + ShakeButton->addListener (this); + + addAndMakeVisible (WeightsSlider = new Slider ("Weights slider")); + WeightsSlider->setRange (0, 10, 1); + WeightsSlider->setSliderStyle (Slider::LinearHorizontal); + WeightsSlider->setTextBoxStyle (Slider::TextBoxLeft, false, 80, 20); + WeightsSlider->addListener (this); + + addAndMakeVisible (numEpochslabel = new Label ("Num Epochs label", + TRANS("99999"))); + numEpochslabel->setFont (Font (15.00f, Font::plain)); + numEpochslabel->setJustificationType (Justification::centred); + numEpochslabel->setEditable (true, true, false); + numEpochslabel->setColour (TextEditor::textColourId, Colours::black); + numEpochslabel->setColour (TextEditor::backgroundColourId, Colour (0x00000000)); + numEpochslabel->addListener (this); + + addAndMakeVisible (learningRateLabel = new Label ("Learning Rate label", + TRANS("0.001"))); + learningRateLabel->setFont (Font (15.00f, Font::plain)); + learningRateLabel->setJustificationType (Justification::centred); + learningRateLabel->setEditable (true, true, false); + learningRateLabel->setColour (TextEditor::textColourId, Colours::black); + learningRateLabel->setColour (TextEditor::backgroundColourId, Colour (0x00000000)); + learningRateLabel->addListener (this); + + addAndMakeVisible (testButton = new TextButton ("Test button")); + testButton->setButtonText (TRANS("Test")); + testButton->addListener (this); + + addAndMakeVisible (numVisibleLabel = new Label ("Num Visible label", + TRANS("99999"))); + numVisibleLabel->setFont (Font (15.00f, Font::plain)); + numVisibleLabel->setJustificationType (Justification::centred); + numVisibleLabel->setEditable (true, true, false); + numVisibleLabel->setColour (TextEditor::textColourId, Colours::black); + numVisibleLabel->setColour (TextEditor::backgroundColourId, Colour (0x00000000)); + numVisibleLabel->addListener (this); + + addAndMakeVisible (numHiddenLabel = new Label ("Num Hidden label", + TRANS("99999"))); + numHiddenLabel->setFont (Font (15.00f, Font::plain)); + numHiddenLabel->setJustificationType (Justification::centred); + numHiddenLabel->setEditable (true, true, false); + numHiddenLabel->setColour (TextEditor::textColourId, Colours::black); + numHiddenLabel->setColour (TextEditor::backgroundColourId, Colour (0x00000000)); + numHiddenLabel->addListener (this); + + addAndMakeVisible (createButton = new TextButton ("Create button")); + createButton->setButtonText (TRANS("Create")); + createButton->addListener (this); + + addAndMakeVisible (projectNameLabel = new Label ("Project Name label", + TRANS("ProjectName"))); + projectNameLabel->setFont (Font (15.00f, Font::plain)); + projectNameLabel->setJustificationType (Justification::centred); + projectNameLabel->setEditable (true, true, false); + projectNameLabel->setColour (TextEditor::textColourId, Colours::black); + projectNameLabel->setColour (TextEditor::backgroundColourId, Colour (0x00000000)); + projectNameLabel->addListener (this); + + addAndMakeVisible (loadButton = new TextButton ("Load button")); + loadButton->setButtonText (TRANS("Load")); + loadButton->addListener (this); + + addAndMakeVisible (saveButton = new TextButton ("Save button")); + saveButton->setButtonText (TRANS("Save")); + saveButton->addListener (this); + + addAndMakeVisible (numVisibleYLabel = new Label ("Num Visible Y label", + TRANS("99999"))); + numVisibleYLabel->setFont (Font (15.00f, Font::plain)); + numVisibleYLabel->setJustificationType (Justification::centred); + numVisibleYLabel->setEditable (true, true, false); + numVisibleYLabel->setColour (TextEditor::textColourId, Colours::black); + numVisibleYLabel->setColour (TextEditor::backgroundColourId, Colour (0x00000000)); + numVisibleYLabel->addListener (this); + + addAndMakeVisible (loadTrainingButton = new TextButton ("Load Training button")); + loadTrainingButton->setButtonText (TRANS("Load T")); + loadTrainingButton->addListener (this); + + addAndMakeVisible (saveTrainingButton = new TextButton ("Save Training button")); + saveTrainingButton->setButtonText (TRANS("Save T")); + saveTrainingButton->addListener (this); + + addAndMakeVisible (clearTrainingButton = new TextButton ("Clear Training button")); + clearTrainingButton->setButtonText (TRANS("Clear T")); + clearTrainingButton->addListener (this); + + addAndMakeVisible (removeTrainingButton = new TextButton ("Remove Training button")); + removeTrainingButton->setButtonText (TRANS("Remove T")); + removeTrainingButton->addListener (this); //[UserPreSize] - addAndMakeVisible (Draw = new DrawComponent (4, 4, 32)); + m_vNumX = 16; + m_vNumY = 16; + m_hNum = 64; + m_vNumX_next = 16; + m_vNumY_next = 16; + m_hNum_next = 64; + +// m_pWeights = new Weights(m_vNumX*m_vNumY, m_hNum); +// m_pWeights = new Weights("C:\\Dokumente und Einstellungen\\Jens\\Desktop\\weights.dat"); + m_weights.load("C:\\Dokumente und Einstellungen\\Jens\\Desktop\\weights.dat"); + m_layers.load("C:\\Dokumente und Einstellungen\\Jens\\Desktop\\training_states.dat"); + create(); + //[/UserPreSize] setSize (600, 400); //[Constructor] You can add your own custom stuff here.. - m_pRbm = new Rbm(16, 4); + + projectNameLabel->setText(String("TestPrj"), dontSendNotification ); + numVisibleLabel->setText(String(m_vNumX), dontSendNotification ); + numVisibleYLabel->setText(String(m_vNumY), dontSendNotification ); + numHiddenLabel->setText(String(m_hNum), dontSendNotification ); + numEpochslabel->setText(String(1000), dontSendNotification ); + learningRateLabel->setText(String(0.2), dontSendNotification ); //[/Constructor] } @@ -50,12 +194,34 @@ MainComponent::~MainComponent() //[Destructor_pre]. You can add your own custom destruction code here.. //[/Destructor_pre] - textButton = nullptr; + trainButton = nullptr; + addButton = nullptr; + patterSlider = nullptr; + reconstructButton = nullptr; + ShakeButton = nullptr; + WeightsSlider = nullptr; + numEpochslabel = nullptr; + learningRateLabel = nullptr; + testButton = nullptr; + numVisibleLabel = nullptr; + numHiddenLabel = nullptr; + createButton = nullptr; + projectNameLabel = nullptr; + loadButton = nullptr; + saveButton = nullptr; + numVisibleYLabel = nullptr; + loadTrainingButton = nullptr; + saveTrainingButton = nullptr; + clearTrainingButton = nullptr; + removeTrainingButton = nullptr; //[Destructor]. You can add your own custom destruction code here.. Draw = nullptr; + Draw2 = nullptr; + DrawWeights = nullptr; m_pRbm = nullptr; + //[/Destructor] } @@ -73,86 +239,268 @@ void MainComponent::paint (Graphics& g) void MainComponent::resized() { - textButton->setBounds (72, 312, 150, 24); + trainButton->setBounds (120, 280, 72, 24); + addButton->setBounds (24, 176, 72, 24); + patterSlider->setBounds (224, 280, 184, 24); + reconstructButton->setBounds (24, 280, 72, 24); + ShakeButton->setBounds (120, 320, 72, 24); + WeightsSlider->setBounds (224, 320, 184, 24); + numEpochslabel->setBounds (24, 248, 72, 24); + learningRateLabel->setBounds (120, 248, 72, 24); + testButton->setBounds (120, 176, 72, 24); + numVisibleLabel->setBounds (440, 256, 72, 24); + numHiddenLabel->setBounds (488, 288, 72, 24); + createButton->setBounds (488, 320, 72, 24); + projectNameLabel->setBounds (472, 224, 96, 24); + loadButton->setBounds (440, 192, 72, 24); + saveButton->setBounds (520, 192, 72, 24); + numVisibleYLabel->setBounds (512, 256, 72, 24); + loadTrainingButton->setBounds (440, 48, 72, 24); + saveTrainingButton->setBounds (520, 48, 72, 24); + clearTrainingButton->setBounds (520, 88, 72, 24); + removeTrainingButton->setBounds (440, 88, 72, 24); //[UserResized] Add your own custom resize handling here.. - Draw->setBounds (16, 16, 336, 232); + Draw->setBounds (16, 16, 100, 100); + Draw2->setBounds (110+16, 16, 100, 100); + DrawWeights->setBounds (220+16, 16, 100, 100); //[/UserResized] } void MainComponent::buttonClicked (Button* buttonThatWasClicked) { //[UserbuttonClicked_Pre] - double trainingData[6][16] = - { - {1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1}, - {1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1}, - {0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0}, - {0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1}, - {1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0} - }; - - double hiddenTest[16][4] = - { - {0, 0, 0, 0}, - {0, 0, 0, 1}, - {0, 0, 1, 0}, - {0, 0, 1, 1}, - {0, 1, 0, 0}, - {0, 1, 0, 1}, - {0, 1, 1, 0}, - {0, 1, 1, 1}, - {1, 0, 0, 0}, - {1, 0, 0, 1}, - {1, 0, 1, 0}, - {1, 0, 1, 1}, - {1, 1, 0, 0}, - {1, 1, 0, 1}, - {1, 1, 1, 0}, - {1, 1, 1, 1} - }; //[/UserbuttonClicked_Pre] - if (buttonThatWasClicked == textButton) + if (buttonThatWasClicked == trainButton) { - //[UserButtonCode_textButton] -- add your button handler code here.. - m_pRbm->weightsShuffle(0.01); - m_pRbm->setNumTrainingPatterns(6); - - for (uint32_t i=0; i < 6; i++) - { - m_pRbm->setTrainingInput(i, trainingData[i]); - } - - m_pRbm->train(10000, 0.2); - m_pRbm->prob(); - -// Draw->drawGray(m_pRbm->toVisible(m_pRbm->toHidden(trainingData[rand()%6]))); - Draw->drawGray(m_pRbm->toVisible(hiddenTest[rand()%16])); - -#if 0 - m_pRbm->weightsPrint(); - // Test the network - for (uint32_t i=0; i < 6; i++) - { - m_pRbm->toHidden(trainingData[i]); - } - for (uint32_t i=0; i < 16; i++) - { - m_pRbm->toVisible(hiddenTest[i]); - } -#endif - - //[/UserButtonCode_textButton] + //[UserButtonCode_trainButton] -- add your button handler code here.. + m_pRbm->train(m_layers, numEpochslabel->getText().getIntValue(), learningRateLabel->getText().getFloatValue()); + //[/UserButtonCode_trainButton] + } + else if (buttonThatWasClicked == addButton) + { + //[UserButtonCode_addButton] -- add your button handler code here.. + Draw2->setData(Draw->getData()); + for (int i=0; i < m_vNumX*m_vNumY; i++) + { + mylog("%3.6f\n", Draw->getData()[i]); + } + m_layers.add(Draw->getData(), m_vNumX*m_vNumY); + patterSlider->setRange (0, m_layers.getSize()-1, 1); + //[/UserButtonCode_addButton] + } + else if (buttonThatWasClicked == reconstructButton) + { + //[UserButtonCode_reconstructButton] -- add your button handler code here.. + Draw2->setData(m_pRbm->toVisible(m_pRbm->toHidden(Draw->getData()))); + //[/UserButtonCode_reconstructButton] + } + else if (buttonThatWasClicked == ShakeButton) + { + //[UserButtonCode_ShakeButton] -- add your button handler code here.. + m_weights.shuffle(0.01); + //[/UserButtonCode_ShakeButton] + } + else if (buttonThatWasClicked == testButton) + { + //[UserButtonCode_testButton] -- add your button handler code here.. + Draw->setData(Draw2->getData()); + //[/UserButtonCode_testButton] + } + else if (buttonThatWasClicked == createButton) + { + //[UserButtonCode_createButton] -- add your button handler code here.. + m_vNumX = m_vNumX_next; + m_vNumY = m_vNumY_next; + m_hNum = m_hNum_next; + numVisibleLabel->setText(String(m_vNumX), dontSendNotification ); + numVisibleYLabel->setText(String(m_vNumY), dontSendNotification ); + numHiddenLabel->setText(String(m_hNum), dontSendNotification ); + m_weights.setUnits(m_vNumX*m_vNumY, m_hNum); + create(); + //[/UserButtonCode_createButton] + } + else if (buttonThatWasClicked == loadButton) + { + //[UserButtonCode_loadButton] -- add your button handler code here.. + load(); + //[/UserButtonCode_loadButton] + } + else if (buttonThatWasClicked == saveButton) + { + //[UserButtonCode_saveButton] -- add your button handler code here.. + save(); + //[/UserButtonCode_saveButton] + } + else if (buttonThatWasClicked == loadTrainingButton) + { + //[UserButtonCode_loadTrainingButton] -- add your button handler code here.. + m_layers.clear(); + m_layers.load((String(getBaseDir() + String(".trainingStates.dat"))).toUTF8()); + //[/UserButtonCode_loadTrainingButton] + } + else if (buttonThatWasClicked == saveTrainingButton) + { + //[UserButtonCode_saveTrainingButton] -- add your button handler code here.. + m_layers.save((String(getBaseDir() + String(".trainingStates.dat"))).toUTF8()); + //[/UserButtonCode_saveTrainingButton] + } + else if (buttonThatWasClicked == clearTrainingButton) + { + //[UserButtonCode_clearTrainingButton] -- add your button handler code here.. + m_layers.clear(); + //[/UserButtonCode_clearTrainingButton] + } + else if (buttonThatWasClicked == removeTrainingButton) + { + //[UserButtonCode_removeTrainingButton] -- add your button handler code here.. + m_layers.removeAt((int)patterSlider->getValue()); + //[/UserButtonCode_removeTrainingButton] } //[UserbuttonClicked_Post] //[/UserbuttonClicked_Post] } +void MainComponent::sliderValueChanged (Slider* sliderThatWasMoved) +{ + //[UsersliderValueChanged_Pre] + //[/UsersliderValueChanged_Pre] + + if (sliderThatWasMoved == patterSlider) + { + //[UserSliderCode_patterSlider] -- add your slider handling code here.. + if (m_layers.getSize() > 0) + { + VisibleLayer &p = m_layers.getAt((int)sliderThatWasMoved->getValue()); + Draw2->setData(p.getStates()); + } + //[/UserSliderCode_patterSlider] + } + else if (sliderThatWasMoved == WeightsSlider) + { + //[UserSliderCode_WeightsSlider] -- add your slider handling code here.. + double *pW = m_weights.getWeights()[(int)sliderThatWasMoved->getValue()]; + ScopedPointer pTemp = new double [m_vNumX*m_vNumY]; + double min = +1E12; + double max = -1E12; + + for (int i=0; i < m_vNumX*m_vNumY; i++) + { + pTemp[i] = pW[i]; + min = std::min(min, pW[i]); + max = std::max(max, pW[i]); + } + for (int i=0; i < m_vNumX*m_vNumY; i++) + { + pTemp[i] -= min; + } + for (int i=0; i < m_vNumX*m_vNumY; i++) + { + pTemp[i] /= (max-min); + } + + DrawWeights->setData(pTemp); + //[/UserSliderCode_WeightsSlider] + } + + //[UsersliderValueChanged_Post] + //[/UsersliderValueChanged_Post] +} + +void MainComponent::labelTextChanged (Label* labelThatHasChanged) +{ + //[UserlabelTextChanged_Pre] + //[/UserlabelTextChanged_Pre] + + if (labelThatHasChanged == numEpochslabel) + { + //[UserLabelCode_numEpochslabel] -- add your label text handling code here.. + //[/UserLabelCode_numEpochslabel] + } + else if (labelThatHasChanged == learningRateLabel) + { + //[UserLabelCode_learningRateLabel] -- add your label text handling code here.. + //[/UserLabelCode_learningRateLabel] + } + else if (labelThatHasChanged == numVisibleLabel) + { + //[UserLabelCode_numVisibleLabel] -- add your label text handling code here.. + m_vNumX_next = labelThatHasChanged->getText().getIntValue(); + //[/UserLabelCode_numVisibleLabel] + } + else if (labelThatHasChanged == numHiddenLabel) + { + //[UserLabelCode_numHiddenLabel] -- add your label text handling code here.. + m_hNum_next = labelThatHasChanged->getText().getIntValue(); + //[/UserLabelCode_numHiddenLabel] + } + else if (labelThatHasChanged == projectNameLabel) + { + //[UserLabelCode_projectNameLabel] -- add your label text handling code here.. + //[/UserLabelCode_projectNameLabel] + } + else if (labelThatHasChanged == numVisibleYLabel) + { + //[UserLabelCode_numVisibleYLabel] -- add your label text handling code here.. + m_vNumY_next = labelThatHasChanged->getText().getIntValue(); + //[/UserLabelCode_numVisibleYLabel] + } + + //[UserlabelTextChanged_Post] + //[/UserlabelTextChanged_Post] +} + //[MiscUserCode] You can add your own definitions of your custom methods or any other code here... +void MainComponent::load () +{ + m_weights.load((String(getBaseDir() + String(".weights.dat"))).toUTF8()); + m_layers.clear(); + m_layers.load((String(getBaseDir() + String(".trainingStates.dat"))).toUTF8()); + + m_vNumX = m_vNumY = (int)sqrt((float)m_weights.getNumVisible()); + m_hNum = m_weights.getNumHidden(); + create(); +} + +void MainComponent::save () +{ + m_weights.save((String(getBaseDir() + String(".weights.dat"))).toUTF8()); +} + +void MainComponent::create() +{ + Draw = nullptr; + Draw2 = nullptr; + DrawWeights = nullptr; + m_pRbm = nullptr; + addAndMakeVisible (Draw = new DrawComponent (m_vNumX, m_vNumX)); + addAndMakeVisible (Draw2 = new DrawComponent (m_vNumX, m_vNumX)); + addAndMakeVisible (DrawWeights = new DrawComponent (m_vNumX, m_vNumX)); + m_pRbm = new Rbm(m_weights); + WeightsSlider->setRange(0, m_hNum-1, 1); + resized(); +} + +void MainComponent::destroy() +{ +} + +const juce::String& MainComponent::getBaseDir() +{ + static String baseDir(String("C:\\Dokumente und Einstellungen\\Jens\\Desktop\\") + projectNameLabel->getText()); + + return baseDir; + +} + +void MainComponent::onChanged(const VisibleLayerArray &obj) +{ + patterSlider->setRange(0, std::max(0,(int)m_layers.getSize()-1), 1); +} + //[/MiscUserCode] @@ -166,16 +514,85 @@ void MainComponent::buttonClicked (Button* buttonThatWasClicked) BEGIN_JUCER_METADATA - + + + + + + END_JUCER_METADATA diff --git a/Source/MainComponent.h b/Source/MainComponent.h index 67e6961..97d930a 100644 --- a/Source/MainComponent.h +++ b/Source/MainComponent.h @@ -22,10 +22,11 @@ //[Headers] -- You can add your own extra header files here -- #include "JuceHeader.h" +#include "DrawComponent.h" +#include "LayerArray.hpp" #include "Rbm.hpp" //[/Headers] -#include "DrawComponent.h" //============================================================================== @@ -37,7 +38,10 @@ //[/Comments] */ class MainComponent : public Component, - public ButtonListener + public VisibleLayerArrayListener, + public ButtonListener, + public SliderListener, + public LabelListener { public: //============================================================================== @@ -51,17 +55,55 @@ public: void paint (Graphics& g); void resized(); void buttonClicked (Button* buttonThatWasClicked); + void sliderValueChanged (Slider* sliderThatWasMoved); + void labelTextChanged (Label* labelThatHasChanged); private: //[UserVariables] -- You can add your own custom variables in this section. - ScopedPointer m_pRbm; + Weights m_weights; + ScopedPointer m_pRbm; ScopedPointer Draw; + ScopedPointer Draw2; + ScopedPointer DrawWeights; + Arraym_trainingData; + uint32_t m_vNumX; + uint32_t m_vNumY; + uint32_t m_hNum; + uint32_t m_vNumX_next; + uint32_t m_vNumY_next; + uint32_t m_hNum_next; + VisibleLayerArray m_layers; + void load(); + void save(); + void create(); + void destroy(); + const juce::String& getBaseDir(); + void onChanged(const VisibleLayerArray &obj); //[/UserVariables] //============================================================================== - ScopedPointer textButton; + ScopedPointer trainButton; + ScopedPointer addButton; + ScopedPointer patterSlider; + ScopedPointer reconstructButton; + ScopedPointer ShakeButton; + ScopedPointer WeightsSlider; + ScopedPointer