Browse Source

Tweaks to fake mouse-move behaviour. Improvements to WASAPI performance. AudioFormatManager is no longer a singleton - just create your own instance and use it instead.

tags/2021-05-28
Julian Storer 15 years ago
parent
commit
4d6b2daa93
13 changed files with 293 additions and 331 deletions
  1. +1
    -0
      extras/the jucer/build/mac/Jucer.xcodeproj/project.pbxproj
  2. +120
    -152
      juce_amalgamated.cpp
  3. +26
    -12
      juce_amalgamated.h
  4. +10
    -16
      src/audio/audio_file_formats/juce_AudioFormatManager.cpp
  5. +0
    -2
      src/audio/audio_file_formats/juce_AudioFormatManager.h
  6. +3
    -2
      src/audio/audio_file_formats/juce_AudioThumbnail.cpp
  7. +1
    -1
      src/core/juce_StandardHeader.h
  8. +12
    -57
      src/gui/components/juce_Component.cpp
  9. +5
    -8
      src/gui/components/juce_Component.h
  10. +48
    -4
      src/gui/components/juce_Desktop.cpp
  11. +18
    -0
      src/gui/components/juce_Desktop.h
  12. +1
    -1
      src/gui/components/mouse/juce_MouseInputSource.h
  13. +48
    -76
      src/native/windows/juce_win32_WASAPI.cpp

+ 1
- 0
extras/the jucer/build/mac/Jucer.xcodeproj/project.pbxproj View File

@@ -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;


+ 120
- 152
juce_amalgamated.cpp View File

@@ -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);
} }
} }




+ 26
- 12
juce_amalgamated.h View File

@@ -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;


+ 10
- 16
src/audio/audio_file_formats/juce_AudioFormatManager.cpp View File

@@ -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()


+ 0
- 2
src/audio/audio_file_formats/juce_AudioFormatManager.h View File

@@ -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.


+ 3
- 2
src/audio/audio_file_formats/juce_AudioThumbnail.cpp View File

@@ -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;
} }
} }


+ 1
- 1
src/core/juce_StandardHeader.h View File

@@ -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.


+ 12
- 57
src/gui/components/juce_Component.cpp View File

@@ -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();
} }
//============================================================================== //==============================================================================


+ 5
- 8
src/gui/components/juce_Component.h View File

@@ -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.


+ 48
- 4
src/gui/components/juce_Desktop.cpp View File

@@ -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)
{ {


+ 18
- 0
src/gui/components/juce_Desktop.h View File

@@ -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;


+ 1
- 1
src/gui/components/mouse/juce_MouseInputSource.h View File

@@ -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;


+ 48
- 76
src/native/windows/juce_win32_WASAPI.cpp View File

@@ -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);
} }
} }


Loading…
Cancel
Save