diff --git a/Sources/Plasma/FeatureLib/pfConsole/pfConsoleCommands.cpp b/Sources/Plasma/FeatureLib/pfConsole/pfConsoleCommands.cpp index 995c503d8c..fcb773ba9d 100644 --- a/Sources/Plasma/FeatureLib/pfConsole/pfConsoleCommands.cpp +++ b/Sources/Plasma/FeatureLib/pfConsole/pfConsoleCommands.cpp @@ -3325,6 +3325,11 @@ PF_CONSOLE_CMD( Audio, SetDeviceName, "string deviceName", "Meant for plClient i plgAudioSys::SetPlaybackDevice(ST::string::from_utf8(params[0])); } +PF_CONSOLE_CMD(Audio, SetCaptureDeviceName, "string deviceName", "Sets the audio capture device name") +{ + plgAudioSys::SetCaptureDevice(ST::string::from_utf8(params[0])); +} + PF_CONSOLE_CMD( Audio, // groupName ShowIcons, // fxnName "bool b", // paramList diff --git a/Sources/Plasma/FeatureLib/pfPython/pyAudioControl.cpp b/Sources/Plasma/FeatureLib/pfPython/pyAudioControl.cpp index 2fc223381b..d7e5fde4d8 100644 --- a/Sources/Plasma/FeatureLib/pfPython/pyAudioControl.cpp +++ b/Sources/Plasma/FeatureLib/pfPython/pyAudioControl.cpp @@ -367,3 +367,20 @@ std::vector pyAudioControl::GetPlaybackDevices() const return plgAudioSys::Sys()->GetPlaybackDevices(); return std::vector(); } + +void pyAudioControl::SetCaptureDevice(const ST::string& device) +{ + plgAudioSys::SetCaptureDevice(device); +} + +ST::string pyAudioControl::GetCaptureDevice() const +{ + return plgAudioSys::GetCaptureDevice(); +} + +std::vector pyAudioControl::GetCaptureDevices() const +{ + if (plgAudioSys::Sys()) + return plgAudioSys::Sys()->GetCaptureDevices(); + return std::vector(); +} diff --git a/Sources/Plasma/FeatureLib/pfPython/pyAudioControl.h b/Sources/Plasma/FeatureLib/pfPython/pyAudioControl.h index 6d600c56c4..0b9d9e05b9 100644 --- a/Sources/Plasma/FeatureLib/pfPython/pyAudioControl.h +++ b/Sources/Plasma/FeatureLib/pfPython/pyAudioControl.h @@ -148,6 +148,11 @@ class pyAudioControl uint8_t GetPriorityCutoff() const; void SetPriorityCutoff(uint8_t cut); + void SetCaptureDevice(const ST::string& device); + ST::string GetCaptureDevice() const; + + std::vector GetCaptureDevices() const; + }; #endif // _pyAudioControl_h_ diff --git a/Sources/Plasma/FeatureLib/pfPython/pyAudioControlGlue.cpp b/Sources/Plasma/FeatureLib/pfPython/pyAudioControlGlue.cpp index ff7f840d4d..480329e6a7 100644 --- a/Sources/Plasma/FeatureLib/pfPython/pyAudioControlGlue.cpp +++ b/Sources/Plasma/FeatureLib/pfPython/pyAudioControlGlue.cpp @@ -429,6 +429,9 @@ PYTHON_START_METHODS_TABLE(ptAudioControl) PYTHON_METHOD_NOARGS(ptAudioControl, getPriorityCutoff, "Returns current sound priority"), PYTHON_METHOD(ptAudioControl, setPriorityCutoff, "Params: priority\nSets the sound priority"), PYTHON_METHOD(ptAudioControl, enableVoiceChat, "Params: state\nEnables or disables voice chat."), + PYTHON_METHOD(ptAudioControl, setCaptureDevice, "Sets the name for the capture device being used by the audio system"), + PYTHON_METHOD_NOARGS(ptAudioControl, getCaptureDevice, "Gets the name for the capture device being used by the audio system."), + PYTHON_METHOD_NOARGS(ptAudioControl, getCaptureDevices, "Gets the name of all available audio capture devices."), PYTHON_END_METHODS_TABLE; diff --git a/Sources/Plasma/PubUtilLib/plAudio/plAudioSystem.cpp b/Sources/Plasma/PubUtilLib/plAudio/plAudioSystem.cpp index 59e107239a..f69983392b 100644 --- a/Sources/Plasma/PubUtilLib/plAudio/plAudioSystem.cpp +++ b/Sources/Plasma/PubUtilLib/plAudio/plAudioSystem.cpp @@ -235,6 +235,27 @@ ST::string plAudioSystem::GetDefaultPlaybackDevice() const } } +std::vector plAudioSystem::GetCaptureDevices() const +{ + std::vector retval; + retval.push_back(s_defaultDeviceMagic); + + const ALchar* devices = alcGetString(nullptr, ALC_CAPTURE_DEVICE_SPECIFIER); + const ALchar* ptr = devices; + while (*ptr) { + ST::string deviceName = ST::string::from_utf8(ptr); + retval.push_back(deviceName); + ptr += deviceName.size() + sizeof(ALchar); + } + + return retval; +} + +ST::string plAudioSystem::GetDefaultCaptureDevice() const +{ + return ST::string::from_utf8(alcGetString(nullptr, ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER)); +} + //// Init //////////////////////////////////////////////////////////////////// bool plAudioSystem::Init() { @@ -878,16 +899,38 @@ bool plAudioSystem::MsgReceive(plMessage* msg) return hsKeyedObject::MsgReceive(msg); } -bool plAudioSystem::BeginCapture() +bool plAudioSystem::OpenCaptureDevice() { - if (fCaptureDevice) { - if (!EndCapture()) - return false; + const ST::string& deviceName = plgAudioSys::fCaptureDeviceName; + bool defaultDeviceRequested = (deviceName.empty() || deviceName == s_defaultDeviceMagic); + if (defaultDeviceRequested) + plgAudioSys::fCaptureDeviceName = s_defaultDeviceMagic; + ALCsizei bufferSize = fCaptureFrequency * sizeof(int16_t) * BUFFER_LEN_SECONDS; + + if (!defaultDeviceRequested) { + fCaptureDevice = alcCaptureOpenDevice(deviceName.c_str(), fCaptureFrequency, AL_FORMAT_MONO16, bufferSize); + if (!fCaptureDevice) { + plStatusLog::AddLineS("audio.log", plStatusLog::kRed, "ASYS: ERROR! Failed to open capture device '%s'.", deviceName.c_str()); + } } - ALCsizei bufferSize = fCaptureFrequency * sizeof(int16_t) * BUFFER_LEN_SECONDS; - fCaptureDevice = alcCaptureOpenDevice(nullptr, fCaptureFrequency, AL_FORMAT_MONO16, bufferSize); - if (fCaptureDevice) { + if (!fCaptureDevice) { + plgAudioSys::fCaptureDeviceName = s_defaultDeviceMagic; + fCaptureDevice = alcCaptureOpenDevice(nullptr, fCaptureFrequency, AL_FORMAT_MONO16, bufferSize); + if (!fCaptureDevice) { + plStatusLog::AddLineS("audio.log", plStatusLog::kRed, "ASYS: ERROR! Failed to open default capture device."); + } + } + + return fCaptureDevice != nullptr; +} + +bool plAudioSystem::BeginCapture() +{ + if (IsCapturing()) + return true; + + if (OpenCaptureDevice()) { alcCaptureStart(fCaptureDevice); return true; } else { @@ -897,7 +940,7 @@ bool plAudioSystem::BeginCapture() bool plAudioSystem::CaptureSamples(uint32_t samples, int16_t* data) const { - if (!fCaptureDevice) + if (!IsCapturing()) return false; alcCaptureSamples(fCaptureDevice, data, samples); @@ -918,7 +961,7 @@ bool plAudioSystem::SetCaptureSampleRate(uint32_t sampleRate) { if (fCaptureFrequency != sampleRate) { fCaptureFrequency = sampleRate; - if (fCaptureDevice) { + if (IsCapturing()) { if (!EndCapture()) return false; return BeginCapture(); @@ -929,7 +972,7 @@ bool plAudioSystem::SetCaptureSampleRate(uint32_t sampleRate) bool plAudioSystem::EndCapture() { - if (!fCaptureDevice) + if (!IsCapturing()) return false; alcCaptureStop(fCaptureDevice); @@ -963,7 +1006,8 @@ uint8_t plgAudioSys::fPriorityCutoff = 9; // We cut off sounds bool plgAudioSys::fEnableExtendedLogs = false; float plgAudioSys::fGlobalFadeVolume = 1.f; bool plgAudioSys::fLogStreamingUpdates = false; -ST::string plgAudioSys::fPlaybackDeviceName; +ST::string plgAudioSys::fPlaybackDeviceName = s_defaultDeviceMagic; +ST::string plgAudioSys::fCaptureDeviceName = s_defaultDeviceMagic; bool plgAudioSys::fRestarting = false; bool plgAudioSys::fMutedStateChange = false; @@ -1124,3 +1168,12 @@ void plgAudioSys::SetListenerOrientation(const hsVector3& view, const hsVector3& if (fSys) fSys->SetListenerOrientation(view, up); } + +void plgAudioSys::SetCaptureDevice(const ST::string& name) +{ + fCaptureDeviceName = name; + if (fSys && fSys->IsCapturing()) { + if (fSys->EndCapture()) + fSys->BeginCapture(); + } +} diff --git a/Sources/Plasma/PubUtilLib/plAudio/plAudioSystem.h b/Sources/Plasma/PubUtilLib/plAudio/plAudioSystem.h index 1442cf674f..c07386bd40 100644 --- a/Sources/Plasma/PubUtilLib/plAudio/plAudioSystem.h +++ b/Sources/Plasma/PubUtilLib/plAudio/plAudioSystem.h @@ -108,6 +108,12 @@ class plAudioSystem : public hsKeyedObject */ ST::string GetDefaultPlaybackDevice() const; + /** Gets a vector of all available audio capture devices. */ + std::vector GetCaptureDevices() const; + + /** Gets the name of the default audio capture device. */ + ST::string GetDefaultCaptureDevice() const; + /** Does the current playback device support EAX? */ bool IsEAXSupported() const { return fEAXSupported; } @@ -120,6 +126,7 @@ class plAudioSystem : public hsKeyedObject bool BeginCapture(); bool CaptureSamples(uint32_t samples, int16_t* data) const; uint32_t GetCaptureSampleCount() const; + bool IsCapturing() const { return fCaptureDevice != nullptr; } bool SetCaptureSampleRate(uint32_t sampleRate); bool EndCapture(); @@ -156,6 +163,8 @@ class plAudioSystem : public hsKeyedObject bool fEAXSupported; double fLastUpdateTimeMs; + bool OpenCaptureDevice(); + void RegisterSoftSound(const plKey& soundKey); void UnregisterSoftSound(const plKey& soundKey); void IUpdateSoftSounds(const hsPoint3& newPosition); @@ -237,6 +246,9 @@ class plgAudioSys Restart(); } + static ST::string GetCaptureDevice() { return fCaptureDeviceName; } + static void SetCaptureDevice(const ST::string& name); + static bool IsRestarting() { return fRestarting; } private: @@ -258,6 +270,7 @@ class plgAudioSys static float f2D3DBias; static bool fLogStreamingUpdates; static ST::string fPlaybackDeviceName; + static ST::string fCaptureDeviceName; static bool fRestarting; static bool fMutedStateChange;