Inconsistent SequenceState -> RangeError on accessing `effectiveSequence`
Which API doesn't behave as documented, and how does it misbehave?
The sequenceStateStream emits inconsistent SequenceState instances.
When I switch between two shuffled playlists (ConcatenatingAudioSource) the sequenceStateStream emits a SequenceState where calling effectiveSequence will throw when the new AudioSource is shorter than the old one.
This is because the SequenceState.shuffleIndices will still contain the old indices (in my case 164) and SequenceState.sequence the actual new AudioSources (in my case 48). When using the shuffleIndices.map((i) => sequence[i]) this will result in an error like this:
RangeError (RangeError (index): Invalid value: Not in inclusive range 0..47: 91)
Minimal reproduction project My play function boils down to this (without any UI code):
/// Play a list of [Song] optionally starting at [initial] **OR** [shuffle]d
/// from [source] list
///
/// Internally used to reduce code duplication
Future<void> _play(
List<Song> songs, {
String? source,
int? initial,
bool shuffle = false,
}) async {
// Only initial song OR shuffled is allowed
assert((initial == null && shuffle) || (initial != null && !shuffle));
// Generate AudioSource's from Song's
final audioSources = _songsToAudiSources(
songs,
source: source,
shuffled: shuffle,
);
// Handle shuffle (we need to shuffle the audioSources directly because the
// first song would always stay the same) (it would stay to allow manual
// selection of single song while in shuffle mode)
if (shuffle) audioSources.shuffle();
await player.setShuffleModeEnabled(shuffle);
// Prepare playlist
final playlist = ConcatenatingAudioSource(
useLazyPreparation: true,
shuffleOrder: DefaultShuffleOrder(),
children: audioSources,
);
// Set playlist and play
await player.setAudioSource(
playlist,
initialIndex: initial,
initialPosition: Duration.zero,
);
// ignore: unawaited_futures
player.play();
My sequenceStateStream callback (attached using .listen:
@action // <--- I am using MobX, but this should not result in an inconsistent `SequenceState` where all fields are `final`
void setSequenceState(SequenceState? sequenceState) {
if (sequenceState == null) {
return;
}
effectiveSequence = sequenceState.effectiveSequence; // <--- This will throw!
// ...
}
To Reproduce (i.e. user steps, not code) Steps to reproduce the behavior:
- Play a number of songs shuffled
- Play another smaller number of songs shuffled
- Access
SequenceState.effectiveSequencein a callback attached tosequenceStateStream
Error messages
RangeError (RangeError (index): Invalid value: Not in inclusive range 0..47: 91)
Expected behavior
The SequenceState is consistent and the shuffleIndices match sequence.
Screenshots N.a.
Smartphone (please complete the following information):
- Device: iPhone 14 Pro Max
- OS: iOS 14.6
Flutter SDK version
[✓] Flutter (Channel stable, 3.7.8, on macOS 12.5.1 21G83 darwin-x64, locale de-DE)
[✗] Android toolchain - develop for Android devices
✗ Unable to locate Android SDK.
Install Android Studio from: https://developer.android.com/studio/index.html
On first launch it will assist you in installing the Android SDK components.
(or visit https://flutter.dev/docs/get-started/install/macos#android-setup for detailed instructions).
If the Android SDK has been installed to a custom location, please use
`flutter config --android-sdk` to update to that location.
[✓] Xcode - develop for iOS and macOS (Xcode 14.1)
[!] Android Studio (not installed)
[✓] VS Code (version 1.78.0)
[✓] Connected device (1 available)
! Error: IOS is busy: Fetching debug symbols for IOS. Xcode will continue when IOS is finished. (code -10)
[✓] HTTP Host Availability
! Doctor found issues in 2 categories.
@Coronon Have you found a workaround for this issue? I get the same error when trying to load a new playlist.
This bug report doesn't have a minimal reproduction project (as per the instructions). Who would like to provide one?
No, sadly I have not :( My app is currently in maintenance mode and not really being actively developed right now. I also currently don't have the time to build a minimal reproducible example - sorry.
@ryanheise I've created a demo project where you can see this issue.
https://github.com/kaciula/just_audio_sequence_bug
Start playing the long shuffled playlist first and then start playing the short shuffled playlist and you'll see the error in the logs. It happens on both Android and iOS.
Let me know if you need anything else from me.
@ryanheise Please let me know if you intend to work on this issue in the near future based on the demo project I've linked above. I want to know if I should switch to implementing my own shuffle logic to avoid this bug.
It turns out that even a manual shuffle logic does not resolve this issue. Rearranging tracks from a playlist triggers a similar bug in just_audio_background plugin.
[RangeError (index): Invalid value: Only valid value is 0: 7] #0 List.[] (dart:core-patch/growable_array.dart:264:36) #1 AudioSourceExtension.shuffleIndices (package:just_audio_background/just_audio_background.dart:904:40) #2 _PlayerAudioHandler._updateShuffleIndices (package:just_audio_background/just_audio_background.dart:589:32) #3 _PlayerAudioHandler.customConcatenatingRemoveRange (package:just_audio_background/just_audio_background.dart:524:5) #4 _JustAudioPlayer.concatenatingRemoveRange (package:just_audio_background/just_audio_background.dart:306:27) #5 ConcatenatingAudioSource.removeRange (package:just_audio/just_audio.dart:2644:40) <asynchronous suspension>
I'm having this problem, is there any solution?