Browse Source

Update to latest juce

tags/2018-04-16
falkTX 10 years ago
parent
commit
350263c485
58 changed files with 1285 additions and 780 deletions
  1. +6
    -10
      libs/juce/source/modules/juce_audio_basics/buffers/juce_AudioSampleBuffer.cpp
  2. +4
    -8
      libs/juce/source/modules/juce_audio_basics/buffers/juce_AudioSampleBuffer.h
  3. +506
    -363
      libs/juce/source/modules/juce_audio_basics/buffers/juce_FloatVectorOperations.cpp
  4. +44
    -2
      libs/juce/source/modules/juce_audio_basics/buffers/juce_FloatVectorOperations.h
  5. +4
    -0
      libs/juce/source/modules/juce_audio_basics/juce_audio_basics.cpp
  6. +4
    -2
      libs/juce/source/modules/juce_audio_basics/midi/juce_MidiFile.cpp
  7. +3
    -1
      libs/juce/source/modules/juce_audio_basics/midi/juce_MidiFile.h
  8. +3
    -2
      libs/juce/source/modules/juce_audio_basics/midi/juce_MidiMessage.cpp
  9. +9
    -5
      libs/juce/source/modules/juce_audio_basics/midi/juce_MidiMessage.h
  10. +23
    -16
      libs/juce/source/modules/juce_audio_basics/synthesisers/juce_Synthesiser.cpp
  11. +9
    -0
      libs/juce/source/modules/juce_audio_basics/synthesisers/juce_Synthesiser.h
  12. +1
    -1
      libs/juce/source/modules/juce_audio_devices/native/juce_win32_WASAPI.cpp
  13. +1
    -0
      libs/juce/source/modules/juce_audio_formats/codecs/juce_FlacAudioFormat.cpp
  14. +21
    -6
      libs/juce/source/modules/juce_audio_formats/codecs/juce_MP3AudioFormat.cpp
  15. +7
    -5
      libs/juce/source/modules/juce_audio_formats/codecs/juce_WavAudioFormat.cpp
  16. +1
    -0
      libs/juce/source/modules/juce_audio_formats/codecs/juce_WindowsMediaAudioFormat.cpp
  17. +1
    -0
      libs/juce/source/modules/juce_audio_formats/codecs/juce_WindowsMediaAudioFormat.h
  18. +10
    -11
      libs/juce/source/modules/juce_audio_formats/format/juce_AudioFormatReader.cpp
  19. +2
    -2
      libs/juce/source/modules/juce_audio_plugin_client/AAX/juce_AAX_Wrapper.cpp
  20. +3
    -3
      libs/juce/source/modules/juce_audio_plugin_client/RTAS/juce_RTAS_Wrapper.cpp
  21. +8
    -50
      libs/juce/source/modules/juce_audio_plugin_client/VST/juce_VST_Wrapper.cpp
  22. +152
    -21
      libs/juce/source/modules/juce_audio_plugin_client/VST3/juce_VST3_Wrapper.cpp
  23. +7
    -1
      libs/juce/source/modules/juce_audio_processors/format_types/juce_VST3PluginFormat.cpp
  24. +2
    -3
      libs/juce/source/modules/juce_audio_utils/gui/juce_AudioThumbnail.cpp
  25. +1
    -1
      libs/juce/source/modules/juce_core/files/juce_File.cpp
  26. +34
    -1
      libs/juce/source/modules/juce_core/maths/juce_Range.h
  27. +7
    -2
      libs/juce/source/modules/juce_core/memory/juce_MemoryBlock.cpp
  28. +6
    -3
      libs/juce/source/modules/juce_core/memory/juce_MemoryBlock.h
  29. +1
    -6
      libs/juce/source/modules/juce_core/network/juce_MACAddress.h
  30. +85
    -75
      libs/juce/source/modules/juce_core/network/juce_URL.cpp
  31. +33
    -14
      libs/juce/source/modules/juce_core/network/juce_URL.h
  32. +1
    -0
      libs/juce/source/modules/juce_core/system/juce_SystemStats.h
  33. +6
    -14
      libs/juce/source/modules/juce_core/threads/juce_ReadWriteLock.cpp
  34. +2
    -0
      libs/juce/source/modules/juce_core/threads/juce_ReadWriteLock.h
  35. +1
    -2
      libs/juce/source/modules/juce_data_structures/values/juce_Value.h
  36. +1
    -1
      libs/juce/source/modules/juce_events/interprocess/juce_ConnectedChildProcess.cpp
  37. +1
    -1
      libs/juce/source/modules/juce_events/messages/juce_MessageManager.h
  38. +0
    -26
      libs/juce/source/modules/juce_events/timers/juce_Timer.cpp
  39. +9
    -0
      libs/juce/source/modules/juce_graphics/fonts/juce_CustomTypeface.h
  40. +11
    -6
      libs/juce/source/modules/juce_graphics/geometry/juce_Path.cpp
  41. +13
    -2
      libs/juce/source/modules/juce_graphics/geometry/juce_Path.h
  42. +54
    -45
      libs/juce/source/modules/juce_graphics/native/juce_RenderingHelpers.h
  43. +2
    -1
      libs/juce/source/modules/juce_graphics/native/juce_win32_Fonts.cpp
  44. +4
    -2
      libs/juce/source/modules/juce_gui_basics/buttons/juce_Button.h
  45. +10
    -16
      libs/juce/source/modules/juce_gui_basics/buttons/juce_TextButton.cpp
  46. +7
    -7
      libs/juce/source/modules/juce_gui_basics/buttons/juce_TextButton.h
  47. +9
    -4
      libs/juce/source/modules/juce_gui_basics/drawables/juce_SVGParser.cpp
  48. +10
    -0
      libs/juce/source/modules/juce_gui_basics/lookandfeel/juce_LookAndFeel_V2.cpp
  49. +1
    -0
      libs/juce/source/modules/juce_gui_basics/lookandfeel/juce_LookAndFeel_V2.h
  50. +6
    -2
      libs/juce/source/modules/juce_gui_basics/native/juce_mac_NSViewComponentPeer.mm
  51. +111
    -21
      libs/juce/source/modules/juce_gui_basics/native/juce_win32_Windowing.cpp
  52. +1
    -1
      libs/juce/source/modules/juce_gui_basics/widgets/juce_Slider.cpp
  53. +9
    -2
      libs/juce/source/modules/juce_gui_basics/windows/juce_CallOutBox.cpp
  54. +2
    -1
      libs/juce/source/modules/juce_gui_basics/windows/juce_CallOutBox.h
  55. +4
    -4
      libs/juce/source/modules/juce_gui_extra/native/juce_android_WebBrowserComponent.cpp
  56. +4
    -4
      libs/juce/source/modules/juce_gui_extra/native/juce_linux_WebBrowserComponent.cpp
  57. +4
    -2
      libs/juce/source/modules/juce_gui_extra/native/juce_mac_WebBrowserComponent.mm
  58. +4
    -2
      libs/juce/source/modules/juce_gui_extra/native/juce_win32_WebBrowserComponent.cpp

+ 6
- 10
libs/juce/source/modules/juce_audio_basics/buffers/juce_AudioSampleBuffer.cpp View File

@@ -487,17 +487,14 @@ void AudioSampleBuffer::reverse (int startSample, int numSamples) const noexcept
reverse (i, startSample, numSamples);
}
void AudioSampleBuffer::findMinMax (const int channel,
const int startSample,
int numSamples,
float& minVal,
float& maxVal) const noexcept
Range<float> AudioSampleBuffer::findMinMax (const int channel,
const int startSample,
int numSamples) const noexcept
{
jassert (isPositiveAndBelow (channel, numChannels));
jassert (startSample >= 0 && startSample + numSamples <= size);
FloatVectorOperations::findMinAndMax (channels [channel] + startSample,
numSamples, minVal, maxVal);
return FloatVectorOperations::findMinAndMax (channels [channel] + startSample, numSamples);
}
float AudioSampleBuffer::getMagnitude (const int channel,
@@ -507,10 +504,9 @@ float AudioSampleBuffer::getMagnitude (const int channel,
jassert (isPositiveAndBelow (channel, numChannels));
jassert (startSample >= 0 && startSample + numSamples <= size);
float mn, mx;
findMinMax (channel, startSample, numSamples, mn, mx);
const Range<float> r (findMinMax (channel, startSample, numSamples));
return jmax (mn, -mn, mx, -mx);
return jmax (r.getStart(), -r.getStart(), r.getEnd(), -r.getEnd());
}
float AudioSampleBuffer::getMagnitude (int startSample, int numSamples) const noexcept


+ 4
- 8
libs/juce/source/modules/juce_audio_basics/buffers/juce_AudioSampleBuffer.h View File

@@ -392,19 +392,15 @@ public:
float endGain) noexcept;
/** Finds the highest and lowest sample values in a given range.
/** Returns a Range indicating the lowest and highest sample values in a given section.
@param channel the channel to read from
@param startSample the start sample within the channel
@param numSamples the number of samples to check
@param minVal on return, the lowest value that was found
@param maxVal on return, the highest value that was found
*/
void findMinMax (int channel,
int startSample,
int numSamples,
float& minVal,
float& maxVal) const noexcept;
Range<float> findMinMax (int channel,
int startSample,
int numSamples) const noexcept;
/** Finds the highest absolute sample value within a region of a channel. */
float getMagnitude (int channel,


+ 506
- 363
libs/juce/source/modules/juce_audio_basics/buffers/juce_FloatVectorOperations.cpp
File diff suppressed because it is too large
View File


+ 44
- 2
libs/juce/source/modules/juce_audio_basics/buffers/juce_FloatVectorOperations.h View File

@@ -38,48 +38,90 @@ public:
/** Clears a vector of floats. */
static void JUCE_CALLTYPE clear (float* dest, int numValues) noexcept;
/** Clears a vector of doubles. */
static void JUCE_CALLTYPE clear (double* dest, int numValues) noexcept;
/** Copies a repeated value into a vector of floats. */
static void JUCE_CALLTYPE fill (float* dest, float valueToFill, int numValues) noexcept;
/** Copies a repeated value into a vector of doubles. */
static void JUCE_CALLTYPE fill (double* dest, double valueToFill, int numValues) noexcept;
/** Copies a vector of floats. */
static void JUCE_CALLTYPE copy (float* dest, const float* src, int numValues) noexcept;
/** Copies a vector of doubles. */
static void JUCE_CALLTYPE copy (double* dest, const double* src, int numValues) noexcept;
/** Copies a vector of floats, multiplying each value by a given multiplier */
static void JUCE_CALLTYPE copyWithMultiply (float* dest, const float* src, float multiplier, int numValues) noexcept;
/** Copies a vector of doubles, multiplying each value by a given multiplier */
static void JUCE_CALLTYPE copyWithMultiply (double* dest, const double* src, double multiplier, int numValues) noexcept;
/** Adds a fixed value to the destination values. */
static void JUCE_CALLTYPE add (float* dest, float amountToAdd, int numValues) noexcept;
/** Adds a fixed value to the destination values. */
static void JUCE_CALLTYPE add (float* dest, float amount, int numValues) noexcept;
static void JUCE_CALLTYPE add (double* dest, double amountToAdd, int numValues) noexcept;
/** Adds the source values to the destination values. */
static void JUCE_CALLTYPE add (float* dest, const float* src, int numValues) noexcept;
/** Adds the source values to the destination values. */
static void JUCE_CALLTYPE add (double* dest, const double* src, int numValues) noexcept;
/** Subtracts the source values from the destination values. */
static void JUCE_CALLTYPE subtract (float* dest, const float* src, int numValues) noexcept;
/** Subtracts the source values from the destination values. */
static void JUCE_CALLTYPE subtract (double* dest, const double* src, int numValues) noexcept;
/** Multiplies each source value by the given multiplier, then adds it to the destination value. */
static void JUCE_CALLTYPE addWithMultiply (float* dest, const float* src, float multiplier, int numValues) noexcept;
/** Multiplies each source value by the given multiplier, then adds it to the destination value. */
static void JUCE_CALLTYPE addWithMultiply (double* dest, const double* src, double multiplier, int numValues) noexcept;
/** Multiplies the destination values by the source values. */
static void JUCE_CALLTYPE multiply (float* dest, const float* src, int numValues) noexcept;
/** Multiplies the destination values by the source values. */
static void JUCE_CALLTYPE multiply (double* dest, const double* src, int numValues) noexcept;
/** Multiplies each of the destination values by a fixed multiplier. */
static void JUCE_CALLTYPE multiply (float* dest, float multiplier, int numValues) noexcept;
/** Multiplies each of the destination values by a fixed multiplier. */
static void JUCE_CALLTYPE multiply (double* dest, double multiplier, int numValues) noexcept;
/** Copies a source vector to a destination, negating each value. */
static void JUCE_CALLTYPE negate (float* dest, const float* src, int numValues) noexcept;
/** Copies a source vector to a destination, negating each value. */
static void JUCE_CALLTYPE negate (double* dest, const double* src, int numValues) noexcept;
/** Converts a stream of integers to floats, multiplying each one by the given multiplier. */
static void JUCE_CALLTYPE convertFixedToFloat (float* dest, const int* src, float multiplier, int numValues) noexcept;
/** Finds the miniumum and maximum values in the given array. */
static void JUCE_CALLTYPE findMinAndMax (const float* src, int numValues, float& minResult, float& maxResult) noexcept;
static Range<float> JUCE_CALLTYPE findMinAndMax (const float* src, int numValues) noexcept;
/** Finds the miniumum and maximum values in the given array. */
static Range<double> JUCE_CALLTYPE findMinAndMax (const double* src, int numValues) noexcept;
/** Finds the miniumum value in the given array. */
static float JUCE_CALLTYPE findMinimum (const float* src, int numValues) noexcept;
/** Finds the miniumum value in the given array. */
static double JUCE_CALLTYPE findMinimum (const double* src, int numValues) noexcept;
/** Finds the maximum value in the given array. */
static float JUCE_CALLTYPE findMaximum (const float* src, int numValues) noexcept;
/** Finds the maximum value in the given array. */
static double JUCE_CALLTYPE findMaximum (const double* src, int numValues) noexcept;
/** On Intel CPUs, this method enables or disables the SSE flush-to-zero mode.
Effectively, this is a wrapper around a call to _MM_SET_FLUSH_ZERO_MODE
*/


+ 4
- 0
libs/juce/source/modules/juce_audio_basics/juce_audio_basics.cpp View File

@@ -36,6 +36,10 @@
#include "AppConfig.h"
#include "juce_audio_basics.h"
#if JUCE_MINGW && ! defined (__SSE2__)
#define JUCE_USE_SSE_INTRINSICS 0
#endif
#ifndef JUCE_USE_SSE_INTRINSICS
#define JUCE_USE_SSE_INTRINSICS 1
#endif


+ 4
- 2
libs/juce/source/modules/juce_audio_basics/midi/juce_MidiFile.cpp View File

@@ -350,11 +350,13 @@ void MidiFile::convertTimestampTicksToSeconds()
}
//==============================================================================
bool MidiFile::writeTo (OutputStream& out)
bool MidiFile::writeTo (OutputStream& out, int midiFileType)
{
jassert (midiFileType >= 0 && midiFileType <= 2);
out.writeIntBigEndian ((int) ByteOrder::bigEndianInt ("MThd"));
out.writeIntBigEndian (6);
out.writeShortBigEndian (1); // type
out.writeShortBigEndian ((short) midiFileType);
out.writeShortBigEndian ((short) tracks.size());
out.writeShortBigEndian (timeFormat);


+ 3
- 1
libs/juce/source/modules/juce_audio_basics/midi/juce_MidiFile.h View File

@@ -151,9 +151,11 @@ public:
bool readFrom (InputStream& sourceStream);
/** Writes the midi tracks as a standard midi file.
The midiFileType value is written as the file's format type, which can be 0, 1
or 2 - see the midi file spec for more info about that.
@returns true if the operation succeeded.
*/
bool writeTo (OutputStream& destStream);
bool writeTo (OutputStream& destStream, int midiFileType = 1);
/** Converts the timestamp of all the midi events from midi ticks to seconds.


+ 3
- 2
libs/juce/source/modules/juce_audio_basics/midi/juce_MidiMessage.cpp View File

@@ -152,7 +152,8 @@ MidiMessage::MidiMessage (const MidiMessage& other, const double newTimeStamp)
}
}
MidiMessage::MidiMessage (const void* srcData, int sz, int& numBytesUsed, const uint8 lastStatusByte, double t)
MidiMessage::MidiMessage (const void* srcData, int sz, int& numBytesUsed, const uint8 lastStatusByte,
double t, bool sysexHasEmbeddedLength)
: timeStamp (t)
{
const uint8* src = static_cast<const uint8*> (srcData);
@@ -175,7 +176,7 @@ MidiMessage::MidiMessage (const void* srcData, int sz, int& numBytesUsed, const
if (byte == 0xf0)
{
const uint8* d = src;
bool haveReadAllLengthBytes = false;
bool haveReadAllLengthBytes = ! sysexHasEmbeddedLength;
int numVariableLengthSysexBytes = 0;
while (d < src + sz)


+ 9
- 5
libs/juce/source/modules/juce_audio_basics/midi/juce_MidiMessage.h View File

@@ -82,10 +82,14 @@ public:
has in fact been dropped.
@param timeStamp the time to give the midi message - this value doesn't
use any particular units, so will be application-specific
@param sysexHasEmbeddedLength when reading sysexes, this flag indicates whether
to expect the data to begin with a variable-length field
indicating its size
*/
MidiMessage (const void* data, int maxBytesToUse,
int& numBytesUsed, uint8 lastStatusByte,
double timeStamp = 0);
double timeStamp = 0,
bool sysexHasEmbeddedLength = true);
/** Creates an active-sense message.
Since the MidiMessage has to contain a valid message, this default constructor
@@ -94,10 +98,10 @@ public:
MidiMessage() noexcept;
/** Creates a copy of another midi message. */
MidiMessage (const MidiMessage& other);
MidiMessage (const MidiMessage&);
/** Creates a copy of another midi message, with a different timestamp. */
MidiMessage (const MidiMessage& other, double newTimeStamp);
MidiMessage (const MidiMessage&, double newTimeStamp);
/** Destructor. */
~MidiMessage();
@@ -106,8 +110,8 @@ public:
MidiMessage& operator= (const MidiMessage& other);
#if JUCE_COMPILER_SUPPORTS_MOVE_SEMANTICS
MidiMessage (MidiMessage&& other) noexcept;
MidiMessage& operator= (MidiMessage&& other) noexcept;
MidiMessage (MidiMessage&&) noexcept;
MidiMessage& operator= (MidiMessage&&) noexcept;
#endif
//==============================================================================


+ 23
- 16
libs/juce/source/modules/juce_audio_basics/synthesisers/juce_Synthesiser.cpp View File

@@ -58,6 +58,11 @@ void SynthesiserVoice::clearCurrentNote()
void SynthesiserVoice::aftertouchChanged (int) {}
bool SynthesiserVoice::wasStartedBefore (const SynthesiserVoice& other) const noexcept
{
return noteOnTime < other.noteOnTime;
}
//==============================================================================
Synthesiser::Synthesiser()
: sampleRate (0),
@@ -407,12 +412,11 @@ void Synthesiser::handleSoftPedal (int midiChannel, bool /*isDown*/)
}
//==============================================================================
SynthesiserVoice* Synthesiser::findFreeVoice (SynthesiserSound* soundToPlay,
const bool stealIfNoneAvailable) const
SynthesiserVoice* Synthesiser::findFreeVoice (SynthesiserSound* soundToPlay, const bool stealIfNoneAvailable) const
{
const ScopedLock sl (lock);
for (int i = voices.size(); --i >= 0;)
for (int i = 0; i < voices.size(); ++i)
{
SynthesiserVoice* const voice = voices.getUnchecked (i);
@@ -421,22 +425,25 @@ SynthesiserVoice* Synthesiser::findFreeVoice (SynthesiserSound* soundToPlay,
}
if (stealIfNoneAvailable)
{
// currently this just steals the one that's been playing the longest, but could be made a bit smarter..
SynthesiserVoice* oldest = nullptr;
return findVoiceToSteal (soundToPlay);
for (int i = voices.size(); --i >= 0;)
{
SynthesiserVoice* const voice = voices.getUnchecked (i);
return nullptr;
}
if (voice->canPlaySound (soundToPlay)
&& (oldest == nullptr || oldest->noteOnTime > voice->noteOnTime))
oldest = voice;
}
SynthesiserVoice* Synthesiser::findVoiceToSteal (SynthesiserSound* soundToPlay) const
{
// currently this just steals the one that's been playing the longest, but could be made a bit smarter..
SynthesiserVoice* oldest = nullptr;
jassert (oldest != nullptr);
return oldest;
for (int i = 0; i < voices.size(); ++i)
{
SynthesiserVoice* const voice = voices.getUnchecked (i);
if (voice->canPlaySound (soundToPlay)
&& (oldest == nullptr || voice->wasStartedBefore (*oldest)))
oldest = voice;
}
return nullptr;
jassert (oldest != nullptr);
return oldest;
}

+ 9
- 0
libs/juce/source/modules/juce_audio_basics/synthesisers/juce_Synthesiser.h View File

@@ -199,6 +199,9 @@ public:
/** Returns true if the sostenuto pedal is currently active for this voice. */
bool isSostenutoPedalDown() const noexcept { return sostenutoPedalDown; }
/** Returns true if this voice started playing its current note before the other voice did. */
bool wasStartedBefore (const SynthesiserVoice& other) const noexcept;
protected:
//==============================================================================
/** Returns the current target sample rate at which rendering is being done.
@@ -481,6 +484,12 @@ protected:
virtual SynthesiserVoice* findFreeVoice (SynthesiserSound* soundToPlay,
const bool stealIfNoneAvailable) const;
/** Chooses a voice that is most suitable for being re-used.
The default method returns the one that has been playing for the longest, but
you may want to override this and do something more cunning instead.
*/
virtual SynthesiserVoice* findVoiceToSteal (SynthesiserSound* soundToPlay) const;
/** Starts a specified voice playing a particular sound.
You'll probably never need to call this, it's used internally by noteOn(), but


+ 1
- 1
libs/juce/source/modules/juce_audio_devices/native/juce_win32_WASAPI.cpp View File

@@ -632,7 +632,7 @@ public:
{
closeClient();
captureClient = nullptr;
reservoir.setSize (0);
reservoir.reset();
}
template <class SourceType>


+ 1
- 0
libs/juce/source/modules/juce_audio_formats/codecs/juce_FlacAudioFormat.cpp View File

@@ -61,6 +61,7 @@ namespace FlacNamespace
#define FLAC__HAS_X86INTRIN 1
#endif
#undef __STDC_LIMIT_MACROS
#define __STDC_LIMIT_MACROS 1
#define flac_max jmax
#define flac_min jmin


+ 21
- 6
libs/juce/source/modules/juce_audio_formats/codecs/juce_MP3AudioFormat.cpp View File

@@ -516,12 +516,21 @@ struct MP3Frame
{ 0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160 } }
};
switch (layer)
if (bitrateIndex == 0)
{
case 1: frameSize = (((frameSizes[lsf][0][bitrateIndex] * 12000) / getFrequency() + padding) * 4) - 4; break;
case 2: frameSize = (frameSizes[lsf][1][bitrateIndex] * 144000) / getFrequency() + (padding - 4); break;
case 3: frameSize = (bitrateIndex == 0) ? 0 : ((frameSizes[lsf][2][bitrateIndex] * 144000) / (getFrequency() << lsf) + (padding - 4)); break;
default: break;
jassertfalse; // This means the file is using "free format". Apparently very few decoders
// support this mode, and this one certainly doesn't handle it correctly!
frameSize = 0;
}
else
{
switch (layer)
{
case 1: frameSize = (((frameSizes[lsf][0][bitrateIndex] * 12000) / getFrequency() + padding) * 4) - 4; break;
case 2: frameSize = (frameSizes[lsf][1][bitrateIndex] * 144000) / getFrequency() + (padding - 4); break;
case 3: frameSize = (bitrateIndex == 0) ? 0 : ((frameSizes[lsf][2][bitrateIndex] * 144000) / (getFrequency() << lsf) + (padding - 4)); break;
default: break;
}
}
}
@@ -1451,7 +1460,7 @@ struct MP3Stream
bufferPointer = bufferSpace[bufferSpaceIndex] + 512;
bitIndex = 0;
if (lastFrameSize == -1)
if (lastFrameSize < 0)
return 1;
}
@@ -1513,8 +1522,14 @@ struct MP3Stream
else
{
const int nextFrameOffset = scanForNextFrameHeader (true);
wasFreeFormat = isFreeFormat;
if (nextFrameOffset < 0)
{
lastFrameSize = frameSize;
return result;
}
frameSize = nextFrameOffset + sideInfoSize + dataSize;
lastFrameSizeNoPadding = frameSize - frame.padding;


+ 7
- 5
libs/juce/source/modules/juce_audio_formats/codecs/juce_WavAudioFormat.cpp View File

@@ -983,11 +983,13 @@ private:
switch (numChannels)
{
case 1: return 0;
case 2: return 1 + 2; // SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT
case 5: return 1 + 2 + 4 + 16 + 32; // SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT
case 6: return 1 + 2 + 4 + 8 + 16 + 32; // SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER | SPEAKER_LOW_FREQUENCY | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT
case 7: return 1 + 2 + 4 + 16 + 32 + 512 + 1024; // SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT | SPEAKER_SIDE_LEFT | SPEAKER_SIDE_RIGHT
case 8: return 1 + 2 + 4 + 8 + 16 + 32 + 512 + 1024; // SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER | SPEAKER_LOW_FREQUENCY | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT | SPEAKER_SIDE_LEFT | SPEAKER_SIDE_RIGHT
case 2: return 1 + 2; // SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT
case 3: return 1 + 2 + 4; // SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER
case 4: return 1 + 2 + 16 + 32; // SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT
case 5: return 1 + 2 + 4 + 16 + 32; // SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT
case 6: return 1 + 2 + 4 + 8 + 16 + 32; // SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER | SPEAKER_LOW_FREQUENCY | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT
case 7: return 1 + 2 + 4 + 16 + 32 + 512 + 1024; // SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT | SPEAKER_SIDE_LEFT | SPEAKER_SIDE_RIGHT
case 8: return 1 + 2 + 4 + 8 + 16 + 32 + 512 + 1024; // SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER | SPEAKER_LOW_FREQUENCY | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT | SPEAKER_SIDE_LEFT | SPEAKER_SIDE_RIGHT
default: break;
}


+ 1
- 0
libs/juce/source/modules/juce_audio_formats/codecs/juce_WindowsMediaAudioFormat.cpp View File

@@ -344,6 +344,7 @@ Array<int> WindowsMediaAudioFormat::getPossibleBitDepths() { return Array<i
bool WindowsMediaAudioFormat::canDoStereo() { return true; }
bool WindowsMediaAudioFormat::canDoMono() { return true; }
bool WindowsMediaAudioFormat::isCompressed() { return true; }
//==============================================================================
AudioFormatReader* WindowsMediaAudioFormat::createReaderFor (InputStream* sourceStream, bool deleteStreamIfOpeningFails)


+ 1
- 0
libs/juce/source/modules/juce_audio_formats/codecs/juce_WindowsMediaAudioFormat.h View File

@@ -40,6 +40,7 @@ public:
Array<int> getPossibleBitDepths() override;
bool canDoStereo() override;
bool canDoMono() override;
bool isCompressed() override;
//==============================================================================
AudioFormatReader* createReaderFor (InputStream*, bool deleteStreamIfOpeningFails) override;


+ 10
- 11
libs/juce/source/modules/juce_audio_formats/format/juce_AudioFormatReader.cpp View File

@@ -174,30 +174,29 @@ void AudioFormatReader::read (AudioSampleBuffer* buffer,
}
template <typename SampleType>
static inline void getChannelMinAndMax (SampleType* channel, const int numSamples, SampleType& mn, SampleType& mx)
static Range<SampleType> getChannelMinAndMax (SampleType* channel, int numSamples) noexcept
{
findMinAndMax (channel, numSamples, mn, mx);
return Range<SampleType>::findMinAndMax (channel, numSamples);
}
static inline void getChannelMinAndMax (float* channel, const int numSamples, float& mn, float& mx)
static Range<float> getChannelMinAndMax (float* channel, int numSamples) noexcept
{
FloatVectorOperations::findMinAndMax (channel, numSamples, mn, mx);
return FloatVectorOperations::findMinAndMax (channel, numSamples);
}
template <typename SampleType>
static void getStereoMinAndMax (SampleType* const* channels, const int numChannels, const int numSamples,
SampleType& lmin, SampleType& lmax, SampleType& rmin, SampleType& rmax)
{
SampleType bufMin, bufMax;
getChannelMinAndMax (channels[0], numSamples, bufMin, bufMax);
lmax = jmax (lmax, bufMax);
lmin = jmin (lmin, bufMin);
Range<SampleType> range (getChannelMinAndMax (channels[0], numSamples));
lmax = jmax (lmax, range.getEnd());
lmin = jmin (lmin, range.getStart());
if (numChannels > 1)
{
getChannelMinAndMax (channels[1], numSamples, bufMin, bufMax);
rmax = jmax (rmax, bufMax);
rmin = jmin (rmin, bufMin);
range = getChannelMinAndMax (channels[1], numSamples);
rmax = jmax (rmax, range.getEnd());
rmin = jmin (rmin, range.getStart());
}
else
{


+ 2
- 2
libs/juce/source/modules/juce_audio_plugin_client/AAX/juce_AAX_Wrapper.cpp View File

@@ -442,7 +442,7 @@ struct AAXClasses
if (chunkID != juceChunkType)
return AAX_CEffectParameters::GetChunkSize (chunkID, oSize);
tempFilterData.setSize (0);
tempFilterData.reset();
pluginInstance->getStateInformation (tempFilterData);
*oSize = (uint32_t) tempFilterData.getSize();
return AAX_SUCCESS;
@@ -458,7 +458,7 @@ struct AAXClasses
oChunk->fSize = (int32_t) tempFilterData.getSize();
tempFilterData.copyTo (oChunk->fData, 0, tempFilterData.getSize());
tempFilterData.setSize (0);
tempFilterData.reset();
return AAX_SUCCESS;
}


+ 3
- 3
libs/juce/source/modules/juce_audio_plugin_client/RTAS/juce_RTAS_Wrapper.cpp View File

@@ -627,7 +627,7 @@ protected:
{
if (chunkID == juceChunkType)
{
tempFilterData.setSize (0);
tempFilterData.reset();
juceFilter->getStateInformation (tempFilterData);
*size = sizeof (SFicPlugInChunkHeader) + tempFilterData.getSize();
@@ -647,7 +647,7 @@ protected:
chunk->fSize = sizeof (SFicPlugInChunkHeader) + tempFilterData.getSize();
tempFilterData.copyTo ((void*) chunk->fData, 0, tempFilterData.getSize());
tempFilterData.setSize (0);
tempFilterData.reset();
return noErr;
}
@@ -659,7 +659,7 @@ protected:
{
if (chunkID == juceChunkType)
{
tempFilterData.setSize (0);
tempFilterData.reset();
if (chunk->fSize - sizeof (SFicPlugInChunkHeader) > 0)
{


+ 8
- 50
libs/juce/source/modules/juce_audio_plugin_client/VST/juce_VST_Wrapper.cpp View File

@@ -96,6 +96,7 @@
#include "../utility/juce_IncludeModuleHeaders.h"
#include "../utility/juce_FakeMouseMoveGenerator.h"
#include "../utility/juce_WindowsHooks.h"
#include "modules/juce_audio_processors/format_types/juce_VSTMidiEventList.h"
#ifdef _MSC_VER
@@ -169,48 +170,7 @@ namespace
return w;
}
//==============================================================================
static HHOOK mouseWheelHook = 0;
static int mouseHookUsers = 0;
LRESULT CALLBACK mouseWheelHookCallback (int nCode, WPARAM wParam, LPARAM lParam)
{
if (nCode >= 0 && wParam == WM_MOUSEWHEEL)
{
// using a local copy of this struct to support old mingw libraries
struct MOUSEHOOKSTRUCTEX_ : public MOUSEHOOKSTRUCT { DWORD mouseData; };
const MOUSEHOOKSTRUCTEX_& hs = *(MOUSEHOOKSTRUCTEX_*) lParam;
if (Component* const comp = Desktop::getInstance().findComponentAt (Point<int> (hs.pt.x, hs.pt.y)))
if (comp->getWindowHandle() != 0)
return PostMessage ((HWND) comp->getWindowHandle(), WM_MOUSEWHEEL,
hs.mouseData & 0xffff0000, (hs.pt.x & 0xffff) | (hs.pt.y << 16));
}
return CallNextHookEx (mouseWheelHook, nCode, wParam, lParam);
}
void registerMouseWheelHook()
{
if (mouseHookUsers++ == 0)
mouseWheelHook = SetWindowsHookEx (WH_MOUSE, mouseWheelHookCallback,
(HINSTANCE) Process::getCurrentModuleInstanceHandle(),
GetCurrentThreadId());
}
void unregisterMouseWheelHook()
{
if (--mouseHookUsers == 0 && mouseWheelHook != 0)
{
UnhookWindowsHookEx (mouseWheelHook);
mouseWheelHook = 0;
}
}
#if JUCE_WINDOWS
static bool messageThreadIsDefinitelyCorrect = false;
#endif
}
//==============================================================================
@@ -978,7 +938,7 @@ public:
if (filter == nullptr)
return 0;
chunkMemory.setSize (0);
chunkMemory.reset();
if (onlyStoreCurrentProgramData)
filter->getCurrentProgramStateInformation (chunkMemory);
else
@@ -997,7 +957,7 @@ public:
{
if (filter != nullptr)
{
chunkMemory.setSize (0);
chunkMemory.reset();
chunkMemoryTime = 0;
if (byteSize > 0 && data != nullptr)
@@ -1024,8 +984,8 @@ public:
&& chunkMemoryTime < juce::Time::getApproximateMillisecondCounter() - 2000
&& ! recursionCheck)
{
chunkMemory.reset();
chunkMemoryTime = 0;
chunkMemory.setSize (0);
}
#if JUCE_MAC
@@ -1302,17 +1262,11 @@ public:
#if JUCE_WINDOWS
if (! getHostType().isReceptor())
addMouseListener (this, true);
registerMouseWheelHook();
#endif
}
~EditorCompWrapper()
{
#if JUCE_WINDOWS
unregisterMouseWheelHook();
#endif
deleteAllChildren(); // note that we can't use a ScopedPointer because the editor may
// have been transferred to another parent which takes over ownership.
}
@@ -1403,6 +1357,10 @@ public:
JuceVSTWrapper& wrapper;
FakeMouseMoveGenerator fakeMouseGenerator;
#if JUCE_WINDOWS
WindowsHooks hooks;
#endif
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (EditorCompWrapper)
};


+ 152
- 21
libs/juce/source/modules/juce_audio_plugin_client/VST3/juce_VST3_Wrapper.cpp View File

@@ -32,8 +32,26 @@
#include "../../juce_audio_processors/format_types/juce_VST3Headers.h"
#include "../utility/juce_CheckSettingMacros.h"
#include "../utility/juce_IncludeModuleHeaders.h"
#include "../utility/juce_WindowsHooks.h"
#include "../../juce_audio_processors/format_types/juce_VST3Common.h"
#ifndef JUCE_VST3_CAN_REPLACE_VST2
#define JUCE_VST3_CAN_REPLACE_VST2 1
#endif
#if JUCE_VST3_CAN_REPLACE_VST2
#if JUCE_MSVC
#pragma warning (push)
#pragma warning (disable: 4514 4996)
#endif
#include <pluginterfaces/vst2.x/vstfxstore.h>
#if JUCE_MSVC
#pragma warning (pop)
#endif
#endif
#undef Point
#undef Component
@@ -194,7 +212,6 @@ public:
{
valueNormalized = v;
changed();
owner.setParameter (paramIndex, (float) v);
return true;
}
@@ -526,6 +543,10 @@ private:
bool isNSView;
#endif
#if JUCE_WINDOWS
WindowsHooks hooks;
#endif
//==============================================================================
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (JuceVST3Editor)
};
@@ -751,10 +772,39 @@ public:
return kResultOk;
}
tresult PLUGIN_API setIoMode (Vst::IoMode) override { return kNotImplemented; }
tresult PLUGIN_API getRoutingInfo (Vst::RoutingInfo&, Vst::RoutingInfo&) override { return kNotImplemented; }
tresult PLUGIN_API setIoMode (Vst::IoMode) override { return kNotImplemented; }
tresult PLUGIN_API getRoutingInfo (Vst::RoutingInfo&, Vst::RoutingInfo&) override { return kNotImplemented; }
bool readFromMemoryStream (IBStream* state) const
#if JUCE_VST3_CAN_REPLACE_VST2
void loadVST2CompatibleState (const char* data, int size)
{
const int headerLen = htonl (*(juce::int32*) (data + 4));
const struct fxBank* bank = (const struct fxBank*) (data + (8 + headerLen));
const int version = htonl (bank->version); (void) version;
jassert ('VstW' == htonl (*(juce::int32*) data));
jassert (1 == htonl (*(juce::int32*) (data + 8))); // version should be 1 according to Steinberg's docs
jassert (cMagic == htonl (bank->chunkMagic));
jassert (chunkBankMagic == htonl (bank->fxMagic));
jassert (version == 1 || version == 2);
jassert (JucePlugin_VSTUniqueID == htonl (bank->fxID));
pluginInstance->setStateInformation (bank->content.data.chunk,
jmin ((int) (size - (bank->content.data.chunk - data)),
(int) htonl (bank->content.data.size)));
}
#endif
void loadStateData (const void* data, int size)
{
#if JUCE_VST3_CAN_REPLACE_VST2
loadVST2CompatibleState ((const char*) data, size);
#else
pluginInstance->setStateInformation (data, size);
#endif
}
bool readFromMemoryStream (IBStream* state)
{
FUnknownPtr<MemoryStream> s (state);
@@ -766,16 +816,16 @@ public:
// Adobe Audition CS6 hack to avoid trying to use corrupted streams:
if (getHostType().isAdobeAudition())
if (s->getSize() >= 5 && memcmp (s->getData(), "VC2!E", 5) == 0)
return kResultFalse;
return false;
pluginInstance->setStateInformation (s->getData(), (int) s->getSize());
loadStateData (s->getData(), (int) s->getSize());
return true;
}
return false;
}
bool readFromUnknownStream (IBStream* state) const
bool readFromUnknownStream (IBStream* state)
{
MemoryOutputStream allData;
@@ -785,9 +835,9 @@ public:
for (;;)
{
int32 bytesRead = 0;
Steinberg::int32 bytesRead = 0;
if (state->read (buffer, (int32) bytesPerBlock, &bytesRead) == kResultTrue && bytesRead > 0)
if (state->read (buffer, (Steinberg::int32) bytesPerBlock, &bytesRead) == kResultTrue && bytesRead > 0)
{
allData.write (buffer, bytesRead);
continue;
@@ -801,7 +851,7 @@ public:
if (dataSize > 0 && dataSize < 0x7fffffff)
{
pluginInstance->setStateInformation (allData.getData(), (int) dataSize);
loadStateData (allData.getData(), (int) dataSize);
return true;
}
@@ -822,16 +872,58 @@ public:
return kResultFalse;
}
#if JUCE_VST3_CAN_REPLACE_VST2
static tresult writeVST2Int (IBStream* state, int n)
{
juce::int32 t = (juce::int32) htonl (n);
return state->write (&t, 4);
}
static tresult writeVST2Header (IBStream* state)
{
tresult status = writeVST2Int (state, 'VstW');
if (status == kResultOk) status = writeVST2Int (state, 8); // header size
if (status == kResultOk) status = writeVST2Int (state, 1); // version
if (status == kResultOk) status = writeVST2Int (state, 0); // bypass
return status;
}
#endif
tresult PLUGIN_API getState (IBStream* state) override
{
if (state != nullptr)
{
juce::MemoryBlock mem;
pluginInstance->getStateInformation (mem);
return state->write (mem.getData(), (Steinberg::int32) mem.getSize());
}
if (state == nullptr)
return kInvalidArgument;
return kInvalidArgument;
juce::MemoryBlock mem;
pluginInstance->getStateInformation (mem);
#if JUCE_VST3_CAN_REPLACE_VST2
tresult status = writeVST2Header (state);
if (status != kResultOk)
return status;
const int bankBlockSize = 160;
struct fxBank bank;
zerostruct (bank);
bank.chunkMagic = htonl (cMagic);
bank.byteSize = htonl (bankBlockSize - 8 + (unsigned int) mem.getSize());
bank.fxMagic = htonl (chunkBankMagic);
bank.version = htonl (2);
bank.fxID = htonl (JucePlugin_VSTUniqueID);
bank.fxVersion = htonl (JucePlugin_VersionCode);
bank.content.data.size = htonl ((unsigned int) mem.getSize());
status = state->write (&bank, bankBlockSize);
if (status != kResultOk)
return status;
#endif
return state->write (mem.getData(), (Steinberg::int32) mem.getSize());
}
//==============================================================================
@@ -1242,11 +1334,50 @@ private:
DECLARE_CLASS_IID (JuceAudioProcessor, 0x0101ABAB, 0xABCDEF01, JucePlugin_ManufacturerCode, JucePlugin_PluginCode)
DEF_CLASS_IID (JuceAudioProcessor)
DECLARE_CLASS_IID (JuceVST3Component, 0xABCDEF01, 0x9182FAEB, JucePlugin_ManufacturerCode, JucePlugin_PluginCode)
DEF_CLASS_IID (JuceVST3Component)
#if JUCE_VST3_CAN_REPLACE_VST2
// NB: Nasty old-fashioned code in here because it's copied from the Steinberg example code.
static FUID getFUIDForVST2ID (bool forControllerUID)
{
char uidString[33];
const int vstfxid = (('V' << 16) | ('S' << 8) | (forControllerUID ? 'E' : 'T'));
char vstfxidStr[7] = { 0 };
sprintf (vstfxidStr, "%06X", vstfxid);
strcpy (uidString, vstfxidStr);
char uidStr[9] = { 0 };
sprintf (uidStr, "%08X", JucePlugin_VSTUniqueID);
strcat (uidString, uidStr);
char nameidStr[3] = { 0 };
const size_t len = strlen (JucePlugin_Name);
for (size_t i = 0; i <= 8; ++i)
{
juce::uint8 c = i < len ? JucePlugin_Name[i] : 0;
if (c >= 'A' && c <= 'Z')
c += 'a' - 'A';
DECLARE_CLASS_IID (JuceVST3EditController, 0xABCDEF01, 0x1234ABCD, JucePlugin_ManufacturerCode, JucePlugin_PluginCode)
DEF_CLASS_IID (JuceVST3EditController)
sprintf (nameidStr, "%02X", c);
strcat (uidString, nameidStr);
}
FUID newOne;
newOne.fromString (uidString);
return newOne;
}
const Steinberg::FUID JuceVST3Component ::iid (getFUIDForVST2ID (false));
const Steinberg::FUID JuceVST3EditController::iid (getFUIDForVST2ID (true));
#else
DECLARE_CLASS_IID (JuceVST3EditController, 0xABCDEF01, 0x1234ABCD, JucePlugin_ManufacturerCode, JucePlugin_PluginCode)
DEF_CLASS_IID (JuceVST3EditController)
DECLARE_CLASS_IID (JuceVST3Component, 0xABCDEF01, 0x9182FAEB, JucePlugin_ManufacturerCode, JucePlugin_PluginCode)
DEF_CLASS_IID (JuceVST3Component)
#endif
#if JUCE_MSVC
#pragma warning (pop)


+ 7
- 1
libs/juce/source/modules/juce_audio_processors/format_types/juce_VST3PluginFormat.cpp View File

@@ -224,6 +224,8 @@ static void toProcessContext (Vst::ProcessContext& context, AudioPlayHead* playH
}
break;
case AudioPlayHead::fpsUnknown: break;
default: jassertfalse; break; // New frame rate?
}
@@ -1634,7 +1636,11 @@ public:
bool hasEditor() const override
{
ComSmartPtr<IPlugView> view (tryCreatingView()); //N.B.: Must use a ComSmartPtr to not delete the view from the plugin permanently!
// (if possible, avoid creating a second instance of the editor, because that crashes some plugins)
if (getActiveEditor() != nullptr)
return true;
ComSmartPtr<IPlugView> view (tryCreatingView());
return view != nullptr;
}


+ 2
- 3
libs/juce/source/modules/juce_audio_utils/gui/juce_AudioThumbnail.cpp View File

@@ -712,10 +712,9 @@ void AudioThumbnail::addBlock (const int64 startSample, const AudioSampleBuffer&
for (int i = 0; i < numToDo; ++i)
{
float low, high;
const int start = i * samplesPerThumbSample;
FloatVectorOperations::findMinAndMax (sourceData + start, jmin (samplesPerThumbSample, numSamples - start), low, high);
dest[i].setFloat (low, high);
Range<float> range (FloatVectorOperations::findMinAndMax (sourceData + start, jmin (samplesPerThumbSample, numSamples - start)));
dest[i].setFloat (range.getStart(), range.getEnd());
}
}


+ 1
- 1
libs/juce/source/modules/juce_core/files/juce_File.cpp View File

@@ -754,7 +754,7 @@ String File::createLegalPathName (const String& original)
String s (original);
String start;
if (s[1] == ':')
if (s.isNotEmpty() && s[1] == ':')
{
start = s.substring (0, 2);
s = s.substring (2);


+ 34
- 1
libs/juce/source/modules/juce_core/maths/juce_Range.h View File

@@ -34,6 +34,9 @@
/** A general-purpose range object, that simply represents any linear range with
a start and end point.
Note that when checking whether values fall within the range, the start value is
considered to be inclusive, and the end of the range exclusive.
The templated parameter is expected to be a primitive integer or floating point
type, though class types could also be used if they behave in a number-like way.
*/
@@ -210,7 +213,10 @@ public:
return jlimit (start, end, value);
}
/** Returns true if the given range lies entirely inside this range. */
/** Returns true if the given range lies entirely inside this range.
When making this comparison, the start value is considered to be inclusive,
and the end of the range exclusive.
*/
bool contains (Range other) const noexcept
{
return start <= other.start && end >= other.end;
@@ -237,6 +243,13 @@ public:
jmax (end, other.end));
}
/** Returns the smallest range that contains both this one and the given value. */
Range getUnionWith (const ValueType valueToInclude) const noexcept
{
return Range (jmin (valueToInclude, start),
jmax (valueToInclude, end));
}
/** Returns a given range, after moving it forwards or backwards to fit it
within this range.
@@ -255,6 +268,26 @@ public:
: rangeToConstrain.movedToStartAt (jlimit (start, end - otherLen, rangeToConstrain.getStart()));
}
/** Scans an array of values for its min and max, and returns these as a Range. */
static Range findMinAndMax (const ValueType* values, int numValues) noexcept
{
if (numValues <= 0)
return Range();
const ValueType first (*values++);
Range r (first, first);
while (--numValues > 0) // (> 0 rather than >= 0 because we've already taken the first sample)
{
const ValueType v (*values++);
if (r.end < v) r.end = v;
if (v < r.start) r.start = v;
}
return r;
}
private:
//==============================================================================
ValueType start, end;


+ 7
- 2
libs/juce/source/modules/juce_core/memory/juce_MemoryBlock.cpp View File

@@ -127,8 +127,7 @@ void MemoryBlock::setSize (const size_t newSize, const bool initialiseToZero)
{
if (newSize <= 0)
{
data.free();
size = 0;
reset();
}
else
{
@@ -149,6 +148,12 @@ void MemoryBlock::setSize (const size_t newSize, const bool initialiseToZero)
}
}
void MemoryBlock::reset()
{
data.free();
size = 0;
}
void MemoryBlock::ensureSize (const size_t minimumSize, const bool initialiseToZero)
{
if (size < minimumSize)


+ 6
- 3
libs/juce/source/modules/juce_core/memory/juce_MemoryBlock.h View File

@@ -108,9 +108,9 @@ public:
/** Resizes the memory block.
This will try to keep as much of the block's current content as it can,
and can optionally be made to clear any new space that gets allocated at
the end of the block.
Any data that is present in both the old and new sizes will be retained.
When enlarging the block, the new space that is allocated at the end can either be
cleared, or left uninitialised.
@param newSize the new desired size for the block
@param initialiseNewSpaceToZero if the block gets enlarged, this determines
@@ -133,6 +133,9 @@ public:
void ensureSize (const size_t minimumSize,
bool initialiseNewSpaceToZero = false);
/** Frees all the blocks data, setting its size to 0. */
void reset();
//==============================================================================
/** Fills the entire memory block with a repeated byte value.
This is handy for clearing a block of memory to zero.


+ 1
- 6
libs/juce/source/modules/juce_core/network/juce_MACAddress.h View File

@@ -32,12 +32,7 @@
//==============================================================================
/**
A wrapper for a streaming (TCP) socket.
This allows low-level use of sockets; for an easier-to-use messaging layer on top of
sockets, you could also try the InterprocessConnection class.
@see DatagramSocket, InterprocessConnection, InterprocessConnectionServer
Represents a MAC network card adapter address ID.
*/
class JUCE_API MACAddress
{


+ 85
- 75
libs/juce/source/modules/juce_core/network/juce_URL.cpp View File

@@ -75,8 +75,7 @@ URL::URL (const URL& other)
postData (other.postData),
parameterNames (other.parameterNames),
parameterValues (other.parameterValues),
filesToUpload (other.filesToUpload),
mimeTypes (other.mimeTypes)
filesToUpload (other.filesToUpload)
{
}
@@ -87,7 +86,6 @@ URL& URL::operator= (const URL& other)
parameterNames = other.parameterNames;
parameterValues = other.parameterValues;
filesToUpload = other.filesToUpload;
mimeTypes = other.mimeTypes;
return *this;
}
@@ -98,8 +96,7 @@ bool URL::operator== (const URL& other) const
&& postData == other.postData
&& parameterNames == other.parameterNames
&& parameterValues == other.parameterValues
&& filesToUpload == other.filesToUpload
&& mimeTypes == other.mimeTypes;
&& filesToUpload == other.filesToUpload;
}
bool URL::operator!= (const URL& other) const
@@ -156,62 +153,6 @@ namespace URLHelpers
return url.indexOfChar (findStartOfNetLocation (url), '/') + 1;
}
static void createHeadersAndPostData (const URL& url, String& headers, MemoryBlock& postData)
{
MemoryOutputStream data (postData, false);
if (url.getFilesToUpload().size() > 0)
{
// need to upload some files, so do it as multi-part...
const String boundary (String::toHexString (Random::getSystemRandom().nextInt64()));
headers << "Content-Type: multipart/form-data; boundary=" << boundary << "\r\n";
data << "--" << boundary;
for (int i = 0; i < url.getParameterNames().size(); ++i)
{
data << "\r\nContent-Disposition: form-data; name=\""
<< url.getParameterNames() [i]
<< "\"\r\n\r\n"
<< url.getParameterValues() [i]
<< "\r\n--"
<< boundary;
}
for (int i = 0; i < url.getFilesToUpload().size(); ++i)
{
const File file (url.getFilesToUpload().getAllValues() [i]);
const String paramName (url.getFilesToUpload().getAllKeys() [i]);
data << "\r\nContent-Disposition: form-data; name=\"" << paramName
<< "\"; filename=\"" << file.getFileName() << "\"\r\n";
const String mimeType (url.getMimeTypesOfUploadFiles()
.getValue (paramName, String()));
if (mimeType.isNotEmpty())
data << "Content-Type: " << mimeType << "\r\n";
data << "Content-Transfer-Encoding: binary\r\n\r\n"
<< file << "\r\n--" << boundary;
}
data << "--\r\n";
}
else
{
data << getMangledParameters (url)
<< url.getPostData();
// if the user-supplied headers didn't contain a content-type, add one now..
if (! headers.containsIgnoreCase ("Content-Type"))
headers << "Content-Type: application/x-www-form-urlencoded\r\n";
headers << "Content-length: " << (int) data.getDataSize() << "\r\n";
}
}
static void concatenatePaths (String& path, const String& suffix)
{
if (! path.endsWithChar ('/'))
@@ -296,6 +237,64 @@ URL URL::getChildURL (const String& subPath) const
return u;
}
void URL::createHeadersAndPostData (String& headers, MemoryBlock& headersAndPostData) const
{
MemoryOutputStream data (headersAndPostData, false);
data << URLHelpers::getMangledParameters (*this);
if (filesToUpload.size() > 0)
{
// (this doesn't currently support mixing custom post-data with uploads..)
jassert (postData.isEmpty());
const String boundary (String::toHexString (Random::getSystemRandom().nextInt64()));
headers << "Content-Type: multipart/form-data; boundary=" << boundary << "\r\n";
data << "--" << boundary;
for (int i = 0; i < parameterNames.size(); ++i)
{
data << "\r\nContent-Disposition: form-data; name=\"" << parameterNames[i]
<< "\"\r\n\r\n" << parameterValues[i]
<< "\r\n--" << boundary;
}
for (int i = 0; i < filesToUpload.size(); ++i)
{
const Upload& f = *filesToUpload.getObjectPointerUnchecked(i);
data << "\r\nContent-Disposition: form-data; name=\"" << f.parameterName
<< "\"; filename=\"" << f.filename << "\"\r\n";
if (f.mimeType.isNotEmpty())
data << "Content-Type: " << f.mimeType << "\r\n";
data << "Content-Transfer-Encoding: binary\r\n\r\n";
if (f.data != nullptr)
data << *f.data;
else
data << f.file;
data << "\r\n--" << boundary;
}
data << "--\r\n";
}
else
{
data << postData;
// if the user-supplied headers didn't contain a content-type, add one now..
if (! headers.containsIgnoreCase ("Content-Type"))
headers << "Content-Type: application/x-www-form-urlencoded\r\n";
headers << "Content-length: " << (int) data.getDataSize() << "\r\n";
}
}
//==============================================================================
bool URL::isProbablyAWebsiteURL (const String& possibleURL)
{
@@ -339,7 +338,7 @@ InputStream* URL::createInputStream (const bool usePostCommand,
headers << "\r\n";
if (usePostCommand)
URLHelpers::createHeadersAndPostData (*this, headers, headersAndPostData);
createHeadersAndPostData (headers, headersAndPostData);
if (! headers.endsWithChar ('\n'))
headers << "\r\n";
@@ -394,33 +393,44 @@ URL URL::withParameter (const String& parameterName,
return u;
}
URL URL::withFileToUpload (const String& parameterName,
const File& fileToUpload,
const String& mimeType) const
URL URL::withPOSTData (const String& newPostData) const
{
jassert (mimeType.isNotEmpty()); // You need to supply a mime type!
URL u (*this);
u.filesToUpload.set (parameterName, fileToUpload.getFullPathName());
u.mimeTypes.set (parameterName, mimeType);
u.postData = newPostData;
return u;
}
URL URL::withPOSTData (const String& newPostData) const
URL::Upload::Upload (const String& param, const String& name,
const String& mime, const File& f, MemoryBlock* mb)
: parameterName (param), filename (name), mimeType (mime), file (f), data (mb)
{
jassert (mimeType.isNotEmpty()); // You need to supply a mime type!
}
URL URL::withUpload (Upload* const f) const
{
URL u (*this);
u.postData = newPostData;
for (int i = u.filesToUpload.size(); --i >= 0;)
if (u.filesToUpload.getObjectPointerUnchecked(i)->parameterName == f->parameterName)
u.filesToUpload.remove (i);
u.filesToUpload.add (f);
return u;
}
const StringPairArray& URL::getFilesToUpload() const
URL URL::withFileToUpload (const String& parameterName, const File& fileToUpload,
const String& mimeType) const
{
return filesToUpload;
return withUpload (new Upload (parameterName, fileToUpload.getFileName(),
mimeType, fileToUpload, nullptr));
}
const StringPairArray& URL::getMimeTypesOfUploadFiles() const
URL URL::withDataToUpload (const String& parameterName, const String& filename,
const MemoryBlock& fileContentToUpload, const String& mimeType) const
{
return mimeTypes;
return withUpload (new Upload (parameterName, filename, mimeType, File(),
new MemoryBlock (fileContentToUpload)));
}
//==============================================================================


+ 33
- 14
libs/juce/source/modules/juce_core/network/juce_URL.h View File

@@ -137,18 +137,35 @@ public:
URL withParameter (const String& parameterName,
const String& parameterValue) const;
/** Returns a copy of this URl, with a file-upload type parameter added to it.
/** Returns a copy of this URL, with a file-upload type parameter added to it.
When performing a POST where one of your parameters is a binary file, this
lets you specify the file.
Note that the filename is stored, but the file itself won't actually be read
until this URL is later used to create a network input stream.
until this URL is later used to create a network input stream. If you want to
upload data from memory, use withDataToUpload().
@see withDataToUpload
*/
URL withFileToUpload (const String& parameterName,
const File& fileToUpload,
const String& mimeType) const;
/** Returns a copy of this URL, with a file-upload type parameter added to it.
When performing a POST where one of your parameters is a binary file, this
lets you specify the file content.
Note that the filename parameter should not be a full path, it's just the
last part of the filename.
@see withFileToUpload
*/
URL withDataToUpload (const String& parameterName,
const String& filename,
const MemoryBlock& fileContentToUpload,
const String& mimeType) const;
/** Returns an array of the names of all the URL's parameters.
E.g. for the url "www.fish.com?type=haddock&amount=some+fish", this array would
@@ -175,17 +192,6 @@ public:
*/
const StringArray& getParameterValues() const noexcept { return parameterValues; }
/** Returns the set of files that should be uploaded as part of a POST operation.
This is the set of files that were added to the URL with the withFileToUpload()
method.
*/
const StringPairArray& getFilesToUpload() const;
/** Returns the set of mime types associated with each of the upload files.
*/
const StringPairArray& getMimeTypesOfUploadFiles() const;
/** Returns a copy of this URL, with a block of data to send as the POST data.
If you're setting the POST data, be careful not to have any parameters set
@@ -343,10 +349,23 @@ private:
//==============================================================================
String url, postData;
StringArray parameterNames, parameterValues;
StringPairArray filesToUpload, mimeTypes;
struct Upload : public ReferenceCountedObject
{
Upload (const String&, const String&, const String&, const File&, MemoryBlock*);
String parameterName, filename, mimeType;
File file;
ScopedPointer<MemoryBlock> data;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Upload)
};
ReferenceCountedArray<Upload> filesToUpload;
URL (const String&, int);
void addParameter (const String&, const String&);
void createHeadersAndPostData (String&, MemoryBlock&) const;
URL withUpload (Upload*) const;
JUCE_LEAK_DETECTOR (URL)
};


+ 1
- 0
libs/juce/source/modules/juce_core/system/juce_SystemStats.h View File

@@ -58,6 +58,7 @@ public:
MacOSX_10_6 = 0x1006,
MacOSX_10_7 = 0x1007,
MacOSX_10_8 = 0x1008,
MacOSX_10_9 = 0x1009,
Win2000 = 0x4105,
WinXP = 0x4106,


+ 6
- 14
libs/juce/source/modules/juce_core/threads/juce_ReadWriteLock.cpp View File

@@ -105,18 +105,8 @@ void ReadWriteLock::enterWrite() const noexcept
const Thread::ThreadID threadId = Thread::getCurrentThreadId();
const SpinLock::ScopedLockType sl (accessLock);
for (;;)
while (! tryEnterWriteInternal (threadId))
{
if (readerThreads.size() + numWriters == 0
|| threadId == writerThreadId
|| (readerThreads.size() == 1
&& readerThreads.getReference(0).threadID == threadId))
{
writerThreadId = threadId;
++numWriters;
break;
}
++numWaitingWriters;
accessLock.exit();
waitEvent.wait (100);
@@ -127,13 +117,15 @@ void ReadWriteLock::enterWrite() const noexcept
bool ReadWriteLock::tryEnterWrite() const noexcept
{
const Thread::ThreadID threadId = Thread::getCurrentThreadId();
const SpinLock::ScopedLockType sl (accessLock);
return tryEnterWriteInternal (Thread::getCurrentThreadId());
}
bool ReadWriteLock::tryEnterWriteInternal (Thread::ThreadID threadId) const noexcept
{
if (readerThreads.size() + numWriters == 0
|| threadId == writerThreadId
|| (readerThreads.size() == 1
&& readerThreads.getReference(0).threadID == threadId))
|| (readerThreads.size() == 1 && readerThreads.getReference(0).threadID == threadId))
{
writerThreadId = threadId;
++numWriters;


+ 2
- 0
libs/juce/source/modules/juce_core/threads/juce_ReadWriteLock.h View File

@@ -143,6 +143,8 @@ private:
mutable Array <ThreadRecursionCount> readerThreads;
bool tryEnterWriteInternal (Thread::ThreadID) const noexcept;
JUCE_DECLARE_NON_COPYABLE (ReadWriteLock)
};


+ 1
- 2
libs/juce/source/modules/juce_data_structures/values/juce_Value.h View File

@@ -75,8 +75,7 @@ public:
operator var() const;
/** Returns the value as a string.
This is alternative to writing things like "myValue.getValue().toString()".
This is a shortcut for "myValue.getValue().toString()".
*/
String toString() const;


+ 1
- 1
libs/juce/source/modules/juce_events/interprocess/juce_ConnectedChildProcess.cpp View File

@@ -77,7 +77,7 @@ private:
}
}
JUCE_DECLARE_NON_COPYABLE (ChildProcessPingThread)
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ChildProcessPingThread)
};
//==============================================================================


+ 1
- 1
libs/juce/source/modules/juce_events/messages/juce_MessageManager.h View File

@@ -128,7 +128,7 @@ public:
*/
Thread::ThreadID getCurrentMessageThread() const noexcept { return messageThreadId; }
/** Returns true if the caller thread has currenltly got the message manager locked.
/** Returns true if the caller thread has currently got the message manager locked.
see the MessageManagerLock class for more info about this.


+ 0
- 26
libs/juce/source/modules/juce_events/timers/juce_Timer.cpp View File

@@ -295,20 +295,12 @@ Timer::TimerThread* Timer::TimerThread::instance = nullptr;
Timer::TimerThread::LockType Timer::TimerThread::lock;
//==============================================================================
#if JUCE_DEBUG
static SortedSet <Timer*> activeTimers;
#endif
Timer::Timer() noexcept
: countdownMs (0),
periodMs (0),
previous (nullptr),
next (nullptr)
{
#if JUCE_DEBUG
const TimerThread::LockType::ScopedLockType sl (TimerThread::lock);
activeTimers.add (this);
#endif
}
Timer::Timer (const Timer&) noexcept
@@ -317,30 +309,17 @@ Timer::Timer (const Timer&) noexcept
previous (nullptr),
next (nullptr)
{
#if JUCE_DEBUG
const TimerThread::LockType::ScopedLockType sl (TimerThread::lock);
activeTimers.add (this);
#endif
}
Timer::~Timer()
{
stopTimer();
#if JUCE_DEBUG
activeTimers.removeValue (this);
#endif
}
void Timer::startTimer (const int interval) noexcept
{
const TimerThread::LockType::ScopedLockType sl (TimerThread::lock);
#if JUCE_DEBUG
// this isn't a valid object! Your timer might be a dangling pointer or something..
jassert (activeTimers.contains (this));
#endif
if (periodMs == 0)
{
countdownMs = interval;
@@ -357,11 +336,6 @@ void Timer::stopTimer() noexcept
{
const TimerThread::LockType::ScopedLockType sl (TimerThread::lock);
#if JUCE_DEBUG
// this isn't a valid object! Your timer might be a dangling pointer or something..
jassert (activeTimers.contains (this));
#endif
if (periodMs > 0)
{
TimerThread::remove (this);


+ 9
- 0
libs/juce/source/modules/juce_graphics/fonts/juce_CustomTypeface.h View File

@@ -36,6 +36,11 @@
If you want to create a copy of a native face, you can use addGlyphsFromOtherTypeface()
to copy glyphs into this face.
NOTE! For most people this class is almost certainly NOT the right tool to use!
If what you want to do is to embed a font into your exe, then your best plan is
probably to embed your TTF/OTF font file into your binary using the Introjucer,
and then call Typeface::createSystemTypefaceFor() to load it from memory.
@see Typeface, Font
*/
class JUCE_API CustomTypeface : public Typeface
@@ -108,6 +113,10 @@ public:
/** Saves this typeface as a Juce-formatted font file.
A CustomTypeface can be created to reload the data that is written - see the CustomTypeface
constructor.
NOTE! Since this class was written, support was added for loading real font files from
memory, so for most people, using Typeface::createSystemTypefaceFor() to load a real font
is more appropriate than using this class to store it in a proprietory format.
*/
bool writeToStream (OutputStream& outputStream);


+ 11
- 6
libs/juce/source/modules/juce_graphics/geometry/juce_Path.cpp View File

@@ -254,6 +254,11 @@ Rectangle<float> Path::getBoundsTransformed (const AffineTransform& transform) c
}
//==============================================================================
void Path::preallocateSpace (int numExtraCoordsToMakeSpaceFor)
{
data.ensureAllocatedSize ((int) numElements + numExtraCoordsToMakeSpaceFor);
}
void Path::startNewSubPath (const float x, const float y)
{
JUCE_CHECK_COORDS_ARE_VALID (x, y);
@@ -263,7 +268,7 @@ void Path::startNewSubPath (const float x, const float y)
else
bounds.extend (x, y);
data.ensureAllocatedSize ((int) numElements + 3);
preallocateSpace (3);
data.elements [numElements++] = moveMarker;
data.elements [numElements++] = x;
@@ -282,7 +287,7 @@ void Path::lineTo (const float x, const float y)
if (numElements == 0)
startNewSubPath (0, 0);
data.ensureAllocatedSize ((int) numElements + 3);
preallocateSpace (3);
data.elements [numElements++] = lineMarker;
data.elements [numElements++] = x;
@@ -305,7 +310,7 @@ void Path::quadraticTo (const float x1, const float y1,
if (numElements == 0)
startNewSubPath (0, 0);
data.ensureAllocatedSize ((int) numElements + 5);
preallocateSpace (5);
data.elements [numElements++] = quadMarker;
data.elements [numElements++] = x1;
@@ -334,7 +339,7 @@ void Path::cubicTo (const float x1, const float y1,
if (numElements == 0)
startNewSubPath (0, 0);
data.ensureAllocatedSize ((int) numElements + 7);
preallocateSpace (7);
data.elements [numElements++] = cubicMarker;
data.elements [numElements++] = x1;
@@ -362,7 +367,7 @@ void Path::closeSubPath()
if (numElements > 0
&& data.elements [numElements - 1] != closeSubPathMarker)
{
data.ensureAllocatedSize ((int) numElements + 1);
preallocateSpace (1);
data.elements [numElements++] = closeSubPathMarker;
}
}
@@ -399,7 +404,7 @@ void Path::addRectangle (const float x, const float y,
if (w < 0) std::swap (x1, x2);
if (h < 0) std::swap (y1, y2);
data.ensureAllocatedSize ((int) numElements + 13);
preallocateSpace (13);
if (numElements == 0)
{


+ 13
- 2
libs/juce/source/modules/juce_graphics/geometry/juce_Path.h View File

@@ -560,6 +560,18 @@ public:
*/
void swapWithPath (Path&) noexcept;
//==============================================================================
/** Preallocates enough space for adding the given number of coordinates to the path.
If you're about to add a large number of lines or curves to the path, it can make
the task much more efficient to call this first and avoid costly reallocations
as the structure grows.
The actual value to pass is a bit tricky to calculate because the space required
depends on what you're adding - e.g. each lineTo() or startNewSubPath() will
require 3 coords (x, y and a type marker). Each quadraticTo() will need 5, and
a cubicTo() will require 7. Closing a sub-path will require 1.
*/
void preallocateSpace (int numExtraCoordsToMakeSpaceFor);
//==============================================================================
/** Applies a 2D transform to all the vertices in the path.
@@ -742,12 +754,11 @@ public:
*/
void restoreFromString (StringRef stringVersion);
private:
//==============================================================================
friend class PathFlatteningIterator;
friend class Path::Iterator;
ArrayAllocationBase <float, DummyCriticalSection> data;
ArrayAllocationBase<float, DummyCriticalSection> data;
size_t numElements;
struct PathBounds


+ 54
- 45
libs/juce/source/modules/juce_graphics/native/juce_RenderingHelpers.h View File

@@ -164,53 +164,16 @@ public:
//==============================================================================
void drawGlyph (RenderTargetType& target, const Font& font, const int glyphNumber, Point<float> pos)
{
++accessCounter;
CachedGlyphType* glyph = nullptr;
const ScopedReadLock srl (lock);
for (int i = glyphs.size(); --i >= 0;)
{
CachedGlyphType* const g = glyphs.getUnchecked (i);
if (g->glyph == glyphNumber && g->font == font)
{
glyph = g;
++hits;
break;
}
}
if (glyph == nullptr)
if (ReferenceCountedObjectPtr<CachedGlyphType> glyph = findOrCreateGlyph (font, glyphNumber))
{
++misses;
const ScopedWriteLock swl (lock);
if (hits.value + misses.value > glyphs.size() * 16)
{
if (misses.value * 2 > hits.value)
addNewGlyphSlots (32);
hits.set (0);
misses.set (0);
glyph = glyphs.getLast();
}
else
{
glyph = findLeastRecentlyUsedGlyph();
}
jassert (glyph != nullptr);
glyph->generate (font, glyphNumber);
glyph->lastAccessCount = ++accessCounter;
glyph->draw (target, pos);
}
glyph->lastAccessCount = accessCounter.value;
glyph->draw (target, pos);
}
void reset()
{
const ScopedWriteLock swl (lock);
const ScopedLock sl (lock);
glyphs.clear();
addNewGlyphSlots (120);
hits.set (0);
@@ -219,9 +182,54 @@ public:
private:
friend struct ContainerDeletePolicy<CachedGlyphType>;
OwnedArray<CachedGlyphType> glyphs;
ReferenceCountedArray<CachedGlyphType> glyphs;
Atomic<int> accessCounter, hits, misses;
ReadWriteLock lock;
CriticalSection lock;
ReferenceCountedObjectPtr<CachedGlyphType> findOrCreateGlyph (const Font& font, int glyphNumber)
{
const ScopedLock sl (lock);
if (CachedGlyphType* g = findExistingGlyph (font, glyphNumber))
{
++hits;
return g;
}
++misses;
CachedGlyphType* g = getGlyphForReuse();
jassert (g != nullptr);
g->generate (font, glyphNumber);
return g;
}
CachedGlyphType* findExistingGlyph (const Font& font, int glyphNumber) const
{
for (int i = 0; i < glyphs.size(); ++i)
{
CachedGlyphType* const g = glyphs.getUnchecked (i);
if (g->glyph == glyphNumber && g->font == font)
return g;
}
return nullptr;
}
CachedGlyphType* getGlyphForReuse()
{
if (hits.value + misses.value > glyphs.size() * 16)
{
if (misses.value * 2 > hits.value)
addNewGlyphSlots (32);
hits.set (0);
misses.set (0);
return glyphs.getLast();
}
return findLeastRecentlyUsedGlyph();
}
void addNewGlyphSlots (int num)
{
@@ -240,7 +248,8 @@ private:
{
CachedGlyphType* const glyph = glyphs.getUnchecked(i);
if (glyph->lastAccessCount <= oldestCounter)
if (glyph->lastAccessCount <= oldestCounter
&& glyph->getReferenceCount() == 1)
{
oldestCounter = glyph->lastAccessCount;
oldest = glyph;