Update custom_player.dart

This commit is contained in:
S.B 2024-10-19 14:54:05 +02:00 committed by GitHub
parent 8b6cc11486
commit c5a72cd44c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -4,43 +4,52 @@ import 'package:media_kit/media_kit.dart';
import 'package:flutter_broadcasts/flutter_broadcasts.dart'; import 'package:flutter_broadcasts/flutter_broadcasts.dart';
import 'package:package_info_plus/package_info_plus.dart'; import 'package:package_info_plus/package_info_plus.dart';
import 'package:audio_session/audio_session.dart'; import 'package:audio_session/audio_session.dart';
// ignore: implementation_imports
import 'package:spotube/services/audio_player/playback_state.dart'; import 'package:spotube/services/audio_player/playback_state.dart';
import 'package:spotube/utils/platform.dart'; import 'package:spotube/utils/platform.dart';
/// MediaKit [Player] by default doesn't have a state stream.
/// This class adds a state stream to the [Player] class.
class CustomPlayer extends Player { class CustomPlayer extends Player {
final StreamController<AudioPlaybackState> _playerStateStream; final StreamController<AudioPlaybackState> _playerStateStream = StreamController.broadcast();
final StreamController<bool> _shuffleStream; final StreamController<bool> _shuffleStream = StreamController.broadcast();
late final List<StreamSubscription> _subscriptions; late final List<StreamSubscription> _subscriptions;
bool _shuffled = false;
bool _shuffled;
int _androidAudioSessionId = 0; int _androidAudioSessionId = 0;
String _packageName = ""; String _packageName = "";
AndroidAudioManager? _androidAudioManager; AndroidAudioManager? _androidAudioManager;
CustomPlayer({super.configuration}) CustomPlayer({super.configuration}) {
: _playerStateStream = StreamController.broadcast(),
_shuffleStream = StreamController.broadcast(),
_shuffled = false {
nativePlayer.setProperty("network-timeout", "120"); nativePlayer.setProperty("network-timeout", "120");
_initPlatformSpecificSetup();
_subscriptions = [ _listenToPlayerEvents();
stream.buffering.listen((event) {
_playerStateStream.add(AudioPlaybackState.buffering);
}),
stream.playing.listen((playing) {
if (playing) {
_playerStateStream.add(AudioPlaybackState.playing);
} else {
_playerStateStream.add(AudioPlaybackState.paused);
} }
Future<void> _initPlatformSpecificSetup() async {
final packageInfo = await PackageInfo.fromPlatform();
_packageName = packageInfo.packageName;
if (kIsAndroid) {
_androidAudioManager = AndroidAudioManager();
_androidAudioSessionId = await _androidAudioManager!.generateAudioSessionId();
notifyAudioSessionUpdate(true);
await _setAndroidAudioSession();
}
}
Future<void> _setAndroidAudioSession() async {
await nativePlayer.setProperty("audiotrack-session-id", _androidAudioSessionId.toString());
await nativePlayer.setProperty("ao", "audiotrack,opensles,");
}
void _listenToPlayerEvents() {
_subscriptions = [
stream.buffering.listen((_) => _playerStateStream.add(AudioPlaybackState.buffering)),
stream.playing.listen((playing) {
_playerStateStream.add(playing ? AudioPlaybackState.playing : AudioPlaybackState.paused);
}), }),
stream.completed.listen((isCompleted) async { stream.completed.listen((isCompleted) {
if (!isCompleted) return; if (isCompleted) {
_playerStateStream.add(AudioPlaybackState.completed); _playerStateStream.add(AudioPlaybackState.completed);
}
}), }),
stream.playlist.listen((event) { stream.playlist.listen((event) {
if (event.medias.isEmpty) { if (event.medias.isEmpty) {
@ -51,23 +60,6 @@ class CustomPlayer extends Player {
AppLogger.reportError('[MediaKitError] \n$event', StackTrace.current); AppLogger.reportError('[MediaKitError] \n$event', StackTrace.current);
}), }),
]; ];
PackageInfo.fromPlatform().then((packageInfo) {
_packageName = packageInfo.packageName;
});
if (kIsAndroid) {
_androidAudioManager = AndroidAudioManager();
AudioSession.instance.then((s) async {
_androidAudioSessionId =
await _androidAudioManager!.generateAudioSessionId();
notifyAudioSessionUpdate(true);
await nativePlayer.setProperty(
"audiotrack-session-id",
_androidAudioSessionId.toString(),
);
await nativePlayer.setProperty("ao", "audiotrack,opensles,");
});
}
} }
Future<void> notifyAudioSessionUpdate(bool active) async { Future<void> notifyAudioSessionUpdate(bool active) async {
@ -79,7 +71,7 @@ class CustomPlayer extends Player {
: "android.media.action.CLOSE_AUDIO_EFFECT_CONTROL_SESSION", : "android.media.action.CLOSE_AUDIO_EFFECT_CONTROL_SESSION",
data: { data: {
"android.media.extra.AUDIO_SESSION": _androidAudioSessionId, "android.media.extra.AUDIO_SESSION": _androidAudioSessionId,
"android.media.extra.PACKAGE_NAME": _packageName "android.media.extra.PACKAGE_NAME": _packageName,
}, },
), ),
); );
@ -90,6 +82,7 @@ class CustomPlayer extends Player {
Stream<AudioPlaybackState> get playerStateStream => _playerStateStream.stream; Stream<AudioPlaybackState> get playerStateStream => _playerStateStream.stream;
Stream<bool> get shuffleStream => _shuffleStream.stream; Stream<bool> get shuffleStream => _shuffleStream.stream;
Stream<int> get indexChangeStream { Stream<int> get indexChangeStream {
int oldIndex = state.playlist.index; int oldIndex = state.playlist.index;
return stream.playlist.map((event) => event.index).where((newIndex) { return stream.playlist.map((event) => event.index).where((newIndex) {
@ -106,6 +99,8 @@ class CustomPlayer extends Player {
_shuffled = shuffle; _shuffled = shuffle;
await super.setShuffle(shuffle); await super.setShuffle(shuffle);
_shuffleStream.add(shuffle); _shuffleStream.add(shuffle);
// Ensure delay before rearranging playlist
await Future.delayed(const Duration(milliseconds: 100)); await Future.delayed(const Duration(milliseconds: 100));
if (shuffle) { if (shuffle) {
await move(state.playlist.index, 0); await move(state.playlist.index, 0);
@ -115,7 +110,6 @@ class CustomPlayer extends Player {
@override @override
Future<void> stop() async { Future<void> stop() async {
await super.stop(); await super.stop();
_shuffled = false; _shuffled = false;
_playerStateStream.add(AudioPlaybackState.stopped); _playerStateStream.add(AudioPlaybackState.stopped);
_shuffleStream.add(false); _shuffleStream.add(false);
@ -123,10 +117,10 @@ class CustomPlayer extends Player {
@override @override
Future<void> dispose() async { Future<void> dispose() async {
for (var element in _subscriptions) { await Future.wait(_subscriptions.map((sub) => sub.cancel()));
element.cancel();
}
await notifyAudioSessionUpdate(false); await notifyAudioSessionUpdate(false);
await _playerStateStream.close();
await _shuffleStream.close();
return super.dispose(); return super.dispose();
} }
@ -138,10 +132,9 @@ class CustomPlayer extends Player {
} }
Future<void> setAudioNormalization(bool normalize) async { Future<void> setAudioNormalization(bool normalize) async {
if (normalize) { await nativePlayer.setProperty(
await nativePlayer.setProperty('af', 'dynaudnorm=g=5:f=250:r=0.9:p=0.5'); 'af',
} else { normalize ? 'dynaudnorm=g=5:f=250:r=0.9:p=0.5' : ''
await nativePlayer.setProperty('af', ''); );
}
} }
} }