mirror of
https://github.com/navidrome/navidrome.git
synced 2026-03-04 06:35:52 +00:00
* feat: add ISRC support to similar songs matching and plugin interface Add ISRC (International Standard Recording Code) as a high-priority identifier in the provider matching algorithm, alongside MBID. The matching pipeline now uses four strategies in priority order: ID > MBID > ISRC > Title+Artist fuzzy match. - Add ISRC field to agents.Song struct - Add ISRC field to plugin capability SongRef (Go, Rust PDKs) - Add loadTracksByISRC using json_tree query on tags column - Integrate ISRC into matchSongsToLibrary, selectBestMatchingSongs, and buildTitleQueries https://claude.ai/code/session_01Dd4mTq1VQZag4RNjCVusiF * chore: regenerate plugin schema after ISRC addition Run `make gen` to update the generated YAML schema for the metadata agent capability with the new ISRC field on SongRef. https://claude.ai/code/session_01Dd4mTq1VQZag4RNjCVusiF * feat(mediafile): add GetAllByTags method to MediaFileRepository for tag-based retrieval Signed-off-by: Deluan <deluan@navidrome.org> * feat(provider): speed up track matching by incorporating prior matches in ISRC and MBID lookups Signed-off-by: Deluan <deluan@navidrome.org> --------- Signed-off-by: Deluan <deluan@navidrome.org> Co-authored-by: Claude <noreply@anthropic.com>
Navidrome Plugin Development Kit for Rust
This directory contains the Rust PDK crates for building Navidrome plugins.
Crate Structure
plugins/pdk/rust/
├── nd-pdk/ # Umbrella crate - use this as your dependency
├── nd-pdk-host/ # Host function wrappers (call Navidrome services)
└── nd-pdk-capabilities/ # Capability traits and types (generated)
Usage
Add the nd-pdk crate as a dependency in your plugin's Cargo.toml:
[package]
name = "my-plugin"
edition = "2021"
[lib]
crate-type = ["cdylib"]
[dependencies]
nd-pdk = { path = "../../pdk/rust/nd-pdk" }
extism-pdk = "1.2"
Implementing a Scrobbler (Required-All Pattern)
The Scrobbler capability requires all methods to be implemented:
use nd_pdk::scrobbler::{
Error, IsAuthorizedRequest,
NowPlayingRequest, ScrobbleRequest, Scrobbler,
};
// Register WASM exports for all Scrobbler methods
nd_pdk::register_scrobbler!(MyPlugin);
#[derive(Default)]
struct MyPlugin;
impl Scrobbler for MyPlugin {
fn is_authorized(&self, req: IsAuthorizedRequest) -> Result<bool, Error> {
Ok(true)
}
fn now_playing(&self, req: NowPlayingRequest) -> Result<(), Error> {
// Handle now playing notification
Ok(())
}
fn scrobble(&self, req: ScrobbleRequest) -> Result<(), Error> {
// Submit scrobble
Ok(())
}
}
Implementing Metadata Agent (Optional Pattern)
The MetadataAgent capability allows implementing individual methods:
use nd_pdk::metadata::{
ArtistBiographyProvider, GetArtistBiographyRequest, ArtistBiography, Error,
};
// Register only the methods you implement
nd_pdk::register_artist_biography!(MyPlugin);
#[derive(Default)]
struct MyPlugin;
impl ArtistBiographyProvider for MyPlugin {
fn get_artist_biography(&self, req: GetArtistBiographyRequest)
-> Result<ArtistBiography, Error>
{
// Return artist biography
Ok(ArtistBiography {
biography: "Artist bio text...".into(),
..Default::default()
})
}
}
Using Host Services
Access Navidrome services via the host module:
use nd_pdk::host::{artwork, scheduler, library};
// Get artwork URL for a track
let url = artwork::get_track_url("track-id", 300)?;
// Schedule a one-time callback
scheduler::schedule_one_time(60, "my-payload", "schedule-id")?;
// Get library information
let libs = library::get_all()?;
Available Capabilities
| Capability | Pattern | Description |
|---|---|---|
scrobbler |
Required-all | Submit listening history to external services |
metadata |
Optional | Provide artist/album metadata from external sources |
lifecycle |
Optional | Handle plugin initialization |
scheduler |
Optional | Receive scheduled callbacks |
websocket |
Optional | Handle WebSocket messages |
Building
Rust plugins must be compiled to WASM using the wasm32-wasip1 target:
cargo build --release --target wasm32-wasip1
The resulting .wasm file can be packaged into an .ndp plugin package.
Examples
See the example plugins for complete implementations:
- webhook-rs - Simple scrobbler using the PDK
- discord-rich-presence-rs - Complex plugin with multiple capabilities
- library-inspector-rs - Host service demonstration
Code Generation
The capability modules in nd-pdk-capabilities are auto-generated from the Go capability definitions. To regenerate after capability changes:
make gen
This generates both Go and Rust PDK code.