| @@ -524,6 +524,7 @@ | |||||
| buildSettings = { | buildSettings = { | ||||
| COPY_PHASE_STRIP = NO; | COPY_PHASE_STRIP = NO; | ||||
| GCC_OPTIMIZATION_LEVEL = 0; | GCC_OPTIMIZATION_LEVEL = 0; | ||||
| GCC_PREPROCESSOR_DEFINITIONS = "DEBUG=1"; | |||||
| INFOPLIST_FILE = Info.plist; | INFOPLIST_FILE = Info.plist; | ||||
| INSTALL_PATH = "$(HOME)/Applications"; | INSTALL_PATH = "$(HOME)/Applications"; | ||||
| PRODUCT_NAME = Jucer; | PRODUCT_NAME = Jucer; | ||||
| @@ -21718,20 +21718,15 @@ AudioFormatManager::AudioFormatManager() | |||||
| 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); | jassert (newFormat != 0); | ||||
| if (newFormat != 0) | if (newFormat != 0) | ||||
| { | { | ||||
| #if JUCE_DEBUG | |||||
| #if JUCE_DEBUG | |||||
| for (int i = getNumKnownFormats(); --i >= 0;) | for (int i = getNumKnownFormats(); --i >= 0;) | ||||
| { | { | ||||
| if (getKnownFormat (i)->getFormatName() == newFormat->getFormatName()) | if (getKnownFormat (i)->getFormatName() == newFormat->getFormatName()) | ||||
| @@ -21739,7 +21734,7 @@ void AudioFormatManager::registerFormat (AudioFormat* newFormat, | |||||
| jassertfalse; // trying to add the same format twice! | jassertfalse; // trying to add the same format twice! | ||||
| } | } | ||||
| } | } | ||||
| #endif | |||||
| #endif | |||||
| if (makeThisTheDefaultFormat) | if (makeThisTheDefaultFormat) | ||||
| defaultFormatIndex = getNumKnownFormats(); | defaultFormatIndex = getNumKnownFormats(); | ||||
| @@ -21750,21 +21745,21 @@ void AudioFormatManager::registerFormat (AudioFormat* newFormat, | |||||
| void AudioFormatManager::registerBasicFormats() | void AudioFormatManager::registerBasicFormats() | ||||
| { | { | ||||
| #if JUCE_MAC | |||||
| #if JUCE_MAC | |||||
| registerFormat (new AiffAudioFormat(), true); | registerFormat (new AiffAudioFormat(), true); | ||||
| registerFormat (new WavAudioFormat(), false); | registerFormat (new WavAudioFormat(), false); | ||||
| #else | |||||
| #else | |||||
| registerFormat (new WavAudioFormat(), true); | registerFormat (new WavAudioFormat(), true); | ||||
| registerFormat (new AiffAudioFormat(), false); | registerFormat (new AiffAudioFormat(), false); | ||||
| #endif | |||||
| #endif | |||||
| #if JUCE_USE_FLAC | |||||
| #if JUCE_USE_FLAC | |||||
| registerFormat (new FlacAudioFormat(), false); | registerFormat (new FlacAudioFormat(), false); | ||||
| #endif | |||||
| #endif | |||||
| #if JUCE_USE_OGGVORBIS | |||||
| #if JUCE_USE_OGGVORBIS | |||||
| registerFormat (new OggVorbisAudioFormat(), false); | registerFormat (new OggVorbisAudioFormat(), false); | ||||
| #endif | |||||
| #endif | |||||
| } | } | ||||
| void AudioFormatManager::clearFormats() | void AudioFormatManager::clearFormats() | ||||
| @@ -22298,9 +22293,10 @@ public: | |||||
| for (int w = clip.getWidth(); --w >= 0;) | for (int w = clip.getWidth(); --w >= 0;) | ||||
| { | { | ||||
| if (cacheData->isNonZero()) | 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; | ++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) | void Component::internalMouseDown (MouseInputSource& source, const Point<int>& relativePos, const Time& time) | ||||
| { | { | ||||
| Desktop& desktop = Desktop::getInstance(); | Desktop& desktop = Desktop::getInstance(); | ||||
| @@ -42254,7 +42199,15 @@ void Component::internalMouseWheel (MouseInputSource& source, const Point<int>& | |||||
| void Component::sendFakeMouseMove() const | 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() | void Component::broughtToFront() | ||||
| @@ -42682,10 +42635,10 @@ ComponentPeer* Component::getPeer() const | |||||
| { | { | ||||
| if (flags.hasHeavyweightPeerFlag) | if (flags.hasHeavyweightPeerFlag) | ||||
| return ComponentPeer::getPeerFor (this); | return ComponentPeer::getPeerFor (this); | ||||
| else if (parentComponent_ != 0) | |||||
| return parentComponent_->getPeer(); | |||||
| else | |||||
| else if (parentComponent_ == 0) | |||||
| return 0; | return 0; | ||||
| return parentComponent_->getPeer(); | |||||
| } | } | ||||
| Component::BailOutChecker::BailOutChecker (Component* const component1, Component* const component2_) | Component::BailOutChecker::BailOutChecker (Component* const component1, Component* const component2_) | ||||
| @@ -42756,11 +42709,10 @@ extern void juce_updateMultiMonitorInfo (Array <Rectangle<int> >& monitorCoords, | |||||
| void Desktop::refreshMonitorSizes() | 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 (monitorCoordsClipped, true); | ||||
| juce_updateMultiMonitorInfo (monitorCoordsUnclipped, false); | juce_updateMultiMonitorInfo (monitorCoordsUnclipped, false); | ||||
| jassert (monitorCoordsClipped.size() == monitorCoordsUnclipped.size()); | jassert (monitorCoordsClipped.size() == monitorCoordsUnclipped.size()); | ||||
| @@ -42939,6 +42891,50 @@ MouseInputSource* Desktop::getDraggingMouseSource (int index) const throw() | |||||
| return 0; | 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) | void Desktop::addFocusChangeListener (FocusChangeListener* const listener) | ||||
| { | { | ||||
| focusListeners.add (listener); | focusListeners.add (listener); | ||||
| @@ -251648,7 +251644,7 @@ AudioIODeviceType* juce_createAudioIODeviceType_DirectSound() | |||||
| #if JUCE_INCLUDED_FILE && JUCE_WASAPI | #if JUCE_INCLUDED_FILE && JUCE_WASAPI | ||||
| #ifndef WASAPI_ENABLE_LOGGING | #ifndef WASAPI_ENABLE_LOGGING | ||||
| #define WASAPI_ENABLE_LOGGING 1 | |||||
| #define WASAPI_ENABLE_LOGGING 0 | |||||
| #endif | #endif | ||||
| namespace WasapiClasses | namespace WasapiClasses | ||||
| @@ -251969,7 +251965,8 @@ public: | |||||
| reservoirCapacity = 16384; | reservoirCapacity = 16384; | ||||
| reservoir.setSize (actualNumChannels * reservoirCapacity * sizeof (float)); | reservoir.setSize (actualNumChannels * reservoirCapacity * sizeof (float)); | ||||
| return openClient (newSampleRate, newChannels) | 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() | void close() | ||||
| @@ -251979,18 +251976,19 @@ public: | |||||
| reservoir.setSize (0); | 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; | 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) | void copyBuffers (float** destBuffers, int numDestBuffers, int bufferSize, Thread& thread) | ||||
| @@ -252011,7 +252009,7 @@ public: | |||||
| bufferSize -= samplesToDo; | bufferSize -= samplesToDo; | ||||
| offset += samplesToDo; | offset += samplesToDo; | ||||
| reservoirSize -= samplesToDo; | |||||
| reservoirSize = 0; | |||||
| } | } | ||||
| else | else | ||||
| { | { | ||||
| @@ -252021,14 +252019,14 @@ public: | |||||
| if (packetLength == 0) | if (packetLength == 0) | ||||
| { | { | ||||
| if (thread.threadShouldExit()) | |||||
| if (thread.threadShouldExit() | |||||
| || WaitForSingleObject (clientEvent, 1000) == WAIT_TIMEOUT) | |||||
| break; | break; | ||||
| Thread::sleep (1); | |||||
| continue; | continue; | ||||
| } | } | ||||
| uint8* inputData = 0; | |||||
| uint8* inputData; | |||||
| UINT32 numSamplesAvailable; | UINT32 numSamplesAvailable; | ||||
| DWORD flags; | DWORD flags; | ||||
| @@ -252089,18 +252087,19 @@ public: | |||||
| renderClient = 0; | renderClient = 0; | ||||
| } | } | ||||
| void updateFormat (bool isFloat) | |||||
| template <class DestType> | |||||
| void updateFormatWithType (DestType*) | |||||
| { | { | ||||
| typedef AudioData::Pointer <AudioData::Float32, AudioData::NativeEndian, AudioData::NonInterleaved, AudioData::Const> NativeType; | 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) | void copyBuffers (const float** const srcBuffers, const int numSrcBuffers, int bufferSize, Thread& thread) | ||||
| @@ -252121,10 +252120,10 @@ public: | |||||
| if (samplesToDo <= 0) | if (samplesToDo <= 0) | ||||
| { | { | ||||
| if (thread.threadShouldExit()) | |||||
| if (thread.threadShouldExit() | |||||
| || WaitForSingleObject (clientEvent, 1000) == WAIT_TIMEOUT) | |||||
| break; | break; | ||||
| Thread::sleep (0); | |||||
| continue; | continue; | ||||
| } | } | ||||
| @@ -252288,11 +252287,8 @@ public: | |||||
| return lastError; | 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); | startThread (8); | ||||
| Thread::sleep (5); | Thread::sleep (5); | ||||
| @@ -252318,20 +252314,15 @@ public: | |||||
| void close() | void close() | ||||
| { | { | ||||
| stop(); | 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); | stopThread (5000); | ||||
| if (inputDevice != 0) | |||||
| inputDevice->close(); | |||||
| if (outputDevice != 0) | |||||
| outputDevice->close(); | |||||
| if (inputDevice != 0) inputDevice->close(); | |||||
| if (outputDevice != 0) outputDevice->close(); | |||||
| isOpen_ = false; | isOpen_ = false; | ||||
| } | } | ||||
| @@ -252377,13 +252368,13 @@ public: | |||||
| void setMMThreadPriority() | void setMMThreadPriority() | ||||
| { | { | ||||
| DynamicLibraryLoader dll ("avrt.dll"); | 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)) | DynamicLibraryImport (AvSetMmThreadPriority, avSetMmThreadPriority, HANDLE, dll, (HANDLE, AVRT_PRIORITY)) | ||||
| if (avSetMmThreadCharacteristics != 0 && avSetMmThreadPriority != 0) | if (avSetMmThreadCharacteristics != 0 && avSetMmThreadPriority != 0) | ||||
| { | { | ||||
| DWORD dummy = 0; | DWORD dummy = 0; | ||||
| HANDLE h = avSetMmThreadCharacteristics (_T("Pro Audio"), &dummy); | |||||
| HANDLE h = avSetMmThreadCharacteristics (L"Pro Audio", &dummy); | |||||
| if (h != 0) | if (h != 0) | ||||
| avSetMmThreadPriority (h, AVRT_PRIORITY_NORMAL); | avSetMmThreadPriority (h, AVRT_PRIORITY_NORMAL); | ||||
| @@ -252396,13 +252387,6 @@ public: | |||||
| const int bufferSize = currentBufferSizeSamples; | 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 numInputBuffers = getActiveInputChannels().countNumberOfSetBits(); | ||||
| const int numOutputBuffers = getActiveOutputChannels().countNumberOfSetBits(); | const int numOutputBuffers = getActiveOutputChannels().countNumberOfSetBits(); | ||||
| @@ -252414,44 +252398,28 @@ public: | |||||
| while (! threadShouldExit()) | 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) | if (inputDevice != 0) | ||||
| { | |||||
| inputDevice->copyBuffers (inputBuffers, numInputBuffers, bufferSize, *this); | inputDevice->copyBuffers (inputBuffers, numInputBuffers, bufferSize, *this); | ||||
| // Make the callback.. | |||||
| if (threadShouldExit()) | |||||
| break; | |||||
| } | |||||
| JUCE_TRY | |||||
| { | { | ||||
| const ScopedLock sl (startStopLock); | const ScopedLock sl (startStopLock); | ||||
| if (isStarted) | 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 | else | ||||
| { | |||||
| outs.clear(); | outs.clear(); | ||||
| } | |||||
| } | } | ||||
| if (useExclusiveMode && WaitForSingleObject (outputDevice->clientEvent, 1000) == WAIT_TIMEOUT) | |||||
| continue; | |||||
| JUCE_CATCH_EXCEPTION | |||||
| if (outputDevice != 0) | 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_MAJOR_VERSION 1 | ||||
| #define JUCE_MINOR_VERSION 52 | #define JUCE_MINOR_VERSION 52 | ||||
| #define JUCE_BUILDNUMBER 104 | |||||
| #define JUCE_BUILDNUMBER 105 | |||||
| /** Current Juce version number. | /** Current Juce version number. | ||||
| @@ -27535,24 +27535,21 @@ public: | |||||
| float wheelIncrementY); | float wheelIncrementY); | ||||
| /** Ensures that a non-stop stream of mouse-drag events will be sent during the | /** 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 | when the mouse isn't moving. This can be useful for things like auto-scrolling | ||||
| components when the mouse is near an edge. | components when the mouse is near an edge. | ||||
| Call this method during a mouseDown() or mouseDrag() callback, specifying the | Call this method during a mouseDown() or mouseDrag() callback, specifying the | ||||
| minimum interval between consecutive mouse drag callbacks. The callbacks | minimum interval between consecutive mouse drag callbacks. The callbacks | ||||
| will continue until the mouse is released, and then the interval will be reset, | 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. | 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. | /** Causes automatic repaints when the mouse enters or exits this component. | ||||
| @@ -29591,6 +29588,23 @@ public: | |||||
| */ | */ | ||||
| MouseInputSource* getDraggingMouseSource (int index) const throw(); | 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. */ | /** In a tablet device which can be turned around, this is used to inidicate the orientation. */ | ||||
| enum DisplayOrientation | enum DisplayOrientation | ||||
| { | { | ||||
| @@ -29654,6 +29668,8 @@ private: | |||||
| int mouseClickCounter; | int mouseClickCounter; | ||||
| void incrementMouseClickCounter() throw(); | void incrementMouseClickCounter() throw(); | ||||
| ScopedPointer<Timer> dragRepeater; | |||||
| Component* kioskModeComponent; | Component* kioskModeComponent; | ||||
| Rectangle<int> kioskComponentOriginalBounds; | Rectangle<int> kioskComponentOriginalBounds; | ||||
| @@ -32425,8 +32441,6 @@ public: | |||||
| /** Destructor. */ | /** Destructor. */ | ||||
| ~AudioFormatManager(); | ~AudioFormatManager(); | ||||
| juce_DeclareSingleton (AudioFormatManager, false); | |||||
| /** Adds a format to the manager's list of available file types. | /** 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 | 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. */ | /** Returns the component that was last known to be under this pointer. */ | ||||
| Component* getComponentUnderMouse() const; | 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. | This is asynchronous - the event will occur on the message thread. | ||||
| */ | */ | ||||
| void triggerFakeMove() const; | void triggerFakeMove() const; | ||||
| @@ -44,22 +44,16 @@ AudioFormatManager::AudioFormatManager() | |||||
| 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); | jassert (newFormat != 0); | ||||
| if (newFormat != 0) | if (newFormat != 0) | ||||
| { | { | ||||
| #if JUCE_DEBUG | |||||
| #if JUCE_DEBUG | |||||
| for (int i = getNumKnownFormats(); --i >= 0;) | for (int i = getNumKnownFormats(); --i >= 0;) | ||||
| { | { | ||||
| if (getKnownFormat (i)->getFormatName() == newFormat->getFormatName()) | if (getKnownFormat (i)->getFormatName() == newFormat->getFormatName()) | ||||
| @@ -67,7 +61,7 @@ void AudioFormatManager::registerFormat (AudioFormat* newFormat, | |||||
| jassertfalse; // trying to add the same format twice! | jassertfalse; // trying to add the same format twice! | ||||
| } | } | ||||
| } | } | ||||
| #endif | |||||
| #endif | |||||
| if (makeThisTheDefaultFormat) | if (makeThisTheDefaultFormat) | ||||
| defaultFormatIndex = getNumKnownFormats(); | defaultFormatIndex = getNumKnownFormats(); | ||||
| @@ -78,21 +72,21 @@ void AudioFormatManager::registerFormat (AudioFormat* newFormat, | |||||
| void AudioFormatManager::registerBasicFormats() | void AudioFormatManager::registerBasicFormats() | ||||
| { | { | ||||
| #if JUCE_MAC | |||||
| #if JUCE_MAC | |||||
| registerFormat (new AiffAudioFormat(), true); | registerFormat (new AiffAudioFormat(), true); | ||||
| registerFormat (new WavAudioFormat(), false); | registerFormat (new WavAudioFormat(), false); | ||||
| #else | |||||
| #else | |||||
| registerFormat (new WavAudioFormat(), true); | registerFormat (new WavAudioFormat(), true); | ||||
| registerFormat (new AiffAudioFormat(), false); | registerFormat (new AiffAudioFormat(), false); | ||||
| #endif | |||||
| #endif | |||||
| #if JUCE_USE_FLAC | |||||
| #if JUCE_USE_FLAC | |||||
| registerFormat (new FlacAudioFormat(), false); | registerFormat (new FlacAudioFormat(), false); | ||||
| #endif | |||||
| #endif | |||||
| #if JUCE_USE_OGGVORBIS | |||||
| #if JUCE_USE_OGGVORBIS | |||||
| registerFormat (new OggVorbisAudioFormat(), false); | registerFormat (new OggVorbisAudioFormat(), false); | ||||
| #endif | |||||
| #endif | |||||
| } | } | ||||
| void AudioFormatManager::clearFormats() | void AudioFormatManager::clearFormats() | ||||
| @@ -56,8 +56,6 @@ public: | |||||
| /** Destructor. */ | /** Destructor. */ | ||||
| ~AudioFormatManager(); | ~AudioFormatManager(); | ||||
| juce_DeclareSingleton (AudioFormatManager, false); | |||||
| //============================================================================== | //============================================================================== | ||||
| /** Adds a format to the manager's list of available file types. | /** Adds a format to the manager's list of available file types. | ||||
| @@ -370,9 +370,10 @@ public: | |||||
| for (int w = clip.getWidth(); --w >= 0;) | for (int w = clip.getWidth(); --w >= 0;) | ||||
| { | { | ||||
| if (cacheData->isNonZero()) | 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; | ++cacheData; | ||||
| } | } | ||||
| } | } | ||||
| @@ -33,7 +33,7 @@ | |||||
| */ | */ | ||||
| #define JUCE_MAJOR_VERSION 1 | #define JUCE_MAJOR_VERSION 1 | ||||
| #define JUCE_MINOR_VERSION 52 | #define JUCE_MINOR_VERSION 52 | ||||
| #define JUCE_BUILDNUMBER 104 | |||||
| #define JUCE_BUILDNUMBER 105 | |||||
| /** Current Juce version number. | /** 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) | 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 | 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() | void Component::broughtToFront() | ||||
| @@ -2993,10 +2948,10 @@ ComponentPeer* Component::getPeer() const | |||||
| { | { | ||||
| if (flags.hasHeavyweightPeerFlag) | if (flags.hasHeavyweightPeerFlag) | ||||
| return ComponentPeer::getPeerFor (this); | return ComponentPeer::getPeerFor (this); | ||||
| else if (parentComponent_ != 0) | |||||
| return parentComponent_->getPeer(); | |||||
| else | |||||
| else if (parentComponent_ == 0) | |||||
| return 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 | /** 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 | when the mouse isn't moving. This can be useful for things like auto-scrolling | ||||
| components when the mouse is near an edge. | components when the mouse is near an edge. | ||||
| Call this method during a mouseDown() or mouseDrag() callback, specifying the | Call this method during a mouseDown() or mouseDrag() callback, specifying the | ||||
| minimum interval between consecutive mouse drag callbacks. The callbacks | minimum interval between consecutive mouse drag callbacks. The callbacks | ||||
| will continue until the mouse is released, and then the interval will be reset, | 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. | 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. | /** 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() | 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 (monitorCoordsClipped, true); | ||||
| juce_updateMultiMonitorInfo (monitorCoordsUnclipped, false); | juce_updateMultiMonitorInfo (monitorCoordsUnclipped, false); | ||||
| jassert (monitorCoordsClipped.size() == monitorCoordsUnclipped.size()); | jassert (monitorCoordsClipped.size() == monitorCoordsUnclipped.size()); | ||||
| @@ -256,6 +255,51 @@ MouseInputSource* Desktop::getDraggingMouseSource (int index) const throw() | |||||
| return 0; | 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) | void Desktop::addFocusChangeListener (FocusChangeListener* const listener) | ||||
| { | { | ||||
| @@ -281,6 +281,22 @@ public: | |||||
| */ | */ | ||||
| MouseInputSource* getDraggingMouseSource (int index) const throw(); | 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. */ | /** In a tablet device which can be turned around, this is used to inidicate the orientation. */ | ||||
| @@ -347,6 +363,8 @@ private: | |||||
| int mouseClickCounter; | int mouseClickCounter; | ||||
| void incrementMouseClickCounter() throw(); | void incrementMouseClickCounter() throw(); | ||||
| ScopedPointer<Timer> dragRepeater; | |||||
| Component* kioskModeComponent; | Component* kioskModeComponent; | ||||
| Rectangle<int> kioskComponentOriginalBounds; | Rectangle<int> kioskComponentOriginalBounds; | ||||
| @@ -109,7 +109,7 @@ public: | |||||
| /** Returns the component that was last known to be under this pointer. */ | /** Returns the component that was last known to be under this pointer. */ | ||||
| Component* getComponentUnderMouse() const; | 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. | This is asynchronous - the event will occur on the message thread. | ||||
| */ | */ | ||||
| void triggerFakeMove() const; | void triggerFakeMove() const; | ||||
| @@ -28,7 +28,7 @@ | |||||
| #if JUCE_INCLUDED_FILE && JUCE_WASAPI | #if JUCE_INCLUDED_FILE && JUCE_WASAPI | ||||
| #ifndef WASAPI_ENABLE_LOGGING | #ifndef WASAPI_ENABLE_LOGGING | ||||
| #define WASAPI_ENABLE_LOGGING 1 | |||||
| #define WASAPI_ENABLE_LOGGING 0 | |||||
| #endif | #endif | ||||
| //============================================================================== | //============================================================================== | ||||
| @@ -353,7 +353,8 @@ public: | |||||
| reservoirCapacity = 16384; | reservoirCapacity = 16384; | ||||
| reservoir.setSize (actualNumChannels * reservoirCapacity * sizeof (float)); | reservoir.setSize (actualNumChannels * reservoirCapacity * sizeof (float)); | ||||
| return openClient (newSampleRate, newChannels) | 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() | void close() | ||||
| @@ -363,18 +364,19 @@ public: | |||||
| reservoir.setSize (0); | 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; | 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) | void copyBuffers (float** destBuffers, int numDestBuffers, int bufferSize, Thread& thread) | ||||
| @@ -395,7 +397,7 @@ public: | |||||
| bufferSize -= samplesToDo; | bufferSize -= samplesToDo; | ||||
| offset += samplesToDo; | offset += samplesToDo; | ||||
| reservoirSize -= samplesToDo; | |||||
| reservoirSize = 0; | |||||
| } | } | ||||
| else | else | ||||
| { | { | ||||
| @@ -405,14 +407,14 @@ public: | |||||
| if (packetLength == 0) | if (packetLength == 0) | ||||
| { | { | ||||
| if (thread.threadShouldExit()) | |||||
| if (thread.threadShouldExit() | |||||
| || WaitForSingleObject (clientEvent, 1000) == WAIT_TIMEOUT) | |||||
| break; | break; | ||||
| Thread::sleep (1); | |||||
| continue; | continue; | ||||
| } | } | ||||
| uint8* inputData = 0; | |||||
| uint8* inputData; | |||||
| UINT32 numSamplesAvailable; | UINT32 numSamplesAvailable; | ||||
| DWORD flags; | DWORD flags; | ||||
| @@ -474,18 +476,19 @@ public: | |||||
| renderClient = 0; | renderClient = 0; | ||||
| } | } | ||||
| void updateFormat (bool isFloat) | |||||
| template <class DestType> | |||||
| void updateFormatWithType (DestType*) | |||||
| { | { | ||||
| typedef AudioData::Pointer <AudioData::Float32, AudioData::NativeEndian, AudioData::NonInterleaved, AudioData::Const> NativeType; | 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) | void copyBuffers (const float** const srcBuffers, const int numSrcBuffers, int bufferSize, Thread& thread) | ||||
| @@ -506,10 +509,10 @@ public: | |||||
| if (samplesToDo <= 0) | if (samplesToDo <= 0) | ||||
| { | { | ||||
| if (thread.threadShouldExit()) | |||||
| if (thread.threadShouldExit() | |||||
| || WaitForSingleObject (clientEvent, 1000) == WAIT_TIMEOUT) | |||||
| break; | break; | ||||
| Thread::sleep (0); | |||||
| continue; | continue; | ||||
| } | } | ||||
| @@ -675,11 +678,8 @@ public: | |||||
| return lastError; | 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); | startThread (8); | ||||
| Thread::sleep (5); | Thread::sleep (5); | ||||
| @@ -705,20 +705,15 @@ public: | |||||
| void close() | void close() | ||||
| { | { | ||||
| stop(); | 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); | stopThread (5000); | ||||
| if (inputDevice != 0) | |||||
| inputDevice->close(); | |||||
| if (outputDevice != 0) | |||||
| outputDevice->close(); | |||||
| if (inputDevice != 0) inputDevice->close(); | |||||
| if (outputDevice != 0) outputDevice->close(); | |||||
| isOpen_ = false; | isOpen_ = false; | ||||
| } | } | ||||
| @@ -764,13 +759,13 @@ public: | |||||
| void setMMThreadPriority() | void setMMThreadPriority() | ||||
| { | { | ||||
| DynamicLibraryLoader dll ("avrt.dll"); | 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)) | DynamicLibraryImport (AvSetMmThreadPriority, avSetMmThreadPriority, HANDLE, dll, (HANDLE, AVRT_PRIORITY)) | ||||
| if (avSetMmThreadCharacteristics != 0 && avSetMmThreadPriority != 0) | if (avSetMmThreadCharacteristics != 0 && avSetMmThreadPriority != 0) | ||||
| { | { | ||||
| DWORD dummy = 0; | DWORD dummy = 0; | ||||
| HANDLE h = avSetMmThreadCharacteristics (_T("Pro Audio"), &dummy); | |||||
| HANDLE h = avSetMmThreadCharacteristics (L"Pro Audio", &dummy); | |||||
| if (h != 0) | if (h != 0) | ||||
| avSetMmThreadPriority (h, AVRT_PRIORITY_NORMAL); | avSetMmThreadPriority (h, AVRT_PRIORITY_NORMAL); | ||||
| @@ -783,13 +778,6 @@ public: | |||||
| const int bufferSize = currentBufferSizeSamples; | 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 numInputBuffers = getActiveInputChannels().countNumberOfSetBits(); | ||||
| const int numOutputBuffers = getActiveOutputChannels().countNumberOfSetBits(); | const int numOutputBuffers = getActiveOutputChannels().countNumberOfSetBits(); | ||||
| @@ -801,44 +789,28 @@ public: | |||||
| while (! threadShouldExit()) | 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) | if (inputDevice != 0) | ||||
| { | |||||
| inputDevice->copyBuffers (inputBuffers, numInputBuffers, bufferSize, *this); | inputDevice->copyBuffers (inputBuffers, numInputBuffers, bufferSize, *this); | ||||
| // Make the callback.. | |||||
| if (threadShouldExit()) | |||||
| break; | |||||
| } | |||||
| JUCE_TRY | |||||
| { | { | ||||
| const ScopedLock sl (startStopLock); | const ScopedLock sl (startStopLock); | ||||
| if (isStarted) | 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 | else | ||||
| { | |||||
| outs.clear(); | outs.clear(); | ||||
| } | |||||
| } | } | ||||
| if (useExclusiveMode && WaitForSingleObject (outputDevice->clientEvent, 1000) == WAIT_TIMEOUT) | |||||
| continue; | |||||
| JUCE_CATCH_EXCEPTION | |||||
| if (outputDevice != 0) | if (outputDevice != 0) | ||||
| outputDevice->copyBuffers ((const float**) outputBuffers, numOutputBuffers, bufferSize, *this); | |||||
| outputDevice->copyBuffers (const_cast <const float**> (outputBuffers), numOutputBuffers, bufferSize, *this); | |||||
| } | } | ||||
| } | } | ||||