Browse Source

Added device detection for DirectSound. New method addToDesktop() for ResizableWindow.

tags/2021-05-28
Julian Storer 14 years ago
parent
commit
dbe5768527
9 changed files with 395 additions and 480 deletions
  1. +9
    -3
      extras/Introjucer/Source/Application/jucer_MainWindow.cpp
  2. +188
    -235
      juce_amalgamated.cpp
  3. +3
    -0
      juce_amalgamated.h
  4. +6
    -1
      src/gui/components/windows/juce_ResizableWindow.cpp
  5. +3
    -0
      src/gui/components/windows/juce_ResizableWindow.h
  6. +37
    -101
      src/native/windows/juce_win32_ASIO.cpp
  7. +112
    -121
      src/native/windows/juce_win32_DirectSound.cpp
  8. +33
    -0
      src/native/windows/juce_win32_Messaging.cpp
  9. +4
    -19
      src/native/windows/juce_win32_WASAPI.cpp

+ 9
- 3
extras/Introjucer/Source/Application/jucer_MainWindow.cpp View File

@@ -37,15 +37,16 @@ ApplicationCommandManager* commandManager = nullptr;
MainWindow::MainWindow() MainWindow::MainWindow()
: DocumentWindow (JUCEApplication::getInstance()->getApplicationName(), : DocumentWindow (JUCEApplication::getInstance()->getApplicationName(),
Colour::greyLevel (0.6f), Colour::greyLevel (0.6f),
DocumentWindow::allButtons)
DocumentWindow::allButtons,
false)
{ {
setUsingNativeTitleBar (true); setUsingNativeTitleBar (true);
setContentOwned (new ProjectContentComponent(), false); setContentOwned (new ProjectContentComponent(), false);
#if ! JUCE_MAC
#if ! JUCE_MAC
JucerApplication* app = static_cast<JucerApplication*> (JUCEApplication::getInstance()); JucerApplication* app = static_cast<JucerApplication*> (JUCEApplication::getInstance());
setMenuBar (app->menuModel); setMenuBar (app->menuModel);
#endif
#endif
setResizable (true, false); setResizable (true, false);
@@ -77,6 +78,11 @@ MainWindow::MainWindow()
//getPeer()->setCurrentRenderingEngine (0); //getPeer()->setCurrentRenderingEngine (0);
getLookAndFeel().setColour (ColourSelector::backgroundColourId, Colours::transparentBlack); getLookAndFeel().setColour (ColourSelector::backgroundColourId, Colours::transparentBlack);
setVisible (true);
addToDesktop();
getContentComponent()->grabKeyboardFocus();
} }
MainWindow::~MainWindow() MainWindow::~MainWindow()


+ 188
- 235
juce_amalgamated.cpp View File

@@ -80492,7 +80492,7 @@ void ResizableWindow::initialise (const bool shouldAddToDesktop)
lastNonFullScreenPos.setBounds (50, 50, 256, 256); lastNonFullScreenPos.setBounds (50, 50, 256, 256);


if (shouldAddToDesktop) if (shouldAddToDesktop)
Component::addToDesktop (ResizableWindow::getDesktopWindowStyleFlags());
addToDesktop();
} }


int ResizableWindow::getDesktopWindowStyleFlags() const int ResizableWindow::getDesktopWindowStyleFlags() const
@@ -80505,6 +80505,11 @@ int ResizableWindow::getDesktopWindowStyleFlags() const
return styleFlags; return styleFlags;
} }


void ResizableWindow::addToDesktop()
{
Component::addToDesktop (ResizableWindow::getDesktopWindowStyleFlags());
}

void ResizableWindow::clearContentComponent() void ResizableWindow::clearContentComponent()
{ {
if (ownsContentComponent) if (ownsContentComponent)
@@ -247265,6 +247270,38 @@ void MessageManager::doPlatformSpecificShutdown()
OleUninitialize(); OleUninitialize();
} }


class DeviceChangeDetector // (Used by various audio classes)
{
public:
DeviceChangeDetector (const wchar_t* const name)
: messageWindow (name, (WNDPROC) deviceChangeEventCallback)
{
SetWindowLongPtr (messageWindow.getHWND(), GWLP_USERDATA, (LONG_PTR) this);
}

virtual ~DeviceChangeDetector() {}

protected:
virtual void systemDeviceChanged() = 0;

private:
HiddenMessageWindow messageWindow;

static LRESULT CALLBACK deviceChangeEventCallback (HWND h, const UINT message,
const WPARAM wParam, const LPARAM lParam)
{
if (message == WM_DEVICECHANGE
&& (wParam == 0x8000 /*DBT_DEVICEARRIVAL*/
|| wParam == 0x8004 /*DBT_DEVICEREMOVECOMPLETE*/
|| wParam == 0x0007 /*DBT_DEVNODES_CHANGED*/))
{
((DeviceChangeDetector*) GetWindowLongPtr (h, GWLP_USERDATA))->systemDeviceChanged();
}

return DefWindowProc (h, message, wParam, lParam);
}
};

#endif #endif


/*** End of inlined file: juce_win32_Messaging.cpp ***/ /*** End of inlined file: juce_win32_Messaging.cpp ***/
@@ -256845,8 +256882,6 @@ namespace ASIODebugging
class ASIOAudioIODevice; class ASIOAudioIODevice;
static ASIOAudioIODevice* volatile currentASIODev[3] = { 0 }; static ASIOAudioIODevice* volatile currentASIODev[3] = { 0 };


static const int maxASIOChannels = 160;

class JUCE_API ASIOAudioIODevice : public AudioIODevice, class JUCE_API ASIOAudioIODevice : public AudioIODevice,
private Timer private Timer
{ {
@@ -257141,30 +257176,7 @@ public:


const int totalBuffers = numActiveInputChans + numActiveOutputChans; const int totalBuffers = numActiveInputChans + numActiveOutputChans;


callbacks.sampleRateDidChange = &sampleRateChangedCallback;

if (currentASIODev[0] == this)
{
callbacks.bufferSwitch = &bufferSwitchCallback0;
callbacks.asioMessage = &asioMessagesCallback0;
callbacks.bufferSwitchTimeInfo = &bufferSwitchTimeInfoCallback0;
}
else if (currentASIODev[1] == this)
{
callbacks.bufferSwitch = &bufferSwitchCallback1;
callbacks.asioMessage = &asioMessagesCallback1;
callbacks.bufferSwitchTimeInfo = &bufferSwitchTimeInfoCallback1;
}
else if (currentASIODev[2] == this)
{
callbacks.bufferSwitch = &bufferSwitchCallback2;
callbacks.asioMessage = &asioMessagesCallback2;
callbacks.bufferSwitchTimeInfo = &bufferSwitchTimeInfoCallback2;
}
else
{
jassertfalse;
}
setCallbackFunctions();


log ("disposing buffers"); log ("disposing buffers");
err = asioObject->disposeBuffers(); err = asioObject->disposeBuffers();
@@ -257197,7 +257209,7 @@ public:
Array <int> types; Array <int> types;
currentBitDepth = 16; currentBitDepth = 16;


for (i = 0; i < jmin ((int) totalNumInputChans, maxASIOChannels); ++i)
for (i = 0; i < jmin ((int) totalNumInputChans, (int) maxASIOChannels); ++i)
{ {
if (inputChannels[i]) if (inputChannels[i])
{ {
@@ -257224,7 +257236,7 @@ public:
jassert (numActiveInputChans == n); jassert (numActiveInputChans == n);
n = 0; n = 0;


for (i = 0; i < jmin ((int) totalNumOutputChans, maxASIOChannels); ++i)
for (i = 0; i < jmin ((int) totalNumOutputChans, (int) maxASIOChannels); ++i)
{ {
if (outputChannels[i]) if (outputChannels[i])
{ {
@@ -257518,6 +257530,8 @@ private:
AudioIODeviceCallback* volatile currentCallback; AudioIODeviceCallback* volatile currentCallback;
CriticalSection callbackLock; CriticalSection callbackLock;


enum { maxASIOChannels = 160 };

ASIOBufferInfo bufferInfos [maxASIOChannels]; ASIOBufferInfo bufferInfos [maxASIOChannels];
float* inBuffers [maxASIOChannels]; float* inBuffers [maxASIOChannels];
float* outBuffers [maxASIOChannels]; float* outBuffers [maxASIOChannels];
@@ -257749,30 +257763,7 @@ private:
++numChans; ++numChans;
} }


callbacks.sampleRateDidChange = &sampleRateChangedCallback;

if (currentASIODev[0] == this)
{
callbacks.bufferSwitch = &bufferSwitchCallback0;
callbacks.asioMessage = &asioMessagesCallback0;
callbacks.bufferSwitchTimeInfo = &bufferSwitchTimeInfoCallback0;
}
else if (currentASIODev[1] == this)
{
callbacks.bufferSwitch = &bufferSwitchCallback1;
callbacks.asioMessage = &asioMessagesCallback1;
callbacks.bufferSwitchTimeInfo = &bufferSwitchTimeInfoCallback1;
}
else if (currentASIODev[2] == this)
{
callbacks.bufferSwitch = &bufferSwitchCallback2;
callbacks.asioMessage = &asioMessagesCallback2;
callbacks.bufferSwitchTimeInfo = &bufferSwitchTimeInfoCallback2;
}
else
{
jassertfalse;
}
setCallbackFunctions();


log ("creating buffers (dummy): " + String (numChans) + ", " + String ((int) preferredSize)); log ("creating buffers (dummy): " + String (numChans) + ", " + String ((int) preferredSize));


@@ -258028,64 +258019,47 @@ private:
asioObject->outputReady(); asioObject->outputReady();
} }


static ASIOTime* JUCE_ASIOCALLBACK bufferSwitchTimeInfoCallback0 (ASIOTime*, long index, long)
{
if (currentASIODev[0] != nullptr)
currentASIODev[0]->callback (index);

return nullptr;
}

static ASIOTime* JUCE_ASIOCALLBACK bufferSwitchTimeInfoCallback1 (ASIOTime*, long index, long)
template <int deviceIndex>
struct ASIOCallbackFunctions
{ {
if (currentASIODev[1] != nullptr)
currentASIODev[1]->callback (index);

return nullptr;
}

static ASIOTime* JUCE_ASIOCALLBACK bufferSwitchTimeInfoCallback2 (ASIOTime*, long index, long)
{
if (currentASIODev[2] != nullptr)
currentASIODev[2]->callback (index);

return nullptr;
}
static ASIOTime* JUCE_ASIOCALLBACK bufferSwitchTimeInfoCallback (ASIOTime*, long index, long)
{
if (currentASIODev[deviceIndex] != nullptr)
currentASIODev[deviceIndex]->callback (index);


static void JUCE_ASIOCALLBACK bufferSwitchCallback0 (long index, long)
{
if (currentASIODev[0] != nullptr)
currentASIODev[0]->callback (index);
}
return nullptr;
}


static void JUCE_ASIOCALLBACK bufferSwitchCallback1 (long index, long)
{
if (currentASIODev[1] != nullptr)
currentASIODev[1]->callback (index);
}
static void JUCE_ASIOCALLBACK bufferSwitchCallback (long index, long)
{
if (currentASIODev[deviceIndex] != nullptr)
currentASIODev[deviceIndex]->callback (index);
}


static void JUCE_ASIOCALLBACK bufferSwitchCallback2 (long index, long)
{
if (currentASIODev[2] != nullptr)
currentASIODev[2]->callback (index);
}
static long JUCE_ASIOCALLBACK asioMessagesCallback (long selector, long value, void*, double*)
{
return ASIOAudioIODevice::asioMessagesCallback (selector, value, deviceIndex);
}


static long JUCE_ASIOCALLBACK asioMessagesCallback0 (long selector, long value, void*, double*)
{
return asioMessagesCallback (selector, value, 0);
}
static void setCallbacks (ASIOCallbacks& callbacks)
{
callbacks.bufferSwitch = &bufferSwitchCallback;
callbacks.asioMessage = &asioMessagesCallback;
callbacks.bufferSwitchTimeInfo = &bufferSwitchTimeInfoCallback;
}
};


static long JUCE_ASIOCALLBACK asioMessagesCallback1 (long selector, long value, void*, double*)
void setCallbackFunctions()
{ {
return asioMessagesCallback (selector, value, 1);
}
callbacks.sampleRateDidChange = &sampleRateChangedCallback;


static long JUCE_ASIOCALLBACK asioMessagesCallback2 (long selector, long value, void*, double*)
{
return asioMessagesCallback (selector, value, 2);
if (currentASIODev[0] == this) ASIOCallbackFunctions<0>::setCallbacks (callbacks);
else if (currentASIODev[1] == this) ASIOCallbackFunctions<1>::setCallbacks (callbacks);
else if (currentASIODev[2] == this) ASIOCallbackFunctions<2>::setCallbacks (callbacks);
else jassertfalse;
} }


static long JUCE_ASIOCALLBACK asioMessagesCallback (long selector, long value, const int deviceIndex)
static long asioMessagesCallback (long selector, long value, const int deviceIndex)
{ {
switch (selector) switch (selector)
{ {
@@ -258805,7 +258779,7 @@ namespace
class DSoundInternalOutChannel class DSoundInternalOutChannel
{ {
public: public:
DSoundInternalOutChannel (const String& name_, LPGUID guid_, int rate,
DSoundInternalOutChannel (const String& name_, const GUID& guid_, int rate,
int bufferSize, float* left, float* right) int bufferSize, float* left, float* right)
: bitDepth (16), name (name_), guid (guid_), sampleRate (rate), : bitDepth (16), name (name_), guid (guid_), sampleRate (rate),
bufferSizeSamples (bufferSize), leftBuffer (left), rightBuffer (right), bufferSizeSamples (bufferSize), leftBuffer (left), rightBuffer (right),
@@ -258854,7 +258828,7 @@ public:
HRESULT hr = E_NOINTERFACE; HRESULT hr = E_NOINTERFACE;


if (dsDirectSoundCreate != 0) if (dsDirectSoundCreate != 0)
hr = dsDirectSoundCreate (guid, &pDirectSound, 0);
hr = dsDirectSoundCreate (&guid, &pDirectSound, 0);


if (hr == S_OK) if (hr == S_OK)
{ {
@@ -259093,7 +259067,7 @@ public:


private: private:
String name; String name;
LPGUID guid;
GUID guid;
int sampleRate, bufferSizeSamples; int sampleRate, bufferSizeSamples;
float* leftBuffer; float* leftBuffer;
float* rightBuffer; float* rightBuffer;
@@ -259115,7 +259089,7 @@ private:
struct DSoundInternalInChannel struct DSoundInternalInChannel
{ {
public: public:
DSoundInternalInChannel (const String& name_, LPGUID guid_, int rate,
DSoundInternalInChannel (const String& name_, const GUID& guid_, int rate,
int bufferSize, float* left, float* right) int bufferSize, float* left, float* right)
: bitDepth (16), name (name_), guid (guid_), sampleRate (rate), : bitDepth (16), name (name_), guid (guid_), sampleRate (rate),
bufferSizeSamples (bufferSize), leftBuffer (left), rightBuffer (right), bufferSizeSamples (bufferSize), leftBuffer (left), rightBuffer (right),
@@ -259173,7 +259147,7 @@ public:
HRESULT hr = E_NOINTERFACE; HRESULT hr = E_NOINTERFACE;


if (dsDirectSoundCaptureCreate != 0) if (dsDirectSoundCaptureCreate != 0)
hr = dsDirectSoundCaptureCreate (guid, &pDirectSoundCapture, 0);
hr = dsDirectSoundCaptureCreate (&guid, &pDirectSoundCapture, 0);


logError (hr); logError (hr);


@@ -259349,7 +259323,7 @@ public:


private: private:
String name; String name;
LPGUID guid;
GUID guid;
int sampleRate, bufferSizeSamples; int sampleRate, bufferSizeSamples;
float* leftBuffer; float* leftBuffer;
float* rightBuffer; float* rightBuffer;
@@ -259668,23 +259642,16 @@ public:
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (DSoundAudioIODevice); JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (DSoundAudioIODevice);
}; };


class DSoundAudioIODeviceType : public AudioIODeviceType
struct DSoundDeviceList
{ {
public:
DSoundAudioIODeviceType()
: AudioIODeviceType ("DirectSound"),
hasScanned (false)
{
initialiseDSoundFunctions();
}
StringArray outputDeviceNames, inputDeviceNames;
Array<GUID> outputGuids, inputGuids;


void scanForDevices()
void scan()
{ {
hasScanned = true;

outputDeviceNames.clear(); outputDeviceNames.clear();
outputGuids.clear();
inputDeviceNames.clear(); inputDeviceNames.clear();
outputGuids.clear();
inputGuids.clear(); inputGuids.clear();


if (dsDirectSoundEnumerateW != 0) if (dsDirectSoundEnumerateW != 0)
@@ -259694,57 +259661,16 @@ public:
} }
} }


StringArray getDeviceNames (bool wantInputNames) const
{
jassert (hasScanned); // need to call scanForDevices() before doing this

return wantInputNames ? inputDeviceNames
: outputDeviceNames;
}

int getDefaultDeviceIndex (bool /*forInput*/) const
bool operator!= (const DSoundDeviceList& other) const noexcept
{ {
jassert (hasScanned); // need to call scanForDevices() before doing this
return 0;
return outputDeviceNames != other.outputDeviceNames
|| inputDeviceNames != other.inputDeviceNames
|| outputGuids != other.outputGuids
|| inputGuids != other.inputGuids;
} }


int getIndexOfDevice (AudioIODevice* device, bool asInput) const
{
jassert (hasScanned); // need to call scanForDevices() before doing this

DSoundAudioIODevice* const d = dynamic_cast <DSoundAudioIODevice*> (device);
if (d == 0)
return -1;

return asInput ? d->inputDeviceIndex
: d->outputDeviceIndex;
}

bool hasSeparateInputsAndOutputs() const { return true; }

AudioIODevice* createDevice (const String& outputDeviceName,
const String& inputDeviceName)
{
jassert (hasScanned); // need to call scanForDevices() before doing this

const int outputIndex = outputDeviceNames.indexOf (outputDeviceName);
const int inputIndex = inputDeviceNames.indexOf (inputDeviceName);

if (outputIndex >= 0 || inputIndex >= 0)
return new DSoundAudioIODevice (outputDeviceName.isNotEmpty() ? outputDeviceName
: inputDeviceName,
outputIndex, inputIndex);

return nullptr;
}

StringArray outputDeviceNames, inputDeviceNames;
OwnedArray <GUID> outputGuids, inputGuids;

private: private:
bool hasScanned;

BOOL outputEnumProc (LPGUID lpGUID, String desc)
static BOOL enumProc (LPGUID lpGUID, String desc, StringArray& names, Array<GUID>& guids)
{ {
desc = desc.trim(); desc = desc.trim();


@@ -259753,68 +259679,28 @@ private:
const String origDesc (desc); const String origDesc (desc);


int n = 2; int n = 2;
while (outputDeviceNames.contains (desc))
while (names.contains (desc))
desc = origDesc + " (" + String (n++) + ")"; desc = origDesc + " (" + String (n++) + ")";


outputDeviceNames.add (desc);

if (lpGUID != 0)
outputGuids.add (new GUID (*lpGUID));
else
outputGuids.add (nullptr);
names.add (desc);
guids.add (lpGUID != nullptr ? *lpGUID : GUID());
} }


return TRUE; return TRUE;
} }


static BOOL CALLBACK outputEnumProcW (LPGUID lpGUID, LPCWSTR description, LPCWSTR, LPVOID object)
{
return ((DSoundAudioIODeviceType*) object)
->outputEnumProc (lpGUID, String (description));
}
BOOL outputEnumProc (LPGUID guid, LPCWSTR desc) { return enumProc (guid, desc, outputDeviceNames, outputGuids); }
BOOL inputEnumProc (LPGUID guid, LPCWSTR desc) { return enumProc (guid, desc, inputDeviceNames, inputGuids); }


static BOOL CALLBACK outputEnumProcA (LPGUID lpGUID, LPCTSTR description, LPCTSTR, LPVOID object)
static BOOL CALLBACK outputEnumProcW (LPGUID lpGUID, LPCWSTR description, LPCWSTR, LPVOID object)
{ {
return ((DSoundAudioIODeviceType*) object)
->outputEnumProc (lpGUID, String (description));
}

BOOL CALLBACK inputEnumProc (LPGUID lpGUID, String desc)
{
desc = desc.trim();

if (desc.isNotEmpty())
{
const String origDesc (desc);

int n = 2;
while (inputDeviceNames.contains (desc))
desc = origDesc + " (" + String (n++) + ")";

inputDeviceNames.add (desc);

if (lpGUID != 0)
inputGuids.add (new GUID (*lpGUID));
else
inputGuids.add (nullptr);
}

return TRUE;
return static_cast<DSoundDeviceList*> (object)->outputEnumProc (lpGUID, description);
} }


static BOOL CALLBACK inputEnumProcW (LPGUID lpGUID, LPCWSTR description, LPCWSTR, LPVOID object) static BOOL CALLBACK inputEnumProcW (LPGUID lpGUID, LPCWSTR description, LPCWSTR, LPVOID object)
{ {
return ((DSoundAudioIODeviceType*) object)
->inputEnumProc (lpGUID, String (description));
return static_cast<DSoundDeviceList*> (object)->inputEnumProc (lpGUID, description);
} }

static BOOL CALLBACK inputEnumProcA (LPGUID lpGUID, LPCTSTR description, LPCTSTR, LPVOID object)
{
return ((DSoundAudioIODeviceType*) object)
->inputEnumProc (lpGUID, String (description));
}

JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (DSoundAudioIODeviceType);
}; };


String DSoundAudioIODevice::openDevice (const BigInteger& inputChannels, String DSoundAudioIODevice::openDevice (const BigInteger& inputChannels,
@@ -259831,8 +259717,8 @@ String DSoundAudioIODevice::openDevice (const BigInteger& inputChannels,


bufferSizeSamples = bufferSizeSamples_ & ~7; bufferSizeSamples = bufferSizeSamples_ & ~7;


DSoundAudioIODeviceType dlh;
dlh.scanForDevices();
DSoundDeviceList dlh;
dlh.scan();


enabledInputs = inputChannels; enabledInputs = inputChannels;
enabledInputs.setRange (inChannels.size(), enabledInputs.setRange (inChannels.size(),
@@ -259945,6 +259831,88 @@ String DSoundAudioIODevice::openDevice (const BigInteger& inputChannels,
return error; return error;
} }


class DSoundAudioIODeviceType : public AudioIODeviceType,
private DeviceChangeDetector
{
public:
DSoundAudioIODeviceType()
: AudioIODeviceType ("DirectSound"),
DeviceChangeDetector (L"DirectSound"),
hasScanned (false)
{
initialiseDSoundFunctions();
}

void scanForDevices()
{
hasScanned = true;
deviceList.scan();
}

StringArray getDeviceNames (bool wantInputNames) const
{
jassert (hasScanned); // need to call scanForDevices() before doing this

return wantInputNames ? deviceList.inputDeviceNames
: deviceList.outputDeviceNames;
}

int getDefaultDeviceIndex (bool /*forInput*/) const
{
jassert (hasScanned); // need to call scanForDevices() before doing this
return 0;
}

int getIndexOfDevice (AudioIODevice* device, bool asInput) const
{
jassert (hasScanned); // need to call scanForDevices() before doing this

DSoundAudioIODevice* const d = dynamic_cast <DSoundAudioIODevice*> (device);
if (d == 0)
return -1;

return asInput ? d->inputDeviceIndex
: d->outputDeviceIndex;
}

bool hasSeparateInputsAndOutputs() const { return true; }

AudioIODevice* createDevice (const String& outputDeviceName,
const String& inputDeviceName)
{
jassert (hasScanned); // need to call scanForDevices() before doing this

const int outputIndex = deviceList.outputDeviceNames.indexOf (outputDeviceName);
const int inputIndex = deviceList.inputDeviceNames.indexOf (inputDeviceName);

if (outputIndex >= 0 || inputIndex >= 0)
return new DSoundAudioIODevice (outputDeviceName.isNotEmpty() ? outputDeviceName
: inputDeviceName,
outputIndex, inputIndex);

return nullptr;
}

private:

DSoundDeviceList deviceList;
bool hasScanned;

void systemDeviceChanged()
{
DSoundDeviceList newList;
newList.scan();

if (newList != deviceList)
{
deviceList = newList;
callDeviceChangeListeners();
}
}

JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (DSoundAudioIODeviceType);
};

AudioIODeviceType* AudioIODeviceType::createAudioIODeviceType_DirectSound() AudioIODeviceType* AudioIODeviceType::createAudioIODeviceType_DirectSound()
{ {
return new DSoundAudioIODeviceType(); return new DSoundAudioIODeviceType();
@@ -260879,15 +260847,15 @@ private:
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (WASAPIAudioIODevice); JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (WASAPIAudioIODevice);
}; };


class WASAPIAudioIODeviceType : public AudioIODeviceType
class WASAPIAudioIODeviceType : public AudioIODeviceType,
private DeviceChangeDetector
{ {
public: public:
WASAPIAudioIODeviceType() WASAPIAudioIODeviceType()
: AudioIODeviceType ("Windows Audio"), : AudioIODeviceType ("Windows Audio"),
deviceChangeCatcher (_T("Windows Audio"), (WNDPROC) deviceChangeEventCallback),
DeviceChangeDetector (L"Windows Audio"),
hasScanned (false) hasScanned (false)
{ {
SetWindowLongPtr (deviceChangeCatcher.getHWND(), GWLP_USERDATA, (LONG_PTR) this);
} }


void scanForDevices() void scanForDevices()
@@ -260957,7 +260925,6 @@ public:
StringArray inputDeviceNames, inputDeviceIds; StringArray inputDeviceNames, inputDeviceIds;


private: private:
HiddenMessageWindow deviceChangeCatcher;
bool hasScanned; bool hasScanned;


static String getDefaultEndpoint (IMMDeviceEnumerator* const enumerator, const bool forCapture) static String getDefaultEndpoint (IMMDeviceEnumerator* const enumerator, const bool forCapture)
@@ -261045,21 +261012,7 @@ private:
outputDeviceNames.appendNumbersToDuplicates (false, false); outputDeviceNames.appendNumbersToDuplicates (false, false);
} }


static LRESULT CALLBACK deviceChangeEventCallback (HWND h, const UINT message,
const WPARAM wParam, const LPARAM lParam)
{
if (message == WM_DEVICECHANGE
&& (wParam == 0x8000 /*DBT_DEVICEARRIVAL*/
|| wParam == 0x8004 /*DBT_DEVICEREMOVECOMPLETE*/
|| wParam == 0x0007 /*DBT_DEVNODES_CHANGED*/))
{
((WASAPIAudioIODeviceType*) GetWindowLongPtr (h, GWLP_USERDATA))->handleDeviceChange();
}

return DefWindowProc (h, message, wParam, lParam);
}

void handleDeviceChange()
void systemDeviceChanged()
{ {
StringArray newOutNames, newInNames, newOutIds, newInIds; StringArray newOutNames, newInNames, newOutIds, newInIds;
scan (newOutNames, newInNames, newOutIds, newInIds); scan (newOutNames, newInNames, newOutIds, newInIds);


+ 3
- 0
juce_amalgamated.h View File

@@ -57521,6 +57521,9 @@ public:
*/ */
void setMinimised (bool shouldMinimise); void setMinimised (bool shouldMinimise);


/** Adds the window to the desktop using the default flags. */
void addToDesktop();

/** Returns a string which encodes the window's current size and position. /** Returns a string which encodes the window's current size and position.


This string will encapsulate the window's size, position, and whether it's This string will encapsulate the window's size, position, and whether it's


+ 6
- 1
src/gui/components/windows/juce_ResizableWindow.cpp View File

@@ -90,7 +90,7 @@ void ResizableWindow::initialise (const bool shouldAddToDesktop)
lastNonFullScreenPos.setBounds (50, 50, 256, 256); lastNonFullScreenPos.setBounds (50, 50, 256, 256);
if (shouldAddToDesktop) if (shouldAddToDesktop)
Component::addToDesktop (ResizableWindow::getDesktopWindowStyleFlags());
addToDesktop();
} }
int ResizableWindow::getDesktopWindowStyleFlags() const int ResizableWindow::getDesktopWindowStyleFlags() const
@@ -103,6 +103,11 @@ int ResizableWindow::getDesktopWindowStyleFlags() const
return styleFlags; return styleFlags;
} }
void ResizableWindow::addToDesktop()
{
Component::addToDesktop (ResizableWindow::getDesktopWindowStyleFlags());
}
//============================================================================== //==============================================================================
void ResizableWindow::clearContentComponent() void ResizableWindow::clearContentComponent()
{ {


+ 3
- 0
src/gui/components/windows/juce_ResizableWindow.h View File

@@ -200,6 +200,9 @@ public:
*/ */
void setMinimised (bool shouldMinimise); void setMinimised (bool shouldMinimise);
/** Adds the window to the desktop using the default flags. */
void addToDesktop();
//============================================================================== //==============================================================================
/** Returns a string which encodes the window's current size and position. /** Returns a string which encodes the window's current size and position.


+ 37
- 101
src/native/windows/juce_win32_ASIO.cpp View File

@@ -75,8 +75,6 @@ namespace ASIODebugging
class ASIOAudioIODevice; class ASIOAudioIODevice;
static ASIOAudioIODevice* volatile currentASIODev[3] = { 0 }; static ASIOAudioIODevice* volatile currentASIODev[3] = { 0 };
static const int maxASIOChannels = 160;
//============================================================================== //==============================================================================
class JUCE_API ASIOAudioIODevice : public AudioIODevice, class JUCE_API ASIOAudioIODevice : public AudioIODevice,
@@ -373,30 +371,7 @@ public:
const int totalBuffers = numActiveInputChans + numActiveOutputChans; const int totalBuffers = numActiveInputChans + numActiveOutputChans;
callbacks.sampleRateDidChange = &sampleRateChangedCallback;
if (currentASIODev[0] == this)
{
callbacks.bufferSwitch = &bufferSwitchCallback0;
callbacks.asioMessage = &asioMessagesCallback0;
callbacks.bufferSwitchTimeInfo = &bufferSwitchTimeInfoCallback0;
}
else if (currentASIODev[1] == this)
{
callbacks.bufferSwitch = &bufferSwitchCallback1;
callbacks.asioMessage = &asioMessagesCallback1;
callbacks.bufferSwitchTimeInfo = &bufferSwitchTimeInfoCallback1;
}
else if (currentASIODev[2] == this)
{
callbacks.bufferSwitch = &bufferSwitchCallback2;
callbacks.asioMessage = &asioMessagesCallback2;
callbacks.bufferSwitchTimeInfo = &bufferSwitchTimeInfoCallback2;
}
else
{
jassertfalse;
}
setCallbackFunctions();
log ("disposing buffers"); log ("disposing buffers");
err = asioObject->disposeBuffers(); err = asioObject->disposeBuffers();
@@ -429,7 +404,7 @@ public:
Array <int> types; Array <int> types;
currentBitDepth = 16; currentBitDepth = 16;
for (i = 0; i < jmin ((int) totalNumInputChans, maxASIOChannels); ++i)
for (i = 0; i < jmin ((int) totalNumInputChans, (int) maxASIOChannels); ++i)
{ {
if (inputChannels[i]) if (inputChannels[i])
{ {
@@ -456,7 +431,7 @@ public:
jassert (numActiveInputChans == n); jassert (numActiveInputChans == n);
n = 0; n = 0;
for (i = 0; i < jmin ((int) totalNumOutputChans, maxASIOChannels); ++i)
for (i = 0; i < jmin ((int) totalNumOutputChans, (int) maxASIOChannels); ++i)
{ {
if (outputChannels[i]) if (outputChannels[i])
{ {
@@ -750,6 +725,8 @@ private:
AudioIODeviceCallback* volatile currentCallback; AudioIODeviceCallback* volatile currentCallback;
CriticalSection callbackLock; CriticalSection callbackLock;
enum { maxASIOChannels = 160 };
ASIOBufferInfo bufferInfos [maxASIOChannels]; ASIOBufferInfo bufferInfos [maxASIOChannels];
float* inBuffers [maxASIOChannels]; float* inBuffers [maxASIOChannels];
float* outBuffers [maxASIOChannels]; float* outBuffers [maxASIOChannels];
@@ -982,31 +959,7 @@ private:
++numChans; ++numChans;
} }
callbacks.sampleRateDidChange = &sampleRateChangedCallback;
if (currentASIODev[0] == this)
{
callbacks.bufferSwitch = &bufferSwitchCallback0;
callbacks.asioMessage = &asioMessagesCallback0;
callbacks.bufferSwitchTimeInfo = &bufferSwitchTimeInfoCallback0;
}
else if (currentASIODev[1] == this)
{
callbacks.bufferSwitch = &bufferSwitchCallback1;
callbacks.asioMessage = &asioMessagesCallback1;
callbacks.bufferSwitchTimeInfo = &bufferSwitchTimeInfoCallback1;
}
else if (currentASIODev[2] == this)
{
callbacks.bufferSwitch = &bufferSwitchCallback2;
callbacks.asioMessage = &asioMessagesCallback2;
callbacks.bufferSwitchTimeInfo = &bufferSwitchTimeInfoCallback2;
}
else
{
jassertfalse;
}
setCallbackFunctions();
log ("creating buffers (dummy): " + String (numChans) + ", " + String ((int) preferredSize)); log ("creating buffers (dummy): " + String (numChans) + ", " + String ((int) preferredSize));
@@ -1264,65 +1217,48 @@ private:
} }
//============================================================================== //==============================================================================
static ASIOTime* JUCE_ASIOCALLBACK bufferSwitchTimeInfoCallback0 (ASIOTime*, long index, long)
{
if (currentASIODev[0] != nullptr)
currentASIODev[0]->callback (index);
return nullptr;
}
static ASIOTime* JUCE_ASIOCALLBACK bufferSwitchTimeInfoCallback1 (ASIOTime*, long index, long)
template <int deviceIndex>
struct ASIOCallbackFunctions
{ {
if (currentASIODev[1] != nullptr)
currentASIODev[1]->callback (index);
return nullptr;
}
static ASIOTime* JUCE_ASIOCALLBACK bufferSwitchTimeInfoCallback2 (ASIOTime*, long index, long)
{
if (currentASIODev[2] != nullptr)
currentASIODev[2]->callback (index);
return nullptr;
}
static ASIOTime* JUCE_ASIOCALLBACK bufferSwitchTimeInfoCallback (ASIOTime*, long index, long)
{
if (currentASIODev[deviceIndex] != nullptr)
currentASIODev[deviceIndex]->callback (index);
static void JUCE_ASIOCALLBACK bufferSwitchCallback0 (long index, long)
{
if (currentASIODev[0] != nullptr)
currentASIODev[0]->callback (index);
}
return nullptr;
}
static void JUCE_ASIOCALLBACK bufferSwitchCallback1 (long index, long)
{
if (currentASIODev[1] != nullptr)
currentASIODev[1]->callback (index);
}
static void JUCE_ASIOCALLBACK bufferSwitchCallback (long index, long)
{
if (currentASIODev[deviceIndex] != nullptr)
currentASIODev[deviceIndex]->callback (index);
}
static void JUCE_ASIOCALLBACK bufferSwitchCallback2 (long index, long)
{
if (currentASIODev[2] != nullptr)
currentASIODev[2]->callback (index);
}
static long JUCE_ASIOCALLBACK asioMessagesCallback (long selector, long value, void*, double*)
{
return ASIOAudioIODevice::asioMessagesCallback (selector, value, deviceIndex);
}
static long JUCE_ASIOCALLBACK asioMessagesCallback0 (long selector, long value, void*, double*)
{
return asioMessagesCallback (selector, value, 0);
}
static void setCallbacks (ASIOCallbacks& callbacks)
{
callbacks.bufferSwitch = &bufferSwitchCallback;
callbacks.asioMessage = &asioMessagesCallback;
callbacks.bufferSwitchTimeInfo = &bufferSwitchTimeInfoCallback;
}
};
static long JUCE_ASIOCALLBACK asioMessagesCallback1 (long selector, long value, void*, double*)
void setCallbackFunctions()
{ {
return asioMessagesCallback (selector, value, 1);
}
callbacks.sampleRateDidChange = &sampleRateChangedCallback;
static long JUCE_ASIOCALLBACK asioMessagesCallback2 (long selector, long value, void*, double*)
{
return asioMessagesCallback (selector, value, 2);
if (currentASIODev[0] == this) ASIOCallbackFunctions<0>::setCallbacks (callbacks);
else if (currentASIODev[1] == this) ASIOCallbackFunctions<1>::setCallbacks (callbacks);
else if (currentASIODev[2] == this) ASIOCallbackFunctions<2>::setCallbacks (callbacks);
else jassertfalse;
} }
//============================================================================== //==============================================================================
static long JUCE_ASIOCALLBACK asioMessagesCallback (long selector, long value, const int deviceIndex)
static long asioMessagesCallback (long selector, long value, const int deviceIndex)
{ {
switch (selector) switch (selector)
{ {


+ 112
- 121
src/native/windows/juce_win32_DirectSound.cpp View File

@@ -228,7 +228,7 @@ namespace
class DSoundInternalOutChannel class DSoundInternalOutChannel
{ {
public: public:
DSoundInternalOutChannel (const String& name_, LPGUID guid_, int rate,
DSoundInternalOutChannel (const String& name_, const GUID& guid_, int rate,
int bufferSize, float* left, float* right) int bufferSize, float* left, float* right)
: bitDepth (16), name (name_), guid (guid_), sampleRate (rate), : bitDepth (16), name (name_), guid (guid_), sampleRate (rate),
bufferSizeSamples (bufferSize), leftBuffer (left), rightBuffer (right), bufferSizeSamples (bufferSize), leftBuffer (left), rightBuffer (right),
@@ -277,7 +277,7 @@ public:
HRESULT hr = E_NOINTERFACE; HRESULT hr = E_NOINTERFACE;
if (dsDirectSoundCreate != 0) if (dsDirectSoundCreate != 0)
hr = dsDirectSoundCreate (guid, &pDirectSound, 0);
hr = dsDirectSoundCreate (&guid, &pDirectSound, 0);
if (hr == S_OK) if (hr == S_OK)
{ {
@@ -516,7 +516,7 @@ public:
private: private:
String name; String name;
LPGUID guid;
GUID guid;
int sampleRate, bufferSizeSamples; int sampleRate, bufferSizeSamples;
float* leftBuffer; float* leftBuffer;
float* rightBuffer; float* rightBuffer;
@@ -539,7 +539,7 @@ private:
struct DSoundInternalInChannel struct DSoundInternalInChannel
{ {
public: public:
DSoundInternalInChannel (const String& name_, LPGUID guid_, int rate,
DSoundInternalInChannel (const String& name_, const GUID& guid_, int rate,
int bufferSize, float* left, float* right) int bufferSize, float* left, float* right)
: bitDepth (16), name (name_), guid (guid_), sampleRate (rate), : bitDepth (16), name (name_), guid (guid_), sampleRate (rate),
bufferSizeSamples (bufferSize), leftBuffer (left), rightBuffer (right), bufferSizeSamples (bufferSize), leftBuffer (left), rightBuffer (right),
@@ -597,7 +597,7 @@ public:
HRESULT hr = E_NOINTERFACE; HRESULT hr = E_NOINTERFACE;
if (dsDirectSoundCaptureCreate != 0) if (dsDirectSoundCaptureCreate != 0)
hr = dsDirectSoundCaptureCreate (guid, &pDirectSoundCapture, 0);
hr = dsDirectSoundCaptureCreate (&guid, &pDirectSoundCapture, 0);
logError (hr); logError (hr);
@@ -773,7 +773,7 @@ public:
private: private:
String name; String name;
LPGUID guid;
GUID guid;
int sampleRate, bufferSizeSamples; int sampleRate, bufferSizeSamples;
float* leftBuffer; float* leftBuffer;
float* rightBuffer; float* rightBuffer;
@@ -1094,26 +1094,17 @@ public:
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (DSoundAudioIODevice); JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (DSoundAudioIODevice);
}; };
//============================================================================== //==============================================================================
class DSoundAudioIODeviceType : public AudioIODeviceType
struct DSoundDeviceList
{ {
public:
DSoundAudioIODeviceType()
: AudioIODeviceType ("DirectSound"),
hasScanned (false)
{
initialiseDSoundFunctions();
}
StringArray outputDeviceNames, inputDeviceNames;
Array<GUID> outputGuids, inputGuids;
//==============================================================================
void scanForDevices()
void scan()
{ {
hasScanned = true;
outputDeviceNames.clear(); outputDeviceNames.clear();
outputGuids.clear();
inputDeviceNames.clear(); inputDeviceNames.clear();
outputGuids.clear();
inputGuids.clear(); inputGuids.clear();
if (dsDirectSoundEnumerateW != 0) if (dsDirectSoundEnumerateW != 0)
@@ -1123,59 +1114,16 @@ public:
} }
} }
StringArray getDeviceNames (bool wantInputNames) const
{
jassert (hasScanned); // need to call scanForDevices() before doing this
return wantInputNames ? inputDeviceNames
: outputDeviceNames;
}
int getDefaultDeviceIndex (bool /*forInput*/) const
{
jassert (hasScanned); // need to call scanForDevices() before doing this
return 0;
}
int getIndexOfDevice (AudioIODevice* device, bool asInput) const
bool operator!= (const DSoundDeviceList& other) const noexcept
{ {
jassert (hasScanned); // need to call scanForDevices() before doing this
DSoundAudioIODevice* const d = dynamic_cast <DSoundAudioIODevice*> (device);
if (d == 0)
return -1;
return asInput ? d->inputDeviceIndex
: d->outputDeviceIndex;
return outputDeviceNames != other.outputDeviceNames
|| inputDeviceNames != other.inputDeviceNames
|| outputGuids != other.outputGuids
|| inputGuids != other.inputGuids;
} }
bool hasSeparateInputsAndOutputs() const { return true; }
AudioIODevice* createDevice (const String& outputDeviceName,
const String& inputDeviceName)
{
jassert (hasScanned); // need to call scanForDevices() before doing this
const int outputIndex = outputDeviceNames.indexOf (outputDeviceName);
const int inputIndex = inputDeviceNames.indexOf (inputDeviceName);
if (outputIndex >= 0 || inputIndex >= 0)
return new DSoundAudioIODevice (outputDeviceName.isNotEmpty() ? outputDeviceName
: inputDeviceName,
outputIndex, inputIndex);
return nullptr;
}
//==============================================================================
StringArray outputDeviceNames, inputDeviceNames;
OwnedArray <GUID> outputGuids, inputGuids;
private: private:
bool hasScanned;
//==============================================================================
BOOL outputEnumProc (LPGUID lpGUID, String desc)
static BOOL enumProc (LPGUID lpGUID, String desc, StringArray& names, Array<GUID>& guids)
{ {
desc = desc.trim(); desc = desc.trim();
@@ -1184,70 +1132,28 @@ private:
const String origDesc (desc); const String origDesc (desc);
int n = 2; int n = 2;
while (outputDeviceNames.contains (desc))
while (names.contains (desc))
desc = origDesc + " (" + String (n++) + ")"; desc = origDesc + " (" + String (n++) + ")";
outputDeviceNames.add (desc);
if (lpGUID != 0)
outputGuids.add (new GUID (*lpGUID));
else
outputGuids.add (nullptr);
names.add (desc);
guids.add (lpGUID != nullptr ? *lpGUID : GUID());
} }
return TRUE; return TRUE;
} }
static BOOL CALLBACK outputEnumProcW (LPGUID lpGUID, LPCWSTR description, LPCWSTR, LPVOID object)
{
return ((DSoundAudioIODeviceType*) object)
->outputEnumProc (lpGUID, String (description));
}
static BOOL CALLBACK outputEnumProcA (LPGUID lpGUID, LPCTSTR description, LPCTSTR, LPVOID object)
{
return ((DSoundAudioIODeviceType*) object)
->outputEnumProc (lpGUID, String (description));
}
BOOL outputEnumProc (LPGUID guid, LPCWSTR desc) { return enumProc (guid, desc, outputDeviceNames, outputGuids); }
BOOL inputEnumProc (LPGUID guid, LPCWSTR desc) { return enumProc (guid, desc, inputDeviceNames, inputGuids); }
//==============================================================================
BOOL CALLBACK inputEnumProc (LPGUID lpGUID, String desc)
static BOOL CALLBACK outputEnumProcW (LPGUID lpGUID, LPCWSTR description, LPCWSTR, LPVOID object)
{ {
desc = desc.trim();
if (desc.isNotEmpty())
{
const String origDesc (desc);
int n = 2;
while (inputDeviceNames.contains (desc))
desc = origDesc + " (" + String (n++) + ")";
inputDeviceNames.add (desc);
if (lpGUID != 0)
inputGuids.add (new GUID (*lpGUID));
else
inputGuids.add (nullptr);
}
return TRUE;
return static_cast<DSoundDeviceList*> (object)->outputEnumProc (lpGUID, description);
} }
static BOOL CALLBACK inputEnumProcW (LPGUID lpGUID, LPCWSTR description, LPCWSTR, LPVOID object) static BOOL CALLBACK inputEnumProcW (LPGUID lpGUID, LPCWSTR description, LPCWSTR, LPVOID object)
{ {
return ((DSoundAudioIODeviceType*) object)
->inputEnumProc (lpGUID, String (description));
}
static BOOL CALLBACK inputEnumProcA (LPGUID lpGUID, LPCTSTR description, LPCTSTR, LPVOID object)
{
return ((DSoundAudioIODeviceType*) object)
->inputEnumProc (lpGUID, String (description));
return static_cast<DSoundDeviceList*> (object)->inputEnumProc (lpGUID, description);
} }
//==============================================================================
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (DSoundAudioIODeviceType);
}; };
//============================================================================== //==============================================================================
@@ -1265,8 +1171,8 @@ String DSoundAudioIODevice::openDevice (const BigInteger& inputChannels,
bufferSizeSamples = bufferSizeSamples_ & ~7; bufferSizeSamples = bufferSizeSamples_ & ~7;
DSoundAudioIODeviceType dlh;
dlh.scanForDevices();
DSoundDeviceList dlh;
dlh.scan();
enabledInputs = inputChannels; enabledInputs = inputChannels;
enabledInputs.setRange (inChannels.size(), enabledInputs.setRange (inChannels.size(),
@@ -1379,6 +1285,91 @@ String DSoundAudioIODevice::openDevice (const BigInteger& inputChannels,
return error; return error;
} }
//==============================================================================
class DSoundAudioIODeviceType : public AudioIODeviceType,
private DeviceChangeDetector
{
public:
DSoundAudioIODeviceType()
: AudioIODeviceType ("DirectSound"),
DeviceChangeDetector (L"DirectSound"),
hasScanned (false)
{
initialiseDSoundFunctions();
}
//==============================================================================
void scanForDevices()
{
hasScanned = true;
deviceList.scan();
}
StringArray getDeviceNames (bool wantInputNames) const
{
jassert (hasScanned); // need to call scanForDevices() before doing this
return wantInputNames ? deviceList.inputDeviceNames
: deviceList.outputDeviceNames;
}
int getDefaultDeviceIndex (bool /*forInput*/) const
{
jassert (hasScanned); // need to call scanForDevices() before doing this
return 0;
}
int getIndexOfDevice (AudioIODevice* device, bool asInput) const
{
jassert (hasScanned); // need to call scanForDevices() before doing this
DSoundAudioIODevice* const d = dynamic_cast <DSoundAudioIODevice*> (device);
if (d == 0)
return -1;
return asInput ? d->inputDeviceIndex
: d->outputDeviceIndex;
}
bool hasSeparateInputsAndOutputs() const { return true; }
AudioIODevice* createDevice (const String& outputDeviceName,
const String& inputDeviceName)
{
jassert (hasScanned); // need to call scanForDevices() before doing this
const int outputIndex = deviceList.outputDeviceNames.indexOf (outputDeviceName);
const int inputIndex = deviceList.inputDeviceNames.indexOf (inputDeviceName);
if (outputIndex >= 0 || inputIndex >= 0)
return new DSoundAudioIODevice (outputDeviceName.isNotEmpty() ? outputDeviceName
: inputDeviceName,
outputIndex, inputIndex);
return nullptr;
}
private:
//==============================================================================
DSoundDeviceList deviceList;
bool hasScanned;
void systemDeviceChanged()
{
DSoundDeviceList newList;
newList.scan();
if (newList != deviceList)
{
deviceList = newList;
callDeviceChangeListeners();
}
}
//==============================================================================
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (DSoundAudioIODeviceType);
};
//============================================================================== //==============================================================================
AudioIODeviceType* AudioIODeviceType::createAudioIODeviceType_DirectSound() AudioIODeviceType* AudioIODeviceType::createAudioIODeviceType_DirectSound()
{ {


+ 33
- 0
src/native/windows/juce_win32_Messaging.cpp View File

@@ -344,4 +344,37 @@ void MessageManager::doPlatformSpecificShutdown()
OleUninitialize(); OleUninitialize();
} }
//==============================================================================
class DeviceChangeDetector // (Used by various audio classes)
{
public:
DeviceChangeDetector (const wchar_t* const name)
: messageWindow (name, (WNDPROC) deviceChangeEventCallback)
{
SetWindowLongPtr (messageWindow.getHWND(), GWLP_USERDATA, (LONG_PTR) this);
}
virtual ~DeviceChangeDetector() {}
protected:
virtual void systemDeviceChanged() = 0;
private:
HiddenMessageWindow messageWindow;
static LRESULT CALLBACK deviceChangeEventCallback (HWND h, const UINT message,
const WPARAM wParam, const LPARAM lParam)
{
if (message == WM_DEVICECHANGE
&& (wParam == 0x8000 /*DBT_DEVICEARRIVAL*/
|| wParam == 0x8004 /*DBT_DEVICEREMOVECOMPLETE*/
|| wParam == 0x0007 /*DBT_DEVNODES_CHANGED*/))
{
((DeviceChangeDetector*) GetWindowLongPtr (h, GWLP_USERDATA))->systemDeviceChanged();
}
return DefWindowProc (h, message, wParam, lParam);
}
};
#endif #endif

+ 4
- 19
src/native/windows/juce_win32_WASAPI.cpp View File

@@ -958,15 +958,15 @@ private:
//============================================================================== //==============================================================================
class WASAPIAudioIODeviceType : public AudioIODeviceType
class WASAPIAudioIODeviceType : public AudioIODeviceType,
private DeviceChangeDetector
{ {
public: public:
WASAPIAudioIODeviceType() WASAPIAudioIODeviceType()
: AudioIODeviceType ("Windows Audio"), : AudioIODeviceType ("Windows Audio"),
deviceChangeCatcher (_T("Windows Audio"), (WNDPROC) deviceChangeEventCallback),
DeviceChangeDetector (L"Windows Audio"),
hasScanned (false) hasScanned (false)
{ {
SetWindowLongPtr (deviceChangeCatcher.getHWND(), GWLP_USERDATA, (LONG_PTR) this);
} }
//============================================================================== //==============================================================================
@@ -1038,7 +1038,6 @@ public:
StringArray inputDeviceNames, inputDeviceIds; StringArray inputDeviceNames, inputDeviceIds;
private: private:
HiddenMessageWindow deviceChangeCatcher;
bool hasScanned; bool hasScanned;
//============================================================================== //==============================================================================
@@ -1129,21 +1128,7 @@ private:
} }
//============================================================================== //==============================================================================
static LRESULT CALLBACK deviceChangeEventCallback (HWND h, const UINT message,
const WPARAM wParam, const LPARAM lParam)
{
if (message == WM_DEVICECHANGE
&& (wParam == 0x8000 /*DBT_DEVICEARRIVAL*/
|| wParam == 0x8004 /*DBT_DEVICEREMOVECOMPLETE*/
|| wParam == 0x0007 /*DBT_DEVNODES_CHANGED*/))
{
((WASAPIAudioIODeviceType*) GetWindowLongPtr (h, GWLP_USERDATA))->handleDeviceChange();
}
return DefWindowProc (h, message, wParam, lParam);
}
void handleDeviceChange()
void systemDeviceChanged()
{ {
StringArray newOutNames, newInNames, newOutIds, newInIds; StringArray newOutNames, newInNames, newOutIds, newInIds;
scan (newOutNames, newInNames, newOutIds, newInIds); scan (newOutNames, newInNames, newOutIds, newInIds);


Loading…
Cancel
Save