play method
- AudioSource music, {
- Duration fade = Duration.zero,
Plays the provided music
looped with the specified fade
.
Stopping the music
means canceling the returned StreamSubscription.
Implementation
StreamSubscription<void> play(
AudioSource music, {
Duration fade = Duration.zero,
}) {
StreamController? controller = _players[music];
StreamSubscription? position;
if (controller == null) {
ja.AudioPlayer? jaPlayer;
Player? player;
Timer? timer;
controller = StreamController.broadcast(
onListen: () async {
try {
if (_isMobile) {
jaPlayer = ja.AudioPlayer();
} else {
player = Player();
}
} catch (e) {
// If [Player] isn't available on the current platform, this throws
// a `null check operator used on a null value`.
if (e is! TypeError) {
Log.error(
'Failed to initialize `Player`: ${e.toString()}',
'$runtimeType',
);
}
}
if (_isMobile) {
await jaPlayer?.setAudioSource(music.source);
await jaPlayer?.setLoopMode(ja.LoopMode.all);
await jaPlayer?.play();
} else {
await player?.open(music.media);
// TODO: Wait for `media_kit` to improve [PlaylistMode.loop] in Web.
if (PlatformUtils.isWeb) {
position = player?.stream.completed.listen((e) async {
await player?.seek(Duration.zero);
await player?.play();
});
} else {
await player?.setPlaylistMode(PlaylistMode.loop);
}
}
if (fade != Duration.zero) {
await (jaPlayer?.setVolume ?? player?.setVolume)?.call(0);
timer = Timer.periodic(
Duration(microseconds: fade.inMicroseconds ~/ 10),
(timer) async {
if (timer.tick > 9) {
timer.cancel();
} else {
await jaPlayer?.setVolume((timer.tick + 1) / 10);
await player?.setVolume(100 * (timer.tick + 1) / 10);
}
},
);
}
},
onCancel: () async {
_players.remove(music);
position?.cancel();
timer?.cancel();
Future<void>? dispose = jaPlayer?.dispose() ?? player?.dispose();
jaPlayer = null;
player = null;
await dispose;
},
);
_players[music] = controller;
}
return controller.stream.listen((_) {});
}