fix: reload audio output on Windows wake from sleep
This commit is contained in:
@@ -147,6 +147,11 @@ std::optional<HRESULT> MpvCore::WindowProc(HWND hwnd, UINT message,
|
||||
::RedrawWindow(flutter_window_, nullptr, nullptr,
|
||||
RDW_INVALIDATE | RDW_UPDATENOW | RDW_ALLCHILDREN);
|
||||
}
|
||||
} else if (wparam == kPowerResumeTimerId) {
|
||||
::KillTimer(flutter_window_, kPowerResumeTimerId);
|
||||
if (power_resume_cb_) {
|
||||
power_resume_cb_();
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -170,6 +175,14 @@ std::optional<HRESULT> MpvCore::WindowProc(HWND hwnd, UINT message,
|
||||
}
|
||||
break;
|
||||
}
|
||||
case WM_POWERBROADCAST: {
|
||||
if (wparam == PBT_APMRESUMEAUTOMATIC && power_resume_cb_) {
|
||||
// Delay audio reload to let WASAPI fully reinitialize after wake.
|
||||
::KillTimer(flutter_window_, kPowerResumeTimerId);
|
||||
::SetTimer(flutter_window_, kPowerResumeTimerId, kPowerResumeAudioDelay, nullptr);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case WM_CLOSE: {
|
||||
::SendMessage(container_, WM_CLOSE, 0, 0);
|
||||
for (const auto& [mpv_view, rect] : mpv_views_) {
|
||||
@@ -202,6 +215,10 @@ RECT MpvCore::GetGlobalRect(int32_t left, int32_t top, int32_t right,
|
||||
return rect;
|
||||
}
|
||||
|
||||
void MpvCore::SetPowerResumeCallback(PowerResumeCallback callback) {
|
||||
power_resume_cb_ = std::move(callback);
|
||||
}
|
||||
|
||||
std::unique_ptr<MpvCore> MpvCore::instance_ = nullptr;
|
||||
|
||||
} // namespace mpv
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include <Windows.h>
|
||||
|
||||
#include <cmath>
|
||||
#include <functional>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
@@ -15,7 +16,9 @@ namespace mpv {
|
||||
class MpvCore {
|
||||
public:
|
||||
static constexpr auto kPositionAndShowDelay = 300;
|
||||
static constexpr auto kPowerResumeAudioDelay = 500;
|
||||
static constexpr UINT_PTR kCompositionRestoreTimerId = 1001;
|
||||
static constexpr UINT_PTR kPowerResumeTimerId = 1002;
|
||||
|
||||
static MpvCore* GetInstance();
|
||||
static void SetInstance(std::unique_ptr<MpvCore> instance);
|
||||
@@ -42,6 +45,10 @@ class MpvCore {
|
||||
std::optional<HRESULT> WindowProc(HWND hwnd, UINT message, WPARAM wparam,
|
||||
LPARAM lparam);
|
||||
|
||||
// Callback invoked when Windows resumes from sleep/hibernate.
|
||||
using PowerResumeCallback = std::function<void()>;
|
||||
void SetPowerResumeCallback(PowerResumeCallback callback);
|
||||
|
||||
private:
|
||||
RECT GetGlobalRect(int32_t left, int32_t top, int32_t right, int32_t bottom);
|
||||
|
||||
@@ -53,6 +60,7 @@ class MpvCore {
|
||||
bool was_window_hidden_due_to_minimize_ = false;
|
||||
bool visible_ = true;
|
||||
bool composition_enabled_ = false;
|
||||
PowerResumeCallback power_resume_cb_;
|
||||
|
||||
static std::unique_ptr<MpvCore> instance_;
|
||||
};
|
||||
|
||||
@@ -121,6 +121,16 @@ void MpvPlayerPlugin::HandleMethodCall(
|
||||
RECT rect = {0, 0, 100, 100};
|
||||
MpvCore::GetInstance()->CreateMpvView(player_->GetHwnd(), rect, 1.0);
|
||||
|
||||
// Reload audio output on wake from sleep to recover stale WASAPI sessions.
|
||||
MpvCore::GetInstance()->SetPowerResumeCallback([this]() {
|
||||
if (player_ && player_->IsInitialized()) {
|
||||
auto device = player_->GetProperty("audio-device");
|
||||
if (!device.empty()) {
|
||||
player_->SetProperty("audio-device", device);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Start hidden.
|
||||
MpvCore::GetInstance()->SetVisible(false);
|
||||
result->Success(flutter::EncodableValue(true));
|
||||
|
||||
Reference in New Issue
Block a user