mirror of
https://github.com/KRTirtho/spotube.git
synced 2025-09-13 07:55:18 +00:00
Update custom_player.dart
This commit is contained in:
parent
8b6cc11486
commit
c5a72cd44c
@ -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', '');
|
);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user