Merged
Conversation
Adds a new audio casting feature to the application, allowing users to stream music to compatible devices. - Adds a new "cast" icon button to the `TopAppBar` in the `FullPlayerContentInternal` composable. - Implements `CastBottomSheet`, a new bottom sheet that displays a list of available cast routes (devices) discovered by Android's `MediaRouter`. - Integrates `androidx.mediarouter.media.MediaRouter` into `PlayerViewModel` to handle device discovery. Discovered routes are exposed via a `StateFlow`. - The `MediaRouter.Callback` is correctly registered on `init` and unregistered in `onCleared` to prevent memory leaks. - Adds the `mediarouter` dependency to the project and a new vector drawable for the cast icon. - The UI is updated to allow users to select a device from the list, which triggers the connection through the ViewModel.
This commit introduces significant improvements to the audio casting functionality, focusing on UI/UX enhancements and adding more granular control for the user. Key changes include: - Redesigned `CastBottomSheet` using Material 3 `Card`s for a more expressive and modern interface. - Implemented explicit connect/disconnect buttons for each cast route. - Added a visual indicator (green dot) to highlight the currently active route. - Integrated icons to display the device type (TV, speaker) and connection type (Wi-Fi, Bluetooth), derived from `MediaRouter.RouteInfo`. - Added a volume slider to the `CastBottomSheet` for devices that support remote volume control. The `PlayerViewModel` now manages volume state and handles `requestSetVolume`. - Introduced a refresh `FloatingActionButton` (FAB) to allow manual rescanning of devices, with a `LinearProgressIndicator` to show the refresh state. - Added new vector drawables for TV, speaker, Bluetooth, and Wi-Fi icons. - Updated `PlayerViewModel` to manage the state for the selected route, volume, and refresh status, and to handle all related user actions.
This commit introduces significant improvements to the audio casting functionality, focusing on UI/UX enhancements and adding more granular control for the user. It also corrects a bug in how connection type icons were determined. Key changes include: - Redesigned `CastBottomSheet` using Material 3 `Card`s for a more expressive and modern interface. - Implemented explicit connect/disconnect buttons for each cast route. - Added a visual indicator (green dot) to highlight the currently active route. - Integrated icons to display the device type (TV, speaker) and connection type (Wi-Fi, Bluetooth). - **Fix:** Corrected the logic to determine connection type by using `route.deviceType` for Bluetooth and `route.playbackType` for remote (Wi-Fi) connections, as `route.connectionType` does not exist. - Added a volume slider to the `CastBottomSheet` for devices that support remote volume control. The `PlayerViewModel` now manages volume state and handles `requestSetVolume`. - Introduced a refresh `FloatingActionButton` (FAB) to allow manual rescanning of devices, with a `LinearProgressIndicator` to show the refresh state. - Added new vector drawables for TV, speaker, Bluetooth, and Wi-Fi icons. - Updated `PlayerViewModel` to manage the state for the selected route, volume, and refresh status, and to handle all related user actions.
This commit delivers a comprehensive audio casting feature, integrating the Google Cast SDK for Smart TV support and addressing detailed UI/UX feedback. Key changes include: - **Google Cast SDK:** Integrated `play-services-cast-framework` to enable casting to Chromecast devices. Implemented `CastOptionsProvider` and a `SessionManagerListener` in `PlayerViewModel` to manage `CastSession` lifecycle. Playback functions now delegate to `RemoteMediaClient` when a cast session is active. - **UI Enhancements:** - Redesigned `CastBottomSheet` using Material 3 `Card`s. - Added explicit connect/disconnect buttons and an active route indicator. - Implemented icons for device type (TV, speaker) and connection type (Wi-Fi, Bluetooth). - Added a `FloatingActionButton` for refreshing the device list and a `LinearProgressIndicator` to show the refresh state. - **Volume Slider:** - Added a volume slider for variable-volume devices. - Fixed the slider's state management with an optimistic update in the ViewModel for a responsive feel. - **Enablement Prompts:** - Added logic to `PlayerViewModel` to detect Wi-Fi and Bluetooth status. - The `CastBottomSheet` now displays prompts to enable these services if they are off, including permission requests and shortcuts to system settings. - **Bug Fix:** Corrected the logic for determining connection type icons, now using `route.deviceType` and `route.playbackType` instead of the non-existent `connectionType` property. - Added necessary permissions for Wi-Fi and Bluetooth state to `AndroidManifest.xml`.
This commit updates the MediaRouter dependency to version `1.8.1` and refactors the `CastBottomSheet` to align with the latest API changes for identifying speaker devices.
Key changes:
- **Dependency Update**: Upgraded `androidx.mediarouter:mediarouter` to version `1.8.1` to leverage new APIs and bug fixes.
- **`CastBottomSheet.kt`**:
- Replaced deprecated speaker device type constants with the new `DEVICE_TYPE_BUILTIN_SPEAKER` and `DEVICE_TYPE_REMOTE_SPEAKER`.
- Adopted the new `DEVICE_TYPE_BLUETOOTH_A2DP` constant for identifying Bluetooth devices.
- Added `@OptIn(UnstableApi::class)` to acknowledge the use of new Media3 APIs.
…t-feature # Conflicts: # app/src/main/java/com/theveloper/pixelplay/presentation/components/CastBottomSheet.kt
This commit delivers a comprehensive audio casting feature, integrating the Google Cast SDK for Smart TV support and addressing detailed UI/UX feedback and bug reports. Key changes include: - **Google Cast SDK:** Integrated `play-services-cast-framework` to enable casting to Chromecast devices. Implemented `CastOptionsProvider` and a `SessionManagerListener` in `PlayerViewModel` to manage `CastSession` lifecycle. Playback functions now delegate to `RemoteMediaClient` when a cast session is active. - **UI Enhancements:** - Redesigned `CastBottomSheet` using Material 3 `Card`s. - Added explicit connect/disconnect buttons and an active route indicator. - Implemented icons for device type and connection type. - Added a `FloatingActionButton` for refreshing the device list and a `LinearProgressIndicator` to show the refresh state. - **Volume Slider:** - Added a volume slider for variable-volume devices. - Fixed the slider's state management with an optimistic update in the ViewModel for a responsive feel. - **Enablement Prompts:** - Added logic to `PlayerViewModel` to detect Wi-Fi and Bluetooth status. - The `CastBottomSheet` now displays prompts to enable these services if they are off, including permission requests and shortcuts to system settings. - **Bug Fixes:** - Corrected the logic for determining connection type icons, now using `route.deviceType` and `route.playbackType`. - Fixed the API usage for shuffle and repeat modes in the Cast SDK, now using the correct `getQueueRepeatMode` and `queueSetRepeatMode` methods and `MediaStatus` constants. - Added necessary permissions for Wi-Fi and Bluetooth state to `AndroidManifest.xml`.
This commit delivers a comprehensive audio casting feature, integrating the Google Cast SDK for Smart TV support and addressing detailed UI/UX feedback and critical bug reports.
Key changes include:
- **Google Cast SDK & Playback Transfer:**
- Integrated `play-services-cast-framework` to enable casting to Chromecast devices.
- Implemented `CastOptionsProvider` and a `SessionManagerListener` to manage the `CastSession` lifecycle.
- Implemented a playback transfer mechanism in `onSessionStarted` and `onSessionEnded` to seamlessly move the current queue and playback state between the local player and the remote device.
- All playback control functions (`playPause`, `seekTo`, etc.) now correctly delegate to the `RemoteMediaClient` when a cast session is active.
- **UI/UX Enhancements:**
- Redesigned `CastBottomSheet` using Material 3 `Card`s.
- Added explicit connect/disconnect buttons and an active route indicator. The sheet no longer dismisses automatically on connection.
- Implemented icons for device type and connection type.
- Added a `FloatingActionButton` for refreshing the device list and a `LinearProgressIndicator` to show the refresh state.
- Added prompts to enable Wi-Fi or Bluetooth if they are disabled, with shortcuts to system settings.
- **Bug Fixes:**
- **Crash:** Fixed an `IndexOutOfBoundsException` by filtering the device list from `MediaRouter` with `distinctBy { it.id }` to prevent duplicates from destabilizing the UI.
- **Shuffle/Repeat:** Corrected the API usage for shuffle and repeat modes for the Cast SDK, now using `getQueueRepeatMode()` and `queueSetRepeatMode()` with the correct `MediaStatus` constants.
- **Volume Slider:** Fixed the slider's state management with an optimistic update in the ViewModel for a responsive feel.
- **Idle Playback:** Corrected the `playPause` logic to load media to the remote device if it's idle when the user presses play.
- **Permissions:** Added necessary permissions for Wi-Fi and Bluetooth state to `AndroidManifest.xml`.
This commit delivers a comprehensive audio casting feature, integrating the Google Cast SDK for Smart TV support and addressing detailed UI/UX feedback and critical bug reports.
Key changes include:
- **Google Cast SDK & Playback Transfer:**
- Integrated `play-services-cast-framework` to enable casting to Chromecast devices.
- Implemented `CastOptionsProvider` and a `SessionManagerListener` in `PlayerViewModel` to manage the `CastSession` lifecycle.
- Implemented a playback transfer mechanism in `onSessionStarted` and `onSessionEnded` to seamlessly move the current queue and playback state between the local player and the remote device.
- All playback control functions (`playPause`, `seekTo`, etc.) now correctly delegate to the `RemoteMediaClient` when a cast session is active.
- **UI/UX Enhancements:**
- Redesigned `CastBottomSheet` using Material 3 `Card`s.
- Added explicit connect/disconnect buttons and an active route indicator. The sheet no longer dismisses automatically on connection.
- Implemented icons for device type and connection type.
- Added a `FloatingActionButton` for refreshing the device list and a `LinearProgressIndicator` to show the refresh state.
- Added prompts to enable Wi-Fi or Bluetooth if they are disabled, with shortcuts to system settings.
- **Bug Fixes:**
- **Crash:** Fixed an `IndexOutOfBoundsException` by filtering the device list from `MediaRouter` with `distinctBy { it.id }` to prevent duplicates from destabilizing the UI.
- **Shuffle/Repeat:** Corrected the API usage for shuffle and repeat modes for the Cast SDK, now using the correct `getQueueRepeatMode` and `queueSetRepeatMode` methods and `MediaStatus` constants.
- **Volume Slider:** Fixed the slider's state management with an optimistic update in the ViewModel for a responsive feel.
- **Idle Playback:** Corrected the `playPause` logic to load media to the remote device if it's idle when the user presses play.
- **Type Mismatch:** Corrected the `queueLoad` method call to use the proper overload with the `playPosition` and `customData` arguments.
- **Permissions:** Added necessary permissions for Wi-Fi and Bluetooth state to `AndroidManifest.xml`.
This commit delivers a comprehensive audio casting feature, integrating a local HTTP server for reliable streaming, implementing full playback state transfer, and fixing several critical bugs reported by the user.
Key changes include:
- **HTTP Server for Streaming:**
- Added Ktor as a dependency to run an embedded HTTP server as a background service.
- The `PlayerViewModel` now serves local audio files via `http://` URLs, making them accessible to remote cast devices like Smart TVs.
- **Playback State Synchronization:**
- Implemented a full playback transfer mechanism in `onSessionStarted` and `onSessionEnded` to seamlessly move the current queue and playback state between the local player and the remote device.
- Added a `RemoteMediaClient.Callback` and `ProgressListener` to keep the local UI in sync with the remote player's state (play/pause, current song, progress) in real-time.
- **Bug Fixes and Enhancements:**
- **Crash:** Fixed an `IndexOutOfBoundsException` by filtering the `MediaRouter` device list with `distinctBy { it.id }`.
- **Playback Controls:** All playback controls now correctly delegate to `RemoteMediaClient` when casting. Fixed a bug where `play` would not work on an idle cast device.
- **Cast SDK API Usage:** Corrected the API calls for shuffle/repeat modes and fixed a `Type Mismatch` error in `queueLoad`.
- **UI:** Added prompts to enable Wi-Fi/Bluetooth and improved the design and logic of the `CastBottomSheet`.
- **Dependencies & Permissions:**
- Added `ktor-server-core` and `ktor-server-netty` dependencies.
- Added necessary permissions for Wi-Fi and Bluetooth state to `AndroidManifest.xml`.
This commit introduces a complete and robust Google Cast functionality, allowing users to stream audio and album art to remote devices like Smart TVs. It also includes several critical bug fixes to ensure stability and a seamless user experience. Key Features & Fixes: - Implemented a Ktor-based HTTP server to serve local media and album art over the network. - Added robust CastSession lifecycle management in PlayerViewModel to handle playback transfer. - Implemented real-time UI synchronization between the local app and the remote player. - Eliminated race conditions by ensuring the HTTP server is running before use. - Corrected the parameter order in the RemoteMediaClient.queueLoad method. - Enhanced the CastBottomSheet UI with better device state indicators and controls.
This commit introduces a complete and robust Google Cast functionality, allowing users to stream audio and album art to remote devices like Smart TVs. It also includes several critical bug fixes to ensure stability and a seamless user experience. Key Features & Fixes: - Implemented a Ktor-based HTTP server to serve local media and album art over the network. - Added robust CastSession lifecycle management in PlayerViewModel to handle playback transfer. - Implemented real-time UI synchronization between the local app and the remote player. - Eliminated race conditions by ensuring the HTTP server is running before use. - Corrected the parameter order in the RemoteMediaClient.queueLoad method. - Moved the `ensureHttpServerRunning` function into the `PlayerViewModel` to fix a private context access error.
This commit resolves critical `Unresolved reference` errors in the `MediaFileHttpServerService`. - Replaced incorrect repository method calls with the correct `getSong(songId)` method. - Updated the deprecated `respondInputStream` to the modern Ktor 2.0 streaming API using `OutgoingContent.ReadChannelContent`. - Corrected the `ContentType` for both audio and image streams.
This commit refactors the Ktor-based `MediaFileHttpServerService` to improve performance and stability when streaming media for casting. It also updates Google Cast dependencies and resolves related build issues.
### Key Changes:
- **`MediaFileHttpServerService.kt`**:
- Refactored the Ktor server endpoints (`/song/{songId}` and `/art/{songId}`) to use `respondOutputStream` instead of `ReadChannelContent`.
- This change directly streams the file content from an `InputStream` to the response, which is more efficient and resolves potential stream closing issues.
- Imports were cleaned up, and HTTP status codes are now used from `io.ktor.http.HttpStatusCode`.
- **Dependency Updates (`libs.versions.toml`, `app/build.gradle.kts`):**
- Added `play-services-cast-framework = "22.1.0"` to manage the dependency version consistently.
- Implemented the new dependency in the `app` module.
- Updated the Ktor version to `2.3.12`.
- **Build & Manifest Configuration:**
- **`app/build.gradle.kts`**: Added a packaging exclusion for `/META-INF/io.netty.versions.properties` to prevent build failures caused by duplicate files from Ktor/Netty dependencies.
- **`AndroidManifest.xml`**: Removed the `tools:usesPermissionFlags="neverForLocation"` attribute from the `NEARBY_WIFI_DEVICES` permission as it is no longer recommended.
- **Code Cleanup:**
- **`PlayerViewModel.kt`**: Made `castSessionManagerListener` nullable to prevent potential null pointer exceptions during lifecycle events and added non-null assertions where the listener is added/removed.
- Removed redundant `@OptIn` annotations in `CastBottomSheet.kt`.
- Corrected import statements in `CastOptionsProvider.kt` to align with the updated Cast SDK.
This commit addresses three critical issues with the Chromecast functionality: 1. **Crash on Device Selection:** An `IndexOutOfBoundsException` in `CastBottomSheet.kt` that occurred due to unstable list updates from `MediaRouter` has been fixed. A stable `key` has been added to the `LazyColumn`'s item renderer, ensuring Compose can track devices correctly during UI updates. 2. **Duplicate Device Entries:** The `PlayerViewModel` now correctly filters the `MediaRouter` routes to only include unique devices that support remote playback, preventing duplicate and non-castable devices from appearing in the selection list. 3. **No Audio Playback:** The root cause was an unreliable HTTP server startup and incorrect IP address retrieval. The `MediaFileHttpServerService` now uses the modern `ConnectivityManager` API to reliably get the device's IP. The `PlayerViewModel` has been updated to proactively start the server when a cast route is selected and includes a robust polling mechanism to ensure the server is ready before attempting to stream media. The cast session lifecycle management has also been overhauled for more reliable playback transfer and teardown.
This commit provides a comprehensive solution to multiple problems with the Chromecast functionality, including a critical fix for a dependency conflict that caused a `NoSuchMethodError`. Key changes: - **Dependency Conflict:** Resolved a `java.lang.NoSuchMethodError` crash by upgrading Ktor to version 2.3.12 and explicitly adding a compatible `kotlinx-coroutines-core` dependency (version 1.8.0). This ensures binary compatibility and prevents runtime crashes when starting the HTTP server. - **UI Crash (`IndexOutOfBoundsException`):** Fixed the crash in `CastBottomSheet.kt` by adding a stable `key` to the `LazyColumn`'s item renderer. This helps Compose correctly track devices during rapid UI updates from the `MediaRouter`. - **Duplicate Devices:** The `PlayerViewModel` now correctly filters `MediaRouter` routes to only include unique, remote-playback-capable devices, preventing duplicates and non-castable devices from appearing in the UI. - **Audio Playback Failure:** - The `MediaFileHttpServerService` now uses the modern `ConnectivityManager` API to reliably retrieve the device's IP address, fixing a major source of failure. - The `PlayerViewModel` now proactively starts the HTTP server when a cast route is selected and uses a robust polling mechanism to ensure the server is ready before streaming, preventing race conditions. - The cast session lifecycle management (`onSessionStarted`, `onSessionEnded`, etc.) has been overhauled for more reliable playback transfer and teardown.
This commit resolves the issue where playback controls (play, pause, next, etc.) were not functioning during a cast session. The playback functions in `PlayerViewModel.kt` have been updated to correctly delegate commands to the `RemoteMediaClient` when a cast session is active. - **Remote-First Logic:** All major playback control functions (`playPause`, `seekTo`, `nextSong`, `previousSong`, `toggleShuffle`, `cycleRepeatMode`) now check for an active `CastSession`. If one exists, the command is sent to the remote device; otherwise, it controls the local player. - **Error Handling:** `ResultCallback` has been added to all `RemoteMediaClient` commands. This ensures that if a command fails (e.g., to play, pause, or seek), the error is logged to Timber, aiding in future debugging efforts. - **Progress Updates:** The `startProgressUpdates` function has been refactored to correctly handle progress updates for both local and remote playback scenarios, ensuring the UI stays in sync.
This commit provides a complete overhaul of the casting functionality to ensure all playback actions are correctly delegated to the remote device when a cast session is active. It also resolves underlying dependency conflicts and improves the robustness of the entire casting feature. Key changes: - **Unified Playback Logic:** The `internalPlaySongs` and `showAndPlaySong` functions in `PlayerViewModel.kt` have been refactored to be fully cast-aware. They now act as a single entry point for all playback initiations, correctly routing commands to either the local `MediaController` or the remote `RemoteMediaClient`. - **Efficient Queue Navigation:** The `showAndPlaySong` function now intelligently checks if a song is already present in the remote queue. If so, it uses `queueJumpToItem` for efficient navigation instead of reloading the entire queue, significantly improving the user experience for carousels and playlists. - **Remote-Aware Controls:** All playback control functions (`playPause`, `seekTo`, `nextSong`, `previousSong`, `toggleShuffle`, `cycleRepeatMode`) have been updated to be remote-first. They check for an active cast session and delegate commands to the `RemoteMediaClient` with error handling callbacks. - **Robust Progress Sync:** The `startProgressUpdates` function has been corrected to handle progress updates for both local and remote playback, ensuring the UI is always in sync. - **Dependency and Server Fixes:** This commit also includes the previous fixes for the Ktor/coroutines dependency conflict and the unreliable IP address retrieval in the HTTP server, which were foundational to this solution.
This commit addresses several critical bugs related to the Chromecast and smart TV casting feature: 1. **Resolves `IndexOutOfBoundsException` Crash:** Fixes a crash that occurred when viewing the cast device list by adding a stable `key` to the `LazyColumn` in `CastBottomSheet.kt`, preventing state-related exceptions during recomposition. 2. **Fixes Duplicate Device Entries:** Corrects the `MediaRouter.Callback` in `PlayerViewModel.kt` to filter for `CATEGORY_REMOTE_PLAYBACK` and use `distinctBy` to ensure that only unique, castable devices are displayed in the cast selection sheet. 3. **Enables Remote Audio Playback:** Implements a local HTTP server (`MediaFileHttpServerService`) to serve local audio and album art files to the cast device. This resolves the issue where audio would not play on the remote device. The server's lifecycle is now correctly tied to the cast session. 4. **Makes Playback Controls Remote-Aware:** All playback controls in `PlayerViewModel.kt` (play/pause, next/previous, seek, shuffle, repeat, and song selection from any list) now check for an active cast session. If a session is active, commands are correctly delegated to the `RemoteMediaClient` instead of the local player. This includes error handling for all remote calls. 5. **Corrects Progress Bar Syncing:** The player UI's progress bar is now correctly synced with the remote device's playback position during a cast session by observing the `RemoteMediaClient.ProgressListener`. Local progress polling is disabled during casting to prevent conflicts. 6. **Resolves Dependency Crash:** Upgrades Ktor and `kotlinx.coroutines` dependencies to resolve a `NoSuchMethodError` crash that occurred during initial testing.
This commit addresses several critical bugs related to the Chromecast and smart TV casting feature: 1. **Resolves `IndexOutOfBoundsException` Crash:** Fixes a crash that occurred when viewing the cast device list by adding a stable `key` to the `LazyColumn` in `CastBottomSheet.kt`, preventing state-related exceptions during recomposition. 2. **Fixes Duplicate Device Entries:** Corrects the `MediaRouter.Callback` in `PlayerViewModel.kt` to filter for `CATEGORY_REMOTE_PLAYBACK` and use `distinctBy` to ensure that only unique, castable devices are displayed in the cast selection sheet. 3. **Enables Remote Audio Playback:** Implements a local HTTP server (`MediaFileHttpServerService`) to serve local audio and album art files to the cast device. This resolves the issue where audio would not play on the remote device. The server's lifecycle is now correctly tied to the cast session. 4. **Makes Playback Controls Remote-Aware:** All playback controls in `PlayerViewModel.kt` (play/pause, next/previous, seek, shuffle, repeat, and song selection from any list) now check for an active cast session. If a session is active, commands are correctly delegated to the `RemoteMediaClient` instead of the local player. This includes error handling for all remote calls. 5. **Corrects Progress Bar Syncing:** The player UI's progress bar is now correctly synced with both local and remote playback. When casting, progress is driven by the `RemoteMediaClient.ProgressListener`. After disconnecting, the local progress polling correctly resumes, fixing a bug where the slider would get stuck. 6. **Resolves Dependency Crash:** Upgrades Ktor and `kotlinx.coroutines` dependencies to resolve a `NoSuchMethodError` crash that occurred during initial testing.
This commit addresses several critical bugs related to the Chromecast and smart TV casting feature:
1. **Resolves `IndexOutOfBoundsException` Crash:** Fixes a crash that occurred when viewing the cast device list by adding a stable `key` to the `LazyColumn` in `CastBottomSheet.kt`, preventing state-related exceptions during recomposition.
2. **Fixes Duplicate Device Entries:** Corrects the `MediaRouter.Callback` in `PlayerViewModel.kt` to filter for `CATEGORY_REMOTE_PLAYBACK` and use `distinctBy` to ensure that only unique, castable devices are displayed in the cast selection sheet.
3. **Enables Remote Audio Playback:** Implements a local HTTP server (`MediaFileHttpServerService`) to serve local audio and album art files to the cast device. This resolves the issue where audio would not play on the remote device. The server's lifecycle is now correctly tied to the cast session.
4. **Makes Playback Controls Remote-Aware:** All playback controls in `PlayerViewModel.kt` (play/pause, next/previous, seek, shuffle, repeat, and song selection from any list) now check for an active cast session. If a session is active, commands are correctly delegated to the `RemoteMediaClient` instead of the local player. This includes error handling for all remote calls.
5. **Corrects Progress Bar Syncing:** The player UI's progress bar is now correctly synced with both local and remote playback. When casting, progress is driven by the `RemoteMediaClient.ProgressListener`. After disconnecting, the local progress polling correctly resumes, fixing a bug where the slider would get stuck.
6. **Resolves Dependency Crash:** Upgrades Ktor and `kotlinx.coroutines` dependencies to resolve a `NoSuchMethodError` crash that occurred during initial testing.
7. **Improves UI/UX and Stability:**
* Fixes album carousel desynchronization by making its state dependent on the queue structure as well as the current song.
* Improves remote seeking via the `WavySlider` by updating the UI instantly and sending the final seek command only when the user releases the slider.
* Stabilizes player state updates by using cancellable jobs in the `Player.Listener` to prevent race conditions during rapid UI events.
This commit addresses several critical bugs related to the Chromecast casting feature, improving stability, user experience, and UI consistency.
The key fixes include:
- **Duplicate Devices:** Resolved the issue of duplicate entries appearing in the cast device selection sheet by correctly filtering routes in the `MediaRouter.Callback`.
- **Crash on Device List:** Prevented an `IndexOutOfBoundsException` crash when rendering the device list by adding a stable `key` to the `LazyColumn` items in `CastBottomSheet.kt`.
- **No Audio on Cast:** Implemented a Ktor-based `MediaFileHttpServerService` to serve local media files over HTTP, enabling audio playback on remote cast devices.
- **Seeking and UI Sync:** Reworked the remote playback logic in `PlayerViewModel` and `UnifiedPlayerSheet` to fix multiple UI bugs:
- The `WavySlider` now seeks correctly without restarting the song by using a local state for dragging and sending the final seek command on release.
- The app's theme color now updates in sync with song changes on the cast device.
- The album art carousel is now correctly synchronized with the remote player's queue.
- **Session Management:** Improved the reliability of starting and stopping cast sessions, ensuring a smooth transition between local and remote playback.
This commit resolves an issue where seeking a track during a cast session using the progress slider would cause the playback to reset to the beginning. The bug was traced to the use of a deprecated `seek()` method in `PlayerViewModel.kt`. The fix involves: - Replacing the deprecated method with the modern `seek(MediaSeekOptions)`. - Explicitly setting the `resumeState` in the `MediaSeekOptions` to either `RESUME_STATE_PLAY` or `RESUME_STATE_PAUSE`, depending on the player's state before the seek action. This ensures the remote player resumes playback correctly from the new position, providing a smooth and predictable user experience.
This commit resolves a persistent issue where seeking a track during a cast session would cause the progress slider to reset to the beginning. The fix addresses two key areas: 1. **Modern Seek API:** The deprecated `seek()` method in `PlayerViewModel.kt` has been replaced with the modern `seek(MediaSeekOptions)`. This allows for explicit control over the player's `resumeState` after seeking, ensuring playback continues correctly. 2. **Optimistic UI Update:** The `seekTo` function now immediately updates the local UI state (`currentPosition`) when a remote seek is initiated. This provides instant visual feedback on the slider and prevents it from snapping back to its old position while waiting for the cast device to report its new progress. These changes work together to create a smooth, reliable, and responsive seeking experience during cast playback.
…t sessions This commit provides a comprehensive solution to issues related to playback continuity and control when using the Chromecast feature. The changes ensure a seamless user experience when transitioning between local and remote playback, and when controlling the remote session. The key fixes include: - **Full State Transfer:** The logic for initiating a cast session (`onSessionStarted`) has been overhauled to transfer the complete local playback state, including the exact queue with unique song IDs, the current track index, the precise playback position, and repeat/shuffle modes. This prevents playback from incorrectly starting at the beginning of a queue. - **Robust Remote Seeking:** Implemented a state-aware seeking mechanism. When the user seeks, a flag (`isRemotelySeeking`) is set to prevent race conditions where stale progress updates from the cast device would override the UI's optimistic new position. This fixes the slider "snapping back" issue. - **Seamless Disconnection:** The disconnection logic (`stopServerAndTransferBack`) has been rewritten to capture the full state from the remote player before terminating the session. It then correctly restores this state (queue, position, modes) to the local player, ensuring the music picks up exactly where it left off. - **Dependency and Stability:** Includes updates to Ktor and Coroutines dependencies to resolve underlying conflicts and adds unique keys to the Cast Bottom Sheet's lazy list to prevent crashes.
This commit provides a comprehensive fix for multiple issues related to Chromecast integration, ensuring seamless playback continuity between the local device and a remote cast device. The key changes include: - **State Transfer:** - `transferPlayback` (on connect): Correctly captures the local player's full state (isPlaying, position, repeat/shuffle modes) *before* pausing to ensure the remote player starts in the exact same state. - `stopServerAndTransferBack` (on disconnect): Reliably captures the remote player's final state and restores it to the local player. Crucially, it now restarts local progress updates, fixing a bug where the progress slider would get stuck. - **Robust Seeking:** - The remote `seekTo` implementation now uses `MediaSeekOptions.RESUME_STATE_UNCHANGED`, delegating play/pause state management to the more reliable cast receiver and preventing tracks from restarting after a seek. - **UI and Data Sync:** - Fixes an `IndexOutOfBoundsException` in the cast device list by using stable keys. - Ensures the UI theme (from album art) and the song carousel stay synchronized with the remote player's state by updating them within the `RemoteMediaClient.Callback`. - **HTTP Server:** - The embedded HTTP server is now started more reliably using a polling mechanism with a timeout, preventing race conditions.
This commit provides a comprehensive fix for multiple issues related to Chromecast integration, ensuring seamless playback continuity between the local device and a remote cast device. The key changes include: - **State Transfer & Synchronization:** - `transferPlayback` (on connect): Correctly captures the local player's full state (isPlaying, position, repeat/shuffle modes) *before* pausing to ensure the remote player starts in the exact same state. - `stopServerAndTransferBack` (on disconnect): Reliably captures the remote player's final, precise position from the real-time progress listener and restores it to the local player, fixing the state desync issue. - UI elements like the theme color and album carousel now correctly sync with the remote player's state. - **Robust Seeking:** - The `WavyMusicSlider` has been refactored into a proper stateless component. - State management for seeking is now correctly handled in `UnifiedPlayerSheet`, which updates the UI visually during a drag and sends a single `seekTo` command on release. This prevents overwhelming the remote player and fixes the track-restarting bug. - **Crash and Bug Fixes:** - Fixes an `IndexOutOfBoundsException` in the cast device list by using a stable, immutable list (`.toList()`) for the `LazyColumn`, preventing crashes from concurrent list modification. - The embedded HTTP server is now started more reliably using a polling mechanism with a timeout.
This commit introduces several code cleanup changes and adds critical ProGuard rules to ensure the stability of release builds.
### Key Changes:
1. **Disable Album Carousel:** The `AlbumCarouselSection` in `UnifiedPlayerSheet.kt` has been temporarily commented out to address unresolved issues or for refactoring purposes.
2. **Add ProGuard Rules:** New rules have been added to `proguard-rules.pro` to prevent crashes in release builds caused by code shrinking (R8). These rules specifically address issues with Ktor and Netty by preserving necessary classes.
3. **Update UI Components:**
* In `CastBottomSheet.kt`, the "Disconnect" button has been changed from `OutlinedButton` to `FilledTonalButton` for better visual prominence.
* The `WavySlider` in `PlayerSeekBar.kt` was updated to use the `value` parameter instead of the deprecated `valueProvider`.
4. **Vector Drawable Updates:** The XML for the `rounded_bluetooth_24.xml` and `rounded_wifi_24.xml` drawables has been replaced with new path data.
5. **Minor Code Cleanup:**
* Removed an unnecessary `?.` safe call in `PlayerViewModel.kt`.
* Removed unused imports from `MediaFileHttpServerService.kt`.
This commit introduces a seamless, continuous playback experience between local and remote (cast) playback and fixes a critical bug with the remote seek functionality. Key changes: - In `PlayerViewModel.kt`, the `transferPlayback` function now captures the local player's `isPlaying` status and correctly translates repeat/shuffle modes, ensuring the remote session starts exactly where the local one left off. - The `stopServerAndTransferBack` function has been enhanced to capture the full remote player state (queue, song ID, position, playing state, and modes) before disconnecting, allowing for a perfect restoration of the local player. - In `UnifiedPlayerSheet.kt`, the `PlayerProgressBarSection` has been updated to fix the remote seeking bug. It now uses a local state to track the slider's position during a drag gesture, sending only a single, final seek command to the `PlayerViewModel` upon release. This prevents the cast device from being overloaded with seek commands and restarting the track.
This commit refactors the player UI and improves the visual styling of several components. Key changes include: - **Lyrics Button Relocation:** The lyrics button has been moved from the mini-player's action row to the main player view, next to the song title and artist. This is achieved by wrapping the song metadata and the new button in a `Row` layout. The button is now a `FilledIconButton` for better visual consistency. - **Album Carousel Code Removal:** The commented-out code for the `AlbumCarouselSection` has been removed to clean up the file. - **Layout Adjustments:** The layout of the mini-player's action row has been updated to accommodate the removal of the lyrics button.
This commit introduces a seamless, continuous playback experience between local and remote (cast) playback and fixes a critical bug with the remote seek functionality. Key changes: - In `PlayerViewModel.kt`, the `transferPlayback` function now captures the local player's `isPlaying` status and correctly translates repeat/shuffle modes, ensuring the remote session starts exactly where the local one left off. - The `stopServerAndTransferBack` function has been enhanced to capture the full remote player state (queue, song ID, position, playing state, and modes) before disconnecting. It now immediately updates the UI with the final remote position to prevent lag before restoring local playback, ensuring a perfect restoration. - In `UnifiedPlayerSheet.kt`, the `PlayerProgressBarSection` has been updated to fix the remote seeking bug. It now uses a local state to track the slider's position during a drag gesture, sending only a single, final seek command to the `PlayerViewModel` upon release. This prevents the cast device from being overloaded with seek commands and restarting the track.
This reverts commit 6007f2c.
This commit refactors the casting implementation in `PlayerViewModel` to ensure seamless state synchronization between the local player and the remote cast device. Key changes include: 1. **`onStatusUpdated` as Single Source of Truth:** The `onStatusUpdated` callback now reconstructs the local playback queue (`currentPlaybackQueue`) and all relevant playback states (current song, isPlaying, shuffle/repeat modes) directly from the `mediaStatus` of the `RemoteMediaClient`. This guarantees that the local UI accurately mirrors the remote player's state at all times, fixing bugs related to UI desynchronization (e.g., incorrect lyrics display). 2. **Seamless Transfer to Local:** The `stopServerAndTransferBack` function has been enhanced to capture the complete and final state of the remote player—including the full queue, current track, playback position, and modes—just before disconnection. It then uses this state to precisely restore the local `mediaController`, ensuring playback continues exactly where it left off. 3. **UI Progress Sync:** A call to `startProgressUpdates()` has been added to `stopServerAndTransferBack` to ensure the local UI's progress bar resumes polling immediately if playback is active upon returning to the local device.
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
No description provided.