-
Notifications
You must be signed in to change notification settings - Fork 174
Stop streamed songs from wedging the player on weak connections #209
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
2 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🗄️ Data Integrity & Integration | 🟠 Major
🧩 Analysis chain
🌐 Web query:
just_audio setUrl call not cancelled by stop, late completion replaces current audio source💡 Result:
In just_audio, calling setUrl is an asynchronous operation that initiates a load process [1][2]. If a previous call to setUrl or load is still in progress when a new one is initiated, or if the player is stopped, the original pending operation may be interrupted [3][1]. When an interruption occurs, such as calling stop or initiating a new load while a previous setUrl is still loading, the original call will throw a PlayerInterruptedException [1]. This is the documented behavior in just_audio to indicate that the operation was aborted because the player state changed (e.g., the player was stopped or a new source was loaded) before the original source could complete its loading process [1]. If you are experiencing "late completion" where a previous source seems to "replace" the current one, it is often due to not properly awaiting the setUrl operation or not handling the resulting PlayerInterruptedException [4][1]. To resolve this: 1. Always await the setUrl or setAudioSource call to ensure the operation completes or throws an exception before proceeding to the next step [4][1]. 2. Wrap your loading calls in a try-catch block to specifically handle PlayerInterruptedException [1]. This allows your application to gracefully ignore the error when you intentionally trigger an interruption (such as a user cancelling a selection) [1]. 3. If you are managing rapid user interactions, ensure that you track the current active load request or use a state-management pattern that prevents outdated "in-flight" requests from overriding the intended current state once they eventually complete [1]. The library has undergone numerous fixes over time to ensure that stop and setUrl behave predictably across platforms, including ensuring that platform-side events are properly synchronized with the Flutter side to avoid race conditions [5][6][7]. If you are on an older version of just_audio, updating to the latest version is strongly recommended [6].
Citations:
play()not completing whenstop()is called ryanheise/just_audio#1297🏁 Script executed:
Repository: koel/player
Length of output: 11288
🏁 Script executed:
Repository: koel/player
Length of output: 25882
🌐 Web query:
just_audio 0.9.32 setUrl stop PlayerInterruptedException pending future completes after stop💡 Result:
In just_audio, a PlayerInterruptedException occurs when a pending operation—such as setUrl—is interrupted by a subsequent, conflicting operation on the same player instance [1][2][3]. If you call setUrl and then immediately call stop before the setUrl future has completed, the original setUrl future will complete with a PlayerInterruptedException [4][2][3]. This exception indicates that the loading process was aborted because another operation (in this case, stop) took precedence [2][3]. To handle this behavior correctly, you should use a try-catch block to specifically handle PlayerInterruptedException when awaiting operations like setUrl [3]: try { await player.setUrl('https://example.com/audio.mp3'); } on PlayerInterruptedException catch (e) { // Handle the interruption (e.g., the player was stopped or another // setUrl call occurred before this one finished loading). print("Loading was interrupted: ${e.message}"); } The best practice to avoid unnecessary interruptions is to always await your player methods (like setUrl) before initiating a new one [5][6]. If your application logic requires starting a new audio source while one is currently loading or playing, ensure you have managed your player state or instances appropriately, as just_audio is designed to handle one primary sequence of operations per instance [7][8][6]. If you need to play multiple sounds simultaneously, the recommended approach is to use multiple AudioPlayer instances rather than interrupting a single one [8].
Citations:
🌐 Web query:
just_audio 0.9.32 setUrl pending stop setUrl no PlayerInterruptedException💡 Result:
The PlayerInterruptedException is an intended behavior in just_audio designed to signal that an operation (like setUrl) was aborted because the player state changed—such as when the player is stopped, disposed, or another audio source is loaded while a previous load was still in progress [1][2]. If you encounter this exception, it generally means your application code is attempting to change the player's state (e.g., calling stop or loading a new URL) while a previous setUrl operation is still awaiting completion [1][3]. To handle or avoid this: 1. Catch the exception: You should wrap your setUrl calls in a try-catch block to specifically handle PlayerInterruptedException. This allows your app to gracefully ignore the error if it is expected behavior [1][2][3]. try { await player.setUrl("https://your-url.com"); } on PlayerInterruptedException { // Ignore this exception as it signifies an intentional interruption } catch (e) { // Handle other actual errors } 2. Ensure proper awaiting: Ensure you are correctly awaiting your setUrl and stop operations before triggering subsequent state changes. Failing to await an asynchronous stop call before initiating a new load is a common cause of this exception [1][4]. 3. State management: If your player is controlled by UI elements that can be triggered rapidly (like tabs or buttons), ensure that your logic is synchronized so that redundant or conflicting commands are not sent to the player simultaneously [4][3]. The version 0.9.32 of just_audio includes specific fixes related to hang issues when stopping while loading and handling pending timers, which may improve stability regarding these interruptions [5][6][7]. However, the core behavior of throwing PlayerInterruptedException remains the standard mechanism for managing interrupted loading sequences [1][2].
Citations:
🌐 Web query:
just_audio 0.9.32 Future.timeout setUrl pending call stopped while still running💡 Result:
When using just_audio, a Future such as setUrl can be interrupted if a new audio source is loaded, or if the player is stopped or disposed before the initial operation completes [1][2]. If you encounter a situation where an asynchronous operation like setUrl is cancelled or reports an interruption, it typically results in a PlayerInterruptedException [1]. Technical details regarding this behavior include: 1. Handling Interruptions: The library is designed to allow operations to be superseded. If you call setUrl and then immediately call stop or load a different URL, the previous pending operation will be aborted as it is no longer relevant to the current player state [1]. 2. Exception Handling: You should handle these cases explicitly using a try-catch block specifically for PlayerInterruptedException [1][2]. This distinguishes intentional interruptions (e.g., user navigated away, playback was stopped) from network errors or platform-level timeouts [1]. 3. Network Timeouts: If the "pending call stopped" behavior is associated with an error message like "The request timed out" (e.g., error -1001 on iOS), this is often a network-related issue rather than a code-level interruption [3][4]. This occurs when the underlying platform player (AVPlayer on iOS or ExoPlayer on Android) fails to fetch the media within the platform's default timeout period [3]. 4. Event Lag: There is a known, slight lag between when a method like setUrl is called in Dart and when the platform side updates the player state [5]. During this transition period, querying the playback state might return unexpected values (such as 'connecting' or 'idle') [5]. To resolve or debug this: - Ensure you are wrapping your load operations in try-catch blocks to catch PlayerInterruptedException specifically [1]. - If you suspect a network timeout, check your network environment, especially if dealing with large files or slow connections [3]. - If you are experiencing this when switching tracks, verify that your logic does not implicitly call stop or clear the player state before the next source has successfully initialized [4].
Citations:
🌐 Web query:
"just_audio" "PlayerInterruptedException" documentation version 0.9.32💡 Result:
In the just_audio package, PlayerInterruptedException is an exception class that indicates an operation on the audio player was interrupted by another simultaneous operation (such as loading a new audio source before the previous one finished) [1][2][3]. Documentation and usage patterns for this exception, consistent with version 0.9.32 and other versions, recommend handling it within a try-catch block when calling asynchronous methods like setUrl or load [4][5][6]. Example usage for catching this exception: try { await player.setUrl("https://example.com/audio.mp3"); } on PlayerInterruptedException catch (e) { // This call was interrupted since another audio source was loaded or the // player was stopped or disposed before this audio source could complete // loading. print("Connection aborted: ${e.message}"); } catch (e) { // Fallback for all other errors print('An error occured: $e'); } The changelog for version 0.9.32 focuses on fixes related to tag parameters in AudioSource and HLS nested URIs [7][8]; it does not introduce or fundamentally change the PlayerInterruptedException class itself, which remains a standard part of the library's error handling API [2][3].
Citations:
🌐 Web query:
just_audio 0.9.32 changelog stop while loading PlayerInterruptedException💡 Result:
The PlayerInterruptedException in just_audio is not a bug, but rather the documented behavior of the library when an ongoing operation (such as loading or playing an audio source) is interrupted by another operation (like a new load request, a stop command, or disposing of the player) before the original operation completes [1][2][3]. Regarding version 0.9.32 specifically, the changelog entries focus on fixes for tag parameters in asset/file audio sources and nested HLS URIs [4][5]. There is no changelog entry for this version indicating a change to how PlayerInterruptedException is handled. The best practice for managing this exception is to catch it explicitly in your code when performing operations that might be interrupted [1][3]. The official documentation provides the following pattern for handling this: try { await player.setUrl("https://example.com/audio.mp3"); } on PlayerInterruptedException catch (e) { // Handle the interruption (e.g., ignore it if it was expected) print("Connection aborted: ${e.message}"); } catch (e) { // Handle other types of errors print('An error occurred: $e'); } If you encounter this exception frequently, it is often due to asynchronous code triggering multiple load or play commands simultaneously [6]. Ensuring you await your player operations properly and managing state to avoid overlapping commands can often resolve or mitigate the issue [3].
Citations:
🌐 Web query:
"just_audio" "setUrl" "no longer running" "PlayerInterruptedException" 2021💡 Result:
The PlayerInterruptedException is not a bug that was removed; rather, it is the intended behavior in the just_audio package when a loading operation (such as setUrl) is interrupted by another action [1][2]. Around 2021, the package was updated to formalize this exception handling [3][4]. Specifically, in version 0.10.1, the library was updated to explicitly throw PlayerInterruptedException instead of a generic PlatformException [3] when an operation is cancelled (for example, if a new audio source is loaded or the player is stopped before the previous one completes loading) [1][2][5]. To resolve issues where this exception disrupts your application flow, you should wrap your loading calls in a try-catch block and specifically catch the PlayerInterruptedException [1][6][2]: try { await player.setUrl("https://example.com/audio.mp3"); } on PlayerInterruptedException catch (e) { // This exception occurs when the operation is interrupted. // You can safely ignore it if your app logic handles the interruption. print("Connection aborted: ${e.message}"); } catch (e) { // Handle other unexpected errors print("An error occurred: $e"); } If you continue to see this error frequently, ensure that you are properly awaiting your asynchronous calls (e.g., await player.setUrl(...)) [1][6] and check if your UI logic is triggering multiple conflicting playback commands simultaneously (such as rapid tab switching or repeated play/stop calls) [6][7].
Citations:
🌐 Web query:
"just_audio" "setUrl" "stopped" "PlayerInterruptedException" "pending" "never completed"💡 Result:
The PlayerInterruptedException in the just_audio Flutter package is not a bug, but rather intended behavior indicating that an audio loading operation was interrupted before it could complete [1][2]. This occurs when a new load request (e.g., calling setUrl or setAudioSource) is initiated while a previous load request is still in progress, or if the player is stopped or disposed during the loading process [3][4][2]. To handle this exception, you should wrap your audio loading calls in a try-catch block and specifically catch PlayerInterruptedException [3][5]. Example implementation: try { await player.setUrl("https://example.com/audio.mp3"); } on PlayerInterruptedException catch (e) { // Handle the interruption (e.g., log it or simply ignore it) print("Connection aborted: ${e.message}"); } catch (e) { // Handle other types of errors print('An error occurred: $e'); } Recommendations to avoid or manage this: 1. Ensure proper awaiting: Always use the await keyword when calling methods like setUrl or load to ensure operations complete before moving to the next step [6][1]. 2. Avoid rapid load requests: If your app logic triggers multiple play requests in rapid succession (e.g., during UI transitions or tab switching), check the player state or implement logic to prevent redundant load requests [7][6][2]. 3. Graceful handling: Since this exception is often a natural consequence of user interaction (like changing a screen or clicking play on a new file before the previous one finished loading), catching it and suppressing it is the standard, documented approach [1][2]. If the player appears to be stuck in a pending or loading state despite your attempts to handle it, ensure your code is not creating a race condition where multiple load commands are fighting for the player's internal state [2][8].
Citations:
🌐 Web query:
"just_audio" "0.9.32" "setUrl" "completed" "PlayerInterruptedException" "setUrl" "completed successfully" "pending"💡 Result:
The PlayerInterruptedException in the just_audio package occurs when a player operation (such as setUrl, load, or play) is interrupted by another simultaneous operation, such as the player being stopped, disposed, or a new audio source being loaded before the previous one finished loading [1][2][3]. In just_audio version 0.9.32 and later, this exception is specifically used to signal that a loading operation was aborted because the state of the player changed (e.g., a new source was requested) [4][2]. To handle this exception, you should wrap your audio loading and playback calls in a try-catch block and specifically catch PlayerInterruptedException [1][3]. This allows your application to gracefully handle cases where, for example, a user rapidly navigates between screens or triggers multiple play requests in quick succession [5][6]. Example of proper handling: try { await player.setUrl("https://your-audio-url.mp3"); } on PlayerInterruptedException catch (e) { // This call was interrupted; log it or ignore it if expected print("Connection aborted: ${e.message}"); } catch (e) { // Handle other types of errors print('An error occurred: $e'); } If you encounter this exception frequently, it is often a sign of asynchronous race conditions in your code where multiple calls to player methods are overlapping [6]. Ensure that your logic properly awaits previous operations or uses state checks (e.g., checking the player's processing state) before initiating new ones [5][6].
Citations:
🌐 Web query:
"just_audio" "0.9.32" "Futures" "timeout" "isCompleted" "PlayerInterruptedException"💡 Result:
In just_audio, a PlayerInterruptedException occurs when a pending operation on the audio player is interrupted by another simultaneous operation, such as loading a new audio source, stopping the player, or disposing of it before the original operation could complete [1][2][3]. In version 0.9.32, this behavior is a standard part of the library's error handling design, where asynchronous operations like load are explicitly aborted if the state changes before they finish [4][3]. How to Handle PlayerInterruptedException: The recommended way to deal with this error is to catch the exception specifically using a try-catch block around your audio operations [2][5]. This is particularly necessary if you are triggering audio loads based on UI interactions (like switching tabs or rapid button clicks) where a previous operation might still be in progress [6]. Example implementation: try { await player.setUrl("https://your-audio-url.mp3"); await player.load; } on PlayerInterruptedException catch (e) { // This call was interrupted because another audio source was loaded, // the player was stopped, or disposed of. // You can safely ignore this or log it for debugging purposes. print("Operation interrupted: ${e.message}"); } catch (e) { // Handle other types of errors print("An unexpected error occurred: $e"); } Common Scenarios for Interruption: 1. UI Transitions: If you trigger an audio load inside a tab change or navigation event, the previous load might still be executing, causing the library to interrupt it to prioritize the new, current state [6]. 2. Rapid Sequential Calls: If you call load or setUrl multiple times in rapid succession, only the latest call is guaranteed to complete, while previous ones will throw PlayerInterruptedException [7][3]. If you are experiencing timeouts (e.g., "The request timed out") in addition to interruptions, note that these are separate from PlayerInterruptedException and typically relate to network conditions [8][9]. While Dart's Future.timeout can be used to limit how long you wait for a player operation, it does not prevent the underlying interruption exception [10]. If you are facing persistent issues with this exception in version 0.9.32, it is often a sign of race conditions in your app's state management. Ensure that your audio player logic is properly synchronized and that you are not initiating multiple conflicting load operations simultaneously [7][11].
Citations:
Handle or guard
_setPlayerSourceinterruptions before usingsourceLoadTimeout.Future.timeout(...)only drops the await at Dart; it does not change the player state. In this flow, a stalledsetUrlcan leave_setPlayerSourceawaiting while other state has moved on, and the surroundingcatchturns interruption into the generic abandoned-source path. Apply a load generation guard when awaiting the future, then await_player.stop()before proceeding.[low_effort_or_unknown]
🤖 Prompt for AI Agents