| @@ -3940,70 +3940,250 @@ END_JUCE_NAMESPACE | |||
| /*** Start of inlined file: juce_Variant.cpp ***/ | |||
| BEGIN_JUCE_NAMESPACE | |||
| class var::VariantType | |||
| { | |||
| public: | |||
| VariantType() {} | |||
| virtual ~VariantType() {} | |||
| virtual int toInt (const ValueUnion&) const { return 0; } | |||
| virtual double toDouble (const ValueUnion&) const { return 0; } | |||
| virtual float toFloat (const ValueUnion&) const { return 0; } | |||
| virtual const String toString (const ValueUnion&) const { return String::empty; } | |||
| virtual bool toBool (const ValueUnion&) const { return false; } | |||
| virtual DynamicObject* toObject (const ValueUnion&) const { return 0; } | |||
| virtual bool isVoid() const throw() { return false; } | |||
| virtual bool isInt() const throw() { return false; } | |||
| virtual bool isBool() const throw() { return false; } | |||
| virtual bool isDouble() const throw() { return false; } | |||
| virtual bool isString() const throw() { return false; } | |||
| virtual bool isObject() const throw() { return false; } | |||
| virtual bool isMethod() const throw() { return false; } | |||
| virtual void cleanUp (ValueUnion&) const throw() {} | |||
| virtual void createCopy (ValueUnion& dest, const ValueUnion& source) const { dest = source; } | |||
| virtual bool equals (const ValueUnion& data, const ValueUnion& otherData, const VariantType& otherType) const throw() = 0; | |||
| virtual void writeToStream (const ValueUnion& data, OutputStream& output) const = 0; | |||
| }; | |||
| class var::VariantType_Void : public var::VariantType | |||
| { | |||
| public: | |||
| static const VariantType_Void* getInstance() { static const VariantType_Void i; return &i; } | |||
| bool isVoid() const throw() { return true; } | |||
| bool equals (const ValueUnion&, const ValueUnion&, const VariantType& otherType) const throw() { return otherType.isVoid(); } | |||
| void writeToStream (const ValueUnion&, OutputStream& output) const { output.writeCompressedInt (0); } | |||
| }; | |||
| class var::VariantType_Int : public var::VariantType | |||
| { | |||
| public: | |||
| static const VariantType_Int* getInstance() { static const VariantType_Int i; return &i; } | |||
| int toInt (const ValueUnion& data) const { return data.intValue; }; | |||
| double toDouble (const ValueUnion& data) const { return (double) data.intValue; } | |||
| float toFloat (const ValueUnion& data) const { return (float) data.intValue; } | |||
| const String toString (const ValueUnion& data) const { return String (data.intValue); } | |||
| bool toBool (const ValueUnion& data) const { return data.intValue != 0; } | |||
| bool isInt() const throw() { return true; } | |||
| bool equals (const ValueUnion& data, const ValueUnion& otherData, const VariantType& otherType) const throw() | |||
| { | |||
| return otherType.toInt (otherData) == data.intValue; | |||
| } | |||
| void writeToStream (const ValueUnion& data, OutputStream& output) const | |||
| { | |||
| output.writeCompressedInt (5); | |||
| output.writeByte (1); | |||
| output.writeInt (data.intValue); | |||
| } | |||
| }; | |||
| class var::VariantType_Double : public var::VariantType | |||
| { | |||
| public: | |||
| static const VariantType_Double* getInstance() { static const VariantType_Double i; return &i; } | |||
| int toInt (const ValueUnion& data) const { return (int) data.doubleValue; }; | |||
| double toDouble (const ValueUnion& data) const { return data.doubleValue; } | |||
| float toFloat (const ValueUnion& data) const { return (float) data.doubleValue; } | |||
| const String toString (const ValueUnion& data) const { return String (data.doubleValue); } | |||
| bool toBool (const ValueUnion& data) const { return data.doubleValue != 0; } | |||
| bool isDouble() const throw() { return true; } | |||
| bool equals (const ValueUnion& data, const ValueUnion& otherData, const VariantType& otherType) const throw() | |||
| { | |||
| return otherType.toDouble (otherData) == data.doubleValue; | |||
| } | |||
| void writeToStream (const ValueUnion& data, OutputStream& output) const | |||
| { | |||
| output.writeCompressedInt (9); | |||
| output.writeByte (4); | |||
| output.writeDouble (data.doubleValue); | |||
| } | |||
| }; | |||
| class var::VariantType_Bool : public var::VariantType | |||
| { | |||
| public: | |||
| static const VariantType_Bool* getInstance() { static const VariantType_Bool i; return &i; } | |||
| int toInt (const ValueUnion& data) const { return data.boolValue ? 1 : 0; }; | |||
| double toDouble (const ValueUnion& data) const { return data.boolValue ? 1.0 : 0.0; } | |||
| float toFloat (const ValueUnion& data) const { return data.boolValue ? 1.0f : 0.0f; } | |||
| const String toString (const ValueUnion& data) const { return String::charToString (data.boolValue ? '1' : '0'); } | |||
| bool toBool (const ValueUnion& data) const { return data.boolValue; } | |||
| bool isBool() const throw() { return true; } | |||
| bool equals (const ValueUnion& data, const ValueUnion& otherData, const VariantType& otherType) const throw() | |||
| { | |||
| return otherType.toBool (otherData) == data.boolValue; | |||
| } | |||
| void writeToStream (const ValueUnion& data, OutputStream& output) const | |||
| { | |||
| output.writeCompressedInt (1); | |||
| output.writeByte (data.boolValue ? 2 : 3); | |||
| } | |||
| }; | |||
| class var::VariantType_String : public var::VariantType | |||
| { | |||
| public: | |||
| static const VariantType_String* getInstance() { static const VariantType_String i; return &i; } | |||
| void cleanUp (ValueUnion& data) const throw() { delete data.stringValue; } | |||
| void createCopy (ValueUnion& dest, const ValueUnion& source) const { dest.stringValue = new String (*source.stringValue); } | |||
| int toInt (const ValueUnion& data) const { return data.stringValue->getIntValue(); }; | |||
| double toDouble (const ValueUnion& data) const { return data.stringValue->getDoubleValue(); } | |||
| float toFloat (const ValueUnion& data) const { return data.stringValue->getFloatValue(); } | |||
| const String toString (const ValueUnion& data) const { return *data.stringValue; } | |||
| bool toBool (const ValueUnion& data) const { return data.stringValue->getIntValue() != 0 | |||
| || data.stringValue->trim().equalsIgnoreCase ("true") | |||
| || data.stringValue->trim().equalsIgnoreCase ("yes"); } | |||
| bool isString() const throw() { return true; } | |||
| bool equals (const ValueUnion& data, const ValueUnion& otherData, const VariantType& otherType) const throw() | |||
| { | |||
| return otherType.toString (otherData) == *data.stringValue; | |||
| } | |||
| void writeToStream (const ValueUnion& data, OutputStream& output) const | |||
| { | |||
| const int len = data.stringValue->getNumBytesAsUTF8() + 1; | |||
| output.writeCompressedInt (len + 1); | |||
| output.writeByte (5); | |||
| HeapBlock<char> temp (len); | |||
| data.stringValue->copyToUTF8 (temp, len); | |||
| output.write (temp, len); | |||
| } | |||
| }; | |||
| class var::VariantType_Object : public var::VariantType | |||
| { | |||
| public: | |||
| static const VariantType_Object* getInstance() { static const VariantType_Object i; return &i; } | |||
| void cleanUp (ValueUnion& data) const throw() { if (data.objectValue != 0) data.objectValue->decReferenceCount(); } | |||
| void createCopy (ValueUnion& dest, const ValueUnion& source) const { dest.objectValue = source.objectValue; if (dest.objectValue != 0) dest.objectValue->incReferenceCount(); } | |||
| const String toString (const ValueUnion& data) const { return "Object 0x" + String::toHexString ((int) (pointer_sized_int) data.objectValue); } | |||
| bool toBool (const ValueUnion& data) const { return data.objectValue != 0; } | |||
| DynamicObject* toObject (const ValueUnion& data) const { return data.objectValue; } | |||
| bool isObject() const throw() { return true; } | |||
| bool equals (const ValueUnion& data, const ValueUnion& otherData, const VariantType& otherType) const throw() | |||
| { | |||
| return otherType.toObject (otherData) == data.objectValue; | |||
| } | |||
| void writeToStream (const ValueUnion&, OutputStream& output) const | |||
| { | |||
| jassertfalse; // Can't write an object to a stream! | |||
| output.writeCompressedInt (0); | |||
| } | |||
| }; | |||
| class var::VariantType_Method : public var::VariantType | |||
| { | |||
| public: | |||
| static const VariantType_Method* getInstance() { static const VariantType_Method i; return &i; } | |||
| const String toString (const ValueUnion&) const { return "Method"; } | |||
| bool toBool (const ValueUnion& data) const { return data.methodValue != 0; } | |||
| bool isMethod() const throw() { return true; } | |||
| bool equals (const ValueUnion& data, const ValueUnion& otherData, const VariantType& otherType) const throw() | |||
| { | |||
| return otherType.isMethod() && otherData.methodValue == data.methodValue; | |||
| } | |||
| void writeToStream (const ValueUnion&, OutputStream& output) const | |||
| { | |||
| jassertfalse; // Can't write a method to a stream! | |||
| output.writeCompressedInt (0); | |||
| } | |||
| }; | |||
| var::var() throw() | |||
| : type (voidType) | |||
| : type (VariantType_Void::getInstance()) | |||
| { | |||
| value.doubleValue = 0; | |||
| } | |||
| var::~var() throw() | |||
| { | |||
| if (type == stringType) | |||
| delete value.stringValue; | |||
| else if (type == objectType && value.objectValue != 0) | |||
| value.objectValue->decReferenceCount(); | |||
| type->cleanUp (value); | |||
| } | |||
| const var var::null; | |||
| var::var (const var& valueToCopy) | |||
| : type (valueToCopy.type), | |||
| value (valueToCopy.value) | |||
| var::var (const var& valueToCopy) : type (valueToCopy.type) | |||
| { | |||
| if (type == stringType) | |||
| value.stringValue = new String (*(value.stringValue)); | |||
| else if (type == objectType && value.objectValue != 0) | |||
| value.objectValue->incReferenceCount(); | |||
| type->createCopy (value, valueToCopy.value); | |||
| } | |||
| var::var (const int value_) throw() | |||
| : type (intType) | |||
| var::var (const int value_) throw() : type (VariantType_Int::getInstance()) | |||
| { | |||
| value.intValue = value_; | |||
| } | |||
| var::var (const bool value_) throw() | |||
| : type (boolType) | |||
| var::var (const bool value_) throw() : type (VariantType_Bool::getInstance()) | |||
| { | |||
| value.boolValue = value_; | |||
| } | |||
| var::var (const double value_) throw() | |||
| : type (doubleType) | |||
| var::var (const double value_) throw() : type (VariantType_Double::getInstance()) | |||
| { | |||
| value.doubleValue = value_; | |||
| } | |||
| var::var (const String& value_) | |||
| : type (stringType) | |||
| var::var (const String& value_) : type (VariantType_String::getInstance()) | |||
| { | |||
| value.stringValue = new String (value_); | |||
| } | |||
| var::var (const char* const value_) | |||
| : type (stringType) | |||
| var::var (const char* const value_) : type (VariantType_String::getInstance()) | |||
| { | |||
| value.stringValue = new String (value_); | |||
| } | |||
| var::var (const juce_wchar* const value_) | |||
| : type (stringType) | |||
| var::var (const juce_wchar* const value_) : type (VariantType_String::getInstance()) | |||
| { | |||
| value.stringValue = new String (value_); | |||
| } | |||
| var::var (DynamicObject* const object) | |||
| : type (objectType) | |||
| var::var (DynamicObject* const object) : type (VariantType_Object::getInstance()) | |||
| { | |||
| value.objectValue = object; | |||
| @@ -4011,125 +4191,46 @@ var::var (DynamicObject* const object) | |||
| object->incReferenceCount(); | |||
| } | |||
| var::var (MethodFunction method_) throw() | |||
| : type (methodType) | |||
| var::var (MethodFunction method_) throw() : type (VariantType_Method::getInstance()) | |||
| { | |||
| value.methodValue = method_; | |||
| } | |||
| bool var::isVoid() const throw() { return type->isVoid(); } | |||
| bool var::isInt() const throw() { return type->isInt(); } | |||
| bool var::isBool() const throw() { return type->isBool(); } | |||
| bool var::isDouble() const throw() { return type->isDouble(); } | |||
| bool var::isString() const throw() { return type->isString(); } | |||
| bool var::isObject() const throw() { return type->isObject(); } | |||
| bool var::isMethod() const throw() { return type->isMethod(); } | |||
| var::operator int() const { return type->toInt (value); } | |||
| var::operator bool() const { return type->toBool (value); } | |||
| var::operator float() const { return type->toFloat (value); } | |||
| var::operator double() const { return type->toDouble (value); } | |||
| const String var::toString() const { return type->toString (value); } | |||
| var::operator const String() const { return type->toString (value); } | |||
| DynamicObject* var::getObject() const { return type->toObject (value); } | |||
| void var::swapWith (var& other) throw() | |||
| { | |||
| swapVariables (type, other.type); | |||
| swapVariables (value, other.value); | |||
| } | |||
| var& var::operator= (const var& value_) { var newValue (value_); swapWith (newValue); return *this; } | |||
| var& var::operator= (int value_) { var newValue (value_); swapWith (newValue); return *this; } | |||
| var& var::operator= (bool value_) { var newValue (value_); swapWith (newValue); return *this; } | |||
| var& var::operator= (double value_) { var newValue (value_); swapWith (newValue); return *this; } | |||
| var& var::operator= (const char* value_) { var newValue (value_); swapWith (newValue); return *this; } | |||
| var& var::operator= (const juce_wchar* value_) { var newValue (value_); swapWith (newValue); return *this; } | |||
| var& var::operator= (const String& value_) { var newValue (value_); swapWith (newValue); return *this; } | |||
| var& var::operator= (DynamicObject* value_) { var newValue (value_); swapWith (newValue); return *this; } | |||
| var& var::operator= (MethodFunction value_) { var newValue (value_); swapWith (newValue); return *this; } | |||
| var::operator int() const | |||
| { | |||
| switch (type) | |||
| { | |||
| case voidType: break; | |||
| case intType: return value.intValue; | |||
| case boolType: return value.boolValue ? 1 : 0; | |||
| case doubleType: return static_cast <int> (value.doubleValue); | |||
| case stringType: return value.stringValue->getIntValue(); | |||
| case objectType: break; | |||
| default: jassertfalse; break; | |||
| } | |||
| return 0; | |||
| } | |||
| var::operator bool() const | |||
| { | |||
| switch (type) | |||
| { | |||
| case voidType: break; | |||
| case intType: return value.intValue != 0; | |||
| case boolType: return value.boolValue; | |||
| case doubleType: return value.doubleValue != 0; | |||
| case stringType: return value.stringValue->getIntValue() != 0 | |||
| || value.stringValue->trim().equalsIgnoreCase ("true") | |||
| || value.stringValue->trim().equalsIgnoreCase ("yes"); | |||
| case objectType: return value.objectValue != 0; | |||
| default: jassertfalse; break; | |||
| } | |||
| return false; | |||
| } | |||
| var::operator float() const | |||
| { | |||
| return (float) operator double(); | |||
| } | |||
| var::operator double() const | |||
| { | |||
| switch (type) | |||
| { | |||
| case voidType: break; | |||
| case intType: return value.intValue; | |||
| case boolType: return value.boolValue ? 1.0 : 0.0; | |||
| case doubleType: return value.doubleValue; | |||
| case stringType: return value.stringValue->getDoubleValue(); | |||
| case objectType: break; | |||
| default: jassertfalse; break; | |||
| } | |||
| return 0.0; | |||
| } | |||
| const String var::toString() const | |||
| { | |||
| switch (type) | |||
| { | |||
| case voidType: return String::empty; | |||
| case intType: return String (value.intValue); | |||
| case boolType: return String::charToString (value.boolValue ? '1' : '0'); | |||
| case doubleType: return String (value.doubleValue); | |||
| case stringType: return *(value.stringValue); | |||
| case objectType: return "Object 0x" + String::toHexString ((int) (pointer_sized_int) value.objectValue); | |||
| case methodType: return "Method"; | |||
| default: jassertfalse; break; | |||
| } | |||
| return String::empty; | |||
| } | |||
| var::operator const String() const | |||
| { | |||
| return toString(); | |||
| } | |||
| DynamicObject* var::getObject() const | |||
| { | |||
| return type == objectType ? value.objectValue : 0; | |||
| } | |||
| var& var::operator= (const var& newValue) { type->cleanUp (value); type = newValue.type; type->createCopy (value, newValue.value); return *this; } | |||
| var& var::operator= (int newValue) { var v (newValue); swapWith (v); return *this; } | |||
| var& var::operator= (bool newValue) { var v (newValue); swapWith (v); return *this; } | |||
| var& var::operator= (double newValue) { var v (newValue); swapWith (v); return *this; } | |||
| var& var::operator= (const char* newValue) { var v (newValue); swapWith (v); return *this; } | |||
| var& var::operator= (const juce_wchar* newValue) { var v (newValue); swapWith (v); return *this; } | |||
| var& var::operator= (const String& newValue) { var v (newValue); swapWith (v); return *this; } | |||
| var& var::operator= (DynamicObject* newValue) { var v (newValue); swapWith (v); return *this; } | |||
| var& var::operator= (MethodFunction newValue) { var v (newValue); swapWith (v); return *this; } | |||
| bool var::equals (const var& other) const throw() | |||
| { | |||
| switch (type) | |||
| { | |||
| case voidType: return other.isVoid(); | |||
| case intType: return value.intValue == static_cast <int> (other); | |||
| case boolType: return value.boolValue == static_cast <bool> (other); | |||
| case doubleType: return value.doubleValue == static_cast <double> (other); | |||
| case stringType: return (*(value.stringValue)) == other.toString(); | |||
| case objectType: return value.objectValue == other.getObject(); | |||
| case methodType: return value.methodValue == other.value.methodValue && other.isMethod(); | |||
| default: jassertfalse; break; | |||
| } | |||
| return false; | |||
| return type->equals (value, other.value, *other.type); | |||
| } | |||
| bool operator== (const var& v1, const var& v2) throw() { return v1.equals (v2); } | |||
| @@ -4139,26 +4240,7 @@ bool operator!= (const var& v1, const String& v2) throw() { return v1.toString | |||
| void var::writeToStream (OutputStream& output) const | |||
| { | |||
| switch (type) | |||
| { | |||
| case voidType: output.writeCompressedInt (0); break; | |||
| case intType: output.writeCompressedInt (5); output.writeByte (1); output.writeInt (value.intValue); break; | |||
| case boolType: output.writeCompressedInt (1); output.writeByte (value.boolValue ? 2 : 3); break; | |||
| case doubleType: output.writeCompressedInt (9); output.writeByte (4); output.writeDouble (value.doubleValue); break; | |||
| case stringType: | |||
| { | |||
| const int len = value.stringValue->getNumBytesAsUTF8() + 1; | |||
| output.writeCompressedInt (len + 1); | |||
| output.writeByte (5); | |||
| HeapBlock<char> temp (len); | |||
| value.stringValue->copyToUTF8 (temp, len); | |||
| output.write (temp, len); | |||
| break; | |||
| } | |||
| case objectType: | |||
| case methodType: output.writeCompressedInt (0); jassertfalse; break; // Can't write an object to a stream! | |||
| default: jassertfalse; break; // Is this a corrupted object? | |||
| } | |||
| type->writeToStream (value, output); | |||
| } | |||
| const var var::readFromStream (InputStream& input) | |||
| @@ -4189,18 +4271,14 @@ const var var::readFromStream (InputStream& input) | |||
| const var var::operator[] (const Identifier& propertyName) const | |||
| { | |||
| if (type == objectType && value.objectValue != 0) | |||
| return value.objectValue->getProperty (propertyName); | |||
| return var::null; | |||
| DynamicObject* const o = getObject(); | |||
| return o != 0 ? o->getProperty (propertyName) : var::null; | |||
| } | |||
| const var var::invoke (const Identifier& method, const var* arguments, int numArguments) const | |||
| { | |||
| if (type == objectType && value.objectValue != 0) | |||
| return value.objectValue->invokeMethod (method, arguments, numArguments); | |||
| return var::null; | |||
| DynamicObject* const o = getObject(); | |||
| return o != 0 ? o->invokeMethod (method, arguments, numArguments) : var::null; | |||
| } | |||
| const var var::invoke (const var& targetObject, const var* arguments, int numArguments) const | |||
| @@ -23783,6 +23861,7 @@ void ResamplingAudioSource::getNextAudioBlock (const AudioSourceChannelInfo& inf | |||
| bufferPos %= bufferSize; | |||
| int endOfBufferPos = bufferPos + sampsInBuffer; | |||
| const int channelsToProcess = jmin (numChannels, info.buffer->getNumChannels()); | |||
| while (sampsNeeded > sampsInBuffer) | |||
| { | |||
| @@ -23802,7 +23881,7 @@ void ResamplingAudioSource::getNextAudioBlock (const AudioSourceChannelInfo& inf | |||
| { | |||
| // for down-sampling, pre-apply the filter.. | |||
| for (int i = jmin (numChannels, info.buffer->getNumChannels()); --i >= 0;) | |||
| for (int i = channelsToProcess; --i >= 0;) | |||
| applyFilter (buffer.getSampleData (i, endOfBufferPos), numToDo, filterStates[i]); | |||
| } | |||
| @@ -23810,7 +23889,7 @@ void ResamplingAudioSource::getNextAudioBlock (const AudioSourceChannelInfo& inf | |||
| endOfBufferPos += numToDo; | |||
| } | |||
| for (int channel = 0; channel < numChannels; ++channel) | |||
| for (int channel = 0; channel < channelsToProcess; ++channel) | |||
| { | |||
| destBuffers[channel] = info.buffer->getSampleData (channel, info.startSample); | |||
| srcBuffers[channel] = buffer.getSampleData (channel, 0); | |||
| @@ -23822,7 +23901,7 @@ void ResamplingAudioSource::getNextAudioBlock (const AudioSourceChannelInfo& inf | |||
| const float alpha = (float) subSampleOffset; | |||
| const float invAlpha = 1.0f - alpha; | |||
| for (int channel = 0; channel < numChannels; ++channel) | |||
| for (int channel = 0; channel < channelsToProcess; ++channel) | |||
| *destBuffers[channel]++ = srcBuffers[channel][bufferPos] * invAlpha + srcBuffers[channel][nextPos] * alpha; | |||
| subSampleOffset += ratio; | |||
| @@ -23844,13 +23923,13 @@ void ResamplingAudioSource::getNextAudioBlock (const AudioSourceChannelInfo& inf | |||
| if (ratio < 0.9999) | |||
| { | |||
| // for up-sampling, apply the filter after transposing.. | |||
| for (int i = jmin (numChannels, info.buffer->getNumChannels()); --i >= 0;) | |||
| for (int i = channelsToProcess; --i >= 0;) | |||
| applyFilter (info.buffer->getSampleData (i, info.startSample), info.numSamples, filterStates[i]); | |||
| } | |||
| else if (ratio <= 1.0001) | |||
| { | |||
| // if the filter's not currently being applied, keep it stoked with the last couple of samples to avoid discontinuities | |||
| for (int i = jmin (numChannels, info.buffer->getNumChannels()); --i >= 0;) | |||
| for (int i = channelsToProcess; --i >= 0;) | |||
| { | |||
| const float* const endOfBuffer = info.buffer->getSampleData (i, info.startSample + info.numSamples - 1); | |||
| FilterState& fs = filterStates[i]; | |||
| @@ -85751,7 +85830,7 @@ void DrawablePath::ValueTreeWrapper::Element::convertToPathBreak (UndoManager* u | |||
| } | |||
| } | |||
| static const Point<float> findCubicSubdivisionPoint (double proportion, const Point<float> points[4]) | |||
| static const Point<float> findCubicSubdivisionPoint (float proportion, const Point<float> points[4]) | |||
| { | |||
| const Point<float> mid1 (points[0] + (points[1] - points[0]) * proportion), | |||
| mid2 (points[1] + (points[2] - points[1]) * proportion), | |||
| @@ -85763,7 +85842,7 @@ static const Point<float> findCubicSubdivisionPoint (double proportion, const Po | |||
| return newCp1 + (newCp2 - newCp1) * proportion; | |||
| } | |||
| static const Point<float> findQuadraticSubdivisionPoint (double proportion, const Point<float> points[3]) | |||
| static const Point<float> findQuadraticSubdivisionPoint (float proportion, const Point<float> points[3]) | |||
| { | |||
| const Point<float> mid1 (points[0] + (points[1] - points[0]) * proportion), | |||
| mid2 (points[1] + (points[2] - points[1]) * proportion); | |||
| @@ -85771,10 +85850,10 @@ static const Point<float> findQuadraticSubdivisionPoint (double proportion, cons | |||
| return mid1 + (mid2 - mid1) * proportion; | |||
| } | |||
| double DrawablePath::ValueTreeWrapper::Element::findProportionAlongLine (const Point<float>& targetPoint, RelativeCoordinate::NamedCoordinateFinder* nameFinder) const | |||
| float DrawablePath::ValueTreeWrapper::Element::findProportionAlongLine (const Point<float>& targetPoint, RelativeCoordinate::NamedCoordinateFinder* nameFinder) const | |||
| { | |||
| const Identifier i (state.getType()); | |||
| double bestProp = 0; | |||
| float bestProp = 0; | |||
| if (i == cubicToElement) | |||
| { | |||
| @@ -85786,7 +85865,7 @@ double DrawablePath::ValueTreeWrapper::Element::findProportionAlongLine (const P | |||
| for (int i = 110; --i >= 0;) | |||
| { | |||
| double prop = i > 10 ? ((i - 10) / 100.0) : (bestProp + ((i - 5) / 1000.0)); | |||
| float prop = i > 10 ? ((i - 10) / 100.0f) : (bestProp + ((i - 5) / 1000.0f)); | |||
| const Point<float> centre (findCubicSubdivisionPoint (prop, points)); | |||
| const float distance = centre.getDistanceFrom (targetPoint); | |||
| @@ -85806,8 +85885,8 @@ double DrawablePath::ValueTreeWrapper::Element::findProportionAlongLine (const P | |||
| for (int i = 110; --i >= 0;) | |||
| { | |||
| double prop = i > 10 ? ((i - 10) / 100.0) : (bestProp + ((i - 5) / 1000.0)); | |||
| const Point<float> centre (findQuadraticSubdivisionPoint (prop, points)); | |||
| float prop = i > 10 ? ((i - 10) / 100.0f) : (bestProp + ((i - 5) / 1000.0f)); | |||
| const Point<float> centre (findQuadraticSubdivisionPoint ((float) prop, points)); | |||
| const float distance = centre.getDistanceFrom (targetPoint); | |||
| if (distance < bestDistance) | |||
| @@ -85834,7 +85913,7 @@ ValueTree DrawablePath::ValueTreeWrapper::Element::insertPoint (const Point<floa | |||
| if (i == cubicToElement) | |||
| { | |||
| double bestProp = findProportionAlongLine (targetPoint, nameFinder); | |||
| float bestProp = findProportionAlongLine (targetPoint, nameFinder); | |||
| RelativePoint rp1 (getStartPoint()), rp2 (getControlPoint (0)), rp3 (getControlPoint (1)), rp4 (getEndPoint()); | |||
| const Point<float> points[] = { rp1.resolve (nameFinder), rp2.resolve (nameFinder), rp3.resolve (nameFinder), rp4.resolve (nameFinder) }; | |||
| @@ -85862,7 +85941,7 @@ ValueTree DrawablePath::ValueTreeWrapper::Element::insertPoint (const Point<floa | |||
| } | |||
| else if (i == quadraticToElement) | |||
| { | |||
| double bestProp = findProportionAlongLine (targetPoint, nameFinder); | |||
| float bestProp = findProportionAlongLine (targetPoint, nameFinder); | |||
| RelativePoint rp1 (getStartPoint()), rp2 (getControlPoint (0)), rp3 (getEndPoint()); | |||
| const Point<float> points[] = { rp1.resolve (nameFinder), rp2.resolve (nameFinder), rp3.resolve (nameFinder) }; | |||
| @@ -259600,8 +259679,6 @@ public: | |||
| callback (0), | |||
| inputId (inputId_), | |||
| outputId (outputId_), | |||
| outputDevice (0), | |||
| inputDevice (0), | |||
| numCallbacks (0), | |||
| inputChannelBuffer (1, 1), | |||
| outputChannelBuffer (1, 1) | |||
| @@ -259666,7 +259743,7 @@ public: | |||
| if (outputDevice->error.isNotEmpty()) | |||
| { | |||
| error = outputDevice->error; | |||
| deleteAndZero (outputDevice); | |||
| outputDevice = 0; | |||
| return; | |||
| } | |||
| @@ -259677,7 +259754,7 @@ public: | |||
| bufferSize)) | |||
| { | |||
| error = outputDevice->error; | |||
| deleteAndZero (outputDevice); | |||
| outputDevice = 0; | |||
| return; | |||
| } | |||
| } | |||
| @@ -259689,7 +259766,7 @@ public: | |||
| if (inputDevice->error.isNotEmpty()) | |||
| { | |||
| error = inputDevice->error; | |||
| deleteAndZero (inputDevice); | |||
| inputDevice = 0; | |||
| return; | |||
| } | |||
| @@ -259700,7 +259777,7 @@ public: | |||
| bufferSize)) | |||
| { | |||
| error = inputDevice->error; | |||
| deleteAndZero (inputDevice); | |||
| inputDevice = 0; | |||
| return; | |||
| } | |||
| } | |||
| @@ -259742,8 +259819,8 @@ public: | |||
| { | |||
| stopThread (6000); | |||
| deleteAndZero (inputDevice); | |||
| deleteAndZero (outputDevice); | |||
| inputDevice = 0; | |||
| outputDevice = 0; | |||
| inputChannelBuffer.setSize (1, 1); | |||
| outputChannelBuffer.setSize (1, 1); | |||
| @@ -259835,8 +259912,7 @@ public: | |||
| private: | |||
| const String inputId, outputId; | |||
| ALSADevice* outputDevice; | |||
| ALSADevice* inputDevice; | |||
| ScopedPointer<ALSADevice> outputDevice, inputDevice; | |||
| int numCallbacks; | |||
| CriticalSection callbackLock; | |||
| @@ -259891,7 +259967,7 @@ public: | |||
| outputId (outputId_), | |||
| isOpen_ (false), | |||
| isStarted (false), | |||
| internal (new ALSAThread (inputId_, outputId_)) | |||
| internal (inputId_, outputId_) | |||
| { | |||
| } | |||
| @@ -259901,22 +259977,22 @@ public: | |||
| const StringArray getOutputChannelNames() | |||
| { | |||
| return internal->channelNamesOut; | |||
| return internal.channelNamesOut; | |||
| } | |||
| const StringArray getInputChannelNames() | |||
| { | |||
| return internal->channelNamesIn; | |||
| return internal.channelNamesIn; | |||
| } | |||
| int getNumSampleRates() | |||
| { | |||
| return internal->sampleRates.size(); | |||
| return internal.sampleRates.size(); | |||
| } | |||
| double getSampleRate (int index) | |||
| { | |||
| return internal->sampleRates [index]; | |||
| return internal.sampleRates [index]; | |||
| } | |||
| int getNumBufferSizesAvailable() | |||
| @@ -259963,17 +260039,17 @@ public: | |||
| } | |||
| } | |||
| internal->open (inputChannels, outputChannels, | |||
| sampleRate, bufferSizeSamples); | |||
| internal.open (inputChannels, outputChannels, | |||
| sampleRate, bufferSizeSamples); | |||
| isOpen_ = internal->error.isEmpty(); | |||
| return internal->error; | |||
| isOpen_ = internal.error.isEmpty(); | |||
| return internal.error; | |||
| } | |||
| void close() | |||
| { | |||
| stop(); | |||
| internal->close(); | |||
| internal.close(); | |||
| isOpen_ = false; | |||
| } | |||
| @@ -259984,27 +260060,27 @@ public: | |||
| int getCurrentBufferSizeSamples() | |||
| { | |||
| return internal->bufferSize; | |||
| return internal.bufferSize; | |||
| } | |||
| double getCurrentSampleRate() | |||
| { | |||
| return internal->sampleRate; | |||
| return internal.sampleRate; | |||
| } | |||
| int getCurrentBitDepth() | |||
| { | |||
| return internal->getBitDepth(); | |||
| return internal.getBitDepth(); | |||
| } | |||
| const BigInteger getActiveOutputChannels() const | |||
| { | |||
| return internal->currentOutputChans; | |||
| return internal.currentOutputChans; | |||
| } | |||
| const BigInteger getActiveInputChannels() const | |||
| { | |||
| return internal->currentInputChans; | |||
| return internal.currentInputChans; | |||
| } | |||
| int getOutputLatencyInSamples() | |||
| @@ -260022,17 +260098,17 @@ public: | |||
| if (! isOpen_) | |||
| callback = 0; | |||
| internal->setCallback (callback); | |||
| if (callback != 0) | |||
| callback->audioDeviceAboutToStart (this); | |||
| internal.setCallback (callback); | |||
| isStarted = (callback != 0); | |||
| } | |||
| void stop() | |||
| { | |||
| AudioIODeviceCallback* const oldCallback = internal->callback; | |||
| AudioIODeviceCallback* const oldCallback = internal.callback; | |||
| start (0); | |||
| @@ -260042,19 +260118,19 @@ public: | |||
| bool isPlaying() | |||
| { | |||
| return isStarted && internal->error.isEmpty(); | |||
| return isStarted && internal.error.isEmpty(); | |||
| } | |||
| const String getLastError() | |||
| { | |||
| return internal->error; | |||
| return internal.error; | |||
| } | |||
| String inputId, outputId; | |||
| private: | |||
| bool isOpen_, isStarted; | |||
| ScopedPointer<ALSAThread> internal; | |||
| ALSAThread internal; | |||
| }; | |||
| class ALSAAudioIODeviceType : public AudioIODeviceType | |||
| @@ -64,7 +64,7 @@ | |||
| */ | |||
| #define JUCE_MAJOR_VERSION 1 | |||
| #define JUCE_MINOR_VERSION 52 | |||
| #define JUCE_BUILDNUMBER 31 | |||
| #define JUCE_BUILDNUMBER 32 | |||
| /** Current Juce version number. | |||
| @@ -5544,13 +5544,13 @@ public: | |||
| const String toString() const; | |||
| DynamicObject* getObject() const; | |||
| bool isVoid() const throw() { return type == voidType; } | |||
| bool isInt() const throw() { return type == intType; } | |||
| bool isBool() const throw() { return type == boolType; } | |||
| bool isDouble() const throw() { return type == doubleType; } | |||
| bool isString() const throw() { return type == stringType; } | |||
| bool isObject() const throw() { return type == objectType; } | |||
| bool isMethod() const throw() { return type == methodType; } | |||
| bool isVoid() const throw(); | |||
| bool isInt() const throw(); | |||
| bool isBool() const throw(); | |||
| bool isDouble() const throw(); | |||
| bool isString() const throw(); | |||
| bool isObject() const throw(); | |||
| bool isMethod() const throw(); | |||
| /** Writes a binary representation of this value to a stream. | |||
| The data can be read back later using readFromStream(). | |||
| @@ -5591,16 +5591,24 @@ public: | |||
| bool equals (const var& other) const throw(); | |||
| private: | |||
| enum Type | |||
| { | |||
| voidType = 0, | |||
| intType, | |||
| boolType, | |||
| doubleType, | |||
| stringType, | |||
| objectType, | |||
| methodType | |||
| }; | |||
| class VariantType; | |||
| friend class VariantType; | |||
| class VariantType_Void; | |||
| friend class VariantType_Void; | |||
| class VariantType_Int; | |||
| friend class VariantType_Int; | |||
| class VariantType_Double; | |||
| friend class VariantType_Double; | |||
| class VariantType_Float; | |||
| friend class VariantType_Float; | |||
| class VariantType_Bool; | |||
| friend class VariantType_Bool; | |||
| class VariantType_String; | |||
| friend class VariantType_String; | |||
| class VariantType_Object; | |||
| friend class VariantType_Object; | |||
| class VariantType_Method; | |||
| friend class VariantType_Method; | |||
| union ValueUnion | |||
| { | |||
| @@ -5612,7 +5620,7 @@ private: | |||
| MethodFunction methodValue; | |||
| }; | |||
| Type type; | |||
| const VariantType* type; | |||
| ValueUnion value; | |||
| }; | |||
| @@ -59416,7 +59424,7 @@ public: | |||
| void convertToPathBreak (UndoManager* undoManager); | |||
| ValueTree insertPoint (const Point<float>& targetPoint, RelativeCoordinate::NamedCoordinateFinder* nameFinder, UndoManager* undoManager); | |||
| void removePoint (UndoManager* undoManager); | |||
| double findProportionAlongLine (const Point<float>& targetPoint, RelativeCoordinate::NamedCoordinateFinder* nameFinder) const; | |||
| float findProportionAlongLine (const Point<float>& targetPoint, RelativeCoordinate::NamedCoordinateFinder* nameFinder) const; | |||
| static const Identifier mode, startSubPathElement, closeSubPathElement, | |||
| lineToElement, quadraticToElement, cubicToElement; | |||
| @@ -110,6 +110,7 @@ void ResamplingAudioSource::getNextAudioBlock (const AudioSourceChannelInfo& inf | |||
| bufferPos %= bufferSize; | |||
| int endOfBufferPos = bufferPos + sampsInBuffer; | |||
| const int channelsToProcess = jmin (numChannels, info.buffer->getNumChannels()); | |||
| while (sampsNeeded > sampsInBuffer) | |||
| { | |||
| @@ -129,7 +130,7 @@ void ResamplingAudioSource::getNextAudioBlock (const AudioSourceChannelInfo& inf | |||
| { | |||
| // for down-sampling, pre-apply the filter.. | |||
| for (int i = jmin (numChannels, info.buffer->getNumChannels()); --i >= 0;) | |||
| for (int i = channelsToProcess; --i >= 0;) | |||
| applyFilter (buffer.getSampleData (i, endOfBufferPos), numToDo, filterStates[i]); | |||
| } | |||
| @@ -137,7 +138,7 @@ void ResamplingAudioSource::getNextAudioBlock (const AudioSourceChannelInfo& inf | |||
| endOfBufferPos += numToDo; | |||
| } | |||
| for (int channel = 0; channel < numChannels; ++channel) | |||
| for (int channel = 0; channel < channelsToProcess; ++channel) | |||
| { | |||
| destBuffers[channel] = info.buffer->getSampleData (channel, info.startSample); | |||
| srcBuffers[channel] = buffer.getSampleData (channel, 0); | |||
| @@ -149,7 +150,7 @@ void ResamplingAudioSource::getNextAudioBlock (const AudioSourceChannelInfo& inf | |||
| const float alpha = (float) subSampleOffset; | |||
| const float invAlpha = 1.0f - alpha; | |||
| for (int channel = 0; channel < numChannels; ++channel) | |||
| for (int channel = 0; channel < channelsToProcess; ++channel) | |||
| *destBuffers[channel]++ = srcBuffers[channel][bufferPos] * invAlpha + srcBuffers[channel][nextPos] * alpha; | |||
| subSampleOffset += ratio; | |||
| @@ -171,13 +172,13 @@ void ResamplingAudioSource::getNextAudioBlock (const AudioSourceChannelInfo& inf | |||
| if (ratio < 0.9999) | |||
| { | |||
| // for up-sampling, apply the filter after transposing.. | |||
| for (int i = jmin (numChannels, info.buffer->getNumChannels()); --i >= 0;) | |||
| for (int i = channelsToProcess; --i >= 0;) | |||
| applyFilter (info.buffer->getSampleData (i, info.startSample), info.numSamples, filterStates[i]); | |||
| } | |||
| else if (ratio <= 1.0001) | |||
| { | |||
| // if the filter's not currently being applied, keep it stoked with the last couple of samples to avoid discontinuities | |||
| for (int i = jmin (numChannels, info.buffer->getNumChannels()); --i >= 0;) | |||
| for (int i = channelsToProcess; --i >= 0;) | |||
| { | |||
| const float* const endOfBuffer = info.buffer->getSampleData (i, info.startSample + info.numSamples - 1); | |||
| FilterState& fs = filterStates[i]; | |||
| @@ -31,72 +31,261 @@ BEGIN_JUCE_NAMESPACE | |||
| #include "juce_DynamicObject.h" | |||
| //============================================================================== | |||
| class var::VariantType | |||
| { | |||
| public: | |||
| VariantType() {} | |||
| virtual ~VariantType() {} | |||
| virtual int toInt (const ValueUnion&) const { return 0; } | |||
| virtual double toDouble (const ValueUnion&) const { return 0; } | |||
| virtual float toFloat (const ValueUnion&) const { return 0; } | |||
| virtual const String toString (const ValueUnion&) const { return String::empty; } | |||
| virtual bool toBool (const ValueUnion&) const { return false; } | |||
| virtual DynamicObject* toObject (const ValueUnion&) const { return 0; } | |||
| virtual bool isVoid() const throw() { return false; } | |||
| virtual bool isInt() const throw() { return false; } | |||
| virtual bool isBool() const throw() { return false; } | |||
| virtual bool isDouble() const throw() { return false; } | |||
| virtual bool isString() const throw() { return false; } | |||
| virtual bool isObject() const throw() { return false; } | |||
| virtual bool isMethod() const throw() { return false; } | |||
| virtual void cleanUp (ValueUnion&) const throw() {} | |||
| virtual void createCopy (ValueUnion& dest, const ValueUnion& source) const { dest = source; } | |||
| virtual bool equals (const ValueUnion& data, const ValueUnion& otherData, const VariantType& otherType) const throw() = 0; | |||
| virtual void writeToStream (const ValueUnion& data, OutputStream& output) const = 0; | |||
| }; | |||
| //============================================================================== | |||
| class var::VariantType_Void : public var::VariantType | |||
| { | |||
| public: | |||
| static const VariantType_Void* getInstance() { static const VariantType_Void i; return &i; } | |||
| bool isVoid() const throw() { return true; } | |||
| bool equals (const ValueUnion&, const ValueUnion&, const VariantType& otherType) const throw() { return otherType.isVoid(); } | |||
| void writeToStream (const ValueUnion&, OutputStream& output) const { output.writeCompressedInt (0); } | |||
| }; | |||
| //============================================================================== | |||
| class var::VariantType_Int : public var::VariantType | |||
| { | |||
| public: | |||
| static const VariantType_Int* getInstance() { static const VariantType_Int i; return &i; } | |||
| int toInt (const ValueUnion& data) const { return data.intValue; }; | |||
| double toDouble (const ValueUnion& data) const { return (double) data.intValue; } | |||
| float toFloat (const ValueUnion& data) const { return (float) data.intValue; } | |||
| const String toString (const ValueUnion& data) const { return String (data.intValue); } | |||
| bool toBool (const ValueUnion& data) const { return data.intValue != 0; } | |||
| bool isInt() const throw() { return true; } | |||
| bool equals (const ValueUnion& data, const ValueUnion& otherData, const VariantType& otherType) const throw() | |||
| { | |||
| return otherType.toInt (otherData) == data.intValue; | |||
| } | |||
| void writeToStream (const ValueUnion& data, OutputStream& output) const | |||
| { | |||
| output.writeCompressedInt (5); | |||
| output.writeByte (1); | |||
| output.writeInt (data.intValue); | |||
| } | |||
| }; | |||
| //============================================================================== | |||
| class var::VariantType_Double : public var::VariantType | |||
| { | |||
| public: | |||
| static const VariantType_Double* getInstance() { static const VariantType_Double i; return &i; } | |||
| int toInt (const ValueUnion& data) const { return (int) data.doubleValue; }; | |||
| double toDouble (const ValueUnion& data) const { return data.doubleValue; } | |||
| float toFloat (const ValueUnion& data) const { return (float) data.doubleValue; } | |||
| const String toString (const ValueUnion& data) const { return String (data.doubleValue); } | |||
| bool toBool (const ValueUnion& data) const { return data.doubleValue != 0; } | |||
| bool isDouble() const throw() { return true; } | |||
| bool equals (const ValueUnion& data, const ValueUnion& otherData, const VariantType& otherType) const throw() | |||
| { | |||
| return otherType.toDouble (otherData) == data.doubleValue; | |||
| } | |||
| void writeToStream (const ValueUnion& data, OutputStream& output) const | |||
| { | |||
| output.writeCompressedInt (9); | |||
| output.writeByte (4); | |||
| output.writeDouble (data.doubleValue); | |||
| } | |||
| }; | |||
| //============================================================================== | |||
| class var::VariantType_Bool : public var::VariantType | |||
| { | |||
| public: | |||
| static const VariantType_Bool* getInstance() { static const VariantType_Bool i; return &i; } | |||
| int toInt (const ValueUnion& data) const { return data.boolValue ? 1 : 0; }; | |||
| double toDouble (const ValueUnion& data) const { return data.boolValue ? 1.0 : 0.0; } | |||
| float toFloat (const ValueUnion& data) const { return data.boolValue ? 1.0f : 0.0f; } | |||
| const String toString (const ValueUnion& data) const { return String::charToString (data.boolValue ? '1' : '0'); } | |||
| bool toBool (const ValueUnion& data) const { return data.boolValue; } | |||
| bool isBool() const throw() { return true; } | |||
| bool equals (const ValueUnion& data, const ValueUnion& otherData, const VariantType& otherType) const throw() | |||
| { | |||
| return otherType.toBool (otherData) == data.boolValue; | |||
| } | |||
| void writeToStream (const ValueUnion& data, OutputStream& output) const | |||
| { | |||
| output.writeCompressedInt (1); | |||
| output.writeByte (data.boolValue ? 2 : 3); | |||
| } | |||
| }; | |||
| //============================================================================== | |||
| class var::VariantType_String : public var::VariantType | |||
| { | |||
| public: | |||
| static const VariantType_String* getInstance() { static const VariantType_String i; return &i; } | |||
| void cleanUp (ValueUnion& data) const throw() { delete data.stringValue; } | |||
| void createCopy (ValueUnion& dest, const ValueUnion& source) const { dest.stringValue = new String (*source.stringValue); } | |||
| int toInt (const ValueUnion& data) const { return data.stringValue->getIntValue(); }; | |||
| double toDouble (const ValueUnion& data) const { return data.stringValue->getDoubleValue(); } | |||
| float toFloat (const ValueUnion& data) const { return data.stringValue->getFloatValue(); } | |||
| const String toString (const ValueUnion& data) const { return *data.stringValue; } | |||
| bool toBool (const ValueUnion& data) const { return data.stringValue->getIntValue() != 0 | |||
| || data.stringValue->trim().equalsIgnoreCase ("true") | |||
| || data.stringValue->trim().equalsIgnoreCase ("yes"); } | |||
| bool isString() const throw() { return true; } | |||
| bool equals (const ValueUnion& data, const ValueUnion& otherData, const VariantType& otherType) const throw() | |||
| { | |||
| return otherType.toString (otherData) == *data.stringValue; | |||
| } | |||
| void writeToStream (const ValueUnion& data, OutputStream& output) const | |||
| { | |||
| const int len = data.stringValue->getNumBytesAsUTF8() + 1; | |||
| output.writeCompressedInt (len + 1); | |||
| output.writeByte (5); | |||
| HeapBlock<char> temp (len); | |||
| data.stringValue->copyToUTF8 (temp, len); | |||
| output.write (temp, len); | |||
| } | |||
| }; | |||
| //============================================================================== | |||
| class var::VariantType_Object : public var::VariantType | |||
| { | |||
| public: | |||
| static const VariantType_Object* getInstance() { static const VariantType_Object i; return &i; } | |||
| void cleanUp (ValueUnion& data) const throw() { if (data.objectValue != 0) data.objectValue->decReferenceCount(); } | |||
| void createCopy (ValueUnion& dest, const ValueUnion& source) const { dest.objectValue = source.objectValue; if (dest.objectValue != 0) dest.objectValue->incReferenceCount(); } | |||
| const String toString (const ValueUnion& data) const { return "Object 0x" + String::toHexString ((int) (pointer_sized_int) data.objectValue); } | |||
| bool toBool (const ValueUnion& data) const { return data.objectValue != 0; } | |||
| DynamicObject* toObject (const ValueUnion& data) const { return data.objectValue; } | |||
| bool isObject() const throw() { return true; } | |||
| bool equals (const ValueUnion& data, const ValueUnion& otherData, const VariantType& otherType) const throw() | |||
| { | |||
| return otherType.toObject (otherData) == data.objectValue; | |||
| } | |||
| void writeToStream (const ValueUnion&, OutputStream& output) const | |||
| { | |||
| jassertfalse; // Can't write an object to a stream! | |||
| output.writeCompressedInt (0); | |||
| } | |||
| }; | |||
| //============================================================================== | |||
| class var::VariantType_Method : public var::VariantType | |||
| { | |||
| public: | |||
| static const VariantType_Method* getInstance() { static const VariantType_Method i; return &i; } | |||
| const String toString (const ValueUnion&) const { return "Method"; } | |||
| bool toBool (const ValueUnion& data) const { return data.methodValue != 0; } | |||
| bool isMethod() const throw() { return true; } | |||
| bool equals (const ValueUnion& data, const ValueUnion& otherData, const VariantType& otherType) const throw() | |||
| { | |||
| return otherType.isMethod() && otherData.methodValue == data.methodValue; | |||
| } | |||
| void writeToStream (const ValueUnion&, OutputStream& output) const | |||
| { | |||
| jassertfalse; // Can't write a method to a stream! | |||
| output.writeCompressedInt (0); | |||
| } | |||
| }; | |||
| //============================================================================== | |||
| var::var() throw() | |||
| : type (voidType) | |||
| : type (VariantType_Void::getInstance()) | |||
| { | |||
| value.doubleValue = 0; | |||
| } | |||
| var::~var() throw() | |||
| { | |||
| if (type == stringType) | |||
| delete value.stringValue; | |||
| else if (type == objectType && value.objectValue != 0) | |||
| value.objectValue->decReferenceCount(); | |||
| type->cleanUp (value); | |||
| } | |||
| const var var::null; | |||
| //============================================================================== | |||
| var::var (const var& valueToCopy) | |||
| : type (valueToCopy.type), | |||
| value (valueToCopy.value) | |||
| { | |||
| if (type == stringType) | |||
| value.stringValue = new String (*(value.stringValue)); | |||
| else if (type == objectType && value.objectValue != 0) | |||
| value.objectValue->incReferenceCount(); | |||
| var::var (const var& valueToCopy) : type (valueToCopy.type) | |||
| { | |||
| type->createCopy (value, valueToCopy.value); | |||
| } | |||
| var::var (const int value_) throw() | |||
| : type (intType) | |||
| var::var (const int value_) throw() : type (VariantType_Int::getInstance()) | |||
| { | |||
| value.intValue = value_; | |||
| } | |||
| var::var (const bool value_) throw() | |||
| : type (boolType) | |||
| var::var (const bool value_) throw() : type (VariantType_Bool::getInstance()) | |||
| { | |||
| value.boolValue = value_; | |||
| } | |||
| var::var (const double value_) throw() | |||
| : type (doubleType) | |||
| var::var (const double value_) throw() : type (VariantType_Double::getInstance()) | |||
| { | |||
| value.doubleValue = value_; | |||
| } | |||
| var::var (const String& value_) | |||
| : type (stringType) | |||
| var::var (const String& value_) : type (VariantType_String::getInstance()) | |||
| { | |||
| value.stringValue = new String (value_); | |||
| } | |||
| var::var (const char* const value_) | |||
| : type (stringType) | |||
| var::var (const char* const value_) : type (VariantType_String::getInstance()) | |||
| { | |||
| value.stringValue = new String (value_); | |||
| } | |||
| var::var (const juce_wchar* const value_) | |||
| : type (stringType) | |||
| var::var (const juce_wchar* const value_) : type (VariantType_String::getInstance()) | |||
| { | |||
| value.stringValue = new String (value_); | |||
| } | |||
| var::var (DynamicObject* const object) | |||
| : type (objectType) | |||
| var::var (DynamicObject* const object) : type (VariantType_Object::getInstance()) | |||
| { | |||
| value.objectValue = object; | |||
| @@ -104,12 +293,28 @@ var::var (DynamicObject* const object) | |||
| object->incReferenceCount(); | |||
| } | |||
| var::var (MethodFunction method_) throw() | |||
| : type (methodType) | |||
| var::var (MethodFunction method_) throw() : type (VariantType_Method::getInstance()) | |||
| { | |||
| value.methodValue = method_; | |||
| } | |||
| //============================================================================== | |||
| bool var::isVoid() const throw() { return type->isVoid(); } | |||
| bool var::isInt() const throw() { return type->isInt(); } | |||
| bool var::isBool() const throw() { return type->isBool(); } | |||
| bool var::isDouble() const throw() { return type->isDouble(); } | |||
| bool var::isString() const throw() { return type->isString(); } | |||
| bool var::isObject() const throw() { return type->isObject(); } | |||
| bool var::isMethod() const throw() { return type->isMethod(); } | |||
| var::operator int() const { return type->toInt (value); } | |||
| var::operator bool() const { return type->toBool (value); } | |||
| var::operator float() const { return type->toFloat (value); } | |||
| var::operator double() const { return type->toDouble (value); } | |||
| const String var::toString() const { return type->toString (value); } | |||
| var::operator const String() const { return type->toString (value); } | |||
| DynamicObject* var::getObject() const { return type->toObject (value); } | |||
| //============================================================================== | |||
| void var::swapWith (var& other) throw() | |||
| { | |||
| @@ -117,115 +322,20 @@ void var::swapWith (var& other) throw() | |||
| swapVariables (value, other.value); | |||
| } | |||
| var& var::operator= (const var& value_) { var newValue (value_); swapWith (newValue); return *this; } | |||
| var& var::operator= (int value_) { var newValue (value_); swapWith (newValue); return *this; } | |||
| var& var::operator= (bool value_) { var newValue (value_); swapWith (newValue); return *this; } | |||
| var& var::operator= (double value_) { var newValue (value_); swapWith (newValue); return *this; } | |||
| var& var::operator= (const char* value_) { var newValue (value_); swapWith (newValue); return *this; } | |||
| var& var::operator= (const juce_wchar* value_) { var newValue (value_); swapWith (newValue); return *this; } | |||
| var& var::operator= (const String& value_) { var newValue (value_); swapWith (newValue); return *this; } | |||
| var& var::operator= (DynamicObject* value_) { var newValue (value_); swapWith (newValue); return *this; } | |||
| var& var::operator= (MethodFunction value_) { var newValue (value_); swapWith (newValue); return *this; } | |||
| //============================================================================== | |||
| var::operator int() const | |||
| { | |||
| switch (type) | |||
| { | |||
| case voidType: break; | |||
| case intType: return value.intValue; | |||
| case boolType: return value.boolValue ? 1 : 0; | |||
| case doubleType: return static_cast <int> (value.doubleValue); | |||
| case stringType: return value.stringValue->getIntValue(); | |||
| case objectType: break; | |||
| default: jassertfalse; break; | |||
| } | |||
| return 0; | |||
| } | |||
| var::operator bool() const | |||
| { | |||
| switch (type) | |||
| { | |||
| case voidType: break; | |||
| case intType: return value.intValue != 0; | |||
| case boolType: return value.boolValue; | |||
| case doubleType: return value.doubleValue != 0; | |||
| case stringType: return value.stringValue->getIntValue() != 0 | |||
| || value.stringValue->trim().equalsIgnoreCase ("true") | |||
| || value.stringValue->trim().equalsIgnoreCase ("yes"); | |||
| case objectType: return value.objectValue != 0; | |||
| default: jassertfalse; break; | |||
| } | |||
| return false; | |||
| } | |||
| var::operator float() const | |||
| { | |||
| return (float) operator double(); | |||
| } | |||
| var::operator double() const | |||
| { | |||
| switch (type) | |||
| { | |||
| case voidType: break; | |||
| case intType: return value.intValue; | |||
| case boolType: return value.boolValue ? 1.0 : 0.0; | |||
| case doubleType: return value.doubleValue; | |||
| case stringType: return value.stringValue->getDoubleValue(); | |||
| case objectType: break; | |||
| default: jassertfalse; break; | |||
| } | |||
| return 0.0; | |||
| } | |||
| const String var::toString() const | |||
| { | |||
| switch (type) | |||
| { | |||
| case voidType: return String::empty; | |||
| case intType: return String (value.intValue); | |||
| case boolType: return String::charToString (value.boolValue ? '1' : '0'); | |||
| case doubleType: return String (value.doubleValue); | |||
| case stringType: return *(value.stringValue); | |||
| case objectType: return "Object 0x" + String::toHexString ((int) (pointer_sized_int) value.objectValue); | |||
| case methodType: return "Method"; | |||
| default: jassertfalse; break; | |||
| } | |||
| return String::empty; | |||
| } | |||
| var::operator const String() const | |||
| { | |||
| return toString(); | |||
| } | |||
| DynamicObject* var::getObject() const | |||
| { | |||
| return type == objectType ? value.objectValue : 0; | |||
| } | |||
| var& var::operator= (const var& newValue) { type->cleanUp (value); type = newValue.type; type->createCopy (value, newValue.value); return *this; } | |||
| var& var::operator= (int newValue) { var v (newValue); swapWith (v); return *this; } | |||
| var& var::operator= (bool newValue) { var v (newValue); swapWith (v); return *this; } | |||
| var& var::operator= (double newValue) { var v (newValue); swapWith (v); return *this; } | |||
| var& var::operator= (const char* newValue) { var v (newValue); swapWith (v); return *this; } | |||
| var& var::operator= (const juce_wchar* newValue) { var v (newValue); swapWith (v); return *this; } | |||
| var& var::operator= (const String& newValue) { var v (newValue); swapWith (v); return *this; } | |||
| var& var::operator= (DynamicObject* newValue) { var v (newValue); swapWith (v); return *this; } | |||
| var& var::operator= (MethodFunction newValue) { var v (newValue); swapWith (v); return *this; } | |||
| //============================================================================== | |||
| bool var::equals (const var& other) const throw() | |||
| { | |||
| switch (type) | |||
| { | |||
| case voidType: return other.isVoid(); | |||
| case intType: return value.intValue == static_cast <int> (other); | |||
| case boolType: return value.boolValue == static_cast <bool> (other); | |||
| case doubleType: return value.doubleValue == static_cast <double> (other); | |||
| case stringType: return (*(value.stringValue)) == other.toString(); | |||
| case objectType: return value.objectValue == other.getObject(); | |||
| case methodType: return value.methodValue == other.value.methodValue && other.isMethod(); | |||
| default: jassertfalse; break; | |||
| } | |||
| return false; | |||
| return type->equals (value, other.value, *other.type); | |||
| } | |||
| bool operator== (const var& v1, const var& v2) throw() { return v1.equals (v2); } | |||
| @@ -236,26 +346,7 @@ bool operator!= (const var& v1, const String& v2) throw() { return v1.toString | |||
| //============================================================================== | |||
| void var::writeToStream (OutputStream& output) const | |||
| { | |||
| switch (type) | |||
| { | |||
| case voidType: output.writeCompressedInt (0); break; | |||
| case intType: output.writeCompressedInt (5); output.writeByte (1); output.writeInt (value.intValue); break; | |||
| case boolType: output.writeCompressedInt (1); output.writeByte (value.boolValue ? 2 : 3); break; | |||
| case doubleType: output.writeCompressedInt (9); output.writeByte (4); output.writeDouble (value.doubleValue); break; | |||
| case stringType: | |||
| { | |||
| const int len = value.stringValue->getNumBytesAsUTF8() + 1; | |||
| output.writeCompressedInt (len + 1); | |||
| output.writeByte (5); | |||
| HeapBlock<char> temp (len); | |||
| value.stringValue->copyToUTF8 (temp, len); | |||
| output.write (temp, len); | |||
| break; | |||
| } | |||
| case objectType: | |||
| case methodType: output.writeCompressedInt (0); jassertfalse; break; // Can't write an object to a stream! | |||
| default: jassertfalse; break; // Is this a corrupted object? | |||
| } | |||
| type->writeToStream (value, output); | |||
| } | |||
| const var var::readFromStream (InputStream& input) | |||
| @@ -286,18 +377,14 @@ const var var::readFromStream (InputStream& input) | |||
| const var var::operator[] (const Identifier& propertyName) const | |||
| { | |||
| if (type == objectType && value.objectValue != 0) | |||
| return value.objectValue->getProperty (propertyName); | |||
| return var::null; | |||
| DynamicObject* const o = getObject(); | |||
| return o != 0 ? o->getProperty (propertyName) : var::null; | |||
| } | |||
| const var var::invoke (const Identifier& method, const var* arguments, int numArguments) const | |||
| { | |||
| if (type == objectType && value.objectValue != 0) | |||
| return value.objectValue->invokeMethod (method, arguments, numArguments); | |||
| return var::null; | |||
| DynamicObject* const o = getObject(); | |||
| return o != 0 ? o->invokeMethod (method, arguments, numArguments) : var::null; | |||
| } | |||
| const var var::invoke (const var& targetObject, const var* arguments, int numArguments) const | |||
| @@ -90,13 +90,13 @@ public: | |||
| const String toString() const; | |||
| DynamicObject* getObject() const; | |||
| bool isVoid() const throw() { return type == voidType; } | |||
| bool isInt() const throw() { return type == intType; } | |||
| bool isBool() const throw() { return type == boolType; } | |||
| bool isDouble() const throw() { return type == doubleType; } | |||
| bool isString() const throw() { return type == stringType; } | |||
| bool isObject() const throw() { return type == objectType; } | |||
| bool isMethod() const throw() { return type == methodType; } | |||
| bool isVoid() const throw(); | |||
| bool isInt() const throw(); | |||
| bool isBool() const throw(); | |||
| bool isDouble() const throw(); | |||
| bool isString() const throw(); | |||
| bool isObject() const throw(); | |||
| bool isMethod() const throw(); | |||
| //============================================================================== | |||
| /** Writes a binary representation of this value to a stream. | |||
| @@ -142,16 +142,24 @@ public: | |||
| bool equals (const var& other) const throw(); | |||
| private: | |||
| enum Type | |||
| { | |||
| voidType = 0, | |||
| intType, | |||
| boolType, | |||
| doubleType, | |||
| stringType, | |||
| objectType, | |||
| methodType | |||
| }; | |||
| class VariantType; | |||
| friend class VariantType; | |||
| class VariantType_Void; | |||
| friend class VariantType_Void; | |||
| class VariantType_Int; | |||
| friend class VariantType_Int; | |||
| class VariantType_Double; | |||
| friend class VariantType_Double; | |||
| class VariantType_Float; | |||
| friend class VariantType_Float; | |||
| class VariantType_Bool; | |||
| friend class VariantType_Bool; | |||
| class VariantType_String; | |||
| friend class VariantType_String; | |||
| class VariantType_Object; | |||
| friend class VariantType_Object; | |||
| class VariantType_Method; | |||
| friend class VariantType_Method; | |||
| union ValueUnion | |||
| { | |||
| @@ -163,7 +171,7 @@ private: | |||
| MethodFunction methodValue; | |||
| }; | |||
| Type type; | |||
| const VariantType* type; | |||
| ValueUnion value; | |||
| }; | |||
| @@ -33,7 +33,7 @@ | |||
| */ | |||
| #define JUCE_MAJOR_VERSION 1 | |||
| #define JUCE_MINOR_VERSION 52 | |||
| #define JUCE_BUILDNUMBER 31 | |||
| #define JUCE_BUILDNUMBER 32 | |||
| /** Current Juce version number. | |||
| @@ -273,7 +273,7 @@ public: | |||
| bool relativeToComponentTopLeft) const; | |||
| /** Returns the component that currently represents a given cell. | |||
| If the component for this cell is off-screen or if the position is out-of-range, | |||
| If the component for this cell is off-screen or if the position is out-of-range, | |||
| this may return 0. | |||
| @see getCellPosition | |||
| */ | |||
| @@ -453,7 +453,7 @@ void DrawablePath::ValueTreeWrapper::Element::convertToPathBreak (UndoManager* u | |||
| } | |||
| } | |||
| static const Point<float> findCubicSubdivisionPoint (double proportion, const Point<float> points[4]) | |||
| static const Point<float> findCubicSubdivisionPoint (float proportion, const Point<float> points[4]) | |||
| { | |||
| const Point<float> mid1 (points[0] + (points[1] - points[0]) * proportion), | |||
| mid2 (points[1] + (points[2] - points[1]) * proportion), | |||
| @@ -465,7 +465,7 @@ static const Point<float> findCubicSubdivisionPoint (double proportion, const Po | |||
| return newCp1 + (newCp2 - newCp1) * proportion; | |||
| } | |||
| static const Point<float> findQuadraticSubdivisionPoint (double proportion, const Point<float> points[3]) | |||
| static const Point<float> findQuadraticSubdivisionPoint (float proportion, const Point<float> points[3]) | |||
| { | |||
| const Point<float> mid1 (points[0] + (points[1] - points[0]) * proportion), | |||
| mid2 (points[1] + (points[2] - points[1]) * proportion); | |||
| @@ -473,10 +473,10 @@ static const Point<float> findQuadraticSubdivisionPoint (double proportion, cons | |||
| return mid1 + (mid2 - mid1) * proportion; | |||
| } | |||
| double DrawablePath::ValueTreeWrapper::Element::findProportionAlongLine (const Point<float>& targetPoint, RelativeCoordinate::NamedCoordinateFinder* nameFinder) const | |||
| float DrawablePath::ValueTreeWrapper::Element::findProportionAlongLine (const Point<float>& targetPoint, RelativeCoordinate::NamedCoordinateFinder* nameFinder) const | |||
| { | |||
| const Identifier i (state.getType()); | |||
| double bestProp = 0; | |||
| float bestProp = 0; | |||
| if (i == cubicToElement) | |||
| { | |||
| @@ -488,7 +488,7 @@ double DrawablePath::ValueTreeWrapper::Element::findProportionAlongLine (const P | |||
| for (int i = 110; --i >= 0;) | |||
| { | |||
| double prop = i > 10 ? ((i - 10) / 100.0) : (bestProp + ((i - 5) / 1000.0)); | |||
| float prop = i > 10 ? ((i - 10) / 100.0f) : (bestProp + ((i - 5) / 1000.0f)); | |||
| const Point<float> centre (findCubicSubdivisionPoint (prop, points)); | |||
| const float distance = centre.getDistanceFrom (targetPoint); | |||
| @@ -508,8 +508,8 @@ double DrawablePath::ValueTreeWrapper::Element::findProportionAlongLine (const P | |||
| for (int i = 110; --i >= 0;) | |||
| { | |||
| double prop = i > 10 ? ((i - 10) / 100.0) : (bestProp + ((i - 5) / 1000.0)); | |||
| const Point<float> centre (findQuadraticSubdivisionPoint (prop, points)); | |||
| float prop = i > 10 ? ((i - 10) / 100.0f) : (bestProp + ((i - 5) / 1000.0f)); | |||
| const Point<float> centre (findQuadraticSubdivisionPoint ((float) prop, points)); | |||
| const float distance = centre.getDistanceFrom (targetPoint); | |||
| if (distance < bestDistance) | |||
| @@ -536,7 +536,7 @@ ValueTree DrawablePath::ValueTreeWrapper::Element::insertPoint (const Point<floa | |||
| if (i == cubicToElement) | |||
| { | |||
| double bestProp = findProportionAlongLine (targetPoint, nameFinder); | |||
| float bestProp = findProportionAlongLine (targetPoint, nameFinder); | |||
| RelativePoint rp1 (getStartPoint()), rp2 (getControlPoint (0)), rp3 (getControlPoint (1)), rp4 (getEndPoint()); | |||
| const Point<float> points[] = { rp1.resolve (nameFinder), rp2.resolve (nameFinder), rp3.resolve (nameFinder), rp4.resolve (nameFinder) }; | |||
| @@ -564,7 +564,7 @@ ValueTree DrawablePath::ValueTreeWrapper::Element::insertPoint (const Point<floa | |||
| } | |||
| else if (i == quadraticToElement) | |||
| { | |||
| double bestProp = findProportionAlongLine (targetPoint, nameFinder); | |||
| float bestProp = findProportionAlongLine (targetPoint, nameFinder); | |||
| RelativePoint rp1 (getStartPoint()), rp2 (getControlPoint (0)), rp3 (getEndPoint()); | |||
| const Point<float> points[] = { rp1.resolve (nameFinder), rp2.resolve (nameFinder), rp3.resolve (nameFinder) }; | |||
| @@ -176,7 +176,7 @@ public: | |||
| void convertToPathBreak (UndoManager* undoManager); | |||
| ValueTree insertPoint (const Point<float>& targetPoint, RelativeCoordinate::NamedCoordinateFinder* nameFinder, UndoManager* undoManager); | |||
| void removePoint (UndoManager* undoManager); | |||
| double findProportionAlongLine (const Point<float>& targetPoint, RelativeCoordinate::NamedCoordinateFinder* nameFinder) const; | |||
| float findProportionAlongLine (const Point<float>& targetPoint, RelativeCoordinate::NamedCoordinateFinder* nameFinder) const; | |||
| static const Identifier mode, startSubPathElement, closeSubPathElement, | |||
| lineToElement, quadraticToElement, cubicToElement; | |||
| @@ -349,8 +349,6 @@ public: | |||
| callback (0), | |||
| inputId (inputId_), | |||
| outputId (outputId_), | |||
| outputDevice (0), | |||
| inputDevice (0), | |||
| numCallbacks (0), | |||
| inputChannelBuffer (1, 1), | |||
| outputChannelBuffer (1, 1) | |||
| @@ -415,7 +413,7 @@ public: | |||
| if (outputDevice->error.isNotEmpty()) | |||
| { | |||
| error = outputDevice->error; | |||
| deleteAndZero (outputDevice); | |||
| outputDevice = 0; | |||
| return; | |||
| } | |||
| @@ -426,7 +424,7 @@ public: | |||
| bufferSize)) | |||
| { | |||
| error = outputDevice->error; | |||
| deleteAndZero (outputDevice); | |||
| outputDevice = 0; | |||
| return; | |||
| } | |||
| } | |||
| @@ -438,7 +436,7 @@ public: | |||
| if (inputDevice->error.isNotEmpty()) | |||
| { | |||
| error = inputDevice->error; | |||
| deleteAndZero (inputDevice); | |||
| inputDevice = 0; | |||
| return; | |||
| } | |||
| @@ -449,7 +447,7 @@ public: | |||
| bufferSize)) | |||
| { | |||
| error = inputDevice->error; | |||
| deleteAndZero (inputDevice); | |||
| inputDevice = 0; | |||
| return; | |||
| } | |||
| } | |||
| @@ -491,8 +489,8 @@ public: | |||
| { | |||
| stopThread (6000); | |||
| deleteAndZero (inputDevice); | |||
| deleteAndZero (outputDevice); | |||
| inputDevice = 0; | |||
| outputDevice = 0; | |||
| inputChannelBuffer.setSize (1, 1); | |||
| outputChannelBuffer.setSize (1, 1); | |||
| @@ -585,8 +583,7 @@ public: | |||
| private: | |||
| //============================================================================== | |||
| const String inputId, outputId; | |||
| ALSADevice* outputDevice; | |||
| ALSADevice* inputDevice; | |||
| ScopedPointer<ALSADevice> outputDevice, inputDevice; | |||
| int numCallbacks; | |||
| CriticalSection callbackLock; | |||
| @@ -643,7 +640,7 @@ public: | |||
| outputId (outputId_), | |||
| isOpen_ (false), | |||
| isStarted (false), | |||
| internal (new ALSAThread (inputId_, outputId_)) | |||
| internal (inputId_, outputId_) | |||
| { | |||
| } | |||
| @@ -653,22 +650,22 @@ public: | |||
| const StringArray getOutputChannelNames() | |||
| { | |||
| return internal->channelNamesOut; | |||
| return internal.channelNamesOut; | |||
| } | |||
| const StringArray getInputChannelNames() | |||
| { | |||
| return internal->channelNamesIn; | |||
| return internal.channelNamesIn; | |||
| } | |||
| int getNumSampleRates() | |||
| { | |||
| return internal->sampleRates.size(); | |||
| return internal.sampleRates.size(); | |||
| } | |||
| double getSampleRate (int index) | |||
| { | |||
| return internal->sampleRates [index]; | |||
| return internal.sampleRates [index]; | |||
| } | |||
| int getNumBufferSizesAvailable() | |||
| @@ -715,17 +712,17 @@ public: | |||
| } | |||
| } | |||
| internal->open (inputChannels, outputChannels, | |||
| sampleRate, bufferSizeSamples); | |||
| internal.open (inputChannels, outputChannels, | |||
| sampleRate, bufferSizeSamples); | |||
| isOpen_ = internal->error.isEmpty(); | |||
| return internal->error; | |||
| isOpen_ = internal.error.isEmpty(); | |||
| return internal.error; | |||
| } | |||
| void close() | |||
| { | |||
| stop(); | |||
| internal->close(); | |||
| internal.close(); | |||
| isOpen_ = false; | |||
| } | |||
| @@ -736,27 +733,27 @@ public: | |||
| int getCurrentBufferSizeSamples() | |||
| { | |||
| return internal->bufferSize; | |||
| return internal.bufferSize; | |||
| } | |||
| double getCurrentSampleRate() | |||
| { | |||
| return internal->sampleRate; | |||
| return internal.sampleRate; | |||
| } | |||
| int getCurrentBitDepth() | |||
| { | |||
| return internal->getBitDepth(); | |||
| return internal.getBitDepth(); | |||
| } | |||
| const BigInteger getActiveOutputChannels() const | |||
| { | |||
| return internal->currentOutputChans; | |||
| return internal.currentOutputChans; | |||
| } | |||
| const BigInteger getActiveInputChannels() const | |||
| { | |||
| return internal->currentInputChans; | |||
| return internal.currentInputChans; | |||
| } | |||
| int getOutputLatencyInSamples() | |||
| @@ -774,17 +771,17 @@ public: | |||
| if (! isOpen_) | |||
| callback = 0; | |||
| internal->setCallback (callback); | |||
| if (callback != 0) | |||
| callback->audioDeviceAboutToStart (this); | |||
| internal.setCallback (callback); | |||
| isStarted = (callback != 0); | |||
| } | |||
| void stop() | |||
| { | |||
| AudioIODeviceCallback* const oldCallback = internal->callback; | |||
| AudioIODeviceCallback* const oldCallback = internal.callback; | |||
| start (0); | |||
| @@ -794,19 +791,19 @@ public: | |||
| bool isPlaying() | |||
| { | |||
| return isStarted && internal->error.isEmpty(); | |||
| return isStarted && internal.error.isEmpty(); | |||
| } | |||
| const String getLastError() | |||
| { | |||
| return internal->error; | |||
| return internal.error; | |||
| } | |||
| String inputId, outputId; | |||
| private: | |||
| bool isOpen_, isStarted; | |||
| ScopedPointer<ALSAThread> internal; | |||
| ALSAThread internal; | |||
| }; | |||