134 Commits

Author SHA1 Message Date
Deluan Quintão
b3efc17669
fix(server): backup and restore issues from the cli (#3579)
* fix(server): backup not working from cli

Signed-off-by: Deluan <deluan@navidrome.org>

* fix(server): make backup-file required for restore

Signed-off-by: Deluan <deluan@navidrome.org>

---------

Signed-off-by: Deluan <deluan@navidrome.org>
2026-01-02 20:43:19 +00:00
Deluan
67d4982632
revert: separation of write and read DBs
Signed-off-by: Deluan <deluan@navidrome.org>
2026-01-02 20:41:56 +00:00
Deluan Quintão
50ad8bb8e6
fix(server): fix case-insensitive sort order and add indexes to improve performance (#3425)
* refactor(server): better sort mappings

* refactor(server): simplify GetIndex

* fix: recreate tables and indexes using proper collation

Also add tests to ensure proper collation

* chore: remove unused method

* fix: sort expressions

* fix: lint errors

* fix: cleanup
2026-01-02 20:41:04 +00:00
Deluan
44b2164659
perf(server): add index for sort tags.
Improves search performance when searching with PreferSortTags=true
2026-01-02 20:41:03 +00:00
Kendall Garner
e8e7309806
feat(server): provide native backup/restore mechanism (#3194)
* [enhancement]: Provide native backup/restore mechanism

- db.go: add Backup/Restore functions that utilize Sqlite's built-in online backup mechanism
- support automatic backup with schedule, limit number of files
- provide commands to manually backup/restore Navidrome

Notes:
`Step(-1)` results in a read-only lock being held for the entire duration of the backup.
This will block out any other write operation (and may hold additional locks.
An alternate implementation that doesn't block but instead retries is available at https://www.sqlite.org/backup.html#:~:text=of%20a%20Running-,database,-%2F*%0A**%20Perform%20an%20online (easily adaptable to go), but has the potential problem of continually getting restarted by background writes.

Additionally, the restore should still only be called when Navidrome is offline, as the restore process does not run migrations that are missing.

* remove empty line

* add more granular backup schedule

* do not remove files when bypass is set

* move prune

* refactor: small nitpicks

* change commands and flags

* tests, return path from backup

* refactor: small nitpicks

---------

Co-authored-by: Deluan <deluan@navidrome.org>
2026-01-02 20:40:20 +00:00
Kendall Garner
a50af42872
Use userId in player, other fixes (#3182)
* [bugfix] player: use userId, other fixes

This PR primarily resolves #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
2026-01-02 20:37:43 +00:00
Deluan
b3450dd880
Remove unnecessary annotation table primary key 2026-01-02 20:37:16 +00:00
Deluan
38a219648d
Refactor string utilities into its own package str 2026-01-02 20:36:59 +00:00
Deluan
a58f04b2ce
Revert isDBInitialized 2026-01-02 20:36:59 +00:00
Deluan
3650a7ba0a
Replace panics with log.Fatals 2026-01-02 20:36:58 +00:00
Deluan
47068d2dea
Optimize SQLite3 access. Mainly separate read access from write access.
Based on tips from https://archive.is/Xfjh6#selection-257.0-278.0
2026-01-02 20:36:58 +00:00
Guilherme Souza
c9a39d9986
Deterministic pagination in random albums sort (#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>
2026-01-02 20:36:58 +00:00
Deluan
82e79073cd
Store MusicFolder as a library in DB 2026-01-02 20:36:57 +00:00
Deluan
4007dd0560
Add sampleRate to the DB 2026-01-02 20:36:56 +00:00
Deluan
5be6dfc54b
Clean up runNavidrome function 2026-01-02 20:36:55 +00:00
Deluan
b20e3ae337
Fix migration package name mismatch 2026-01-02 20:36:54 +00:00
Deluan
d94e73236b
Change default transcodings to a proper typed struct 2026-01-02 20:36:54 +00:00
Deluan
d46740771c
Fix scrobble error spam in the logs.
Relates to #2831 and #2975
2026-01-02 20:35:04 +00:00
Deluan
a8a14370bd
Use new slices package from Go standard lib 2026-01-02 20:33:14 +00:00
Caio Cotts
b57ba9e232
Fix null values in DB (#2840)
* Fix album image_files being null.

* Fix small nitpick.

* Use ExecContext instead of Exec.

* Change more columns to not null and set default values.

* Remove columns that don't need to be changed from migration.

* Fix typo.

* Remove unnecessary select statements.

* Remove duplicate code.

* Do not apply changes to radio table.

* Do not apply changes full_text columns and respective indexes.

* Fix musicbrainz columns.

* Rename migration.

* Make ExternalInfoUpdatedAt nullable

* Make Share's timestamps nullable

---------

Co-authored-by: Deluan Quintão <deluan@navidrome.org>
2026-01-02 20:32:59 +00:00
Deluan
3897f424d3
Add a "upgrading schema" log message to the DB initialization when there are pending migrations. 2026-01-02 20:32:59 +00:00
Deluan
88e74c0233
Don't force a full scan after upgrading the lyrics 2026-01-02 20:32:37 +00:00
Kendall Garner
044c8c09ac
Add OS Lyrics extension (#2656)
* draft commit

* time to fight pipeline

* round 2 changes

* remove unnecessary line

* fight taglib. again

* make taglib work again???

* add id3 tags

* taglib 1.12 vs 1.13

* use int instead for windows

* store as json now

* add migration, more tests

* support repeated line, multiline

* fix ms and support .m, .mm, .mmm

* address some concerns, make cpp a bit safer

* separate responses from model

* remove [:]

* Add trace log

* Try to unblock pipeline

* Fix merge errors

* Fix SIGSEGV error (proper handling of empty frames)

* Add fallback artist/title to structured lyrics

* Rename conflicting named vars

* Fix tests

* Do we still need ffmpeg in the pipeline?

* Revert "Do we still need ffmpeg in the pipeline?"

Yes we do.

This reverts commit 87df7f6df79bccee83f48c4b7a8118a7636a5e66.

* Does this passes now, with a newer ffmpeg version?

* Revert "Does this passes now, with a newer ffmpeg version?"

No, it does not :(

This reverts commit 372eb4b0ae05d9ffe98078e9bc4e56a9b2921f32.

* My OCD made me do it :P

---------

Co-authored-by: Deluan Quintão <deluan@navidrome.org>
2026-01-02 20:32:37 +00:00
Deluan
d9ce8b54f0
Add discs to album 2026-01-02 20:31:57 +00:00
Deluan
e4610ace22
Upgrade to Goose 3.15.1 2026-01-02 20:31:56 +00:00
Philipp Wolfer
cd62da04f8
Fix listenbrainz submission and clarify MusicBrainz recording ID field (#2279)
* Fix MB recording ID parameter name for ListenBrainz submission

This follows the ListenBrainz API documentation.

Fixes #1657

* Rename MediaFile.MbzTrackID to MbzRecordingID

This better reflects the actual data. That the MusicBrainz
recording ID is stored in file metadata as musicbrainz_trackid
is a historical artifact.

* Rename database column mbz_track_id to mbz_recording_id
2026-01-02 20:27:27 +00:00
certuna
3d1228db3b
Support for Original Date, Release Date & splitting/grouping of album editions (#2162)
* Update AlbumGridView.js

* Update AlbumDetails.js

* Update AlbumDetails.js

* Create DoubleRangeField.js

* Update and rename DoubleRangeField.js to RangeFieldDouble.js

* Update RangeFieldDouble.js

* Update AlbumGridView.js

* Update AlbumDetails.js

* Update RangeFieldDouble.js

* Update index.js

* Update RangeFieldDouble.js

* Update RangeFieldDouble.js

* Update RangeFieldDouble.js

* Update RangeFieldDouble.js

* Update RangeFieldDouble.js

* Update AlbumDetails.js

* Update RangeFieldDouble.js

* Update AlbumDetails.js

* Update RangeFieldDouble.js

* Update AlbumDetails.js

* Update RangeFieldDouble.js

* Update RangeFieldDouble.js

* Update AlbumDetails.js

* Update AlbumDetails.js

* Update RangeFieldDouble.js

* Update RangeFieldDouble.js

* Update AlbumDetails.js

* Update RangeFieldDouble.js

* Update AlbumDetails.js

* Update en.json

* Update en.json

* Update AlbumDetails.js

* Update RangeFieldDouble.js

* Update AlbumGridView.js

* Update AlbumDetails.js

* Update AlbumSongs.js

* Update ContextMenus.js

* Update SongDatagrid.js

* Update AlbumSongs.js

* Update SongDatagrid.js

* Update SongDatagrid.js

* Update SongDatagrid.js

* Update AlbumSongs.js

* Update SongList.js

* Update playlist_track_repository.go

* Update 20230113000000_release_year.go

* Update PlayButton.js

* Update mediafile_repository.go

* Update album.go

* Update playlist_track_repository.go

* Update playlist_track_repository.go

* Update SongDatagrid.js

* Update 20230113000000_release_year.go

* Update SongDatagrid.js

* Update AlbumSongs.js

* Update SongDatagrid.js

* Update SongDatagrid.js

* Update SongDatagrid.js

* Update SongDatagrid.js

* Update AlbumDetails.js

* Update AlbumSongs.js

* Update AlbumSongs.js

* Update RangeFieldDouble.js

* Update SongDatagrid.js

* Update 20230113000000_release_year.go

* Update 20230113000000_release_year.go

* Update 20230113000000_release_year.go

* Update 20230113000000_release_year.go

* Update AlbumSongs.js

* Update AlbumSongs.js

* Update mapping.go

* Update RangeFieldDouble.js

* Update AlbumGridView.js

* Update AlbumSongs.js

* Update en.json

* Update SongDatagrid.js

* Update SongDatagrid.js

* Update metadata.go

* Update mapping.go

* Update AlbumDetails.js

* Update AlbumGridView.js

* Update RangeFieldDouble.js

* Update mapping.go

* Update metadata.go

* Update mapping.go

* Update AlbumDetails.js

* Update 20230113000000_release_year.go

* Update AlbumDetails.js

* Update en.json

* Update configuration.go

* Update mapping.go

* Update configuration.go

* Update mediafile.go

* Update metadata.go

* Update RangeFieldDouble.js

* Update 20230113000000_release_year.go

* Update configuration.go

* Update mapping.go

* Update mediafile.go

* Update mapping.go

* Update RangeFieldDouble.js

* Update RangeFieldDouble.js

* Update RangeFieldDouble.js

* Update RangeFieldDouble.js

* Update RangeFieldDouble.js

* Update 20230113000000_release_year.go

* Update AlbumDetails.js

* Update RangeFieldDouble.js

* Update mapping.go

* Update metadata.go

* Update album.go

* Update mediafile.go

* Update mediafile.go

* Update album.go

* Update fields.go

* Update mediafile_repository.go

* Update playlist_track_repository.go

* Update AlbumSongs.js

* Update SongDatagrid.js

* Update PlayButton.js

* Update SongList.js

* Update ContextMenus.js

* Update SongDatagrid.js

* Update metadata.go

* Update ArtistShow.js

* Update mapping.go

* Update configuration.go

* Update mapping.go

* Update metadata.go

* Update metadata.go

* Update mapping.go

* Update metadata.go

* Update metadata.go

* Update mapping.go

* Update 20230113000000_release_year.go

* Update 20230113000000_release_year.go

* Update mapping.go

* Update metadata.go

* Update metadata.go

* Update album.go

* Update mediafile.go

* Update AlbumDetails.js

* Update AlbumSongs.js

* Update album.go

* Update mediafile.go

* Update metadata.go

* Update mediafile.go

* Update 20230113000000_release_year.go

* Update 20230113000000_release_year.go

* Update album.go

* Update mediafile.go

* Update RangeFieldDouble.js

* Update AlbumDetails.js

* Update AlbumGridView.js

* Update en.json

* Update AlbumGridView.js

* Update RangeFieldDouble.js

* Update and rename 20230113000000_release_year.go to 20230113000000_release_date.go

* Update album.go

* Update mediafile.go

* Update fields.go

* Update playlist_track_repository.go

* Update mediafile_repository.go

* Update mapping.go

* Update metadata.go

* Update mapping.go

* Update SongDatagrid.js

* Update RangeFieldDouble.js

* Update index.js

* Update ContextMenus.js

* Update PlayButton.js

* Create FormatDate.js

* Update SongList.js

* Update AlbumDetails.js

* Update AlbumSongs.js

* Update AlbumSongs.js

* Update en.json

* Update AlbumDetails.js

* Update album.go

fixed conflict I think?

* Update mediafile.go

fixed conflict

* Format with goimports

* Update SongDatagrid.js

only show Cat # in desktop view

* Update metadata_internal_test.go

* Update metadata_test.go

* Delete test.mp3

* Add files via upload

mp3 test file with Date, Original Date and Release Date

* Update metadata_test.go

* Update metadata_test.go

* Update metadata_test.go

* Update metadata_test.go

* Update taglib_test.go

* Delete test.mp3

* Add files via upload

file with replaygain & dates

* Update AlbumGridView.js

* Update AlbumDetails.js

* Update AlbumSongs.js

* Update ContextMenus.js

* Update FormatDate.js

* Update PlayButton.js

* Update RangeFieldDouble.js

* Update SongDatagrid.js

* Update AlbumSongs.js

* Update SongDatagrid.js

* Update AlbumSongs.js

* Fix formatting

* Update mapping.go

* Update AlbumSongs.js

* Update SongDatagrid.js

* Update SongDatagrid.js

prettier

* Create RangeDoubleField.js

rename of RangeFieldDouble.js

* Update AlbumGridView.js

RangeFieldDouble -> RangeDoubleField

* Update mediafile.go

AllOrNothing() -> allOrNothing()

* Update metadata_internal_test.go

getYear -> getDate

* Update AlbumDetails.js

wrote suggested changes

* Update en.json

Editions -> Releases & fixed the field name

* Update configuration.go

Rename Editions -> Releases

* Update 20230113000000_release_date.go

Editions -> Releases

* Update album.go

Editions -> Releases

* Update mediafile.go

Editions -> Releases

* Update AlbumDetails.js

Editions -> Releases

* Update AlbumSongs.js

Editions -> Releases

* Update RangeDoubleField.js

Editions -> Releases

* Update SongDatagrid.js

Editions -> Releases

* Update index.js

FormatFullDate and RangeDoubleField

* Rename FormatDate.js to FormatFullDate.js

* Delete RangeFieldDouble.js

* Update mediafile.go

AllOrNothing -> allOrNothing

* Update mapping.go

Editions -> Releases

* Update AlbumDetails.js

prettier

* Update SongDatagrid.js

showReleaseRow -> showReleaseDivider

* Update AlbumSongs.js

showReleaseRow -> showReleaseDivider for clarity

* Update and rename 20230113000000_release_date.go to 20230515184510_add_release_date.go

- rename the migration file
- fixed the import to goose/v3
- additional db fields for original date & year

* Update 20230515184510_add_release_date.go

* Update fields.go

* Update album.go

* Update mediafile.go

* Update mapping.go

* Update AlbumDetails.js

* Update en.json

* Update AlbumDetails.js

* Update AlbumDetails.js

now hopefully prettier

* Update mapping.go

---------

Co-authored-by: Deluan <deluan@navidrome.org>
2026-01-02 20:27:25 +00:00
Deluan
43f4e8a009
Fix SQL migrations 2026-01-02 20:25:44 +00:00
Deluan
55c1d95376
Enable SQL migrations 2026-01-02 20:25:44 +00:00
Deluan
145bed52c5
Upgrade goose 2026-01-02 20:25:44 +00:00
Deluan
7a5f3f419e
Add option to allow share to be downloaded 2026-01-02 20:24:47 +00:00
Deluan
82d907d037
Fix DB migration. Fix #2168 2026-01-02 20:23:39 +00:00
Deluan
c27294989d
Fix album's image_files 2026-01-02 20:23:39 +00:00
Deluan
fe3f9c2436
Add migration to rebuild albums paths 2026-01-02 20:22:23 +00:00
Deluan
08782ef16a
Fix artwork resolution when paths contains :. Fix #2137 2026-01-02 20:22:23 +00:00
Deluan
04abdf4509
Initial work on Shares 2026-01-02 20:21:58 +00:00
Kendall Garner
3242ae96b7
Get album info (when available) from Last.fm, add getAlbumInfo endpoint (#2061)
* lastfm album.getInfo, getAlbuminfo(2) endpoints

* ... for description and reduce not found log level

* address first comments

* return all images

* Update migration timestamp

* Handle a few edge cases

* Add CoverArtPriority option to retrieve albumart from external sources

* Make agents methods more descriptive

* Use Last.fm name consistently

Co-authored-by: Deluan <deluan@navidrome.org>
2026-01-02 20:21:18 +00:00
Kendall Garner
2fb60b92ca
ReplayGain support + audio normalization (web player) (#1988)
* ReplayGain support

- extract ReplayGain tags from files, expose via native api
- use metadata to normalize audio in web player

* make pre-push happy

* remove unnecessary prints

* remove another unnecessary print

* add tooltips, see metadata

* address comments, use settings instead

* remove console.log

* use better language for gain modes
2026-01-02 20:21:18 +00:00
Kendall Garner
2cab4a4352
Add Internet Radio support (#2063)
* add internet radio support

* Add dynamic sidebar icon to Radios

* Fix typos

* Make URL suffix consistent

* Fix typo

* address feedback

* Don't need to preload when playing Internet Radios

* Reorder migration, or else it won't be applied

* Make Radio list view responsive

Also added filter by name, removed RadioActions and RadioContextMenu, and added a default radio icon, in case of favicon is not available.

* Simplify StreamField usage

* fix button, hide progress on mobile

* use js styles over index.css

Co-authored-by: Deluan <deluan@navidrome.org>
2026-01-02 20:21:17 +00:00
Deluan
0399741cd9
"Touch" playlists to force some clients to reload cover art 2026-01-02 20:21:17 +00:00
Deluan
25d61c0456
Find artist.* image in Artist folder 2026-01-02 20:21:16 +00:00
Deluan
4bd0f4400e
Use custom sanitize package, fix #2070 2026-01-02 20:20:21 +00:00
Deluan
e44a9574b9
Remove CoverArtID, fix tests 2026-01-02 20:20:17 +00:00
Deluan
d201cc4c79
Add all images found for each album in the database 2026-01-02 20:20:17 +00:00
Deluan
e8d8fdd8eb
Remove old refresh code 2026-01-02 20:20:17 +00:00
Deluan
e0bfb22007
Rename log.LevelCritical to log.LevelFatal 2026-01-02 20:20:16 +00:00
Deluan
34bd983ef5
Shutdown gracefully, close DB connection 2026-01-02 20:16:00 +00:00
Zane van Iperen
82c56e1115
Capture "musicbrainz_releasetrackid" tag (#1827)
* db/migration: typo fix

* model: add MbzReleaseTrackID field

* scanner: capture the musicbrainz_releasetrackid tag
2026-01-02 20:15:58 +00:00
Deluan
4bfceb3710
Simplify Singleton usage by leveraging Go 1.18's generics 2026-01-02 20:14:22 +00:00
Deluan
90bc1981d8
Upgrade Ginkgo to V2 2026-01-02 20:14:21 +00:00