streaming edits
This commit is contained in:
parent
0a7af1d813
commit
db33f0764b
3 changed files with 62 additions and 15 deletions
|
|
@ -32,6 +32,7 @@ class PlaybackState {
|
|||
this.queue = const [],
|
||||
this.currentIndex,
|
||||
this.playing = false,
|
||||
this.buffering = false,
|
||||
this.position = Duration.zero,
|
||||
this.duration = Duration.zero,
|
||||
this.shuffle = false,
|
||||
|
|
@ -43,6 +44,13 @@ class PlaybackState {
|
|||
final List<Song> queue;
|
||||
final int? currentIndex;
|
||||
final bool playing;
|
||||
|
||||
/// True while the player is loading/buffering a source (not yet `ready`). A
|
||||
/// streamed source that is buffering legitimately reports position 0; this
|
||||
/// lets the UI show a spinner instead of a frozen 0:00 bar. Transient — never
|
||||
/// persisted.
|
||||
final bool buffering;
|
||||
|
||||
final Duration position;
|
||||
final Duration duration;
|
||||
final bool shuffle;
|
||||
|
|
@ -83,6 +91,7 @@ class PlaybackState {
|
|||
List<Song>? queue,
|
||||
int? currentIndex,
|
||||
bool? playing,
|
||||
bool? buffering,
|
||||
Duration? position,
|
||||
Duration? duration,
|
||||
bool? shuffle,
|
||||
|
|
@ -95,6 +104,7 @@ class PlaybackState {
|
|||
queue: queue ?? this.queue,
|
||||
currentIndex: currentIndex ?? this.currentIndex,
|
||||
playing: playing ?? this.playing,
|
||||
buffering: buffering ?? this.buffering,
|
||||
position: position ?? this.position,
|
||||
duration: duration ?? this.duration,
|
||||
shuffle: shuffle ?? this.shuffle,
|
||||
|
|
@ -215,7 +225,12 @@ class PlaybackController extends StateNotifier<PlaybackState>
|
|||
_maybeSlideWindow();
|
||||
});
|
||||
player.playerStateStream.listen((s) {
|
||||
state = state.copyWith(playing: s.playing);
|
||||
final ps = s.processingState;
|
||||
state = state.copyWith(
|
||||
playing: s.playing,
|
||||
buffering: ps == ProcessingState.loading ||
|
||||
ps == ProcessingState.buffering,
|
||||
);
|
||||
});
|
||||
player.positionStream.listen((p) {
|
||||
state = state.copyWith(position: p);
|
||||
|
|
@ -306,20 +321,32 @@ class PlaybackController extends StateNotifier<PlaybackState>
|
|||
|
||||
AudioSource _sourceFor(Song song) {
|
||||
final uri = _streamUriFor(song)!;
|
||||
if (!uri.isScheme('file')) _remoteSourceIds.add(song.id);
|
||||
final isRemote = !uri.isScheme('file');
|
||||
if (isRemote) _remoteSourceIds.add(song.id);
|
||||
final art = _coverArtUriFor(song);
|
||||
return AudioSource.uri(
|
||||
uri,
|
||||
tag: MediaItem(
|
||||
id: '${song.id}#${_tagSeq++}',
|
||||
title: song.title ?? 'Unknown',
|
||||
album: song.album,
|
||||
artist: song.artist,
|
||||
duration:
|
||||
song.duration != null ? Duration(seconds: song.duration!) : null,
|
||||
artUri: art,
|
||||
),
|
||||
final tag = MediaItem(
|
||||
id: '${song.id}#${_tagSeq++}',
|
||||
title: song.title ?? 'Unknown',
|
||||
album: song.album,
|
||||
artist: song.artist,
|
||||
duration:
|
||||
song.duration != null ? Duration(seconds: song.duration!) : null,
|
||||
artUri: art,
|
||||
);
|
||||
// Wrap remote streams in a caching source on mobile: it fetches bytes to an
|
||||
// OS-evictable temp file, giving the native player a genuinely seekable
|
||||
// source with a known length — robust against chunked transcodes that omit
|
||||
// Content-Length and against brief network drops. Downloads (file://) are
|
||||
// already seekable, and the media_kit desktop backend uses just_audio's
|
||||
// localhost proxy path we don't rely on, so both stay on the plain source.
|
||||
if (isRemote && (Platform.isAndroid || Platform.isIOS)) {
|
||||
// LockCachingAudioSource is marked experimental in just_audio but is
|
||||
// stable in practice; the streaming reliability it provides is the whole
|
||||
// point of this path.
|
||||
// ignore: experimental_member_use
|
||||
return LockCachingAudioSource(uri, tag: tag);
|
||||
}
|
||||
return AudioSource.uri(uri, tag: tag);
|
||||
}
|
||||
|
||||
/// Replace the queue with [songs] and start at [startIndex].
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue