MusicPlayerDaemon / MPD

Music Player Daemon
https://www.musicpd.org/
GNU General Public License v2.0
2.17k stars 352 forks source link

directory listing: option to sort by filename, directories first #855

Closed sebastian-de closed 4 years ago

sebastian-de commented 4 years ago

I first opened a similar issue for the MPD client myMPD, but the maintainer suggested to open an issue here (myMPD issue).

Feature request

It would be nice to have a configuration option to sort MPD directory listings by filename. Ideally the folders would be listed first.

To be more specific: when I browse a directory using a MPD-client, I'd like it to be sorted like the output of tree -L 1 <directory>

Example

Output of tree -L 1 <directory>

``` $ tree -L 1 Hip\ Hop/Roots\ Manuva Hip Hop/Roots Manuva ├── 1999 Brand New Second Hand ├── 2001 Run Come Save Me ├── 2002 Dub Come Save Me ├── 2005 Awfully Deep ├── 2005 Back to Mine ├── 2010 Roots Manuva meets Wrongtom - Duppy Writer ├── DJ Shadow - GDMFSOB (UNKLE UNCENSORED) feat. Roots Manuva.mp3 ├── Roots Manuva - Colossal Insight (Manoustic at Reading).mp3 ├── Roots Manuva - Stolen Youth.mp3 └── Roots Manuva - Stolen Youth (Segal Remix).mp3 ```

MPD API command lsinfo of that same directory returns:

``` [{'file': 'Hip Hop/Roots Manuva/Roots Manuva - Colossal Insight (Manoustic at Reading).mp3', 'last-modified': '2017-01-30T17:41:43Z', 'format': '44100:24:2', 'time': '240', 'duration': '239.960', 'artist': 'Roots Manuva', 'albumartist': 'Roots Manuva', 'title': 'Colossal Insight (Manoustic at Reading)', 'album': 'Awfully Deep'}, {'file': 'Hip Hop/Roots Manuva/Roots Manuva - Stolen Youth.mp3', 'last-modified': '2017-01-30T17:41:44Z', 'format': '44100:24:2', 'time': '225', 'duration': '224.679', 'artist': 'Roots Manuva', 'albumartist': 'Roots Manuva', 'title': 'Stolen Youth', 'album': 'Stolen Youth', 'track': '2', 'date': '2013', 'disc': '1'}, {'file': 'Hip Hop/Roots Manuva/Roots Manuva - Stolen Youth (Segal Remix).mp3', 'last-modified': '2017-01-30T17:41:43Z', 'format': '44100:24:2', 'time': '197', 'duration': '197.355', 'artist': 'Roots Manuva', 'albumartist': 'Roots Manuva', 'title': 'Stolen Youth (Segal Remix)', 'album': 'Stolen Youth', 'track': '3', 'date': '2013', 'disc': '1'}, {'file': 'Hip Hop/Roots Manuva/DJ Shadow - GDMFSOB (UNKLE UNCENSORED) feat. Roots Manuva.mp3', 'last-modified': '2017-01-30T17:41:43Z', 'format': '44100:24:2', 'time': '386', 'duration': '385.906', 'artist': 'DJ Shadow', 'albumartist': 'DJ Shadow', 'title': 'GDMFSOB (UNKLE UNCENSORED) feat. Roots Manuva', 'album': 'The Private Repress', 'track': '3', 'date': '2003'}, {'directory': 'Hip Hop/Roots Manuva/1999 Brand New Second Hand', 'last-modified': '2017-06-04T12:57:30Z'}, {'directory': 'Hip Hop/Roots Manuva/2001 Run Come Save Me', 'last-modified': '2017-06-04T12:53:55Z'}, {'directory': 'Hip Hop/Roots Manuva/2002 Dub Come Save Me', 'last-modified': '2017-06-04T12:48:07Z'}, {'directory': 'Hip Hop/Roots Manuva/2005 Awfully Deep', 'last-modified': '2017-06-04T12:47:06Z'}, {'directory': 'Hip Hop/Roots Manuva/2005 Back to Mine', 'last-modified': '2017-06-04T12:47:42Z'}, {'directory': 'Hip Hop/Roots Manuva/2010 Roots Manuva meets Wrongtom - Duppy Writer', 'last-modified': '2017-06-04T12:52:23Z'}] ```

What I tried so far

  1. sort by filename I had a quick look and was able to sort the songs by filename by modifying song_list_sort() in db/plugins/simple/SongSort.cxx
  2. list directories first I also tried to modify Directory::Sort() in db/plugins/simple/Directory.cxx to get directories listed first, but wasn't able to achieve that.

I don't know if modifying the simple db plugin is the right approach to do that, or if it would be better to do this via db_selection_print.

Motivation I organize my music collection in a directory structure with many sub-directories, which can contain a lot of single files that don't belong to an album. When listening to music I usually browse these directories with a file manager and pick the songs I'd like to play. When the directories aren't sorted by filename, it takes much longer for me to find the music I'd like to hear.

MaxKellermann commented 4 years ago

You did not explain why this needs to be done server-side. Sorting is a way of displaying, and displaying is within the client's responsibility. Do you have a reason why MPD should do this and not the client?

sebastian-de commented 4 years ago

quoting https://github.com/jcorporation/myMPD/issues/256#issuecomment-622071468

Client side sorting is slow and error prone. I think you should open an issue for MPD.

I don't know if this is true or not. However other protocol commands that query the db like find or search already provide a server side way for sorting the results. The result of lsinfo currently gets sorted too, but the sorting defaults to the album tag. It would be nice to make this configurable either similar to the protocol commands mentioned above, or a configuration option. If this is implemented in MPD, all clients could benefit from this and don't have to implement sorting by themselves.

But if this is something that's not wanted server side at all I'm fine.

jcorporation commented 4 years ago

Extending the protocol by a sort and a window option would be ideal for clients. It should be faster if the server sorts and transfers only the wanted range of the result to the client. Especially if the list is long as described by @sebastian-de.

If client sorts: myMPD (server process) gets the whole unsorted list from MPD, sorts the list in memory and puts the requested range from the sorted list to the client.

If server sorts: myMPD can transfer the requested range directly to client.

If the output of lsinfo is already sorted as sebastian-de wrotes than we sort one result unnecessarily a second time.

MaxKellermann commented 4 years ago

However other protocol commands that query the db like find or search already provide a server side way for sorting the results.

Because those commands have a window parameter which makes only sense if you have a well-defined ordering.

lsinfo (which this request is about) doesn't have this. That's why @jcorporation's argument can't be applied.