PooledPlayback mixin

PooledPlayback

Opt-in audio pooling for instant retrigger/overlap of short sounds. Intended for SFX-style channels that often replay the same clip rapidly.

What it does

  • Keeps a tiny pool of pre-prepared AudioPlayers per sound key.
  • Inherits the channel’s AudioContext so focus/ducking rules match.
  • Supports assets, device files, URLs, and bytes sources.
  • Automatically marks the channel as multi-player capable, so BaseAudioChannel.waitUntilStopped() / playAndWait() will throw (waiting is ambiguous when multiple players can run).

Typical usage

class SfxChannel extends BaseAudioChannel with PooledPlayback {
  SfxChannel() : super('sfx_player');

  @override PlayerMode get playerMode => PlayerMode.lowLatency;
  @override ReleaseMode get releaseMode => ReleaseMode.stop;

  // Make pooling transparent for .play(path)
  @override
  Future<void> play(String path) async {
    await playPooledPath(path, key: path, volume: volume);
  }

  @override
  Future<void> dispose() async {
    await disposePools();  // ← clean pooled players
    return super.dispose();
  }
}

// Configure pooling (optional; defaults shown)
SoundEngine.instance.sfx.enablePooling(
  enabled: true,
  poolSizePerSound: 4,     // max concurrent players for a given sound
  minPlayersPerSound: 1,   // pre-warmed instances per sound
);

// Fire-and-forget retriggers (instant overlaps)
await SoundEngine.instance.sfx.play('assets/sfx/click.mp3');

When to refresh pools

If you change a channel’s AudioContext after some pools were built, call refreshPoolsAudioContext to recreate existing pools with the new context:

await sfx.setAudioContext(newCtx);
await sfx.refreshPoolsAudioContext();

Waiting caveat

Pooling enables concurrent playbacks; a single “wait until stop” has no unambiguous target. The mixin reports concurrency via hasMultipleConcurrentPlayers, so waitUntilStopped / playAndWait will throw UnsupportedError. If you need blocking behavior, disable pooling (globally or for the duration) or use a dedicated non-pooled channel.

Superclass constraints
Mixin applications

Properties

currentAudioContext → AudioContext?
Current audio context getter (nullable if never set).
no setterinherited
hashCode → int
The hash code for this object.
no setterinherited
hasMultipleConcurrentPlayers → bool
Report concurrency to the base so wait-helpers throw automatically.
no setteroverride
isActive → bool
Active Flag
no setterinherited
isMuted → bool
Muted Flag
no setterinherited
isPlaying → bool
Current Status
no setterinherited
isPoolingEnabled → bool
Whether pooling is currently enabled.
no setter
minPlayersPerSound → int
Pre-warmed players per sound key.
no setter
onDurationChanged → Stream<Duration>
Duration Stream
no setterinherited
onIsPlayingChanged → Stream<bool>
Reactive isPlaying Stream
no setterinherited
onPlayerComplete → Stream<void>
Completion Event
no setterinherited
onPositionChanged → Stream<Duration>
Position Stream
no setterinherited
playerId → String
Stable Identifier
finalinherited
playerMode → PlayerMode
Player Mode
no setterinherited
poolSizePerSound → int
Maximum concurrent players per sound key.
no setter
releaseMode → ReleaseMode
Release Mode
no setterinherited
runtimeType → Type
A representation of the runtime type of the object.
no setterinherited
volume → double
Current Volume (0.0 → 1.0)
no setterinherited

Methods

activate() → void
Activate
inherited
changeSource(AudioSourceBuilder builder) → void
Swap Loader
inherited
deactivate() → void
Deactivate
inherited
disableLifecycle() → void
Disable lifecycle handling for this channel.
inherited
dispose() → Future<void>
Dispose
inherited
disposePools() → Future<void>
Dispose all pools.
enableLifecycle([ChannelLifecycleConfig? cfg]) → void
Enable per-channel lifecycle handling
inherited
enablePooling({bool enabled = true, int poolSizePerSound = 4, int minPlayersPerSound = 1}) → void
Enable/disable pooling and configure pool sizes.
ensureWaitSupported(String methodName) → void
Throws if waiting semantics are unsupported for this channel.
inherited
fadeIn({Duration duration = const Duration(seconds: 2), Curve curve = Curves.easeInOut}) → Future<void>
Fade In
inherited
fadeInVolume(FadePreset preset) → Future<void>
Helper: Fade In via FadePreset
inherited
fadeOut({Duration duration = const Duration(seconds: 2), Curve curve = Curves.easeOut}) → Future<void>
Fade Out
inherited
fadeOutVolume(FadePreset preset) → Future<void>
Helper: Fade Out via FadePreset
inherited
fadeTo(double targetVolume, {Duration duration = const Duration(seconds: 2), Curve curve = Curves.linear}) → Future<void>
Fade To Target Volume
inherited
getDuration() → Future<Duration?>
Current Media Duration
inherited
mute() → Future<void>
Mute (volume → 0.0)
inherited
noSuchMethod(Invocation invocation) → dynamic
Invoked when a nonexistent method or property is accessed.
inherited
onStateChanged(PlayerState state) → void
Subclass Hook: Player State Changed
inherited
pause() → Future<void>
Pause
inherited
play(String path) → Future<void>
Play by Path
inherited
playAndWait(String path, {Duration startTimeout = const Duration(seconds: 3), Duration timeout = const Duration(minutes: 2), bool forceStopOnTimeout = true}) → Future<bool>
Convenience: play a path and wait for completion/stop
inherited
playFromSource(Source source) → Future<void>
Play from Source
inherited
playFromSourceAndWait(Source source, {Duration startTimeout = const Duration(seconds: 3), Duration timeout = const Duration(minutes: 2), bool forceStopOnTimeout = true}) → Future<bool>
Convenience: play a Source and wait for completion/stop
inherited
playPooled(String key, Source source, {double? volume}) → Future<StopFunction?>
Play using a pooled player (or fallback to the single channel player).
playPooledPath(String path, {String? key, double? volume}) → Future<StopFunction?>
Play a path using pooling, resolving the path with the channel’s current loader (respects changeSource(...)).
refreshPoolsAudioContext() → Future<void>
Rebuild all pools so they inherit the channel’s current AudioContext. Useful after calling setAudioContext(...) at runtime.
resolveSource(String path) → Source
Resolve a path into a Source using the current builder (assets/files/urls). Override via changeSource to switch the strategy at runtime.
inherited
resume() → Future<void>
Resume
inherited
seek(Duration position) → Future<void>
Seek
inherited
setAudioContext(AudioContext audioContext) → Future<void>
Apply Platform Audio Context
inherited
setVolume(double volume) → Future<void>
Set Volume
inherited
stop() → Future<void>
Stop
inherited
toggleActive() → void
Toggle Active
inherited
toString() → String
A string representation of this object.
inherited
unmute() → Future<void>
Unmute (volume → 1.0)
inherited
waitUntilStarted({Duration timeout = const Duration(seconds: 3)}) → Future<bool>
Wait until playback starts (first true)
inherited
waitUntilStopped({Duration startTimeout = const Duration(seconds: 3), Duration timeout = const Duration(minutes: 2), bool forceStopOnTimeout = true}) → Future<bool>
Wait until playback stops/completes
inherited
withFade(Future<void> action(), {FadePreset? fadeOut, FadePreset? fadeIn}) → Future<void>
withFade
inherited

Operators

operator ==(Object other) → bool
The equality operator.
inherited