Conversation
|
Hi, thanks for the contribution! Can you elaborate on the use case for this PR? Is there already a defined standard (maybe just for arguments?) for starting app playback in Home Assistant? I know the Jellyfin server has websocket commands for browsing and playing media that Wholphin does not implement yet. |
|
Hi, yes of course. Home assistant has an integration with Jellyfin already, however it can only initiate playback to a client device if the client is already in the Jellyfin app and waiting for a command. The integration is useful for managing playback media that has already started, or state based automations (e.g. dim the lights when a movie starts), but it's not good for initiating playback to begin with unless you're already in the app. Enter android intents, this allows me to use the Home Assistant "Android Debug Bridge" to send ADB commands to my TV device. In my case I have some NFC cards for my little girl that she can tap on a sensor, doing so starts the movie printed on the card. The official Jellyfin and Plex clients support android intents that will start their respective apps and navigate to the media item ID provided. The limitation with those clients is that they both stop at the "User Select" screen if you have multiple users, and even if you don't, they require an "Ok/Enter" command to be sent to press play on the item it navigated to. This PR takes it a step further by adding support for autoplay, sending a user ID and sending a server ID, meaning the command can be a one shot! Some links for context below jellyfin/jellyfin-androidtv#3452 (reply in thread) https://simplyexplained.com/blog/how-i-built-an-nfc-movie-library-for-my-kids/ |
Enhanced wholphin://play/ intent handling to work reliably from any app state (server select, user select, or logged in). Added autoplay support for Series (next unwatched episode) and Season (first episode). Fixed resume position handling for user switches and prevented error screen flash when playing seasons. - Refactored handleIntent() to suspend function for async handling - Enhanced createDestinationFromIntentData() to resolve seasons/series to episodes before creating Playback destinations - Improved error handling for unresolvable SEASON/SERIES types - Code cleanup and comment simplification
|
Adding that I am willing to help test this. I use HomeAssistant for this exact purpose. (in my case, I have a voice assistant I can ask to play a movie/ TV show), etc. |
|
Would love to test this so that I can integrate a button into Home Assistant to quickly load specific content. Would this work with playlists too? Could it also do a randomize sort perhaps? (e.g. load random cartoon from playlist) |
damontecres
left a comment
There was a problem hiding this comment.
There's a lot of hard to follow code here, so it needs some TLC before it can be considered.
| } | ||
|
|
||
| if (autoplay) { | ||
| val currentUser = viewModel.serverRepository.currentUser.value |
There was a problem hiding this comment.
Some of this logic is already implemented in SeriesViewModel, so would be good reuse that maybe by creating a service class.
| } | ||
| } | ||
|
|
||
| private fun parseDeepLink(uri: Uri?): Destination? { |
There was a problem hiding this comment.
What is this function for? There seems to be several new functions for parsing information from the URI and/or intent, but its unclear what each is for or how they are used.
| } | ||
| } | ||
|
|
||
| private fun parseUUID(input: String?): UUID? { |
There was a problem hiding this comment.
String.toUUIDOrNull() from the jellyfin sdk already handles this.
| var pendingRequestedDestination: Destination? = null | ||
| var lastProcessedItemId: UUID? = null | ||
| var pendingIntentData: MainActivity.IntentData? = null |
There was a problem hiding this comment.
Should be using state or passing these around in functions. Just parking variables in the ViewModel isn't great.
|
|
||
| LaunchedEffect(appContentKey) { | ||
| if (appContentKey != null) { | ||
| delay(200) |
| appPreferences.updateUrl, | ||
| ) | ||
| } catch (ex: Exception) { | ||
| if (ex is kotlinx.coroutines.CancellationException) throw ex |
| viewModel.pendingRequestedDestination | ||
| ?.also { viewModel.pendingRequestedDestination = null } |
There was a problem hiding this comment.
This seems like code smell. See my comment about using state in the ViewModel.
| fun EpisodeDetails( | ||
| preferences: UserPreferences, | ||
| destination: Destination.MediaItem, | ||
| autoPlayOnLoad: Boolean = false, |
There was a problem hiding this comment.
It seems like the intention here to load this page and have it auto play so you can go back to this page?
If so, a better way would be to navigate twice (or set the backstack to two items in MainActivity), to this page followed by the Playback destination.
Description
This PR implements new deep linking functionality for media playback, enabling external tools (e.g., ADB, Home Assistant) to trigger content directly.
Previously, there was no support for deep linking directly into playback. This PR introduces the
wholphin://play/scheme and adds specific intent parameters (userId,serverId) to bypass the login and server selection screens entirely, allowing for seamless automation from a cold or warm start.Changes Implemented:
wholphin://play/{itemId}URIs.userIdandserverIdvia intent extras.onNewIntent), allowing for instant user switching.Related issues
Implements deep linking support for home automation integration.
Steps to verify:
Screenshots
N/A - Logic implementation only.
AI/LLM usage
I utilized an LLM (Gemini) to assist with the architecture of the
appStartauthentication flow and the intent handling lifecycle (onNewIntent) to ensuring smooth transitions between cold and warm states. Validated via ADB debugging and Home Assistant integration.