| @@ -524,6 +524,7 @@ | |||
| buildSettings = { | |||
| COPY_PHASE_STRIP = NO; | |||
| GCC_OPTIMIZATION_LEVEL = 0; | |||
| GCC_PREPROCESSOR_DEFINITIONS = "DEBUG=1"; | |||
| INFOPLIST_FILE = Info.plist; | |||
| INSTALL_PATH = "$(HOME)/Applications"; | |||
| PRODUCT_NAME = Jucer; | |||
| @@ -21718,20 +21718,15 @@ AudioFormatManager::AudioFormatManager() | |||
| AudioFormatManager::~AudioFormatManager() | |||
| { | |||
| clearFormats(); | |||
| clearSingletonInstance(); | |||
| } | |||
| juce_ImplementSingleton (AudioFormatManager); | |||
| void AudioFormatManager::registerFormat (AudioFormat* newFormat, | |||
| const bool makeThisTheDefaultFormat) | |||
| void AudioFormatManager::registerFormat (AudioFormat* newFormat, const bool makeThisTheDefaultFormat) | |||
| { | |||
| jassert (newFormat != 0); | |||
| if (newFormat != 0) | |||
| { | |||
| #if JUCE_DEBUG | |||
| #if JUCE_DEBUG | |||
| for (int i = getNumKnownFormats(); --i >= 0;) | |||
| { | |||
| if (getKnownFormat (i)->getFormatName() == newFormat->getFormatName()) | |||
| @@ -21739,7 +21734,7 @@ void AudioFormatManager::registerFormat (AudioFormat* newFormat, | |||
| jassertfalse; // trying to add the same format twice! | |||
| } | |||
| } | |||
| #endif | |||
| #endif | |||
| if (makeThisTheDefaultFormat) | |||
| defaultFormatIndex = getNumKnownFormats(); | |||
| @@ -21750,21 +21745,21 @@ void AudioFormatManager::registerFormat (AudioFormat* newFormat, | |||
| void AudioFormatManager::registerBasicFormats() | |||
| { | |||
| #if JUCE_MAC | |||
| #if JUCE_MAC | |||
| registerFormat (new AiffAudioFormat(), true); | |||
| registerFormat (new WavAudioFormat(), false); | |||
| #else | |||
| #else | |||
| registerFormat (new WavAudioFormat(), true); | |||
| registerFormat (new AiffAudioFormat(), false); | |||
| #endif | |||
| #endif | |||
| #if JUCE_USE_FLAC | |||
| #if JUCE_USE_FLAC | |||
| registerFormat (new FlacAudioFormat(), false); | |||
| #endif | |||
| #endif | |||
| #if JUCE_USE_OGGVORBIS | |||
| #if JUCE_USE_OGGVORBIS | |||
| registerFormat (new OggVorbisAudioFormat(), false); | |||
| #endif | |||
| #endif | |||
| } | |||
| void AudioFormatManager::clearFormats() | |||
| @@ -22298,9 +22293,10 @@ public: | |||
| for (int w = clip.getWidth(); --w >= 0;) | |||
| { | |||
| if (cacheData->isNonZero()) | |||
| g.drawVerticalLine (x++, jmax (midY - cacheData->maxValue * vscale - 0.3f, topY), | |||
| jmin (midY - cacheData->minValue * vscale + 0.3f, bottomY)); | |||
| g.drawVerticalLine (x, jmax (midY - cacheData->maxValue * vscale - 0.3f, topY), | |||
| jmin (midY - cacheData->minValue * vscale + 0.3f, bottomY)); | |||
| ++x; | |||
| ++cacheData; | |||
| } | |||
| } | |||
| @@ -41995,57 +41991,6 @@ void Component::internalMouseExit (MouseInputSource& source, const Point<int>& r | |||
| } | |||
| } | |||
| class InternalDragRepeater : public Timer | |||
| { | |||
| public: | |||
| InternalDragRepeater() | |||
| {} | |||
| ~InternalDragRepeater() | |||
| { | |||
| clearSingletonInstance(); | |||
| } | |||
| juce_DeclareSingleton_SingleThreaded_Minimal (InternalDragRepeater) | |||
| void timerCallback() | |||
| { | |||
| Desktop& desktop = Desktop::getInstance(); | |||
| int numMiceDown = 0; | |||
| for (int i = desktop.getNumMouseSources(); --i >= 0;) | |||
| { | |||
| MouseInputSource* const source = desktop.getMouseSource(i); | |||
| if (source->isDragging()) | |||
| { | |||
| source->triggerFakeMove(); | |||
| ++numMiceDown; | |||
| } | |||
| } | |||
| if (numMiceDown == 0) | |||
| deleteInstance(); | |||
| } | |||
| private: | |||
| JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (InternalDragRepeater); | |||
| }; | |||
| juce_ImplementSingleton_SingleThreaded (InternalDragRepeater) | |||
| void Component::beginDragAutoRepeat (const int interval) | |||
| { | |||
| if (interval > 0) | |||
| { | |||
| if (InternalDragRepeater::getInstance()->getTimerInterval() != interval) | |||
| InternalDragRepeater::getInstance()->startTimer (interval); | |||
| } | |||
| else | |||
| { | |||
| InternalDragRepeater::deleteInstance(); | |||
| } | |||
| } | |||
| void Component::internalMouseDown (MouseInputSource& source, const Point<int>& relativePos, const Time& time) | |||
| { | |||
| Desktop& desktop = Desktop::getInstance(); | |||
| @@ -42254,7 +42199,15 @@ void Component::internalMouseWheel (MouseInputSource& source, const Point<int>& | |||
| void Component::sendFakeMouseMove() const | |||
| { | |||
| Desktop::getInstance().getMainMouseSource().triggerFakeMove(); | |||
| MouseInputSource& mainMouse = Desktop::getInstance().getMainMouseSource(); | |||
| if (! mainMouse.isDragging()) | |||
| mainMouse.triggerFakeMove(); | |||
| } | |||
| void Component::beginDragAutoRepeat (const int interval) | |||
| { | |||
| Desktop::getInstance().beginDragAutoRepeat (interval); | |||
| } | |||
| void Component::broughtToFront() | |||
| @@ -42682,10 +42635,10 @@ ComponentPeer* Component::getPeer() const | |||
| { | |||
| if (flags.hasHeavyweightPeerFlag) | |||
| return ComponentPeer::getPeerFor (this); | |||
| else if (parentComponent_ != 0) | |||
| return parentComponent_->getPeer(); | |||
| else | |||
| else if (parentComponent_ == 0) | |||
| return 0; | |||
| return parentComponent_->getPeer(); | |||
| } | |||
| Component::BailOutChecker::BailOutChecker (Component* const component1, Component* const component2_) | |||
| @@ -42756,11 +42709,10 @@ extern void juce_updateMultiMonitorInfo (Array <Rectangle<int> >& monitorCoords, | |||
| void Desktop::refreshMonitorSizes() | |||
| { | |||
| const Array <Rectangle<int> > oldClipped (monitorCoordsClipped); | |||
| const Array <Rectangle<int> > oldUnclipped (monitorCoordsUnclipped); | |||
| Array <Rectangle<int> > oldClipped, oldUnclipped; | |||
| oldClipped.swapWithArray (monitorCoordsClipped); | |||
| oldUnclipped.swapWithArray (monitorCoordsUnclipped); | |||
| monitorCoordsClipped.clear(); | |||
| monitorCoordsUnclipped.clear(); | |||
| juce_updateMultiMonitorInfo (monitorCoordsClipped, true); | |||
| juce_updateMultiMonitorInfo (monitorCoordsUnclipped, false); | |||
| jassert (monitorCoordsClipped.size() == monitorCoordsUnclipped.size()); | |||
| @@ -42939,6 +42891,50 @@ MouseInputSource* Desktop::getDraggingMouseSource (int index) const throw() | |||
| return 0; | |||
| } | |||
| class MouseDragAutoRepeater : public Timer | |||
| { | |||
| public: | |||
| MouseDragAutoRepeater() {} | |||
| void timerCallback() | |||
| { | |||
| Desktop& desktop = Desktop::getInstance(); | |||
| int numMiceDown = 0; | |||
| for (int i = desktop.getNumMouseSources(); --i >= 0;) | |||
| { | |||
| MouseInputSource* const source = desktop.getMouseSource(i); | |||
| if (source->isDragging()) | |||
| { | |||
| source->triggerFakeMove(); | |||
| ++numMiceDown; | |||
| } | |||
| } | |||
| if (numMiceDown == 0) | |||
| desktop.beginDragAutoRepeat (0); | |||
| } | |||
| private: | |||
| JUCE_DECLARE_NON_COPYABLE (MouseDragAutoRepeater); | |||
| }; | |||
| void Desktop::beginDragAutoRepeat (const int interval) | |||
| { | |||
| if (interval > 0) | |||
| { | |||
| if (dragRepeater == 0) | |||
| dragRepeater = new MouseDragAutoRepeater(); | |||
| if (dragRepeater->getTimerInterval() != interval) | |||
| dragRepeater->startTimer (interval); | |||
| } | |||
| else | |||
| { | |||
| dragRepeater = 0; | |||
| } | |||
| } | |||
| void Desktop::addFocusChangeListener (FocusChangeListener* const listener) | |||
| { | |||
| focusListeners.add (listener); | |||
| @@ -251648,7 +251644,7 @@ AudioIODeviceType* juce_createAudioIODeviceType_DirectSound() | |||
| #if JUCE_INCLUDED_FILE && JUCE_WASAPI | |||
| #ifndef WASAPI_ENABLE_LOGGING | |||
| #define WASAPI_ENABLE_LOGGING 1 | |||
| #define WASAPI_ENABLE_LOGGING 0 | |||
| #endif | |||
| namespace WasapiClasses | |||
| @@ -251969,7 +251965,8 @@ public: | |||
| reservoirCapacity = 16384; | |||
| reservoir.setSize (actualNumChannels * reservoirCapacity * sizeof (float)); | |||
| return openClient (newSampleRate, newChannels) | |||
| && (numChannels == 0 || check (client->GetService (__uuidof (IAudioCaptureClient), (void**) captureClient.resetAndGetPointerAddress()))); | |||
| && (numChannels == 0 || check (client->GetService (__uuidof (IAudioCaptureClient), | |||
| (void**) captureClient.resetAndGetPointerAddress()))); | |||
| } | |||
| void close() | |||
| @@ -251979,18 +251976,19 @@ public: | |||
| reservoir.setSize (0); | |||
| } | |||
| void updateFormat (bool isFloat) | |||
| template <class SourceType> | |||
| void updateFormatWithType (SourceType*) | |||
| { | |||
| typedef AudioData::Pointer <AudioData::Float32, AudioData::NativeEndian, AudioData::NonInterleaved, AudioData::NonConst> NativeType; | |||
| converter = new AudioData::ConverterInstance <AudioData::Pointer <SourceType, AudioData::LittleEndian, AudioData::Interleaved, AudioData::Const>, NativeType> (actualNumChannels, 1); | |||
| } | |||
| if (isFloat) | |||
| converter = new AudioData::ConverterInstance <AudioData::Pointer <AudioData::Float32, AudioData::LittleEndian, AudioData::Interleaved, AudioData::Const>, NativeType> (actualNumChannels, 1); | |||
| else if (bytesPerSample == 4) | |||
| converter = new AudioData::ConverterInstance <AudioData::Pointer <AudioData::Int32, AudioData::LittleEndian, AudioData::Interleaved, AudioData::Const>, NativeType> (actualNumChannels, 1); | |||
| else if (bytesPerSample == 3) | |||
| converter = new AudioData::ConverterInstance <AudioData::Pointer <AudioData::Int24, AudioData::LittleEndian, AudioData::Interleaved, AudioData::Const>, NativeType> (actualNumChannels, 1); | |||
| else | |||
| converter = new AudioData::ConverterInstance <AudioData::Pointer <AudioData::Int16, AudioData::LittleEndian, AudioData::Interleaved, AudioData::Const>, NativeType> (actualNumChannels, 1); | |||
| void updateFormat (bool isFloat) | |||
| { | |||
| if (isFloat) updateFormatWithType ((AudioData::Float32*) 0); | |||
| else if (bytesPerSample == 4) updateFormatWithType ((AudioData::Int32*) 0); | |||
| else if (bytesPerSample == 3) updateFormatWithType ((AudioData::Int24*) 0); | |||
| else updateFormatWithType ((AudioData::Int16*) 0); | |||
| } | |||
| void copyBuffers (float** destBuffers, int numDestBuffers, int bufferSize, Thread& thread) | |||
| @@ -252011,7 +252009,7 @@ public: | |||
| bufferSize -= samplesToDo; | |||
| offset += samplesToDo; | |||
| reservoirSize -= samplesToDo; | |||
| reservoirSize = 0; | |||
| } | |||
| else | |||
| { | |||
| @@ -252021,14 +252019,14 @@ public: | |||
| if (packetLength == 0) | |||
| { | |||
| if (thread.threadShouldExit()) | |||
| if (thread.threadShouldExit() | |||
| || WaitForSingleObject (clientEvent, 1000) == WAIT_TIMEOUT) | |||
| break; | |||
| Thread::sleep (1); | |||
| continue; | |||
| } | |||
| uint8* inputData = 0; | |||
| uint8* inputData; | |||
| UINT32 numSamplesAvailable; | |||
| DWORD flags; | |||
| @@ -252089,18 +252087,19 @@ public: | |||
| renderClient = 0; | |||
| } | |||
| void updateFormat (bool isFloat) | |||
| template <class DestType> | |||
| void updateFormatWithType (DestType*) | |||
| { | |||
| typedef AudioData::Pointer <AudioData::Float32, AudioData::NativeEndian, AudioData::NonInterleaved, AudioData::Const> NativeType; | |||
| converter = new AudioData::ConverterInstance <NativeType, AudioData::Pointer <DestType, AudioData::LittleEndian, AudioData::Interleaved, AudioData::NonConst> > (1, actualNumChannels); | |||
| } | |||
| if (isFloat) | |||
| converter = new AudioData::ConverterInstance <NativeType, AudioData::Pointer <AudioData::Float32, AudioData::LittleEndian, AudioData::Interleaved, AudioData::NonConst> > (1, actualNumChannels); | |||
| else if (bytesPerSample == 4) | |||
| converter = new AudioData::ConverterInstance <NativeType, AudioData::Pointer <AudioData::Int32, AudioData::LittleEndian, AudioData::Interleaved, AudioData::NonConst> > (1, actualNumChannels); | |||
| else if (bytesPerSample == 3) | |||
| converter = new AudioData::ConverterInstance <NativeType, AudioData::Pointer <AudioData::Int24, AudioData::LittleEndian, AudioData::Interleaved, AudioData::NonConst> > (1, actualNumChannels); | |||
| else | |||
| converter = new AudioData::ConverterInstance <NativeType, AudioData::Pointer <AudioData::Int16, AudioData::LittleEndian, AudioData::Interleaved, AudioData::NonConst> > (1, actualNumChannels); | |||
| void updateFormat (bool isFloat) | |||
| { | |||
| if (isFloat) updateFormatWithType ((AudioData::Float32*) 0); | |||
| else if (bytesPerSample == 4) updateFormatWithType ((AudioData::Int32*) 0); | |||
| else if (bytesPerSample == 3) updateFormatWithType ((AudioData::Int24*) 0); | |||
| else updateFormatWithType ((AudioData::Int16*) 0); | |||
| } | |||
| void copyBuffers (const float** const srcBuffers, const int numSrcBuffers, int bufferSize, Thread& thread) | |||
| @@ -252121,10 +252120,10 @@ public: | |||
| if (samplesToDo <= 0) | |||
| { | |||
| if (thread.threadShouldExit()) | |||
| if (thread.threadShouldExit() | |||
| || WaitForSingleObject (clientEvent, 1000) == WAIT_TIMEOUT) | |||
| break; | |||
| Thread::sleep (0); | |||
| continue; | |||
| } | |||
| @@ -252288,11 +252287,8 @@ public: | |||
| return lastError; | |||
| } | |||
| if (inputDevice != 0) | |||
| ResetEvent (inputDevice->clientEvent); | |||
| if (outputDevice != 0) | |||
| ResetEvent (outputDevice->clientEvent); | |||
| if (inputDevice != 0) ResetEvent (inputDevice->clientEvent); | |||
| if (outputDevice != 0) ResetEvent (outputDevice->clientEvent); | |||
| startThread (8); | |||
| Thread::sleep (5); | |||
| @@ -252318,20 +252314,15 @@ public: | |||
| void close() | |||
| { | |||
| stop(); | |||
| signalThreadShouldExit(); | |||
| if (inputDevice != 0) | |||
| SetEvent (inputDevice->clientEvent); | |||
| if (outputDevice != 0) | |||
| SetEvent (outputDevice->clientEvent); | |||
| if (inputDevice != 0) SetEvent (inputDevice->clientEvent); | |||
| if (outputDevice != 0) SetEvent (outputDevice->clientEvent); | |||
| stopThread (5000); | |||
| if (inputDevice != 0) | |||
| inputDevice->close(); | |||
| if (outputDevice != 0) | |||
| outputDevice->close(); | |||
| if (inputDevice != 0) inputDevice->close(); | |||
| if (outputDevice != 0) outputDevice->close(); | |||
| isOpen_ = false; | |||
| } | |||
| @@ -252377,13 +252368,13 @@ public: | |||
| void setMMThreadPriority() | |||
| { | |||
| DynamicLibraryLoader dll ("avrt.dll"); | |||
| DynamicLibraryImport (AvSetMmThreadCharacteristics, avSetMmThreadCharacteristics, HANDLE, dll, (LPCTSTR, LPDWORD)) | |||
| DynamicLibraryImport (AvSetMmThreadCharacteristicsW, avSetMmThreadCharacteristics, HANDLE, dll, (LPCWSTR, LPDWORD)) | |||
| DynamicLibraryImport (AvSetMmThreadPriority, avSetMmThreadPriority, HANDLE, dll, (HANDLE, AVRT_PRIORITY)) | |||
| if (avSetMmThreadCharacteristics != 0 && avSetMmThreadPriority != 0) | |||
| { | |||
| DWORD dummy = 0; | |||
| HANDLE h = avSetMmThreadCharacteristics (_T("Pro Audio"), &dummy); | |||
| HANDLE h = avSetMmThreadCharacteristics (L"Pro Audio", &dummy); | |||
| if (h != 0) | |||
| avSetMmThreadPriority (h, AVRT_PRIORITY_NORMAL); | |||
| @@ -252396,13 +252387,6 @@ public: | |||
| const int bufferSize = currentBufferSizeSamples; | |||
| HANDLE events[2]; | |||
| int numEvents = 0; | |||
| if (inputDevice != 0) | |||
| events [numEvents++] = inputDevice->clientEvent; | |||
| if (outputDevice != 0) | |||
| events [numEvents++] = outputDevice->clientEvent; | |||
| const int numInputBuffers = getActiveInputChannels().countNumberOfSetBits(); | |||
| const int numOutputBuffers = getActiveOutputChannels().countNumberOfSetBits(); | |||
| @@ -252414,44 +252398,28 @@ public: | |||
| while (! threadShouldExit()) | |||
| { | |||
| const DWORD result = useExclusiveMode ? (inputDevice != 0 ? WaitForSingleObject (inputDevice->clientEvent, 1000) : S_OK) | |||
| : WaitForMultipleObjects (numEvents, events, true, 1000); | |||
| if (result == WAIT_TIMEOUT) | |||
| continue; | |||
| if (threadShouldExit()) | |||
| break; | |||
| if (inputDevice != 0) | |||
| { | |||
| inputDevice->copyBuffers (inputBuffers, numInputBuffers, bufferSize, *this); | |||
| // Make the callback.. | |||
| if (threadShouldExit()) | |||
| break; | |||
| } | |||
| JUCE_TRY | |||
| { | |||
| const ScopedLock sl (startStopLock); | |||
| if (isStarted) | |||
| { | |||
| JUCE_TRY | |||
| { | |||
| callback->audioDeviceIOCallback ((const float**) inputBuffers, | |||
| numInputBuffers, | |||
| outputBuffers, | |||
| numOutputBuffers, | |||
| bufferSize); | |||
| } | |||
| JUCE_CATCH_EXCEPTION | |||
| } | |||
| callback->audioDeviceIOCallback (const_cast <const float**> (inputBuffers), numInputBuffers, | |||
| outputBuffers, numOutputBuffers, bufferSize); | |||
| else | |||
| { | |||
| outs.clear(); | |||
| } | |||
| } | |||
| if (useExclusiveMode && WaitForSingleObject (outputDevice->clientEvent, 1000) == WAIT_TIMEOUT) | |||
| continue; | |||
| JUCE_CATCH_EXCEPTION | |||
| if (outputDevice != 0) | |||
| outputDevice->copyBuffers ((const float**) outputBuffers, numOutputBuffers, bufferSize, *this); | |||
| outputDevice->copyBuffers (const_cast <const float**> (outputBuffers), numOutputBuffers, bufferSize, *this); | |||
| } | |||
| } | |||
| @@ -64,7 +64,7 @@ | |||
| */ | |||
| #define JUCE_MAJOR_VERSION 1 | |||
| #define JUCE_MINOR_VERSION 52 | |||
| #define JUCE_BUILDNUMBER 104 | |||
| #define JUCE_BUILDNUMBER 105 | |||
| /** Current Juce version number. | |||
| @@ -27535,24 +27535,21 @@ public: | |||
| float wheelIncrementY); | |||
| /** Ensures that a non-stop stream of mouse-drag events will be sent during the | |||
| next mouse-drag operation. | |||
| current mouse-drag operation. | |||
| This allows you to make sure that mouseDrag() events sent continuously, even | |||
| This allows you to make sure that mouseDrag() events are sent continuously, even | |||
| when the mouse isn't moving. This can be useful for things like auto-scrolling | |||
| components when the mouse is near an edge. | |||
| Call this method during a mouseDown() or mouseDrag() callback, specifying the | |||
| minimum interval between consecutive mouse drag callbacks. The callbacks | |||
| will continue until the mouse is released, and then the interval will be reset, | |||
| so you need to make sure it's called every time you begin a drag event. If it | |||
| is called when the mouse isn't actually being pressed, it will apply to the next | |||
| mouse-drag operation that happens. | |||
| so you need to make sure it's called every time you begin a drag event. | |||
| Passing an interval of 0 or less will cancel the auto-repeat. | |||
| @see mouseDrag | |||
| @see mouseDrag, Desktop::beginDragAutoRepeat | |||
| */ | |||
| static void beginDragAutoRepeat (int millisecondIntervalBetweenCallbacks); | |||
| static void beginDragAutoRepeat (int millisecondsBetweenCallbacks); | |||
| /** Causes automatic repaints when the mouse enters or exits this component. | |||
| @@ -29591,6 +29588,23 @@ public: | |||
| */ | |||
| MouseInputSource* getDraggingMouseSource (int index) const throw(); | |||
| /** Ensures that a non-stop stream of mouse-drag events will be sent during the | |||
| current mouse-drag operation. | |||
| This allows you to make sure that mouseDrag() events are sent continuously, even | |||
| when the mouse isn't moving. This can be useful for things like auto-scrolling | |||
| components when the mouse is near an edge. | |||
| Call this method during a mouseDown() or mouseDrag() callback, specifying the | |||
| minimum interval between consecutive mouse drag callbacks. The callbacks | |||
| will continue until the mouse is released, and then the interval will be reset, | |||
| so you need to make sure it's called every time you begin a drag event. | |||
| Passing an interval of 0 or less will cancel the auto-repeat. | |||
| @see mouseDrag | |||
| */ | |||
| void beginDragAutoRepeat (int millisecondsBetweenCallbacks); | |||
| /** In a tablet device which can be turned around, this is used to inidicate the orientation. */ | |||
| enum DisplayOrientation | |||
| { | |||
| @@ -29654,6 +29668,8 @@ private: | |||
| int mouseClickCounter; | |||
| void incrementMouseClickCounter() throw(); | |||
| ScopedPointer<Timer> dragRepeater; | |||
| Component* kioskModeComponent; | |||
| Rectangle<int> kioskComponentOriginalBounds; | |||
| @@ -32425,8 +32441,6 @@ public: | |||
| /** Destructor. */ | |||
| ~AudioFormatManager(); | |||
| juce_DeclareSingleton (AudioFormatManager, false); | |||
| /** Adds a format to the manager's list of available file types. | |||
| The object passed-in will be deleted by this object, so don't keep a pointer | |||
| @@ -56680,7 +56694,7 @@ public: | |||
| /** Returns the component that was last known to be under this pointer. */ | |||
| Component* getComponentUnderMouse() const; | |||
| /** Tells the device to dispatch a mouse-move event. | |||
| /** Tells the device to dispatch a mouse-move or mouse-drag event. | |||
| This is asynchronous - the event will occur on the message thread. | |||
| */ | |||
| void triggerFakeMove() const; | |||
| @@ -44,22 +44,16 @@ AudioFormatManager::AudioFormatManager() | |||
| AudioFormatManager::~AudioFormatManager() | |||
| { | |||
| clearFormats(); | |||
| clearSingletonInstance(); | |||
| } | |||
| juce_ImplementSingleton (AudioFormatManager); | |||
| //============================================================================== | |||
| void AudioFormatManager::registerFormat (AudioFormat* newFormat, | |||
| const bool makeThisTheDefaultFormat) | |||
| void AudioFormatManager::registerFormat (AudioFormat* newFormat, const bool makeThisTheDefaultFormat) | |||
| { | |||
| jassert (newFormat != 0); | |||
| if (newFormat != 0) | |||
| { | |||
| #if JUCE_DEBUG | |||
| #if JUCE_DEBUG | |||
| for (int i = getNumKnownFormats(); --i >= 0;) | |||
| { | |||
| if (getKnownFormat (i)->getFormatName() == newFormat->getFormatName()) | |||
| @@ -67,7 +61,7 @@ void AudioFormatManager::registerFormat (AudioFormat* newFormat, | |||
| jassertfalse; // trying to add the same format twice! | |||
| } | |||
| } | |||
| #endif | |||
| #endif | |||
| if (makeThisTheDefaultFormat) | |||
| defaultFormatIndex = getNumKnownFormats(); | |||
| @@ -78,21 +72,21 @@ void AudioFormatManager::registerFormat (AudioFormat* newFormat, | |||
| void AudioFormatManager::registerBasicFormats() | |||
| { | |||
| #if JUCE_MAC | |||
| #if JUCE_MAC | |||
| registerFormat (new AiffAudioFormat(), true); | |||
| registerFormat (new WavAudioFormat(), false); | |||
| #else | |||
| #else | |||
| registerFormat (new WavAudioFormat(), true); | |||
| registerFormat (new AiffAudioFormat(), false); | |||
| #endif | |||
| #endif | |||
| #if JUCE_USE_FLAC | |||
| #if JUCE_USE_FLAC | |||
| registerFormat (new FlacAudioFormat(), false); | |||
| #endif | |||
| #endif | |||
| #if JUCE_USE_OGGVORBIS | |||
| #if JUCE_USE_OGGVORBIS | |||
| registerFormat (new OggVorbisAudioFormat(), false); | |||
| #endif | |||
| #endif | |||
| } | |||
| void AudioFormatManager::clearFormats() | |||
| @@ -56,8 +56,6 @@ public: | |||
| /** Destructor. */ | |||
| ~AudioFormatManager(); | |||
| juce_DeclareSingleton (AudioFormatManager, false); | |||
| //============================================================================== | |||
| /** Adds a format to the manager's list of available file types. | |||
| @@ -370,9 +370,10 @@ public: | |||
| for (int w = clip.getWidth(); --w >= 0;) | |||
| { | |||
| if (cacheData->isNonZero()) | |||
| g.drawVerticalLine (x++, jmax (midY - cacheData->maxValue * vscale - 0.3f, topY), | |||
| jmin (midY - cacheData->minValue * vscale + 0.3f, bottomY)); | |||
| g.drawVerticalLine (x, jmax (midY - cacheData->maxValue * vscale - 0.3f, topY), | |||
| jmin (midY - cacheData->minValue * vscale + 0.3f, bottomY)); | |||
| ++x; | |||
| ++cacheData; | |||
| } | |||
| } | |||
| @@ -33,7 +33,7 @@ | |||
| */ | |||
| #define JUCE_MAJOR_VERSION 1 | |||
| #define JUCE_MINOR_VERSION 52 | |||
| #define JUCE_BUILDNUMBER 104 | |||
| #define JUCE_BUILDNUMBER 105 | |||
| /** Current Juce version number. | |||
| @@ -2296,59 +2296,6 @@ void Component::internalMouseExit (MouseInputSource& source, const Point<int>& r | |||
| } | |||
| } | |||
| //============================================================================== | |||
| class InternalDragRepeater : public Timer | |||
| { | |||
| public: | |||
| InternalDragRepeater() | |||
| {} | |||
| ~InternalDragRepeater() | |||
| { | |||
| clearSingletonInstance(); | |||
| } | |||
| juce_DeclareSingleton_SingleThreaded_Minimal (InternalDragRepeater) | |||
| void timerCallback() | |||
| { | |||
| Desktop& desktop = Desktop::getInstance(); | |||
| int numMiceDown = 0; | |||
| for (int i = desktop.getNumMouseSources(); --i >= 0;) | |||
| { | |||
| MouseInputSource* const source = desktop.getMouseSource(i); | |||
| if (source->isDragging()) | |||
| { | |||
| source->triggerFakeMove(); | |||
| ++numMiceDown; | |||
| } | |||
| } | |||
| if (numMiceDown == 0) | |||
| deleteInstance(); | |||
| } | |||
| private: | |||
| JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (InternalDragRepeater); | |||
| }; | |||
| juce_ImplementSingleton_SingleThreaded (InternalDragRepeater) | |||
| void Component::beginDragAutoRepeat (const int interval) | |||
| { | |||
| if (interval > 0) | |||
| { | |||
| if (InternalDragRepeater::getInstance()->getTimerInterval() != interval) | |||
| InternalDragRepeater::getInstance()->startTimer (interval); | |||
| } | |||
| else | |||
| { | |||
| InternalDragRepeater::deleteInstance(); | |||
| } | |||
| } | |||
| //============================================================================== | |||
| void Component::internalMouseDown (MouseInputSource& source, const Point<int>& relativePos, const Time& time) | |||
| { | |||
| @@ -2559,7 +2506,15 @@ void Component::internalMouseWheel (MouseInputSource& source, const Point<int>& | |||
| void Component::sendFakeMouseMove() const | |||
| { | |||
| Desktop::getInstance().getMainMouseSource().triggerFakeMove(); | |||
| MouseInputSource& mainMouse = Desktop::getInstance().getMainMouseSource(); | |||
| if (! mainMouse.isDragging()) | |||
| mainMouse.triggerFakeMove(); | |||
| } | |||
| void Component::beginDragAutoRepeat (const int interval) | |||
| { | |||
| Desktop::getInstance().beginDragAutoRepeat (interval); | |||
| } | |||
| void Component::broughtToFront() | |||
| @@ -2993,10 +2948,10 @@ ComponentPeer* Component::getPeer() const | |||
| { | |||
| if (flags.hasHeavyweightPeerFlag) | |||
| return ComponentPeer::getPeerFor (this); | |||
| else if (parentComponent_ != 0) | |||
| return parentComponent_->getPeer(); | |||
| else | |||
| else if (parentComponent_ == 0) | |||
| return 0; | |||
| return parentComponent_->getPeer(); | |||
| } | |||
| //============================================================================== | |||
| @@ -1514,24 +1514,21 @@ public: | |||
| //============================================================================== | |||
| /** Ensures that a non-stop stream of mouse-drag events will be sent during the | |||
| next mouse-drag operation. | |||
| current mouse-drag operation. | |||
| This allows you to make sure that mouseDrag() events sent continuously, even | |||
| This allows you to make sure that mouseDrag() events are sent continuously, even | |||
| when the mouse isn't moving. This can be useful for things like auto-scrolling | |||
| components when the mouse is near an edge. | |||
| Call this method during a mouseDown() or mouseDrag() callback, specifying the | |||
| minimum interval between consecutive mouse drag callbacks. The callbacks | |||
| will continue until the mouse is released, and then the interval will be reset, | |||
| so you need to make sure it's called every time you begin a drag event. If it | |||
| is called when the mouse isn't actually being pressed, it will apply to the next | |||
| mouse-drag operation that happens. | |||
| so you need to make sure it's called every time you begin a drag event. | |||
| Passing an interval of 0 or less will cancel the auto-repeat. | |||
| @see mouseDrag | |||
| @see mouseDrag, Desktop::beginDragAutoRepeat | |||
| */ | |||
| static void beginDragAutoRepeat (int millisecondIntervalBetweenCallbacks); | |||
| static void beginDragAutoRepeat (int millisecondsBetweenCallbacks); | |||
| /** Causes automatic repaints when the mouse enters or exits this component. | |||
| @@ -70,11 +70,10 @@ extern void juce_updateMultiMonitorInfo (Array <Rectangle<int> >& monitorCoords, | |||
| void Desktop::refreshMonitorSizes() | |||
| { | |||
| const Array <Rectangle<int> > oldClipped (monitorCoordsClipped); | |||
| const Array <Rectangle<int> > oldUnclipped (monitorCoordsUnclipped); | |||
| Array <Rectangle<int> > oldClipped, oldUnclipped; | |||
| oldClipped.swapWithArray (monitorCoordsClipped); | |||
| oldUnclipped.swapWithArray (monitorCoordsUnclipped); | |||
| monitorCoordsClipped.clear(); | |||
| monitorCoordsUnclipped.clear(); | |||
| juce_updateMultiMonitorInfo (monitorCoordsClipped, true); | |||
| juce_updateMultiMonitorInfo (monitorCoordsUnclipped, false); | |||
| jassert (monitorCoordsClipped.size() == monitorCoordsUnclipped.size()); | |||
| @@ -256,6 +255,51 @@ MouseInputSource* Desktop::getDraggingMouseSource (int index) const throw() | |||
| return 0; | |||
| } | |||
| //============================================================================== | |||
| class MouseDragAutoRepeater : public Timer | |||
| { | |||
| public: | |||
| MouseDragAutoRepeater() {} | |||
| void timerCallback() | |||
| { | |||
| Desktop& desktop = Desktop::getInstance(); | |||
| int numMiceDown = 0; | |||
| for (int i = desktop.getNumMouseSources(); --i >= 0;) | |||
| { | |||
| MouseInputSource* const source = desktop.getMouseSource(i); | |||
| if (source->isDragging()) | |||
| { | |||
| source->triggerFakeMove(); | |||
| ++numMiceDown; | |||
| } | |||
| } | |||
| if (numMiceDown == 0) | |||
| desktop.beginDragAutoRepeat (0); | |||
| } | |||
| private: | |||
| JUCE_DECLARE_NON_COPYABLE (MouseDragAutoRepeater); | |||
| }; | |||
| void Desktop::beginDragAutoRepeat (const int interval) | |||
| { | |||
| if (interval > 0) | |||
| { | |||
| if (dragRepeater == 0) | |||
| dragRepeater = new MouseDragAutoRepeater(); | |||
| if (dragRepeater->getTimerInterval() != interval) | |||
| dragRepeater->startTimer (interval); | |||
| } | |||
| else | |||
| { | |||
| dragRepeater = 0; | |||
| } | |||
| } | |||
| //============================================================================== | |||
| void Desktop::addFocusChangeListener (FocusChangeListener* const listener) | |||
| { | |||
| @@ -281,6 +281,22 @@ public: | |||
| */ | |||
| MouseInputSource* getDraggingMouseSource (int index) const throw(); | |||
| /** Ensures that a non-stop stream of mouse-drag events will be sent during the | |||
| current mouse-drag operation. | |||
| This allows you to make sure that mouseDrag() events are sent continuously, even | |||
| when the mouse isn't moving. This can be useful for things like auto-scrolling | |||
| components when the mouse is near an edge. | |||
| Call this method during a mouseDown() or mouseDrag() callback, specifying the | |||
| minimum interval between consecutive mouse drag callbacks. The callbacks | |||
| will continue until the mouse is released, and then the interval will be reset, | |||
| so you need to make sure it's called every time you begin a drag event. | |||
| Passing an interval of 0 or less will cancel the auto-repeat. | |||
| @see mouseDrag | |||
| */ | |||
| void beginDragAutoRepeat (int millisecondsBetweenCallbacks); | |||
| //============================================================================== | |||
| /** In a tablet device which can be turned around, this is used to inidicate the orientation. */ | |||
| @@ -347,6 +363,8 @@ private: | |||
| int mouseClickCounter; | |||
| void incrementMouseClickCounter() throw(); | |||
| ScopedPointer<Timer> dragRepeater; | |||
| Component* kioskModeComponent; | |||
| Rectangle<int> kioskComponentOriginalBounds; | |||
| @@ -109,7 +109,7 @@ public: | |||
| /** Returns the component that was last known to be under this pointer. */ | |||
| Component* getComponentUnderMouse() const; | |||
| /** Tells the device to dispatch a mouse-move event. | |||
| /** Tells the device to dispatch a mouse-move or mouse-drag event. | |||
| This is asynchronous - the event will occur on the message thread. | |||
| */ | |||
| void triggerFakeMove() const; | |||
| @@ -28,7 +28,7 @@ | |||
| #if JUCE_INCLUDED_FILE && JUCE_WASAPI | |||
| #ifndef WASAPI_ENABLE_LOGGING | |||
| #define WASAPI_ENABLE_LOGGING 1 | |||
| #define WASAPI_ENABLE_LOGGING 0 | |||
| #endif | |||
| //============================================================================== | |||
| @@ -353,7 +353,8 @@ public: | |||
| reservoirCapacity = 16384; | |||
| reservoir.setSize (actualNumChannels * reservoirCapacity * sizeof (float)); | |||
| return openClient (newSampleRate, newChannels) | |||
| && (numChannels == 0 || check (client->GetService (__uuidof (IAudioCaptureClient), (void**) captureClient.resetAndGetPointerAddress()))); | |||
| && (numChannels == 0 || check (client->GetService (__uuidof (IAudioCaptureClient), | |||
| (void**) captureClient.resetAndGetPointerAddress()))); | |||
| } | |||
| void close() | |||
| @@ -363,18 +364,19 @@ public: | |||
| reservoir.setSize (0); | |||
| } | |||
| void updateFormat (bool isFloat) | |||
| template <class SourceType> | |||
| void updateFormatWithType (SourceType*) | |||
| { | |||
| typedef AudioData::Pointer <AudioData::Float32, AudioData::NativeEndian, AudioData::NonInterleaved, AudioData::NonConst> NativeType; | |||
| converter = new AudioData::ConverterInstance <AudioData::Pointer <SourceType, AudioData::LittleEndian, AudioData::Interleaved, AudioData::Const>, NativeType> (actualNumChannels, 1); | |||
| } | |||
| if (isFloat) | |||
| converter = new AudioData::ConverterInstance <AudioData::Pointer <AudioData::Float32, AudioData::LittleEndian, AudioData::Interleaved, AudioData::Const>, NativeType> (actualNumChannels, 1); | |||
| else if (bytesPerSample == 4) | |||
| converter = new AudioData::ConverterInstance <AudioData::Pointer <AudioData::Int32, AudioData::LittleEndian, AudioData::Interleaved, AudioData::Const>, NativeType> (actualNumChannels, 1); | |||
| else if (bytesPerSample == 3) | |||
| converter = new AudioData::ConverterInstance <AudioData::Pointer <AudioData::Int24, AudioData::LittleEndian, AudioData::Interleaved, AudioData::Const>, NativeType> (actualNumChannels, 1); | |||
| else | |||
| converter = new AudioData::ConverterInstance <AudioData::Pointer <AudioData::Int16, AudioData::LittleEndian, AudioData::Interleaved, AudioData::Const>, NativeType> (actualNumChannels, 1); | |||
| void updateFormat (bool isFloat) | |||
| { | |||
| if (isFloat) updateFormatWithType ((AudioData::Float32*) 0); | |||
| else if (bytesPerSample == 4) updateFormatWithType ((AudioData::Int32*) 0); | |||
| else if (bytesPerSample == 3) updateFormatWithType ((AudioData::Int24*) 0); | |||
| else updateFormatWithType ((AudioData::Int16*) 0); | |||
| } | |||
| void copyBuffers (float** destBuffers, int numDestBuffers, int bufferSize, Thread& thread) | |||
| @@ -395,7 +397,7 @@ public: | |||
| bufferSize -= samplesToDo; | |||
| offset += samplesToDo; | |||
| reservoirSize -= samplesToDo; | |||
| reservoirSize = 0; | |||
| } | |||
| else | |||
| { | |||
| @@ -405,14 +407,14 @@ public: | |||
| if (packetLength == 0) | |||
| { | |||
| if (thread.threadShouldExit()) | |||
| if (thread.threadShouldExit() | |||
| || WaitForSingleObject (clientEvent, 1000) == WAIT_TIMEOUT) | |||
| break; | |||
| Thread::sleep (1); | |||
| continue; | |||
| } | |||
| uint8* inputData = 0; | |||
| uint8* inputData; | |||
| UINT32 numSamplesAvailable; | |||
| DWORD flags; | |||
| @@ -474,18 +476,19 @@ public: | |||
| renderClient = 0; | |||
| } | |||
| void updateFormat (bool isFloat) | |||
| template <class DestType> | |||
| void updateFormatWithType (DestType*) | |||
| { | |||
| typedef AudioData::Pointer <AudioData::Float32, AudioData::NativeEndian, AudioData::NonInterleaved, AudioData::Const> NativeType; | |||
| converter = new AudioData::ConverterInstance <NativeType, AudioData::Pointer <DestType, AudioData::LittleEndian, AudioData::Interleaved, AudioData::NonConst> > (1, actualNumChannels); | |||
| } | |||
| if (isFloat) | |||
| converter = new AudioData::ConverterInstance <NativeType, AudioData::Pointer <AudioData::Float32, AudioData::LittleEndian, AudioData::Interleaved, AudioData::NonConst> > (1, actualNumChannels); | |||
| else if (bytesPerSample == 4) | |||
| converter = new AudioData::ConverterInstance <NativeType, AudioData::Pointer <AudioData::Int32, AudioData::LittleEndian, AudioData::Interleaved, AudioData::NonConst> > (1, actualNumChannels); | |||
| else if (bytesPerSample == 3) | |||
| converter = new AudioData::ConverterInstance <NativeType, AudioData::Pointer <AudioData::Int24, AudioData::LittleEndian, AudioData::Interleaved, AudioData::NonConst> > (1, actualNumChannels); | |||
| else | |||
| converter = new AudioData::ConverterInstance <NativeType, AudioData::Pointer <AudioData::Int16, AudioData::LittleEndian, AudioData::Interleaved, AudioData::NonConst> > (1, actualNumChannels); | |||
| void updateFormat (bool isFloat) | |||
| { | |||
| if (isFloat) updateFormatWithType ((AudioData::Float32*) 0); | |||
| else if (bytesPerSample == 4) updateFormatWithType ((AudioData::Int32*) 0); | |||
| else if (bytesPerSample == 3) updateFormatWithType ((AudioData::Int24*) 0); | |||
| else updateFormatWithType ((AudioData::Int16*) 0); | |||
| } | |||
| void copyBuffers (const float** const srcBuffers, const int numSrcBuffers, int bufferSize, Thread& thread) | |||
| @@ -506,10 +509,10 @@ public: | |||
| if (samplesToDo <= 0) | |||
| { | |||
| if (thread.threadShouldExit()) | |||
| if (thread.threadShouldExit() | |||
| || WaitForSingleObject (clientEvent, 1000) == WAIT_TIMEOUT) | |||
| break; | |||
| Thread::sleep (0); | |||
| continue; | |||
| } | |||
| @@ -675,11 +678,8 @@ public: | |||
| return lastError; | |||
| } | |||
| if (inputDevice != 0) | |||
| ResetEvent (inputDevice->clientEvent); | |||
| if (outputDevice != 0) | |||
| ResetEvent (outputDevice->clientEvent); | |||
| if (inputDevice != 0) ResetEvent (inputDevice->clientEvent); | |||
| if (outputDevice != 0) ResetEvent (outputDevice->clientEvent); | |||
| startThread (8); | |||
| Thread::sleep (5); | |||
| @@ -705,20 +705,15 @@ public: | |||
| void close() | |||
| { | |||
| stop(); | |||
| signalThreadShouldExit(); | |||
| if (inputDevice != 0) | |||
| SetEvent (inputDevice->clientEvent); | |||
| if (outputDevice != 0) | |||
| SetEvent (outputDevice->clientEvent); | |||
| if (inputDevice != 0) SetEvent (inputDevice->clientEvent); | |||
| if (outputDevice != 0) SetEvent (outputDevice->clientEvent); | |||
| stopThread (5000); | |||
| if (inputDevice != 0) | |||
| inputDevice->close(); | |||
| if (outputDevice != 0) | |||
| outputDevice->close(); | |||
| if (inputDevice != 0) inputDevice->close(); | |||
| if (outputDevice != 0) outputDevice->close(); | |||
| isOpen_ = false; | |||
| } | |||
| @@ -764,13 +759,13 @@ public: | |||
| void setMMThreadPriority() | |||
| { | |||
| DynamicLibraryLoader dll ("avrt.dll"); | |||
| DynamicLibraryImport (AvSetMmThreadCharacteristics, avSetMmThreadCharacteristics, HANDLE, dll, (LPCTSTR, LPDWORD)) | |||
| DynamicLibraryImport (AvSetMmThreadCharacteristicsW, avSetMmThreadCharacteristics, HANDLE, dll, (LPCWSTR, LPDWORD)) | |||
| DynamicLibraryImport (AvSetMmThreadPriority, avSetMmThreadPriority, HANDLE, dll, (HANDLE, AVRT_PRIORITY)) | |||
| if (avSetMmThreadCharacteristics != 0 && avSetMmThreadPriority != 0) | |||
| { | |||
| DWORD dummy = 0; | |||
| HANDLE h = avSetMmThreadCharacteristics (_T("Pro Audio"), &dummy); | |||
| HANDLE h = avSetMmThreadCharacteristics (L"Pro Audio", &dummy); | |||
| if (h != 0) | |||
| avSetMmThreadPriority (h, AVRT_PRIORITY_NORMAL); | |||
| @@ -783,13 +778,6 @@ public: | |||
| const int bufferSize = currentBufferSizeSamples; | |||
| HANDLE events[2]; | |||
| int numEvents = 0; | |||
| if (inputDevice != 0) | |||
| events [numEvents++] = inputDevice->clientEvent; | |||
| if (outputDevice != 0) | |||
| events [numEvents++] = outputDevice->clientEvent; | |||
| const int numInputBuffers = getActiveInputChannels().countNumberOfSetBits(); | |||
| const int numOutputBuffers = getActiveOutputChannels().countNumberOfSetBits(); | |||
| @@ -801,44 +789,28 @@ public: | |||
| while (! threadShouldExit()) | |||
| { | |||
| const DWORD result = useExclusiveMode ? (inputDevice != 0 ? WaitForSingleObject (inputDevice->clientEvent, 1000) : S_OK) | |||
| : WaitForMultipleObjects (numEvents, events, true, 1000); | |||
| if (result == WAIT_TIMEOUT) | |||
| continue; | |||
| if (threadShouldExit()) | |||
| break; | |||
| if (inputDevice != 0) | |||
| { | |||
| inputDevice->copyBuffers (inputBuffers, numInputBuffers, bufferSize, *this); | |||
| // Make the callback.. | |||
| if (threadShouldExit()) | |||
| break; | |||
| } | |||
| JUCE_TRY | |||
| { | |||
| const ScopedLock sl (startStopLock); | |||
| if (isStarted) | |||
| { | |||
| JUCE_TRY | |||
| { | |||
| callback->audioDeviceIOCallback ((const float**) inputBuffers, | |||
| numInputBuffers, | |||
| outputBuffers, | |||
| numOutputBuffers, | |||
| bufferSize); | |||
| } | |||
| JUCE_CATCH_EXCEPTION | |||
| } | |||
| callback->audioDeviceIOCallback (const_cast <const float**> (inputBuffers), numInputBuffers, | |||
| outputBuffers, numOutputBuffers, bufferSize); | |||
| else | |||
| { | |||
| outs.clear(); | |||
| } | |||
| } | |||
| if (useExclusiveMode && WaitForSingleObject (outputDevice->clientEvent, 1000) == WAIT_TIMEOUT) | |||
| continue; | |||
| JUCE_CATCH_EXCEPTION | |||
| if (outputDevice != 0) | |||
| outputDevice->copyBuffers ((const float**) outputBuffers, numOutputBuffers, bufferSize, *this); | |||
| outputDevice->copyBuffers (const_cast <const float**> (outputBuffers), numOutputBuffers, bufferSize, *this); | |||
| } | |||
| } | |||