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
This is a music streaming server written in Go with a React frontend. The application manages music libraries, provides streaming capabilities, and offers various features like artist information, artwork handling, and external service integrations.
## Code Standards
### Backend (Go)
- Follow standard Go conventions and idioms
- Use context propagation for cancellation signals
- Write unit tests for new functionality using Ginkgo/Gomega
- Use mutex appropriately for concurrent operations
- Implement interfaces for dependencies to facilitate testing
### Frontend (React)
- Use functional components with hooks
- Follow React best practices for state management
- Implement PropTypes for component properties
- Prefer using React-Admin and Material-UI components
- Icons should be imported from `react-icons` only
- Follow existing patterns for API interaction
## Repository Structure
-`core/`: Server-side business logic (artwork handling, playback, etc.)
-`ui/`: React frontend components
-`model/`: Data models and repository interfaces
-`server/`: API endpoints and server implementation
-`utils/`: Shared utility functions
-`persistence/`: Database access layer
-`scanner/`: Music library scanning functionality
## Key Guidelines
1. Maintain cache management patterns for performance
2. Follow the existing concurrency patterns (mutex, atomic)
3. Use the testing framework appropriately (Ginkgo/Gomega for Go)
4. Keep UI components focused and reusable
5. Document configuration options in code
6. Consider performance implications when working with music libraries
7. Follow existing error handling patterns
8. Ensure compatibility with external services (LastFM, Spotify, Deezer)
## Development Workflow
- Test changes thoroughly, especially around concurrent operations
- Validate both backend and frontend interactions
- Consider how changes will affect user experience and performance
- Test with different music library sizes and configurations
- Before committing, ALWAYS run `make format lint test`, and make sure there are no issues
## Important commands
-`make build`: Build the application
-`make test`: Run Go tests
- To run tests for a specific package, use `make test PKG=./pkgname/...`
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
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")
// TODO: Implement some struct tags to map flags to viper
funcinit(){
cobra.OnInitialize(func(){
@@ -158,16 +355,19 @@ func init() {
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().Duration("sessiontimeout",viper.GetDuration("sessiontimeout"),"how long Navidrome will wait before closing web ui idle sessions")
@@ -176,6 +376,7 @@ func init() {
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("Invalid ScanSchedule. Please read format spec at https://pkg.go.dev/github.com/robfig/cron#hdr-CRON_Expression_Format","schedule",Server.ScanSchedule,err)
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)
}
returnerr
returnschedule,err
}
// AddHook is used to register initialization code that should run as soon as the config is loaded
Expect(agent.GetArtistBiography(ctx,"123","U2","mbid-1234")).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>"))
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>"))
@@ -368,24 +345,6 @@ var _ = Describe("lastfmAgent", func() {
MBID:"03c91c40-49a6-44a7-90e7-a700edf97a62",
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>.",
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.