diff --git a/JuceLibraryCode/modules/juce_audio_basics/effects/juce_FFT.cpp b/JuceLibraryCode/modules/juce_audio_basics/effects/juce_FFT.cpp new file mode 100644 index 0000000..afb4ced --- /dev/null +++ b/JuceLibraryCode/modules/juce_audio_basics/effects/juce_FFT.cpp @@ -0,0 +1,277 @@ +/* + ============================================================================== + + This file is part of the JUCE library. + Copyright (c) 2015 - ROLI Ltd. + + Permission is granted to use this software under the terms of either: + a) the GPL v2 (or any later version) + b) the Affero GPL v3 + + Details of these licenses can be found at: www.gnu.org/licenses + + JUCE is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + To release a closed-source product which uses JUCE, commercial licenses are + available: visit www.juce.com for more information. + + ============================================================================== +*/ + +// (For the moment, we'll implement a few local operators for this complex class - one +// day we'll probably either have a juce complex class, or use the C++11 one) +static FFT::Complex operator+ (FFT::Complex a, FFT::Complex b) noexcept { FFT::Complex c = { a.r + b.r, a.i + b.i }; return c; } +static FFT::Complex operator- (FFT::Complex a, FFT::Complex b) noexcept { FFT::Complex c = { a.r - b.r, a.i - b.i }; return c; } +static FFT::Complex operator* (FFT::Complex a, FFT::Complex b) noexcept { FFT::Complex c = { a.r * b.r - a.i * b.i, a.r * b.i + a.i * b.r }; return c; } +static FFT::Complex& operator+= (FFT::Complex& a, FFT::Complex b) noexcept { a.r += b.r; a.i += b.i; return a; } + +//============================================================================== +struct FFT::FFTConfig +{ + FFTConfig (int sizeOfFFT, bool isInverse) + : fftSize (sizeOfFFT), inverse (isInverse), twiddleTable ((size_t) sizeOfFFT) + { + for (int i = 0; i < fftSize; ++i) + { + const double phase = (isInverse ? 2.0 : -2.0) * double_Pi * i / fftSize; + twiddleTable[i].r = (float) cos (phase); + twiddleTable[i].i = (float) sin (phase); + } + + const int root = (int) std::sqrt ((double) fftSize); + int divisor = 4, n = fftSize; + + for (int i = 0; i < numElementsInArray (factors); ++i) + { + while ((n % divisor) != 0) + { + if (divisor == 2) divisor = 3; + else if (divisor == 4) divisor = 2; + else divisor += 2; + + if (divisor > root) + divisor = n; + } + + n /= divisor; + + jassert (divisor == 1 || divisor == 2 || divisor == 4); + factors[i].radix = divisor; + factors[i].length = n; + } + } + + void perform (const Complex* input, Complex* output) const noexcept + { + perform (input, output, 1, 1, factors); + } + + const int fftSize; + const bool inverse; + + struct Factor { int radix, length; }; + Factor factors[32]; + HeapBlock twiddleTable; + + void perform (const Complex* input, Complex* output, const int stride, const int strideIn, const Factor* facs) const noexcept + { + const Factor factor (*facs++); + Complex* const originalOutput = output; + const Complex* const outputEnd = output + factor.radix * factor.length; + + if (stride == 1 && factor.radix <= 5) + { + for (int i = 0; i < factor.radix; ++i) + perform (input + stride * strideIn * i, output + i * factor.length, stride * factor.radix, strideIn, facs); + + butterfly (factor, output, stride); + return; + } + + if (factor.length == 1) + { + do + { + *output++ = *input; + input += stride * strideIn; + } + while (output < outputEnd); + } + else + { + do + { + perform (input, output, stride * factor.radix, strideIn, facs); + input += stride * strideIn; + output += factor.length; + } + while (output < outputEnd); + } + + butterfly (factor, originalOutput, stride); + } + + void butterfly (const Factor factor, Complex* data, const int stride) const noexcept + { + switch (factor.radix) + { + case 1: break; + case 2: butterfly2 (data, stride, factor.length); return; + case 4: butterfly4 (data, stride, factor.length); return; + default: jassertfalse; break; + } + + Complex* scratch = static_cast (alloca (sizeof (Complex) * (size_t) factor.radix)); + + for (int i = 0; i < factor.length; ++i) + { + for (int k = i, q1 = 0; q1 < factor.radix; ++q1) + { + scratch[q1] = data[k]; + k += factor.length; + } + + for (int k = i, q1 = 0; q1 < factor.radix; ++q1) + { + int twiddleIndex = 0; + data[k] = scratch[0]; + + for (int q = 1; q < factor.radix; ++q) + { + twiddleIndex += stride * k; + + if (twiddleIndex >= fftSize) + twiddleIndex -= fftSize; + + data[k] += scratch[q] * twiddleTable[twiddleIndex]; + } + + k += factor.length; + } + } + } + + void butterfly2 (Complex* data, const int stride, const int length) const noexcept + { + Complex* dataEnd = data + length; + const Complex* tw = twiddleTable; + + for (int i = length; --i >= 0;) + { + const Complex s (*dataEnd * *tw); + tw += stride; + *dataEnd++ = *data - s; + *data++ += s; + } + } + + void butterfly4 (Complex* data, const int stride, const int length) const noexcept + { + const int lengthX2 = length * 2; + const int lengthX3 = length * 3; + + const Complex* twiddle1 = twiddleTable; + const Complex* twiddle2 = twiddle1; + const Complex* twiddle3 = twiddle1; + + for (int i = length; --i >= 0;) + { + const Complex s0 = data[length] * *twiddle1; + const Complex s1 = data[lengthX2] * *twiddle2; + const Complex s2 = data[lengthX3] * *twiddle3; + const Complex s3 = s0 + s2; + const Complex s4 = s0 - s2; + const Complex s5 = *data - s1; + *data += s1; + data[lengthX2] = *data - s3; + twiddle1 += stride; + twiddle2 += stride * 2; + twiddle3 += stride * 3; + *data += s3; + + if (inverse) + { + data[length].r = s5.r - s4.i; + data[length].i = s5.i + s4.r; + data[lengthX3].r = s5.r + s4.i; + data[lengthX3].i = s5.i - s4.r; + } + else + { + data[length].r = s5.r + s4.i; + data[length].i = s5.i - s4.r; + data[lengthX3].r = s5.r - s4.i; + data[lengthX3].i = s5.i + s4.r; + } + + ++data; + } + } + + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (FFTConfig) +}; + + +//============================================================================== +FFT::FFT (int order, bool inverse) : config (new FFTConfig (1 << order, inverse)), size (1 << order) {} +FFT::~FFT() {} + +void FFT::perform (const Complex* const input, Complex* const output) const noexcept +{ + config->perform (input, output); +} + +void FFT::performRealOnlyForwardTransform (float* d) const noexcept +{ + // This can only be called on an FFT object that was created to do forward transforms. + jassert (! config->inverse); + + Complex* const scratch = static_cast (alloca (16 + sizeof (Complex) * (size_t) size)); + + for (int i = 0; i < size; ++i) + { + scratch[i].r = d[i]; + scratch[i].i = 0; + } + + perform (scratch, reinterpret_cast (d)); +} + +void FFT::performRealOnlyInverseTransform (float* d) const noexcept +{ + // This can only be called on an FFT object that was created to do inverse transforms. + jassert (config->inverse); + + Complex* const scratch = static_cast (alloca (16 + sizeof (Complex) * (size_t) size)); + + perform (reinterpret_cast (d), scratch); + + const float scaleFactor = 1.0f / size; + + for (int i = 0; i < size; ++i) + { + d[i] = scratch[i].r * scaleFactor; + d[i + size] = scratch[i].i * scaleFactor; + } +} + +void FFT::performFrequencyOnlyForwardTransform (float* d) const noexcept +{ + performRealOnlyForwardTransform (d); + const int twiceSize = size * 2; + + for (int i = 0; i < twiceSize; i += 2) + { + d[i / 2] = juce_hypot (d[i], d[i + 1]); + + if (i >= size) + { + d[i] = 0; + d[i + 1] = 0; + } + } +} diff --git a/JuceLibraryCode/modules/juce_audio_basics/effects/juce_FFT.h b/JuceLibraryCode/modules/juce_audio_basics/effects/juce_FFT.h new file mode 100644 index 0000000..cd0e502 --- /dev/null +++ b/JuceLibraryCode/modules/juce_audio_basics/effects/juce_FFT.h @@ -0,0 +1,92 @@ +/* + ============================================================================== + + This file is part of the JUCE library. + Copyright (c) 2015 - ROLI Ltd. + + Permission is granted to use this software under the terms of either: + a) the GPL v2 (or any later version) + b) the Affero GPL v3 + + Details of these licenses can be found at: www.gnu.org/licenses + + JUCE is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + To release a closed-source product which uses JUCE, commercial licenses are + available: visit www.juce.com for more information. + + ============================================================================== +*/ + +/** + A very minimal FFT class. + + This is only a simple low-footprint implementation and isn't tuned for speed - it may + be useful for simple applications where one of the more complex FFT libraries would be + overkill. (But in the future it may end up becoming optimised of course...) + + The FFT class itself contains lookup tables, so there's some overhead in creating + one, you should create and cache an FFT object for each size/direction of transform + that you need, and re-use them to perform the actual operation. +*/ +class JUCE_API FFT +{ +public: + /** Initialises an object for performing either a forward or inverse FFT with the given size. + The the number of points the FFT will operate on will be 2 ^ order. + */ + FFT (int order, bool isInverse); + + /** Destructor. */ + ~FFT(); + + /** A complex number, for the purposes of the FFT class. */ + struct Complex + { + float r; /**< Real part. */ + float i; /**< Imaginary part. */ + }; + + /** Performs an out-of-place FFT, either forward or inverse depending on the mode + that was passed to this object's constructor. + + The arrays must contain at least getSize() elements. + */ + void perform (const Complex* input, Complex* output) const noexcept; + + /** Performs an in-place forward transform on a block of real data. + + The size of the array passed in must be 2 * getSize(), and the first half + should contain your raw input sample data. On return, the array will contain + complex frequency + phase data, and can be passed to performRealOnlyInverseTransform() + in order to convert it back to reals. + */ + void performRealOnlyForwardTransform (float* inputOutputData) const noexcept; + + /** Performs a reverse operation to data created in performRealOnlyForwardTransform(). + + The size of the array passed in must be 2 * getSize(), containing complex + frequency and phase data. On return, the first half of the array will contain + the reconstituted samples. + */ + void performRealOnlyInverseTransform (float* inputOutputData) const noexcept; + + /** Takes an array and simply transforms it to the frequency spectrum. + This may be handy for things like frequency displays or analysis. + */ + void performFrequencyOnlyForwardTransform (float* inputOutputData) const noexcept; + + /** Returns the number of data points that this FFT was created to work with. */ + int getSize() const noexcept { return size; } + +private: + struct FFTConfig; + ScopedPointer config; + const int size; + + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (FFT) +}; diff --git a/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/include/private/stream_encoder.h b/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/include/private/stream_encoder.h new file mode 100644 index 0000000..6a75d6d --- /dev/null +++ b/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/libFLAC/include/private/stream_encoder.h @@ -0,0 +1,67 @@ +/* libFLAC - Free Lossless Audio Codec library + * Copyright (C) 2000-2009 Josh Coalson + * Copyright (C) 2011-2014 Xiph.Org Foundation + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of the Xiph.org Foundation nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef FLAC__PRIVATE__STREAM_ENCODER_H +#define FLAC__PRIVATE__STREAM_ENCODER_H + +#ifdef HAVE_CONFIG_H +#include +#endif + +/* + * This is used to avoid overflow with unusual signals in 32-bit + * accumulator in the *precompute_partition_info_sums_* functions. + */ +#define FLAC__MAX_EXTRA_RESIDUAL_BPS 4 + +#if (defined FLAC__CPU_IA32 || defined FLAC__CPU_X86_64) && defined FLAC__HAS_X86INTRIN +#include "cpu.h" +#include "../../../format.h" + +#ifdef FLAC__SSE2_SUPPORTED +extern void FLAC__precompute_partition_info_sums_intrin_sse2(const FLAC__int32 residual[], FLAC__uint64 abs_residual_partition_sums[], + unsigned residual_samples, unsigned predictor_order, unsigned min_partition_order, unsigned max_partition_order, unsigned bps); +#endif + +#ifdef FLAC__SSSE3_SUPPORTED +extern void FLAC__precompute_partition_info_sums_intrin_ssse3(const FLAC__int32 residual[], FLAC__uint64 abs_residual_partition_sums[], + unsigned residual_samples, unsigned predictor_order, unsigned min_partition_order, unsigned max_partition_order, unsigned bps); +#endif + +#ifdef FLAC__AVX2_SUPPORTED +extern void FLAC__precompute_partition_info_sums_intrin_avx2(const FLAC__int32 residual[], FLAC__uint64 abs_residual_partition_sums[], + unsigned residual_samples, unsigned predictor_order, unsigned min_partition_order, unsigned max_partition_order, unsigned bps); +#endif + +#endif + +#endif diff --git a/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/win_utf8_io.h b/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/win_utf8_io.h new file mode 100644 index 0000000..1d15339 --- /dev/null +++ b/JuceLibraryCode/modules/juce_audio_formats/codecs/flac/win_utf8_io.h @@ -0,0 +1,69 @@ +/* libFLAC - Free Lossless Audio Codec library + * Copyright (C) 2013-2014 Xiph.Org Foundation + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of the Xiph.org Foundation nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifdef _WIN32 + +#ifndef flac__win_utf8_io_h +#define flac__win_utf8_io_h + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include +#include + +int get_utf8_argv(int *argc, char ***argv); + +int printf_utf8(const char *format, ...); +int fprintf_utf8(FILE *stream, const char *format, ...); +int vfprintf_utf8(FILE *stream, const char *format, va_list argptr); + +FILE *fopen_utf8(const char *filename, const char *mode); +int stat_utf8(const char *path, struct stat *buffer); +int _stat64_utf8(const char *path, struct __stat64 *buffer); +int chmod_utf8(const char *filename, int pmode); +int utime_utf8(const char *filename, struct utimbuf *times); +int unlink_utf8(const char *filename); +int rename_utf8(const char *oldname, const char *newname); +size_t strlen_utf8(const char *str); +int win_get_console_width(void); +int print_console(FILE *stream, const wchar_t *text, size_t len); +HANDLE WINAPI CreateFile_utf8(const char *lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif +#endif diff --git a/JuceLibraryCode/modules/juce_audio_processors/processors/juce_AudioProcessorParameter.h b/JuceLibraryCode/modules/juce_audio_processors/processors/juce_AudioProcessorParameter.h new file mode 100644 index 0000000..0708956 --- /dev/null +++ b/JuceLibraryCode/modules/juce_audio_processors/processors/juce_AudioProcessorParameter.h @@ -0,0 +1,158 @@ +/* + ============================================================================== + + This file is part of the JUCE library. + Copyright (c) 2015 - ROLI Ltd. + + Permission is granted to use this software under the terms of either: + a) the GPL v2 (or any later version) + b) the Affero GPL v3 + + Details of these licenses can be found at: www.gnu.org/licenses + + JUCE is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + To release a closed-source product which uses JUCE, commercial licenses are + available: visit www.juce.com for more information. + + ============================================================================== +*/ + +#ifndef JUCE_AUDIOPROCESSORPARAMETER_H_INCLUDED +#define JUCE_AUDIOPROCESSORPARAMETER_H_INCLUDED + + +//============================================================================== +/** An abstract base class for parameter objects that can be added to an + AudioProcessor. + + @see AudioProcessor::addParameter +*/ +class JUCE_API AudioProcessorParameter +{ +public: + AudioProcessorParameter() noexcept; + + /** Destructor. */ + virtual ~AudioProcessorParameter(); + + /** Called by the host to find out the value of this parameter. + + Hosts will expect the value returned to be between 0 and 1.0. + + This could be called quite frequently, so try to make your code efficient. + It's also likely to be called by non-UI threads, so the code in here should + be thread-aware. + */ + virtual float getValue() const = 0; + + /** The host will call this method to change the value of one of the filter's parameters. + + The host may call this at any time, including during the audio processing + callback, so the filter has to process this very fast and avoid blocking. + + If you want to set the value of a parameter internally, e.g. from your + editor component, then don't call this directly - instead, use the + setValueNotifyingHost() method, which will also send a message to + the host telling it about the change. If the message isn't sent, the host + won't be able to automate your parameters properly. + + The value passed will be between 0 and 1.0. + */ + virtual void setValue (float newValue) = 0; + + /** Your filter can call this when it needs to change one of its parameters. + + This could happen when the editor or some other internal operation changes + a parameter. This method will call the setValue() method to change the + value, and will then send a message to the host telling it about the change. + + Note that to make sure the host correctly handles automation, you should call + the beginChangeGesture() and endChangeGesture() methods to tell the host when + the user has started and stopped changing the parameter. + */ + void setValueNotifyingHost (float newValue); + + /** Sends a signal to the host to tell it that the user is about to start changing this + parameter. + This allows the host to know when a parameter is actively being held by the user, and + it may use this information to help it record automation. + If you call this, it must be matched by a later call to endChangeGesture(). + */ + void beginChangeGesture(); + + /** Tells the host that the user has finished changing this parameter. + This allows the host to know when a parameter is actively being held by the user, + and it may use this information to help it record automation. + A call to this method must follow a call to beginChangeGesture(). + */ + void endChangeGesture(); + + /** This should return the default value for this parameter. */ + virtual float getDefaultValue() const = 0; + + /** Returns the name to display for this parameter, which should be made + to fit within the given string length. + */ + virtual String getName (int maximumStringLength) const = 0; + + /** Some parameters may be able to return a label string for + their units. For example "Hz" or "%". + */ + virtual String getLabel() const = 0; + + /** Returns the number of discrete interval steps that this parameter's range + should be quantised into. + + If you want a continuous range of values, don't override this method, and allow + the default implementation to return 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 getNumSteps() const; + + /** Returns a textual version of the supplied parameter value. + The default implementation just returns the floating point value + as a string, but this could do anything you need for a custom type + of value. + */ + virtual String getText (float value, int /*maximumStringLength*/) const; + + /** Should parse a string and return the appropriate value for it. */ + virtual float getValueForText (const String& text) const = 0; + + /** This can be overridden to tell the host that this parameter operates in the + reverse direction. + (Not all plugin formats or hosts will actually use this information). + */ + virtual bool isOrientationInverted() const; + + /** Returns true if the host can automate this parameter. + By default, this returns true. + */ + virtual bool isAutomatable() const; + + /** Should return true if this parameter is a "meta" parameter. + A meta-parameter is a parameter that changes other params. It is used + by some hosts (e.g. AudioUnit hosts). + By default this returns false. + */ + virtual bool isMetaParameter() const; + + /** Returns the index of this parameter in its parent processor's parameter list. */ + int getParameterIndex() const noexcept { return parameterIndex; } + +private: + friend class AudioProcessor; + AudioProcessor* processor; + int parameterIndex; + + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AudioProcessorParameter) +}; + + +#endif // JUCE_AUDIOPROCESSORPARAMETER_H_INCLUDED diff --git a/JuceLibraryCode/modules/juce_core/maths/juce_NormalisableRange.h b/JuceLibraryCode/modules/juce_core/maths/juce_NormalisableRange.h new file mode 100644 index 0000000..4a2de93 --- /dev/null +++ b/JuceLibraryCode/modules/juce_core/maths/juce_NormalisableRange.h @@ -0,0 +1,169 @@ +/* + ============================================================================== + + This file is part of the juce_core module of the JUCE library. + Copyright (c) 2015 - ROLI Ltd. + + Permission to use, copy, modify, and/or distribute this software for any purpose with + or without fee is hereby granted, provided that the above copyright notice and this + permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD + TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN + NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + + ------------------------------------------------------------------------------ + + NOTE! This permissive ISC license applies ONLY to files within the juce_core module! + All other JUCE modules are covered by a dual GPL/commercial license, so if you are + using any other modules, be sure to check that you also comply with their license. + + For more details, visit www.juce.com + + ============================================================================== +*/ + +#ifndef JUCE_NORMALISABLERANGE_H_INCLUDED +#define JUCE_NORMALISABLERANGE_H_INCLUDED + + +//============================================================================== +/** + Represents a mapping between an arbitrary range of values and a + normalised 0->1 range. + + The properties of the mapping also include an optional snapping interval + and skew-factor. + + @see Range +*/ +template +class NormalisableRange +{ +public: + /** Creates a continuous range that performs a dummy mapping. */ + NormalisableRange() noexcept : start(), end (1), interval(), skew (static_cast (1)) {} + + /** Creates a copy of another range. */ + NormalisableRange (const NormalisableRange& other) noexcept + : start (other.start), end (other.end), + interval (other.interval), skew (other.skew) + { + checkInvariants(); + } + + /** Creates a copy of another range. */ + NormalisableRange& operator= (const NormalisableRange& other) noexcept + { + start = other.start; + end = other.end; + interval = other.interval; + skew = other.skew; + checkInvariants(); + return *this; + } + + /** Creates a NormalisableRange with a given range, interval and skew factor. */ + NormalisableRange (ValueType rangeStart, + ValueType rangeEnd, + ValueType intervalValue, + ValueType skewFactor) noexcept + : start (rangeStart), end (rangeEnd), + interval (intervalValue), skew (skewFactor) + { + checkInvariants(); + } + + /** Creates a NormalisableRange with a given range and interval, but a dummy skew-factor. */ + NormalisableRange (ValueType rangeStart, + ValueType rangeEnd, + ValueType intervalValue) noexcept + : start (rangeStart), end (rangeEnd), + interval (intervalValue), skew (static_cast (1)) + { + checkInvariants(); + } + + /** Creates a NormalisableRange with a given range, continuous interval, but a dummy skew-factor. */ + NormalisableRange (ValueType rangeStart, + ValueType rangeEnd) noexcept + : start (rangeStart), end (rangeEnd), + interval(), skew (static_cast (1)) + { + checkInvariants(); + } + + /** Uses the properties of this mapping to convert a non-normalised value to + its 0->1 representation. + */ + ValueType convertTo0to1 (ValueType v) const noexcept + { + ValueType proportion = (v - start) / (end - start); + + if (skew != static_cast (1)) + proportion = std::pow (proportion, skew); + + return proportion; + } + + /** Uses the properties of this mapping to convert a normalised 0->1 value to + its full-range representation. + */ + ValueType convertFrom0to1 (ValueType proportion) const noexcept + { + if (skew != static_cast (1) && proportion > ValueType()) + proportion = std::exp (std::log (proportion) / skew); + + return start + (end - start) * proportion; + } + + /** Takes a non-normalised value and snaps it based on the interval property of + this NormalisedRange. */ + ValueType snapToLegalValue (ValueType v) const noexcept + { + if (interval > ValueType()) + v = start + interval * std::floor ((v - start) / interval + static_cast (0.5)); + + if (v <= start || end <= start) + return start; + + if (v >= end) + return end; + + return v; + } + + /** The start of the non-normalised range. */ + ValueType start; + + /** The end of the non-normalised range. */ + ValueType end; + + /** The snapping interval that should be used (in non-normalised value). Use 0 for a continuous range. */ + ValueType interval; + + /** An optional skew factor that alters the way values are distribute across the range. + + The skew factor lets you skew the mapping logarithmically so that larger or smaller + values are given a larger proportion of the avilable space. + + A factor of 1.0 has no skewing effect at all. If the factor is < 1.0, the lower end + of the range will fill more of the slider's length; if the factor is > 1.0, the upper + end of the range will be expanded. + */ + ValueType skew; + +private: + void checkInvariants() const + { + jassert (end > start); + jassert (interval >= ValueType()); + jassert (skew > ValueType()); + } +}; + + +#endif // JUCE_NORMALISABLERANGE_H_INCLUDED diff --git a/JuceLibraryCode/modules/juce_core/native/juce_curl_Network.cpp b/JuceLibraryCode/modules/juce_core/native/juce_curl_Network.cpp new file mode 100644 index 0000000..2a4d9cb --- /dev/null +++ b/JuceLibraryCode/modules/juce_core/native/juce_curl_Network.cpp @@ -0,0 +1,471 @@ +/* + ============================================================================== + + This file is part of the juce_core module of the JUCE library. + Copyright (c) 2015 - ROLI Ltd. + + Permission to use, copy, modify, and/or distribute this software for any purpose with + or without fee is hereby granted, provided that the above copyright notice and this + permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD + TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN + NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + + ------------------------------------------------------------------------------ + + NOTE! This permissive ISC license applies ONLY to files within the juce_core module! + All other JUCE modules are covered by a dual GPL/commercial license, so if you are + using any other modules, be sure to check that you also comply with their license. + + For more details, visit www.juce.com + + ============================================================================== +*/ + +class WebInputStream : public InputStream +{ +public: + WebInputStream (const String& address, bool isPost, const MemoryBlock& postData, + URL::OpenStreamProgressCallback* progressCallback, void* progressCallbackContext, + const String& headers, int timeOutMs, StringPairArray* responseHeaders, + const int maxRedirects) + : multi (nullptr), curl (nullptr), headerList (nullptr), lastError (CURLE_OK), + contentLength (-1), streamPos (0), + finished (false), skipBytes (0), + postBuffer (nullptr), postPosition (0) + { + statusCode = -1; + + if (init() && setOptions (address, timeOutMs, (responseHeaders != nullptr), + maxRedirects, headers, isPost, postData.getSize())) + { + connect (responseHeaders, isPost, postData, progressCallback, progressCallbackContext); + } + else + { + cleanup(); + } + } + + ~WebInputStream() + { + cleanup(); + } + + //============================================================================== + // Input Stream overrides + bool isError() const { return curl == nullptr || lastError != CURLE_OK; } + bool isExhausted() override { return (isError() || finished) && curlBuffer.getSize() == 0; } + int64 getPosition() override { return streamPos; } + int64 getTotalLength() override { return contentLength; } + + int read (void* buffer, int bytesToRead) override + { + return readOrSkip (buffer, bytesToRead, false); + } + + bool setPosition (int64 wantedPos) override + { + const int amountToSkip = static_cast (wantedPos - getPosition()); + + if (amountToSkip < 0) + return false; + + if (amountToSkip == 0) + return true; + + const int actuallySkipped = readOrSkip (nullptr, amountToSkip, true); + + return actuallySkipped == amountToSkip; + } + + //============================================================================== + int statusCode; + +private: + //============================================================================== + bool init() + { + multi = curl_multi_init(); + + if (multi != nullptr) + { + curl = curl_easy_init(); + + if (curl != nullptr) + if (curl_multi_add_handle (multi, curl) == CURLM_OK) + return true; + } + + cleanup(); + return false; + } + + void cleanup() + { + if (curl != nullptr) + { + curl_multi_remove_handle (multi, curl); + + if (headerList != nullptr) + { + curl_slist_free_all (headerList); + headerList = nullptr; + } + + curl_easy_cleanup (curl); + curl = nullptr; + } + + if (multi != nullptr) + { + curl_multi_cleanup (multi); + multi = nullptr; + } + } + + //============================================================================== + bool setOptions (const String& address, int timeOutMs, bool wantsHeaders, + const int maxRedirects, const String& headers, + bool isPost, size_t postSize) + { + if (curl_easy_setopt (curl, CURLOPT_URL, address.toRawUTF8()) == CURLE_OK + && curl_easy_setopt (curl, CURLOPT_WRITEDATA, this) == CURLE_OK + && curl_easy_setopt (curl, CURLOPT_WRITEFUNCTION, StaticCurlWrite) == CURLE_OK + && curl_easy_setopt (curl, CURLOPT_MAXREDIRS, static_cast (maxRedirects)) == CURLE_OK) + { + if (isPost) + { + if (curl_easy_setopt (curl, CURLOPT_READDATA, this) != CURLE_OK + || curl_easy_setopt (curl, CURLOPT_READFUNCTION, StaticCurlRead) != CURLE_OK) + return false; + + if (curl_easy_setopt (curl, CURLOPT_POST, 1) != CURLE_OK + || curl_easy_setopt (curl, CURLOPT_POSTFIELDSIZE_LARGE, static_cast (postSize)) != CURLE_OK) + return false; + } + + // do we want to parse the headers + if (wantsHeaders) + { + if (curl_easy_setopt (curl, CURLOPT_HEADERDATA, this) != CURLE_OK + || curl_easy_setopt (curl, CURLOPT_HEADERFUNCTION, StaticCurlHeader) != CURLE_OK) + return false; + } + + if (headers.isNotEmpty()) + { + const StringArray headerLines = StringArray::fromLines (headers); + + // fromLines will always return at least one line if the string is not empty + jassert (headerLines.size() > 0); + headerList = curl_slist_append (headerList, headerLines [0].toRawUTF8()); + + for (int i = 1; (i < headerLines.size() && headerList != nullptr); ++i) + headerList = curl_slist_append (headerList, headerLines [i].toRawUTF8()); + + if (headerList == nullptr) + return false; + + if (curl_easy_setopt (curl, CURLOPT_HTTPHEADER, headerList) != CURLE_OK) + return false; + } + + if (timeOutMs > 0) + { + long timeOutSecs = static_cast (ceil (static_cast (timeOutMs) / 1000.0)); + + if (curl_easy_setopt (curl, CURLOPT_CONNECTTIMEOUT, timeOutSecs) != CURLE_OK) + return false; + } + + return true; + } + + return false; + } + + void connect (StringPairArray* responseHeaders, bool isPost, const MemoryBlock& postData, + URL::OpenStreamProgressCallback* progressCallback, void* progressCallbackContext) + { + if (isPost) + postBuffer = &postData; + + size_t lastPos = static_cast (-1); + + // step until either: 1) there is an error 2) the transaction is complete + // or 3) data is in the in buffer + while ((! finished) && curlBuffer.getSize() == 0 && curl != nullptr) + { + singleStep(); + + // call callbacks if this is a post request + if (isPost && progressCallback != nullptr && lastPos != postPosition) + { + lastPos = postPosition; + + if (! progressCallback (progressCallbackContext, + static_cast (lastPos), + static_cast (postData.getSize()))) + { + // user has decided to abort the transaction + cleanup(); + return; + } + } + } + + long responseCode; + if (curl_easy_getinfo (curl, CURLINFO_RESPONSE_CODE, &responseCode) == CURLE_OK) + statusCode = static_cast (responseCode); + + // parse headers + if (responseHeaders != nullptr) + parseHttpHeaders (*responseHeaders); + + // get content length size + double curlLength; + if (curl_easy_getinfo (curl, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &curlLength) == CURLE_OK) + contentLength = static_cast (curlLength); + } + + void finish() + { + if (curl == nullptr) + return; + + for (;;) + { + int cnt = 0; + + if (CURLMsg* msg = curl_multi_info_read (multi, &cnt)) + { + if (msg->msg == CURLMSG_DONE && msg->easy_handle == curl) + { + lastError = msg->data.result; // this is the error that stopped our process from continuing + break; + } + } + else + { + break; + } + } + + finished = true; + } + + //============================================================================== + void singleStep() + { + if (curl == nullptr || lastError != CURLE_OK) + return; + + fd_set fdread, fdwrite, fdexcep; + int maxfd = -1; + long curl_timeo; + + if ((lastError = (int) curl_multi_timeout (multi, &curl_timeo)) != CURLM_OK) + return; + + // why 980? see http://curl.haxx.se/libcurl/c/curl_multi_timeout.html + if (curl_timeo < 0) + curl_timeo = 980; + + struct timeval tv; + tv.tv_sec = curl_timeo / 1000; + tv.tv_usec = (curl_timeo % 1000) * 1000; + + FD_ZERO (&fdread); + FD_ZERO (&fdwrite); + FD_ZERO (&fdexcep); + + + if ((lastError = (int) curl_multi_fdset (multi, &fdread, &fdwrite, &fdexcep, &maxfd)) != CURLM_OK) + return; + + if (maxfd != -1) + { + if (select (maxfd + 1, &fdread, &fdwrite, &fdexcep, &tv) < 0) + { + lastError = -1; + return; + } + } + else + { + // if curl does not return any sockets for to wait on, then the doc says to wait 100 ms + Thread::sleep (100); + } + + int still_running = 0; + int curlRet; + + while ((curlRet = (int) curl_multi_perform (multi, &still_running)) == CURLM_CALL_MULTI_PERFORM) + {} + + if ((lastError = curlRet) != CURLM_OK) + return; + + if (still_running <= 0) + finish(); + } + + int readOrSkip (void* buffer, int bytesToRead, bool skip) + { + if (bytesToRead <= 0) + return 0; + + size_t pos = 0; + size_t len = static_cast (bytesToRead); + + while (len > 0) + { + size_t bufferBytes = curlBuffer.getSize(); + bool removeSection = true; + + if (bufferBytes == 0) + { + // do not call curl again if we are finished + if (finished || curl == nullptr) + return static_cast (pos); + + skipBytes = skip ? len : 0; + singleStep(); + + // update the amount that was read/skipped from curl + bufferBytes = skip ? len - skipBytes : curlBuffer.getSize(); + removeSection = ! skip; + } + + // can we copy data from the internal buffer? + if (bufferBytes > 0) + { + size_t max = jmin (len, bufferBytes); + + if (! skip) + memcpy (addBytesToPointer (buffer, pos), curlBuffer.getData(), max); + + pos += max; + streamPos += static_cast (max); + len -= max; + + if (removeSection) + curlBuffer.removeSection (0, max); + } + } + + return static_cast (pos); + } + + + //============================================================================== + void parseHttpHeaders (StringPairArray& responseHeaders) + { + StringArray headerLines = StringArray::fromLines (curlHeaders); + + // ignore the first line as this is the status line + for (int i = 1; i < headerLines.size(); ++i) + { + const String& headersEntry = headerLines[i]; + + if (headersEntry.isNotEmpty()) + { + const String key (headersEntry.upToFirstOccurrenceOf (": ", false, false)); + const String value (headersEntry.fromFirstOccurrenceOf (": ", false, false)); + const String previousValue (responseHeaders [key]); + responseHeaders.set (key, previousValue.isEmpty() ? value : (previousValue + "," + value)); + } + } + } + + + //============================================================================== + // CURL callbacks + size_t curlWriteCallback (char* ptr, size_t size, size_t nmemb) + { + if (curl == nullptr || lastError != CURLE_OK) + return 0; + + const size_t len = size * nmemb; + + // skip bytes if necessary + size_t max = jmin (skipBytes, len); + skipBytes -= max; + + if (len > max) + curlBuffer.append (ptr + max, len - max); + + return len; + } + + size_t curlReadCallback (char* ptr, size_t size, size_t nmemb) + { + if (curl == nullptr || postBuffer == nullptr || lastError != CURLE_OK) + return 0; + + const size_t len = size * nmemb; + + size_t max = jmin (postBuffer->getSize() - postPosition, len); + memcpy (ptr, (char*)postBuffer->getData() + postPosition, max); + postPosition += max; + + return max; + } + + size_t curlHeaderCallback (char* ptr, size_t size, size_t nmemb) + { + if (curl == nullptr || lastError != CURLE_OK) + return 0; + + size_t len = size * nmemb; + + curlHeaders += String (ptr, len); + return len; + } + + //============================================================================== + // Static method wrappers + static size_t StaticCurlWrite (char* ptr, size_t size, size_t nmemb, void* userdata) + { + WebInputStream* wi = reinterpret_cast (userdata); + return wi->curlWriteCallback (ptr, size, nmemb); + } + + static size_t StaticCurlRead (char* ptr, size_t size, size_t nmemb, void* userdata) + { + WebInputStream* wi = reinterpret_cast (userdata); + return wi->curlReadCallback (ptr, size, nmemb); + } + + static size_t StaticCurlHeader (char* ptr, size_t size, size_t nmemb, void* userdata) + { + WebInputStream* wi = reinterpret_cast (userdata); + return wi->curlHeaderCallback (ptr, size, nmemb); + } + +private: + CURLM* multi; + CURL* curl; + struct curl_slist* headerList; + int lastError; + + //============================================================================== + // internal buffers and buffer positions + int64 contentLength, streamPos; + MemoryBlock curlBuffer; + String curlHeaders; + bool finished; + size_t skipBytes; + + //============================================================================== + // Http POST variables + const MemoryBlock* postBuffer; + size_t postPosition; + + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (WebInputStream) +}; diff --git a/JuceLibraryCode/modules/juce_core/system/juce_CompilerSupport.h b/JuceLibraryCode/modules/juce_core/system/juce_CompilerSupport.h new file mode 100644 index 0000000..af705f3 --- /dev/null +++ b/JuceLibraryCode/modules/juce_core/system/juce_CompilerSupport.h @@ -0,0 +1,160 @@ +/* + ============================================================================== + + This file is part of the juce_core module of the JUCE library. + Copyright (c) 2015 - ROLI Ltd. + + Permission to use, copy, modify, and/or distribute this software for any purpose with + or without fee is hereby granted, provided that the above copyright notice and this + permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD + TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN + NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + + ------------------------------------------------------------------------------ + + NOTE! This permissive ISC license applies ONLY to files within the juce_core module! + All other JUCE modules are covered by a dual GPL/commercial license, so if you are + using any other modules, be sure to check that you also comply with their license. + + For more details, visit www.juce.com + + ============================================================================== +*/ + +#ifndef JUCE_COMPILERSUPPORT_H_INCLUDED +#define JUCE_COMPILERSUPPORT_H_INCLUDED + +/* This file has some checks to see whether the compiler supports various C++11/14 features, + When these aren't available, the code defines a few workarounds, so that we can still use + some of the newer language features like nullptr and noexcept, even on old compilers. +*/ + +//============================================================================== +// GCC +#if (__cplusplus >= 201103L || defined (__GXX_EXPERIMENTAL_CXX0X__)) && (__GNUC__ * 100 + __GNUC_MINOR__) >= 405 + #define JUCE_COMPILER_SUPPORTS_NOEXCEPT 1 + #define JUCE_COMPILER_SUPPORTS_NULLPTR 1 + #define JUCE_COMPILER_SUPPORTS_MOVE_SEMANTICS 1 + #define JUCE_COMPILER_SUPPORTS_INITIALIZER_LISTS 1 + #define JUCE_COMPILER_SUPPORTS_VARIADIC_TEMPLATES 1 + + #if (__GNUC__ * 100 + __GNUC_MINOR__) >= 407 && ! defined (JUCE_COMPILER_SUPPORTS_OVERRIDE_AND_FINAL) + #define JUCE_COMPILER_SUPPORTS_OVERRIDE_AND_FINAL 1 + #endif + + #if (__GNUC__ * 100 + __GNUC_MINOR__) >= 407 && ! defined (JUCE_DELETED_FUNCTION) + #define JUCE_DELETED_FUNCTION = delete + #endif + + #if (__GNUC__ * 100 + __GNUC_MINOR__) >= 406 && ! defined (JUCE_COMPILER_SUPPORTS_LAMBDAS) + #define JUCE_COMPILER_SUPPORTS_LAMBDAS 1 + #endif +#endif + +//============================================================================== +// Clang +#if JUCE_CLANG && defined (__has_feature) + #if __has_feature (cxx_nullptr) + #define JUCE_COMPILER_SUPPORTS_NULLPTR 1 + #endif + + #if __has_feature (cxx_noexcept) + #define JUCE_COMPILER_SUPPORTS_NOEXCEPT 1 + #endif + + #if __has_feature (cxx_rvalue_references) + #define JUCE_COMPILER_SUPPORTS_MOVE_SEMANTICS 1 + #endif + + #if __has_feature (cxx_deleted_functions) + #define JUCE_DELETED_FUNCTION = delete + #endif + + #if __has_feature (cxx_lambdas) && (defined (_LIBCPP_VERSION) || ! (JUCE_MAC || JUCE_IOS)) + #define JUCE_COMPILER_SUPPORTS_LAMBDAS 1 + #endif + + #if __has_feature (cxx_generalized_initializers) && (defined (_LIBCPP_VERSION) || ! (JUCE_MAC || JUCE_IOS)) + #define JUCE_COMPILER_SUPPORTS_INITIALIZER_LISTS 1 + #endif + + #if __has_feature (cxx_variadic_templates) + #define JUCE_COMPILER_SUPPORTS_VARIADIC_TEMPLATES 1 + #endif + + #ifndef JUCE_COMPILER_SUPPORTS_OVERRIDE_AND_FINAL + #define JUCE_COMPILER_SUPPORTS_OVERRIDE_AND_FINAL 1 + #endif + + #ifndef JUCE_COMPILER_SUPPORTS_ARC + #define JUCE_COMPILER_SUPPORTS_ARC 1 + #endif + +#endif + +//============================================================================== +// MSVC +#ifdef _MSC_VER + #if _MSC_VER >= 1600 + #define JUCE_COMPILER_SUPPORTS_NULLPTR 1 + #define JUCE_COMPILER_SUPPORTS_MOVE_SEMANTICS 1 + #endif + + #if _MSC_VER >= 1700 + #define JUCE_COMPILER_SUPPORTS_OVERRIDE_AND_FINAL 1 + #define JUCE_COMPILER_SUPPORTS_LAMBDAS 1 + #endif + + #if _MSC_VER >= 1800 + #define JUCE_COMPILER_SUPPORTS_INITIALIZER_LISTS 1 + #define JUCE_COMPILER_SUPPORTS_VARIADIC_TEMPLATES 1 + #define JUCE_DELETED_FUNCTION = delete + #endif + + #if _MSC_VER >= 1900 + #define JUCE_COMPILER_SUPPORTS_NOEXCEPT 1 + #endif +#endif + +//============================================================================== +// Declare some fake versions of nullptr and noexcept, for older compilers: + +#ifndef JUCE_DELETED_FUNCTION + /** This macro can be placed after a method declaration to allow the use of + the C++11 feature "= delete" on all compilers. + On newer compilers that support it, it does the C++11 "= delete", but on + older ones it's just an empty definition. + */ + #define JUCE_DELETED_FUNCTION +#endif + +#if ! DOXYGEN + #if ! JUCE_COMPILER_SUPPORTS_NOEXCEPT + #ifdef noexcept + #undef noexcept + #endif + #define noexcept throw() + #if defined (_MSC_VER) && _MSC_VER > 1600 + #define _ALLOW_KEYWORD_MACROS 1 // (to stop VC2012 complaining) + #endif + #endif + + #if ! JUCE_COMPILER_SUPPORTS_NULLPTR + #ifdef nullptr + #undef nullptr + #endif + #define nullptr (0) + #endif + + #if ! JUCE_COMPILER_SUPPORTS_OVERRIDE_AND_FINAL + #undef override + #define override + #endif +#endif + +#endif // JUCE_COMPILERSUPPORT_H_INCLUDED diff --git a/JuceLibraryCode/modules/juce_data_structures/values/juce_ValueTreeSynchroniser.cpp b/JuceLibraryCode/modules/juce_data_structures/values/juce_ValueTreeSynchroniser.cpp new file mode 100644 index 0000000..2da6228 --- /dev/null +++ b/JuceLibraryCode/modules/juce_data_structures/values/juce_ValueTreeSynchroniser.cpp @@ -0,0 +1,217 @@ +/* + ============================================================================== + + This file is part of the JUCE library. + Copyright (c) 2015 - ROLI Ltd. + + Permission is granted to use this software under the terms of either: + a) the GPL v2 (or any later version) + b) the Affero GPL v3 + + Details of these licenses can be found at: www.gnu.org/licenses + + JUCE is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + To release a closed-source product which uses JUCE, commercial licenses are + available: visit www.juce.com for more information. + + ============================================================================== +*/ + +namespace ValueTreeSynchroniserHelpers +{ + enum ChangeType + { + propertyChanged = 1, + fullSync = 2, + childAdded = 3, + childRemoved = 4, + childMoved = 5 + }; + + static void getValueTreePath (ValueTree v, const ValueTree& topLevelTree, Array& path) + { + while (v != topLevelTree) + { + ValueTree parent (v.getParent()); + + if (! parent.isValid()) + break; + + path.add (parent.indexOf (v)); + v = parent; + } + } + + static void writeHeader (MemoryOutputStream& stream, ChangeType type) + { + stream.writeByte ((char) type); + } + + static void writeHeader (ValueTreeSynchroniser& target, MemoryOutputStream& stream, + ChangeType type, ValueTree v) + { + writeHeader (stream, type); + + Array path; + getValueTreePath (v, target.getRoot(), path); + + stream.writeCompressedInt (path.size()); + + for (int i = path.size(); --i >= 0;) + stream.writeCompressedInt (path.getUnchecked(i)); + } + + static ValueTree readSubTreeLocation (MemoryInputStream& input, ValueTree v) + { + const int numLevels = input.readCompressedInt(); + + if (! isPositiveAndBelow (numLevels, 65536)) // sanity-check + return ValueTree(); + + for (int i = numLevels; --i >= 0;) + { + const int index = input.readCompressedInt(); + + if (! isPositiveAndBelow (index, v.getNumChildren())) + return ValueTree(); + + v = v.getChild (index); + } + + return v; + } +} + +ValueTreeSynchroniser::ValueTreeSynchroniser (const ValueTree& tree) : valueTree (tree) +{ + valueTree.addListener (this); +} + +ValueTreeSynchroniser::~ValueTreeSynchroniser() +{ + valueTree.removeListener (this); +} + +void ValueTreeSynchroniser::sendFullSyncCallback() +{ + MemoryOutputStream m; + writeHeader (m, ValueTreeSynchroniserHelpers::fullSync); + valueTree.writeToStream (m); + stateChanged (m.getData(), m.getDataSize()); +} + +void ValueTreeSynchroniser::valueTreePropertyChanged (ValueTree& vt, const Identifier& property) +{ + MemoryOutputStream m; + ValueTreeSynchroniserHelpers::writeHeader (*this, m, ValueTreeSynchroniserHelpers::propertyChanged, vt); + m.writeString (property.toString()); + vt.getProperty (property).writeToStream (m); + stateChanged (m.getData(), m.getDataSize()); +} + +void ValueTreeSynchroniser::valueTreeChildAdded (ValueTree& parentTree, ValueTree& childTree) +{ + const int index = parentTree.indexOf (childTree); + jassert (index >= 0); + + MemoryOutputStream m; + ValueTreeSynchroniserHelpers::writeHeader (*this, m, ValueTreeSynchroniserHelpers::childAdded, parentTree); + m.writeCompressedInt (index); + childTree.writeToStream (m); + stateChanged (m.getData(), m.getDataSize()); +} + +void ValueTreeSynchroniser::valueTreeChildRemoved (ValueTree& parentTree, ValueTree&, int oldIndex) +{ + MemoryOutputStream m; + ValueTreeSynchroniserHelpers::writeHeader (*this, m, ValueTreeSynchroniserHelpers::childRemoved, parentTree); + m.writeCompressedInt (oldIndex); + stateChanged (m.getData(), m.getDataSize()); +} + +void ValueTreeSynchroniser::valueTreeChildOrderChanged (ValueTree& parent, int oldIndex, int newIndex) +{ + MemoryOutputStream m; + ValueTreeSynchroniserHelpers::writeHeader (*this, m, ValueTreeSynchroniserHelpers::childMoved, parent); + m.writeCompressedInt (oldIndex); + m.writeCompressedInt (newIndex); + stateChanged (m.getData(), m.getDataSize()); +} + +void ValueTreeSynchroniser::valueTreeParentChanged (ValueTree&) {} // (No action needed here) + +bool ValueTreeSynchroniser::applyChange (ValueTree& root, const void* data, size_t dataSize, UndoManager* undoManager) +{ + MemoryInputStream input (data, dataSize, false); + + const ValueTreeSynchroniserHelpers::ChangeType type = (ValueTreeSynchroniserHelpers::ChangeType) input.readByte(); + + if (type == ValueTreeSynchroniserHelpers::fullSync) + { + root = ValueTree::readFromStream (input); + return true; + } + + ValueTree v (ValueTreeSynchroniserHelpers::readSubTreeLocation (input, root)); + + if (! v.isValid()) + return false; + + switch (type) + { + case ValueTreeSynchroniserHelpers::propertyChanged: + { + Identifier property (input.readString()); + v.setProperty (property, var::readFromStream (input), undoManager); + return true; + } + + case ValueTreeSynchroniserHelpers::childAdded: + { + const int index = input.readCompressedInt(); + v.addChild (ValueTree::readFromStream (input), index, undoManager); + return true; + } + + case ValueTreeSynchroniserHelpers::childRemoved: + { + const int index = input.readCompressedInt(); + + if (isPositiveAndBelow (index, v.getNumChildren())) + { + v.removeChild (index, undoManager); + return true; + } + + jassertfalse; // Either received some corrupt data, or the trees have drifted out of sync + break; + } + + case ValueTreeSynchroniserHelpers::childMoved: + { + const int oldIndex = input.readCompressedInt(); + const int newIndex = input.readCompressedInt(); + + if (isPositiveAndBelow (oldIndex, v.getNumChildren()) + && isPositiveAndBelow (newIndex, v.getNumChildren())) + { + v.moveChild (oldIndex, newIndex, undoManager); + return true; + } + + jassertfalse; // Either received some corrupt data, or the trees have drifted out of sync + break; + } + + default: + jassertfalse; // Seem to have received some corrupt data? + break; + } + + return false; +} diff --git a/JuceLibraryCode/modules/juce_data_structures/values/juce_ValueTreeSynchroniser.h b/JuceLibraryCode/modules/juce_data_structures/values/juce_ValueTreeSynchroniser.h new file mode 100644 index 0000000..f442c0f --- /dev/null +++ b/JuceLibraryCode/modules/juce_data_structures/values/juce_ValueTreeSynchroniser.h @@ -0,0 +1,98 @@ +/* + ============================================================================== + + This file is part of the JUCE library. + Copyright (c) 2015 - ROLI Ltd. + + Permission is granted to use this software under the terms of either: + a) the GPL v2 (or any later version) + b) the Affero GPL v3 + + Details of these licenses can be found at: www.gnu.org/licenses + + JUCE is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + To release a closed-source product which uses JUCE, commercial licenses are + available: visit www.juce.com for more information. + + ============================================================================== +*/ + +#ifndef JUCE_VALUETREESYNCHRONISER_H_INCLUDED +#define JUCE_VALUETREESYNCHRONISER_H_INCLUDED + + +//============================================================================== +/** + This class can be used to watch for all changes to the state of a ValueTree, + and to convert them to a transmittable binary encoding. + + The purpose of this class is to allow two or more ValueTrees to be remotely + synchronised by transmitting encoded changes over some kind of transport + mechanism. + + To use it, you'll need to implement a subclass of ValueTreeSynchroniser + and implement the stateChanged() method to transmit the encoded change (maybe + via a network or other means) to a remote destination, where it can be + applied to a target tree. +*/ +class JUCE_API ValueTreeSynchroniser : private ValueTree::Listener +{ +public: + /** Creates a ValueTreeSynchroniser that watches the given tree. + + After creating an instance of this class and somehow attaching it to + a target tree, you probably want to call sendFullSyncCallback() to + get them into a common starting state. + */ + ValueTreeSynchroniser (const ValueTree& tree); + + /** Destructor. */ + virtual ~ValueTreeSynchroniser(); + + /** This callback happens when the ValueTree changes and the given state-change message + needs to be applied to any other trees that need to stay in sync with it. + The data is an opaque blob of binary that you should transmit to wherever your + target tree lives, and use applyChange() to apply this to the target tree. + */ + virtual void stateChanged (const void* encodedChange, size_t encodedChangeSize) = 0; + + /** Forces the sending of a full state message, which may be large, as it + encodes the entire ValueTree. + + This will internally invoke stateChanged() with the encoded version of the state. + */ + void sendFullSyncCallback(); + + /** Applies an encoded change to the given destination tree. + + When you implement a receiver for changes that were sent by the stateChanged() + message, this is the function that you'll need to call to apply them to the + target tree that you want to be synced. + */ + static bool applyChange (ValueTree& target, + const void* encodedChangeData, size_t encodedChangeDataSize, + UndoManager* undoManager); + + /** Returns the root ValueTree that is being observed. */ + const ValueTree& getRoot() noexcept { return valueTree; } + +private: + ValueTree valueTree; + + void valueTreePropertyChanged (ValueTree&, const Identifier&) override; + void valueTreeChildAdded (ValueTree&, ValueTree&) override; + void valueTreeChildRemoved (ValueTree&, ValueTree&, int) override; + void valueTreeChildOrderChanged (ValueTree&, int, int) override; + void valueTreeParentChanged (ValueTree&) override; + + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ValueTreeSynchroniser) +}; + + + +#endif // JUCE_VALUETREESYNCHRONISER_H_INCLUDED diff --git a/JuceLibraryCode/modules/juce_events/messages/juce_MountedVolumeListChangeDetector.h b/JuceLibraryCode/modules/juce_events/messages/juce_MountedVolumeListChangeDetector.h new file mode 100644 index 0000000..a10865b --- /dev/null +++ b/JuceLibraryCode/modules/juce_events/messages/juce_MountedVolumeListChangeDetector.h @@ -0,0 +1,59 @@ +/* + ============================================================================== + + This file is part of the JUCE library. + Copyright (c) 2015 - ROLI Ltd. + + Permission is granted to use this software under the terms of either: + a) the GPL v2 (or any later version) + b) the Affero GPL v3 + + Details of these licenses can be found at: www.gnu.org/licenses + + JUCE is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + To release a closed-source product which uses JUCE, commercial licenses are + available: visit www.juce.com for more information. + + ============================================================================== +*/ + +#ifndef JUCE_MOUNTEDVOLUMELISTCHANGEDETECTOR_H_INCLUDED +#define JUCE_MOUNTEDVOLUMELISTCHANGEDETECTOR_H_INCLUDED + +#if JUCE_MAC || JUCE_WINDOWS || defined (DOXYGEN) + +//============================================================================== +/** + An instance of this class will provide callbacks when drives are + mounted or unmounted on the system. + + Just inherit from this class and implement the pure virtual method + to get the callbacks, there's no need to do anything else. + + @see File::findFileSystemRoots() +*/ +class JUCE_API MountedVolumeListChangeDetector +{ +public: + MountedVolumeListChangeDetector(); + virtual ~MountedVolumeListChangeDetector(); + + /** This method is called when a volume is mounted or unmounted. */ + virtual void mountedVolumeListChanged() = 0; + +private: + JUCE_PUBLIC_IN_DLL_BUILD (struct Pimpl) + friend struct ContainerDeletePolicy; + ScopedPointer pimpl; + + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MountedVolumeListChangeDetector) +}; + +#endif + +#endif // JUCE_MOUNTEDVOLUMELISTCHANGEDETECTOR_H_INCLUDED diff --git a/JuceLibraryCode/modules/juce_gui_extra/misc/juce_AnimatedAppComponent.cpp b/JuceLibraryCode/modules/juce_gui_extra/misc/juce_AnimatedAppComponent.cpp new file mode 100644 index 0000000..affc7b5 --- /dev/null +++ b/JuceLibraryCode/modules/juce_gui_extra/misc/juce_AnimatedAppComponent.cpp @@ -0,0 +1,48 @@ +/* + ============================================================================== + + This file is part of the JUCE library. + Copyright (c) 2015 - ROLI Ltd. + + Permission is granted to use this software under the terms of either: + a) the GPL v2 (or any later version) + b) the Affero GPL v3 + + Details of these licenses can be found at: www.gnu.org/licenses + + JUCE is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + To release a closed-source product which uses JUCE, commercial licenses are + available: visit www.juce.com for more information. + + ============================================================================== +*/ + +AnimatedAppComponent::AnimatedAppComponent() + : lastUpdateTime (Time::getCurrentTime()), totalUpdates (0) +{ + setOpaque (true); +} + +void AnimatedAppComponent::setFramesPerSecond (int framesPerSecond) +{ + jassert (framesPerSecond > 0 && framesPerSecond < 1000); + startTimerHz (framesPerSecond); +} + +int AnimatedAppComponent::getMillisecondsSinceLastUpdate() const noexcept +{ + return (int) (Time::getCurrentTime() - lastUpdateTime).inMilliseconds(); +} + +void AnimatedAppComponent::timerCallback() +{ + ++totalUpdates; + update(); + repaint(); + lastUpdateTime = Time::getCurrentTime(); +} diff --git a/JuceLibraryCode/modules/juce_gui_extra/misc/juce_AnimatedAppComponent.h b/JuceLibraryCode/modules/juce_gui_extra/misc/juce_AnimatedAppComponent.h new file mode 100644 index 0000000..1e5380c --- /dev/null +++ b/JuceLibraryCode/modules/juce_gui_extra/misc/juce_AnimatedAppComponent.h @@ -0,0 +1,77 @@ +/* + ============================================================================== + + This file is part of the JUCE library. + Copyright (c) 2015 - ROLI Ltd. + + Permission is granted to use this software under the terms of either: + a) the GPL v2 (or any later version) + b) the Affero GPL v3 + + Details of these licenses can be found at: www.gnu.org/licenses + + JUCE is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + ------------------------------------------------------------------------------ + + To release a closed-source product which uses JUCE, commercial licenses are + available: visit www.juce.com for more information. + + ============================================================================== +*/ + +#ifndef JUCE_ANIMATEDAPPCOMPONENT_H_INCLUDED +#define JUCE_ANIMATEDAPPCOMPONENT_H_INCLUDED + + +//============================================================================== +/** + A base class for writing simple one-page graphical apps. + + A subclass can inherit from this and implement just a few methods such as + paint() and mouse-handling. The base class provides some simple abstractions + to take care of continuously repainting itself. +*/ +class AnimatedAppComponent : public Component, + private Timer +{ +public: + AnimatedAppComponent(); + + /** Your subclass can call this to start a timer running which will + call update() and repaint the component at the given frequency. + */ + void setFramesPerSecond (int framesPerSecond); + + /** Called periodically, at the frequency specified by setFramesPerSecond(). + This is a the best place to do things like advancing animation parameters, + checking the mouse position, etc. + */ + virtual void update() = 0; + + /** Returns the number of times that update() has been called since the component + started running. + */ + int getFrameCounter() const noexcept { return totalUpdates; } + + /** When called from update(), this returns the number of milliseconds since the + last update call. + This might be useful for accurately timing animations, etc. + */ + int getMillisecondsSinceLastUpdate() const noexcept; + +private: + //============================================================================== + Time lastUpdateTime; + int totalUpdates; + + void timerCallback() override; + + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AnimatedAppComponent) +}; + + + +#endif // JUCE_ANIMATEDAPPCOMPONENT_H_INCLUDED