MCPcopy Create free account
hub / github.com/BohemiaInteractive/CWR / SwitchOutputDevice

Method SwitchOutputDevice

engine/PoseidonOpenAL/SoundSystemOAL.cpp:729–845  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

727{
728 if (!_selectedDevice.empty())
729 return _selectedDevice;
730 if (_device)
731 {
732 const char* name = alcGetString(static_cast<ALCdevice*>(_device), ALC_DEVICE_SPECIFIER);
733 if (name)
734 return name;
735 }
736 return {};
737}
738
739bool SoundSystemOAL::SwitchOutputDevice(const char* name)
740{
741 // Hold the audio lock across the whole swap: between destroying the old
742 // context and binding the new one there is no current context, so the
743 // streaming pump must not issue AL calls. It blocks on this lock until the
744 // rebind completes, then resumes against the new context.
745 std::lock_guard<std::recursive_mutex> lk(_audioMutex);
746 std::string requested = (name && *name) ? std::string(name) : std::string();
747 if (requested == _selectedDevice && _device)
748 return true;
749
750 ALCdevice* newDevice = alcOpenDevice(requested.empty() ? nullptr : requested.c_str());
751 if (!newDevice)
752 {
753 LOG_ERROR(Audio, "SwitchOutputDevice: alcOpenDevice failed for '{}'",
754 requested.empty() ? "<default>" : requested.c_str());
755 return false;
756 }
757
758 ALCcontext* newContext = alcCreateContext(newDevice, nullptr);
759 if (!newContext)
760 {
761 LOG_ERROR(Audio, "SwitchOutputDevice: alcCreateContext failed");
762 alcCloseDevice(newDevice);
763 return false;
764 }
765
766 // Snapshot volumes — backends typically initialise to 5.f on
767 // construction and we don't want a device-switch to silently
768 // jolt levels.
769 ALCdevice* oldDevice = static_cast<ALCdevice*>(_device);
770 ALCcontext* oldContext = static_cast<ALCcontext*>(_context);
771 float cd = _cdVolume;
772 float wave = _waveVolume;
773 float speech = _speechVolume;
774 bool wantEAX = _eaxEnabled;
775
776 // Note whether the device preview is currently in flight so we can
777 // resume after the context swap. StartDevicePreview computes the
778 // playback offset from a wall-clock anchor (NOT the AL source's
779 // AL_SEC_OFFSET) — this stays accurate across the context teardown
780 // and rapid clicks no longer collapse the offset to ~0.
781 bool wasDevicePreviewing = (_previewDevice.GetRef() != nullptr);
782
783 // Drop the in-flight preview waves while the OLD context is still
784 // current so their AL handles get released cleanly. Note: the
785 // wall-clock anchor (_devicePreviewAnchorMs) is intentionally NOT
786 // reset here — only TerminatePreview's "true cancel" path resets

Callers

nothing calls this directly

Calls 4

emptyMethod · 0.45
GetRefMethod · 0.45
FreeMethod · 0.45
UnloadMethod · 0.45

Tested by

no test coverage detected