Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Smart Playlists #1417

Open
12 of 25 tasks
deluan opened this issue Oct 19, 2021 · 186 comments
Open
12 of 25 tasks

Smart Playlists #1417

deluan opened this issue Oct 19, 2021 · 186 comments

Comments

@deluan
Copy link
Member

deluan commented Oct 19, 2021

Smart playlists can be created as a json object into a file with .nsp extension and Navidrome will create a dynamic/query based playlist and keep it updated. These .nsp files will be imported the same way as normal playlists, i.e. at scan time. See comment below for a complete list of fields and operators available.

Some examples:

  • Recently Played:
{
  "name": "Recently Played",
  "comment": "Recently played tracks",
  "all": [
    {"inTheLast": {"lastPlayed": 30}}
  ],
  "sort": "lastPlayed",
  "order": "desc",
  "limit": 100
}
  • 80's Top Songs
{
  "all": [
    { "any": [
      {"is": {"loved": true}},
      {"gt": {"rating": 3}}
    ]},
    {"inTheRange": {"year": [1981, 1990]}}
  ],
  "sort": "year",
  "order": "desc",
  "limit": 25
}
  • Favourites
{
  "all": [
    {"is": {"loved": true}}
  ],
  "sort": "dateLoved",
  "order": "desc",
  "limit": 500
}
  • All songs in random order (not recommended for large libraries)
{
  "all": [
    {"gt": {"playCount":-1}}
  ],
  "sort": "random"
}

TODO

  • PHASE 1 - On demand

    • Add rules to playlists table
    • Rule compiler (to SQL)
    • Calculate tracks on get
      • Cache results (for 5 secs)
    • Import smart playlists found in Music Folder (extension .NSP)
    • Handle permissions
      • Smart Playlists (tracks) are read-only
      • Cannot be shared
    • Refactor and clean up
  • PHASE 2 - Live update

    • Update fields table on smart playlist create/update
    • Live update queue: Persistent queue (SQLite3?) to store id and rules of playlist to process
    • SP queue processor: get id and rules from queue and refresh tracks based on rules
    • UpdateNotifier (in memory)
      • Group updates (10 items or 3 secs idle)
      • Add playlists to live update queue
      • Call it from Media Annotations and Scanner (when new tracks are imported)
  • PHASE 3 - UI

    • Rule editor
    • Reorganize sidebar
  • MISCELANEOUS

    • Sort by "random"
    • Album and Artist attributes
    • Add a "playlist" field - see how to use it
@deluan
Copy link
Member Author

deluan commented Nov 18, 2021

Current list of fields available (case-insensitive):

title
album
artist
albumartist
hascoverart
tracknumber
discnumber
year
size
compilation
dateadded
datemodified
discsubtitle
comment
lyrics
sorttitle
sortalbum
sortartist
sortalbumartist
albumtype
albumcomment
catalognumber
filepath
filetype
duration
bitrate
bpm
channels
genre
loved
dateloved
lastplayed
playcount
rating

Operators available (case-insensitive):

is
isNot
gt
lt
contains
notContains
startsWith
endsWith
inTheRange
before
after
inTheLast
notInTheLast
inPlaylist
notInPlaylist

@RedKage
Copy link

RedKage commented Nov 19, 2021

Hello, not sure if I should post this here or make a new issue.
I have a use case which is to find all the songs which are unrated. I want to find those which have no star.

I played a bit with the NSP, and my take is that it's like an expression tree which builds SQL queries. Haven't looked at the source, yet. And indeed, the "problem" is that
select * from annotation where rating = 0 and item_type = 'media_file'
returns only the songs with no rating, but they still need to have a row in the annotation table.

In effect I have only 10 songs returned without star. When in actuality I have thousands, but these have never been annotated.
So they are never in the scope of the expression tree. So they can never be found? Or is there another way?

EDIT: I wonder if there's like some sort of left outer join or something that would still target media_files which have no annotations yet, kinda like changing that LeftJoin in persistence/playlist_repository.go:207

@deluan
Copy link
Member Author

deluan commented Nov 19, 2021

Hello, not sure if I should post this here or make a new issue.

That's fine

I played a bit with the NSP, and my take is that it's like an expression tree which builds SQL queries. Haven't looked at the source, yet. And indeed, the "problem" is that select * from annotation where rating = 0 and item_type = 'media_file' returns only the songs with no rating, but they still need to have a row in the annotation table.

Yes, that's how it works, and yes, this is a "problem". I think a good approach for this is to introduce a new operator, isSet (true/false) that will be converted to is null/is not null and will allow these use cases where you don't have the record in the annotation table.

EDIT: I wonder if there's like some sort of left outer join or something that would still target media_files which have no annotations yet, kinda like changing that LeftJoin in persistence/playlist_repository.go:207

It is already a left join, the issue is that when there's no matching row in the annotation table, its values are all null

@deluan
Copy link
Member Author

deluan commented Nov 19, 2021

I actually did some experimentation and I think a better way is to wrap all fields from the left joined tables with COALESCE, like this:

COALESCE(annotation.rating, 0 ) = 0)

This will allow to use "is": {"rating": 0} in the NSP file.

deluan added a commit that referenced this issue Nov 20, 2021
@0bmay
Copy link

0bmay commented Nov 20, 2021

First off, thanks for the smart playlists.. It really opens up the possibilities for Navidrome!

using the latest docker image (Navidrome Version: | 0.47.0 (8c7d95c)), trying to use dateadded and datemodified return invalid key errors. I'm attempting to make a Songs newly added and unrated playlist.. I took a cue from the random sorting post on reddit. Not sure if it would work, but it appears I can't filter on dateadded or datemodified. I'm assuming I'm doing something wrong, but just in case....

{
"all": [
{"is": {"rating": 0}},
{"datemodified": {"gt": "DATE('now','-90 day')"}}, -- using this line or the next..
{"dateadded": {"gt": "DATE('now','-90 day')"}}
],
"sort": "dateadded",
"order": "asc",
"limit": 100
}

time="2021-11-20T00:56:54Z" level=error msg="Error parsing SmartPlaylist" error="invalid expression key dateadded" playlist="Songs to Rate - Newly Added" requestId=e31872cd1409/MIUyT3LsdO-001067,
time="2021-11-20T00:56:54Z" level=error msg="Error parsing playlist" error="invalid expression key dateadded" path="/music/playlists/Songs to Rate - Newly Added.nsp" requestId=e31872cd1409/MIUyT3LsdO-001067,
time="2021-11-20T01:02:46Z" level=error msg="Error parsing SmartPlaylist" error="invalid expression key datemodified" playlist="Songs to Rate - Newly Added" requestId=e31872cd1409/MIUyT3LsdO-001108,
time="2021-11-20T01:02:46Z" level=error msg="Error parsing playlist" error="invalid expression key datemodified" path="/music/playlists/Songs to Rate - Newly Added.nsp" requestId=e31872cd1409/MIUyT3LsdO-001108,

@deluan
Copy link
Member Author

deluan commented Nov 20, 2021

Hey @0bmay, the issue is that the key of the rule has to be the operator, not the field. So in the snippet:

{"dateadded": {"gt": "DATE('now','-90 day')"}}

should be:

{"gt": {"dateadded": "DATE('now','-90 day')"}}

Also notice the operator inTheLast, that was created specifically for this type of rules:

{"inTheLast": {"dateadded": "90"}}, 

I don't even know if DATE('now','-90 day') will work..

@0bmay
Copy link

0bmay commented Nov 20, 2021

Thank you @deluan!

@MichaelBechHansen
Copy link

Smart playlists are similar, but not the same as normal playlists in the Subsonic API - yet they are exposed via the same API endpoints. Some differences are, smart playlists are readonly, and are auto regenerated on read (I believe).
This poses some challenges for client apps / API consumers.

For client apps to be able to give a good user experience, information about what playlists are smart (readonly, auto regenerated) and what playlists are user edited is necessary. This information does not seem to be present with the current implementation.

Some points from a discord discussion on smart playlists in the context of the Subsonic API:

Is there any way of distinguishing smart playlists from plain old user-maintained playlists?

  • so an app does not offer to add tracks to a smart playlist.
  • so an app can know whether it syncs a changed user maintained playlist OR is refreshing a smart playlist.
  • ...

Suggestion for one way to add extra information to the Subsonic API:

I think it's pretty safe to add properties to the existing Subsonic JSON/XML response outputs.
So one way could be to add a "navidrome:properties" object to the playlists:
"playlist": [
{
"navidrome:properties": {
"type": "smart", // smart, manual
....
}
"id": "af1a19a2-bafe-4b17-841c-73b0175891a3",
"name": "ABC",
"songCount": 0,
"duration": 0,
"public": false,
"owner": "demo",
"created": "2021-11-28T07:21:40.384665077Z",
"changed": "2021-12-03T09:13:46.098202015Z"
},

...

The presence of the "navidrome:properties" could also be conditional on the client sending some magic parameter in the request.

So in sum, one way to deliver extra playlist information to client apps would be:

  • Add an extra, custom parameter to the getPlaylists.view request, for example: extensions=yes. When the server sees extensions=yes, it will output additional, non-standard, properties in the response.
  • API consumers will have given the extensions=yes parameter, and be prepared to handle custom properties like "navidrome:properties".
  • Legacy client apps will not give this parameter, and will therefore never see anything new.

@aewne
Copy link

aewne commented Dec 14, 2021

Would it be possible to add playlist name/id as a selector field for the smart playlists? That way you can mix playlists together without all the hassle that it is now.

@AndersMoberg
Copy link
Contributor

AndersMoberg commented Dec 20, 2021

I renamed my NSP files to include emoji, and Navidrome started counting them as separate playlists.. ergo, it wouldn't purge the smart playlists that didn't have a file still.

Green are the new files, yellow are the previous names of these playlists.

image

@certuna
Copy link
Contributor

certuna commented Dec 20, 2021

Yes, playlist import is a one-direction process unfortunately. Change the name of the m3u/nsp, and it gets re-imported as a new playlist.

@ryoku-cha
Copy link

Is there any way to assign the Smart Playlists to any user (or all users)?

I tried putting the following in the .nsp File. But that did not change anything.
"owner": "username"
-> where username was the username for my account.

Currently my Smart Playlists appear only for the "admin" User, but not for my daily use user-account.

@TheWrathKing
Copy link

Is there any way to assign the Smart Playlists to any user (or all users)?

Yes, this is possible in the UI. When logged in as admin, click on the icon next to the word "Playlists" on the left side menu and in this new screen you can make the playlists 'public' or edit them.
In the 'Edit' screen you can change the owner of the playlist.
Hope this will help

@deluan
Copy link
Member Author

deluan commented Jan 6, 2022

Would it be possible to add playlist name/id as a selector field for the smart playlists? That way you can mix playlists together without all the hassle that it is now.

@aewne Yes, this is planned.

@MichaelBechHansen, I think a generic property instead of navidrome:properties would be a better approach, that could be used by other server implementations

@RedKage
Copy link

RedKage commented Jan 22, 2022

Hello, just a heads up while testing v0.47.5, it seems some of my smart playlists NSP are broken.
After a full refresh my playlists got emptied.
They contain NSP like this one

{
  "all": [
    {"is": {"rating": "5"}}
  ],
  "sort": "playcount",
  "order": "desc"
}

Which was working fine on the previous version.

The issue is that the value, in the above 5 is a string with double quotes in my NSP.
I changed my NSP with "rating": 5 without double quotes, touched and refresh and now they all work properly.

It makes sense, the value is a number.

This works as of 0.47.5

{
  "all": [
    {"is": {"rating": 5}}
  ],
  "sort": "playcount",
  "order": "desc"
}

This is not a bug, just an observation.

Also confirmed "rating": 0 works!
Thanks for the new release!

@gardebreak
Copy link

I have a "Recently Played" smart playlist:

{
  "all": [
    {"inTheLast": {"lastPlayed": 30}}
  ],
  "sort": "lastPlayed",
  "order": "desc",
  "limit": 50
}

Only tracks that I play through the web UI will show up on the list. It seems any tracks played on an external client don't get marked as "played." Is that the expected behavior?

@deluan
Copy link
Member Author

deluan commented Jan 26, 2022

@RedKage thanks for reporting this. I'll check if I can keep supporting both syntaxes in future releases

@gardebreak, you need to enable "Scrobbling" in your Subsonic client, see #593

@0bmay
Copy link

0bmay commented Feb 5, 2022

I think the smart play list sorting by random may be broken.. I'm getting back items that are sorted by song title instead..

{
"all": [
{ "any": [
{"is": {"loved": true}},
{"gt": {"rating": 3}}
]},
{"notInTheLast": {"lastPlayed": 180}},
{"contains": {"genre": "metal"}},
],
"sort": "random()",
"limit": 25,
"source": "https://www.reddit.com/r/navidrome/comments/qxh3qu/comment/hl9fb6x/?utm_source=reddit&utm_medium=web2x&context=3"
}

this returns a list of:

#EXTINF:260,Corporate Avenger - $20 Bill
#EXTINF:186,Celtic Frost - (Beyond the) North Winds
#EXTINF:192,Spineshank - (Can't Be) Fixed
#EXTINF:256,The Crown - (I Am) Hell
#EXTINF:275,The Resistance - (I will) Die Alone
#EXTINF:426,Mudvayne - (K)now F(orever)
#EXTINF:340,Pantera - (Reprise) Sandblasted Skin
#EXTINF:185,Judas Priest - (Take These) Chains
#EXTINF:239,Mudvayne - -1
#EXTINF:262,Static-X - ...In a Bag
#EXTINF:192,Rise to Fall - ...Kills the Reason
#EXTINF:550,Seemless - ...Things Fall Apart
#EXTINF:378,Isis - 1,000 Shards
#EXTINF:201,Five Finger Death Punch - 100 Ways to Hate
#EXTINF:386,Megadeth - 1000 Times Goodbye
#EXTINF:374,Megadeth - 1000 Times Goodbye
#EXTINF:386,Megadeth - 1000 Times Goodbye
#EXTINF:232,36 Crazyfists - 11.24.11
#EXTINF:223,Lamb of God - 11th Hour (Remixed) [Remastered]
#EXTINF:350,Megadeth - 13
#EXTINF:396,Corrosion of Conformity - 13 Angels
#EXTINF:252,Black Label Society - 13 Years of Grief
#EXTINF:161,Seance - 13th Moon
#EXTINF:338,Iron Maiden - 2 A.M.
#EXTINF:360,Iron Maiden - 2 Minutes to Midnight

songs that match the criteria, that all start with symbols or numbers, sorted by title. I would expect the listing to be more random. I know there were some changes to the smart lists in the latest release. Did random get broken, or is there a new way to randomize the returned data?

Thank you for all the hard work on navidrome.

@deluan
Copy link
Member Author

deluan commented Feb 9, 2022

Yeah, the fix to avoid possible SQL injections also closed this loophole. I just pushed a fix for random. Now you have to specify "sort": "random" (without ()) and it should work. To test it out and use it, please update to the latest dev build

@0bmay
Copy link

0bmay commented Feb 9, 2022

Thanks! I run navidrome from a docker image, so I will have to wait for either a dev build or a the next release. I didn't see anything in the documentation on how to build a docker image.

@garethw11
Copy link

Hi, I've posted an idea for smart queries #3179 please provide any feedback in that Ideas discussion thread, see also https://github.com/garethw11/navidrome
Cheers, Gareth.

@Eidansoft
Copy link

Eidansoft commented Jul 31, 2024 via email

@janaxhell
Copy link

How can I exclude Compilations from a smart playlist?
I've made a few decade smart playlists like this one

{
  "all": [
    { "any": [
      {"is": {"loved": true}},
      {"gt": {"rating": 4}}
    ]},
    {"inTheRange": {"year": [2011, 2020]}},
  ],
  "sort": "random",
  "order": "desc",
  "limit": 500
}

but Compliations contain songs that have no relation to the compilation release date, so I see songs from the 80s/90s/00s even if the decade is 10s.
I have set all my albums with mp3Tag in the Grouping tag as Album/EP/Single/Live/Compilation/etc
In MusicBee I have cloned the same tag in the Disctype tag that is not visible in mp3Tag.
I see in the list at the beginning of this thread that there is a "compilation" entry that can be used in the smart playlists, but how do I use it? Does it refer to the same tags I've mentioned?
Because when I tried to add
{"compilation": false}
after
{"gt": {"rating": 4}}
Navidrome completely ignored the smart playlist.

@metalheim
Copy link
Contributor

How can I exclude Compilations from a smart playlist?

It works on the "compilation" tag (TCMP in id3 tags).
You can see this if an album has it set by clicking on the "three dot menu" -> more information.

Try adding the compilation tag and then add someting like this to your smartplaylist:

{"is": {"compilation": false}},

@janaxhell
Copy link

janaxhell commented Aug 3, 2024

Ok about the smartpalylist entry.
About TCMP in id3 tags: is this what in mp3Tag is Value->Extended Fields->Compilation and can be added to visible columns as %compilation%?
So I should retag all my compilations in that field with "1"?
EDIT
Seems like so: after adding that tag to visible columns, when I set it to "1", in MusicBee I see the tag "iTunes Compilation" changing from No to Yes.
EDIT2
Perfect, I've tagged all Compilations with "1" and the smartplaylist filtered them out.
Is there anything similar that can be done for Live albums for the same "wrong year" reason? I see there is no specific tag for that, so I tried {"notContains": {"album": "Live"}} , but many Live albums often do not have the word "Live" in the title (while others do and are not Live albums).

felipemarinho97 added a commit to felipemarinho97/navidrome that referenced this issue Aug 7, 2024
* Bump golang.org/x/sync from 0.6.0 to 0.7.0

Bumps [golang.org/x/sync](https://github.com/golang/sync) from 0.6.0 to 0.7.0.
- [Commits](golang/sync@v0.6.0...v0.7.0)

---
updated-dependencies:
- dependency-name: golang.org/x/sync
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

* Bump github.com/onsi/gomega from 1.31.1 to 1.32.0

Bumps [github.com/onsi/gomega](https://github.com/onsi/gomega) from 1.31.1 to 1.32.0.
- [Release notes](https://github.com/onsi/gomega/releases)
- [Changelog](https://github.com/onsi/gomega/blob/master/CHANGELOG.md)
- [Commits](onsi/gomega@v1.31.1...v1.32.0)

---
updated-dependencies:
- dependency-name: github.com/onsi/gomega
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

* Fix DiscTitle OpenSubsonic compatibility. Closes navidrome#2929

* Bump github.com/onsi/ginkgo/v2 from 2.15.0 to 2.17.1

Bumps [github.com/onsi/ginkgo/v2](https://github.com/onsi/ginkgo) from 2.15.0 to 2.17.1.
- [Release notes](https://github.com/onsi/ginkgo/releases)
- [Changelog](https://github.com/onsi/ginkgo/blob/master/CHANGELOG.md)
- [Commits](onsi/ginkgo@v2.15.0...v2.17.1)

---
updated-dependencies:
- dependency-name: github.com/onsi/ginkgo/v2
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

* Bump github.com/pressly/goose/v3 from 3.18.0 to 3.19.2

Bumps [github.com/pressly/goose/v3](https://github.com/pressly/goose) from 3.18.0 to 3.19.2.
- [Release notes](https://github.com/pressly/goose/releases)
- [Changelog](https://github.com/pressly/goose/blob/master/CHANGELOG.md)
- [Commits](pressly/goose@v3.18.0...v3.19.2)

---
updated-dependencies:
- dependency-name: github.com/pressly/goose/v3
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

* Update Go to 1.22.2 and TagLib to 2.0.1 (navidrome#2946)

* Bump github.com/pelletier/go-toml/v2 from 2.1.1 to 2.2.0

Bumps [github.com/pelletier/go-toml/v2](https://github.com/pelletier/go-toml) from 2.1.1 to 2.2.0.
- [Release notes](https://github.com/pelletier/go-toml/releases)
- [Changelog](https://github.com/pelletier/go-toml/blob/v2/.goreleaser.yaml)
- [Commits](pelletier/go-toml@v2.1.1...v2.2.0)

---
updated-dependencies:
- dependency-name: github.com/pelletier/go-toml/v2
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

* Bump github.com/go-chi/jwtauth/v5 from 5.3.0 to 5.3.1

Bumps [github.com/go-chi/jwtauth/v5](https://github.com/go-chi/jwtauth) from 5.3.0 to 5.3.1.
- [Release notes](https://github.com/go-chi/jwtauth/releases)
- [Commits](go-chi/jwtauth@v5.3.0...v5.3.1)

---
updated-dependencies:
- dependency-name: github.com/go-chi/jwtauth/v5
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

* Fix function name in comment (navidrome#2947)

Signed-off-by: looklose <shishuaiqun@yeah.net>

* Fix a few mistakes in the French translation (navidrome#2872)

Co-authored-by: Deluan Quintão <deluan@navidrome.org>

* Ignore formatting diffs when checking for POEditor changes

* Fix some typos in comments (navidrome#2949)

Signed-off-by: oftenoccur <ezc5@sina.com>

* Add make target to build docker image

* Bump follow-redirects from 1.15.4 to 1.15.6 in /ui (navidrome#2911)

Bumps [follow-redirects](https://github.com/follow-redirects/follow-redirects) from 1.15.4 to 1.15.6.
- [Release notes](https://github.com/follow-redirects/follow-redirects/releases)
- [Commits](follow-redirects/follow-redirects@v1.15.4...v1.15.6)

---
updated-dependencies:
- dependency-name: follow-redirects
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Bump @testing-library/jest-dom from 6.2.0 to 6.4.2 in /ui (navidrome#2845)

Bumps [@testing-library/jest-dom](https://github.com/testing-library/jest-dom) from 6.2.0 to 6.4.2.
- [Release notes](https://github.com/testing-library/jest-dom/releases)
- [Changelog](https://github.com/testing-library/jest-dom/blob/main/CHANGELOG.md)
- [Commits](testing-library/jest-dom@v6.2.0...v6.4.2)

---
updated-dependencies:
- dependency-name: "@testing-library/jest-dom"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Bump prettier from 3.2.2 to 3.2.5 in /ui (navidrome#2844)

Bumps [prettier](https://github.com/prettier/prettier) from 3.2.2 to 3.2.5.
- [Release notes](https://github.com/prettier/prettier/releases)
- [Changelog](https://github.com/prettier/prettier/blob/main/CHANGELOG.md)
- [Commits](prettier/prettier@3.2.2...3.2.5)

---
updated-dependencies:
- dependency-name: prettier
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Remove deprecation warning about `notify`

* Fix jukebox mode under Windows (navidrome#2774)

* bug(core/playback/mpv): jukebox mode under windows - navidrome#2767

Use named pipe for socket path under windows during mpv playback, change function name, unexport function

Signed-off-by: apkatsikas <apkatsikas@gmail.com>

* bug(core/playback/mpv): jukebox mode under windows - navidrome#2767

Fix typo

Signed-off-by: apkatsikas <apkatsikas@gmail.com>

* bug(core/playback/mpv): jukebox mode under windows - navidrome#2767

Early return for Close on Windows

Signed-off-by: apkatsikas <apkatsikas@gmail.com>

* bug(core/playback/mpv): jukebox mode under windows - navidrome#2767

Update import and run prettier

Signed-off-by: apkatsikas <apkatsikas@gmail.com>

* bug(core/playback/mpv): jukebox mode under windows - navidrome#2767

Update function name

Signed-off-by: apkatsikas <apkatsikas@gmail.com>

* bug(core/playback/mpv): jukebox mode under windows - navidrome#2767

Create track_close files for both platforms and move MpvTrack Close into new file

Signed-off-by: apkatsikas <apkatsikas@gmail.com>

* bug(core/playback/mpv): jukebox mode under windows - navidrome#2767

Create SocketName function for both platforms, restore name of TempFileName

Signed-off-by: apkatsikas <apkatsikas@gmail.com>

* bug(core/playback/mpv): jukebox mode under windows - navidrome#2767

Add missing params to SocketName on windows

Signed-off-by: apkatsikas <apkatsikas@gmail.com>

* Unexport SocketName, use socketName in NewTrack

---------

Signed-off-by: apkatsikas <apkatsikas@gmail.com>

* Bump github.com/pelletier/go-toml/v2 from 2.2.0 to 2.2.1 (navidrome#2956)

Bumps [github.com/pelletier/go-toml/v2](https://github.com/pelletier/go-toml) from 2.2.0 to 2.2.1.
- [Release notes](https://github.com/pelletier/go-toml/releases)
- [Changelog](https://github.com/pelletier/go-toml/blob/v2/.goreleaser.yaml)
- [Commits](pelletier/go-toml@v2.2.0...v2.2.1)

---
updated-dependencies:
- dependency-name: github.com/pelletier/go-toml/v2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Bump react-icons from 5.0.1 to 5.1.0 in /ui (navidrome#2957)

Bumps [react-icons](https://github.com/react-icons/react-icons) from 5.0.1 to 5.1.0.
- [Release notes](https://github.com/react-icons/react-icons/releases)
- [Commits](react-icons/react-icons@v5.0.1...v5.1.0)

---
updated-dependencies:
- dependency-name: react-icons
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Externalize MPV command template (navidrome#2948)

* externalise MPVTemplate

* Remove unnecessary comment

---------

Co-authored-by: Deluan <deluan@navidrome.org>

* Bump golang.org/x/net from 0.21.0 to 0.23.0 (navidrome#2962)

Bumps [golang.org/x/net](https://github.com/golang/net) from 0.21.0 to 0.23.0.
- [Commits](golang/net@v0.21.0...v0.23.0)

---
updated-dependencies:
- dependency-name: golang.org/x/net
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Fix issue in navidrome#2767 (comment)

* Block regular users from changing their own playlists ownership

* Allow comments in the NSP file.

See comment navidrome#1417 (comment)

* Fix typo

* Include MPV in release Docker image. Refers to navidrome#2910

* Bump github.com/onsi/gomega from 1.32.0 to 1.33.0 (navidrome#2968)

Bumps [github.com/onsi/gomega](https://github.com/onsi/gomega) from 1.32.0 to 1.33.0.
- [Release notes](https://github.com/onsi/gomega/releases)
- [Changelog](https://github.com/onsi/gomega/blob/master/CHANGELOG.md)
- [Commits](onsi/gomega@v1.32.0...v1.33.0)

---
updated-dependencies:
- dependency-name: github.com/onsi/gomega
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Handling long playlist comments (navidrome#2973)

Closes navidrome#1737

* wrapping playlist comment in a <Collapse> element

* Extract common collapsible logic into a component

---------

Co-authored-by: Deluan <deluan@navidrome.org>

* Use the RealIP middleware also behind a reverse proxy (navidrome#2858)

* Use the RealIP middleware only behind a reverse proxy

* Fix proxy ip source in tests

* Fix test for PR#2087

The PR did not update the test after changing the behavior, but the test still
passed because another condition was preventing the user from being created in
the test.

* Use RealIP even without a trusted reverse proxy

* Use own type for context key

* Fix casing to follow go's conventions

* Do not apply RealIP middleware twice

* Fix IP source in logs

The most interesting data point in the log message is the proxy's IP, but
having the client IP too can help identify integration issues.

* Fix scrobble error spam in the logs.

Relates to navidrome#2831 and navidrome#2975

* Add OpenSubsonic channelCount

* Fix typo in comment (navidrome#2974)

* Bump github.com/pressly/goose/v3 from 3.19.2 to 3.20.0

* Bump Go dependencies (navidrome#2976)

* Fix build

* Bump dependencies

* Bump github.com/spf13/viper from 1.15.0 to 1.18.2

* Add support for Reverse Proxy auth in Subsonic endpoints  (navidrome#2558)

* feat(subsonic): Add support for Reverse Proxy auth - navidrome#2557

Signed-off-by: Jeremiah Menétrey <superjun1@gmail.com>

* Small refactoring

---------

Signed-off-by: Jeremiah Menétrey <superjun1@gmail.com>
Co-authored-by: Deluan Quintão <deluan@navidrome.org>

* Add AlbumPlayCountMode config option (navidrome#2803)

Closes navidrome#1032

* feat(album_repository.go): add kodi-style album playcount option - navidrome#1032

Signed-off-by: Victor van der Veen <vvdveen@gmail.com>

* fix format issue and remove reference to kodi (now normalized)

Signed-off-by: Victor van der Veen <vvdveen@gmail.com>

* reduced complexity but added rounding

Signed-off-by: Victor van der Veen <vvdveen@gmail.com>

* Use constants for AlbumPlayCountMode values

---------

Signed-off-by: Victor van der Veen <vvdveen@gmail.com>
Co-authored-by: Deluan <deluan@navidrome.org>

* Add tests for AlbumPlayCountMode

* Add tests for AlbumPlayCountMode, change the calc to match the request from navidrome#1032

* Remove AlbumPlayCountMode from command line options

* Load mime_types from external file

* Refactor DB Album mapping to model.Album

* Refactor loadGenres, remove duplication

* Use signal.NotifyContext

* Fix signaler on Windows

* Fix int types in OpenSubsonic responses.

Refer to https://support.symfonium.app/t/symfonium-sync-crashes-when-tpos-is-not-an-int/4204

* Fix AlbumPlayCountMode. Closes navidrome#2984

* Fix PlaylistTracks's loadAllGenres. Fix navidrome#2988

* Bump Go dependencies

* Sort repeated lyrics that may be out of order (navidrome#2989)

With synchronized lyrics with repeated text, there is not a guarantee that the repeat is in order (e.g. `[00:00.00][00:10.00] a\n[00:05.00]b`).
This change will post-process lyrics with repeated timestamps in one line to ensure that it is always sorted.

* Fix typo

* Add `HTTPSecurityHeaders.CustomFrameOptionsValue` option.

Requested in navidrome#248 (comment)

* Fix CollapsibleComment in PlaylistDetails. Closes navidrome#2992

* Pin golangci-lint-action version as a workaround to fix the pipeline.

See golangci/golangci-lint#4695

* Improves golangci-lint configuration and workflow (navidrome#3004)

* chore: the default Go version is based on the go.mod

* chore: use linter configuration instead of exclude-rules

* chore: update workflow

* Persist adjusted volume (navidrome#2997)

Co-authored-by: Deluan Quintão <deluan@navidrome.org>

* Guard against missing active track (navidrome#2996)

Co-authored-by: Deluan Quintão <deluan@navidrome.org>

* Bump Go dependencies

* Limit access to Jukebox for admins only (configurable).

Closes navidrome#2849

* Fix ambiguous column when sorting media_files by created_at.

Fix navidrome#3006

* Change default transcodings to a proper typed struct

* Fix migration package name mismatch

* Make dependency injection more consistent

* Terminate all MPV instances when stopping Navidrome (navidrome#3008)

* Terminate all mpv instances when stopping Navidrome

* Exit trackSwitcher goroutine when terminating

* Remove potential race condition when starting the Playback device

* Fix lint error

* Removed unused and unneeded vars/functions

* Use device short name in log

* Small refactor

* Small nitpick

* Make start functions more uniform

* Make sorting lists by name/title case-insensitive (navidrome#2993)

* Make sort by order_* fields case-insensitive.

* Sort internet radios by name case-insensitive

* Clean up runNavidrome function

* Remove unused code

* Simplify normalized AlbumPlayCountMode calc

* fix: languageName for Persian (navidrome#3011)

"انگلیسی" is "English"

* Update Go to 1.22.3

* Fix M3U mimetype on Debian Bullseye

* Replace sync.WaitGroup with more appropriate errgroup.Group

* Bump actions/stale and dessant/lock-threads versions

* Bump actions/github-script to v7

* Add Catppuccin Macchiato Theme (navidrome#3014)

* Added Catppuccin Macchiato theme

* fixed index.js formatting

* Do not panic if when updatePlaylist is called with a non-existent ID.

Fix navidrome#2876

* Read sampleRate from audio files

* Add sampleRate to the DB

* Add samplingRate to OpenSubsonic responses

* Fix "Add download link to PR" workflow

* Refactor merge.FS

* Refactor cache.HTTPClient

* Uses Unix milliseconds support from standard Go lib

* Refactor random functions

* Simplify random.Int64 usage with generics

* Remove duplicated test

* Revert "Add download link to PR" workflow

* Change dsf mime-type to audio/x-dsf.

Fix navidrome#3021

* Update Go to 1.22.3

* Refactor to use more Go 1.22 features

* Rename MediaFolder to Library

* Store MusicFolder as a library in DB

* Associate main entities with library

* Fix race condition

* fix bug in jukebox: property unavailable (navidrome#3024)

* fix bug in jukebox: property unavailable

* fix lint error

* Fix memory leak in CachedGenreRepository (navidrome#3031)

that the scanner was run, the ttlcache was also created each time.
This caused (under testing with 166 genres in the database) the
memory consumed by navidrome to 101.18MB over approx 3 days; 96%
of which is in instances of this cache. Swapping to a singleton
has reduced this to down to ~ 2.6MB

Co-authored-by: Rob Emery <git@mintsoft.net>

* Improve resizeImage code readability

* Simplify image format detection code

* Simplify resources.FS

* Refactor random.WeightedChooser, unsing generics

* Fix lint error

* Always run docker steps (navidrome#3034)

* Fix docker publishing for PRs

* Revert "Fix docker publishing for PRs"

This reverts commit 15c9a0d.

* Revert "Always run docker steps (navidrome#3034)"

This reverts commit 5d41165.

* Deterministic pagination in random albums sort (navidrome#1841)

* Deterministic pagination in random albums sort

* Reseed on first random page

* Add unit tests

* Use rand in Subsonic API

* Use different seeds per user on SEEDEDRAND() SQLite3 function

* Small refactor

* Fix id mismatch

* Add seeded random to media_file (subsonic endpoint `getRandomSongs`)

* Refactor

* Remove unneeded import

---------

Co-authored-by: Deluan <deluan@navidrome.org>

* Add missing Test function

* Make first WebUI random page stick

* Update caniuse-lite

* Fix 32 bits builds

* Fix G404 gosec lint error

* Update Ukrainian translations (navidrome#3029)

Co-authored-by: deluan <331353+deluan@users.noreply.github.com>

* Show number of results from a query in the logs

* Bump github.com/matoous/go-nanoid/v2 from 2.0.0 to 2.1.0 (navidrome#3038)

Bumps [github.com/matoous/go-nanoid/v2](https://github.com/matoous/go-nanoid) from 2.0.0 to 2.1.0.
- [Release notes](https://github.com/matoous/go-nanoid/releases)
- [Commits](matoous/go-nanoid@v2.0.0...v2.1.0)

---
updated-dependencies:
- dependency-name: github.com/matoous/go-nanoid/v2
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Optimize SQLite3 access. Mainly separate read access from write access.

Based on tips from https://archive.is/Xfjh6#selection-257.0-278.0

* Replace panics with log.Fatals

* Fix XML marshaling of OpenSubsonic structured lyrics (navidrome#3041)

* Revert isDBInitialized

* Fix image stuttering (navidrome#3035)

* Fix image stuttering.

* Fix docker publishing for PRs

* Write tests for new square parameter.

* Simplify code for createImage.

---------

Co-authored-by: Deluan Quintão <deluan@navidrome.org>

* Small optimization in MediaFiles.ToAlbum()

* Bump github.com/onsi/ginkgo/v2 from 2.17.3 to 2.19.0 (navidrome#3054)

Bumps [github.com/onsi/ginkgo/v2](https://github.com/onsi/ginkgo) from 2.17.3 to 2.19.0.
- [Release notes](https://github.com/onsi/ginkgo/releases)
- [Changelog](https://github.com/onsi/ginkgo/blob/master/CHANGELOG.md)
- [Commits](onsi/ginkgo@v2.17.3...v2.19.0)

---
updated-dependencies:
- dependency-name: github.com/onsi/ginkgo/v2
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Simplify dbx wrapper

* Bump github.com/spf13/viper from 1.18.2 to 1.19.0 (navidrome#3068)

Bumps [github.com/spf13/viper](https://github.com/spf13/viper) from 1.18.2 to 1.19.0.
- [Release notes](https://github.com/spf13/viper/releases)
- [Commits](spf13/viper@v1.18.2...v1.19.0)

---
updated-dependencies:
- dependency-name: github.com/spf13/viper
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Bump prettier from 3.2.5 to 3.3.0 in /ui (navidrome#3069)

Bumps [prettier](https://github.com/prettier/prettier) from 3.2.5 to 3.3.0.
- [Release notes](https://github.com/prettier/prettier/releases)
- [Changelog](https://github.com/prettier/prettier/blob/main/CHANGELOG.md)
- [Commits](prettier/prettier@3.2.5...3.3.0)

---
updated-dependencies:
- dependency-name: prettier
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Fix tests expectations

* Refactor string utilities into its own package `str`

* Small refactoring

* Replace gg.If with cmp.Or

* Initialize Index Groups regex just once

* More micro-optimizations

* Small refactoring

* Fix race condition in external metadata retrieval

* Increase artist image url sizes.

See https://support.symfonium.app/t/artist-picture-less-compressed/4447

* Change resized image cache key

* Add R128_{TRACK,ALBUM}_GAIN support to the scanner (navidrome#3072)

* Add R128 gain tags support to the scanner

* Add R128 test to metadata_internal_test.go

* Pass explicit tag names to getGainValue function

* Don't expose `fullText` data in the Native API

* Bump prettier from 3.3.0 to 3.3.1 in /ui

Bumps [prettier](https://github.com/prettier/prettier) from 3.3.0 to 3.3.1.
- [Release notes](https://github.com/prettier/prettier/releases)
- [Changelog](https://github.com/prettier/prettier/blob/main/CHANGELOG.md)
- [Commits](prettier/prettier@3.3.0...3.3.1)

---
updated-dependencies:
- dependency-name: prettier
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

* Do not use lastFM api key and secret to determine if LastFM.Enabled should be set.

* Increase artist image url sizes.

See https://support.symfonium.app/t/artist-picture-less-compressed/4447

* Bump uuid from 9.0.1 to 10.0.0 in /ui

Bumps [uuid](https://github.com/uuidjs/uuid) from 9.0.1 to 10.0.0.
- [Changelog](https://github.com/uuidjs/uuid/blob/main/CHANGELOG.md)
- [Commits](uuidjs/uuid@v9.0.1...v10.0.0)

---
updated-dependencies:
- dependency-name: uuid
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

* Bump react-icons from 5.1.0 to 5.2.1 in /ui

Bumps [react-icons](https://github.com/react-icons/react-icons) from 5.1.0 to 5.2.1.
- [Release notes](https://github.com/react-icons/react-icons/releases)
- [Commits](react-icons/react-icons@v5.1.0...v5.2.1)

---
updated-dependencies:
- dependency-name: react-icons
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

* Bump golang.org/x/image from 0.16.0 to 0.17.0

Bumps [golang.org/x/image](https://github.com/golang/image) from 0.16.0 to 0.17.0.
- [Commits](golang/image@v0.16.0...v0.17.0)

---
updated-dependencies:
- dependency-name: golang.org/x/image
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

* Bump clsx from 2.1.0 to 2.1.1 in /ui

Bumps [clsx](https://github.com/lukeed/clsx) from 2.1.0 to 2.1.1.
- [Release notes](https://github.com/lukeed/clsx/releases)
- [Commits](lukeed/clsx@v2.1.0...v2.1.1)

---
updated-dependencies:
- dependency-name: clsx
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

* Bump ejs from 3.1.9 to 3.1.10 in /ui

Bumps [ejs](https://github.com/mde/ejs) from 3.1.9 to 3.1.10.
- [Release notes](https://github.com/mde/ejs/releases)
- [Commits](mde/ejs@v3.1.9...v3.1.10)

---
updated-dependencies:
- dependency-name: ejs
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

* Bump @testing-library/jest-dom from 6.4.2 to 6.4.5 in /ui

Bumps [@testing-library/jest-dom](https://github.com/testing-library/jest-dom) from 6.4.2 to 6.4.5.
- [Release notes](https://github.com/testing-library/jest-dom/releases)
- [Changelog](https://github.com/testing-library/jest-dom/blob/main/CHANGELOG.md)
- [Commits](testing-library/jest-dom@v6.4.2...v6.4.5)

---
updated-dependencies:
- dependency-name: "@testing-library/jest-dom"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

* Bump github.com/prometheus/client_golang from 1.19.0 to 1.19.1

Bumps [github.com/prometheus/client_golang](https://github.com/prometheus/client_golang) from 1.19.0 to 1.19.1.
- [Release notes](https://github.com/prometheus/client_golang/releases)
- [Changelog](https://github.com/prometheus/client_golang/blob/main/CHANGELOG.md)
- [Commits](prometheus/client_golang@v1.19.0...v1.19.1)

---
updated-dependencies:
- dependency-name: github.com/prometheus/client_golang
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

* fix album/media file random sort (navidrome#3089)

* Add http headers to trace log

* Wrap ttlcache in our own SimpleCache implementation

* Also use SimpleCache in cache.HTTPClient

* Upgrade to ttlcache/v3

* Evict expired items from SimpleCache

* Don't panic on PostScan errors. Fix navidrome#3118

* Bump golang.org/x/image from 0.17.0 to 0.18.0 (navidrome#3119)

Bumps [golang.org/x/image](https://github.com/golang/image) from 0.17.0 to 0.18.0.
- [Commits](golang/image@v0.17.0...v0.18.0)

---
updated-dependencies:
- dependency-name: golang.org/x/image
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Bump github.com/lestrrat-go/jwx/v2 from 2.0.21 to 2.1.0 (navidrome#3113)

Bumps [github.com/lestrrat-go/jwx/v2](https://github.com/lestrrat-go/jwx) from 2.0.21 to 2.1.0.
- [Release notes](https://github.com/lestrrat-go/jwx/releases)
- [Changelog](https://github.com/lestrrat-go/jwx/blob/develop/v2/Changes)
- [Commits](lestrrat-go/jwx@v2.0.21...v2.1.0)

---
updated-dependencies:
- dependency-name: github.com/lestrrat-go/jwx/v2
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Bump github.com/go-chi/chi/v5 from 5.0.12 to 5.0.14 (navidrome#3115)

Bumps [github.com/go-chi/chi/v5](https://github.com/go-chi/chi) from 5.0.12 to 5.0.14.
- [Release notes](https://github.com/go-chi/chi/releases)
- [Changelog](https://github.com/go-chi/chi/blob/master/CHANGELOG.md)
- [Commits](go-chi/chi@v5.0.12...v5.0.14)

---
updated-dependencies:
- dependency-name: github.com/go-chi/chi/v5
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Bump github.com/pressly/goose/v3 from 3.20.0 to 3.21.1 (navidrome#3114)

Bumps [github.com/pressly/goose/v3](https://github.com/pressly/goose) from 3.20.0 to 3.21.1.
- [Release notes](https://github.com/pressly/goose/releases)
- [Changelog](https://github.com/pressly/goose/blob/master/CHANGELOG.md)
- [Commits](pressly/goose@v3.20.0...v3.21.1)

---
updated-dependencies:
- dependency-name: github.com/pressly/goose/v3
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Bump prettier from 3.3.1 to 3.3.2 in /ui (navidrome#3097)

Bumps [prettier](https://github.com/prettier/prettier) from 3.3.1 to 3.3.2.
- [Release notes](https://github.com/prettier/prettier/releases)
- [Changelog](https://github.com/prettier/prettier/blob/main/CHANGELOG.md)
- [Commits](prettier/prettier@3.3.1...3.3.2)

---
updated-dependencies:
- dependency-name: prettier
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Bump @testing-library/jest-dom from 6.4.5 to 6.4.6 in /ui (navidrome#3096)

Bumps [@testing-library/jest-dom](https://github.com/testing-library/jest-dom) from 6.4.5 to 6.4.6.
- [Release notes](https://github.com/testing-library/jest-dom/releases)
- [Changelog](https://github.com/testing-library/jest-dom/blob/main/CHANGELOG.md)
- [Commits](testing-library/jest-dom@v6.4.5...v6.4.6)

---
updated-dependencies:
- dependency-name: "@testing-library/jest-dom"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Bump braces from 3.0.2 to 3.0.3 in /ui (navidrome#3085)

Bumps [braces](https://github.com/micromatch/braces) from 3.0.2 to 3.0.3.
- [Changelog](https://github.com/micromatch/braces/blob/master/CHANGELOG.md)
- [Commits](micromatch/braces@3.0.2...3.0.3)

---
updated-dependencies:
- dependency-name: braces
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Bump github.com/spf13/cobra from 1.8.0 to 1.8.1 (navidrome#3095)

Bumps [github.com/spf13/cobra](https://github.com/spf13/cobra) from 1.8.0 to 1.8.1.
- [Release notes](https://github.com/spf13/cobra/releases)
- [Commits](spf13/cobra@v1.8.0...v1.8.1)

---
updated-dependencies:
- dependency-name: github.com/spf13/cobra
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Remove unnecessary annotation table primary key

* Add Nuclear Theme (navidrome#3098)

* fix background color for nord theme (navidrome#3124)

* Bump github.com/go-chi/chi/v5 from 5.0.14 to 5.1.0 (navidrome#3126)

Bumps [github.com/go-chi/chi/v5](https://github.com/go-chi/chi) from 5.0.14 to 5.1.0.
- [Release notes](https://github.com/go-chi/chi/releases)
- [Changelog](https://github.com/go-chi/chi/blob/master/CHANGELOG.md)
- [Commits](go-chi/chi@v5.0.14...v5.1.0)

---
updated-dependencies:
- dependency-name: github.com/go-chi/chi/v5
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Bump github.com/unrolled/secure from 1.14.0 to 1.15.0 (navidrome#3127)

Bumps [github.com/unrolled/secure](https://github.com/unrolled/secure) from 1.14.0 to 1.15.0.
- [Release notes](https://github.com/unrolled/secure/releases)
- [Commits](unrolled/secure@v1.14.0...v1.15.0)

---
updated-dependencies:
- dependency-name: github.com/unrolled/secure
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Fix album sorting in Artist page

* Remove unnecessary Fragment component.

* Add Auto-Import toggle switch to playlists list view.

* Fix race condition

* Bump github.com/go-chi/httprate from 0.9.0 to 0.10.0 (navidrome#3160)

Bumps [github.com/go-chi/httprate](https://github.com/go-chi/httprate) from 0.9.0 to 0.10.0.
- [Commits](go-chi/httprate@v0.9.0...v0.10.0)

---
updated-dependencies:
- dependency-name: github.com/go-chi/httprate
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Add Hungarian language (navidrome#3157)

* Use SHA256 in Gravatar URLs

* Fix "Cannot read properties of undefined". Closes navidrome#3070

* Bump github.com/microcosm-cc/bluemonday from 1.0.26 to 1.0.27 (navidrome#3141)

Bumps [github.com/microcosm-cc/bluemonday](https://github.com/microcosm-cc/bluemonday) from 1.0.26 to 1.0.27.
- [Release notes](https://github.com/microcosm-cc/bluemonday/releases)
- [Commits](microcosm-cc/bluemonday@v1.0.26...v1.0.27)

---
updated-dependencies:
- dependency-name: github.com/microcosm-cc/bluemonday
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Bump github.com/onsi/gomega from 1.33.1 to 1.34.0 (navidrome#3176)

Bumps [github.com/onsi/gomega](https://github.com/onsi/gomega) from 1.33.1 to 1.34.0.
- [Release notes](https://github.com/onsi/gomega/releases)
- [Changelog](https://github.com/onsi/gomega/blob/master/CHANGELOG.md)
- [Commits](onsi/gomega@v1.33.1...v1.34.0)

---
updated-dependencies:
- dependency-name: github.com/onsi/gomega
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Use userId in player, other fixes (navidrome#3182)

* [bugfix] player: use userId, other fixes

This PR primarily resolves navidrome#1928 by switching the foreign key of `player` from `user.user_name` to `user.id`.
There are also a few other fixes/changes:

- For some bizarre reason, `ip_address` is never returned from `read`/`get`. Change the field to `ip`, which works. Somehow
- Update `players_test.go` mock to also check for user agent, replicating the actual code
- Update `player_repository.go` `isPermitted` to check user id. I don't know how this worked before...
- tests!
- a few places referred to `typ`, when it is really `userAgent`. Change the field names

* baseRequest -> selectPlayer

* remove comment

* update migration, make all of persistence foreign key enabled

* maybe don't forget to save the file first

* Use same key for replaygain's preAmp (navidrome#3184)

Resolves navidrome#2933. To prevent this from happening again, make the localstorage keys consts for set/get

* Fix Player filter

---------

Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: looklose <shishuaiqun@yeah.net>
Signed-off-by: oftenoccur <ezc5@sina.com>
Signed-off-by: apkatsikas <apkatsikas@gmail.com>
Signed-off-by: Jeremiah Menétrey <superjun1@gmail.com>
Signed-off-by: Victor van der Veen <vvdveen@gmail.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Deluan <deluan@navidrome.org>
Co-authored-by: looklose <166388131+looklose@users.noreply.github.com>
Co-authored-by: Cyrille <2franix@users.noreply.github.com>
Co-authored-by: oftenoccur <166520808+oftenoccur@users.noreply.github.com>
Co-authored-by: Andrew Katsikas <apkatsikas@gmail.com>
Co-authored-by: Jonathan <jonathan.vogt@allcloud.io>
Co-authored-by: Tim <TimHiller@live.de>
Co-authored-by: crazygolem <crazygolem@users.noreply.github.com>
Co-authored-by: Anna Smith <155628741+socialsister@users.noreply.github.com>
Co-authored-by: vvdveen <vvdveen@gmail.com>
Co-authored-by: Kendall Garner <17521368+kgarner7@users.noreply.github.com>
Co-authored-by: Ludovic Fernandez <ldez@users.noreply.github.com>
Co-authored-by: Matthias Schmidt <matthias.schmidt@gmail.com>
Co-authored-by: Valeri Sokolov <ulfurinn@ulfurinn.net>
Co-authored-by: edthu <127602296+edthu@users.noreply.github.com>
Co-authored-by: Fynn Petersen-Frey <10599762+fyfrey@users.noreply.github.com>
Co-authored-by: Rob Emery <mintsoft@users.noreply.github.com>
Co-authored-by: Rob Emery <git@mintsoft.net>
Co-authored-by: Guilherme Souza <32180229+gqgs@users.noreply.github.com>
Co-authored-by: deluan <331353+deluan@users.noreply.github.com>
Co-authored-by: Drew Weymouth <dweymouth@users.noreply.github.com>
Co-authored-by: Caio Cotts <caio@cotts.com.br>
Co-authored-by: kartikynwa <kartik.ynwa@gmail.com>
Co-authored-by: gruneforth <114325145+gruneforth@users.noreply.github.com>
Co-authored-by: Caio Cotts <caio@hyperion.lan>
Co-authored-by: Soderes <kennex@protonmail.com>
@certuna
Copy link
Contributor

certuna commented Aug 12, 2024

Is there anything similar that can be done for Live albums for the same "wrong year" reason? I see there is no specific tag for that, so I tried {"notContains": {"album": "Live"}} , but many Live albums often do not have the word "Live" in the title (while others do and are not Live albums).

This will come when the new scanner + support for more tag fields is done, the releasetype tag has this information ("album;live" , for example). When that's supported, you'll be able to do something like {"isNot": {"releasetype": "live"}.

Unfortunately, this tag is usually only populated on the album/release level (by Picard, etc), so individual live tracks, such as bonus tracks on a studio album, can not be caught that way.

@blastbeng
Copy link

For anyone looking into smart playlists i made a sample playlist generator based off a user spotify activity and music library.

https://github.com/blastbeng/spotify-playlist-generator

@janaxhell
Copy link

For anyone looking into smart playlists i made a sample playlist generator based off a user spotify activity and music library.

https://github.com/blastbeng/spotify-playlist-generator

It would be very interesting, but for me this point is a show-stopper:

!!It is important that you have all the artists folder at the root of your library!!

Long before music organizers existed I sorted all my artists into about 75 macro-genre folders for easy finding. So my hierarchy is /music/[genre folder]/artist/album. Musicbee, Navidrome, and basically every other tool I use have no problem with that.

@blastbeng
Copy link

For anyone looking into smart playlists i made a sample playlist generator based off a user spotify activity and music library.
https://github.com/blastbeng/spotify-playlist-generator

It would be very interesting, but for me this point is a show-stopper:

!!It is important that you have all the artists folder at the root of your library!!

Long before music organizers existed I sorted all my artists into about 75 macro-genre folders for easy finding. So my hierarchy is /music/[genre folder]/artist/album. Musicbee, Navidrome, and basically every other tool I use have no problem with that.

I may implement /music/genre/artist later maybe, at the moment my script supports /music/artist/song, music/artist/album/song, music/artist/album/cd/song

At the actual state the important thing is the /music/artist path.

And I had a lot of problems with Spotify rate limiting, but kinda solved it putting a lot of sleeps in the code.

@janaxhell
Copy link

I will subscribe to your git and wait :)

@kgarner7
Copy link
Contributor

kgarner7 commented Sep 6, 2024

On a related note, MusicBrainz also has tooling for creating playlists via Subsonic api, available https://github.com/metabrainz/troi-recommendation-playground (this is useful if you have tracks tagged with mbid).

@blastbeng
Copy link

I will subscribe to your git and wait :)

Next step is to create a docker image so people don't need to install python and deps by theirselfs.

@blastbeng
Copy link

I will subscribe to your git and wait :)

I refeactored the code, now it works just by using subsonic apis :) So no matter how your music library is organized.

@janaxhell
Copy link

Great! Later I will look through the docker-compose!

@pr0927
Copy link

pr0927 commented Sep 24, 2024

This is the most roundabout thing, but I've been using Feishin on desktop - which is phenomenal - and making smart playlists in there. They then appear as playlists in Navidrome, on the web and all (reverse-proxied website pointing to the instance).

I don't think this is ideal, of course - would be great to have a built-in GUI for this, but it's a nice workaround for now - somehow could never get the text file approach to work.

@TobiasDax
Copy link

This is the most roundabout thing, but I've been using Feishin on desktop - which is phenomenal - and making smart playlists in there. They then appear as playlists in Navidrome, on the web and all (reverse-proxied website pointing to the instance).

I don't think this is ideal, of course - would be great to have a built-in GUI for this, but it's a nice workaround for now - somehow could never get the text file approach to work.

Just as a heads up, feishin has preview button for the smart playlists that gives you the code for the nsp file (missing the sort and limit settings)
You can use that to create the nsp files as well

@RedKage
Copy link

RedKage commented Sep 24, 2024

I'm discovering Feishin thanks to you guys, and as you said, this is indeed a phenomenal client!

@garyo
Copy link

garyo commented Sep 29, 2024

Just wanted to chime in here and say I'd love to see multi-field sort in smart playlists. I have a "Favorites Rotation" with not-recently-played favorites, like this:

{
  "all": [
    {"is": {"loved": true}},
    {"notInTheLast": {"lastPlayed": 60}}
  ],
  "sort": "lastPlayed",
  "limit": 500
}

which works great, but I'd prefer if it kept songs from the same album (or artist) together, not randomly jumbled. So I'd like to see "sort": ["lastPlayed", "sortAlbum", "sortArtist"] or something like that.

@deluan
Copy link
Member Author

deluan commented Sep 29, 2024

So I'd like to see "sort": ["lastPlayed", "sortAlbum", "sortArtist"] or something like that.

@garyo: yes this is planned :)

@relink2013
Copy link

This may be a ridiculous question, and I hope it's ok to ask it here but it seemed relevant.

Would it be possible to have smart playlist templates that are assigned keywords? Users can create their own smart lists by just putting certain keywords in the title of the playlist.

Just as an example since all major streaming services like to use the word "radio", I'll go with that.

So you can name the playlist whatever you want, but if it ends with [Radio] then that keyword will trigger Navidrome to pull the template associated with the keyword [Radio].

It will then automatically assign the playlist only to the user who created it, and as they add music the playlist will automatically grow with similar artists and new tracks from artists in the playlist. Contents of the playlist can be modified periodically based on favorites, number of skips, play count, etc.

It would also be great if every time the playlist was updated on the backend it would re shuffle all the tracks, this way your "Radio Station" doesn't start in the same place every time.

The inspiration for the idea came from the fact that every compatible client app does things differently, so to have a consistent experience this would have to be done on the backend, and not reliant on the client apps to support it.

@SickProdigy
Copy link

This may be a ridiculous question, and I hope it's ok to ask it here but it seemed relevant.

Would it be possible to have smart playlist templates that are assigned keywords? Users can create their own smart lists by just putting certain keywords in the title of the playlist.

Just as an example since all major streaming services like to use the word "radio", I'll go with that.

So you can name the playlist whatever you want, but if it ends with [Radio] then that keyword will trigger Navidrome to pull the template associated with the keyword [Radio].

It will then automatically assign the playlist only to the user who created it, and as they add music the playlist will automatically grow with similar artists and new tracks from artists in the playlist. Contents of the playlist can be modified periodically based on favorites, number of skips, play count, etc.

It would also be great if every time the playlist was updated on the backend it would re shuffle all the tracks, this way your "Radio Station" doesn't start in the same place every time.

The inspiration for the idea came from the fact that every compatible client app does things differently, so to have a consistent experience this would have to be done on the backend, and not reliant on the client apps to support it.

You could script yourself something that builds these.
First: I think smart playlist are only given to admin user/ first user you create. I don't think smart playlist can be added to other users only at the moment. So every time it updates it will just give it to the admin account.

What I'd do is make a folder available editable by different users and mount that folder to add to library.
There's other programs to create smart playlists too that may help your end users out if they want to give it a shot.

Second: I don't think individual user ratings or favorites are taken into the database yet.
So only admin users ratings and favorites will work with smart playlists at the moment.

It may be possible in future update though.

@deluan
Copy link
Member Author

deluan commented Oct 25, 2024

@SickProdigy:

First: I think smart playlist are only given to admin user/ first user you create. I don't think smart playlist can be added to other users only at the moment. So every time it updates it will just give it to the admin account.

Yes, but you can change the smart-playlist ownership in the UI, and then it uses the new owner's data when updating.

Second: I don't think individual user ratings or favorites are taken into the database yet. So only admin users ratings and favorites will work with smart playlists at the moment.

Not really. All users have their own ratings. favorites, play counts, etc... But as I said above, the Smart Playlist is calculated with its owner's data. You just need to change the owner.

@relink2013:

It will then automatically assign the playlist only to the user who created it, and as they add music the playlist will automatically grow with similar artists and new tracks from artists in the playlist. Contents of the playlist can be modified periodically based on favorites, number of skips, play count, etc.

Have you tried using Feishin to create/edit smart playlists? Your users can use it with their own account and create the playlists automatically, without the trouble of changing ownership as I explained above.

@relink2013
Copy link

Have you tried using Feishin to create/edit smart playlists? Your users can use it with their own account and create the playlists automatically, without the trouble of changing ownership as I explained above.

I have never even heard of that until now! That looks absolutely awesome! Are there other projects like that too?

@deluan
Copy link
Member Author

deluan commented Oct 30, 2024

I have never even heard of that until now! That looks absolutely awesome! Are there other projects like that too?

Only Feishin has the Smart Playlist editing feature, as this is a Navidrome exclusive feature, not available in the Subsonic API, and Feishin uses Navidrome API.

But there are quite a few apps out there compatible with Navidrome, for all tastes. Take a look at this non-comprehensive list: https://www.navidrome.org/docs/overview/#apps

@TheMemoman
Copy link

TheMemoman commented Nov 14, 2024

I'm loving Smart Playlists! It was just what I needed to create new mixes. God sent, thank you.

I have either found a bug or a limitation: On a new Smart Playlist file, when referencing a playlist by ID (taken from reading the database file), it works as long as it isn't another Smart Playlist. For example:

{
  "comment": "Last Year's Best Rated",
  "all": [
   {"inPlaylist": {"id": "631db380-38ce-4b93-947a-abae8357da50"}},
   {"gt": {"rating": 3}}
  ],
  "sort": "random"
}

Works as long as the ID belongs to a regular playlist, if it belongs to a Smart Playlist it's not working. In the example, it references a Smart Playlist for songs added {"after": {"dateadded": "2024-03-01"}}, which is working fine.

I have the latest navidrome release. As well as Feishin's, for some testing there (it behaves the same way).
I've done multiple other playlists using notInPlaylist or inPlaylist. All of them work, get updated, some have a much longer list of regular playlists. All good.

Any insights on this would be greatly appreciated.

@TobiasDax
Copy link

@TheMemoman it's a known thing and just badly documented.
If you want to reference a smart playlist it needs to be set to 'public'. Then everything works as expected.

@oransterf
Copy link

oransterf commented Dec 15, 2024

Hello, I am new at navidrome so thank you for the great software.
I am having an issue with some smart playlists where the contains or endsWith condition is not respected.
Example:

{
    "name": "Three Underscores Test",
    "all": [
        {
            "startsWith": {
                "comment": "pop"
            }
        },
        {
            "endsWith": {
                "comment": "___"
            }
        }
    ],
    "sort": "datemodified",
    "order": "desc"
}

or similarly

{
    "name": "Two Underscores Test",
    "all": [
        {
            "startsWith": {
                "comment": "pop"
            }
        },
        {
            "contains": {
                "comment": "__"
            }
        }
    ],
    "sort": "datemodified",
    "order": "desc"
}

These both will only grab songs that have a comment starting with "pop" but will not care for two or three underscores in the comments.
I have a feeling underscores get ignored at some point in this computation. Is there a way to unignore them?

Thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests