mirror of
https://github.com/kunkundi/crossdesk.git
synced 2026-10-29 17:22:39 +08:00
[fix] release idle audio playback devices to allow Windows sleep, refs #131
This commit is contained in:
@@ -123,7 +123,6 @@ void SessionDeviceManager::RecordCaptureCadence(
|
||||
}
|
||||
|
||||
void SessionDeviceManager::Initialize() {
|
||||
if (!owner_.unattended_host_) InitializeAudioOutput();
|
||||
screen_capturer_factory_ = new ScreenCapturerFactory();
|
||||
device_controller_factory_ = new DeviceControllerFactory();
|
||||
keyboard_capturer_ =
|
||||
@@ -573,6 +572,12 @@ int SessionDeviceManager::StopKeyboardCapturer() {
|
||||
}
|
||||
|
||||
int SessionDeviceManager::InitializeAudioOutput() {
|
||||
if (output_device_) return 0;
|
||||
const auto now = std::chrono::steady_clock::now();
|
||||
if (now < next_audio_output_retry_) return -1;
|
||||
// A missing/unavailable playback device must not be reopened for every frame.
|
||||
next_audio_output_retry_ = now + std::chrono::seconds(1);
|
||||
|
||||
SDL_AudioSpec desired_out{};
|
||||
desired_out.freq = 48000;
|
||||
desired_out.format = SDL_AUDIO_S16;
|
||||
@@ -610,7 +615,12 @@ int SessionDeviceManager::InitializeAudioOutput() {
|
||||
#endif
|
||||
}
|
||||
|
||||
SDL_ResumeAudioDevice(output_device_);
|
||||
if (!SDL_ResumeAudioDevice(output_device_)) {
|
||||
LOG_ERROR("Failed to resume output device: {}", SDL_GetError());
|
||||
DestroyAudioOutput();
|
||||
return -1;
|
||||
}
|
||||
next_audio_output_retry_ = {};
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -630,11 +640,15 @@ void SessionDeviceManager::ClearAudio(const std::string& remote_id) {
|
||||
if (found == output_streams_.end()) return;
|
||||
SDL_DestroyAudioStream(found->second);
|
||||
output_streams_.erase(found);
|
||||
// An open SDL playback device can keep the Windows audio driver active even
|
||||
// without queued samples. Release it when no peer needs playback anymore.
|
||||
if (output_streams_.empty()) DestroyAudioOutput();
|
||||
}
|
||||
|
||||
void SessionDeviceManager::PushAudio(const std::string& remote_id,
|
||||
const char *data, size_t size) {
|
||||
if (!output_device_) return;
|
||||
if (!data || size == 0 || owner_.unattended_host_) return;
|
||||
if (InitializeAudioOutput() != 0) return;
|
||||
auto found = output_streams_.find(remote_id);
|
||||
if (found == output_streams_.end()) {
|
||||
SDL_AudioSpec spec{};
|
||||
@@ -644,17 +658,20 @@ void SessionDeviceManager::PushAudio(const std::string& remote_id,
|
||||
auto* stream = SDL_CreateAudioStream(&spec, &spec);
|
||||
if (!stream) {
|
||||
LOG_ERROR("Failed to create output stream: {}", SDL_GetError());
|
||||
if (output_streams_.empty()) DestroyAudioOutput();
|
||||
return;
|
||||
}
|
||||
if (!SDL_BindAudioStream(output_device_, stream)) {
|
||||
LOG_ERROR("Failed to bind output stream: {}", SDL_GetError());
|
||||
SDL_DestroyAudioStream(stream);
|
||||
if (output_streams_.empty()) DestroyAudioOutput();
|
||||
return;
|
||||
}
|
||||
found = output_streams_.emplace(remote_id, stream).first;
|
||||
}
|
||||
if (!SDL_PutAudioStreamData(found->second, data, static_cast<int>(size))) {
|
||||
LOG_ERROR("Failed to push audio data: {}", SDL_GetError());
|
||||
ClearAudio(remote_id);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -79,10 +79,10 @@ public:
|
||||
int StartKeyboardCapturer();
|
||||
int StopKeyboardCapturer();
|
||||
|
||||
int InitializeAudioOutput();
|
||||
int DestroyAudioOutput();
|
||||
// Serialized by GuiRuntime::audio_delivery_mutex_. Each peer has its own
|
||||
// stream so SDL mixes simultaneous playback and muting clears only that peer.
|
||||
// Open the output on the first frame and close it after the last stream ends.
|
||||
void ClearAudio(const std::string& remote_id);
|
||||
void PushAudio(const std::string& remote_id, const char *data, size_t size);
|
||||
|
||||
@@ -102,6 +102,7 @@ public:
|
||||
std::vector<HostDisplay> host_display_list() const;
|
||||
|
||||
private:
|
||||
int InitializeAudioOutput();
|
||||
unsigned ReleaseMouseButtonMask(unsigned mask);
|
||||
void DrainCapturedKeyboardInput();
|
||||
bool ShouldSendCapturedFrame(std::chrono::steady_clock::time_point now,
|
||||
@@ -117,6 +118,7 @@ private:
|
||||
GuiRuntime &owner_;
|
||||
uint32_t output_device_ = 0;
|
||||
std::unordered_map<std::string, SDL_AudioStream*> output_streams_;
|
||||
std::chrono::steady_clock::time_point next_audio_output_retry_{};
|
||||
ScreenCapturerFactory *screen_capturer_factory_ = nullptr;
|
||||
ScreenCapturer *screen_capturer_ = nullptr;
|
||||
ScreenSharingPower screen_sharing_power_;
|
||||
|
||||
Reference in New Issue
Block a user