Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
105 changes: 71 additions & 34 deletions packages/audioplayers_windows/windows/audioplayers_windows_plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,12 @@
#include <flutter/plugin_registrar_windows.h>
#include <flutter/standard_method_codec.h>

#include <iostream>
#include <map>
#include <memory>
#include <sstream>
#include <string>
#include <unordered_map>

#include "audio_player.h"
#include "audioplayers_helpers.h"
Expand Down Expand Up @@ -47,10 +50,17 @@ class AudioplayersWindowsPlugin : public Plugin {
private:
std::map<std::string, std::unique_ptr<AudioPlayer>> audioPlayers;

static inline BinaryMessenger* binaryMessenger;
static inline std::unique_ptr<MethodChannel<EncodableValue>> methods{};
static inline std::unique_ptr<MethodChannel<EncodableValue>> globalMethods{};
static inline std::unique_ptr<EventStreamHandler<>> globalEvents{};
BinaryMessenger* binaryMessenger;
std::unique_ptr<MethodChannel<EncodableValue>> methods{};
std::unique_ptr<MethodChannel<EncodableValue>> globalMethods{};

// Event channels and handlers must be kept alive
std::unique_ptr<EventChannel<EncodableValue>> globalEventChannel{};
EventStreamHandler<>* globalEvents = nullptr; // Owned by globalEventChannel

// Map to keep player event channels alive
std::map<std::string, std::unique_ptr<EventChannel<EncodableValue>>>
playerEventChannels;

// Called when a method is called on this plugin's channel from Dart.
void HandleMethodCall(const MethodCall<EncodableValue>& method_call,
Expand All @@ -70,33 +80,36 @@ class AudioplayersWindowsPlugin : public Plugin {
// static
void AudioplayersWindowsPlugin::RegisterWithRegistrar(
PluginRegistrarWindows* registrar) {
binaryMessenger = registrar->messenger();
methods = std::make_unique<MethodChannel<EncodableValue>>(
binaryMessenger, "xyz.luan/audioplayers",
&StandardMethodCodec::GetInstance());
globalMethods = std::make_unique<MethodChannel<EncodableValue>>(
binaryMessenger, "xyz.luan/audioplayers.global",
auto plugin = std::make_unique<AudioplayersWindowsPlugin>();

plugin->binaryMessenger = registrar->messenger();

plugin->methods = std::make_unique<MethodChannel<EncodableValue>>(
plugin->binaryMessenger, "xyz.luan/audioplayers",
&StandardMethodCodec::GetInstance());
auto _globalEventChannel = std::make_unique<EventChannel<EncodableValue>>(
binaryMessenger, "xyz.luan/audioplayers.global/events",

plugin->globalMethods = std::make_unique<MethodChannel<EncodableValue>>(
plugin->binaryMessenger, "xyz.luan/audioplayers.global",
&StandardMethodCodec::GetInstance());

auto plugin = std::make_unique<AudioplayersWindowsPlugin>();
plugin->globalEventChannel = std::make_unique<EventChannel<EncodableValue>>(
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<EventStreamHandler<>>();
auto _obj_stm_handle =
static_cast<StreamHandler<EncodableValue>*>(globalEvents.get());
std::unique_ptr<StreamHandler<EncodableValue>> _ptr{_obj_stm_handle};
_globalEventChannel->SetStreamHandler(std::move(_ptr));

auto handler = std::make_unique<EventStreamHandler<EncodableValue>>();
plugin->globalEvents = handler.get();

plugin->globalEventChannel->SetStreamHandler(std::move(handler));

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a question: do you think it would make sense to have a constructor taking all the initial parameters, similar to Flutter plugins:
https://github.com/flutter/packages/blob/a0ad9d99b16e1879f597f9c0b0150cb01f29a57e/packages/camera/camera_windows/windows/camera_plugin.cpp#L122


registrar->AddPlugin(std::move(plugin));
}
Expand All @@ -123,7 +136,9 @@ void AudioplayersWindowsPlugin::HandleGlobalMethodCall(
} else if (method_call.method_name().compare("emitError") == 0) {
auto code = GetArgument<std::string>("code", args, std::string());
auto message = GetArgument<std::string>("message", args, std::string());
globalEvents->Error(code, message, nullptr);
if (globalEvents) {
globalEvents->Error(code, message, nullptr);
}
result->Success();
} else {
result->NotImplemented();
Expand Down Expand Up @@ -247,6 +262,7 @@ void AudioplayersWindowsPlugin::HandleMethodCall(
} else if (method_call.method_name().compare("dispose") == 0) {
player->Dispose();
audioPlayers.erase(playerId);
playerEventChannels.erase(playerId);
} else {
result->NotImplemented();
return;
Expand All @@ -259,15 +275,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<StreamHandler<EncodableValue>*>(eventHandler);
std::unique_ptr<StreamHandler<EncodableValue>> _ptr{_obj_stm_handle};
eventChannel->SetStreamHandler(std::move(_ptr));
auto eventHandler = std::make_unique<EventStreamHandler<EncodableValue>>();
EventStreamHandler<EncodableValue>* eventHandlerPtr = eventHandler.get();
eventChannel->SetStreamHandler(std::move(eventHandler));

auto player =
std::make_unique<AudioPlayer>(playerId, methods.get(), eventHandler);
std::make_unique<AudioPlayer>(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);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if this is actually necessary to hold the values in an extra array. Theoretically the channels should be referenced by the AudioPlayer instance and thus in the audioPlayers map / array. So they should be kept alive as long as the players are present in the array, or am I mistaken?

}

AudioPlayer* AudioplayersWindowsPlugin::GetPlayer(std::string playerId) {
Expand All @@ -279,18 +297,37 @@ AudioPlayer* AudioplayersWindowsPlugin::GetPlayer(std::string playerId) {
}

void AudioplayersWindowsPlugin::OnGlobalLog(const std::string& message) {
globalEvents->Success(std::make_unique<flutter::EncodableValue>(
flutter::EncodableMap({{flutter::EncodableValue("event"),
flutter::EncodableValue("audio.onLog")},
{flutter::EncodableValue("value"),
flutter::EncodableValue(message)}})));
if (globalEvents) {
globalEvents->Success(std::make_unique<flutter::EncodableValue>(
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<PluginRegistrarWindows>(registrar));
->GetRegistrar<PluginRegistrarWindows>(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();
}
}
Loading