* feat(plugins): add lyrics provider plugin capability Refactor the lyrics system from a static function to an interface-based service that supports WASM plugin providers. Plugins listed in the LyricsPriority config (alongside "embedded" and file extensions) are now resolved through the plugin system. Includes capability definition, Go/Rust PDK, adapter, Wire integration, and tests for plugin fallback behavior. * test(plugins): add lyrics capability integration test with test plugin * fix(plugins): default lyrics language to 'xxx' when plugin omits it Per the OpenSubsonic spec, the server must return 'und' or 'xxx' when the lyrics language is unknown. The lyrics plugin adapter was passing an empty string through when a plugin didn't provide a language value. This defaults the language to 'xxx', consistent with all other callers of model.ToLyrics() in the codebase. * refactor(plugins): rename lyrics import to improve clarity Signed-off-by: Deluan <deluan@navidrome.org> * refactor(lyrics): update TrackInfo description for clarity Signed-off-by: Deluan <deluan@navidrome.org> * fix(lyrics): enhance lyrics plugin handling and case sensitivity Signed-off-by: Deluan <deluan@navidrome.org> * fix(plugins): update payload type to string with byte format for task data Signed-off-by: Deluan <deluan@navidrome.org> --------- Signed-off-by: Deluan <deluan@navidrome.org>
Navidrome Plugin Capabilities
This directory contains the Go interface definitions for Navidrome plugin capabilities. These interfaces are the source of truth for plugin development and are used to generate:
- Go PDK packages (
pdk/go/*/) - Type-safe wrappers for Go plugin developers - Rust PDK crates (
pdk/rust/*/) - Type-safe wrappers for Rust plugin developers - XTP YAML schemas (
*.yaml) - Schema files for other Extism plugin languages (TypeScript, Python, C#, Zig, C++, ...)
For Go Plugin Developers
Go developers should use the generated PDK packages in plugins/pdk/go/. See the example Go plugins in plugins/examples/ for usage patterns.
For Rust Plugin Developers
Rust developers should use the generated PDK crate in plugins/pdk/rust/nd-pdk. See the example Rust plugins in plugins/examples for usage patterns.
For Non-Go Plugin Developers
If you're developing plugins in other languages (TypeScript, Rust, Python, C#, Zig, C++), you can use the XTP CLI to generate type-safe bindings from the YAML schema files in this directory.
Prerequisites
Install the XTP CLI:
# macOS
brew install dylibso/tap/xtp
# Other platforms - see https://docs.xtp.dylibso.com/docs/cli
curl https://static.dylibso.com/cli/install.sh | bash
Generating Plugin Scaffolding
Use the XTP CLI to generate plugin boilerplate from any capability schema:
# TypeScript
xtp plugin init --schema-file plugins/capabilities/metadata_agent.yaml \
--template typescript --path my-plugin
# Rust
xtp plugin init --schema-file plugins/capabilities/scrobbler.yaml \
--template rust --path my-plugin
# Python
xtp plugin init --schema-file plugins/capabilities/lifecycle.yaml \
--template python --path my-plugin
# C#
xtp plugin init --schema-file plugins/capabilities/scheduler_callback.yaml \
--template csharp --path my-plugin
# Go (alternative to using the PDK packages)
xtp plugin init --schema-file plugins/capabilities/websocket_callback.yaml \
--template go --path my-plugin
Available Capabilities
| Capability | Schema File | Description |
|---|---|---|
| Metadata Agent | metadata_agent.yaml |
Fetch artist biographies, album images, and similar artists |
| Scrobbler | scrobbler.yaml |
Report listening activity to external services |
| Lifecycle | lifecycle.yaml |
Plugin initialization callbacks |
| Scheduler Callback | scheduler_callback.yaml |
Scheduled task execution |
| WebSocket Callback | websocket_callback.yaml |
Real-time WebSocket message handling |
Building Your Plugin
After generating the scaffolding, implement the required functions and build your plugin as a WebAssembly module. The exact build process depends on your chosen language - see the Extism PDK documentation for language-specific guides.
XTP Schema Generation
The YAML schemas in this package are automatically generated from the capability Go interfaces using ndpgen.
To regenerate the schemas after modifying the interfaces, run:
cd plugins/cmd/ndpgen && go run . -schemas -input=./plugins/capabilities