loop mode, just_audio update
This commit is contained in:
parent
f6e025c017
commit
ac143220e6
12 changed files with 180 additions and 126 deletions
|
@ -1,22 +1,32 @@
|
||||||
class PlayerState {
|
class PlaybackEvent {
|
||||||
PlayerState(this.playing, this.processingState);
|
PlaybackEvent({
|
||||||
|
this.duration,
|
||||||
final bool playing;
|
this.index,
|
||||||
|
this.processingState,
|
||||||
|
this.updatePosition,
|
||||||
|
this.updateTime,
|
||||||
|
});
|
||||||
|
|
||||||
|
final Duration duration;
|
||||||
|
final int index;
|
||||||
final ProcessingState processingState;
|
final ProcessingState processingState;
|
||||||
|
final Duration updatePosition;
|
||||||
|
final DateTime updateTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Enumerates the different processing states of a player.
|
|
||||||
enum ProcessingState {
|
enum ProcessingState {
|
||||||
/// The player has not loaded an [AudioSource].
|
/// The player has not loaded an [AudioSource].
|
||||||
none,
|
none,
|
||||||
|
|
||||||
/// The player is loading an [AudioSource].
|
/// The player is loading an [AudioSource].
|
||||||
loading,
|
loading,
|
||||||
|
|
||||||
/// The player is buffering audio and unable to play.
|
/// The player is buffering audio and unable to play.
|
||||||
buffering,
|
buffering,
|
||||||
|
|
||||||
/// The player is has enough audio buffered and is able to play.
|
/// The player is has enough audio buffered and is able to play.
|
||||||
ready,
|
ready,
|
||||||
|
|
||||||
/// The player has reached the end of the audio.
|
/// The player has reached the end of the audio.
|
||||||
completed,
|
completed,
|
||||||
}
|
}
|
|
@ -106,7 +106,6 @@ abstract class _AudioStore with Store {
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> setLoopMode(LoopMode loopMode) async {
|
Future<void> setLoopMode(LoopMode loopMode) async {
|
||||||
print('setLoopMode');
|
|
||||||
_audioRepository.setLoopMode(loopMode);
|
_audioRepository.setLoopMode(loopMode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,9 +4,10 @@ import 'package:audio_service/audio_service.dart';
|
||||||
import 'package:logging/logging.dart';
|
import 'package:logging/logging.dart';
|
||||||
|
|
||||||
import '../../domain/entities/loop_mode.dart';
|
import '../../domain/entities/loop_mode.dart';
|
||||||
import '../../domain/entities/player_state.dart';
|
import '../../domain/entities/playback_event.dart';
|
||||||
import '../../domain/entities/shuffle_mode.dart';
|
import '../../domain/entities/shuffle_mode.dart';
|
||||||
import '../datasources/music_data_source_contract.dart';
|
import '../datasources/music_data_source_contract.dart';
|
||||||
|
import '../models/playback_event_model.dart';
|
||||||
import '../models/queue_item_model.dart';
|
import '../models/queue_item_model.dart';
|
||||||
import '../models/song_model.dart';
|
import '../models/song_model.dart';
|
||||||
import 'audio_player_contract.dart';
|
import 'audio_player_contract.dart';
|
||||||
|
@ -18,17 +19,16 @@ class MyAudioHandler extends BaseAudioHandler {
|
||||||
_handleSetQueue(event);
|
_handleSetQueue(event);
|
||||||
});
|
});
|
||||||
|
|
||||||
_audioPlayer.currentIndexStream.listen((event) => _handleIndexChange(event));
|
|
||||||
|
|
||||||
_audioPlayer.currentSongStream.listen((songModel) {
|
_audioPlayer.currentSongStream.listen((songModel) {
|
||||||
mediaItemSubject.add(songModel.toMediaItem());
|
mediaItemSubject.add(songModel.toMediaItem());
|
||||||
});
|
});
|
||||||
|
|
||||||
_audioPlayer.playerStateStream.listen((event) {
|
_audioPlayer.playbackEventStream.listen((event) {
|
||||||
_handlePlayerState(event);
|
_handlePlaybackEvent(event);
|
||||||
});
|
});
|
||||||
|
|
||||||
_audioPlayer.shuffleModeStream.listen((shuffleMode) {
|
_audioPlayer.shuffleModeStream.listen((shuffleMode) {
|
||||||
|
_musicDataSource.setShuffleMode(shuffleMode);
|
||||||
customEventSubject.add({SHUFFLE_MODE: shuffleMode});
|
customEventSubject.add({SHUFFLE_MODE: shuffleMode});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -40,6 +40,14 @@ class MyAudioHandler extends BaseAudioHandler {
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _initAudioPlayer() async {
|
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) {
|
if (_musicDataSource.queueStream != null && _musicDataSource.currentIndexStream != null) {
|
||||||
_audioPlayer.loadQueue(
|
_audioPlayer.loadQueue(
|
||||||
queue: await _musicDataSource.queueStream.first,
|
queue: await _musicDataSource.queueStream.first,
|
||||||
|
@ -56,7 +64,7 @@ class MyAudioHandler extends BaseAudioHandler {
|
||||||
@override
|
@override
|
||||||
Future<void> stop() async {
|
Future<void> stop() async {
|
||||||
await _audioPlayer.stop();
|
await _audioPlayer.stop();
|
||||||
// await _audioPlayer.dispose();
|
await _audioPlayer.dispose();
|
||||||
await super.stop();
|
await super.stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -128,7 +136,6 @@ class MyAudioHandler extends BaseAudioHandler {
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> setCustomLoopMode(LoopMode mode) async {
|
Future<void> setCustomLoopMode(LoopMode mode) async {
|
||||||
|
|
||||||
_audioPlayer.setLoopMode(mode);
|
_audioPlayer.setLoopMode(mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -151,48 +158,34 @@ class MyAudioHandler extends BaseAudioHandler {
|
||||||
}
|
}
|
||||||
|
|
||||||
void _handleSetQueue(List<QueueItemModel> queue) {
|
void _handleSetQueue(List<QueueItemModel> queue) {
|
||||||
print('handleSetQueue');
|
|
||||||
_musicDataSource.setQueue(queue);
|
_musicDataSource.setQueue(queue);
|
||||||
|
|
||||||
final mediaItems = queue.map((e) => e.song.toMediaItem()).toList();
|
final mediaItems = queue.map((e) => e.song.toMediaItem()).toList();
|
||||||
queueSubject.add(mediaItems);
|
queueSubject.add(mediaItems);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _handleIndexChange(int index) {
|
void _handlePlaybackEvent(PlaybackEventModel pe) {
|
||||||
_log.info('index: $index');
|
if (pe.index != null) {
|
||||||
if (index != null) {
|
_musicDataSource.setCurrentIndex(pe.index);
|
||||||
_musicDataSource.setCurrentIndex(index);
|
customEventSubject.add({KEY_INDEX: pe.index});
|
||||||
|
|
||||||
customEventSubject.add({KEY_INDEX: index});
|
|
||||||
playbackStateSubject.add(playbackState.value.copyWith(
|
|
||||||
controls: [
|
|
||||||
MediaControl.skipToPrevious,
|
|
||||||
MediaControl.pause,
|
|
||||||
MediaControl.skipToNext,
|
|
||||||
],
|
|
||||||
playing: _audioPlayer.playerStateStream.value.playing,
|
|
||||||
processingState: AudioProcessingState.ready,
|
|
||||||
updatePosition: const Duration(milliseconds: 0), // _audioPlayer.positionStream.value,
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void _handlePlayerState(PlayerState ps) {
|
if (pe.processingState == ProcessingState.ready) {
|
||||||
_log.info('handlePlayerState called');
|
if (_audioPlayer.playingStream.value) {
|
||||||
if (ps.processingState == ProcessingState.ready && ps.playing) {
|
playbackStateSubject.add(playbackState.value.copyWith(
|
||||||
playbackStateSubject.add(playbackState.value.copyWith(
|
controls: [MediaControl.skipToPrevious, MediaControl.pause, MediaControl.skipToNext],
|
||||||
controls: [MediaControl.skipToPrevious, MediaControl.pause, MediaControl.skipToNext],
|
playing: true,
|
||||||
playing: true,
|
processingState: AudioProcessingState.ready,
|
||||||
processingState: AudioProcessingState.ready,
|
updatePosition: pe.updatePosition,
|
||||||
updatePosition: _audioPlayer.positionStream.value,
|
));
|
||||||
));
|
} else {
|
||||||
} else if (ps.processingState == ProcessingState.ready && !ps.playing) {
|
playbackStateSubject.add(playbackState.value.copyWith(
|
||||||
playbackStateSubject.add(playbackState.value.copyWith(
|
controls: [MediaControl.skipToPrevious, MediaControl.play, MediaControl.skipToNext],
|
||||||
controls: [MediaControl.skipToPrevious, MediaControl.play, MediaControl.skipToNext],
|
processingState: AudioProcessingState.ready,
|
||||||
processingState: AudioProcessingState.ready,
|
updatePosition: pe.updatePosition,
|
||||||
updatePosition: _audioPlayer.positionStream.value,
|
playing: false,
|
||||||
playing: false,
|
));
|
||||||
));
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -118,7 +118,6 @@ class AudioManagerImpl implements AudioManager {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> setLoopMode(LoopMode loopMode) async {
|
Future<void> setLoopMode(LoopMode loopMode) async {
|
||||||
print('setLoopMode!!');
|
|
||||||
await _audioHandler.customAction(SET_LOOP_MODE, {'LOOP_MODE': loopMode});
|
await _audioHandler.customAction(SET_LOOP_MODE, {'LOOP_MODE': loopMode});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,14 +2,15 @@ import 'package:rxdart/rxdart.dart';
|
||||||
|
|
||||||
import '../../domain/entities/loop_mode.dart';
|
import '../../domain/entities/loop_mode.dart';
|
||||||
import '../../domain/entities/shuffle_mode.dart';
|
import '../../domain/entities/shuffle_mode.dart';
|
||||||
import '../models/player_state_model.dart';
|
import '../models/playback_event_model.dart';
|
||||||
import '../models/queue_item_model.dart';
|
import '../models/queue_item_model.dart';
|
||||||
import '../models/song_model.dart';
|
import '../models/song_model.dart';
|
||||||
|
|
||||||
abstract class AudioPlayer {
|
abstract class AudioPlayer {
|
||||||
ValueStream<int> get currentIndexStream;
|
ValueStream<int> get currentIndexStream;
|
||||||
ValueStream<SongModel> get currentSongStream;
|
ValueStream<SongModel> get currentSongStream;
|
||||||
ValueStream<PlayerStateModel> get playerStateStream;
|
ValueStream<PlaybackEventModel> get playbackEventStream;
|
||||||
|
ValueStream<bool> get playingStream;
|
||||||
ValueStream<Duration> get positionStream;
|
ValueStream<Duration> get positionStream;
|
||||||
ValueStream<List<QueueItemModel>> get queueStream;
|
ValueStream<List<QueueItemModel>> get queueStream;
|
||||||
ValueStream<ShuffleMode> get shuffleModeStream;
|
ValueStream<ShuffleMode> get shuffleModeStream;
|
||||||
|
|
|
@ -5,7 +5,7 @@ import '../../domain/entities/loop_mode.dart';
|
||||||
import '../../domain/entities/queue_item.dart';
|
import '../../domain/entities/queue_item.dart';
|
||||||
import '../../domain/entities/shuffle_mode.dart';
|
import '../../domain/entities/shuffle_mode.dart';
|
||||||
import '../models/loop_mode_model.dart';
|
import '../models/loop_mode_model.dart';
|
||||||
import '../models/player_state_model.dart';
|
import '../models/playback_event_model.dart';
|
||||||
import '../models/queue_item_model.dart';
|
import '../models/queue_item_model.dart';
|
||||||
import '../models/song_model.dart';
|
import '../models/song_model.dart';
|
||||||
import 'audio_player_contract.dart';
|
import 'audio_player_contract.dart';
|
||||||
|
@ -14,24 +14,31 @@ import 'queue_generator.dart';
|
||||||
class AudioPlayerImpl implements AudioPlayer {
|
class AudioPlayerImpl implements AudioPlayer {
|
||||||
AudioPlayerImpl(this._audioPlayer, this._queueGenerator) {
|
AudioPlayerImpl(this._audioPlayer, this._queueGenerator) {
|
||||||
_audioPlayer.currentIndexStream.listen((event) {
|
_audioPlayer.currentIndexStream.listen((event) {
|
||||||
|
print('currentIndex: $event');
|
||||||
_currentIndexSubject.add(event);
|
_currentIndexSubject.add(event);
|
||||||
_currentSongSubject.add(_queueSubject.value[event].song);
|
if (_queueSubject.value != null) {
|
||||||
|
_currentSongSubject.add(_queueSubject.value[event].song);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
_audioPlayer.playingStream.listen((event) => _playingSubject.add(event));
|
||||||
|
|
||||||
|
_audioPlayer.playbackEventStream.listen((event) {
|
||||||
|
_playbackEventSubject.add(PlaybackEventModel.fromJAPlaybackEvent(event));
|
||||||
});
|
});
|
||||||
|
|
||||||
_audioPlayer.positionStream.listen((event) {
|
_audioPlayer.positionStream.listen((event) {
|
||||||
_positionSubject.add(event);
|
_positionSubject.add(event);
|
||||||
});
|
});
|
||||||
|
|
||||||
_audioPlayer.playerStateStream.listen((event) {
|
|
||||||
_playerStateSubject.add(PlayerStateModel.fromJAPlayerState(event));
|
|
||||||
});
|
|
||||||
|
|
||||||
_audioPlayer.loopModeStream.listen((event) {
|
_audioPlayer.loopModeStream.listen((event) {
|
||||||
_loopModeSubject.add(event.toEntity());
|
_loopModeSubject.add(event.toEntity());
|
||||||
});
|
});
|
||||||
|
|
||||||
_queueSubject.listen((event) {
|
_queueSubject.listen((event) {
|
||||||
_currentSongSubject.add(event[_currentIndexSubject.value].song);
|
if (_currentIndexSubject.value != null) {
|
||||||
|
_currentSongSubject.add(event[_currentIndexSubject.value].song);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -44,7 +51,8 @@ class AudioPlayerImpl implements AudioPlayer {
|
||||||
|
|
||||||
final BehaviorSubject<int> _currentIndexSubject = BehaviorSubject();
|
final BehaviorSubject<int> _currentIndexSubject = BehaviorSubject();
|
||||||
final BehaviorSubject<SongModel> _currentSongSubject = BehaviorSubject();
|
final BehaviorSubject<SongModel> _currentSongSubject = BehaviorSubject();
|
||||||
final BehaviorSubject<PlayerStateModel> _playerStateSubject = BehaviorSubject();
|
final BehaviorSubject<PlaybackEventModel> _playbackEventSubject = BehaviorSubject();
|
||||||
|
final BehaviorSubject<bool> _playingSubject = BehaviorSubject();
|
||||||
final BehaviorSubject<Duration> _positionSubject = BehaviorSubject();
|
final BehaviorSubject<Duration> _positionSubject = BehaviorSubject();
|
||||||
final BehaviorSubject<List<QueueItemModel>> _queueSubject = BehaviorSubject();
|
final BehaviorSubject<List<QueueItemModel>> _queueSubject = BehaviorSubject();
|
||||||
final BehaviorSubject<ShuffleMode> _shuffleModeSubject = BehaviorSubject.seeded(ShuffleMode.none);
|
final BehaviorSubject<ShuffleMode> _shuffleModeSubject = BehaviorSubject.seeded(ShuffleMode.none);
|
||||||
|
@ -57,11 +65,14 @@ class AudioPlayerImpl implements AudioPlayer {
|
||||||
ValueStream<SongModel> get currentSongStream => _currentSongSubject.stream;
|
ValueStream<SongModel> get currentSongStream => _currentSongSubject.stream;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
ValueStream<PlayerStateModel> get playerStateStream => _playerStateSubject.stream;
|
ValueStream<PlaybackEventModel> get playbackEventStream => _playbackEventSubject.stream;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
ValueStream<Duration> get positionStream => _positionSubject.stream;
|
ValueStream<Duration> get positionStream => _positionSubject.stream;
|
||||||
|
|
||||||
|
@override
|
||||||
|
ValueStream<bool> get playingStream => _playingSubject.stream;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
ValueStream<List<QueueItemModel>> get queueStream => _queueSubject.stream;
|
ValueStream<List<QueueItemModel>> get queueStream => _queueSubject.stream;
|
||||||
|
|
||||||
|
@ -75,7 +86,7 @@ class AudioPlayerImpl implements AudioPlayer {
|
||||||
Future<void> dispose() async {
|
Future<void> dispose() async {
|
||||||
await _currentIndexSubject.close();
|
await _currentIndexSubject.close();
|
||||||
await _currentSongSubject.close();
|
await _currentSongSubject.close();
|
||||||
await _playerStateSubject.close();
|
await _playbackEventSubject.close();
|
||||||
await _positionSubject.close();
|
await _positionSubject.close();
|
||||||
await _queueSubject.close();
|
await _queueSubject.close();
|
||||||
await _shuffleModeSubject.close();
|
await _shuffleModeSubject.close();
|
||||||
|
@ -85,11 +96,16 @@ class AudioPlayerImpl implements AudioPlayer {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> loadQueue({List<QueueItemModel> queue, int startIndex = 0}) async {
|
Future<void> loadQueue({List<QueueItemModel> queue, int startIndex = 0}) async {
|
||||||
if (queue == null || queue.isEmpty) {
|
if (queue == null || queue.isEmpty ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (startIndex >= queue.length) {
|
||||||
|
print('$startIndex >= ${queue.length}');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_audioSource = _queueGenerator.songModelsToAudioSource([queue[startIndex].song]);
|
_audioSource = _queueGenerator.songModelsToAudioSource([queue[startIndex].song]);
|
||||||
await _audioPlayer.load(_audioSource);
|
await _audioPlayer.setAudioSource(_audioSource);
|
||||||
|
// await _audioPlayer.load();
|
||||||
|
|
||||||
final songModelQueue = queue.map((e) => e.song).toList();
|
final songModelQueue = queue.map((e) => e.song).toList();
|
||||||
_queueSubject.add(queue);
|
_queueSubject.add(queue);
|
||||||
|
@ -115,11 +131,11 @@ class AudioPlayerImpl implements AudioPlayer {
|
||||||
Future<void> playSongList(List<SongModel> songs, int startIndex) async {
|
Future<void> playSongList(List<SongModel> songs, int startIndex) async {
|
||||||
_inputQueue = songs;
|
_inputQueue = songs;
|
||||||
|
|
||||||
final firstSong = songs[startIndex]; // .sublist(startIndex, startIndex + 1);
|
final firstSong = songs[startIndex];
|
||||||
_queueSubject.add([QueueItemModel(firstSong, originalIndex: startIndex)]);
|
_queueSubject.add([QueueItemModel(firstSong, originalIndex: startIndex)]);
|
||||||
_audioSource = _queueGenerator.songModelsToAudioSource([firstSong]);
|
_audioSource = _queueGenerator.songModelsToAudioSource([firstSong]);
|
||||||
|
await _audioPlayer.setAudioSource(_audioSource);
|
||||||
_audioPlayer.play();
|
_audioPlayer.play();
|
||||||
await _audioPlayer.load(_audioSource, initialIndex: 0);
|
|
||||||
|
|
||||||
_queue = await _queueGenerator.generateQueue(_shuffleModeSubject.value, songs, startIndex);
|
_queue = await _queueGenerator.generateQueue(_shuffleModeSubject.value, songs, startIndex);
|
||||||
final songModelQueue = _queue.map((e) => e.song).toList();
|
final songModelQueue = _queue.map((e) => e.song).toList();
|
||||||
|
@ -127,7 +143,7 @@ class AudioPlayerImpl implements AudioPlayer {
|
||||||
|
|
||||||
final int splitIndex = _shuffleModeSubject.value == ShuffleMode.none ? startIndex : 0;
|
final int splitIndex = _shuffleModeSubject.value == ShuffleMode.none ? startIndex : 0;
|
||||||
final newQueue = _queueGenerator.songModelsToAudioSource(songModelQueue);
|
final newQueue = _queueGenerator.songModelsToAudioSource(songModelQueue);
|
||||||
_audioSource.insertAll(0, newQueue.children.sublist(0, splitIndex));
|
await _audioSource.insertAll(0, newQueue.children.sublist(0, splitIndex));
|
||||||
_audioSource.addAll(newQueue.children.sublist(splitIndex + 1, newQueue.length));
|
_audioSource.addAll(newQueue.children.sublist(splitIndex + 1, newQueue.length));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -176,6 +192,7 @@ class AudioPlayerImpl implements AudioPlayer {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> setShuffleMode(ShuffleMode shuffleMode, bool updateQueue) async {
|
Future<void> setShuffleMode(ShuffleMode shuffleMode, bool updateQueue) async {
|
||||||
|
if (shuffleMode == null) return;
|
||||||
_shuffleModeSubject.add(shuffleMode);
|
_shuffleModeSubject.add(shuffleMode);
|
||||||
|
|
||||||
if (updateQueue) {
|
if (updateQueue) {
|
||||||
|
@ -193,11 +210,11 @@ class AudioPlayerImpl implements AudioPlayer {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> setLoopMode(LoopMode loopMode) async {
|
Future<void> setLoopMode(LoopMode loopMode) async {
|
||||||
print('ap loopmode');
|
if (loopMode == null) return;
|
||||||
await _audioPlayer.setLoopMode(loopMode.toJA());
|
await _audioPlayer.setLoopMode(loopMode.toJA());
|
||||||
}
|
}
|
||||||
|
|
||||||
void _updateQueue(ja.ConcatenatingAudioSource newQueue, QueueItem currentQueueItem) {
|
Future<void> _updateQueue(ja.ConcatenatingAudioSource newQueue, QueueItem currentQueueItem) async {
|
||||||
final int index = currentQueueItem.originalIndex;
|
final int index = currentQueueItem.originalIndex;
|
||||||
|
|
||||||
_audioSource.removeRange(0, _currentIndexSubject.value);
|
_audioSource.removeRange(0, _currentIndexSubject.value);
|
||||||
|
@ -207,15 +224,15 @@ class AudioPlayerImpl implements AudioPlayer {
|
||||||
switch (currentQueueItem.type) {
|
switch (currentQueueItem.type) {
|
||||||
case QueueItemType.added:
|
case QueueItemType.added:
|
||||||
case QueueItemType.standard:
|
case QueueItemType.standard:
|
||||||
_audioSource.insertAll(0, newQueue.children.sublist(0, index));
|
await _audioSource.insertAll(0, newQueue.children.sublist(0, index));
|
||||||
_audioSource.addAll(newQueue.children.sublist(index + 1));
|
_audioSource.addAll(newQueue.children.sublist(index + 1));
|
||||||
break;
|
break;
|
||||||
case QueueItemType.predecessor:
|
case QueueItemType.predecessor:
|
||||||
_audioSource.insertAll(0, newQueue.children.sublist(0, index));
|
await _audioSource.insertAll(0, newQueue.children.sublist(0, index));
|
||||||
_audioSource.addAll(newQueue.children.sublist(index));
|
_audioSource.addAll(newQueue.children.sublist(index));
|
||||||
break;
|
break;
|
||||||
case QueueItemType.successor:
|
case QueueItemType.successor:
|
||||||
_audioSource.insertAll(0, newQueue.children.sublist(0, index + 1));
|
await _audioSource.insertAll(0, newQueue.children.sublist(0, index + 1));
|
||||||
_audioSource.addAll(newQueue.children.sublist(index + 1));
|
_audioSource.addAll(newQueue.children.sublist(index + 1));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,7 @@ import '../models/album_model.dart';
|
||||||
import '../models/artist_model.dart';
|
import '../models/artist_model.dart';
|
||||||
import '../models/loop_mode_model.dart';
|
import '../models/loop_mode_model.dart';
|
||||||
import '../models/queue_item_model.dart';
|
import '../models/queue_item_model.dart';
|
||||||
|
import '../models/shuffle_mode_model.dart';
|
||||||
import '../models/song_model.dart';
|
import '../models/song_model.dart';
|
||||||
import 'music_data_source_contract.dart';
|
import 'music_data_source_contract.dart';
|
||||||
|
|
||||||
|
@ -242,7 +243,6 @@ class MoorMusicDataSource extends _$MoorMusicDataSource implements MusicDataSour
|
||||||
.join([innerJoin(songs, songs.path.equalsExp(queueEntries.path))]);
|
.join([innerJoin(songs, songs.path.equalsExp(queueEntries.path))]);
|
||||||
|
|
||||||
return query.watch().map((rows) {
|
return query.watch().map((rows) {
|
||||||
print('rows: ${rows.length}');
|
|
||||||
return rows.map((row) => SongModel.fromMoorSong(row.readTable(songs))).toList();
|
return rows.map((row) => SongModel.fromMoorSong(row.readTable(songs))).toList();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -265,7 +265,6 @@ class MoorMusicDataSource extends _$MoorMusicDataSource implements MusicDataSour
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> setQueue(List<QueueItemModel> queue) async {
|
Future<void> setQueue(List<QueueItemModel> queue) async {
|
||||||
print('setQueue');
|
|
||||||
final _queueEntries = <Insertable<MoorQueueEntry>>[];
|
final _queueEntries = <Insertable<MoorQueueEntry>>[];
|
||||||
|
|
||||||
for (var i = 0; i < queue.length; i++) {
|
for (var i = 0; i < queue.length; i++) {
|
||||||
|
@ -290,7 +289,6 @@ class MoorMusicDataSource extends _$MoorMusicDataSource implements MusicDataSour
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> setCurrentIndex(int index) async {
|
Future<void> setCurrentIndex(int index) async {
|
||||||
print('setCurrentIndex: $index');
|
|
||||||
final currentState = await select(playerState).getSingle();
|
final currentState = await select(playerState).getSingle();
|
||||||
if (currentState != null) {
|
if (currentState != null) {
|
||||||
update(playerState).write(PlayerStateCompanion(index: Value(index)));
|
update(playerState).write(PlayerStateCompanion(index: Value(index)));
|
||||||
|
@ -306,7 +304,6 @@ class MoorMusicDataSource extends _$MoorMusicDataSource implements MusicDataSour
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> setLoopMode(LoopMode loopMode) async {
|
Future<void> setLoopMode(LoopMode loopMode) async {
|
||||||
print('setLoopMode!!!');
|
|
||||||
final currentState = await select(playerState).getSingle();
|
final currentState = await select(playerState).getSingle();
|
||||||
if (currentState != null) {
|
if (currentState != null) {
|
||||||
update(playerState).write(PlayerStateCompanion(loopMode: Value(loopMode.toInt())));
|
update(playerState).write(PlayerStateCompanion(loopMode: Value(loopMode.toInt())));
|
||||||
|
@ -316,14 +313,19 @@ class MoorMusicDataSource extends _$MoorMusicDataSource implements MusicDataSour
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> setShuffleMode(ShuffleMode shuffleMode) {
|
Future<void> setShuffleMode(ShuffleMode shuffleMode) async {
|
||||||
// TODO: implement setShuffleMode
|
final currentState = await select(playerState).getSingle();
|
||||||
throw UnimplementedError();
|
if (currentState != null) {
|
||||||
|
update(playerState).write(PlayerStateCompanion(shuffleMode: Value(shuffleMode.toInt())));
|
||||||
|
} else {
|
||||||
|
into(playerState).insert(PlayerStateCompanion(shuffleMode: Value(shuffleMode.toInt())));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
// TODO: implement shuffleModeStream
|
Stream<ShuffleMode> get shuffleModeStream {
|
||||||
Stream<ShuffleMode> get shuffleModeStream => throw UnimplementedError();
|
return select(playerState).watchSingle().map((event) => event.shuffleMode.toShuffleMode());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LazyDatabase _openConnection() {
|
LazyDatabase _openConnection() {
|
||||||
|
|
|
@ -1,15 +1,29 @@
|
||||||
import 'package:just_audio/just_audio.dart' as ja;
|
import 'package:just_audio/just_audio.dart' as ja;
|
||||||
|
|
||||||
import '../../domain/entities/player_state.dart';
|
import '../../domain/entities/playback_event.dart';
|
||||||
|
|
||||||
class PlayerStateModel extends PlayerState {
|
class PlaybackEventModel extends PlaybackEvent {
|
||||||
PlayerStateModel(bool playing, ProcessingState processingState)
|
PlaybackEventModel({
|
||||||
: super(playing, processingState);
|
Duration duration,
|
||||||
|
int index,
|
||||||
|
ProcessingState processingState,
|
||||||
|
Duration updatePosition,
|
||||||
|
DateTime updateTime,
|
||||||
|
}) : super(
|
||||||
|
duration: duration,
|
||||||
|
index: index,
|
||||||
|
processingState: processingState,
|
||||||
|
updatePosition: updatePosition,
|
||||||
|
updateTime: updateTime,
|
||||||
|
);
|
||||||
|
|
||||||
factory PlayerStateModel.fromJAPlayerState(ja.PlayerState playerState) =>
|
factory PlaybackEventModel.fromJAPlaybackEvent(ja.PlaybackEvent playbackEvent) =>
|
||||||
PlayerStateModel(
|
PlaybackEventModel(
|
||||||
playerState.playing,
|
duration: playbackEvent.duration,
|
||||||
playerState.processingState.toProcessingState(),
|
index: playbackEvent.currentIndex,
|
||||||
|
processingState: playbackEvent.processingState.toProcessingState(),
|
||||||
|
updatePosition: playbackEvent.updatePosition,
|
||||||
|
updateTime: playbackEvent.updateTime,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
29
lib/system/models/shuffle_mode_model.dart
Normal file
29
lib/system/models/shuffle_mode_model.dart
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
|
||||||
|
import '../../domain/entities/shuffle_mode.dart';
|
||||||
|
|
||||||
|
|
||||||
|
extension ShuffleModeToInt on ShuffleMode {
|
||||||
|
int toInt() {
|
||||||
|
switch(this) {
|
||||||
|
case ShuffleMode.standard:
|
||||||
|
return 1;
|
||||||
|
case ShuffleMode.plus:
|
||||||
|
return 2;
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension IntToShuffleMode on int {
|
||||||
|
ShuffleMode toShuffleMode() {
|
||||||
|
switch(this) {
|
||||||
|
case 1:
|
||||||
|
return ShuffleMode.standard;
|
||||||
|
case 2:
|
||||||
|
return ShuffleMode.plus;
|
||||||
|
default:
|
||||||
|
return ShuffleMode.none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -101,7 +101,6 @@ class AudioRepositoryImpl implements AudioRepository {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> setLoopMode(LoopMode loopMode) async {
|
Future<void> setLoopMode(LoopMode loopMode) async {
|
||||||
print('setLoopMode!');
|
|
||||||
await _audioManager.setLoopMode(loopMode);
|
await _audioManager.setLoopMode(loopMode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
52
pubspec.lock
52
pubspec.lock
|
@ -7,18 +7,18 @@ packages:
|
||||||
name: _fe_analyzer_shared
|
name: _fe_analyzer_shared
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "7.0.0"
|
version: "12.0.0"
|
||||||
analyzer:
|
analyzer:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: analyzer
|
name: analyzer
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.39.17"
|
version: "0.40.6"
|
||||||
analyzer_plugin:
|
analyzer_plugin_fork:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: analyzer_plugin
|
name: analyzer_plugin_fork
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.3.0"
|
version: "0.3.0"
|
||||||
|
@ -65,7 +65,7 @@ packages:
|
||||||
name: build
|
name: build
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.3.0"
|
version: "1.5.2"
|
||||||
build_config:
|
build_config:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -86,21 +86,21 @@ packages:
|
||||||
name: build_resolvers
|
name: build_resolvers
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.3.11"
|
version: "1.4.4"
|
||||||
build_runner:
|
build_runner:
|
||||||
dependency: "direct dev"
|
dependency: "direct dev"
|
||||||
description:
|
description:
|
||||||
name: build_runner
|
name: build_runner
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.10.2"
|
version: "1.10.11"
|
||||||
build_runner_core:
|
build_runner_core:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: build_runner_core
|
name: build_runner_core
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "6.0.1"
|
version: "6.0.3"
|
||||||
built_collection:
|
built_collection:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -178,20 +178,13 @@ packages:
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.1.5"
|
version: "2.1.5"
|
||||||
csslib:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: csslib
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "0.16.2"
|
|
||||||
dart_style:
|
dart_style:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: dart_style
|
name: dart_style
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.3.6"
|
version: "1.3.10"
|
||||||
dartz:
|
dartz:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
|
@ -319,13 +312,6 @@ packages:
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.2.0"
|
version: "0.2.0"
|
||||||
html:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: html
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "0.14.0+4"
|
|
||||||
http:
|
http:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -378,24 +364,26 @@ packages:
|
||||||
just_audio:
|
just_audio:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: just_audio
|
path: just_audio
|
||||||
url: "https://pub.dartlang.org"
|
ref: HEAD
|
||||||
source: hosted
|
resolved-ref: "62c369527f749ff06428c8de26d318e77e803cdf"
|
||||||
version: "0.5.7"
|
url: "https://github.com/ryanheise/just_audio.git"
|
||||||
|
source: git
|
||||||
|
version: "0.6.1"
|
||||||
just_audio_platform_interface:
|
just_audio_platform_interface:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: just_audio_platform_interface
|
name: just_audio_platform_interface
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.1.1"
|
version: "2.0.0"
|
||||||
just_audio_web:
|
just_audio_web:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: just_audio_web
|
name: just_audio_web
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.1.1"
|
version: "0.2.0"
|
||||||
logging:
|
logging:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
|
@ -439,7 +427,7 @@ packages:
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.1.2"
|
version: "1.1.2"
|
||||||
mockito:
|
mockito:
|
||||||
dependency: "direct main"
|
dependency: "direct dev"
|
||||||
description:
|
description:
|
||||||
name: mockito
|
name: mockito
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
|
@ -458,7 +446,7 @@ packages:
|
||||||
name: moor_generator
|
name: moor_generator
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.3.1"
|
version: "3.4.0"
|
||||||
nested:
|
nested:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -673,7 +661,7 @@ packages:
|
||||||
name: sqlparser
|
name: sqlparser
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.10.1"
|
version: "0.11.0"
|
||||||
stack_trace:
|
stack_trace:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|
11
pubspec.yaml
11
pubspec.yaml
|
@ -21,10 +21,12 @@ dependencies:
|
||||||
flutter_audio_query: ^0.3.5
|
flutter_audio_query: ^0.3.5
|
||||||
flutter_mobx: ^1.1.0
|
flutter_mobx: ^1.1.0
|
||||||
get_it: ^4.0.2
|
get_it: ^4.0.2
|
||||||
just_audio: ^0.5.0
|
just_audio: # ^0.6.1
|
||||||
|
git:
|
||||||
|
url: https://github.com/ryanheise/just_audio.git
|
||||||
|
path: just_audio
|
||||||
logging: ^0.11.4
|
logging: ^0.11.4
|
||||||
mobx: ^1.1.1
|
mobx: ^1.1.1
|
||||||
mockito: ^4.1.1
|
|
||||||
moor: ^3.0.2
|
moor: ^3.0.2
|
||||||
# moor_ffi: ^0.5.0
|
# moor_ffi: ^0.5.0
|
||||||
path:
|
path:
|
||||||
|
@ -33,11 +35,12 @@ dependencies:
|
||||||
sqlite3_flutter_libs: ^0.2.0
|
sqlite3_flutter_libs: ^0.2.0
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
build_runner: 1.10.2
|
build_runner: 1.10.11
|
||||||
flutter_test:
|
flutter_test:
|
||||||
sdk: flutter
|
sdk: flutter
|
||||||
mobx_codegen: ^1.0.3
|
mobx_codegen: ^1.0.3
|
||||||
moor_generator: ^3.0.0
|
mockito: ^4.1.1
|
||||||
|
moor_generator: ^3.4.0
|
||||||
|
|
||||||
|
|
||||||
# For information on the generic Dart part of this file, see the
|
# For information on the generic Dart part of this file, see the
|
||||||
|
|
Loading…
Add table
Reference in a new issue