Repository navigation
Playlists feature - #1065
Playlists feature#1065elgarima77 wants to merge 4 commits into
Conversation
|
| Filename | Overview |
|---|---|
| app/src/main/java/org/xbmc/kore/ui/sections/file/MediaFileListFragment.java | Adds playlist detection and asynchronous expansion, but globally changes shared-browser behavior and leaves queue mutations vulnerable to stale or overlapping callbacks. |
| app/src/main/java/org/xbmc/kore/ui/sections/audio/MusicListFragment.java | Replaces the fifth music tab with a MediaFileListFragment rooted at Kodi’s saved music-playlists directory. |
| app/src/main/java/org/xbmc/kore/ui/sections/audio/MusicActivity.java | Removes music-video detail selection state and callbacks consistently with removal of that tab. |
| app/src/main/res/menu/playlist_list_item.xml | Adds a focused Play/Queue popup menu for playlist rows. |
Sequence Diagram
sequenceDiagram
actor User
participant UI as MediaFileListFragment
participant Files as Files.GetDirectory
participant Queue as Kodi Playlist
participant Player as Kodi Player
User->>UI: Play saved playlist
UI->>Files: Expand playlist file
Files-->>UI: Track entries
UI->>Queue: Clear
loop Each track
UI->>Queue: Add track
Queue-->>UI: Callback
end
UI->>Player: Open playlist at position 0
Reviews (1): Last reviewed commit: "Remove now-unused MusicVideo section" | Re-trigger Greptile
| @Override | ||
| public void onSuccess(String result) { | ||
| queuePlaylistTracks(connection, tracks, startPlayback); | ||
| } |
There was a problem hiding this comment.
Stale playlist operations keep running
If the user leaves this fragment or starts another playlist action while tracks are still being added, the success callbacks continue the old clear/add/open chain without a lifecycle or operation-identity check, causing playback after navigation or a mixed, incomplete queue.
There was a problem hiding this comment.
Stale/overlapping async chains: added a request-generation counter (playlistOperationId), incremented each time a new play/queue operation starts and again in a new onPause() override. Every callback in the Clear → Add×N → Open chain captures the id it started with and checks it against the current value before proceeding, so it's now a no-op if the fragment's been paused or if a newer operation has since superseded it. That closes both the "user navigates away mid-chain" case and the "user starts a second playlist operation before the first finishes" race.
| } else if (isPlaylistFile(f.file)) { | ||
| playPlaylistFile(f.file); |
There was a problem hiding this comment.
Playlist handling escapes music tab
When a matching .m3u, .m3u8, .pls, or .xsp path is selected in another consumer of this shared fragment, this branch intercepts it before normal directory handling and clears, fills, and opens the playlist selected by that consumer's media type, preventing normal browsing and potentially replacing an unrelated queue.
There was a problem hiding this comment.
Scoping: isPlaylistFile() had no awareness of which tab it was running in, so a .m3u sitting in a folder browsed from the Files section's Music tab would trigger playlist behavior too. Fixed by adding an opt-in flag (ENABLE_PLAYLIST_HANDLING) that only the new Playlists tab sets via its fragment arguments; every call site (handleFileSelect, the context menu visibility check, and the popup menu builder) now checks the flag before treating a file as a playlist. The Files section's other tabs are back to their exact pre-PR behavior.
Browse & Play Saved Music Playlists in Kore
…rlapping async queue operations
|
Both changes are pushed. Let me know if you'd like anything adjusted. |
Browse & Play Saved Music Playlists in Kore
Summary
Kore lets you control whatever is currently playing on Kodi, but had no way to
browse the audio playlists saved on the Kodi machine (e.g.
Summer Hits.m3u,Chill.pls) and start one playing. This closes that gap by replacing the"Videos" tab in the Music section with a "Playlists" tab that lists saved
playlists and lets you play or queue them, with correct track metadata shown
during playback.
This addresses the feature request in
xbmc/Kore#808.
How it works
A "saved playlist" isn't a database entity in Kodi's music library — it's a file
sitting in a special virtual folder,
special://musicplaylists/. The featureis built entirely on JSON-RPC calls Kore already had wrappers for:
Files.GetDirectorywithdirectory: "special://musicplaylists/",media: "music".Files.GetDirectoryagain, this timepassing the playlist's own file path as the directory. Kodi treats a
.m3u/.pls/.xspfile as a browsable "directory" of its own tracks, andmarks it as
filetype: "directory"in listings — this quirk is the sourceof most of the work below.
Player.Openon theplaylist file directly (which plays audio but leaves Now Playing and the
queue empty, since Kodi has no track-level metadata for "the file that is
the whole playlist"), we clear Kodi's active music playlist
(
Playlist.Clear), add each track individually (Playlist.Add), then callPlayer.Openon Kodi's playlist, not the file. This is the samemechanism Kore already uses elsewhere (e.g. playing an album), just applied
to a playlist file's expanded contents.
of clear, and only auto-start playback if nothing is currently playing.
Rather than write a new browsing screen from scratch, the feature reuses
MediaFileListFragment— the fragment that already powers Kore's "Files"section — pointed at the playlists folder instead of the file-source root.
This meant the new functionality is almost entirely small, targeted edits to
existing, well-established code paths, instead of a parallel implementation.
Files changed
ui/sections/audio/MusicListFragment.javaMediaFileListFragmentui/sections/file/MediaFileListFragment.javares/menu/playlist_list_item.xmlres/values/strings.xmlplaylistsstring (and optionally remove now-unusedmusic_videos)ui/sections/audio/MusicActivity.java1.
MusicListFragment.javaThis fragment defines which fragments appear as tabs in the Music section.
Before:
After:
Why:
MediaFileListFragmentalready supports starting from an arbitrarydirectory via a
CURRENT_LOCATIONargument (used by the existing "Files"section for its Video/Music/Pictures tabs, which all start from Sources).
Passing a
FileLocationforspecial://musicplaylists/withisRoot = truemakes it open directly into the playlists folder, with no Sources screen and
no ".." row above it.
2.
MediaFileListFragment.javaThis is the shared fragment behind Kore's "Files" browsing screens. All
changes here are additive/conditional — existing behavior for regular files
and folders is unchanged.
2a. New import
Needed for locale-independent, case-insensitive extension matching in
isPlaylistFile()below.2b. Detecting playlist files
New method:
Why: Kodi's
Files.GetDirectoryreports playlist files withfiletype: "directory"(soListType.ItemFile.isDirectoryistrueforthem), because their contents can be browsed the same way a folder's can. Every
other piece of this feature exists to work around that one API quirk.
2c. Tapping an item — play instead of browse
Before:
After:
Why: The playlist check has to come before the
isDirectorycheck,since playlist files are (mis)reported as directories. Everything else is
unaffected — regular folders and regular files behave exactly as before.
2d. Playing/queueing a playlist with correct track metadata
Why not just call
Player.Openon the playlist file directly? That wasthe first approach tried, and it does play the audio — but Kodi treats the
whole playlist file as a single opaque "item" it's now playing, with no
per-track metadata. Now Playing and the queue both come up empty. Every other
media type in Kore that plays a set of items (e.g. an album) expands it into
individual tracks and queues them via
Playlist.Add, then opens Kodi'splaylist rather than a file — this mirrors that existing pattern instead of
introducing a new one.
queuePlaylistTracksrecurses instead of loopingbecause each
Playlist.Addcall is asynchronous; chaining off eachonSuccessguarantees tracks are added in order, one at a time, beforeplayback starts.
No new imports were needed for this section —
Playlist,Player,PlaylistType,Queue, andLinkedListwere already imported in this filefor its existing queueing logic.
2e. Context menu — show it for playlists, with playlist-appropriate actions
Before (
ViewHolder.bindView):After:
Before (
itemMenuClickListener):After:
Why: "Play locally"/"stream" and "Play from this item" (which queues the
rest of the current directory listing behind the tapped item) are both
meaningless for a playlist row — it represents a whole playlist, not a
position within a directory of individual songs. So playlist rows get their
own, smaller menu (
playlist_list_item.xml, below) instead of reusingfile_list_item.xml; regular file rows are completely unaffected.3.
res/menu/playlist_list_item.xml(new file)Reuses the existing
queue_file/play_filestrings andaction_queue_item/action_play_itemIDs fromfile_list_item.xml, so wording stays consistentwith the rest of the app and no new string resources were needed for the menu
itself.
4.
res/values/strings.xmlAdd (if not already present):
The now-unused
music_videosstring can be removed once confirmed unreferencedelsewhere (see cleanup note below).
5.
MusicActivity.java— cleanupOnce Playlists fully replaced the Videos tab, the music-video selection state
and callback in
MusicActivitybecame dead code (Option 1 — reusingMediaFileListFragment, which handles browsing and playback internally —meant
MusicActivityneeded no new callback of its own, so this is a puresubtraction with no corresponding addition).
Before:
After: all of the above removed — the
implementsclause dropsMusicVideoListFragment.OnMusicVideoSelectedListener, the now-unusedimport org.xbmc.kore.ui.AbstractInfoFragment;is removed, the two constantsand two fields are gone, every method's music-video branch is gone, and
onMusicVideoSelected(...)is deleted entirely.MusicActivitynow onlytracks album/artist/genre selection state.
Follow-up cleanup (verified safe via Find Usages in Android Studio
before deleting, since "Music Videos" is also a real Kodi video-library
category and these classes needed to be confirmed as audio-section-only
first):
ui/sections/audio/MusicVideoListFragment.javaui/sections/audio/MusicVideoInfoFragment.javaTesting performed
.m3u/.plsfiles from a real Kodi instanceKnown limitations / possible follow-ups
its track list before committing (an intermediate "browse into it" step was
functional during development, since Kodi does support it, but was replaced
in favor of immediate play/queue for a simpler v1).
play/queue as a deliberate follow-up action, similar to how Album details
work — is a natural next step if immediate play/queue turns out to be too
eager for some users.