Skip to content

[WIP] Initial multiple queues support#865

Draft
mikooomich wants to merge 9 commits intoFoedusProgramme:betafrom
mikooomich:multiqueue
Draft

[WIP] Initial multiple queues support#865
mikooomich wants to merge 9 commits intoFoedusProgramme:betafrom
mikooomich:multiqueue

Conversation

@mikooomich
Copy link
Copy Markdown
Collaborator

To test: Enable in Flags.kt, then enable settings toggle

[Rest of pr details to be filled out later]

customExtras.putInt("index", index)
}, Bundle.EMPTY
).get().extras.run {
if (containsKey("allQueues")) {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why bother with containsKey if you throw anyway, you can just let the !! do its job

/**
* Deletes a queue.
*
* When deleting the active queue,
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

,

if (index == masterQueues.lastIndex) {
masterQueues.removeAt(index)
if (index <= 0) {
player.pauseAllPlayersAndStopSelf() // TODO: correct way to stop playback
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just removeMediaItems()

val endedWorkaroundPlayer
get() = mediaSession?.player as EndedWorkaroundPlayer?
private var controller: MediaBrowser? = null
val qb: QueueBoard = QueueBoard(this)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe should be inited in onCreate

}

// TODO: shuffle and repeat mode
fun MediaController.playQueue(
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you are doing this at the wrong level, Android AUto for example will just not call your SERVICE_QB_ENQUEUE, it will keep doing setMediaItems(). Instead a player wrapper should give old queue to queueboard before executing setMediaItems()

/**
* Retrieve a song given a song ID. Returns null if no song is found
*/
fun findSong(mediaId: String): MediaItem? {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

unused?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For future uses. Should i remove it for the time being?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

having smth for future use is ok if you know for what use, but atleast for me its not really clear what its useful for


val current = (instance?.currentMediaItemIndex ?: 0)
if (current > playlistAdapter.playlist.second.size) {
// hax to workaround ui loading itself 4 times
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

?

controller?.setMediaItems(albums.shuffled().flatMap { it.songList })
controller?.prepare()
controller?.play()
controller?.playQueue(
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cf, this ui code shouldnt be changed. isOriginal is always true after setMediaItems(), it should only be considered changed after add/remove/move(/replace if id changed)


if (startIndex == 0) {
val playerItemCount = plr.mediaItemCount
// player.player.replaceMediaItems seems to stop playback so we
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

replaceMediaItems probably does but replaceMediaItem without s does not, update current song with repalceMediaItem too

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The currently playing media item can be at any index, and it needs to become the first index.. I'm not sure how replaceMediaItem would work better than what I current have.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I mean in addition to what you have, as replaceMediaItem updates metadata without interruptting playback

return null
}

// I have no idea why this value gets reset to 0 by the end... but ig this works
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

?

<string name="actions_query_shuffle_specific">shuffle $item_name</string>
<string name="please_allow_to_delete">Press allow to delete files</string>
<string name="choose_sd">Choose %s</string>
<string name="settings_mq_preview">Enable multiple queues preview</string>
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

try to avoid mentioning preview, instead use strings that can be reused once feature is stable, to avoid double work for translators

* And so it begins: My attempt to implement one of OuterTune's most
  cursed features (code wise), but without programming crimes.
* LocalDateTime methods shouldn't need sdk 26. Figure it out later
@mikooomich mikooomich force-pushed the multiqueue branch 2 times, most recently from 02e20d1 to 4304106 Compare April 8, 2026 14:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants