Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
095efe5
Fixed crash related to missing Media Feature Pack
krll-kov Oct 21, 2025
400e4d4
Fixed build and functions usage
krll-kov Oct 21, 2025
e94e91f
Try delayed load approach
krll-kov Oct 21, 2025
8416488
Fixed build
krll-kov Oct 21, 2025
dbc516c
Fixed build
krll-kov Oct 21, 2025
c34af47
Fixed build?
krll-kov Oct 21, 2025
1d50aa6
clang-formatted
krll-kov Oct 21, 2025
d6b2279
clang-formatted
krll-kov Oct 21, 2025
08a3525
Merge branch 'main' into main
Gustl22 Jan 16, 2026
1efadb8
Update WIL version to 1.0.260126.7
krll-kov May 22, 2026
5f48550
Restore WIL version in CMakeLists.txt (New version makes plugin a mal…
krll-kov May 23, 2026
50dbf41
Merge remote-tracking branch 'upstream/HEAD'
krll-kov May 29, 2026
65669e6
Merge pull request #2 from bluefireteam/main
krll-kov Jun 21, 2026
25c988f
Restore WIL version in CMakeLists.txt (New version makes plugin a mal…
krll-kov Jun 21, 2026
0b7ea81
Temporary sync pubspeck with original repo
krll-kov Jun 23, 2026
227c77d
Temporary sync pubspeck with original repo
krll-kov Jun 23, 2026
df4ff0f
Merge pull request #3 from bluefireteam/main
krll-kov Jun 23, 2026
8b0aa0a
Bump version from 4.4.0 to 4.5.0
krll-kov Jun 23, 2026
b9e52c8
Add changelog entry for version 4.5.0
krll-kov Jun 23, 2026
2c3a1c0
temporary downgrade version from 4.5.0 to 4.4.0
krll-kov Jun 27, 2026
d17bb7b
Merge remote-tracking branch 'upstream/main'
krll-kov Jun 27, 2026
28aad94
Merge remote-tracking branch 'origin/main' into krll-kov-windows-n
Gustl22 Jul 22, 2026
f94f16f
improvements
Gustl22 Jul 22, 2026
8b5f7b7
format
Gustl22 Jul 22, 2026
79623d7
rename
Gustl22 Jul 22, 2026
1dab382
fix platform tests
Gustl22 Jul 22, 2026
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
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ void main() async {
isAndroid && await PlatformFeatures.usesAndroidMediaPlayerImpl();
final audioTestDataList = await getAudioTestDataList();

// Ensure global platform scope is initialized.
await AudioPlayer.global.ensureInitialized();

group('Platform method channel', () {
late AudioplayersPlatformInterface platform;
late String playerId;
Expand Down
7 changes: 5 additions & 2 deletions packages/audioplayers_windows/windows/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -48,13 +48,16 @@ set_target_properties(${PLUGIN_NAME} PROPERTIES
target_compile_features(${PLUGIN_NAME} PRIVATE cxx_std_20)

target_link_libraries(${PLUGIN_NAME} PRIVATE ${CMAKE_BINARY_DIR}/packages/Microsoft.Windows.ImplementationLibrary/build/native/Microsoft.Windows.ImplementationLibrary.targets)
target_link_libraries(${PLUGIN_NAME} PRIVATE Mfplat windowsapp)
target_link_libraries(${PLUGIN_NAME} PRIVATE windowsapp)

target_compile_definitions(${PLUGIN_NAME} PRIVATE FLUTTER_PLUGIN_IMPL)
target_include_directories(${PLUGIN_NAME} INTERFACE
"${CMAKE_CURRENT_SOURCE_DIR}/include")
target_link_libraries(${PLUGIN_NAME} PRIVATE flutter flutter_wrapper_plugin)
target_link_libraries(${PLUGIN_NAME} PRIVATE shlwapi)
target_link_libraries(${PLUGIN_NAME} PRIVATE shlwapi Mfplat)

target_link_libraries(${PLUGIN_NAME} PRIVATE delayimp)
target_link_options(${PLUGIN_NAME} PRIVATE "/DELAYLOAD:Mfplat.dll")

# List of absolute paths to libraries that should be bundled with the plugin
set(audioplayers_windows_bundled_libraries
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,10 @@ class AudioplayersWindowsPlugin : public Plugin {
AudioPlayer* GetPlayer(std::string playerId);

void OnGlobalLog(const std::string& message);

bool isMediaFoundationSupported = false;

void CheckMediaFoundationSupport();
};

// static
Expand Down Expand Up @@ -118,12 +122,38 @@ AudioplayersWindowsPlugin::AudioplayersWindowsPlugin() {}

AudioplayersWindowsPlugin::~AudioplayersWindowsPlugin() {}

// Test if on Windows N without Media Feature Pack installed
void AudioplayersWindowsPlugin::CheckMediaFoundationSupport() {
HMODULE hMfplat =
LoadLibraryEx(L"Mfplat.dll", NULL, LOAD_LIBRARY_SEARCH_SYSTEM32);
HMODULE hMfreadwrite =
LoadLibraryEx(L"mfreadwrite.dll", NULL, LOAD_LIBRARY_SEARCH_SYSTEM32);
isMediaFoundationSupported = hMfplat && hMfreadwrite;
if (hMfplat)
FreeLibrary(hMfplat);
if (hMfreadwrite)
FreeLibrary(hMfreadwrite);
}

void AudioplayersWindowsPlugin::HandleGlobalMethodCall(
const MethodCall<EncodableValue>& method_call,
std::unique_ptr<MethodResult<EncodableValue>> result) {
auto args = method_call.arguments();

if (method_call.method_name().compare("init") == 0) {
CheckMediaFoundationSupport();
if (!isMediaFoundationSupported) {
// Just log without returning an error: the global channel works fine
// nontheless.
if (globalEvents) {
globalEvents->Error(
"WindowsAudioError",
"Media Feature Pack not found. Please install it from "
"Windows Settings > Optional Features.",
nullptr);
}
}

for (const auto& entry : audioPlayers) {
entry.second->Dispose();
}
Expand Down Expand Up @@ -168,9 +198,22 @@ void AudioplayersWindowsPlugin::HandleMethodCall(

auto player = GetPlayer(playerId);
if (!player) {
result->Error(
"WindowsAudioError",
"Player has not yet been created or has already been disposed.");
if (method_call.method_name().compare("dispose") == 0) {
// If no player is available, still can dispose the event channel,
// e.g. when isMediaFoundationSupported is false.
playerEventChannels.erase(playerId);
result->Success();
return;
}
if (isMediaFoundationSupported) {
result->Error(
"WindowsAudioError",
"Player has not yet been created or has already been disposed.");
} else {
result->Error("WindowsAudioError",
"Media Feature Pack not found. Please install it from "
"Windows Settings > Optional Features.");
}
return;
}

Expand Down Expand Up @@ -275,9 +318,11 @@ void AudioplayersWindowsPlugin::CreatePlayer(std::string playerId) {
EventStreamHandler<EncodableValue>* eventHandlerPtr = eventHandler.get();
eventChannel->SetStreamHandler(std::move(eventHandler));

auto player =
std::make_unique<AudioPlayer>(playerId, methods.get(), eventHandlerPtr);
audioPlayers.insert(std::make_pair(playerId, std::move(player)));
if (isMediaFoundationSupported) {
auto player =
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
Expand Down
Loading