BLeeEZ / amperfy

Amperfy is an iOS/iPadOS/macOS app to play songs from an Ampache or Subsonic server
GNU General Public License v3.0
502 stars 40 forks source link

[Feature]: implement queuing such as is done in the Spotify app #34

Closed sandersantema closed 2 years ago

sandersantema commented 3 years ago

I was wondering whether you'd be interested in implementing queuing such as is done in the Spotify app and whether you are already familiar with this behavior (if not I could describe it in detail to make implementation easier).

It basically works like the following:

This is how it looks: image

I could elaborate more on the exact behavior and arguments on why I think this is better behavior than for instance the Apple Music app queuing if you might be interested in implementing this.

BLeeEZ commented 3 years ago

This looks really interesting and helpful. I think I will add this feature soon.

sandersantema commented 3 years ago

Would you still like a more in-depth description of the spotify behavior? I can try to do a little write up on what exactly happens when and how.

BLeeEZ commented 3 years ago

Yeah I think a in-depth description would be nice. I was thiniking of simply adding the song to the player as next song to play.

sandersantema commented 3 years ago

In spotify you have a user queue and what I'll call a context queue a third element of spotify's queuing system is the current song. The queues can be seen in this screenshot, the text of spotify itself is not that important and in Dutch but you might be able to understand it just fine if I'm to believe the domain of the email address on testflight, hello neighbor! :)

Current Song

The current song, can be mutated by the following three actions:

  1. Action c1: A song which is played manually because of user interaction i.e. clicking on a song, shuffling a playlist, album etc.
  2. Action c2: The following song in the user queue
  3. Action c3: The following song in the context queue

Context queue

The context queue is mutated by action c1 and c3. Action c1 changes the whole context queue depending on what the context of the manually selected item is, e.g. an album, artist, playlist, genre (which don't exist in Spotify but I'd imagine it should be part of this list in Amperfy) and others. Action c2 obviously just pops the top item of the user queue which then becomes the current song. Action c3 is the same but will only occur whenever the user queue is empty.

User queue

This is what makes the Spotify queuing system special and very nice to use in my opinion.

The user queue is only mutated by the following actions:

  1. Action u1: The user queues a song in one of two ways:

    1. The user swipes a song to the right such as can be seen in this screenshot, the song will then be appended to the user queue which is FIFO by default instead of the default LIFO of apple's queuing system.
    2. The user rearranges the order of the user queue or adds new songs from the context queue to the user queue by grabbing the handlebars as indicated by a red circle/ arrow in this screenshot
  2. Action u2: The head of the queue becomes the current playing song, this occurs together with action c2.

  3. Action u3: The user can wipe the whole user queue using a button which can be seen in this screenshot with a red circle around it, the button text says: "Erase queue".

As you can see all of these actions require manual interaction of the user. Changing the current playing song and context queue don't mutate the user queue.

Why is this so handy? Well say that I want to have a nice queue of songs before stepping into my car, so that I won't be distracted by choosing music to play while driving, I queue some songs but I'm not sure whether I'd want to play song X. When using the apple music app it's game over, I can't play the song since it will wipe my queue, I can only queue the song play it and then decide whether I like it. In Spotify you can play the song without having to worry about changing the user queue since you can change the current song without mutating the user queue.

In the Apple Music app there's no separation between the user queue and context queue which I think is insane. If I'm queuing songs it means just directly playing some genre, artist or album didn't suit my needs and I didn't have a playlist which fits the occasion either. If I wanted to use the context queue I wouldn't have used the user queue anyways! It seems that in the apple music app queuing is seen as an extension of playlists while in Spotify it serves as another mechanism for when no playlist or context is appropriate.

I hope this was somewhat of an in depth explanation instead of unclear ramblings but if anything is unclear I can add details.

BLeeEZ commented 3 years ago

Thank you for this in depth description. This feature is really nice. I think the time to implement this is quite high. I add this to the feature list.

BLeeEZ commented 3 years ago

I am currently working on this feature and I have some questions regarding the behavior.

As example please take a look at the following picture:

Simulator Screen Shot - iPhone 11 - 2021-11-10 at 16 04 51

There we have the red songs 1, 2 and 3. Currently the songs "Example Artists - Good Morning" is playing. What is the expected behavior when I press on song red 2? (a) Is song red 1 removed from the user queue without playing? => song red 2 is playing and the user queue displays song red 3 (b) Is song red 2 prioritized higher? => song red 2 is playing and the user queue displays songs red is 1, 3?

An other important question: What happens with songs from the user queue if they have been played? (a) They are simply removed and are not displayed in the Player anymore? (b) They are displayed in the played previous section (same behavior as regular played songs)?

Should the swipe to the right also be available in the Popup player view or only in the library views (songs, playlist details, ...)?

How to name the section names? Currently the section names in the PopupPlayer are "Previous" and "Next". How are the new sections should be named (there are now three sections or two if no song is in the user queue)?

BLeeEZ commented 3 years ago

Do artists/albums/playlists have the right swipe too?

sandersantema commented 2 years ago

Just tried it out on Spotify, apparently they don't. But I think that could actually be a very nice improvement. They do allow you to queue the artist or album via one of those circles with three dots in them menu's. But I could really think of a ton of cases where this would be a lot nicer, think of queuing multiple albums whole because you'd like to listen to the whole album, in spotify this would take five taps and swipes in total, one simple swipe would be a lot faster!

BLeeEZ commented 2 years ago

Waiting is implemented with these two commits: f02233b930de48a48be7d17c661b6609040380bf 2c31d0a641ef8ea4cba6f144c9f2ab4005750e8b

Currently only songs and podcast episodes can be added to the waiting queue via a right swipe.

BLeeEZ commented 2 years ago

Could you please give me some feedback about the implemented behavior? Behaves it as you expect it to be?

sandersantema commented 2 years ago

Hi sorry for the delay. There are a few things I think could be polished. In short I think it would be nice to be able to queue everything, including artists, albums, genres, directories and playlists in the same way you queue songs. I also think the wording of the queue could be a bit better, I rather like the way spotify did it:

image

What's particularly nice about this queue is that it also shows you the context of what is playing next.

Would you like me to create new issues for these improvement suggestions or extend on them here?

sandersantema commented 2 years ago

continued here: https://github.com/BLeeEZ/amperfy/issues/85#issue-1093480517

First of all a few definitions (because I noticed I use a lot of words of which the meaning isn't clear):

I forgot about a big one: automatic context switching of the non user queue. The context is changed whenever a user manually taps on one of the possible contexts enumerated above. Automatically switching the context would replace the Play all button and make the context switch implicit. As far as I can think of this reduces the amount of clicks needed to get the queue like you want it quite a lot and works really well together with a user queue since the user queue never changes context (it doesn't have one either). It would furthermore then be possible to replace the Play all button with a shuffle button (the functionality of the play all button is replaced by simply clicking the first song in a context). This further reducing the amount of taps needed to shuffle which currently takes two taps. Two taps isn't that much but for some users like me who mostly shuffle certain playlists these two taps add up, with a shuffle button it would only take one.

Here's an example use case to show how automatic context switching reduces the number of taps needed. If a user wants to play all songs in a playlist which come after certain song in a playlist what you'd have to do at the moment is add the whole playlist to the queue, open the queue, scroll down to the song (which can take quite some time if you've got a big playlist) and tap on the song. If I counted correctly this takes 4 taps excluding the scrolling needed to find the appropriate song in the queue.

If the context of the non user queue changed automatically you'd be done by clicking on the song in the playlist, thus only requiring one tap.

Again, I can open another issue for this and can think of more use cases if you're not quite convinced yet. Let me know what is best for you.

BLeeEZ commented 2 years ago

I agree, everything should be queueable. I will add this for the next release.

The complete context switch/ "play all" behavior is a lot more effort that I will not implement till the next release. I am also not quite convinced about this context mechanism. The naming of the queue makes sense if the player context is implemented. Your explanation was good and I think I have now a better understanding of your request. Could you take your explanation above and open a new feature request?

Are there any other suggestions regarding the current "waiting queue" implementation? Should the waiting queue still be renamed?

sandersantema commented 2 years ago

referencing https://github.com/BLeeEZ/amperfy/issues/34#issuecomment-1004347794

The naming of the queue makes sense if the player context is implemented. Are there any other suggestions regarding the current "waiting queue" implementation? Should the waiting queue still be renamed?

I think it would still be a good idea to rename the user queue from Waiting Queue to Next In Queue, if automatic context switching is implemented the context could always be added to the non-user queue. Even more so, Spotify desktop does the same and doesn't indicate the context.

BLeeEZ commented 2 years ago

I renamed it to "Next in Queue" with be933d8acc7f2dffd98e496c415fece09f8d764e

BLeeEZ commented 2 years ago

Did you get time to test this feature in beta v1.1.0? I am interested to hear if there are any bugs or adjustments needed for this feature.

Is the behavior correct if a song from a new context is played?

sandersantema commented 2 years ago

As of now it seems there are some bugs in the new queueing system, there seem to be some weird interactions between queued songs and the context queue.

If I for instance queue a song to the user queue and press play on a playlist the expected behavior would be that the playlist would start playing and the queued song would be played after the current song if I skip to the next song. Currently however the queued song is played when pressing the play button.

Another example is if I queue something to the user queue (or something which had previously been queued in the user queue is playing) pressing play on any other song doesn't work.

I'll pay closer attention and figure out what is happening exactly, I'll try and see if I can figure some more out by looking at the code as well. Since it's not completely clear to me currently whether these behaviors and functions are bugs or if you meant to implement them like that. So for now I think it's best to leave this issue open and resolve other potential bugs in new issues.

BLeeEZ commented 2 years ago

OK thank you for your feedback. Your mentioned bugs are currently intended behavior. Here my questions regarding these edge cases.

1) assumption: there are some songs in the user queue. user action: the user presses on a song in playlist. expected behavior: the context queue gets replaced with the playlist of the pressed song. The pressed song gets immediately played. The context queue (previous and next) are according to the position of the pressed song in the playlist. The user queue is directly placed below the now playing pressed song (the next song which will be played is the first song of the context queue).

2) assumption: currently a song from the user queue is playing user action: the user presses on a song in playlist. behavior question: now playing song and context queue should behave like 1). What happens with the previously playing user queue song: a) it gets removed. b) it gets added to user queue again as the first item (it will be next song to be played)

The above describe scenarios should behave the same if the play button is pressed in a playlist (the first song of the playlist is the "pressed" song). Are the describe scenarios correct?

sandersantema commented 2 years ago

Is 1. currently implemented? It doesn't seem to be in the current version on testflight. But the behavior described in 1. is exactly what I meant in my proposal.

  1. Play a song from a playlist, i.e. don't queue it but play it directly by clicking on the song.
  2. Queue a song from the same playlist to the user queue, called song A.
  3. Press on another song from the playlist, called song B, now song A starts playing while song B was expected to start playing.

In regards to 2. I think a is most logical, given that when a song is playing already it is not part of any queue anymore. If I did want it to be part of the user-queue I shouldn't have skipped to it in the first place or should queue it again.

In short I think a currently playing song should not be part of the user queue. I suppose this should simplify the current logic for queuing quite a bit as well.

BLeeEZ commented 2 years ago

1. is currently not implemented, you are right. After my vacation I will implement 1. and 2.a).

BLeeEZ commented 2 years ago

Is the queuing behaviour now correct?

sandersantema commented 2 years ago

It seems so yes, although there might be some edge cases but in general the functionality is very very good so it isn't noticeable if there are. I'll open a new issue if I find another bug. Thanks a lot for implementing this :)