Added genre as a toggleable column in the playlist songs table. The Genre column
displays genre information for each song in playlists and is available through
the column toggle menu but disabled by default.
Implements feature request from GitHub discussion #4400.
Signed-off-by: Deluan <deluan@navidrome.org>
Added functionality to populate the Folder field in GetUser and GetUsers API responses
with the library IDs that the user has access to. This allows Subsonic API clients
to understand which music folders (libraries) a user can access for proper
content filtering and UI presentation.
Signed-off-by: Deluan <deluan@navidrome.org>
* feat(plugins): add PluginList method
Signed-off-by: Deluan <deluan@navidrome.org>
* feat: enhance insights collection with plugin awareness and expanded metrics
Enhanced the insights collection system to provide more comprehensive telemetry data about Navidrome installations. This update adds plugin awareness through dependency injection integration, expands configuration detection capabilities, and includes additional library metrics.
Key improvements include:
- Added PluginLoader interface integration to collect plugin information when enabled
- Enhanced configuration detection with proper credential validation for LastFM, Spotify, and Deezer
- Added new library metrics including Libraries count and smart playlist detection
- Expanded configuration insights with reverse proxy, custom PID, and custom tags detection
- Updated Wire dependency injection to support the new plugin loader requirement
- Added corresponding data structures for plugin information collection
This enhancement provides valuable insights into feature usage patterns and plugin adoption while maintaining privacy and following existing telemetry practices.
* fix: correct type assertion in plugin manager test
Fixed type mismatch in test where PluginManifestCapabilitiesElem was being
compared with string literal. The test now properly casts the string to the
correct enum type for comparison.
* refactor: move static config checks to staticData function
Moved HasCustomTags, ReverseProxyConfigured, and HasCustomPID configuration checks from the dynamic collect() function to the static staticData() function where they belong. This eliminates redundant computation on every insights collection cycle and implements the actual logic for HasCustomTags instead of the hardcoded false value.
The HasCustomTags field now properly detects if custom tags are configured by checking the length of conf.Server.Tags. This change improves performance by computing static configuration values only once rather than on every insights collection.
* feat: add granular control for insights collection
Added DevEnablePluginsInsights configuration option to allow fine-grained control over whether plugin information is collected as part of the insights data. This change enhances privacy controls by allowing users to opt-out of plugin reporting while still participating in general insights collection.
The implementation includes:
- New configuration option DevEnablePluginsInsights with default value true
- Gated plugin collection in insights.go based on both plugin enablement and permission flag
- Enhanced plugin information to include version data alongside name
- Improved code organization with clearer conditional logic for data collection
* refactor: rename PluginNames parameter from serviceName to capability
Signed-off-by: Deluan <deluan@navidrome.org>
---------
Signed-off-by: Deluan <deluan@navidrome.org>
* fix(auth): Do not try reverse proxy auth if internal auth succeeds
* cmp.Or will still require function results to be evaluated...
* move to a function
* fix: resolve playlist import issues with Unicode character paths
Fixes#3332 where songs with accented characters failed to import from Apple Music M3U playlists. The issue occurred because Apple Music exports use NFC Unicode normalization while macOS filesystem stores paths in NFD normalization.
Added normalizePathForComparison() function that normalizes both filesystem and M3U playlist paths to NFC form before comparison. This ensures consistent path matching regardless of the Unicode normalization form used.
Changes include comprehensive test coverage for Unicode normalization scenarios with both NFC and NFD character representations.
* address comments
Signed-off-by: Deluan <deluan@navidrome.org>
* fix(tests): add check for unequal original Unicode paths in playlist normalization tests
Signed-off-by: Deluan <deluan@navidrome.org>
---------
Signed-off-by: Deluan <deluan@navidrome.org>
* fix(server): remove includeMissing from search (always false)
Signed-off-by: Deluan <deluan@navidrome.org>
* fix(search): optimize search order by using natural order for improved performance
Signed-off-by: Deluan <deluan@navidrome.org>
---------
Signed-off-by: Deluan <deluan@navidrome.org>
* refactor: improve URL path handling in local storage system
Enhanced the local storage implementation to properly handle URL-decoded paths
and fix issues with file paths containing special characters. Added decodedPath
field to localStorage struct to separate URL parsing concerns from file system
operations.
Key changes:
- Added decodedPath field to localStorage struct for proper URL decoding
- Modified newLocalStorage to use decoded path instead of modifying original URL
- Fixed Windows path handling to work with decoded paths
- Improved URL escaping in storage.For() to handle special characters
- Added comprehensive test suite covering URL decoding, symlink resolution,
Windows paths, and edge cases
- Refactored test extractor to use mockTestExtractor for better isolation
This ensures that file paths with spaces, hash symbols, and other special
characters are handled correctly throughout the storage system.
Signed-off-by: Deluan <deluan@navidrome.org>
* fix(tests): fix test file permissions and add missing tests.Init call
* refactor(tests): remove redundant test
Signed-off-by: Deluan <deluan@navidrome.org>
* fix: URL building for Windows and remove redundant variable
Signed-off-by: Deluan <deluan@navidrome.org>
* refactor: simplify URL path escaping in local storage
Signed-off-by: Deluan <deluan@navidrome.org>
---------
Signed-off-by: Deluan <deluan@navidrome.org>
* ui: reset activity icon after viewing error
* refactor: improve ActivityPanel error acknowledgment logic
Replaced boolean errorAcknowledged state with acknowledgedError string state to track which specific error was acknowledged. This prevents icon flickering when error messages change and simplifies the logic by removing the need for useEffect.
Key changes:
- Changed from errorAcknowledged boolean to acknowledgedError string state
- Added derived isErrorVisible computed value for cleaner logic
- Removed useEffect dependency on scanStatus.error changes
- Updated handleMenuOpen to store actual error string instead of boolean flag
- Fixed test mock to return proper error state matching test expectations
This change addresses code review feedback and follows React best practices by using derived state instead of imperative effects.
* fix: prevent foreign key constraint error in album participants
Prevent foreign key constraint errors when album participants contain
artist IDs that don't exist in the artist table. The updateParticipants
method now filters out non-existent artist IDs before attempting to
insert album_artists relationships.
- Add defensive filtering in updateParticipants() to query existing artist IDs
- Only insert relationships for artist IDs that exist in the artist table
- Add comprehensive regression test for both albums and media files
- Fixes scanner errors when JSON participant data contains stale artist references
Signed-off-by: Deluan <deluan@navidrome.org>
* fix: optimize foreign key handling in album artists insertion
Signed-off-by: Deluan <deluan@navidrome.org>
* fix: improve participants foreign key tests
Signed-off-by: Deluan <deluan@navidrome.org>
* fix: clarify comments in album artists insertion query
Signed-off-by: Deluan <deluan@navidrome.org>
* test: add cleanup to album repository tests
Added individual test cleanup to 4 album repository tests that create temporary
artists and albums. This ensures proper test isolation by removing test data
after each test completes, preventing test interference when running with
shuffle mode. Each test now cleans up its own temporary data from the artist,
library_artist, album, and album_artists tables using direct SQL deletion.
Signed-off-by: Deluan <deluan@navidrome.org>
* fix: refactor participant JSON handling for simpler and improved SQL processing
Signed-off-by: Deluan <deluan@navidrome.org>
* fix: update test command description in Makefile for clarity
Signed-off-by: Deluan <deluan@navidrome.org>
* fix: refactor album repository tests to use albumRepository type directly
Signed-off-by: Deluan <deluan@navidrome.org>
---------
Signed-off-by: Deluan <deluan@navidrome.org>
* fix: prevent foreign key constraint error in tag UpdateCounts
Added JOIN clause with tag table in UpdateCounts SQL query to filter out
tag IDs from JSON that don't exist in the tag table. This prevents
'FOREIGN KEY constraint failed' errors when the library_tag table
tries to reference non-existent tag IDs during scanner operations.
The fix ensures only valid tag references are counted while maintaining
data integrity and preventing scanner failures during library updates.
* test(tag): add regression tests for foreign key constraint fix
Add comprehensive regression tests to prevent the foreign key constraint
error when tag IDs in JSON data don't exist in the tag table. Tests cover
both album and media file scenarios with non-existent tag IDs.
- Test UpdateCounts() with albums containing non-existent tag IDs
- Test UpdateCounts() with media files containing non-existent tag IDs
- Verify operations complete without foreign key errors
Signed-off-by: Deluan <deluan@navidrome.org>
---------
Signed-off-by: Deluan <deluan@navidrome.org>
* fix: enable library access for headless processes
Fixed multi-library filtering to allow headless processes (shares, external providers) to access data by skipping library restrictions when no user context is present.
Previously, the library filtering system returned empty results (WHERE 1=0) for processes without user authentication, breaking functionality like public shares and external service integrations.
Key changes:
- Modified applyLibraryFilter methods to skip filtering when user.ID == invalidUserId
- Refactored tag repository to use helper method for library filtering logic
- Fixed SQL aggregation bug in tag statistics calculation across multiple libraries
- Added comprehensive test coverage for headless process scenarios
- Updated genre repository to support proper column mappings for aggregated data
This preserves the secure "safe by default" approach for authenticated users while restoring backward compatibility for background processes that need unrestricted data access.
Signed-off-by: Deluan <deluan@navidrome.org>
* fix: resolve SQL ambiguity errors in share queries
Fixed SQL ambiguity errors that were breaking share links after the Multi-library PR.
The Multi-library changes introduced JOINs between album and library tables,
both of which have 'id' columns, causing 'ambiguous column name: id' errors
when unqualified column references were used in WHERE clauses.
Changes made:
- Updated core/share.go to use 'album.id' instead of 'id' in contentsLabelFromAlbums
- Updated persistence/share_repository.go to use 'album.id' in album share loading
- Updated persistence/sql_participations.go to use 'artist.id' for consistency
- Added regression tests to prevent future SQL ambiguity issues
This resolves HTTP 500 errors that users experienced when accessing existing
share URLs after the Multi-library feature was merged.
Signed-off-by: Deluan <deluan@navidrome.org>
* fix: improve headless library access handling
Added proper user context validation and reordered joins in applyLibraryFilterToArtistQuery to ensure library filtering works correctly for both authenticated and headless operations. The user_library join is now only applied when a valid user context exists, while the library_artist join is always applied to maintain proper data relationships. (+1 squashed commit)
Squashed commits:
[a28c6965b] fix: remove headless library access guard
Removed the invalidUserId guard condition in applyLibraryFilterToArtistQuery that was preventing proper library filtering for headless operations. This fix ensures that library filtering joins are always applied consistently, allowing headless library access to work correctly with the library_artist junction table filtering.
The previous guard was skipping all library filtering when no user context was present, which could cause issues with headless operations that still need to respect library boundaries through the library_artist relationship.
* fix: simplify genre selection query in genre repository
Signed-off-by: Deluan <deluan@navidrome.org>
* fix: enhance tag library filtering tests for headless access
Signed-off-by: Deluan <deluan@navidrome.org>
* test: add comprehensive test coverage for headless library access
Added extensive test coverage for headless library access improvements including:
- Added 17 new tests across 4 test files covering headless access scenarios
- artist_repository_test.go: Added headless process tests for GetAll, Count,
Get operations and explicit library_id filtering functionality
- genre_repository_test.go: Added library filtering tests for headless processes
including GetAll, Count, ReadAll, and Read operations
- sql_base_repository_test.go: Added applyLibraryFilter method tests covering
admin users, regular users, and headless processes with/without custom table names
- share_repository_test.go: Added headless access tests and SQL ambiguity
verification for the album.id vs id fix in loadMedia function
- Cleaned up test setup by replacing log.NewContext usage with GinkgoT().Context()
and removing unnecessary configtest.SetupConfig() calls for better test isolation
These tests ensure that headless processes (background operations without user context)
can access all libraries while respecting explicit filters, and verify that the SQL
ambiguity fixes work correctly without breaking existing functionality.
* revert: remove user context handling from scrobble buffer getParticipants
Reverts commit 5b8ef74f05.
The artist repository no longer requires user context for proper library
filtering, so the workaround of temporarily injecting user context into
the scrobbleBufferRepository.Next method is no longer needed.
This simplifies the code and removes the dependency on fetching user
information during background scrobbling operations.
* fix: improve library access filtering for artists
Enhanced artist repository filtering to properly handle library access restrictions
and prevent artists with no accessible content from appearing in results.
Backend changes:
- Modified roleFilter to use direct JSON_EXTRACT instead of EXISTS subquery for better performance
- Enhanced applyLibraryFilterToArtistQuery to filter out artists with empty stats (no content)
- Changed from LEFT JOIN to INNER JOIN with library_artist table for stricter filtering
- Added condition to exclude artists where library_artist.stats = '{}' (empty content)
Frontend changes:
- Added null-checking in getCounter function to prevent TypeError when accessing undefined records
- Improved optional chaining for safer property access in role-based statistics display
These changes ensure that users only see artists that have actual accessible content
in their permitted libraries, fixing issues where artists appeared in the list
despite having no albums or songs available to the user.
* fix: update library access logic for non-admin users and enhance test coverage
Signed-off-by: Deluan <deluan@navidrome.org>
* fix: refine library artist query and implement cleanup for empty entries
Signed-off-by: Deluan <deluan@navidrome.org>
* refactor: consolidate artist repository tests to eliminate duplication
Significantly refactored artist_repository_test.go to reduce code duplication and
improve maintainability by ~27% (930 to 680 lines). Key improvements include:
- Added test helper functions createTestArtistWithMBID() and createUserWithLibraries()
to eliminate repetitive test data creation
- Consolidated duplicate MBID search tests using DescribeTable for parameterized testing
- Removed entire 'Permission-Based Behavior Comparison' section (~150 lines) that
duplicated functionality already covered in other test contexts
- Reorganized search tests into cohesive 'MBID and Text Search' section with proper
setup/teardown and shared test infrastructure
- Streamlined missing artist tests and moved them to dedicated section
- Maintained 100% test coverage while eliminating redundant test patterns
All tests continue to pass with identical functionality and coverage.
---------
Signed-off-by: Deluan <deluan@navidrome.org>
Add EnsureCompiled calls in plugin test BeforeEach blocks to wait for
WebAssembly compilation before loading plugins. This prevents race conditions
where tests would attempt to load plugins before compilation completed,
causing flaky test failures in CI environments.
The race condition occurred because ScanPlugins() registers plugins
synchronously but compiles them asynchronously in background goroutines
with a concurrency limit of 2. Tests that immediately called LoadPlugin()
or LoadMediaAgent() after ScanPlugins() could fail if compilation wasn't
finished yet.
Fixed in both adapter_media_agent_test.go and manager_test.go which had
multiple tests vulnerable to this timing issue.
* feat(database): add user_library table and library access methods
Signed-off-by: Deluan <deluan@navidrome.org>
# Conflicts:
# tests/mock_library_repo.go
* feat(database): enhance user retrieval with library associations
Signed-off-by: Deluan <deluan@navidrome.org>
* feat(api): implement library management and user-library association endpoints
Signed-off-by: Deluan <deluan@navidrome.org>
* feat(api): restrict access to library and config endpoints to admin users
Signed-off-by: Deluan <deluan@navidrome.org>
* refactor(library): implement library management service and update API routes
Signed-off-by: Deluan <deluan@navidrome.org>
* feat(database): add library filtering to album, folder, and media file queries
Signed-off-by: Deluan <deluan@navidrome.org>
* refactor library service to use REST repository pattern and remove CRUD operations
Signed-off-by: Deluan <deluan@navidrome.org>
* add total_duration column to library and update user_library table
Signed-off-by: Deluan <deluan@navidrome.org>
* fix migration file name
Signed-off-by: Deluan <deluan@navidrome.org>
* feat(library): add library management features including create, edit, delete, and list functionalities - WIP
Signed-off-by: Deluan <deluan@navidrome.org>
* feat(library): enhance library validation and management with path checks and normalization - WIP
Signed-off-by: Deluan <deluan@navidrome.org>
* feat(library): improve library path validation and error handling - WIP
Signed-off-by: Deluan <deluan@navidrome.org>
* use utils/formatBytes
Signed-off-by: Deluan <deluan@navidrome.org>
* simplify DeleteLibraryButton.jsx
Signed-off-by: Deluan <deluan@navidrome.org>
* feat(library): enhance validation messages and error handling for library paths
Signed-off-by: Deluan <deluan@navidrome.org>
* lint
Signed-off-by: Deluan <deluan@navidrome.org>
* test(scanner): add tests for multi-library scanning and validation
Signed-off-by: Deluan <deluan@navidrome.org>
* test(scanner): improve handling of filesystem errors and ensure warnings are returned
Signed-off-by: Deluan <deluan@navidrome.org>
* feat(controller): add function to retrieve the most recent scan time across all libraries
Signed-off-by: Deluan <deluan@navidrome.org>
* feat(library): add additional fields and restructure LibraryEdit component for enhanced statistics display
Signed-off-by: Deluan <deluan@navidrome.org>
* feat(library): enhance LibraryCreate and LibraryEdit components with additional props and styling
Signed-off-by: Deluan <deluan@navidrome.org>
* feat(mediafile): add LibraryName field and update queries to include library name
Signed-off-by: Deluan <deluan@navidrome.org>
* feat(missingfiles): add library filter and display in MissingFilesList component
Signed-off-by: Deluan <deluan@navidrome.org>
* feat(library): implement scanner interface for triggering library scans on create/update
Signed-off-by: Deluan <deluan@navidrome.org>
# Conflicts:
# cmd/wire_gen.go
# cmd/wire_injectors.go
# Conflicts:
# cmd/wire_gen.go
# Conflicts:
# cmd/wire_gen.go
# cmd/wire_injectors.go
* feat(library): trigger scan after successful library deletion to clean up orphaned data
Signed-off-by: Deluan <deluan@navidrome.org>
* rename migration file for user library table to maintain versioning order
Signed-off-by: Deluan <deluan@navidrome.org>
* refactor: move scan triggering logic into a helper method for clarity
Signed-off-by: Deluan <deluan@navidrome.org>
* feat(library): add library path and name fields to album and mediafile models
Signed-off-by: Deluan <deluan@navidrome.org>
* feat(library): add/remove watchers on demand, not only when server starts
Signed-off-by: Deluan <deluan@navidrome.org>
* refactor(scanner): streamline library handling by using state-libraries for consistency
Signed-off-by: Deluan <deluan@navidrome.org>
* fix: track processed libraries by updating state with scan timestamps
Signed-off-by: Deluan <deluan@navidrome.org>
* prepend libraryID for track and album PIDs
Signed-off-by: Deluan <deluan@navidrome.org>
* feat(repository): apply library filtering in CountAll methods for albums, folders, and media files
Signed-off-by: Deluan <deluan@navidrome.org>
* feat(user): add library selection for user creation and editing
Signed-off-by: Deluan <deluan@navidrome.org>
* feat(library): implement library selection functionality with reducer and UI component
Signed-off-by: Deluan <deluan@navidrome.org>
# Conflicts:
# .github/copilot-instructions.md
# Conflicts:
# .gitignore
* feat(library): add tests for LibrarySelector and library selection hooks
Signed-off-by: Deluan <deluan@navidrome.org>
* test: add unit tests for file utility functions
Signed-off-by: Deluan <deluan@navidrome.org>
* feat(library): add library ID filtering for album resources
Signed-off-by: Deluan <deluan@navidrome.org>
* feat(library): streamline library ID filtering in repositories and update resource filtering logic
Signed-off-by: Deluan <deluan@navidrome.org>
* fix(repository): add table name handling in filter functions for SQL queries
Signed-off-by: Deluan <deluan@navidrome.org>
* feat(library): add refresh functionality on LibrarySelector close
Signed-off-by: Deluan <deluan@navidrome.org>
* feat(artist): add library ID filtering for artists in repository and update resource filtering logic
Signed-off-by: Deluan <deluan@navidrome.org>
# Conflicts:
# persistence/artist_repository.go
* Add library_id field support for smart playlists
- Add library_id field to smart playlist criteria system
- Supports Is and IsNot operators for filtering by library ID
- Includes comprehensive test coverage for single values and lists
- Enables creation of library-specific smart playlists
* feat(subsonic): implement user-specific library access in GetMusicFolders
Signed-off-by: Deluan <deluan@navidrome.org>
* feat(library): enhance LibrarySelectionField to extract library IDs from record
Signed-off-by: Deluan <deluan@navidrome.org>
* feat(subsonic): update GetIndexes and GetArtists method to support library ID filtering
Signed-off-by: Deluan <deluan@navidrome.org>
* fix: ensure LibrarySelector dropdown refreshes on button close
Added refresh() call when closing the dropdown via button click to maintain
consistency with the ClickAwayListener behavior. This ensures the UI
updates properly regardless of how the dropdown is closed, fixing an
inconsistent refresh behavior between different closing methods.
The fix tracks the previous open state and calls refresh() only when
the dropdown was open and is being closed by the button click.
* refactor: simplify getUserAccessibleLibraries function and update related tests
Signed-off-by: Deluan <deluan@navidrome.org>
* feat: enhance selectedMusicFolderIds function to handle valid music folder IDs and improve fallback logic
Signed-off-by: Deluan <deluan@navidrome.org>
* refactor: change ArtistRepository.GetIndex to accept multiple library IDs
Updated the GetIndex method signature to accept a slice of library IDs instead of a single ID, enabling support for filtering artists across multiple libraries simultaneously.
Changes include:
- Modified ArtistRepository interface in model/artist.go
- Updated implementation in persistence/artist_repository.go with improved library filtering logic
- Refactored Subsonic API browsing.go to use new selectedMusicFolderIds helper
- Added comprehensive test coverage for multiple library scenarios
- Updated mock repository implementation for testing
This change improves flexibility for multi-library operations while maintaining backward compatibility through the selectedMusicFolderIds helper function.
* feat: add library access validation to selectedMusicFolderIds
Enhanced the selectedMusicFolderIds function to validate musicFolderId parameters
against the user's accessible libraries. Invalid library IDs (those the user
doesn't have access to) are now silently filtered out, improving security by
preventing users from accessing libraries they don't have permission for.
Changes include:
- Added validation logic to check musicFolderId parameters against user's accessible libraries
- Added slices package import for efficient validation
- Enhanced function documentation to clarify validation behavior
- Added comprehensive test cases covering validation scenarios
- Maintains backward compatibility with existing behavior
* feat: implement multi-library support for GetAlbumList and GetAlbumList2 endpoints
- Enhanced selectedMusicFolderIds helper to validate and filter library IDs
- Added ApplyLibraryFilter function in filter/filters.go for library filtering
- Updated getAlbumList to support musicFolderId parameter filtering
- Added comprehensive tests for multi-library functionality
- Supports single and multiple musicFolderId values
- Falls back to all accessible libraries when no musicFolderId provided
- Validates library access permissions for user security
* feat: implement multi-library support for GetRandomSongs, GetSongsByGenre, GetStarred, and GetStarred2
- Added multi-library filtering to GetRandomSongs endpoint using musicFolderId parameter
- Added multi-library filtering to GetSongsByGenre endpoint using musicFolderId parameter
- Enhanced GetStarred and GetStarred2 to filter artists, albums, and songs by library
- Added Options field to MockMediaFileRepo and MockArtistRepo for test compatibility
- Added comprehensive Ginkgo/Gomega tests for all new multi-library functionality
- All tests verify proper SQL filter generation and library access validation
- Supports single/multiple musicFolderId values with fallback to all accessible libraries
* refactor: optimize starred items queries with parallel execution and fix test isolation
Refactored starred items functionality by extracting common logic into getStarredItems()
method that executes artist, album, and media file queries in parallel for better performance.
This eliminates code duplication between GetStarred and GetStarred2 methods while improving
response times through concurrent database queries using run.Parallel().
Also fixed test isolation issues by adding missing auth.Init(ds) call in album lists test setup.
This resolves nil pointer dereference errors in GetStarred and GetStarred2 tests when run independently.
* fix: add ApplyArtistLibraryFilter to filter artists by associated music folders
Signed-off-by: Deluan <deluan@navidrome.org>
* feat: add library access methods to User model
Signed-off-by: Deluan <deluan@navidrome.org>
* feat: implement library access filtering for artist queries based on user permissions
Signed-off-by: Deluan <deluan@navidrome.org>
* feat: enhance artist library filtering based on user permissions and optimize library ID retrieval
Signed-off-by: Deluan <deluan@navidrome.org>
* fix: return error when any musicFolderId is invalid or inaccessible
Changed behavior from silently filtering invalid library IDs to returning
ErrorDataNotFound (code 70) when any provided musicFolderId parameter
is invalid or the user doesn't have access to it.
The error message includes the specific library number for better debugging.
This affects album/song list endpoints (getAlbumList, getRandomSongs,
getSongsByGenre, getStarred) to provide consistent error handling
across all Subsonic API endpoints.
Updated corresponding tests to expect errors instead of silent filtering.
* feat: add musicFolderId parameter support to Search2 and Search3 endpoints
Implemented musicFolderId parameter support for Subsonic API Search2 and Search3 endpoints, completing multi-library functionality across all Subsonic endpoints.
Key changes:
- Added musicFolderId parameter handling to Search2 and Search3 endpoints
- Updated search logic to filter results by specified library or all accessible libraries when parameter not provided
- Added proper error handling for invalid/inaccessible musicFolderId values
- Refactored SearchableRepository interface to support library filtering with variadic QueryOptions
- Updated repository implementations (Album, Artist, MediaFile) to handle library filtering in search operations
- Added comprehensive test coverage with robust assertions verifying library filtering works correctly
- Enhanced mock repositories to capture QueryOptions for test validation
Signed-off-by: Deluan <deluan@navidrome.org>
* feat: refresh LibraryList on scan end
Signed-off-by: Deluan <deluan@navidrome.org>
* fix: allow editing name of main library
Signed-off-by: Deluan <deluan@navidrome.org>
* refactor: implement SendBroadcastMessage method for event broadcasting
Signed-off-by: Deluan <deluan@navidrome.org>
* feat: add event broadcasting for library creation, update, and deletion
Signed-off-by: Deluan <deluan@navidrome.org>
* feat: add useRefreshOnEvents hook for custom refresh logic on event changes
Signed-off-by: Deluan <deluan@navidrome.org>
* feat: enhance library management with refresh event broadcasting
Signed-off-by: Deluan <deluan@navidrome.org>
* feat: replace AddUserLibrary and RemoveUserLibrary with SetUserLibraries for better library management
Signed-off-by: Deluan <deluan@navidrome.org>
* chore: remove commented-out genre repository code from persistence tests
* feat: enhance library selection with master checkbox functionality
Added a master checkbox to the SelectLibraryInput component, allowing users to select or deselect all libraries at once. This improves user experience by simplifying the selection process when multiple libraries are available. Additionally, updated translations in the en.json file to include a new message for selecting all libraries, ensuring consistency in user interface messaging.
Signed-off-by: Deluan <deluan@navidrome.org>
* feat: add default library assignment for new users
Introduced a new column `default_new_users` in the library table to
facilitate automatic assignment of default libraries to new regular users.
When a new user is created, they will now be assigned to libraries marked
as default, enhancing user experience by ensuring they have immediate access
to essential resources. Additionally, updated the user repository logic
to handle this new functionality and modified the user creation validation
to reflect that library selection is optional for non-admin users.
Signed-off-by: Deluan <deluan@navidrome.org>
* fix: correct updated_at assignment in library repository
Signed-off-by: Deluan <deluan@navidrome.org>
* fix: improve cache buffering logic
Refactored the cache buffering logic to ensure thread safety when checking
the buffer length
Signed-off-by: Deluan <deluan@navidrome.org>
* fix formating
Signed-off-by: Deluan <deluan@navidrome.org>
* feat: implement per-library artist statistics with automatic aggregation
Implemented comprehensive multi-library support for artist statistics that
automatically aggregates stats from user-accessible libraries. This fundamental
change moves artist statistics from global scope to per-library granularity
while maintaining backward compatibility and transparent operation.
Key changes include:
- Migrated artist statistics from global artist.stats to per-library library_artist.stats
- Added automatic library filtering and aggregation in existing Get/GetAll methods
- Updated role-based filtering to work with per-library statistics storage
- Enhanced statistics calculation to process and store stats per library
- Implemented user permission-aware aggregation that respects library access control
- Added comprehensive test coverage for library filtering and restricted user access
- Created helper functions to ensure proper library associations in tests
This enables users to see statistics that accurately reflect only the content
from libraries they have access to, providing proper multi-tenant behavior
while maintaining the existing API surface and UI functionality.
Signed-off-by: Deluan <deluan@navidrome.org>
* feat: add multi-library support with per-library tag statistics - WIP
Signed-off-by: Deluan <deluan@navidrome.org>
* refactor: genre and tag repositories. add comprehensive tests
Signed-off-by: Deluan <deluan@navidrome.org>
* feat: add multi-library support to tag repository system
Implemented comprehensive library filtering for tag repositories to support the multi-library feature. This change ensures that users only see tags from libraries they have access to, while admin users can see all tags.
Key changes:
- Enhanced TagRepository.Add() method to accept libraryID parameter for proper library association
- Updated baseTagRepository to implement library-aware queries with proper joins
- Added library_tag table integration for per-library tag statistics
- Implemented user permission-based filtering through user_library associations
- Added comprehensive test coverage for library filtering scenarios
- Updated UI data provider to include tag filtering by selected libraries
- Modified scanner to pass library ID when adding tags during folder processing
The implementation maintains backward compatibility while providing proper isolation between libraries for tag-based operations like genres and other metadata tags.
* refactor: simplify artist repository library filtering
Removed conditional admin logic from applyLibraryFilterToArtistQuery method
and unified the library filtering approach to match the tag repository pattern.
The method now always uses the same SQL join structure regardless of user role,
with admin access handled automatically through user_library associations.
Added artistLibraryIdFilter function to properly qualify library_id column
references and prevent SQL ambiguity errors when multiple tables contain
library_id columns. This ensures the filter targets library_artist.library_id
specifically rather than causing ambiguous column name conflicts.
* fix: resolve LibrarySelectionField validation error for non-admin users
Fixed validation error 'At least one library must be selected for non-admin users' that appeared even when libraries were selected. The issue was caused by a data format mismatch between backend and frontend.
The backend sends user data with libraries as an array of objects, but the LibrarySelectionField component expects libraryIds as an array of IDs. Added data transformation in the data provider's getOne method to automatically convert libraries array to libraryIds format when fetching user records.
Also extracted validation logic into a separate userValidation module for better code organization and added comprehensive test coverage to prevent similar issues.
* refactor: remove unused library access functions and related tests
Signed-off-by: Deluan <deluan@navidrome.org>
* refactor: rename search_test.go to searching_test.go for consistency
Signed-off-by: Deluan <deluan@navidrome.org>
* fix: add user context to scrobble buffer getParticipants call
Added user context handling to scrobbleBufferRepository.Next method to resolve
SQL error 'no such column: library_artist.library_id' when processing scrobble
entries in multi-library environments. The artist repository now requires user
context for proper library filtering, so we fetch the user and temporarily
inject it into the context before calling getParticipants. This ensures
background scrobbling operations work correctly with multi-library support.
* feat: add cross-library move detection for scanner
Implemented cross-library move detection for the scanner phase 2 to properly handle files moved between libraries. This prevents users from losing play counts, ratings, and other metadata when moving files across library boundaries.
Changes include:
- Added MediaFileRepository methods for two-tier matching: FindRecentFilesByMBZTrackID (primary) and FindRecentFilesByProperties (fallback)
- Extended scanner phase 2 pipeline with processCrossLibraryMoves stage that processes files unmatched within their library
- Implemented findCrossLibraryMatch with MusicBrainz Release Track ID priority and intrinsic properties fallback
- Updated producer logic to handle missing tracks without matches, ensuring cross-library processing
- Updated tests to reflect new producer behavior and cross-library functionality
The implementation uses existing moveMatched function for unified move operations, automatically preserving all user data through database foreign key relationships. Cross-library moves are detected using the same Equals() and IsEquivalent() matching logic as within-library moves for consistency.
Signed-off-by: Deluan <deluan@navidrome.org>
* feat: add album annotation reassignment for cross-library moves
Implemented album annotation reassignment functionality for the scanner's missing tracks phase. When tracks move between libraries and change album IDs, the system now properly reassigns album annotations (starred status, ratings) from the old album to the new album. This prevents loss of user annotations when tracks are moved across library boundaries.
The implementation includes:
- Thread-safe annotation reassignment using mutex protection
- Duplicate reassignment prevention through processed album tracking
- Graceful error handling that doesn't fail the entire move operation
- Comprehensive test coverage for various scenarios including error conditions
This enhancement ensures data integrity and user experience continuity during cross-library media file movements.
* fix: address PR review comments for multi-library support
Fixed several issues identified in PR review:
- Removed unnecessary artist stats initialization check since the map is already initialized in PostScan()
- Improved code clarity in user repository by extracting isNewUser variable to avoid checking count == 0 twice
- Fixed library selection logic to properly handle initial library state and prevent overriding user selections
These changes address code quality and logic issues identified during the multi-library support PR review.
* feat: add automatic playlist statistics refreshing
Implemented automatic playlist statistics (duration, size, song count) refreshing
when tracks are modified. Added new refreshStats() method to recalculate
statistics from playlist tracks, and SetTracks() method to update tracks
and refresh statistics atomically. Modified all track manipulation methods
(RemoveTracks, AddTracks, AddMediaFiles) to automatically refresh statistics.
Updated playlist repository to use the new SetTracks method for consistent
statistics handling.
* refactor: rename AddTracks to AddMediaFilesByID for clarity
Renamed the AddTracks method to AddMediaFilesByID throughout the codebase
to better reflect its purpose of adding media files to a playlist by their IDs.
This change improves code readability and makes the method name more descriptive
of its actual functionality. Updated all references in playlist model, tests,
core playlist logic, and Subsonic API handlers to use the new method name.
* refactor: consolidate user context access in persistence layer
Removed duplicate helper functions userId() and isAdmin() from sql_base_repository.go and consolidated all user context access to use loggedUser(r.ctx).ID and loggedUser(r.ctx).IsAdmin consistently across the persistence layer.
This change eliminates code duplication and provides a single, consistent pattern for accessing user context information in repository methods. All functionality remains unchanged - this is purely a code cleanup refactoring.
* refactor: eliminate MockLibraryService duplication using embedded struct
- Replace 235-line MockLibraryService with 40-line embedded struct pattern
- Enhance MockLibraryRepo with service-layer methods (192→310 lines)
- Maintain full compatibility with existing tests
- All 72 nativeapi specs pass with proper error handling
Signed-off-by: Deluan <deluan@navidrome.org>
* refactor: cleanup
Signed-off-by: Deluan <deluan@navidrome.org>
---------
Signed-off-by: Deluan <deluan@navidrome.org>
* fix: prevent disabled Show in Playlist menu item from triggering actions
Fixed bug where clicking on the disabled 'Show in Playlist' menu item would unintentionally trigger music playback and replace the queue. The menu item now properly prevents event propagation when disabled and takes no action.
This resolves the issue where users would accidentally start playing music when clicking on the greyed-out menu option. The fix includes:
- Custom onClick handler that stops event propagation for disabled state
- Proper styling to maintain visual disabled state while allowing event handling
- Comprehensive test coverage for the disabled behavior
* style: clean up disabled menu item styling code
Simplified the arrow function for disabled onClick handler and changed inline style from empty object to undefined when not needed. Also added a CSS class for disabled menu items for potential future use.
These changes improve code readability and follow React best practices by using undefined instead of empty objects for conditional styles.
Fixed a race condition in the plugin manager where goroutines started during
plugin registration could concurrently access shared plugin maps while the
main registration loop was still running. The fix separates plugin registration
from background processing by collecting all plugins first, then starting
background goroutines after registration is complete.
This prevents concurrent read/write access to the plugins and adapters maps
that was causing data races detected by the Go race detector. The solution
maintains the same functionality while ensuring thread safety during the
plugin scanning and registration process.
Signed-off-by: Deluan <deluan@navidrome.org>
* feat: add TimeNow function to SchedulerService plugin
Added new TimeNow RPC method to the SchedulerService host service that returns
the current time in two formats: RFC3339Nano string and Unix milliseconds int64.
This provides plugins with a standardized way to get current time information
from the host system.
The implementation includes:
- TimeNowRequest/TimeNowResponse protobuf message definitions
- Go host service implementation using time.Now()
- Complete test coverage with format validation
- Generated WASM interface code for plugin communication
* feat: add LocalTimeZone field to TimeNow response
Added LocalTimeZone field to TimeNowResponse message in the SchedulerService
plugin host service. This field contains the server's local timezone name
(e.g., 'America/New_York', 'UTC') providing plugins with timezone context
alongside the existing RFC3339Nano and Unix milliseconds timestamps.
The implementation includes:
- New local_time_zone protobuf field definition
- Go implementation using time.Now().Location().String()
- Updated test coverage with timezone validation
- Generated protobuf serialization/deserialization code
* docs: update plugin README with TimeNow function documentation
Updated the plugins README.md to document the new TimeNow function in the
SchedulerService. The documentation includes detailed descriptions of the
three return formats (RFC3339Nano, UnixMilli, LocalTimeZone), practical
use cases, and a comprehensive Go code example showing how plugins can
access current time information for logging, calculations, and timezone-aware
operations.
* docs: remove wrong comment from InitRequest
Signed-off-by: Deluan <deluan@navidrome.org>
* fix: add missing TimeNow method to namedSchedulerService
Added TimeNow method implementation to namedSchedulerService struct to satisfy the scheduler.SchedulerService interface contract. This method was recently added to the interface but the namedSchedulerService wrapper was not updated, causing compilation failures in plugin tests. The implementation is a simple pass-through to the underlying scheduler service since TimeNow doesn't require any special handling for named callbacks.
---------
Signed-off-by: Deluan <deluan@navidrome.org>
Added console.log mock in eventStream.test.js to suppress the 'EventStream error' message that was appearing during test execution. This improves test output cleanliness by preventing the expected error logging from the eventStream error handling code from cluttering the test console output.
The mock follows the existing pattern used in the codebase for suppressing console output during tests and only affects the test environment, preserving the original logging functionality in production code.
Improved the error handling logic in the checkErr function to map specific error strings to their corresponding API error constants. This change ensures that errors from plugins are correctly identified and returned, enhancing the robustness of error reporting.
Signed-off-by: Deluan <deluan@navidrome.org>
Updated the error handling logic in the plugin lifecycle manager to accurately record the success of the OnInit method. The change ensures that the metrics reflect whether the initialization was successful, improving the reliability of plugin metrics tracking. Additionally, removed the unused errorMapper interface from base_capability.go to clean up the codebase.
Signed-off-by: Deluan <deluan@navidrome.org>
* refactor: enhance agent loading with structured data
Introduced a new struct, EnabledAgent, to encapsulate agent name and type
information (plugin or built-in). Updated the getEnabledAgentNames function
to return a slice of EnabledAgent instead of a slice of strings, allowing
for more detailed agent management. This change improves the clarity and
maintainability of the code by providing a structured approach to handling
enabled agents and their types.
Signed-off-by: Deluan <deluan@navidrome.org>
* refactor: remove agent caching logic
Eliminated the caching mechanism for agents, including the associated
data structures and methods. This change simplifies the agent loading
process by directly retrieving agents without caching, which is no longer
necessary for the current implementation. The removal of this logic helps
reduce complexity and improve maintainability of the codebase.
Signed-off-by: Deluan <deluan@navidrome.org>
* refactor: replace range with slice.Contains
Signed-off-by: Deluan <deluan@navidrome.org>
* test: simplify agent name extraction in tests
Signed-off-by: Deluan <deluan@navidrome.org>
---------
Signed-off-by: Deluan <deluan@navidrome.org>
* refactor: implement OnSchedulerCallback method in wasmSchedulerCallback
Added the OnSchedulerCallback method to the wasmSchedulerCallback struct, enabling it to handle scheduler callback events. This method constructs a SchedulerCallbackRequest and invokes the corresponding plugin method, facilitating better integration with the scheduling system. The changes improve the plugin's ability to respond to scheduled events, enhancing overall functionality.
Signed-off-by: Deluan <deluan@navidrome.org>
* fix(plugins): update executeCallback method to use callMethod
Modified the executeCallback method to accept an additional parameter,
methodName, which specifies the callback method to be executed. This change
ensures that the correct method is called for each WebSocket event,
improving the accuracy of callback execution for plugins.
Signed-off-by: Deluan <deluan@navidrome.org>
* fix(plugins): capture OnInit metrics
Signed-off-by: Deluan <deluan@navidrome.org>
* fix(plugins): improve logging for metrics in callMethod
Updated the logging statement in the callMethod function to include the
elapsed time as a separate key in the log output. This change enhances
the clarity of the logged metrics, making it easier to analyze the
performance of plugin requests and troubleshoot any issues that may arise.
Signed-off-by: Deluan <deluan@navidrome.org>
* fix(plugins): enhance logging for schedule callback execution
Signed-off-by: Deluan <deluan@navidrome.org>
* refactor(server): streamline scrobbler stopping logic
Refactored the logic for stopping scrobbler instances when they are removed.
The new implementation introduces a `stoppableScrobbler` interface to
simplify the type assertion process, allowing for a more concise and
readable code structure. This change ensures that any scrobbler
implementing the `Stop` method is properly stopped before removal,
improving the overall reliability of the plugin management system.
Signed-off-by: Deluan <deluan@navidrome.org>
* fix(plugins): improve plugin lifecycle management and error handling
Enhanced the plugin lifecycle management by implementing error handling in the OnInit method. The changes include the addition of specific error conditions that can be returned during plugin initialization, allowing for better management of plugin states. Additionally, the unregisterPlugin method was updated to ensure proper cleanup of plugins that fail to initialize, improving overall stability and reliability of the plugin system.
Signed-off-by: Deluan <deluan@navidrome.org>
* refactor(plugins): remove unused LoadAllPlugins and related methods
Eliminated the LoadAllPlugins, LoadAllMediaAgents, and LoadAllScrobblers
methods from the manager implementation as they were not utilized in the codebase.
This cleanup reduces complexity and improves maintainability by removing
redundant code, allowing for a more streamlined plugin management process.
Signed-off-by: Deluan <deluan@navidrome.org>
* fix(plugins): update logging configuration for plugins
Configured logging for multiple plugins to remove timestamps and source file/line information, while adding specific prefixes for better identification.
Signed-off-by: Deluan <deluan@navidrome.org>
* fix(plugins): clear initialization state when unregistering a plugin
Added functionality to clear the initialization state of a plugin in the
lifecycle manager when it is unregistered. This change ensures that the
lifecycle state is accurately maintained, preventing potential issues with
plugins that may be re-registered after being unregistered. The new method
`clearInitialized` was implemented to handle this state management.
Signed-off-by: Deluan <deluan@navidrome.org>
* test: add unit tests for convertError function, rename to checkErr
Added comprehensive unit tests for the convertError function to ensure
correct behavior across various scenarios, including handling nil responses,
typed nils, and responses implementing errorResponse. These tests validate
that the function returns the expected results without panicking and
correctly wraps original errors when necessary.
Signed-off-by: Deluan <deluan@navidrome.org>
* fix(plugins): update plugin base implementation and method calls
Refactored the plugin base implementation by renaming `wasmBasePlugin` to `baseCapability` across multiple files. Updated method calls in the `wasmMediaAgent`, `wasmSchedulerCallback`, and `wasmScrobblerPlugin` to align with the new base structure. These changes improve code clarity and maintainability by standardizing the plugin architecture, ensuring consistent usage of the base capabilities across different plugin types.
Signed-off-by: Deluan <deluan@navidrome.org>
* fix(discord): handle failed connections and improve heartbeat checks
Added a new method to clean up failed connections, which cancels the heartbeat schedule, closes the WebSocket connection, and removes cache entries. Enhanced the heartbeat check to log failures and trigger the cleanup process on the first failure. These changes ensure better management of user connections and improve the overall reliability of the RPC system.
Signed-off-by: Deluan <deluan@navidrome.org>
---------
Signed-off-by: Deluan <deluan@navidrome.org>
* feat: add translation validation script and update JSON files
Introduced a new script `validate-translations.sh` to validate the structure
of JSON translation files against an English reference. This script checks
for missing and extra translation keys, ensuring consistency across language
files. Additionally, several JSON files were updated to include new keys
and improve existing translations, enhancing the overall localization
efforts for the application.
Signed-off-by: Deluan <deluan@navidrome.org>
* feat: enhance translation validation script
Updated the translation validation script to improve its functionality and usability. The script now validates JSON translation files against a reference English file, checking for JSON syntax, structural integrity, and reporting missing or extra keys. It also integrates with GitHub Actions for CI/CD, providing annotations for errors and warnings. Additionally, the usage instructions have been clarified, and verbose output options have been added for better debugging.
Signed-off-by: Deluan <deluan@navidrome.org>
* revert translations
Signed-off-by: Deluan <deluan@navidrome.org>
* fix: Hungarian translation JSON structure
Signed-off-by: Deluan <deluan@navidrome.org>
* chore: update testall target in Makefile
Modified the 'testall' target in the Makefile to include 'test-i18n' in the test sequence. This change ensures that internationalization tests are run alongside other tests, improving the overall testing process and ensuring that translation-related issues are caught early in the development cycle.
Signed-off-by: Deluan <deluan@navidrome.org>
* run validation with verbose output
Signed-off-by: Deluan <deluan@navidrome.org>
---------
Signed-off-by: Deluan <deluan@navidrome.org>
- Add ErrNotImplemented error to plugins/api package with proper documentation
- Refactor callMethod in wasm_base_plugin to use api.ErrNotImplemented
- Improve metrics recording logic to exclude not-implemented methods
- Add better tracing and context handling for plugin calls
- Reorganize error definitions with clear documentation
* fix(taglib): read cover art from dsf
* address feedback and alsi realize wma/wavpack are missing
* feedback
* more const char and remove unused import
Not all systems have bash at `/bin/bash`. `/bin/sh` is POSIX and should
be present on all systems making this much more portable. No bash
features are currently used in the script so this change should be safe.
* fix(plugins): silence repeated “Plugin not found” spam for inactive Spotify/Last.fm plugins
Navidrome was emitting a warning when the optional Spotify or
Last.fm agents weren’t enabled, filling the journal with entries like:
level=warning msg="Plugin not found" capability=MetadataAgent name=spotify
Fixed by completely disable the plugin system when Plugins.Enabled = false.
Signed-off-by: Deluan <deluan@navidrome.org>
* style: update test description for clarity
Signed-off-by: Deluan <deluan@navidrome.org>
* fix: ensure plugin folder is created only if plugins are enabled
Signed-off-by: Deluan <deluan@navidrome.org>
---------
Signed-off-by: Deluan <deluan@navidrome.org>
* Hungarian: added new strings
new strings from the comparition of d903d3f1 and 4909232e
* Hungarian: fixed my mistakes
---------
Co-authored-by: ChekeredList71 <asd@asd.com>
Introduced a new pull request template to standardize contributions and improve clarity in the review process. This template includes sections for description, related issues, type of change, checklist, testing instructions, and additional notes. By providing a structured format, contributors can better communicate their changes and maintainers can more easily review submissions.
Signed-off-by: Deluan <deluan@navidrome.org>
* feat(subsonic): search by MBID functionality
Updated the search methods in the mediaFileRepository, albumRepository, and artistRepository to support searching by MBID in addition to the existing query methods. This change improves the efficiency of media file, album, and artist searches, allowing for faster retrieval of records based on MBID.
Signed-off-by: Deluan <deluan@navidrome.org>
* feat(subsonic): enhance MBID search functionality for albums and artists
Updated the search functionality to support searching by MBID for both
albums and artists. The fullTextFilter function was modified to accept
additional MBID fields, allowing for more comprehensive searches. New
tests were added to ensure that the search functionality correctly
handles MBID queries, including cases for missing entries and the
includeMissing parameter. This enhancement improves the overall search
capabilities of the application, making it easier for users to find
specific media items by their unique identifiers.
Signed-off-by: Deluan <deluan@navidrome.org>
* fix(subsonic): normalize MBID to lowercase for consistent querying
Updated the MBID handling in the SQL search logic to convert the input
to lowercase before executing the query. This change ensures that
searches are case-insensitive, improving the accuracy and reliability
of the search results when querying by MBID.
Signed-off-by: Deluan <deluan@navidrome.org>
---------
Signed-off-by: Deluan <deluan@navidrome.org>
* chore: update CROSS_TAGLIB_VERSION to 2.1.1-1
* feat: add run-docker target
Introduced a new Makefile target `run-docker` that allows users to run a Navidrome Docker image with specified tags. This addition simplifies the process of launching the Docker container by handling volume mappings for configuration and music folders. The change enhances the development workflow by making it easier to test and run PR images
Signed-off-by: Deluan <deluan@navidrome.org>
---------
Signed-off-by: Deluan <deluan@navidrome.org>
* fix: implement RecentlyAddedByModTime support for mediafiles
Fixes#4046 by adding recently_added sort mapping to MediaFileRepository that respects the RecentlyAddedByModTime configuration setting. Previously, this feature only worked for albums, causing inconsistent behavior when clients requested tracks sorted by 'recently added'.
Changes include:
- Add mediaFileRecentlyAddedSort() function that returns 'updated_at' when RecentlyAddedByModTime=true, 'created_at' otherwise
- Add 'recently_added' sort mapping to mediafile repository
- Add comprehensive tests to verify both configuration scenarios
This ensures consistent sorting behavior between albums and tracks when using the RecentlyAddedByModTime feature.
* fix: update createdAt field to sort by recently added
Modified the createdAt field in the SongList component to include a sortBy
attribute set to "recently_added". This change ensures that the media files
are displayed in the order they were added, improving the user experience
when browsing through recently added items.
Signed-off-by: Deluan <deluan@navidrome.org>
* better testing
Signed-off-by: Deluan <deluan@navidrome.org>
---------
Signed-off-by: Deluan <deluan@navidrome.org>
Introduced a new event, EVENT_STREAM_RECONNECTED, to track the last
timestamp of stream reconnections. This change updates the activity
reducer to handle the new event and modifies the NowPlayingPanel to
refresh data based on server and stream status.
Signed-off-by: Deluan <deluan@navidrome.org>
Added a new event stream connection method to enhance the handling of
server events. This includes a reconnect mechanism for improved reliability
in case of connection errors. The configuration now allows toggling the
new event stream feature via `devNewEventStream`. Additionally, tests
were added to ensure the new functionality works as expected, including
reconnection behavior after an error.
Signed-off-by: Deluan <deluan@navidrome.org>
* attempt using artist | albumartist
* add primary stats, expose to ND and Subsonic
* response to feedback (1)
* address feedback part 1
* fix docs and artist show
* fix migration order
---------
Co-authored-by: Deluan Quintão <deluan@navidrome.org>
* feat(agents): Add Deezer API artist image provider agent
* fix(agents): Use proper naming convention of consts
* fix(agents): Check if json test data can be read
* fix(agents): Use underscores for unused function arguments
* fix(agents): Move int literal to deezerArtistSearchLimit const
* feat: add Deezer configuration option to disable it.
Signed-off-by: Deluan <deluan@navidrome.org>
---------
Signed-off-by: Deluan <deluan@navidrome.org>
Co-authored-by: Deluan Quintão <deluan@navidrome.org>
* Add prometheus metrics to subsonic and plugins
* address feedback, do not log error if operation is not supported
* add missing timestamp and client to stats
* remove .view from subsonic route
* directly inject DataStore in Prometheus, to avoid having to pass it in every call
Signed-off-by: Deluan <deluan@navidrome.org>
---------
Signed-off-by: Deluan <deluan@navidrome.org>
Co-authored-by: Deluan <deluan@navidrome.org>
* Fix artist not being marked as touched during quick scans
When a new album is added during quick scans, artists were not being
marked as 'touched' due to media files having older modification times
than the scan completion time.
Changes:
- Add 'updated_at' to artist Put() columns in scanner to ensure
timestamp is set when artists are processed
- Simplify RefreshStats query to check artist.updated_at directly
instead of complex media file joins
- Artists from new albums now properly get refreshed in later phases
This fixes the issue where newly added albums would have incomplete
artist information after quick scans.
* fix(missing): refresh artist stats in background after deleting missing files
Signed-off-by: Deluan <deluan@navidrome.org>
* fix(request): add InternalAuth to user context
Signed-off-by: Deluan <deluan@navidrome.org>
* Add comprehensive test for artist stats update during quick scans
- Add test that verifies artist statistics are correctly updated when new files are added during incremental scans
- Test ensures both overall stats (AlbumCount, SongCount) and role-specific stats are properly refreshed
- Validates fix for artist stats not being refreshed during quick scans when new albums are added
- Uses real artist repository instead of mock to verify actual stats calculation behavior
---------
Signed-off-by: Deluan <deluan@navidrome.org>
* fix: ensure full scan refreshes all artist stats
After PR #4059, full scans were not forcing a refresh of all artists.
This change ensures that during full scans, all artist stats are refreshed
instead of only those with recently updated media files.
Changes:
- Set changesDetected=true at start of full scans to ensure maintenance operations run
- Add allArtists parameter to RefreshStats() method
- Pass fullScan state to RefreshStats to control refresh scope
- Update mock repository to match new interface
Fixes#4246
Related to PR #4059
* fix: add tests for full and incremental scans
Signed-off-by: Deluan <deluan@navidrome.org>
---------
Signed-off-by: Deluan <deluan@navidrome.org>
* fix: eliminate race condition in plugin system
Added compilation waiting mechanism to prevent WASM plugins from being instantiated
before their background compilation completes. This fixes the intermittent error
'source module must be compiled before instantiation' that occurred when tests
or plugin usage happened before asynchronous compilation finished.
Changes include:
- Added manager reference to wasmBasePlugin for compilation synchronization
- Modified all plugin adapter constructors to accept manager parameter
- Updated getInstance() to wait for compilation before loading instances
- Fixed runtime test to handle manually created plugins appropriately
The race condition was caused by plugins trying to compile WASM modules
synchronously during Load() calls while background compilation was still
in progress. This change ensures proper coordination between the compilation
and instantiation phases.
* fix: add plugin-clean target to Makefile for easier plugin cleanup
Signed-off-by: Deluan <deluan@navidrome.org>
* refactor: reorder plugin constructor parameters and add nil safety
Moved manager parameter to third position in pluginConstructor signature for\nbetter parameter ordering consistency.\n\nAlso added nil check for adapter creation to prevent registration of failed\nplugin adapters, which could lead to nil-pointer dereferences. Plugin\ncreation failures are now logged with context and gracefully skipped.\n\nChanges:\n- Reordered pluginConstructor parameters: manager moved before runtime\n- Updated all 4 adapter constructor signatures to match new order\n- Added nil safety check in registerPlugin to skip failed adapters\n- Updated runtime test to use new parameter order\n\nThis improves both code consistency and runtime safety by preventing\nnil adapters from being registered in the plugin manager.
* fix: prevent concurrent WASM compilation race condition
* refactor: remove unnecessary manager parameter from plugin constructors
* fix: update parameter name in newWasmSchedulerCallback for consistency
Signed-off-by: Deluan <deluan@navidrome.org>
---------
Signed-off-by: Deluan <deluan@navidrome.org>
* feat(plugins): add minimal test agent plugin with API definitions
Signed-off-by: Deluan <deluan@navidrome.org>
* feat: add plugin manager with auto-registration and unique agent names
Introduced a plugin manager that scans the plugins folder for subdirectories containing plugin.wasm files and auto-registers them as agents using the directory name as the unique agent name. Updated the configuration to support plugins with enabled/folder options, and ensured the plugin manager is started as a concurrent task during server startup. The wasmAgent now returns the plugin directory name for AgentName, ensuring each plugin agent is uniquely identifiable. This enables dynamic plugin discovery and integration with the agents orchestrator.
* test: add Ginkgo suite and test for plugin manager auto-registration
Added a Ginkgo v2 suite bootstrap (plugins_suite_test.go) for the plugins package and a test (manager_test.go) to verify that plugins in the testdata folder are auto-registered and can be loaded as agents. The test uses a mock DataStore and asserts that the agent is registered and its AgentName matches the plugin directory. Updated go.mod and go.sum for wazero dependency required by plugin WASM support.
* test(plugins): ensure test WASM plugin is always freshly built before running suite; add real-plugin Ginkgo tests. Add BeforeSuite to plugins suite to build plugins/testdata/agent/plugin.wasm using Go WASI build command, matching README instructions. Remove plugin.wasm before build to guarantee a clean build. Add full real-plugin Ginkgo/Gomega tests for wasmAgent, covering all methods and error cases. Fix manager_test.go to use pointer to Manager. This ensures plugin tests are always run against a freshly compiled WASM binary, increasing reliability and reproducibility.
Signed-off-by: Deluan <deluan@navidrome.org>
* feat(plugins): implement persistent compilation cache for WASM agent plugins
Signed-off-by: Deluan <deluan@navidrome.org>
* feat(plugins): implement instance pooling for wasmAgent to improve resource management
Signed-off-by: Deluan <deluan@navidrome.org>
* feat(plugins): enhance logging for wasmAgent and plugin manager operations
Signed-off-by: Deluan <deluan@navidrome.org>
* feat(plugins): implement HttpService for handling HTTP requests in WASM plugins
Also add a sample Wikimedia plugin
Signed-off-by: Deluan <deluan@navidrome.org>
* feat(plugins): standardize error handling in wasmAgent and MinimalAgent
Signed-off-by: Deluan <deluan@navidrome.org>
* refactor: clean up wikimedia plugin code
Standardized error creation using 'errors.New' where formatting was not needed. Introduced a constant for HTTP request timeouts. Removed commented-out log statement. Improved code comments for clarity and accuracy.
* refactor: use unified SPARQLResult struct and parser for SPARQL responses
Introduced a single SPARQLResult struct to represent all possible SPARQL response fields (sitelink, wiki, comment, img). Added a parseSPARQLResult helper to unmarshal and check for empty results, simplifying all fetch functions and improving type safety and maintainability.
* feat(plugins): improve error handling in HTTP request processing
Signed-off-by: Deluan <deluan@navidrome.org>
* fix: background plugin compilation, logging, and race safety
Implemented background WASM plugin compilation with concurrency limits, proper closure capture, and global compilation cache to avoid data races. Added debug and warning logs for plugin compilation results, including elapsed time. Ensured plugin registration is correct and all tests pass.
* perf: implement true lazy loading for agents
Changed agent instantiation to be fully lazy. The Agents struct now stores agent names in order and only instantiates each agent on first use, caching the result. This preserves agent call order, improves server startup time, and ensures thread safety. Updated all agent methods and tests to use the new pattern. No changes to agent registration or interface. All tests pass.
* fix: ensure wasm plugin instances are closed via runtime.AddCleanup
Introduced runtime.AddCleanup to guarantee that the Close method of WASM plugin instances is called, even if they are garbage collected from the sync.Pool. Modified the sync.Pool.New function in manager.go to register a cleanup function for each loaded instance that implements Close. Updated agent.go to handle the pooledInstance wrapper containing the instance and its cleanup handle. Ensured cleanup.Stop() is called before explicitly closing an instance (on error or agent shutdown) to prevent double closing. This fixes a potential resource leak where instances could be GC'd from the pool without proper cleanup.
* refactor: break down long functions in plugin manager and agent
Refactored plugins/manager.go and plugins/agent.go to improve readability and reduce function length. Extracted pool initialization logic into newPluginPool and background compilation/agent factory logic into precompilePlugin/createAgentFactory in manager.go. Extracted pool retrieval/validation and cleanup function creation into getValidPooledInstance/createPoolCleanupFunc in agent.go.
Signed-off-by: Deluan <deluan@navidrome.org>
* refactor(plugins): rename wasmAgent to wasmArtistAgent
Signed-off-by: Deluan <deluan@navidrome.org>
* feat(api): add AlbumMetadataService with AlbumInfo and AlbumImages requests
Signed-off-by: Deluan <deluan@navidrome.org>
* refactor(plugin): rename MinimalAgent for artist metadata service
Signed-off-by: Deluan <deluan@navidrome.org>
* feat(api): implement wasmAlbumAgent for album metadata service with GetAlbumInfo and GetAlbumImages methods
Signed-off-by: Deluan <deluan@navidrome.org>
* refactor(plugins): simplify wasmAlbumAgent and wasmArtistAgent by using wasmBasePlugin
Signed-off-by: Deluan <deluan@navidrome.org>
* feat(plugins): add support for ArtistMetadataService and AlbumMetadataService in plugin manager
Signed-off-by: Deluan <deluan@navidrome.org>
* feat(plugins): enhance plugin pool creation with custom runtime and precompilation support
Signed-off-by: Deluan <deluan@navidrome.org>
* refactor(plugins): implement generic plugin pool and agent factory for improved service handling
Signed-off-by: Deluan <deluan@navidrome.org>
* refactor(plugins): reorganize plugin management
Signed-off-by: Deluan <deluan@navidrome.org>
* refactor(plugins): improve function signatures for clarity and consistency
Signed-off-by: Deluan <deluan@navidrome.org>
* feat(plugins): implement background precompilation for plugins and agent factory creation
Signed-off-by: Deluan <deluan@navidrome.org>
* refactor(plugins): include instanceID in logging for better traceability
Signed-off-by: Deluan <deluan@navidrome.org>
* test(plugins): add tests for plugin pre-compilation and agent factory synchronization
Signed-off-by: Deluan <deluan@navidrome.org>
* feat(plugins): add minimal album test agent plugin for AlbumMetadataService
Signed-off-by: Deluan <deluan@navidrome.org>
* feat(plugins): rename fake artist and album test agent plugins for metadata services
Signed-off-by: Deluan <deluan@navidrome.org>
* feat(makefile): add Makefile for building plugin WASM binaries
Signed-off-by: Deluan <deluan@navidrome.org>
* feat(plugins): add FakeMultiAgent plugin implementing Artist and Album metadata services
Signed-off-by: Deluan <deluan@navidrome.org>
* refactor(plugins): remove log statements from FakeArtistAgent and FakeMultiAgent methods
Signed-off-by: Deluan <deluan@navidrome.org>
* refactor: split AlbumInfoRetriever and AlbumImageRetriever, update all usages
Split the AlbumInfoRetriever interface into two: AlbumInfoRetriever (for album metadata) and AlbumImageRetriever (for album images), to better separate concerns and simplify implementations. Updated all agents, providers, plugins, and tests to use the new interfaces and methods. Removed the now-unnecessary mockAlbumAgents in favor of the shared mockAgents. Fixed a missing images slice declaration in lastfm agent. All tests pass except for known ignored persistence tests. This change reduces code duplication, improves clarity, and keeps the codebase clean and organized.
* feat(plugins): add Cover Art Archive AlbumMetadataService plugin for album cover images
Signed-off-by: Deluan <deluan@navidrome.org>
* refactor: remove wasm module pooling
it was causing issues with the GC and the Close methods
Signed-off-by: Deluan <deluan@navidrome.org>
* refactor: rename metadata service files to adapter naming convention
Signed-off-by: Deluan <deluan@navidrome.org>
* refactor: unify album and artist method calls by introducing callMethod function
Signed-off-by: Deluan <deluan@navidrome.org>
* refactor: unify album and artist method calls by introducing callMethod function
Signed-off-by: Deluan <deluan@navidrome.org>
* fix: handle nil values in data redaction process
Signed-off-by: Deluan <deluan@navidrome.org>
* fix: add timeout for plugin compilation to prevent indefinite blocking
Signed-off-by: Deluan <deluan@navidrome.org>
* feat: implement ScrobblerService plugin with authorization and scrobbling capabilities
Signed-off-by: Deluan <deluan@navidrome.org>
* refactor: simplify generalization
Signed-off-by: Deluan <deluan@navidrome.org>
* fix: tests
Signed-off-by: Deluan <deluan@navidrome.org>
* refactor: enhance plugin management by improving scanning and loading mechanisms
Signed-off-by: Deluan <deluan@navidrome.org>
* refactor: update plugin creation functions to return specific interfaces for better type safety
Signed-off-by: Deluan <deluan@navidrome.org>
* refactor: enhance wasmBasePlugin to support specific plugin types for improved type safety
Signed-off-by: Deluan <deluan@navidrome.org>
* refactor: implement MediaMetadataService with combined artist and album methods
Signed-off-by: Deluan <deluan@navidrome.org>
* refactor: improve MediaMetadataService plugin implementation and testing structure
Signed-off-by: Deluan <deluan@navidrome.org>
* refactor: add tests for Adapter Media Agent and improve plugin documentation
Signed-off-by: Deluan <deluan@navidrome.org>
* docs: add README for Navidrome Plugin System with detailed architecture and usage guidelines
Signed-off-by: Deluan <deluan@navidrome.org>
* refactor: enhance agent management with plugin loading and caching
Signed-off-by: Deluan <deluan@navidrome.org>
* refactor: update agent discovery logic to include only local agent when no config is specified
Signed-off-by: Deluan <deluan@navidrome.org>
* refactor: encapsulate agent caching logic in agentCache struct\n\nReplaced direct map/mutex usage for agent caching in Agents with a dedicated agentCache struct. This improves readability, maintainability, and testability by centralizing TTL and concurrency logic. Cleaned up comments and ensured all linter and test requirements are met.
Signed-off-by: Deluan <deluan@navidrome.org>
* fix: correct file extension filter in goimports command
Signed-off-by: Deluan <deluan@navidrome.org>
* refactor: use defer to unlock the mutex
Signed-off-by: Deluan <deluan@navidrome.org>
* chore: move Cover Art Archive AlbumMetadataService plugins to an example folder
Signed-off-by: Deluan <deluan@navidrome.org>
* fix: handle errors when creating media metadata and scrobbler service plugins
Signed-off-by: Deluan <deluan@navidrome.org>
* fix: increase compilation timeout to one minute
Signed-off-by: Deluan <deluan@navidrome.org>
* feat: add configurable plugin compilation timeout
Signed-off-by: Deluan <deluan@navidrome.org>
* feat: implement plugin scrobbler support in PlayTracker
Signed-off-by: Deluan <deluan@navidrome.org>
* feat: add context management and Stop method to buffered scrobbler
Signed-off-by: Deluan <deluan@navidrome.org>
* feat: add username field to scrobbler requests and update logging
Signed-off-by: Deluan <deluan@navidrome.org>
* fix: data race in test
Signed-off-by: Deluan <deluan@navidrome.org>
* refactor: rename http proto files to host and update references
Signed-off-by: Deluan <deluan@navidrome.org>
* refactor: remove unused plugin registration methods from manager
Signed-off-by: Deluan <deluan@navidrome.org>
* feat: extend plugin manifests and implement plugin management commands
Signed-off-by: Deluan <deluan@navidrome.org>
* Update utils/files.go
Co-authored-by: ellipsis-dev[bot] <65095814+ellipsis-dev[bot]@users.noreply.github.com>
* fix for code scanning alert no. 43: Arbitrary file access during archive extraction ("Zip Slip")
Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
* feat: add plugin dev workflow support
Added new CLI commands to improve plugin development workflow: 'plugin dev' to create symlinks from development directories to plugins folder, 'plugin refresh' to reload plugins without restarting Navidrome, enhanced 'plugin remove' to handle symlinked development plugins correctly, and updated 'plugin list' to display development plugins with '(dev)' indicator. These changes make the plugin development workflow more efficient by allowing developers to work on plugins in their own directories, link them to Navidrome without copying files, refresh plugins after changes without restart, and clean up safely.
Signed-off-by: Deluan <deluan@navidrome.org>
* feat(plugins): implement timer service with register and cancel functionality - WIP
Signed-off-by: Deluan <deluan@navidrome.org>
* feat(plugins): implement timer service with register and cancel functionality - WIP
Signed-off-by: Deluan <deluan@navidrome.org>
* feat(plugins): implement timer service with register and cancel functionality - WIP
Signed-off-by: Deluan <deluan@navidrome.org>
* feat(plugins): implement timer service with register and cancel functionality
Signed-off-by: Deluan <deluan@navidrome.org>
* fix: lint errors
Signed-off-by: Deluan <deluan@navidrome.org>
* feat(README): update documentation to include TimerCallbackService and its functionality
Signed-off-by: Deluan <deluan@navidrome.org>
* feat(plugins): add InitService with OnInit method and initialization tracking - WIP
Signed-off-by: Deluan <deluan@navidrome.org>
* feat(plugins): add tests for InitService and plugin initialization tracking
Signed-off-by: Deluan <deluan@navidrome.org>
* feat(plugins): expand documentation on plugin system implementation and architecture
Signed-off-by: Deluan <deluan@navidrome.org>
* fix: panic
Signed-off-by: Deluan <deluan@navidrome.org>
* feat(plugins): redirect plugins' stderr to logs
Signed-off-by: Deluan <deluan@navidrome.org>
* feat(plugins): add safe accessor methods for TimerService
Signed-off-by: Deluan <deluan@navidrome.org>
* feat(plugins): add plugin-specific configuration support in InitRequest and documentation
Signed-off-by: Deluan <deluan@navidrome.org>
* feat(plugins): add TimerCallbackService plugin adapter and integration
Signed-off-by: Deluan <deluan@navidrome.org>
* refactor(plugins): rename services for consistency and clarity
Signed-off-by: Deluan <deluan@navidrome.org>
* feat(plugins): add mutex for configuration access and clone plugin config
Signed-off-by: Deluan <deluan@navidrome.org>
* refactor(tests): remove configtest dependency to prevent data races in integration tests
Signed-off-by: Deluan <deluan@navidrome.org>
* refactor(plugins): remove PluginName method from WASM plugin implementations and update LoadPlugin to accept service type
Signed-off-by: Deluan <deluan@navidrome.org>
* feat(plugins): implement instance pooling for wasmBasePlugin to improve performance - WIP
Signed-off-by: Deluan <deluan@navidrome.org>
* feat(plugins): add wasmInstancePool for managing WASM plugin instances with TTL and max size
Signed-off-by: Deluan <deluan@navidrome.org>
* fix(plugins): correctly pass error to done function in wasmBasePlugin
Signed-off-by: Deluan <deluan@navidrome.org>
* refactor(plugins): rename service types to capabilities for consistency
Signed-off-by: Deluan <deluan@navidrome.org>
* refactor(plugins): simplify instance management in wasmBasePlugin by removing error handling in closure
Signed-off-by: Deluan <deluan@navidrome.org>
* refactor(plugins): update wasmBasePlugin and wasmInstancePool to return errors for better error handling
Signed-off-by: Deluan <deluan@navidrome.org>
* refactor(plugins): rename InitService to LifecycleManagement for consistency
Signed-off-by: Deluan <deluan@navidrome.org>
* refactor(plugins): fix instance ID logging in wasmBasePlugin
Signed-off-by: Deluan <deluan@navidrome.org>
* refactor(plugins): extract instance ID logging to a separate function in wasmBasePlugin, to avoid vet error
Signed-off-by: Deluan <deluan@navidrome.org>
* refactor(plugins): make timers be isolated per plugin
Signed-off-by: Deluan <deluan@navidrome.org>
* refactor(plugins): make timers be isolated per plugin
Signed-off-by: Deluan <deluan@navidrome.org>
* refactor(plugins): rename HttpServiceImpl to httpServiceImpl for consistency and improve logging
Signed-off-by: Deluan <deluan@navidrome.org>
* feat(plugins): add config service for plugin-specific configuration management
Signed-off-by: Deluan <deluan@navidrome.org>
* Update plugins/manager.go
Co-authored-by: ellipsis-dev[bot] <65095814+ellipsis-dev[bot]@users.noreply.github.com>
* Update plugins/manager.go
Co-authored-by: ellipsis-dev[bot] <65095814+ellipsis-dev[bot]@users.noreply.github.com>
* feat(crontab): implement crontab service for scheduling and canceling jobs
Signed-off-by: Deluan <deluan@navidrome.org>
* fix(singleton): fix deadlock issue when a constructor calls GetSingleton again
Signed-off-by: Deluan <deluan@navidrome.org> (+1 squashed commit)
Squashed commits:
[325a96ea2] fix(singleton): fix deadlock issue when a constructor calls GetSingleton again
Signed-off-by: Deluan <deluan@navidrome.org>
* feat(scheduler): implement Scheduler for one-time and recurring job scheduling, merging CrontabService and TimerService
Signed-off-by: Deluan <deluan@navidrome.org>
* fix(scheduler): race condition in the scheduleOneTime and scheduleRecurring methods when replacing jobs with the same ID
Signed-off-by: Deluan <deluan@navidrome.org>
* refactor(scheduler): consolidate job scheduling logic into a single helper function
Signed-off-by: Deluan <deluan@navidrome.org>
* refactor(plugin): rename GetInstance method to Instantiate for clarity
Signed-off-by: Deluan <deluan@navidrome.org>
* feat(plugins): add WebSocket service for handling connections and messages
Signed-off-by: Deluan <deluan@navidrome.org>
* feat(crypto-ticker): add WebSocket plugin for real-time cryptocurrency price tracking
Signed-off-by: Deluan <deluan@navidrome.org>
* feat(websocket): enhance connection management and callback handling
Signed-off-by: Deluan <deluan@navidrome.org>
* feat(manager): only create one adapter instance for each adapter/capability pair
Signed-off-by: Deluan <deluan@navidrome.org>
* fix(websocket): ensure proper resource management by closing response body and use defer to unlocking mutexes
Signed-off-by: Deluan <deluan@navidrome.org>
* fix: flaky test
Signed-off-by: Deluan <deluan@navidrome.org>
* feat(plugin): refactor WebSocket service integration and improve error logging
Signed-off-by: Deluan <deluan@navidrome.org>
* feat(plugin): add SchedulerCallback support and improve reconnection logic
Signed-off-by: Deluan <deluan@navidrome.org>
* fix: test panic
Signed-off-by: Deluan <deluan@navidrome.org>
* docs: add crypto-ticker plugin example to README
Signed-off-by: Deluan <deluan@navidrome.org>
* feat(manager): add LoadAllPlugins and LoadAllMediaAgents methods with slice.Map integration
Signed-off-by: Deluan <deluan@navidrome.org>
* feat(api): add Timestamp field to ScrobblerNowPlayingRequest and update related methods
Signed-off-by: Deluan <deluan@navidrome.org>
* feat(websocket): add error field to response messages for better error handling
Signed-off-by: Deluan <deluan@navidrome.org>
* feat(cache): implement CacheService with string, int, float, and byte operations
Signed-off-by: Deluan <deluan@navidrome.org>
* feat(tests): update buffered scrobbler tests for improved scrobble verification and use RWMutex in mock repo
Signed-off-by: Deluan <deluan@navidrome.org>
* refactor(cache): simplify cache service implementation and remove unnecessary synchronization
Signed-off-by: Deluan <deluan@navidrome.org>
* feat(tests): add build step for test plugins in the test suite
Signed-off-by: Deluan <deluan@navidrome.org>
* wip
Signed-off-by: Deluan <deluan@navidrome.org>
* feat(scheduler): implement named scheduler callbacks and enhance Discord plugin integration
Signed-off-by: Deluan <deluan@navidrome.org>
* feat(rpc): enhance activity image processing and improve error handling in Discord integration
Signed-off-by: Deluan <deluan@navidrome.org>
* feat(discord): enhance activity state with artist list and add large text asset
Signed-off-by: Deluan <deluan@navidrome.org>
* fix tests
Signed-off-by: Deluan <deluan@navidrome.org>
* feat(artwork): implement ArtworkService for retrieving artwork URLs
Signed-off-by: Deluan <deluan@navidrome.org>
* Add playback position to scrobble NowPlaying (#4089)
* test(playtracker): cover playback position
* address review comment
Signed-off-by: Deluan <deluan@navidrome.org>
---------
Signed-off-by: Deluan <deluan@navidrome.org>
* fix merge
Signed-off-by: Deluan <deluan@navidrome.org>
* refactor: remove unnecessary check for empty slice in Map function
Signed-off-by: Deluan <deluan@navidrome.org>
* fix: update reflex.conf to include .wasm file extension
Signed-off-by: Deluan <deluan@navidrome.org>
* fix(scanner): normalize attribute strings and add edge case tests for PID calculation
Relates to https://github.com/navidrome/navidrome/issues/4183#issuecomment-2952729458
Signed-off-by: Deluan <deluan@navidrome.org>
* test(ui): fix warnings (#4187)
* fix(ui): address test warnings
* ignore lint error in test
Signed-off-by: Deluan <deluan@navidrome.org>
---------
Signed-off-by: Deluan <deluan@navidrome.org>
* refactor(server): optimize top songs lookup (#4189)
* optimize top songs lookup
* Optimize title matching queries
* refactor: simplify top songs matching
* improve error handling and logging in track loading functions
Signed-off-by: Deluan <deluan@navidrome.org>
* test: add cases for fallback to title matching and combined MBID/title matching
Signed-off-by: Deluan <deluan@navidrome.org>
---------
Signed-off-by: Deluan <deluan@navidrome.org>
* fix(ui): playlist details overflow in spotify-based themes (#4184)
* test: ensure playlist details width
* fix(test): simplify expectation for minWidth in NDPlaylistDetails
Signed-off-by: Deluan <deluan@navidrome.org>
* fix(test): test all themes
Signed-off-by: Deluan <deluan@navidrome.org>
---------
Signed-off-by: Deluan <deluan@navidrome.org>
* chore(deps): update TagLib to version 2.1 (#4185)
* chore: update cross-taglib
* fix(taglib): add logging for TagLib version
Signed-off-by: Deluan <deluan@navidrome.org>
---------
Signed-off-by: Deluan <deluan@navidrome.org>
* test: verify agents fallback (#4191)
* build(docker): downgrade Alpine version from 3.21 to 3.19, oldest supported version.
This is to reduce the image size, as we don't really need the latest.
Signed-off-by: Deluan <deluan@navidrome.org>
* fix tests
Signed-off-by: Deluan <deluan@navidrome.org>
* feat(runtime): implement pooled WASM runtime and module for better instance management
Signed-off-by: Deluan <deluan@navidrome.org>
* fix(discord-plugin): adjust timer delay calculation for track completion
Signed-off-by: Deluan <deluan@navidrome.org>
* resolve PR comments
Signed-off-by: Deluan <deluan@navidrome.org>
* feat(plugins): implement cache cleanup by size functionality
Signed-off-by: Deluan <deluan@navidrome.org>
* fix(manager): return error from getCompilationCache and handle it in ScanPlugins
Signed-off-by: Deluan <deluan@navidrome.org>
* fix possible rce condition
Signed-off-by: Deluan <deluan@navidrome.org>
* feat(docs): update README to include Cache and Artwork services
Signed-off-by: Deluan <deluan@navidrome.org>
* feat(manager): add permissions support for host services in custom runtime - WIP
Signed-off-by: Deluan <deluan@navidrome.org>
* feat(manifest): add permissions field to plugin manifests - WIP
Signed-off-by: Deluan <deluan@navidrome.org>
* test(permissions): implement permission validation and testing for plugins - WIP
Signed-off-by: Deluan <deluan@navidrome.org>
* feat(plugins): add unauthorized_plugin to test permission enforcement - WIP
Signed-off-by: Deluan <deluan@navidrome.org>
* feat(docs): add Plugin Permission System section to README - WIP
Signed-off-by: Deluan <deluan@navidrome.org>
* feat(manifest): add detailed reasons for permissions in plugin manifests - WIP
Signed-off-by: Deluan <deluan@navidrome.org>
* feat(permissions): implement granular HTTP permissions for plugins - WIP
Signed-off-by: Deluan <deluan@navidrome.org>
* feat(permissions): implement HTTP and WebSocket permissions for plugins - WIP
Signed-off-by: Deluan <deluan@navidrome.org>
* refactor
Signed-off-by: Deluan <deluan@navidrome.org>
* refactor: unexport all plugins package private symbols
Signed-off-by: Deluan <deluan@navidrome.org>
* update docs
Signed-off-by: Deluan <deluan@navidrome.org>
* refactor: rename plugin_lifecycle_manager
Signed-off-by: Deluan <deluan@navidrome.org>
* docs: add discord-rich-presence plugin example to README
Signed-off-by: Deluan <deluan@navidrome.org>
* feat: add support for PATCH, HEAD, and OPTIONS HTTP methods
Signed-off-by: Deluan <deluan@navidrome.org>
* feat: use folder names as unique identifiers for plugins
Signed-off-by: Deluan <deluan@navidrome.org>
* fix: read config just once, to avoid data race in tests
Signed-off-by: Deluan <deluan@navidrome.org>
* refactor: rename pluginName to pluginID for consistency across services
Signed-off-by: Deluan <deluan@navidrome.org>
* fix: use symlink name instead of folder name for plugin registration
Signed-off-by: Deluan <deluan@navidrome.org>
* feat: update plugin output format to include ID and enhance README with symlink usage
Signed-off-by: Deluan <deluan@navidrome.org>
* refactor: implement shared plugin discovery function to streamline plugin scanning and error handling
Signed-off-by: Deluan <deluan@navidrome.org>
* feat: show plugin permissions in `plugin info`
Signed-off-by: Deluan <deluan@navidrome.org>
* feat: add JSON schema for Navidrome Plugin manifest and generate corresponding Go types - WIP
Signed-off-by: Deluan <deluan@navidrome.org>
* feat: implement typed permissions for plugins to enhance permission handling
Signed-off-by: Deluan <deluan@navidrome.org>
* feat: refactor plugin permissions to use typed schema and improve validation - WIP
Signed-off-by: Deluan <deluan@navidrome.org>
* feat: update HTTP permissions handling to use typed schema for allowed URLs - WIP
Signed-off-by: Deluan <deluan@navidrome.org>
* feat: remove unused JSON schema validation for plugin manifests
Signed-off-by: Deluan <deluan@navidrome.org>
* feat: remove unused fields from PluginPackage struct in package.go
Signed-off-by: Deluan <deluan@navidrome.org>
* feat: update file permissions in tests and remove unused permission parsing function
Signed-off-by: Deluan <deluan@navidrome.org>
* feat: refactor test plugin creation to use typed permissions and remove legacy helper
Signed-off-by: Deluan <deluan@navidrome.org>
* feat: add website field to plugin manifests and update test cases
Signed-off-by: Deluan <deluan@navidrome.org>
* refactor: permission schema to use basePermission structure for consistency
Signed-off-by: Deluan <deluan@navidrome.org>
* feat: enhance host service management by adding permission checks for each service
Signed-off-by: Deluan <deluan@navidrome.org>
* refactor: reorganize code files
Signed-off-by: Deluan <deluan@navidrome.org>
* refactor: simplify custom runtime creation by removing compilation cache parameter
Signed-off-by: Deluan <deluan@navidrome.org>
* doc: add WebSocketService and update ConfigService for plugin-specific configuration
Signed-off-by: Deluan <deluan@navidrome.org>
* feat: implement WASM loading optimization to enhance plugin instance creation speed
Signed-off-by: Deluan <deluan@navidrome.org>
* refactor: rename custom runtime functions and update related tests for clarity
Signed-off-by: Deluan <deluan@navidrome.org>
* refactor: enhance plugin structure with compilation handling and error reporting
Signed-off-by: Deluan <deluan@navidrome.org>
* refactor: improve logging and context tracing in runtime and wasm base plugin
Signed-off-by: Deluan <deluan@navidrome.org>
* refactor: enhance runtime management with scoped runtime and caching improvements
Signed-off-by: Deluan <deluan@navidrome.org>
* refactor: implement EnsureCompiled method for improved plugin compilation handling
Signed-off-by: Deluan <deluan@navidrome.org>
* refactor: implement cached module management with TTL for improved performance
Signed-off-by: Deluan <deluan@navidrome.org>
* refactor: replace map with sync.Map
Signed-off-by: Deluan <deluan@navidrome.org>
* refactor: adjust time tolerance in scrobble buffer repository tests to avoid flakiness
Signed-off-by: Deluan <deluan@navidrome.org>
* refactor: enhance image processing with fallback mechanism for improved error handling
Signed-off-by: Deluan <deluan@navidrome.org>
* docs: review test plugins readme
Signed-off-by: Deluan <deluan@navidrome.org>
* feat: set default timeout for HTTP client to 10 seconds
Signed-off-by: Deluan <deluan@navidrome.org>
* feat: enhance wasm instance pool with concurrency limits and timeout settings
Signed-off-by: Deluan <deluan@navidrome.org>
* feat(discordrp): implement caching for processed image URLs with configurable TTL
Signed-off-by: Deluan <deluan@navidrome.org>
---------
Signed-off-by: Deluan <deluan@navidrome.org>
Co-authored-by: ellipsis-dev[bot] <65095814+ellipsis-dev[bot]@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
* fix(ui,scanner,subsonic): Allow nullable replaygain and support 0.0
Resolves#4236.
Makes the replaygain columns (track/album gain/peak) nullable.
Converts the type to a pointer, allowing for 0.0 (a valid value) to be returned from Subsonic.
Updates tests for this behavior.
* small refactor
Signed-off-by: Deluan <deluan@navidrome.org>
---------
Signed-off-by: Deluan <deluan@navidrome.org>
Co-authored-by: Deluan <deluan@navidrome.org>
* fix(subsonic): Sort songs by presence of lyrics for `getLyrics`
The current implementation of `getLyrics` fetches any songs matching the artist and title.
However, this misses a case where there may be multiple matches for the same artist/song, and one has lyrics while the other doesn't.
Resolve this by adding a custom SQL dynamic column that checks for the presence of lyrics.
* add options to selectMediaFile, update test
* more robust testing of GetAllByLyrics
* fix(subsonic): refactor GetAllByLyrics to GetAll with lyrics sorting
Signed-off-by: Deluan <deluan@navidrome.org>
* use has_lyrics, and properly support multiple sort parts
* better handle complicated internal sorts
* just use a simpler filter
* add note to setSortMappings
* remove custom sort mapping, improve test with different updatedat
* refactor tests and mock
Signed-off-by: Deluan <deluan@navidrome.org>
* default order when not specified is `asc`
Signed-off-by: Deluan <deluan@navidrome.org>
---------
Signed-off-by: Deluan <deluan@navidrome.org>
Co-authored-by: Deluan <deluan@navidrome.org>
* fix(db): add user foreign key constraint to annotation table
Associates user_id with user.id, with cascade for delete (drop annotation) and update (update annotation).
Migration script will only copy/insert annotations for user IDs that exist
* remove default for user_id
* refactor(db): rename migration correct sequencing
Signed-off-by: Deluan <deluan@navidrome.org>
---------
Signed-off-by: Deluan <deluan@navidrome.org>
Co-authored-by: Deluan <deluan@navidrome.org>
* Add migration converting playqueue current to index
* refactor
Signed-off-by: Deluan <deluan@navidrome.org>
* fix(queue): ensure valid current index and improve test coverage
Signed-off-by: Deluan <deluan@navidrome.org>
---------
Signed-off-by: Deluan <deluan@navidrome.org>
* feat(ui): add Now Playing panel and integrate now playing count updates
Signed-off-by: Deluan <deluan@navidrome.org>
* fix: check return value in test to satisfy linter
* fix: format React code with prettier
* fix: resolve race condition in play tracker test
* fix: log error when fetching now playing data fails
Signed-off-by: Deluan <deluan@navidrome.org>
* feat(ui): refactor Now Playing panel with new components and error handling
Signed-off-by: Deluan <deluan@navidrome.org>
* fix(ui): adjust padding and height in Now Playing panel for improved layout
Signed-off-by: Deluan <deluan@navidrome.org>
* fix(cache): add automatic cleanup to prevent goroutine leak on cache garbage collection
Signed-off-by: Deluan <deluan@navidrome.org>
---------
Signed-off-by: Deluan <deluan@navidrome.org>
* ui: add Play button to artist toolbar
* refactor
Signed-off-by: Deluan <deluan@navidrome.org>
* test(ui): add tests for Play button functionality in ArtistActions
Signed-off-by: Deluan <deluan@navidrome.org>
* ui: update Play button label to Top Songs in ArtistActions
Signed-off-by: Deluan <deluan@navidrome.org>
---------
Signed-off-by: Deluan <deluan@navidrome.org>
* Add Play Similar option
* Add pt-br translation for Play Similar
* Refactor playSimilar and add helper
* Improve Play Similar feedback
* Add artist actions bar with shuffle and radio
* Add Play Similar menu and align artist actions
* Refine artist actions and revert menu option
* fix(ui): enhance layout of ArtistActions and ArtistShow components
Signed-off-by: Deluan <deluan@navidrome.org>
* fix(i18n): revert unused changes
Signed-off-by: Deluan <deluan@navidrome.org>
* fix(ui): improve layout for mobile
Signed-off-by: Deluan <deluan@navidrome.org>
* fix(ui): improve error handling for fetching similar songs
Signed-off-by: Deluan <deluan@navidrome.org>
* fix(ui): enhance error logging for fetching songs in shuffle
Signed-off-by: Deluan <deluan@navidrome.org>
* refactor(ui): shuffle handling to use async/await for better readability
Signed-off-by: Deluan <deluan@navidrome.org>
* refactor(ui): simplify button label handling in ArtistActions component
Signed-off-by: Deluan <deluan@navidrome.org>
---------
Signed-off-by: Deluan <deluan@navidrome.org>
- Fix GetUser JukeboxRole to properly respect AdminOnly setting
- Extract buildUserResponse helper to eliminate duplication between GetUser and GetUsers
- Fix username field inconsistency (GetUsers was using loggedUser.Name instead of UserName)
- Add comprehensive tests covering jukebox role permissions and consistency between methods
Fixes#4160
* fix(configuration.go, mpv.go): Jukebox mode doesn't include MusicFolder in mpv command - #4066
The call to createMPVCommand is not including the MusicFolder path in
mpv command causing it to fail with file not found errors.
Updated default command template and createMPVCommand to use additional
substitution with conf.server.MusicFolder
Signed-off-by: Pat <patso.oshea@gmail.com>
* Revert config.go change, use filepath.Join for cross platform
* Update track.go with mf.AbsolutePath()
---------
Signed-off-by: Pat <patso.oshea@gmail.com>
Co-authored-by: Deluan <deluan@navidrome.org>
* Update song playlist menu and endpoint
* feat(ui): show submenu on click, not on hover
Signed-off-by: Deluan <deluan@navidrome.org>
* feat(ui): integrate dataProvider for fetching playlists in song context menu
Signed-off-by: Deluan <deluan@navidrome.org>
* feat(ui): update song context menu to use dataProvider for fetching playlists and inspecting songs
Signed-off-by: Deluan <deluan@navidrome.org>
* feat(ui): stop event propagation when closing playlist submenu
Signed-off-by: Deluan <deluan@navidrome.org>
* feat(ui): add 'show in playlist' option to options object
Signed-off-by: Deluan <deluan@navidrome.org>
---------
Signed-off-by: Deluan <deluan@navidrome.org>
* fix: enhance artist folder detection with directory traversal
Enhanced fromArtistFolder function to implement directory traversal fallback for finding artist images. The original implementation only searched in the calculated artist folder, which failed for single album artists where artist.jpg files were not detected.
Changes: Modified fromArtistFolder to search up to 3 directory levels (artist folder + 2 parent levels), extracted findImageInFolder helper function for cleaner code organization, added proper boundary checks to prevent infinite traversal, maintained backward compatibility with existing functionality.
This fix ensures artist.jpg files are properly detected for single album artists while preserving all existing behavior for multi-album artists.
* refactor: address PR review suggestions
Applied review suggestions from gemini-code-assist bot:
- Added maxArtistFolderTraversalDepth constant instead of hardcoded value 3
- Updated error message to mention that parent directories were also searched
- Enhanced test assertion to verify the improved error message
* fix: improve artist folder traversal logic and enhance error logging
Signed-off-by: Deluan <deluan@navidrome.org>
* fix: remove test for special glob characters in artist folder detection
Signed-off-by: Deluan <deluan@navidrome.org>
* fix: add logging for artist image search in folder
Signed-off-by: Deluan <deluan@navidrome.org>
---------
Signed-off-by: Deluan <deluan@navidrome.org>
Changed translation of "Top Rated" from "Los Mejores Calificados" to "Mejor Calificados" for consistency purposes with other list entries. While the previous version was correct, this version is shorter and aligns better with the rest of the terms.
* Update eu.json
Added roles, reordered some strings, small fixes
* fix(ui): update Basque translation
* Update eu.json
third time's the charm
* please bear with me
I'm not a developer. I'm trying my hardest.
* Update eu.json
Added newest strings
* find artist by multivalued exact match, instead of 'artist' field
* check if lyrics are not empty
* refactor(filters): rename function to better reflect its purpose
Signed-off-by: Deluan <deluan@navidrome.org>
---------
Signed-off-by: Deluan <deluan@navidrome.org>
Co-authored-by: Deluan <deluan@navidrome.org>
* feat(scanner): add LastScanError tracking to scanner status
- Introduced LastScanErrorKey constant for error tracking.
- Updated StatusInfo struct to include LastError field.
- Modified scanner logic to store and retrieve last scan error.
- Enhanced ScanStatus response to include error information.
- Updated UI components to display last scan error when applicable.
- Added tests to verify last scan error functionality.
Signed-off-by: Deluan <deluan@navidrome.org>
* feat(scanner): enhance scan status with type and elapsed time tracking
- Added LastScanTypeKey and LastScanStartTimeKey constants for tracking scan type and start time.
- Updated StatusInfo struct to include ScanType and ElapsedTime fields.
- Implemented getScanInfo method to retrieve scan type, elapsed time, and last error.
- Modified scanner logic to store scan type and start time during scans.
- Enhanced ScanStatus response and UI components to display scan type and elapsed time.
- Added formatShortDuration utility for better elapsed time representation.
- Updated activity reducer to handle new scan status fields.
Signed-off-by: Deluan <deluan@navidrome.org>
* refactor(tests): consolidate controller status tests into a single file
- Removed the old controller_status_test.go file.
- Merged relevant tests into the new controller_test.go file for better organization and maintainability.
- Ensured all existing test cases for controller status are preserved and functional.
Signed-off-by: Deluan <deluan@navidrome.org>
* Fix formatting issues
* refactor(scanner): update getScanInfo method documentation
---------
Signed-off-by: Deluan <deluan@navidrome.org>
* fix(artist): update RefreshStats to only process artists with recently updated media files
Signed-off-by: Deluan <deluan@navidrome.org>
* fix: paginate Artist's RefreshStats, also replace rawSQL with Expr
Signed-off-by: Deluan <deluan@navidrome.org>
---------
Signed-off-by: Deluan <deluan@navidrome.org>
Removed all code, config, and test references to DevEnableBufferedScrobble. Buffered scrobbling is now always enabled. Added this option to the list of deprecated config options with a warning. Updated all logic and tests to reflect this. No linter issues remain. Some PlayTracker tests are failing, but these are likely due to test data or logic unrelated to this change. All other tests pass. Review required for PlayTracker test failures.
Signed-off-by: Deluan <deluan@navidrome.org>
Added Ginkgo/Gomega tests for userName and AbsolutePath functions in core/common.go. Tests cover normal and error cases, using existing mocks and helpers. This improves coverage and ensures correct behavior for user context extraction and library path resolution.
* fix(ui): ensure album tracks are always ordered by disc and track number (fixes#3720)
* refactor(ui): remove obsolete release date grouping logic from SongDatagrid and AlbumSongs
* fix(ui): ensure correct album track ordering in context menu and play button
* fix: Update album sort to use album_id instead of release_date
* refactor: Adjust filters in PlayButton and AlbumContextMenu
* fix: correct typo in comment regarding participants in GetMissingAndMatching function
* fix: prevent visual separation of tracks on same disc
Removes the leftover `releaseDate` check from the `firstTracksOfDiscs` calculation in `SongDatagridBody`. This check caused unnecessary `DiscSubtitleRow` insertions when tracks on the same disc had different release dates, leading to an incorrect visual grouping that resembled a multi-disc layout.
This change ensures disc subtitles are only shown when the actual `discNumber` changes, correcting the UI presentation issue reported in issue #3720 after PR #3975.
* fix: remove remaining releaseDate references in SongDatagrid
Cleaned up leftover `releaseDate` references in `SongDatagrid.jsx`:
- Removed `releaseDate` parameter and usage from `handlePlaySubset` in `DiscSubtitleRow`.
- Removed `releaseDate` prop passed to `AlbumContextMenu` in `DiscSubtitleRow`.
- Removed `releaseDate` from the drag item data in `SongDatagridRow`.
- Removed `releaseDate` parameter and the corresponding `else` block from the `playSubset` function in `SongDatagridBody`.
This ensures the component consistently uses `discNumber` for grouping and playback actions initiated from the disc subtitle, fully resolving the inconsistencies related to issue #3720.
* fix(server): bring back legacy date mappings
Signed-off-by: Deluan <deluan@navidrome.org>
* reuse the mapDates logic in the legacyReleaseDate function
Signed-off-by: Deluan <deluan@navidrome.org>
* fix mappings
Signed-off-by: Deluan <deluan@navidrome.org>
* show original and release dates in album grid
Signed-off-by: Deluan <deluan@navidrome.org>
* fix tests based on new year mapping
Signed-off-by: Deluan <deluan@navidrome.org>
* fix(subsonic): prefer returning original_year over (recording) year
when sorting albums
Signed-off-by: Deluan <deluan@navidrome.org>
* fix case when we don't have originalYear
Signed-off-by: Deluan <deluan@navidrome.org>
* show all dates in album's info, and remove the recording date from the album page
Signed-off-by: Deluan <deluan@navidrome.org>
* better?
Signed-off-by: Deluan <deluan@navidrome.org>
* add snapshot tests for Album Details
Signed-off-by: Deluan <deluan@navidrome.org>
* fix(subsonic): sort order for getAlbumList?type=byYear
Signed-off-by: Deluan <deluan@navidrome.org>
---------
Signed-off-by: Deluan <deluan@navidrome.org>
* chore(server): add more info to scrobble errors
Signed-off-by: Deluan <deluan@navidrome.org>
* chore(server): add more info to scrobble errors
Signed-off-by: Deluan <deluan@navidrome.org>
* chore(server): add more info to scrobble errors
Signed-off-by: Deluan <deluan@navidrome.org>
---------
Signed-off-by: Deluan <deluan@navidrome.org>
* chore(scanner): add trace logs
Signed-off-by: Deluan <deluan@navidrome.org>
* fix(bfr): force upgrade to read all folders. It was skipping folders for certain timezones
Signed-off-by: Deluan <deluan@navidrome.org>
---------
Signed-off-by: Deluan <deluan@navidrome.org>
- `-map 0:v` selects all video streams from the input
- `-map -0:V` excludes all "main" video streams (capital V)
This combination effectively selects only the attached pictures
Signed-off-by: Deluan <deluan@navidrome.org>
Previously addLine would add-or-update, resulting in the custom settings being overriden on upgrade. createLine will only add to the ini if the key doesn't already exist.
* chore(ui): Fix minor inconsistencies
1. The icons in the user menu are a mix of MUI and react-icons. Move them all to react-icons, and use a standard size (24px)
2. On missing files page, provide a custom Empty component that just removes 'yet'
* use RA's builtin support for custom empty message
Signed-off-by: Deluan <deluan@navidrome.org>
---------
Signed-off-by: Deluan <deluan@navidrome.org>
Co-authored-by: Deluan <deluan@navidrome.org>
* only do subsonic instead
* make sure to actually populate response first
* navidrome artist filtering
* address discord feedback
* perPage min 36
* various artist artist_id -> albumartist_id
* artist_id, role_id separate
* remove all ui changes I guess
* Revert role filters
Signed-off-by: Deluan <deluan@navidrome.org>
---------
Signed-off-by: Deluan <deluan@navidrome.org>
Co-authored-by: Deluan <deluan@navidrome.org>
With old metadata, Disc Subtitle was one of `tsst`, `discsubtitle`, or `setsubtitle`.
With the updated, `setsubtitle` is only available for flac.
Update `mappings.yaml` to maintain prior behavior.
* fix(server): db migration was not working for MusicFolders ending with a trailing slash.
Signed-off-by: Deluan <deluan@navidrome.org>
* fix(server): db migration for relative paths
Signed-off-by: Deluan <deluan@navidrome.org>
---------
Signed-off-by: Deluan <deluan@navidrome.org>
1. For some bizarre reason, importing inflection by itself is undefined. But you can import specific functions
2. Per https://github.com/vite-pwa/vite-plugin-pwa/issues/419, `type: 'module',` is only for non-chromium browsers
* fix(server): db migration not working when MusicFolder is a relative path
Signed-off-by: Deluan <deluan@navidrome.org>
* remove todo
Signed-off-by: Deluan <deluan@navidrome.org>
* fix migration of paths in Windows
---------
Signed-off-by: Deluan <deluan@navidrome.org>
* fix(scanner): Always refresh folder image time when adding first image
Currently, the `images_updated_at` field is only set to the image modification time.
However, in cases where a new image is added _and_ said image is older than the folder mod time, the field is not updated properly.
In this the case where `images_updated_at` is null (no images were ever added) and a new images is found, use the folder modification time instead of image modification time.
**Note**, this doesn't handle cases such as replacing a newer image with an older one.
* simplify image update at
* we don't want to set imagesUpdatedAt when there's no images in the folder
Signed-off-by: Deluan <deluan@navidrome.org>
---------
Signed-off-by: Deluan <deluan@navidrome.org>
Co-authored-by: Deluan <deluan@navidrome.org>
* feat(subsonic): Set SortName for OS AlbumList, test to JSON/XML
* albumlist2, star2 updated properly
* fix(subsonic): add sort or order name based on config
Signed-off-by: Deluan <deluan@navidrome.org>
---------
Signed-off-by: Deluan <deluan@navidrome.org>
Co-authored-by: Deluan <deluan@navidrome.org>
* fix(scanner): remove transactions where they are not strictly needed
Signed-off-by: Deluan <deluan@navidrome.org>
* fix(server): force setStar transaction to start as IMMEDIATE
Signed-off-by: Deluan <deluan@navidrome.org>
* fix(server): encapsulated way to upgrade tx to write mode
Signed-off-by: Deluan <deluan@navidrome.org>
* fix(server): use tx immediate for some playlist endpoints
Signed-off-by: Deluan <deluan@navidrome.org>
* make more transactions immediate (#3759)
---------
Signed-off-by: Deluan <deluan@navidrome.org>
Co-authored-by: Kendall Garner <17521368+kgarner7@users.noreply.github.com>
* test(server): validate play tracker participants, scrobble buffer
* tests(server): nit: remove duplicated tests and small cleanups
Signed-off-by: Deluan <deluan@navidrome.org>
* tests(server): nit: replace panics with assertions
Signed-off-by: Deluan <deluan@navidrome.org>
* just use random ids, and store it instead
---------
Signed-off-by: Deluan <deluan@navidrome.org>
Co-authored-by: Deluan <deluan@navidrome.org>
* feat(ui): Improve Artist Album pagination
- use maximum of albumartist/artist credits for determining pagination
- reduce default maxPerPage considerably. This gives values of 36/72/108 at largest size
* enable pagination when over 90
Signed-off-by: Deluan <deluan@navidrome.org>
---------
Signed-off-by: Deluan <deluan@navidrome.org>
Co-authored-by: Deluan <deluan@navidrome.org>
* fix(ui): Update Russian translations
- Adds missing strings added in the past couple releases
- Fixes a few confusing translations in the "share" section
* Add missing comma
* 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>
* refactor(ci): add updated languages to the POEditor PR title
Signed-off-by: Deluan <deluan@navidrome.org>
* refactor(ci): add an author to the PR
Signed-off-by: Deluan <deluan@navidrome.org>
---------
Signed-off-by: Deluan <deluan@navidrome.org>
As documented in the OCI Image Format,
org.opencontainers.image.source[1] identifies an image's source
repository. This is purely for documentation purposes. It does however
help tools such as Renovate[2] to find the changelogs when a new
Navidrome version is released. The changelogs would then be included in
the PR Renovate creates.
[1]: 5325ec4885/annotations.md (L24)
[2]: https://docs.renovatebot.com/modules/datasource/docker/#description
Signed-off-by: Dany Marcoux <git@dmarcoux.com>
* fix(insights): show error whn reading library counts
Signed-off-by: Deluan <deluan@navidrome.org>
* fix(insights): wait 30 mins before send first report
Signed-off-by: Deluan <deluan@navidrome.org>
* fix(insights): send number of active players, grouped by client type
Signed-off-by: Deluan <deluan@navidrome.org>
* fix(insights): disable reports when running in dev mode
Signed-off-by: Deluan <deluan@navidrome.org>
* fix(insights): add Dockerfile to the docker build, to avoid `vcs.modified=true`
Signed-off-by: Deluan <deluan@navidrome.org>
* fix(insights): add more linux fs types
Signed-off-by: Deluan <deluan@navidrome.org>
* fix(insights): need admin permissions to retrieve library counts
Signed-off-by: Deluan <deluan@navidrome.org>
* fix(insights): dev flag to disable player insights
Signed-off-by: Deluan <deluan@navidrome.org>
---------
Signed-off-by: Deluan <deluan@navidrome.org>
* Completed the translation of zh-Hant and zh-Hans
* Update translation terms in zh-Hans and zh-Hant files
---------
Co-authored-by: Deluan <deluan@navidrome.org>
* feat(insights): initial code (WIP)
* feat(insights): add more info
* feat(insights): add fs info
* feat(insights): export insights.Data
Signed-off-by: Deluan <deluan@navidrome.org>
* feat(insights): more config info
Signed-off-by: Deluan <deluan@navidrome.org>
* refactor(insights): move data struct to its own package
Signed-off-by: Deluan <deluan@navidrome.org>
* refactor(insights): omit some attrs if empty
Signed-off-by: Deluan <deluan@navidrome.org>
* feat(insights): send insights to server, add option to disable
Signed-off-by: Deluan <deluan@navidrome.org>
* fix(insights): remove info about anonymous login
Signed-off-by: Deluan <deluan@navidrome.org>
* chore(insights): fix lint
Signed-off-by: Deluan <deluan@navidrome.org>
* fix(insights): disable collector if EnableExternalServices is false
Signed-off-by: Deluan <deluan@navidrome.org>
* fix(insights): fix type casting for 32bit platforms
Signed-off-by: Deluan <deluan@navidrome.org>
* fix(insights): remove EnableExternalServices from the collection (as it will always be false)
Signed-off-by: Deluan <deluan@navidrome.org>
* chore(insights): fix lint
Signed-off-by: Deluan <deluan@navidrome.org>
* refactor(insights): rename function for consistency
Signed-off-by: Deluan <deluan@navidrome.org>
* feat(insights): log the data sent to the collector server
Signed-off-by: Deluan <deluan@navidrome.org>
* feat(insights): add last collection timestamp to the "about" dialog.
Also add opt-out info to the SignUp form
Signed-off-by: Deluan <deluan@navidrome.org>
* feat(insights): only sends the initial data collection after an admin user is created
Signed-off-by: Deluan <deluan@navidrome.org>
* feat(insights): remove dangling comment
Signed-off-by: Deluan <deluan@navidrome.org>
* feat(insights): Translate insights messages
Signed-off-by: Deluan <deluan@navidrome.org>
* fix(insights): reporting empty library
Signed-off-by: Deluan <deluan@navidrome.org>
* refactor: move URL to consts.js
Signed-off-by: Deluan <deluan@navidrome.org>
---------
Signed-off-by: Deluan <deluan@navidrome.org>
* fix(artwork): get the first image from vorbis comments, not the last. fixes#3254
This uses a fork for now.
* fix(artwork): prioritize getting embedded types that are listed as "front" covers
* fix: cleanup
* feat(build): add a make target to build a msi installer locally
* Testing wrapping the executable in cmd
* build(ci): build msis in parallel
* feat(server): add LogFile config option
* Revert "Testing wrapping the executable in cmd"
This reverts commit be29592254.
* Adding --log-file for service executable
* feat(ini): wip
* feat(ini): parse nested ini section
* fix(conf): fix fatal error messages
* Now navidrome supports INI, we can use the built-in msi ini system
and not require the VBScript to convert it into toml
* File needs to be called .ini to be parsed as an INI and correct filename
needs to be passed to the service
* fix(msi): build msi locally
* fix(msi): pipeline
* fix(msi): pipeline
* fix(msi): pipeline
* fix(msi): pipeline
* fix(msi): pipeline
* fix(msi): Makefile
* fix(msi): more clean up
* fix(log): convert LF to CRLF on Windows
* fix(msi): config filename should be case-insensitive
* fix(msi): make it a little more idiomatic
* Including the latest windows release of ffmpeg into the msi
as built by https://www.gyan.dev/ffmpeg/builds/ (linked
to on the official ffmpeg source)
* This should version independent
* Need bash expansion for the * to work
* This will run twice, once for x86 and once for x64, I'll make it cache
the executable for now as it'll be quicker
* Silencing wget
* Add ffmpeg path to the config so Navidrome knows where to find it
* refactor: download ffmpeg from our repository
* When going back from the "Are you ready to install?" it should go back to the
Settings dialogue that you just came from
* fix: comments
---------
Co-authored-by: Deluan <deluan@navidrome.org>
* build: new pipeline, new way to cross-compile and build docker images locally. (#3383)
* build: use alternative repositories
* build: fix
* build: validate taglib downloads
* build: control concurrency
* build: validate xx version
* build: remove taglib download validation as the version can be changed as an argument.
* [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>
* First version/rough layout of the required wix to build an MSI that embeds everything
* Don't need revision number
* produced exe from existing build process is navidrome not Navidrome
* Adding Kardianos wrapper around Cobra so the callbacks are handled
automatically (this is basically only for windows)
* Adding pointless check to shut up lint for now
* make format
* Revert disabling npm tidy
* Using Kardianos always will result in the application hanging so it
needs only be wrapped to handle the callbacks if it's being used in
the service context, otherwise use cobra directly
* Copying in service installation etc from https://github.com/navidrome/navidrome/pull/2295
* Under Linux this installs a user service (I don't think this is
correct, but lets get this working first). User units/services
cannot depends on system units, so previously this bombed out
with Exit Code 5.
* Under Windows we can install both the x86 and x64 builds, they
will install to different folders, but previously they would
overwrite the service as they were both called Navidrome. Now,
it will install 2 services. This will still be weird/broken as
they will attempt to listen on the same port, however uninstalling
the "wrong" arch will not cause the "right" one to be partially
uninstalled anymore
* Reverting changes to the context as they don't really seem necessary anyway
* Need to consistently name the service
* Fixing broken context
* The included files should be removed when the app is uninstalled
* Reverting back to the original context here, I don't think
it makes any difference to running under kardianos
* Let's see what we have immediately available
* OK, the build takes ages so let's just try and do the whole thing in one go, maybe we'll get lucky
* Need -r on directory copy, plus we'll probably need to install wixl
* No sudo cmd, so I assume this runs as root
* WORKSPACE!
* Moving the version to be a single variable, we'll probably be able to pull it from the github tag or whatever
* Might as well put the msi in the right folder, it's tidier
* Writing the version number into the msi, from the output of goreleaser
* Using jq to parse the goreleaser metadata, so need to install it
* MSI only supports numerical version numbers, so I'll make the "snapshot" version .1 minor patch greater
* -r or --raw (on newer versions) means we don't get the "" around the value
* Running as a user service I think makes limited sense for this
* Will now ask for configuration settings during install.
MSI/WiX only supports writing out INI files, Toml is almost
INI compatable, except that the INI needs to write out a section
first, so we need to have a script to strip that off.
We are forced to display a License.rtf file by the UI so I think
the build process should probably rename the default licence file
and that will suffice.
Uninstalling works cleanly, howvever upgrades seem to leave the old
version installed in "programs and features" currently.
Adding the UI has introduced a requirement for WiX 0.103
* Updating the build to include --ext ui for the new config ui
* Configuration dialog should not display for upgrades as the config file
is already written
* Making description consistent with the systemd service and making
the build process produce the required License.rtf
* Fixing " non-constant format string in call to fmt.Errorf (govet)"
* Its a string, not an int; read better.
* Wixl 103 is required for --ext ui, so we need 24.04
* OK this is still installing Wix 0.101, maybe it all needs to be 24.04?
* Switching the builds back to ubuntu-latest (22.04 at current)
as it runs on a custom container, it's actually debian anyway
Moving msi build into its own job so it can run on 24.04 so
we have access to wixl 0.103 for --ext ui support
* Forcing build
* Whitespace fix
* Adding sudo I guess
* Gotta checkout as well
* Adding debugging for when there's soemthing wrong with the paths
* Adding more ls to see if the output has worked
* The msi's are in subdirs
* Actually they're in the ./wix directory
* Still can't find these msi's?
* I think that was being treated literally previously
* No idea why this isn't working, give it a relative path instead?
* Making explicit on the dialogue that the configuration file will be
where the installation dir is
* The lint keeps failing and it's just getting in the way so I'll
turn this off for now and we'll edit out this commit from the merge
* Cutting more out of the build to get more stuff out of the way
* Need to increase the width to fit the text in
* Calling everything License.rtf, presumably one of them is correct
* I am pretty sure the License.rtf loading is broken under Wixl; so
let's just bypass the EULA from the UI which is a nicer experience
for the users anyway
* This needs to be after WelcomeDlg now the Eula isn't displayed
* You're supposed to be able to use <WixVariable> to override the
location that the bmp's are loaded from, I can't get this to work
under wixl so I'm guessing given that the ui extension is new, it
hasn't been implemented with that in mind. So we'll hack it by
overwriting the files installed with the package.
* We should make this less brittle so when wixl is updated it still works
* Re-enabling the lint and tests etc
* Improving the scaling quality and removing borders from images to
tidy them up a tad
* Pretty sure this isn't necessary as MY_PROPERTY will always be false
* Without publishing this event, we can't continue to the next dialogue
however I think we should be able to get away without the property
* Refactoring out the duplication so we only have one service
defined and we can run that either way
* Pushing the Interactive check into the root commmand? Feels like it
is probably getting closer to the right place at least
* go tidy
* OK this didn't work under windows, I'm guessing it's because
it's lacking all the metadata about the service it needs to
report back to Windows on.
* We need to run service execute now so that the windows
service will behave (hopefully)!
* Lint
* go tidy
* Renaming service to "navidrome" rather than "Navidrome" as this
is the filename that systemd writes and it's unusual to have
capital letters in service names under Linux.
Switching to use service execute for Linux to mirror Windows
* Need to provide the arguments to append
* Without passing the context around, the DB isn't closed gracefully
so we end up with with .db-shm and .db-wal files for recovery
* We should log fatal rather than outputting directly to stdout
* go tidy
* refactor: small nitpicks
* fix: terminate service gracefully
---------
Co-authored-by: Deluan Quintão <deluan@navidrome.org>
* refactor(server): replace RangeByChunks with Go 1.23 iterators
* chore: fix comments re: SQLITE_MAX_VARIABLE_NUMBER
* test: improve playqueue test
* refactor(server): don't create a new iterator when it is not required
* fix(ui): update sort mapping for title in mediafile repository
* fix(ui): create sort mapping for username in share repository
* fix(ui): create sort mapping for owner_name in playlist repository
* fix(ui): create sort mapping for username in player repository
* fix(ui): remove sort mapping for track number in mediafile repository
* chore: add todo to change user_name
* fix(scanner): use sort_artist_name when the config PreferSortTags is true - #3285
* revert unwanted modifications
* refactor(server): use cmp.Or to simplify nested ifs
---------
Co-authored-by: Deluan <deluan@navidrome.org>
* [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
* 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>
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>
* 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
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.
Closes#1032
* feat(album_repository.go): add kodi-style album playcount option - #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>
* 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.
Closes#1737
* wrapping playlist comment in a <Collapse> element
* Extract common collapsible logic into a component
---------
Co-authored-by: Deluan <deluan@navidrome.org>
* bug(core/playback/mpv): jukebox mode under windows - #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 - #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>
* 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>
Closes#1417
A smart playlist can use the playlist id for filtering. This can be
used to create combined playlists or to filter multiple playlists.
To filter by a playlist id, a subquery is created that will match the
media ids with the playlists within the playlist_tracks table.
Signed-off-by: flyingOwl <ofenfisch@googlemail.com>
* 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 87df7f6df7.
* 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 372eb4b0ae.
* My OCD made me do it :P
---------
Co-authored-by: Deluan Quintão <deluan@navidrome.org>
Beep isn't needed anymore since we rely on MPV instead.
The changes to `go.mod` and `go.sum` were done with:
```
go get github.com/faiface/beep@none
go mod tidy
```
Signed-off-by: Dany Marcoux <git@dmarcoux.com>
* Start migration to dbx package
* Fix annotations and bookmarks bindings
* Fix tests
* Fix more tests
* Remove remaining references to beego/orm
* Add PostScanner/PostMapper interfaces
* Fix importing SmartPlaylists
* Renaming
* More renaming
* Fix artist DB mapping
* Fix playlist updates
* Remove bookmarks at the end of the test
* Remove remaining `orm` struct tags
* Fix user timestamps DB access
* Fix smart playlist evaluated_at DB access
* Fix search3
* Optimize pagination, removing offset
* For search, don't add `where` clause for empty queries
* Revert "Replace `COUNT(DISTINCT primary_key)` with `COUNT(*)`"
Genres are required as part of the count queries, so filter by genres work
* Optimize search3 query, using order by id if it is a "" query.
Also fix the optimizePagination query logic
* Allow offset optimizer threshold to be configured
* Update mapping.go
fallback in the case there's no Date tagged but Original Date or Release Date are tagged
* Add tests
---------
Co-authored-by: Deluan <deluan@navidrome.org>
* Update mapping.go
CreatedAt = BirthTime
* Update metadata.go
Add BirthTime() function
* Update spread_fs.go
Replacing djherbis/atime package with djherbis/times, as times includes the functionality of atime
* Update go.mod
remove djherbis/atime, add djherbis/times
* Update mapping.go
time package not used anymore
* Update go.sum
removed djherbis/atime, added djherbis/times
* Update spread_fs.go
revert to previous, cannot get rid of /atime after all since it's a dependency of /fscache
* Update go.mod
djherbis/times 1.6.0 now released
* Update go.sum
new sums
* Update metadata.go
Inverted if statement, more readable
* Update go.mod
format fix
* Update go.sum
format fix
* Update go.sum
format fix
* Update go.sum
format fix
* Update metadata.go
variable name times -> fileProperties
check for errors
* Update metadata.go
reverse order of error check
* Update metadata.go
typo
* Update metadata.go
https://github.com/navidrome/navidrome/pull/2553#issuecomment-1787967615
* wip: API endpoint for creating playlists from m3u files
* wip: get user id from context
* temporarily disable failing test
* custom logic for playlist route to accomodate m3u content type
* incorporate playlist parsing into existing logic in core
* re-enable test
* fix locally failing test
* Address requested changes.
* Improve ImportFile tests.
* Remove ownerID as a parameter of ImportM3U.
* Write tests for ImportM3U.
* Separate ImportM3U test into two.
* Test OwnerID and playlist Name.
---------
Co-authored-by: Sam Watson <SwatsonCodes@users.noreply.github.com>
Co-authored-by: caiocotts <caio@cotts.com.br>
* Adding cache directory to ignore-list
* Adding jukebox-related config options
* Adding DevEnableJukebox config option pls. dummy server
* Adding types and routers
* Now without panic
* First draft on parsing the action
* Some cleanups
* Adding playback server
* Verify audio device configuration
* Adding debug-build target to have full symbol support
* Adding beep sound library pls some example code. Not working yet
* Play a fixed mp3 on any interface access for testing purposes
* Put action code into separate file, adding stringer, more debug output, prepare structs, validation
* Put action parameter parser code where it belongs
* Have a single Action transporting all information
* User fmt.Errorf for error-generation
* Adding wide playback interface
* Use action map for parsing, stringer instead switch stmt.
* Use but only one switch case and direct dispatch, refactoring
* Add error handling and pushing to client
* send decent errormessage, no internal server error
* Adding playback devices slice and load it from config
* Combine config-verification and structure init
* Return user-specific device
* Separate playback server from device
* Use dataStore to retrieve mediafile by id
* WIP: Playlist and start/stop handling. Doing start/stop the hard way as of now
* WIP: set, start and stop work on one single song. More to come
* Dont need to wait for the end
* Merge jukebox_action.go into jukebox.go
* Remove getParameterAsInt64(). Use existing requiredParamInt() instead
* Dont need to call newFailure() explicitly
* Remove int64, use int instead.
* Add and set action now accept multiple ids
* Kickout copy of childFromMediaFile(). It is not needed here.
* Refactoring devices and playbackServer
* Turn (internal) playback.DeviceStatus into subsonic JukeboxStatus when rendering output. Indexes int64 -> int
* Now we have a position and playing status
* Switching gain to float32, xs:float is defined as 32 bit. Fixing nasty copy/pointer bug
* Now with volume control
* Start working the queue
* Remove user from device interface
* Rename function GetDevice -> GetDeviceForUser to make intention clearer
* Have a nice stringer for the queue
* User Prepared boolean for now to allow pause/unpause
* Skipping works, but without offsets
* Make ChildFromMediaFile public to be used in jukebox get() implementation
* Return position in seconds and implement offset-skip in seconds
* Default offset to 0
* Adding a simple setGain implementation
* Prepare for transcoding AAC
* WIP: transcode to WAV to use beeps wav decoder. Not done yet.
* WIP: out of sheer desparation: convert to MP3 (which works) rather than WAV to troubleshoot issue.
* Use FLAC as intermediate format to play Apple AAC
* A bit of cleanup
* Catching the end-of-stream event for further reactions
* Have a trackSwitching goroutine waiting on channel when track ends
* Move decoder code into own file. Restructure code a bit
* Now with going on to play the next song in the playlist
* Adding shuffle feature
* Implementing remove action
* Cleanup code
* Remove templates for ffmpeg mp3 generation. Not needed anymore.
* Adding some documentation
* Check whether offset into track is in range. Fixing potential remove track bug. Documentation
* Make golangci-lint happy: handling return values
* Adding test suite and example dummy for playback package
* Adding some basic queue tests
* Only use Jukebox.Enabled config option
* Adding stream closing handling
* Pass context.Context to all PlaybackDevice methods
* Remove unneeded function
* Correct spelling
* Reduce visibility of ChildFromMediaFile
* Decomplicate action-parsing
* Adding simple tempfile-based AAC->FLAC transcoding. No parallel reading and writing yet.
* Try to optimize pipe-writing, tempfile-handling and reading. Not done yet.
* Do a synchronous copy of the tempfile. Racecondition detected
* More debugging statements and fixing the play/pause bug. More work needed
* Start the trackSwitcher() with each device once. Return JSON position even if its 0. More debug-output
* Moving all track-handling code into own module
* Fix typo. Do not pass ctx around when not applicable
* WIP: More refactoring, debugging output
* Fix nil pointer
* Repairing MP3 playback by pinning indirect dependencies: hajimehoshi/go-mp3 and hajimehoshi/oto
* Do not forget to cleanup after a skip action
* Make resync with master easy
* Adding missing mocks
* Adding missing error-handling found by linter
* Updating github.com/hajimehoshi/oto
* Removing duplicate function
* Move BEEP-related code into own package
* Juggle beep-related code around as preparation for interface access
* More refactoring for interface separation
* Gather CloseDevice() behind Track interface.
* Adding skeleton, draft audio-interface using mpv.io
* Adding majority of interface commands using messages to mpv socket.
* Adding end-of-stream handling
* MPV: start/stop are working
* postition is given in float in mpv
* Unify Close() and CloseDevice(). Using temp filename for controlling socket
* Wait until control-socket shows up. Cleanup socket in Close()
* Use canceable command. Rename to Executor
* Skipping tracks works now
* Now with actually setting the position
* Fix regain
* Add missing error-handling found by linter
* Adding retry mode on time-pos property getter
* Remove unneeded code on queue
* Putting build-tag beep onto beep files
* Remove deprecated call to rand.Seed()
"As of Go 1.20 there is no reason to call Seed with a random value. Programs that call Seed with a known value to get a specific sequence of results should use New(NewSource(seed)) to obtain a local random generator."
* Using int32 to conform to Subsonic API spec
* Fix merge error
* Minor style changes
* Get username from context
---------
Co-authored-by: Deluan <deluan@navidrome.org>
* Add support for lyrics tag `unsynced_lyrics`
* Update metadata.go
* Update metadata.go
resolve lint issue
* format the code with `goimports`
format the code with `goimports`
* 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
* Set all clients to dev_download for make get-music
* Use multiple TranscodingCache instances in tests
This fixes flaky tests. The issue is that the TranscodingCache object
was being reused in tests from media_stream_Internal_test.go and
media_stream_test.go. If tests from the former was run first, the cache
would be filled up, so that when running tests from the latter, the `NON
seekable` test would fail.
* Allow configuring cache folder
This commit introduces a new configuration option to configure the cache
folder. This allows the cache to be in a separate folder such as
/var/cache/navidrome on Linux distributions.
* Fix tests
* Removed unused test setup code
---------
Co-authored-by: Deluan <deluan@deluan.com>
Co-authored-by: Deluan <deluan@navidrome.org>
Changes the default transcoding commands to only use the first audio
stream, instead of the first arbitrary stream.
Co-authored-by: Deluan Quintão <deluan@navidrome.org>
* fix(persistence): Update play_date on scrobble only when newer - #2262
Signed-off-by: Xidorn Quan <me@upsuper.org>
* expand iff
---------
Signed-off-by: Xidorn Quan <me@upsuper.org>
* playlist view: optionally show genre and comment columns
* Remove genre from Playlist columns, as it is not a valid attribute of playlist
Co-authored-by: Deluan <deluan@navidrome.org>
* Create accounts automatically when authenticating from HTTP header
* Disable password check when header auth is enabled
* Formatting
* Password change is valid when no password (old or new) is provided
* Test suite runs with header auth disabled (mock config)
Prevents nil pointer access (panic) while testing password validating logic
* Use a constant prefix for autogenerated passwords (header auth case)
* Add tests
* Add context to log messages
Co-authored-by: Deluan <deluan@navidrome.org>
* feat: Add metrics worker
* refactor: Add todos for useful for metrics methods
* feat: Run MetricsWorker is Prometheus is Enabled
* refactor: Unused low-level variable was removed in metrics
* feat: No worker for metrics, add more
* refactor: Unnecessary todo removed
* refactor: Remove dead unused constant
* Reduce metrics public interface
Co-authored-by: Deluan <deluan@navidrome.org>
* persistence/genre: change Put() to upsert
Absolutely disgusting hack to work around [1]. Try to insert the genre,
but if it conflicts, ignore it and update the genre with the existing
ID.
[1]: https://github.com/navidrome/navidrome/issues/1918.
* scanner: remove cached genre repository
Not needed anytmore. And remember:
"Many Small Queries Are Efficient In SQLite" [1].
[1]: https://www.sqlite.org/np1queryprob.html
* Revert "scanner: remove cached genre repository"
This reverts commit c5d900aa43.
* Use squirrel to build SQL, to reduce risk of SQL injection
Co-authored-by: Deluan <deluan@navidrome.org>
* 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>
* 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
* 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>
* Don't cache transcoded files if the request was cancelled (or there was a transcoding error)
* Add context to logs
* Simplify Wait error handling
* Fix flaky test
* Change log level for "populating cache" error message
* Small cleanups
* Add global downsampling feature
* Default to Opus & consider player transcoder
* Add a test case for DefaultDownsamplingFormat
Co-authored-by: Deluan <deluan@navidrome.org>
* fix(taglib): Fix misleading error message on unreadable media - #1576
Signed-off-by: reo <reo_999@proton.me>
* fix(taglib): Add unit test and exclude scan for only unreadable file - #1576
Signed-off-by: reo <reo_999@proton.me>
* fix(taglib): Add unit test and exclude scan for only unreadable file - #1576
Signed-off-by: reo <reo_999@proton.me>
* fix(taglib): Add unit test and exclude scan for only unreadable file - #1576
Signed-off-by: reo <reo_999@proton.me>
* fix(taglib): Add unit test and exclude scan for only unreadable file - #1576
Signed-off-by: reo <reo_999@proton.me>
* fix(taglib): Add unit test and exclude scan for only unreadable file - #1576
Signed-off-by: reo <reo_999@proton.me>
* Fix test and simplify code a bit
We don't need to expose the type of error: `taglib.Parse()` always return nil
* Fix comment
Signed-off-by: reo <reo_999@proton.me>
Co-authored-by: Deluan <deluan@navidrome.org>
* Corrected some Simplified Chinese translations
* Fix wrong expression symbols in Traditional Chinese translation
* Modify punctuation to Chinese punctuation in Chinese translation
Add spaces between Chinese and English words in Chinese translation
* Added missing Traditional Chinese translation
* Improve some Chinese translations
* Remove redundant punctuation in Traditional Chinese translation
* Adjust the order of fields in `zh-Hans` and `zh-Hant` to be consistent with `en`
* Re-add tpbnick's Nord theme
* Run Prettier formatter on Nord theme
* Update themes index
* Fix button margins
* Modernise the look of switches
* Adjust margins and padding
* Fix sidebar's background colour not applying to all of sidebar when scrolling down
* Adjust App Bar box shadow
* Adjust roundedness
* Adjust shadows
* Adjust outlined inputs
* Add transitions to items in sidebar when hovered / losing hover
* Adjust border radiuses
* Adjust pagination buttons
* Add big play button from Spotify theme
* Remove playlist background gradient
* Adjust colour of MuiChip elelments
* Adjust table borders
* Remove duplicate MuiTableRow key
* Attempt to make switches in both the playlist section and settings section visable against background & the toggle. Not ideal.
* Style the player
* Format CSS to Prettier standards
* Fix mobile player style
* Make play button in album grid view blue
* Make main view background lighter
* Allow ArtistExternalLink icons to be styled
* Allow AlbumExternalLink icons to be styled
* Standardize external links' classes to kebab-case
Co-authored-by: Deluan <deluan@navidrome.org>
* add new translations
* translation: fix improper full width character usage in zh-Hans translation
Full width % messed up with format strings.
* translation: fix two machine translations in zh-Hans
* translation: fix one mistranslation in zh-Hans
* translation: fix format in zh-Hans
* translation: fix format and two translations in zh-Hans
* translation: fix format in zh-Hans
* feat: Add listenbrainz base url configuration
- ListenBrainz.BaseURL config value
* Don't need to store baseUrl
* Use `url.JoinPath` to concatenate url paths
* Replace url.JoinPath (Go 1.19 only) with custom function
Co-authored-by: Deluan <deluan@navidrome.org>
* None is deprecated and will fallback to Lax in the future.
* Using Strict is future proof and provides additional CSR protection
Signed-off-by: Manuel Kroeber <manuel.kroeber@gmail.com>
Signed-off-by: Manuel Kroeber <manuel.kroeber@gmail.com>
* fix: make signaler exit on cancel
`break` is incorrect here, as it just breaks out of the select.
`return` to exit the function instead.
Fixes#1636.
Signed-off-by: Ian Kerins <ianskerins@gmail.com>
* fix: exit non-zero on fatal error
Signed-off-by: Ian Kerins <ianskerins@gmail.com>
* Adding 'x-content-duratin' and 'x-total-count' to CORS exposed headers
* Moving cors setup to middlewares.go
* adding x-nd-authorization to exposed headers
* Refactor session_keys to its own package
* Adjust play_tracker
- Don't send external NowPlaying/Scrobble for tracks with unknown artist
- Continue to the next agent on error
* Implement ListenBrainz Agent and Auth Router
* Implement frontend for ListenBrainz linking
* Update listenBrainzRequest
- Don't marshal Player to json
- Rename Track to Title
* Return ErrRetryLater on ListenBrainz server errors
* Add tests for listenBrainzAgent
* Add tests for ListenBrainz Client
* Adjust ListenBrainzTokenDialog to handle errors better
* Refactor listenbrainz.formatListen and listenBrainzRequest structs
* Refactor agent auth_routers
* Refactor session_keys to agents package
* Add test for listenBrainzResponse
* Add tests for ListenBrainz auth_router
* Update ListenBrainzTokenDialog and auth_router
* Adjust player scrobble toggle
* Extract version from directory name if .git dir is missing
* Avoid using shell
* Remove .gitinfo build from pipeline
* Fix git-detecting rule to be robust in presence of setup-git
* Add function 'isSynced' that identifies if lyrics are synced or not and add tests for the same
* implement 'getLyrics' which returns lyrics if they exist
Signed-off-by: Dheeraj Lalwani <lalwanidheeraj1234@gmail.com>
* remove timestamps frorom the the lyrics if they are synced, fix filters & clean up code
Signed-off-by: Dheeraj Lalwani <lalwanidheeraj1234@gmail.com>
* add snapshot tests for the 'Lyrics' response & add some clean up
Signed-off-by: Dheeraj Lalwani <lalwanidheeraj1234@gmail.com>
* add tests for 'GetLyrics' function
Signed-off-by: Dheeraj Lalwani <lalwanidheeraj1234@gmail.com>
* update the snapshot test & the test for 'GetLyrics' function
Signed-off-by: Dheeraj Lalwani <lalwanidheeraj1234@gmail.com>
* Seperate mobile desktop components
* Fix err
* Rename classes and fix some styles
* Add lastFM button and remove console log
* Add Mbiz Icon
* render bio as dangerouslySetInnerHTML and remove unused css classes
* Add Fav and Stars
* Remove unstandardised class selector
* Remove ext link from m view
* Fix naming and simplify rounded styling
* Refactor ArtistShow:
- Extracted DesktopArtistDetails to its own file
- Removed album count as it was incorrect, it is not considering compilations
- Show bio and image from Native API, if it is available, before calling `getArtistInfo`
Co-authored-by: Deluan <deluan@navidrome.org>
* Rename manifest.json to manifest.webmanifest
browser consoles keep complaining that the manifest doesn't have the `.webmanifest` extension.
* FIx manifest.webmanifest references
Co-authored-by: Deluan <deluan@navidrome.org>
* Check goimports in the pipeline
* Check goimports in the pipeline
* Check goimports in the pipeline
* go mod tidy
* wip
* wip
* Fix goimports and go:build tags
* Run golangci-lint before goimports
* Use local copy of workbox service worker scripts
* Refactor workbox integration:
- Only add prod js, without maps. Reduces the size from 170k to 24k
- Removed it from build. As it is small now, we can add it to source, and have a script to just update it whenever it is required
- Fixed relative paths in navidrome-service-worker.js, should now work with BaseUrl != ''
Co-authored-by: Deluan <deluan@navidrome.org>
* Configure fetching from API and route
* pretty
* Remove errors
* Remove errors
* Remove errors
* Complete page for Desktop view
* Fix error
* Add xs Artist page
* Remove unused import
* Add styles for theme
* Change route path
* Remove artId useEffect array
* Remove array
* Fix cover load err
* Add redirect on err
* Remove route
* What's in a name? consistency :)
* Fix err
* Fix UI changes
* Fetch album from resource
* Renaming done
* Review changes
* Some touch-up
* Small refactor, to make naming and structure more consistent with AlbumShow
* Make artist's album list similar to original implementation
* Reuse AlbumGridView, to avoid duplication
* Add feature flag to enable new Artist Page, default false
* Better biography styling. Small refactorings,
* Don't encode quotes and other symbols
* Moved AlbumShow to correct folder
Co-authored-by: Deluan <deluan@navidrome.org>
Syntax is Ant-style Globs, with support for '**' (any subfolder). Default: '.:**' (or '.;**' in Windows`, meaning all folders and subfolders under `MusicFolder`
* Show playlists in sidebar menu
* Fix menu
* Refresh playlist submenu when adding new playlist
* Group shared playlists below user's playlists
* Fix text overflow in menu options
* Add button in playlist menu to go to Playlists list
* Add config option `DevSidebarPlaylists` to enable this feature (default false)
* Added back button
* Added back button
* Added back button
* Fixed Album size overflow
* Fixed Album size overflow
* Fixed album size overflowing
* Fixed album size overflowing
* Fixed album size overflowing
* Fixed album size overflow on small screen
* Changes reverted in PlayerEdit.js
* prettier formatting issue resolved
Co-authored-by: Deluan <deluan@navidrome.org>
* Don't include updatedAt field when fetching album art placeholder. This will allow browers to cache the place holder
* Apply resizing to placeholder image
* Fix issues discovered by CI linter and prettier
* Updates from PR review
* Use wchar_t for tagLib filenames on Windows
* Make TagLib default extractor for all platforms.
* Organize imports
Co-authored-by: Deluan <deluan@navidrome.org>
* Disable mobile player cover animation when EnableCoverAnimation is set to false. Also increase cover art size and remove rounded borders.
* Display song album and year in mobile player view
* Remove default singer element from mobile player and reduce vertical white space
* Only add song year if it exists
* Add song year to desktop player when present
* Increase non-animated cover size to 85% and set a limit on the width of 600px.
* Explain what what the styles impact
* Remove unused style for songArtist
* Apply prettier
* Adjust player styles to handle nonsquare album art better. Should probably push this upstream too
* Also fix desktop player's handling of non square cover art.
* added a dependency npm was complaining about
added playlist to album actions
* removed chokidar dependency
Co-authored-by: Skrtansh Rajput <srajput@alienvault.com>
* Make authentication part of the server, so it can be reused outside the Native API
This commit has broken tests after a rebase
* Serve frontend assets from `server`, and not from Native API
* Change Native API URL
* Fix auth tests
* Refactor server authentication
* Simplify authProvider, now subsonic token+salt comes from the server
* Don't send JWT token to UI when authenticated via Request Header
* Enable ReverseProxyWhitelist to be read from environment
* Call Last.FM's getInfo again without mbid when artist is not found
* Call Last.FM's getSimilar again without mbid when artist is not found
* Call Last.FM's getTopTracks again without mbid when artist is not found
* Upgrade to CRA 4.0.3
* Try to fix tests. No lucky
* Fix new ESLint errors
* Fix JS tests and remove unwanted dependency. (#1106)
* Fix tests
* Fix lint
* Remove React v16 workaround (fixed in v17)
* Force eslint to break on warnings
* Lint now needs to be called explicitly in the pipeline
Co-authored-by: Yash Jipkate <34203227+YashJipkate@users.noreply.github.com>
* Swedish translation
* Updated and renamed to sv.json
Added further lines/translations from the english.json and corrected some of the previous translations
* Update sv.json
* Update sv.json
Ok now i'm done! :P
* Show more descriptive success messages for User actions
* Check username uniqueness when creating/updating User
* Adjust translations
* Add tests for `validateUsernameUnique()`
Co-authored-by: Deluan <deluan@navidrome.org>
See https://pkg.go.dev/github.com/robfig/cron#hdr-CRON_Expression_Format for expression syntax.
`ScanInterval` will still work for the time being. The only situation it does not work is when you want to disable periodic scanning by setting `ScanInterval=0`. If you want to disable it, please set `ScanSchedule=""`
Closes#1085
* BPM metadata enhancement
Related to #1036.
Adds BPM to the stored metadata about MediaFiles.
Displays BPM in the following locations:
- Listing songs in the song list (desktop, sortable)
- Listing songs in playlists (desktop, sortable)
- Listing songs in albums (desktop)
- Expanding song details
When listing, shows a blank field if no BPM is present. When showing song details, shows a question mark.
Updates test MP3 file to have BPM tag. Updated test to ensure tag is read correctly.
Updated localization files. Most languages just use "BPM" as discovered during research on Wikipedia. However, a couple use some different nomenclature. Spanish uses PPM and Japanese uses M.M.
* Enhances support for BPM metadata extraction
- Supports reading floating point BPM (still storing it as an integer) and FFmpeg as the extractor
- Replaces existing .ogg test file with one that shouldn't fail randomly
- Adds supporting tests for both FFmpeg and TagLib
* Addresses various issues with PR #1087.
- Adds index for BPM. Removes drop column as it's not supported by SQLite (duh).
- Removes localizations for BPM as those will be done in POEditor.
- Moves BPM before Comment in Song Details and removes BPM altogether if it's empty.
- Omits empty BPM in JSON responses, eliminating need for FunctionField.
- Fixes copy/paste error in ffmpeg_test.
Imported redacting code from https://github.com/whuang8/redactrus (thanks William Huang)
Didn't use it as a dependency as it was too small and we want to keep dependencies at a minimum
* Handle subdirectories without rx permission correctly
Allow ogg files w/o metadata, having taglib behave more like ffmpeg
* Fix test for walk_dir_tree, fix full reading of files in permission-
constrained directories, allow directories with leading ellipses
* Sorted directory traversal is preferred, and cleanup tests
* Small refactoring to clean-up `loadDir` function and to remove some "warnings" from IntelliJ
Co-authored-by: Deluan <deluan@navidrome.org>
This gives more space for the song and artist names in the player
* fix min-width of AlbumDetails
* Fix song play time display
* Song duration display fix#2
* Removed important
* Resolve conflicts
* Update Player.js
* Change breakdown and hide volume
Co-authored-by: Deluan <deluan@navidrome.org>
* Add support for multiple playlists
* Fix lint
* Remove console log comment
* Disable 'check' when loading
* Fix lint
* reset playlists on closeAddToPlaylist
* new playlist: accomodate string type on enter
* Fix lint
* multiple new playlists are added correctly
* use makestyle()
* Add tests
* Fix lint
* refactored some styles in jinkieplayer
* fix: refactored some styles in jinkie player and removed br tag - #865
* fix: refactored some styles in jinkie player and removed br tag - #865
Signed-off-by: armedev <epiratesdev@gmail.com>
* add icons
* add logic to change the icon
* make the active menu bold
* Encapsulate the dynamic icon behaviour into a self-contained component
Co-authored-by: Deluan <deluan@navidrome.org>
* Added Star Rating functionality for Songs
* Added Star Rating functionality for Artists
* Added Star Rating functionality for AlbumListView
* Added Star Rating functionality for AlbumDetails and improved typography for title
* Added functionality to turn on/off Star Rating functionality for Songs
* Added functionality to turn on/off Star Rating functionality for Artists
* Added functionality to turn on/off Star Rating functionality for Albums
* Added enableStarRating to server config
* Resolved the bugs and improved the ratings functionality.
* synced repo and removed duplicate key
* changed the default rating size to small, and changed the color to match the theme.
* Added translations for ratings, and Top Rated tab in side menu.
* Changed rating translation to topRated in albumLists, and added has_rating filter to topRated.
* Added empty stars icon to RatingField.
* Added sortable=false in AlbumSongs and added sortByOrder=DESC in all List components.
* Added translations for rating, for artists and albums, and removed the sortByOrder=DESC from SimpleLists.
* added quality info
* fixed formatting
* implemented various suggestions
* npm run prettier
* applied suggestions
* npm run prettier
* corrected lossless formats and other suggestions
* moved losslessformats into consts.js
* added some test
* typo while resolving conflicts
* fetch
* removed a bug causing component (as suggested)
* Update PlayerToolbar.js
* implemented suggestions
* added few more tests
* npm run prettier
* added size
* updated qualityInfo
* implemented suggestions
* added test for when no record is recieved
* Update QualityInfo.js
* fix(ui/src/album): White play button on hover for all themes - #960
* fix(PlayButton) : White play button for light theme - #960
* fix(PlayButton) : White play button for light theme - #960
* bug(AlbumGridView.js) - Album play button defaults to white, can be overridden - #960
Signed-off-by: Shishir <shishir.srik@gmail.com>
* bug(AlbumGridView.js) - Album play button defaults to white, can be overridden - #960
* Reverted package.json and package-lock.json - #960
Signed-off-by: Shishir <shishir.srik@gmail.com>
* Missing lint script added - #960
Signed-off-by: Shishir <shishir.srik@gmail.com>
* Removed color, added className and made record required in PlayButton.propTypes - #960
* added new theme - night
* removed a unused field
* fixed a typo from previous change
* night theme in login window
* changed name
changed the theme name from "Night" to "Extra Dark"
* changed the theme name
* Update index.js
* Rename night.js to extradark.js
* trying something
* formatted
the JS build was failing because I haven't formatted the index.js file with prettier. I got to know about this now.
I think now it will be resolved.
* Fix the Album Details UI to look similar to Song Details UI
* Remove the unused components
* Fix the gap between row and the first field in the details view
* Fix the width of the row of Album Details UI
* [Theme] Allow customising album and player parts
* [Theme] Allow customizing song lists view
* Make spotify-ish more spotify-ish
* Fix responsive issues in spotify-ish
* Spotify-ish login page
* Add back the previous "Spotify-ish" theme as "Green"
Co-authored-by: Deluan <deluan@navidrome.org>
* Added option to enable/disable favorites in Song
* Added option to enable/disable favorites in Artist
* Added option to enable/disable favorites in Albums and Favorites tab in sidebar
* Added option to enable/disable favorites in Player
* Set default value of enableFavourites as true
* Improved the functionality to enable/disable Favorites
* Add `EnableFavourites` config option
Co-authored-by: Deluan <deluan@navidrome.org>
* Added setRating feature to AlbumListView
* Refactored the iconography from ⭐ to ❤️
* Refactored the current component from StarButton to LoveButton
* Refactored all translations from Starred to Loved, and all props from showStar to showLove
* Refactored useToggleStar hook to useToggleLove
* rebased repository from master and removed stray commmits
* Refactored handler name from TOGGLE_STAR to TOGGLE_LOVE in PlayerToolbar.js
* Change "starred" translation to "Favorite"
Co-authored-by: Deluan <deluan@navidrome.org>
* added new component SONGSIMPLELIST for smaller displays
* added new component SONGSIMPLELIST for smaller displays
* added new component SONGSIMPLELIST for smaller displays
* Updated songsimplelist
Removed truncation
* removed garbage code
* refactored some issues of overlapping
* refactored some issues of overlapping
* changed the song ui design
* refactored some bugs in artist display
* refactored some bugs in artist display
* removed garbage dependencies
* removed div bugs
* added all the logic to the component itself
* Make the version number clickable for the SNAPSHOT version while using development docker build
* Update the snapshot version link in to view list of commits since the release
* Create a new component for the link to the version
* Add tests and refactored a bit
Co-authored-by: Deluan <deluan@navidrome.org>
* Auto theme preference added
* Fix lint
* Add and use AUTO from consts
* Add shared custom hook to get current theme
* Moved up 'Auto' choice
* AUTO -> AUTO_THEME_ID & extract useCurrentTheme to file
* Liberalise theme setting
* Add tests
* Use new embed functionality for serving UI assets
* Use new embed functionality for serving resources. Remove dependency on go-bindata
* Remove Go 1.15
This will allow to use 'embed' and 'fs' packages.
This also makes the check for the Go environment when running the
Makefile fail if Golang version isn't 1.16.x
This caused a panic and needs more investigation:
http: superfluous response.WriteHeader call from github.com/go-chi/chi/middleware.Recoverer.func1.1 (recoverer.go:33)
panic: interface conversion: *middleware.compressResponseWriter is not io.ReaderFrom: missing method ReadFrom
-> github.com/go-chi/chi/middleware.(*httpFancyWriter).ReadFrom
-> /Users/deluan/go/pkg/mod/github.com/go-chi/chi@v1.5.2/middleware/wrap_writer.go:135
If files cannot be sorted by disc and track id, try by artist then
title.
One use case is a loose compilation of files with same album, album
artist, and no track numbers. File order was then undetermined, in
practice depended on insertion order in the database.
description:Before opening a new issue, please search to see if an issue already exists for the bug you encountered.
title:"[Bug]: "
labels:["bug","triage"]
#assignees:
# - deluan
body:
- type:markdown
attributes:
value:|
### Thanks for taking the time to fill out this bug report!
- type:checkboxes
id:requirements
attributes:
label:"I confirm that:"
options:
- label:I have searched the existing [open AND closed issues](https://github.com/navidrome/navidrome/issues?q=is%3Aissue) to see if an issue already exists for the bug I've encountered
required:true
- label:I'm using the latest version (your issue may have been fixed already)
required:false
- type:input
id:version
attributes:
label:Version
description:What version of Navidrome are you running? (please try upgrading first, as your issue may have been fixed already).
validations:
required:true
- type:textarea
attributes:
label:Current Behavior
description:A concise description of what you're experiencing.
validations:
required:true
- type:textarea
attributes:
label:Expected Behavior
description:A concise description of what you expected to happen.
validations:
required:true
- type:textarea
attributes:
label:Steps To Reproduce
description:Steps to reproduce the behavior.
placeholder:|
1. In this scenario...
2. With this config...
3. Click (or Execute) '...'
4. See error...
validations:
required:false
- type:textarea
id:env
attributes:
label:Environment
description:|
examples:
- **OS**: Ubuntu 20.04
- **Browser**: Chrome 110.0.5481.177 on Windows 11
- **Client**: DSub 5.5.1
value:|
- OS:
- Browser:
- Client:
render:markdown
- type:dropdown
id:distribution
attributes:
label:How Navidrome is installed?
multiple:false
options:
- Docker
- Binary (from downloads page)
- Package
- Built from sources
validations:
required:true
- type:textarea
id:config
attributes:
label:Configuration
description:Please copy and paste your `navidrome.toml` (and/or `docker-compose.yml`) configuration. This will be automatically formatted into code, so no need for backticks.
render:toml
- type:textarea
id:logs
attributes:
label:Relevant log output
description:Please copy and paste any relevant log output (change your `LogLevel` (`ND_LOGLEVEL`) to debug). This will be automatically formatted into code, so no need for backticks. ([Where I can find the logs?](https://www.navidrome.org/docs/faq/#where-are-the-logs))
render:shell
- type:textarea
attributes:
label:Anything else?
description:|
Links? References? Anything that will give us more context about the issue you are encountering!
Tip: You can attach screenshots by clicking this area to highlight it and then dragging files in.
- type:checkboxes
id:terms
attributes:
label:Code of Conduct
description:By submitting this issue, you agree to follow our [Code of Conduct](https://github.com/navidrome/navidrome/blob/master/CODE_OF_CONDUCT.md).
options:
- label:I agree to follow Navidrome's Code of Conduct
This issue has been automatically locked since there
has not been any recent activity after it was closed.
Please open a new issue for related bugs.
pr-comment:>
This pull request has been automatically locked since there
has not been any recent activity after it was closed.
Please open a new issue for related bugs.
- uses:actions/stale@v10
with:
operations-per-run:999
days-before-issue-stale:180
days-before-pr-stale:180
days-before-issue-close:30
days-before-pr-close:30
stale-issue-message:>
This issue has been automatically marked as stale because it has not had
recent activity. The resources of the Navidrome team are limited, and so we are asking for your help.
If this is a **bug** and you can still reproduce this error on the <code>master</code> branch, please reply with all of the information you have about it in order to keep the issue open.
If this is a **feature request**, and you feel that it is still relevant and valuable, please tell us why.
This issue will automatically be closed in the near future if no further activity occurs. Thank you for all your contributions.
stale-pr-message:This PR has been automatically marked as stale because it has not had
recent activity. The resources of the Navidrome team are limited, and so we are asking for your help.
Please check https://github.com/navidrome/navidrome/blob/master/CONTRIBUTING.md#pull-requests and verify that this code contribution fits with the description. If yes, tell it in a comment.
This PR will automatically be closed in the near future if no further activity occurs. Thank you for all your contributions.
Navidrome is a streaming service which allows you to enjoy your music collection from anywhere. We'd welcome you to contribute to our open source project and make Navidrome even better. There are some basic guidelines which you need to follow if you like to contribute to Navidrome.
- [Asking Support Questions](#asking-support-questions)
- [Code of Conduct](#code-of-conduct)
- [Issues](#issues)
- [Pull Requests](#pull-requests)
## Asking Support Questions
We have an active [discussion forum](https://github.com/navidrome/navidrome/discussions) where users and developers can ask questions. Please don't use the GitHub issue tracker to ask questions.
## Code of Conduct
Please read the following [Code of Conduct](https://github.com/navidrome/navidrome/blob/master/CODE_OF_CONDUCT.md).
## Issues
Found any issue or bug in our codebase? Have a great idea you want to propose or discuss with
the developers? You can help by submitting an [issue](https://github.com/navidrome/navidrome/issues/new/choose)
to the GitHub repository.
**Before opening a new issue, please check if the issue has not been already made by searching
the [issues](https://github.com/navidrome/navidrome/issues)**
## Pull requests
Before submitting a pull request, ensure that you go through the following:
- Open a corresponding issue for the Pull Request, if not existing. The issue can be opened following [these guidelines](#issues)
- Ensure that there is no open or closed Pull Request corresponding to your submission to avoid duplication of effort.
- Setup the [development environment](https://www.navidrome.org/docs/developers/dev-environment/)
- Create a new branch on your forked repo and make the changes in it. Naming conventions for branch are: `<Issue Title>/<Issue Number>`. Example:
```
git checkout -b adding-docs/834 master
```
- The commits should follow a [specific convention](#commit-conventions)
- Ensure that a DCO sign-off for commits is provided via `--signoff` option of git commit
- Provide a link to the issue that will be closed via your Pull request.
### Commit Conventions
Each commit message must adhere to the following format:
```
<type>(scope): <description> - <issue number>
[optional body]
```
This improves the readability of the messages
#### Type
It can be one of the following:
1.**feat**: Addition of a new feature
2.**fix**: Bug fix
3.**sec**: Fixing security issues
4.**docs**: Documentation Changes
5.**style**: Changes to styling
6.**refactor**: Refactoring of code
7.**perf**: Code that affects performance
8.**test**: Updating or improving the current tests
9.**build**: Changes to Build process
10.**revert**: Reverting to a previous commit
11.**chore** : updating grunt tasks etc
If there is a breaking change in your Pull Request, please add `BREAKING CHANGE` in the optional body section
#### Scope
The file or folder where the changes are made. If there are more than one, you can mention any
#### Description
A short description of the issue
#### Issue number
The issue fixed by this Pull Request.
The body is optional. It may contain short description of changes made.
Following all the guidelines an ideal commit will look like:
docker-image:##@Cross_Compilation Build Docker image, tagged as `deluan/navidrome:develop`, override with DOCKER_TAG var. Use IMAGE_PLATFORMS to specify target platforms
@echo $(IMAGE_PLATFORMS)| grep -q "windows"&&echo"ERROR: Windows is not supported for Docker builds"&&exit1||true
@echo $(IMAGE_PLATFORMS)| grep -q "darwin"&&echo"ERROR: macOS is not supported for Docker builds"&&exit1||true
@echo $(IMAGE_PLATFORMS)| grep -q "arm/v5"&&echo"ERROR: Linux ARMv5 is not supported for Docker builds"&&exit1||true
# Navidrome Music Server [](https://twitter.com/intent/tweet?text=Tired%20of%20paying%20for%20music%20subscriptions%2C%20and%20not%20finding%20what%20you%20really%20like%3F%20Roll%20your%20own%20streaming%20service%21&url=https://navidrome.org&via=navidrome)
pruneCmd.Flags().IntVarP(&backupCount,"keep-count","k",-1,"specify the number of backups to keep. 0 remove ALL backups, and negative values mean to use the default from configuration")
pruneCmd.Flags().BoolVarP(&force,"force","f",false,"bypass warning when backup count is zero")
backupRoot.AddCommand(pruneCmd)
restoreCommand.Flags().StringVarP(&restorePath,"backup-file","b","","path of backup database to restore")
rootCmd.PersistentFlags().BoolVarP(&noBanner,"nobanner","n",false,`don't show banner`)
rootCmd.PersistentFlags().String("musicfolder",viper.GetString("musicfolder"),"folder where your music is stored")
rootCmd.PersistentFlags().String("datafolder",viper.GetString("datafolder"),"folder to store application data (DB, cache...), needs write access")
rootCmd.PersistentFlags().String("datafolder",viper.GetString("datafolder"),"folder to store application data (DB), needs write access")
rootCmd.PersistentFlags().String("cachefolder",viper.GetString("cachefolder"),"folder to store cache data (transcoding, images...), needs write access")
rootCmd.PersistentFlags().StringP("loglevel","l",viper.GetString("loglevel"),"log level, possible values: error, info, debug, trace")
rootCmd.PersistentFlags().String("logfile",viper.GetString("logfile"),"log file path, if not set logs will be printed to stderr")
rootCmd.Flags().StringP("address","a",viper.GetString("address"),"IP address to bind to")
rootCmd.Flags().IntP("port","p",viper.GetInt("port"),"HTTP port Navidrome will listen to")
rootCmd.Flags().String("baseurl",viper.GetString("baseurl"),"base URL to configure Navidrome behind a proxy (ex: /music or http://my.server.com)")
rootCmd.Flags().String("tlscert",viper.GetString("tlscert"),"optional path to a TLS cert file (enables HTTPS listening)")
rootCmd.Flags().String("unixsocketperm",viper.GetString("unixsocketperm"),"optional file permission for the unix socket")
rootCmd.Flags().String("tlskey",viper.GetString("tlskey"),"optional path to a TLS key file (enables HTTPS listening)")
rootCmd.Flags().StringP("address","a",viper.GetString("address"),"IP address to bind")
rootCmd.Flags().IntP("port","p",viper.GetInt("port"),"HTTP port Navidrome will use")
rootCmd.Flags().Duration("sessiontimeout",viper.GetDuration("sessiontimeout"),"how long Navidrome will wait before closing web ui idle sessions")
rootCmd.Flags().Duration("scaninterval",viper.GetDuration("scaninterval"),"how frequently to scan for changes in your music library")
rootCmd.Flags().String("baseurl",viper.GetString("baseurl"),"base URL (only the path part) to configure Navidrome behind a proxy (ex: /music)")
rootCmd.Flags().String("uiloginbackgroundurl",viper.GetString("uiloginbackgroundurl"),"URL to a backaground image used in the Login page")
rootCmd.Flags().Bool("enabletranscodingconfig",viper.GetBool("enabletranscodingconfig"),"enables transcoding configuration in the UI")
rootCmd.Flags().String("transcodingcachesize",viper.GetString("transcodingcachesize"),"size of transcoding cache")
rootCmd.Flags().String("imagecachesize",viper.GetString("imagecachesize"),"size of image (art work) cache. set to 0 to disable cache")
rootCmd.Flags().String("albumplaycountmode",viper.GetString("albumplaycountmode"),"how to compute playcount for albums. absolute (default) or normalized")
log.Error(fmt.Sprintf("Invalid %s. Please read format spec at https://pkg.go.dev/github.com/robfig/cron#hdr-CRON_Expression_Format",field),"schedule",schedule,err)
}else{
c.Remove(id)
}
returnschedule,err
}
// AddHook is used to register initialization code that should run as soon as the config is loaded
A couple things to keep in mind with this manifest:
1. This creates a namespace called `navidrome`. Adjust this as needed.
1. This manifest was created on [K3s](https://github.com/k3s-io/k3s), which uses its own storage provisioner called [local-path-provisioner](https://github.com/rancher/local-path-provisioner). Be sure to change the `storageClassName` of the `PersistentVolumeClaim` as needed.
1. The `PersistentVolumeClaim` sets up a 2Gi volume for Navidrome's database. Adjust this as needed.
1. Be sure to change the `image` tag from `ghcr.io/navidrome/navidrome:0.49.3` to whatever the newest version is.
1. This assumes your music is mounted on the host using `hostPath` at `/path/to/your/music/on/the/host`. Adjust this as needed.
1. The `Ingress` is already configured for `cert-manager` to obtain a Let's Encrypt TLS certificate and uses Traefik for routing. Adjust this as needed.
1. The `Ingress` presents the service at `navidrome.${SECRET_INTERNAL_DOMAIN_NAME}`, which needs to already be setup in DNS.
This folder abstracts metadata lookup into "agents". Each agent can be implemented to get as
much info as the external source provides, by using a granular set of interfaces
(see [interfaces](interfaces.go)).
A new agent must comply with these simple implementation rules:
1) Implement the `AgentName()` method. It just returns the name of the agent for logging purposes.
2) Implement one or more of the `*Retriever()` interfaces. That's where the agent's logic resides.
3) Register itself (in its `init()` function).
For an agent to be used it needs to be listed in the `Agents` config option (default is `"lastfm,spotify"`). The order dictates the priority of the agents
For a simple Agent example, look at the [local_agent](local_agent.go) agent source code.
Expect(agent.GetArtistBiography(ctx,"123","U2","")).To(Equal("U2 é uma das mais importantes bandas de rock de todos os tempos. Formada em 1976 em Dublin, composta por Bono (vocalista e guitarrista), The Edge (guitarrista, pianista e backing vocal), Adam Clayton (baixista), Larry Mullen, Jr. (baterista e percussionista).\n\nDesde a década de 80, U2 é uma das bandas mais populares no mundo. Seus shows são únicos e um verdadeiro festival de efeitos especiais, além de serem um dos que mais arrecadam anualmente. <a href=\"https://www.last.fm/music/U2\">Read more on Last.fm</a>"))
Description:"Believe is the twenty-third studio album by American singer-actress Cher, released on November 10, 1998 by Warner Bros. Records. The RIAA certified it Quadruple Platinum on December 23, 1999, recognizing four million shipments in the United States; Worldwide, the album has sold more than 20 million copies, making it the biggest-selling album of her career. In 1999 the album received three Grammy Awards nominations including \"Record of the Year\", \"Best Pop Album\" and winning \"Best Dance Recording\" for the single \"Believe\". It was released by Warner Bros. Records at the end of 1998. The album was executive produced by Rob <a href=\"https://www.last.fm/music/Cher/Believe\">Read more on Last.fm</a>.",
body:=[]byte(`{"error":3,"message":"Invalid Method - No method with that name in this package"}`)
err:=json.Unmarshal(body,&error)
Expect(err).To(BeNil())
Expect(error.Code).To(Equal(3))
Expect(error.Error).To(Equal(3))
Expect(error.Message).To(Equal("Invalid Method - No method with that name in this package"))
})
})
Some files were not shown because too many files have changed in this diff
Show More
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.