mucke/lib/system/audio/audio_handler.dart
2020-12-20 16:21:48 +01:00

191 lines
5.6 KiB
Dart

import 'dart:math';
import 'package:audio_service/audio_service.dart';
import 'package:logging/logging.dart';
import '../../domain/entities/loop_mode.dart';
import '../../domain/entities/playback_event.dart';
import '../../domain/entities/shuffle_mode.dart';
import '../datasources/music_data_source_contract.dart';
import '../models/playback_event_model.dart';
import '../models/queue_item_model.dart';
import '../models/song_model.dart';
import 'audio_player_contract.dart';
import 'stream_constants.dart';
class MyAudioHandler extends BaseAudioHandler {
MyAudioHandler(this._musicDataSource, this._audioPlayer) {
_audioPlayer.queueStream.listen((event) {
_handleSetQueue(event);
});
_audioPlayer.currentSongStream.listen((songModel) {
mediaItemSubject.add(songModel.toMediaItem());
});
_audioPlayer.playbackEventStream.listen((event) {
_handlePlaybackEvent(event);
});
_audioPlayer.shuffleModeStream.listen((shuffleMode) {
_musicDataSource.setShuffleMode(shuffleMode);
customEventSubject.add({SHUFFLE_MODE: shuffleMode});
});
_audioPlayer.loopModeStream.listen((event) {
_musicDataSource.setLoopMode(event);
});
_initAudioPlayer();
}
Future<void> _initAudioPlayer() async {
if (_musicDataSource.loopModeStream != null) {
_audioPlayer.setLoopMode(await _musicDataSource.loopModeStream.first);
}
if (_musicDataSource.shuffleModeStream != null) {
_audioPlayer.setShuffleMode(await _musicDataSource.shuffleModeStream.first, false);
}
if (_musicDataSource.queueStream != null && _musicDataSource.currentIndexStream != null) {
_audioPlayer.loadQueue(
queue: await _musicDataSource.queueStream.first,
startIndex: await _musicDataSource.currentIndexStream.first,
);
}
}
final AudioPlayer _audioPlayer;
final MusicDataSource _musicDataSource;
static final _log = Logger('AudioHandler');
@override
Future<void> stop() async {
await _audioPlayer.stop();
await _audioPlayer.dispose();
await super.stop();
}
@override
Future<void> play() async {
_audioPlayer.play();
}
@override
Future<void> pause() async {
await _audioPlayer.pause();
}
@override
Future<void> skipToNext() async {
_audioPlayer.seekToNext();
}
@override
Future<void> skipToPrevious() async {
_audioPlayer.seekToPrevious();
}
@override
Future<void> addQueueItem(MediaItem mediaItem) async {
_audioPlayer.addToQueue(SongModel.fromMediaItem(mediaItem));
}
@override
Future<void> customAction(String name, Map<String, dynamic> arguments) async {
switch (name) {
case PLAY_WITH_CONTEXT:
final context = arguments['CONTEXT'] as List<String>;
final index = arguments['INDEX'] as int;
return playWithContext(context, index);
case APP_LIFECYCLE_RESUMED:
return onAppLifecycleResumed();
case SET_SHUFFLE_MODE:
return setCustomShuffleMode(arguments['SHUFFLE_MODE'] as ShuffleMode);
case SET_LOOP_MODE:
return setCustomLoopMode(arguments['LOOP_MODE'] as LoopMode);
case SHUFFLE_ALL:
return shuffleAll();
case MOVE_QUEUE_ITEM:
return moveQueueItem(arguments['OLD_INDEX'] as int, arguments['NEW_INDEX'] as int);
case REMOVE_QUEUE_ITEM:
return removeQueueIndex(arguments as int);
default:
}
}
Future<void> playWithContext(List<String> context, int index) async {
final songs = <SongModel>[];
for (final path in context) {
final song = await _musicDataSource.getSongByPath(path);
songs.add(song);
}
_audioPlayer.playSongList(songs, index);
}
Future<void> onAppLifecycleResumed() async {
// customEventSubject.add({SHUFFLE_MODE: shuffleMode});
// customEventSubject.add({KEY_INDEX: playbackIndex});
}
Future<void> setCustomShuffleMode(ShuffleMode mode) async {
_audioPlayer.setShuffleMode(mode, true);
}
Future<void> setCustomLoopMode(LoopMode mode) async {
_audioPlayer.setLoopMode(mode);
}
Future<void> shuffleAll() async {
_audioPlayer.setShuffleMode(ShuffleMode.plus, false);
final List<SongModel> songs = await _musicDataSource.getSongs();
final rng = Random();
final index = rng.nextInt(songs.length);
_audioPlayer.playSongList(songs, index);
}
Future<void> moveQueueItem(int oldIndex, int newIndex) async {
_audioPlayer.moveQueueItem(oldIndex, newIndex);
}
Future<void> removeQueueIndex(int index) async {
_audioPlayer.removeQueueIndex(index);
}
void _handleSetQueue(List<QueueItemModel> queue) {
_musicDataSource.setQueue(queue);
final mediaItems = queue.map((e) => e.song.toMediaItem()).toList();
queueSubject.add(mediaItems);
}
void _handlePlaybackEvent(PlaybackEventModel pe) {
if (pe.index != null) {
_musicDataSource.setCurrentIndex(pe.index);
customEventSubject.add({KEY_INDEX: pe.index});
}
if (pe.processingState == ProcessingState.ready) {
if (_audioPlayer.playingStream.value) {
playbackStateSubject.add(playbackState.value.copyWith(
controls: [MediaControl.skipToPrevious, MediaControl.pause, MediaControl.skipToNext],
playing: true,
processingState: AudioProcessingState.ready,
updatePosition: pe.updatePosition,
));
} else {
playbackStateSubject.add(playbackState.value.copyWith(
controls: [MediaControl.skipToPrevious, MediaControl.play, MediaControl.skipToNext],
processingState: AudioProcessingState.ready,
updatePosition: pe.updatePosition,
playing: false,
));
}
}
}
}