From 6bdef00e159ef2383cf2f829e9315199044c7d10 Mon Sep 17 00:00:00 2001 From: idcpj Date: Tue, 27 Jan 2026 14:59:47 +0800 Subject: [PATCH] fix(windows): refactor static globals to instance members to support multiple windows - Replaced all `static inline` global variables with instance members in `AudioplayersWindowsPlugin`. - Ensured each Engine instance possesses its own independent `MethodChannel` and `EventStreamHandler`. - Fixed crashes occurring when opening a second window due to global static pointer overwriting. - Isolated plugin state across different windows to prevent interference. --- .../windows/audioplayers_windows_plugin.cpp | 109 ++++++++++++------ 1 file changed, 75 insertions(+), 34 deletions(-) diff --git a/packages/audioplayers_windows/windows/audioplayers_windows_plugin.cpp b/packages/audioplayers_windows/windows/audioplayers_windows_plugin.cpp index c84e8cbed..b156f8c31 100644 --- a/packages/audioplayers_windows/windows/audioplayers_windows_plugin.cpp +++ b/packages/audioplayers_windows/windows/audioplayers_windows_plugin.cpp @@ -11,9 +11,12 @@ #include #include +#include #include #include #include +#include +#include #include "audio_player.h" #include "audioplayers_helpers.h" @@ -47,10 +50,20 @@ class AudioplayersWindowsPlugin : public Plugin { private: std::map> audioPlayers; - static inline BinaryMessenger* binaryMessenger; - static inline std::unique_ptr> methods{}; - static inline std::unique_ptr> globalMethods{}; - static inline std::unique_ptr> globalEvents{}; + BinaryMessenger* binaryMessenger; + std::unique_ptr> methods{}; + std::unique_ptr> globalMethods{}; + + // Event channels and handlers must be kept alive + std::unique_ptr> globalEventChannel{}; + EventStreamHandler<>* globalEvents = nullptr; // Owned by globalEventChannel + + // Map to keep player event channels alive + std::map>> + playerEventChannels; + // Map to keep player event handlers alive + std::map>> + playerEventHandlers; // Called when a method is called on this plugin's channel from Dart. void HandleMethodCall(const MethodCall& method_call, @@ -70,33 +83,36 @@ class AudioplayersWindowsPlugin : public Plugin { // static void AudioplayersWindowsPlugin::RegisterWithRegistrar( PluginRegistrarWindows* registrar) { - binaryMessenger = registrar->messenger(); - methods = std::make_unique>( - binaryMessenger, "xyz.luan/audioplayers", - &StandardMethodCodec::GetInstance()); - globalMethods = std::make_unique>( - binaryMessenger, "xyz.luan/audioplayers.global", + auto plugin = std::make_unique(); + + plugin->binaryMessenger = registrar->messenger(); + + plugin->methods = std::make_unique>( + plugin->binaryMessenger, "xyz.luan/audioplayers", &StandardMethodCodec::GetInstance()); - auto _globalEventChannel = std::make_unique>( - binaryMessenger, "xyz.luan/audioplayers.global/events", + + plugin->globalMethods = std::make_unique>( + plugin->binaryMessenger, "xyz.luan/audioplayers.global", &StandardMethodCodec::GetInstance()); - auto plugin = std::make_unique(); + plugin->globalEventChannel = std::make_unique>( + plugin->binaryMessenger, "xyz.luan/audioplayers.global/events", + &StandardMethodCodec::GetInstance()); - methods->SetMethodCallHandler( + plugin->methods->SetMethodCallHandler( [plugin_pointer = plugin.get()](const auto& call, auto result) { plugin_pointer->HandleMethodCall(call, std::move(result)); }); - globalMethods->SetMethodCallHandler( + plugin->globalMethods->SetMethodCallHandler( [plugin_pointer = plugin.get()](const auto& call, auto result) { plugin_pointer->HandleGlobalMethodCall(call, std::move(result)); }); - globalEvents = std::make_unique>(); - auto _obj_stm_handle = - static_cast*>(globalEvents.get()); - std::unique_ptr> _ptr{_obj_stm_handle}; - _globalEventChannel->SetStreamHandler(std::move(_ptr)); + + auto handler = std::make_unique>(); + plugin->globalEvents = handler.get(); + + plugin->globalEventChannel->SetStreamHandler(std::move(handler)); registrar->AddPlugin(std::move(plugin)); } @@ -123,7 +139,9 @@ void AudioplayersWindowsPlugin::HandleGlobalMethodCall( } else if (method_call.method_name().compare("emitError") == 0) { auto code = GetArgument("code", args, std::string()); auto message = GetArgument("message", args, std::string()); - globalEvents->Error(code, message, nullptr); + if (globalEvents) { + globalEvents->Error(code, message, nullptr); + } result->Success(); } else { result->NotImplemented(); @@ -247,6 +265,8 @@ void AudioplayersWindowsPlugin::HandleMethodCall( } else if (method_call.method_name().compare("dispose") == 0) { player->Dispose(); audioPlayers.erase(playerId); + playerEventChannels.erase(playerId); + playerEventHandlers.erase(playerId); } else { result->NotImplemented(); return; @@ -259,15 +279,17 @@ void AudioplayersWindowsPlugin::CreatePlayer(std::string playerId) { binaryMessenger, "xyz.luan/audioplayers/events/" + playerId, &StandardMethodCodec::GetInstance()); - auto eventHandler = new EventStreamHandler<>(); - auto _obj_stm_handle = - static_cast*>(eventHandler); - std::unique_ptr> _ptr{_obj_stm_handle}; - eventChannel->SetStreamHandler(std::move(_ptr)); + auto eventHandler = std::make_unique>(); + EventStreamHandler* eventHandlerPtr = eventHandler.get(); + eventChannel->SetStreamHandler(std::move(eventHandler)); auto player = - std::make_unique(playerId, methods.get(), eventHandler); + std::make_unique(playerId, methods.get(), eventHandlerPtr); audioPlayers.insert(std::make_pair(playerId, std::move(player))); + + // Keep the event channel and handler alive as long as the plugin/player + // exists + playerEventChannels[playerId] = std::move(eventChannel); } AudioPlayer* AudioplayersWindowsPlugin::GetPlayer(std::string playerId) { @@ -279,18 +301,37 @@ AudioPlayer* AudioplayersWindowsPlugin::GetPlayer(std::string playerId) { } void AudioplayersWindowsPlugin::OnGlobalLog(const std::string& message) { - globalEvents->Success(std::make_unique( - flutter::EncodableMap({{flutter::EncodableValue("event"), - flutter::EncodableValue("audio.onLog")}, - {flutter::EncodableValue("value"), - flutter::EncodableValue(message)}}))); + if (globalEvents) { + globalEvents->Success(std::make_unique( + flutter::EncodableMap({{flutter::EncodableValue("event"), + flutter::EncodableValue("audio.onLog")}, + {flutter::EncodableValue("value"), + flutter::EncodableValue(message)}}))); + } } } // namespace void AudioplayersWindowsPluginRegisterWithRegistrar( FlutterDesktopPluginRegistrarRef registrar) { - AudioplayersWindowsPlugin::RegisterWithRegistrar( + if (!registrar) { + std::cerr << "====== Audioplayers: Error - C-API Registrar is NULL!" + << std::endl; + std::cerr.flush(); + return; + } + + auto* plugin_registrar = PluginRegistrarManager::GetInstance() - ->GetRegistrar(registrar)); + ->GetRegistrar(registrar); + + if (plugin_registrar) { + std::cout.flush(); + AudioplayersWindowsPlugin::RegisterWithRegistrar(plugin_registrar); + } else { + std::cerr + << "====== Audioplayers: Failed to get plugin registrar from manager" + << std::endl; + std::cerr.flush(); + } }