mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-01-10 23:44:24 +00:00
Added device detection for DirectSound. New method addToDesktop() for ResizableWindow.
This commit is contained in:
parent
fb58d0c380
commit
dbe5768527
9 changed files with 404 additions and 489 deletions
|
|
@ -37,15 +37,16 @@ ApplicationCommandManager* commandManager = nullptr;
|
|||
MainWindow::MainWindow()
|
||||
: DocumentWindow (JUCEApplication::getInstance()->getApplicationName(),
|
||||
Colour::greyLevel (0.6f),
|
||||
DocumentWindow::allButtons)
|
||||
DocumentWindow::allButtons,
|
||||
false)
|
||||
{
|
||||
setUsingNativeTitleBar (true);
|
||||
setContentOwned (new ProjectContentComponent(), false);
|
||||
|
||||
#if ! JUCE_MAC
|
||||
#if ! JUCE_MAC
|
||||
JucerApplication* app = static_cast<JucerApplication*> (JUCEApplication::getInstance());
|
||||
setMenuBar (app->menuModel);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
setResizable (true, false);
|
||||
|
||||
|
|
@ -77,6 +78,11 @@ MainWindow::MainWindow()
|
|||
|
||||
//getPeer()->setCurrentRenderingEngine (0);
|
||||
getLookAndFeel().setColour (ColourSelector::backgroundColourId, Colours::transparentBlack);
|
||||
|
||||
setVisible (true);
|
||||
addToDesktop();
|
||||
|
||||
getContentComponent()->grabKeyboardFocus();
|
||||
}
|
||||
|
||||
MainWindow::~MainWindow()
|
||||
|
|
|
|||
|
|
@ -80492,7 +80492,7 @@ void ResizableWindow::initialise (const bool shouldAddToDesktop)
|
|||
lastNonFullScreenPos.setBounds (50, 50, 256, 256);
|
||||
|
||||
if (shouldAddToDesktop)
|
||||
Component::addToDesktop (ResizableWindow::getDesktopWindowStyleFlags());
|
||||
addToDesktop();
|
||||
}
|
||||
|
||||
int ResizableWindow::getDesktopWindowStyleFlags() const
|
||||
|
|
@ -80505,6 +80505,11 @@ int ResizableWindow::getDesktopWindowStyleFlags() const
|
|||
return styleFlags;
|
||||
}
|
||||
|
||||
void ResizableWindow::addToDesktop()
|
||||
{
|
||||
Component::addToDesktop (ResizableWindow::getDesktopWindowStyleFlags());
|
||||
}
|
||||
|
||||
void ResizableWindow::clearContentComponent()
|
||||
{
|
||||
if (ownsContentComponent)
|
||||
|
|
@ -247265,6 +247270,38 @@ void MessageManager::doPlatformSpecificShutdown()
|
|||
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
|
||||
|
||||
/*** End of inlined file: juce_win32_Messaging.cpp ***/
|
||||
|
|
@ -256845,8 +256882,6 @@ namespace ASIODebugging
|
|||
class ASIOAudioIODevice;
|
||||
static ASIOAudioIODevice* volatile currentASIODev[3] = { 0 };
|
||||
|
||||
static const int maxASIOChannels = 160;
|
||||
|
||||
class JUCE_API ASIOAudioIODevice : public AudioIODevice,
|
||||
private Timer
|
||||
{
|
||||
|
|
@ -257141,30 +257176,7 @@ public:
|
|||
|
||||
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");
|
||||
err = asioObject->disposeBuffers();
|
||||
|
|
@ -257197,7 +257209,7 @@ public:
|
|||
Array <int> types;
|
||||
currentBitDepth = 16;
|
||||
|
||||
for (i = 0; i < jmin ((int) totalNumInputChans, maxASIOChannels); ++i)
|
||||
for (i = 0; i < jmin ((int) totalNumInputChans, (int) maxASIOChannels); ++i)
|
||||
{
|
||||
if (inputChannels[i])
|
||||
{
|
||||
|
|
@ -257224,7 +257236,7 @@ public:
|
|||
jassert (numActiveInputChans == n);
|
||||
n = 0;
|
||||
|
||||
for (i = 0; i < jmin ((int) totalNumOutputChans, maxASIOChannels); ++i)
|
||||
for (i = 0; i < jmin ((int) totalNumOutputChans, (int) maxASIOChannels); ++i)
|
||||
{
|
||||
if (outputChannels[i])
|
||||
{
|
||||
|
|
@ -257518,6 +257530,8 @@ private:
|
|||
AudioIODeviceCallback* volatile currentCallback;
|
||||
CriticalSection callbackLock;
|
||||
|
||||
enum { maxASIOChannels = 160 };
|
||||
|
||||
ASIOBufferInfo bufferInfos [maxASIOChannels];
|
||||
float* inBuffers [maxASIOChannels];
|
||||
float* outBuffers [maxASIOChannels];
|
||||
|
|
@ -257749,30 +257763,7 @@ private:
|
|||
++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));
|
||||
|
||||
|
|
@ -258028,64 +258019,47 @@ private:
|
|||
asioObject->outputReady();
|
||||
}
|
||||
|
||||
static ASIOTime* JUCE_ASIOCALLBACK bufferSwitchTimeInfoCallback0 (ASIOTime*, long index, long)
|
||||
template <int deviceIndex>
|
||||
struct ASIOCallbackFunctions
|
||||
{
|
||||
if (currentASIODev[0] != nullptr)
|
||||
currentASIODev[0]->callback (index);
|
||||
static ASIOTime* JUCE_ASIOCALLBACK bufferSwitchTimeInfoCallback (ASIOTime*, long index, long)
|
||||
{
|
||||
if (currentASIODev[deviceIndex] != nullptr)
|
||||
currentASIODev[deviceIndex]->callback (index);
|
||||
|
||||
return nullptr;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static void JUCE_ASIOCALLBACK bufferSwitchCallback (long index, long)
|
||||
{
|
||||
if (currentASIODev[deviceIndex] != nullptr)
|
||||
currentASIODev[deviceIndex]->callback (index);
|
||||
}
|
||||
|
||||
static long JUCE_ASIOCALLBACK asioMessagesCallback (long selector, long value, void*, double*)
|
||||
{
|
||||
return ASIOAudioIODevice::asioMessagesCallback (selector, value, deviceIndex);
|
||||
}
|
||||
|
||||
static void setCallbacks (ASIOCallbacks& callbacks)
|
||||
{
|
||||
callbacks.bufferSwitch = &bufferSwitchCallback;
|
||||
callbacks.asioMessage = &asioMessagesCallback;
|
||||
callbacks.bufferSwitchTimeInfo = &bufferSwitchTimeInfoCallback;
|
||||
}
|
||||
};
|
||||
|
||||
void setCallbackFunctions()
|
||||
{
|
||||
callbacks.sampleRateDidChange = &sampleRateChangedCallback;
|
||||
|
||||
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 ASIOTime* JUCE_ASIOCALLBACK bufferSwitchTimeInfoCallback1 (ASIOTime*, long index, long)
|
||||
{
|
||||
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 void JUCE_ASIOCALLBACK bufferSwitchCallback0 (long index, long)
|
||||
{
|
||||
if (currentASIODev[0] != nullptr)
|
||||
currentASIODev[0]->callback (index);
|
||||
}
|
||||
|
||||
static void JUCE_ASIOCALLBACK bufferSwitchCallback1 (long index, long)
|
||||
{
|
||||
if (currentASIODev[1] != nullptr)
|
||||
currentASIODev[1]->callback (index);
|
||||
}
|
||||
|
||||
static void JUCE_ASIOCALLBACK bufferSwitchCallback2 (long index, long)
|
||||
{
|
||||
if (currentASIODev[2] != nullptr)
|
||||
currentASIODev[2]->callback (index);
|
||||
}
|
||||
|
||||
static long JUCE_ASIOCALLBACK asioMessagesCallback0 (long selector, long value, void*, double*)
|
||||
{
|
||||
return asioMessagesCallback (selector, value, 0);
|
||||
}
|
||||
|
||||
static long JUCE_ASIOCALLBACK asioMessagesCallback1 (long selector, long value, void*, double*)
|
||||
{
|
||||
return asioMessagesCallback (selector, value, 1);
|
||||
}
|
||||
|
||||
static long JUCE_ASIOCALLBACK asioMessagesCallback2 (long selector, long value, void*, double*)
|
||||
{
|
||||
return asioMessagesCallback (selector, value, 2);
|
||||
}
|
||||
|
||||
static long JUCE_ASIOCALLBACK asioMessagesCallback (long selector, long value, const int deviceIndex)
|
||||
static long asioMessagesCallback (long selector, long value, const int deviceIndex)
|
||||
{
|
||||
switch (selector)
|
||||
{
|
||||
|
|
@ -258805,7 +258779,7 @@ namespace
|
|||
class DSoundInternalOutChannel
|
||||
{
|
||||
public:
|
||||
DSoundInternalOutChannel (const String& name_, LPGUID guid_, int rate,
|
||||
DSoundInternalOutChannel (const String& name_, const GUID& guid_, int rate,
|
||||
int bufferSize, float* left, float* right)
|
||||
: bitDepth (16), name (name_), guid (guid_), sampleRate (rate),
|
||||
bufferSizeSamples (bufferSize), leftBuffer (left), rightBuffer (right),
|
||||
|
|
@ -258854,7 +258828,7 @@ public:
|
|||
HRESULT hr = E_NOINTERFACE;
|
||||
|
||||
if (dsDirectSoundCreate != 0)
|
||||
hr = dsDirectSoundCreate (guid, &pDirectSound, 0);
|
||||
hr = dsDirectSoundCreate (&guid, &pDirectSound, 0);
|
||||
|
||||
if (hr == S_OK)
|
||||
{
|
||||
|
|
@ -259093,7 +259067,7 @@ public:
|
|||
|
||||
private:
|
||||
String name;
|
||||
LPGUID guid;
|
||||
GUID guid;
|
||||
int sampleRate, bufferSizeSamples;
|
||||
float* leftBuffer;
|
||||
float* rightBuffer;
|
||||
|
|
@ -259115,7 +259089,7 @@ private:
|
|||
struct DSoundInternalInChannel
|
||||
{
|
||||
public:
|
||||
DSoundInternalInChannel (const String& name_, LPGUID guid_, int rate,
|
||||
DSoundInternalInChannel (const String& name_, const GUID& guid_, int rate,
|
||||
int bufferSize, float* left, float* right)
|
||||
: bitDepth (16), name (name_), guid (guid_), sampleRate (rate),
|
||||
bufferSizeSamples (bufferSize), leftBuffer (left), rightBuffer (right),
|
||||
|
|
@ -259173,7 +259147,7 @@ public:
|
|||
HRESULT hr = E_NOINTERFACE;
|
||||
|
||||
if (dsDirectSoundCaptureCreate != 0)
|
||||
hr = dsDirectSoundCaptureCreate (guid, &pDirectSoundCapture, 0);
|
||||
hr = dsDirectSoundCaptureCreate (&guid, &pDirectSoundCapture, 0);
|
||||
|
||||
logError (hr);
|
||||
|
||||
|
|
@ -259349,7 +259323,7 @@ public:
|
|||
|
||||
private:
|
||||
String name;
|
||||
LPGUID guid;
|
||||
GUID guid;
|
||||
int sampleRate, bufferSizeSamples;
|
||||
float* leftBuffer;
|
||||
float* rightBuffer;
|
||||
|
|
@ -259668,23 +259642,16 @@ public:
|
|||
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();
|
||||
outputGuids.clear();
|
||||
inputDeviceNames.clear();
|
||||
outputGuids.clear();
|
||||
inputGuids.clear();
|
||||
|
||||
if (dsDirectSoundEnumerateW != 0)
|
||||
|
|
@ -259694,57 +259661,16 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
StringArray getDeviceNames (bool wantInputNames) const
|
||||
bool operator!= (const DSoundDeviceList& other) const noexcept
|
||||
{
|
||||
jassert (hasScanned); // need to call scanForDevices() before doing this
|
||||
|
||||
return wantInputNames ? inputDeviceNames
|
||||
: outputDeviceNames;
|
||||
return outputDeviceNames != other.outputDeviceNames
|
||||
|| inputDeviceNames != other.inputDeviceNames
|
||||
|| outputGuids != other.outputGuids
|
||||
|| inputGuids != other.inputGuids;
|
||||
}
|
||||
|
||||
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 = 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:
|
||||
bool hasScanned;
|
||||
|
||||
BOOL outputEnumProc (LPGUID lpGUID, String desc)
|
||||
static BOOL enumProc (LPGUID lpGUID, String desc, StringArray& names, Array<GUID>& guids)
|
||||
{
|
||||
desc = desc.trim();
|
||||
|
||||
|
|
@ -259753,68 +259679,28 @@ private:
|
|||
const String origDesc (desc);
|
||||
|
||||
int n = 2;
|
||||
while (outputDeviceNames.contains (desc))
|
||||
while (names.contains (desc))
|
||||
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;
|
||||
}
|
||||
|
||||
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 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 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)
|
||||
{
|
||||
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,
|
||||
|
|
@ -259831,8 +259717,8 @@ String DSoundAudioIODevice::openDevice (const BigInteger& inputChannels,
|
|||
|
||||
bufferSizeSamples = bufferSizeSamples_ & ~7;
|
||||
|
||||
DSoundAudioIODeviceType dlh;
|
||||
dlh.scanForDevices();
|
||||
DSoundDeviceList dlh;
|
||||
dlh.scan();
|
||||
|
||||
enabledInputs = inputChannels;
|
||||
enabledInputs.setRange (inChannels.size(),
|
||||
|
|
@ -259945,6 +259831,88 @@ String DSoundAudioIODevice::openDevice (const BigInteger& inputChannels,
|
|||
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()
|
||||
{
|
||||
return new DSoundAudioIODeviceType();
|
||||
|
|
@ -260879,15 +260847,15 @@ private:
|
|||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (WASAPIAudioIODevice);
|
||||
};
|
||||
|
||||
class WASAPIAudioIODeviceType : public AudioIODeviceType
|
||||
class WASAPIAudioIODeviceType : public AudioIODeviceType,
|
||||
private DeviceChangeDetector
|
||||
{
|
||||
public:
|
||||
WASAPIAudioIODeviceType()
|
||||
: AudioIODeviceType ("Windows Audio"),
|
||||
deviceChangeCatcher (_T("Windows Audio"), (WNDPROC) deviceChangeEventCallback),
|
||||
DeviceChangeDetector (L"Windows Audio"),
|
||||
hasScanned (false)
|
||||
{
|
||||
SetWindowLongPtr (deviceChangeCatcher.getHWND(), GWLP_USERDATA, (LONG_PTR) this);
|
||||
}
|
||||
|
||||
void scanForDevices()
|
||||
|
|
@ -260957,7 +260925,6 @@ public:
|
|||
StringArray inputDeviceNames, inputDeviceIds;
|
||||
|
||||
private:
|
||||
HiddenMessageWindow deviceChangeCatcher;
|
||||
bool hasScanned;
|
||||
|
||||
static String getDefaultEndpoint (IMMDeviceEnumerator* const enumerator, const bool forCapture)
|
||||
|
|
@ -261045,21 +261012,7 @@ private:
|
|||
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;
|
||||
scan (newOutNames, newInNames, newOutIds, newInIds);
|
||||
|
|
|
|||
|
|
@ -57521,6 +57521,9 @@ public:
|
|||
*/
|
||||
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.
|
||||
|
||||
This string will encapsulate the window's size, position, and whether it's
|
||||
|
|
|
|||
|
|
@ -90,7 +90,7 @@ void ResizableWindow::initialise (const bool shouldAddToDesktop)
|
|||
lastNonFullScreenPos.setBounds (50, 50, 256, 256);
|
||||
|
||||
if (shouldAddToDesktop)
|
||||
Component::addToDesktop (ResizableWindow::getDesktopWindowStyleFlags());
|
||||
addToDesktop();
|
||||
}
|
||||
|
||||
int ResizableWindow::getDesktopWindowStyleFlags() const
|
||||
|
|
@ -103,6 +103,11 @@ int ResizableWindow::getDesktopWindowStyleFlags() const
|
|||
return styleFlags;
|
||||
}
|
||||
|
||||
void ResizableWindow::addToDesktop()
|
||||
{
|
||||
Component::addToDesktop (ResizableWindow::getDesktopWindowStyleFlags());
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void ResizableWindow::clearContentComponent()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -200,6 +200,9 @@ public:
|
|||
*/
|
||||
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.
|
||||
|
||||
|
|
|
|||
|
|
@ -75,8 +75,6 @@ namespace ASIODebugging
|
|||
class ASIOAudioIODevice;
|
||||
static ASIOAudioIODevice* volatile currentASIODev[3] = { 0 };
|
||||
|
||||
static const int maxASIOChannels = 160;
|
||||
|
||||
|
||||
//==============================================================================
|
||||
class JUCE_API ASIOAudioIODevice : public AudioIODevice,
|
||||
|
|
@ -373,30 +371,7 @@ public:
|
|||
|
||||
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");
|
||||
err = asioObject->disposeBuffers();
|
||||
|
|
@ -429,7 +404,7 @@ public:
|
|||
Array <int> types;
|
||||
currentBitDepth = 16;
|
||||
|
||||
for (i = 0; i < jmin ((int) totalNumInputChans, maxASIOChannels); ++i)
|
||||
for (i = 0; i < jmin ((int) totalNumInputChans, (int) maxASIOChannels); ++i)
|
||||
{
|
||||
if (inputChannels[i])
|
||||
{
|
||||
|
|
@ -456,7 +431,7 @@ public:
|
|||
jassert (numActiveInputChans == n);
|
||||
n = 0;
|
||||
|
||||
for (i = 0; i < jmin ((int) totalNumOutputChans, maxASIOChannels); ++i)
|
||||
for (i = 0; i < jmin ((int) totalNumOutputChans, (int) maxASIOChannels); ++i)
|
||||
{
|
||||
if (outputChannels[i])
|
||||
{
|
||||
|
|
@ -750,6 +725,8 @@ private:
|
|||
AudioIODeviceCallback* volatile currentCallback;
|
||||
CriticalSection callbackLock;
|
||||
|
||||
enum { maxASIOChannels = 160 };
|
||||
|
||||
ASIOBufferInfo bufferInfos [maxASIOChannels];
|
||||
float* inBuffers [maxASIOChannels];
|
||||
float* outBuffers [maxASIOChannels];
|
||||
|
|
@ -982,31 +959,7 @@ private:
|
|||
++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));
|
||||
|
||||
|
|
@ -1264,65 +1217,48 @@ private:
|
|||
}
|
||||
|
||||
//==============================================================================
|
||||
static ASIOTime* JUCE_ASIOCALLBACK bufferSwitchTimeInfoCallback0 (ASIOTime*, long index, long)
|
||||
template <int deviceIndex>
|
||||
struct ASIOCallbackFunctions
|
||||
{
|
||||
if (currentASIODev[0] != nullptr)
|
||||
currentASIODev[0]->callback (index);
|
||||
static ASIOTime* JUCE_ASIOCALLBACK bufferSwitchTimeInfoCallback (ASIOTime*, long index, long)
|
||||
{
|
||||
if (currentASIODev[deviceIndex] != nullptr)
|
||||
currentASIODev[deviceIndex]->callback (index);
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static ASIOTime* JUCE_ASIOCALLBACK bufferSwitchTimeInfoCallback1 (ASIOTime*, long index, long)
|
||||
static void JUCE_ASIOCALLBACK bufferSwitchCallback (long index, long)
|
||||
{
|
||||
if (currentASIODev[deviceIndex] != nullptr)
|
||||
currentASIODev[deviceIndex]->callback (index);
|
||||
}
|
||||
|
||||
static long JUCE_ASIOCALLBACK asioMessagesCallback (long selector, long value, void*, double*)
|
||||
{
|
||||
return ASIOAudioIODevice::asioMessagesCallback (selector, value, deviceIndex);
|
||||
}
|
||||
|
||||
static void setCallbacks (ASIOCallbacks& callbacks)
|
||||
{
|
||||
callbacks.bufferSwitch = &bufferSwitchCallback;
|
||||
callbacks.asioMessage = &asioMessagesCallback;
|
||||
callbacks.bufferSwitchTimeInfo = &bufferSwitchTimeInfoCallback;
|
||||
}
|
||||
};
|
||||
|
||||
void setCallbackFunctions()
|
||||
{
|
||||
if (currentASIODev[1] != nullptr)
|
||||
currentASIODev[1]->callback (index);
|
||||
callbacks.sampleRateDidChange = &sampleRateChangedCallback;
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static ASIOTime* JUCE_ASIOCALLBACK bufferSwitchTimeInfoCallback2 (ASIOTime*, long index, long)
|
||||
{
|
||||
if (currentASIODev[2] != nullptr)
|
||||
currentASIODev[2]->callback (index);
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static void JUCE_ASIOCALLBACK bufferSwitchCallback0 (long index, long)
|
||||
{
|
||||
if (currentASIODev[0] != nullptr)
|
||||
currentASIODev[0]->callback (index);
|
||||
}
|
||||
|
||||
static void JUCE_ASIOCALLBACK bufferSwitchCallback1 (long index, long)
|
||||
{
|
||||
if (currentASIODev[1] != nullptr)
|
||||
currentASIODev[1]->callback (index);
|
||||
}
|
||||
|
||||
static void JUCE_ASIOCALLBACK bufferSwitchCallback2 (long index, long)
|
||||
{
|
||||
if (currentASIODev[2] != nullptr)
|
||||
currentASIODev[2]->callback (index);
|
||||
}
|
||||
|
||||
static long JUCE_ASIOCALLBACK asioMessagesCallback0 (long selector, long value, void*, double*)
|
||||
{
|
||||
return asioMessagesCallback (selector, value, 0);
|
||||
}
|
||||
|
||||
static long JUCE_ASIOCALLBACK asioMessagesCallback1 (long selector, long value, void*, double*)
|
||||
{
|
||||
return asioMessagesCallback (selector, value, 1);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -228,7 +228,7 @@ namespace
|
|||
class DSoundInternalOutChannel
|
||||
{
|
||||
public:
|
||||
DSoundInternalOutChannel (const String& name_, LPGUID guid_, int rate,
|
||||
DSoundInternalOutChannel (const String& name_, const GUID& guid_, int rate,
|
||||
int bufferSize, float* left, float* right)
|
||||
: bitDepth (16), name (name_), guid (guid_), sampleRate (rate),
|
||||
bufferSizeSamples (bufferSize), leftBuffer (left), rightBuffer (right),
|
||||
|
|
@ -277,7 +277,7 @@ public:
|
|||
HRESULT hr = E_NOINTERFACE;
|
||||
|
||||
if (dsDirectSoundCreate != 0)
|
||||
hr = dsDirectSoundCreate (guid, &pDirectSound, 0);
|
||||
hr = dsDirectSoundCreate (&guid, &pDirectSound, 0);
|
||||
|
||||
if (hr == S_OK)
|
||||
{
|
||||
|
|
@ -516,7 +516,7 @@ public:
|
|||
|
||||
private:
|
||||
String name;
|
||||
LPGUID guid;
|
||||
GUID guid;
|
||||
int sampleRate, bufferSizeSamples;
|
||||
float* leftBuffer;
|
||||
float* rightBuffer;
|
||||
|
|
@ -539,7 +539,7 @@ private:
|
|||
struct DSoundInternalInChannel
|
||||
{
|
||||
public:
|
||||
DSoundInternalInChannel (const String& name_, LPGUID guid_, int rate,
|
||||
DSoundInternalInChannel (const String& name_, const GUID& guid_, int rate,
|
||||
int bufferSize, float* left, float* right)
|
||||
: bitDepth (16), name (name_), guid (guid_), sampleRate (rate),
|
||||
bufferSizeSamples (bufferSize), leftBuffer (left), rightBuffer (right),
|
||||
|
|
@ -597,7 +597,7 @@ public:
|
|||
HRESULT hr = E_NOINTERFACE;
|
||||
|
||||
if (dsDirectSoundCaptureCreate != 0)
|
||||
hr = dsDirectSoundCaptureCreate (guid, &pDirectSoundCapture, 0);
|
||||
hr = dsDirectSoundCaptureCreate (&guid, &pDirectSoundCapture, 0);
|
||||
|
||||
logError (hr);
|
||||
|
||||
|
|
@ -773,7 +773,7 @@ public:
|
|||
|
||||
private:
|
||||
String name;
|
||||
LPGUID guid;
|
||||
GUID guid;
|
||||
int sampleRate, bufferSizeSamples;
|
||||
float* leftBuffer;
|
||||
float* rightBuffer;
|
||||
|
|
@ -1094,26 +1094,17 @@ public:
|
|||
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();
|
||||
outputGuids.clear();
|
||||
inputDeviceNames.clear();
|
||||
outputGuids.clear();
|
||||
inputGuids.clear();
|
||||
|
||||
if (dsDirectSoundEnumerateW != 0)
|
||||
|
|
@ -1123,59 +1114,16 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
StringArray getDeviceNames (bool wantInputNames) const
|
||||
bool operator!= (const DSoundDeviceList& other) const noexcept
|
||||
{
|
||||
jassert (hasScanned); // need to call scanForDevices() before doing this
|
||||
|
||||
return wantInputNames ? inputDeviceNames
|
||||
: outputDeviceNames;
|
||||
return outputDeviceNames != other.outputDeviceNames
|
||||
|| inputDeviceNames != other.inputDeviceNames
|
||||
|| outputGuids != other.outputGuids
|
||||
|| inputGuids != other.inputGuids;
|
||||
}
|
||||
|
||||
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 = 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:
|
||||
bool hasScanned;
|
||||
|
||||
//==============================================================================
|
||||
BOOL outputEnumProc (LPGUID lpGUID, String desc)
|
||||
static BOOL enumProc (LPGUID lpGUID, String desc, StringArray& names, Array<GUID>& guids)
|
||||
{
|
||||
desc = desc.trim();
|
||||
|
||||
|
|
@ -1184,70 +1132,28 @@ private:
|
|||
const String origDesc (desc);
|
||||
|
||||
int n = 2;
|
||||
while (outputDeviceNames.contains (desc))
|
||||
while (names.contains (desc))
|
||||
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;
|
||||
}
|
||||
|
||||
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 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 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)
|
||||
{
|
||||
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);
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
|
|
@ -1265,8 +1171,8 @@ String DSoundAudioIODevice::openDevice (const BigInteger& inputChannels,
|
|||
|
||||
bufferSizeSamples = bufferSizeSamples_ & ~7;
|
||||
|
||||
DSoundAudioIODeviceType dlh;
|
||||
dlh.scanForDevices();
|
||||
DSoundDeviceList dlh;
|
||||
dlh.scan();
|
||||
|
||||
enabledInputs = inputChannels;
|
||||
enabledInputs.setRange (inChannels.size(),
|
||||
|
|
@ -1379,6 +1285,91 @@ String DSoundAudioIODevice::openDevice (const BigInteger& inputChannels,
|
|||
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()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -344,4 +344,37 @@ void MessageManager::doPlatformSpecificShutdown()
|
|||
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
|
||||
|
|
|
|||
|
|
@ -958,15 +958,15 @@ private:
|
|||
|
||||
|
||||
//==============================================================================
|
||||
class WASAPIAudioIODeviceType : public AudioIODeviceType
|
||||
class WASAPIAudioIODeviceType : public AudioIODeviceType,
|
||||
private DeviceChangeDetector
|
||||
{
|
||||
public:
|
||||
WASAPIAudioIODeviceType()
|
||||
: AudioIODeviceType ("Windows Audio"),
|
||||
deviceChangeCatcher (_T("Windows Audio"), (WNDPROC) deviceChangeEventCallback),
|
||||
DeviceChangeDetector (L"Windows Audio"),
|
||||
hasScanned (false)
|
||||
{
|
||||
SetWindowLongPtr (deviceChangeCatcher.getHWND(), GWLP_USERDATA, (LONG_PTR) this);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
|
|
@ -1038,7 +1038,6 @@ public:
|
|||
StringArray inputDeviceNames, inputDeviceIds;
|
||||
|
||||
private:
|
||||
HiddenMessageWindow deviceChangeCatcher;
|
||||
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;
|
||||
scan (newOutNames, newInNames, newOutIds, newInIds);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue