just_audio_windows_plus 0.4.0
just_audio_windows_plus: ^0.4.0 copied to clipboard
High-performance, seamless audio player for Flutter on Windows. Effortlessly play audio files, live streams, and playlists powered by native C++20 WinRT MediaPlayer.
just_audio_windows_plus #
High-performance, seamless native audio player for Flutter on Windows desktop.
Play internet audio streams, local audio files, sound effects, and gapless playlists effortlessly in your Flutter desktop applications. Powered by native Windows Media Foundation (WinRT Windows.Media.Playback.MediaPlayer) and modern C++20, just_audio_windows_plus gives you a fast, reliable, and production-grade audio experience right out of the box.
π Windows Platform Feature Matrix #
| Feature | Windows Support | Notes / Underlying Architecture |
|---|---|---|
| Audio from URL | β | HTTP / HTTPS progressive streams |
| Audio from File | β | Absolute local disk paths with Unicode handling |
| Audio from Asset | β | Flutter bundled package assets |
HLS Streams (.m3u8) |
β | Native Media Foundation HLS tag support |
DASH Streams (.mpd) |
β | Windows native DASH profile playback |
| Gapless Playlists | β | Native MediaPlaybackList with zero transition delay |
| Play / Pause / Seek | β | Frame-accurate seeking with reactive position stream |
| Buffering Progress | β | Real-time bufferingProgress event stream |
| Variable Playback Speed | β | 0.5x to 2.0x pitch-corrected playback |
| Volume Adjustment | β | 0.0 (silent) to 1.0 (full scale) |
| Looping & Shuffling | β | LoopMode.off, one, all & custom shuffle algorithms |
| Error Handling | β | Structured PlayerException mapped from WinRT HRESULT |
| Permutation Shuffling | β | Exclusive to Plus: $O(N)$ bounds-checked shuffle engine |
| Buffering NaN Protection | β | Exclusive to Plus: Guaranteed bounded buffer progress |
| UI Platform Thread Safety | β | Exclusive to Plus: Marshals to UI thread (HWND_MESSAGE) |
| Modern C++20 Toolchain | β | Exclusive to Plus: Seamless MSVC 14.40+ / VS 2026 build |
| Atomic Player Lifecycle | β | Exclusive to Plus: Zero 0xC0000005 access violations |
| Clean SMTC Separation | β | Exclusive to Plus: Conflict-free with audio_service |
β‘ 30-Second Quickstart #
Using just_audio_windows_plus is as simple as it gets. You use the standard, beloved just_audio API:
import 'package:flutter/material.dart';
import 'package:just_audio/just_audio.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
final player = AudioPlayer();
// Play an internet audio stream or local file in two lines
await player.setUrl('https://server10.mp3quran.net/minsh/001.mp3');
await player.play();
}
π What You Can Build #
- π All Modern Audio Formats: Native support for MP3, AAC, WAV, FLAC, M4A, as well as live HTTP/HTTPS, HLS, and DASH streams.
- π Dynamic Playlists: Next/previous track navigation, shuffling, looping, and gapless transitions with
ConcatenatingAudioSource. - β© Smooth Seeking & Scrubbing: High-precision timeline scrubbing with reactive position streams.
- ποΈ Fine-Grained Controls: Variable playback speed (0.5x to 2.0x), volume adjustment, looping modes, and silence skipping.
- π₯οΈ Native Windows Architecture: Uses Windows Media Foundation built directly into Windows 10 and 11. Zero extra DLLs or runtimes to package.
- π‘οΈ Rock-Solid Stability: Fully hardened with thread-safe mutexes and platform-thread dispatching to ensure your desktop app never stutters, locks up, or crashes.
π¦ Installation #
Path 1: For New Flutter Projects #
Add just_audio_windows_plus alongside just_audio in your pubspec.yaml:
dependencies:
flutter:
sdk: flutter
just_audio: ^0.10.6 # Full compatibility with ^0.10.x and ^0.9.x
just_audio_windows_plus: ^0.4.0
Path 2: Instant Upgrade for Existing Projects #
If your project already uses just_audio, simply add just_audio_windows_plus to your dependencies. Flutter's federated plugin system automatically selects just_audio_windows_plus as the Windows platform implementation, giving you full C++20 reliability and zero crashes with zero changes to your existing Dart code:
dependencies:
just_audio: ^0.10.6
just_audio_windows_plus: ^0.4.0
Tip (Testing via Git): If you wish to track the latest unreleased developments from GitHub:
dependencies: just_audio_windows_plus: git: url: https://github.com/OmarAfifi-CSE/just_audio_windows_plus.git
π οΈ Code Recipes & Examples #
1. Continuous Playlists & Track Navigation #
Easily queue multiple tracks, navigate between recordings, and listen for index changes:
// Works natively with modern just_audio 0.10.x setAudioSources
await player.setAudioSources([
AudioSource.uri(Uri.parse('https://server10.mp3quran.net/minsh/001.mp3')),
AudioSource.uri(Uri.parse('https://server10.mp3quran.net/minsh/112.mp3')),
AudioSource.uri(Uri.parse('https://server10.mp3quran.net/minsh/113.mp3')),
]);
await player.play();
// Smoothly skip tracks without UI stutter
await player.seekToNext();
await player.seekToPrevious();
2. Local Audio Files & Flutter Assets #
// Local file paths (handles spaces and international Unicode characters cleanly)
await player.setFilePath(r'C:\Audio\Recordings\01 Surah Al-Fatihah.mp3');
// Flutter bundled assets
await player.setAsset('assets/audio/notification.wav');
3. Playback Controls & Speed #
// Volume control (0.0 silent to 1.0 full)
await player.setVolume(0.8);
// Variable playback speed (e.g. 0.75x, 1.25x, 1.5x)
await player.setSpeed(1.25);
// Loop modes (off, one, all)
await player.setLoopMode(LoopMode.all);
// Shuffle mode
await player.setShuffleModeEnabled(true);
4. Complete Ready-to-Copy Player Widget #
Here is a full Flutter widget featuring a seek bar, real-time position timestamps (01:23 / 03:45), and play/pause controls:
class DesktopAudioBar extends StatelessWidget {
final AudioPlayer player;
const DesktopAudioBar({super.key, required this.player});
String _formatDuration(Duration? d) {
if (d == null) return '--:--';
final minutes = d.inMinutes.remainder(60).toString().padLeft(2, '0');
final seconds = d.inSeconds.remainder(60).toString().padLeft(2, '0');
return '$minutes:$seconds';
}
@override
Widget build(BuildContext context) {
return StreamBuilder<Duration?>(
stream: player.durationStream,
builder: (context, durationSnapshot) {
final duration = durationSnapshot.data ?? Duration.zero;
return StreamBuilder<Duration>(
stream: player.positionStream,
builder: (context, positionSnapshot) {
var position = positionSnapshot.data ?? Duration.zero;
if (position > duration) position = duration;
return Row(
children: [
StreamBuilder<PlayerState>(
stream: player.playerStateStream,
builder: (context, snapshot) {
final isPlaying = snapshot.data?.playing ?? false;
return IconButton(
icon: Icon(isPlaying ? Icons.pause_circle_filled : Icons.play_circle_filled),
iconSize: 42,
onPressed: () => isPlaying ? player.pause() : player.play(),
);
},
),
Text(_formatDuration(position)),
Expanded(
child: Slider(
min: 0.0,
max: duration.inMilliseconds.toDouble(),
value: position.inMilliseconds.toDouble().clamp(0.0, duration.inMilliseconds.toDouble()),
onChanged: (value) {
player.seek(Duration(milliseconds: value.round()));
},
),
),
Text(_formatDuration(duration)),
],
);
},
);
},
);
}
}
π¬ Under the Hood: Built for Production Reliability #
Developing desktop audio on Windows requires handling native COM/WinRT events and background threads gracefully. just_audio_windows_plus was engineered specifically to address common desktop audio pitfalls:
- Platform Thread Dispatcher (
platform_thread.hpp): WinRT Media Foundation delivers playback callbacks on background threadpools. We marshal these events onto Flutter's UI platform thread via a dedicated Win32 message window (HWND_MESSAGE). This ensures zero non-platform thread engine warnings and zero dropped events. - Thread-Safe Mutex & Concurrency Hardening: All internal player registries and event sinks are synchronized with
std::mutexand atomic variables (std::atomic<bool> source_set_,loop_mode_,shuffle_mode_), preventing data races and Access Violations (0xC0000005) during rapid track changes, hot-reload, and teardown. - Permutation-Safe Playlist Shuffling (
native_utils.hpp): Employs a linear $O(N)$ permutation mapping (ReorderByShuffleOrder) with strict validation to prevent index corruption, out-of-bounds access, and duplicate item insertion during playlist shuffles. - Live-Stream Buffering Defense: Guards progress calculations with
ClampBufferedPosition, preventingNaNand out-of-range floats from triggering assertion failures in Dart during dynamic network changes. - Modern C++20 Standard: Built with
CMAKE_CXX_STANDARD 20, ensuring seamless compilation with Visual Studio 2026 and modern MSVC toolchains (eliminatingSTL1011coroutine deprecation errors). - Clean System Media Separation: Disables automatic lockscreen flyout hijacking (
mediaPlayer.CommandManager().IsEnabled(false)), allowing apps to optionally manage media keys viaaudio_servicewithout conflicts. - Diagnostic Native Logging: Replaced silent empty catch blocks with structured
JAW_ERRORdiagnostics, while tracing logs are gated behindJAW_TRACEunder#ifndef NDEBUG, preventing console flood in production.
ποΈ Architectural Comparison #
How just_audio_windows_plus compares to legacy implementations:
| Feature / Capability | Legacy just_audio_windows (0.2.3) |
just_audio_windows_plus |
|---|---|---|
| Platform Thread Dispatching | β Background Threadpool (Engine warnings) | β
Win32 Message Window (HWND_MESSAGE) |
| C++ Toolchain Standard | β C++17 (Fails on MSVC 14.51 / VS 2026 STL1011) |
β C++20 Native Coroutine Standard |
| Concurrency & Thread Safety | β Unguarded raw pointers (Fatal 0xC0000005) |
β
std::mutex + std::atomic Lifecycle |
| Playlist Shuffling Engine | β $O(N^2)$ erase-insert (corrupts indices) | β
$O(N)$ Permutation-Safe Engine (native_utils.hpp) |
| Buffering Progress Defense | β Unchecked float (NaN/Inf crashes Dart) |
β
Guarded ClampBufferedPosition |
| Playlist Rapid Skipping | β Freezes BufferingProgress / Crashes | β Defensive WinRT Probing (Zero-Crash) |
| Source Swap Handling | β Falsely signals idle mid-swap (Aborts load) |
β
Protected source_set_ State Guard |
| Initial Load Duration | β Falsely evaluates 0 == 0 as completed |
β
NaturalDuration > 0 Gating |
| Exception Resiliency | β catch(char*) escapes to std::terminate |
β
Structured hresult_error & std::exception |
| Native Error Visibility | β Empty catch(...) (Silent runtime failure) |
β
Diagnostic JAW_ERROR Logging |
| System Media Flyout | β Hijacks lockscreen with blank info | β Clean Separation (De-conflicted SMTC) |
| Release Log Overhead | β Floods terminal on every volume/seek | β
Silent Release Builds (JAW_TRACE) |
| Maintenance Status | β οΈ Abandoned (>2 years without pub update) | π Actively Maintained & Production Ready |
β Frequently Asked Questions (FAQ) #
Q: Do my users need to install any external C++ runtimes or codecs?
No. just_audio_windows_plus uses Windows Media Foundation (WinRT Windows.Media.Playback.MediaPlayer), which is pre-installed on every Windows 10 and 11 machine. It compiles directly into your Flutter executable.
Q: What audio formats are supported?
All standard formats supported by Windows Media Foundation: MP3, AAC, WAV, FLAC, M4A, WMA, as well as HTTP/HTTPS, HLS, and DASH streams.
Q: Can I run multiple AudioPlayer instances simultaneously?
Yes. All internal state, channels, and event sinks are fully isolated and thread-safe per player instance.
Q: How do I handle background audio or keyboard media keys?
Because just_audio_windows_plus cleanly opts out of automatic SMTC hijacking, you can use audio_service to manage keyboard media keys and OS lock screen widgets with complete control.
π§ͺ Stress Benchmarks & Verification #
- 100+ Rapid Consecutive Seeks & Track Switches: 0 crashes, 0 unhandled COM exceptions, 0 deadlocks.
- Resource Leak Audits: Verified complete destruction of WinRT objects and Flutter channels upon player disposal.
- 120 FPS Zero-Jank Conformance: Background media notifications do not block the Windows UI message loop.
π Author & License #
- Engineered, hardened, and maintained by Omar Afifi (@OmarAfifi-CSE).
- Foundational heritage credited to Bruno D'Luka and Ryan Heise.
- Licensed under the MIT License. See LICENSE for details.
