mirror of
https://github.com/navidrome/navidrome.git
synced 2026-11-09 03:38:48 +01:00
feat: generate PDK code for PlaylistGenerator capability
Generated via ndpgen: Go PDK wrappers, Rust PDK wrappers, and XTP schema for non-Go plugins.
This commit is contained in:
parent
4908dae21f
commit
dedaf8e64a
5 changed files with 535 additions and 0 deletions
|
|
@ -8,6 +8,7 @@
|
|||
pub mod lifecycle;
|
||||
pub mod lyrics;
|
||||
pub mod metadata;
|
||||
pub mod playlistgenerator;
|
||||
pub mod scheduler;
|
||||
pub mod scrobbler;
|
||||
pub mod taskworker;
|
||||
|
|
|
|||
165
plugins/pdk/rust/nd-pdk-capabilities/src/playlistgenerator.rs
Normal file
165
plugins/pdk/rust/nd-pdk-capabilities/src/playlistgenerator.rs
Normal file
|
|
@ -0,0 +1,165 @@
|
|||
// Code generated by ndpgen. DO NOT EDIT.
|
||||
//
|
||||
// This file contains export wrappers for the PlaylistGenerator capability.
|
||||
// It is intended for use in Navidrome plugins built with extism-pdk.
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
// Helper functions for skip_serializing_if with numeric types
|
||||
#[allow(dead_code)]
|
||||
fn is_zero_i32(value: &i32) -> bool { *value == 0 }
|
||||
#[allow(dead_code)]
|
||||
fn is_zero_u32(value: &u32) -> bool { *value == 0 }
|
||||
#[allow(dead_code)]
|
||||
fn is_zero_i64(value: &i64) -> bool { *value == 0 }
|
||||
#[allow(dead_code)]
|
||||
fn is_zero_u64(value: &u64) -> bool { *value == 0 }
|
||||
#[allow(dead_code)]
|
||||
fn is_zero_f32(value: &f32) -> bool { *value == 0.0 }
|
||||
#[allow(dead_code)]
|
||||
fn is_zero_f64(value: &f64) -> bool { *value == 0.0 }
|
||||
/// GetPlaylistRequest is the request for GetPlaylist.
|
||||
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct GetPlaylistRequest {
|
||||
/// ID is the plugin-scoped playlist ID.
|
||||
#[serde(default)]
|
||||
pub id: String,
|
||||
}
|
||||
/// GetPlaylistResponse is the response for GetPlaylist.
|
||||
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct GetPlaylistResponse {
|
||||
/// Name is the display name of the playlist.
|
||||
#[serde(default)]
|
||||
pub name: String,
|
||||
/// Description is an optional description for the playlist.
|
||||
#[serde(default, skip_serializing_if = "String::is_empty")]
|
||||
pub description: String,
|
||||
/// CoverArtURL is an optional external URL for the playlist cover art.
|
||||
#[serde(default, skip_serializing_if = "String::is_empty")]
|
||||
pub cover_art_url: String,
|
||||
/// Tracks is the list of songs in the playlist, using SongRef for matching.
|
||||
#[serde(default)]
|
||||
pub tracks: Vec<SongRef>,
|
||||
/// ValidUntil is a unix timestamp indicating when this playlist data expires.
|
||||
/// 0 means static (never refresh).
|
||||
#[serde(default)]
|
||||
pub valid_until: i64,
|
||||
}
|
||||
/// GetPlaylistsRequest is the request for GetPlaylists.
|
||||
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct GetPlaylistsRequest {
|
||||
}
|
||||
/// GetPlaylistsResponse is the response for GetPlaylists.
|
||||
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct GetPlaylistsResponse {
|
||||
/// Playlists is the list of playlists provided by this plugin.
|
||||
#[serde(default)]
|
||||
pub playlists: Vec<PlaylistInfo>,
|
||||
/// RefreshInterval is the number of seconds until the next GetPlaylists call.
|
||||
/// 0 means never re-discover.
|
||||
#[serde(default)]
|
||||
pub refresh_interval: i64,
|
||||
}
|
||||
/// PlaylistInfo identifies a plugin playlist and its target user.
|
||||
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct PlaylistInfo {
|
||||
/// ID is the plugin-scoped unique identifier for this playlist.
|
||||
#[serde(default)]
|
||||
pub id: String,
|
||||
/// OwnerUserID is the Navidrome user ID that owns this playlist.
|
||||
#[serde(default)]
|
||||
pub owner_user_id: String,
|
||||
}
|
||||
/// SongRef is a reference to a song with metadata for matching.
|
||||
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct SongRef {
|
||||
/// ID is the internal Navidrome mediafile ID (if known).
|
||||
#[serde(default, skip_serializing_if = "String::is_empty")]
|
||||
pub id: String,
|
||||
/// Name is the song name.
|
||||
#[serde(default)]
|
||||
pub name: String,
|
||||
/// MBID is the MusicBrainz ID for the song.
|
||||
#[serde(default, skip_serializing_if = "String::is_empty")]
|
||||
pub mbid: String,
|
||||
/// ISRC is the International Standard Recording Code for the song.
|
||||
#[serde(default, skip_serializing_if = "String::is_empty")]
|
||||
pub isrc: String,
|
||||
/// Artist is the artist name.
|
||||
#[serde(default, skip_serializing_if = "String::is_empty")]
|
||||
pub artist: String,
|
||||
/// ArtistMBID is the MusicBrainz artist ID.
|
||||
#[serde(default, skip_serializing_if = "String::is_empty")]
|
||||
pub artist_mbid: String,
|
||||
/// Album is the album name.
|
||||
#[serde(default, skip_serializing_if = "String::is_empty")]
|
||||
pub album: String,
|
||||
/// AlbumMBID is the MusicBrainz release ID.
|
||||
#[serde(default, skip_serializing_if = "String::is_empty")]
|
||||
pub album_mbid: String,
|
||||
/// Duration is the song duration in seconds.
|
||||
#[serde(default, skip_serializing_if = "is_zero_f32")]
|
||||
pub duration: f32,
|
||||
}
|
||||
|
||||
/// Error represents an error from a capability method.
|
||||
#[derive(Debug)]
|
||||
pub struct Error {
|
||||
pub message: String,
|
||||
}
|
||||
|
||||
impl std::fmt::Display for Error {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "{}", self.message)
|
||||
}
|
||||
}
|
||||
|
||||
impl std::error::Error for Error {}
|
||||
|
||||
impl Error {
|
||||
pub fn new(message: impl Into<String>) -> Self {
|
||||
Self { message: message.into() }
|
||||
}
|
||||
}
|
||||
|
||||
/// PlaylistGenerator requires all methods to be implemented.
|
||||
/// PlaylistGenerator provides dynamically-generated playlists (e.g., "Daily Mix",
|
||||
/// personalized recommendations). Plugins implementing this capability expose two
|
||||
/// functions: GetPlaylists for lightweight discovery and GetPlaylist for fetching
|
||||
/// the heavy payload (tracks, metadata).
|
||||
pub trait PlaylistGenerator {
|
||||
/// GetPlaylists - GetPlaylists returns the list of playlists this plugin provides.
|
||||
fn get_playlists(&self, req: GetPlaylistsRequest) -> Result<GetPlaylistsResponse, Error>;
|
||||
/// GetPlaylist - GetPlaylist returns the full data for a single playlist (tracks, metadata).
|
||||
fn get_playlist(&self, req: GetPlaylistRequest) -> Result<GetPlaylistResponse, Error>;
|
||||
}
|
||||
|
||||
/// Register all exports for the PlaylistGenerator capability.
|
||||
/// This macro generates the WASM export functions for all trait methods.
|
||||
#[macro_export]
|
||||
macro_rules! register_playlistgenerator {
|
||||
($plugin_type:ty) => {
|
||||
#[extism_pdk::plugin_fn]
|
||||
pub fn nd_playlist_generator_get_playlists(
|
||||
req: extism_pdk::Json<$crate::playlistgenerator::GetPlaylistsRequest>
|
||||
) -> extism_pdk::FnResult<extism_pdk::Json<$crate::playlistgenerator::GetPlaylistsResponse>> {
|
||||
let plugin = <$plugin_type>::default();
|
||||
let result = $crate::playlistgenerator::PlaylistGenerator::get_playlists(&plugin, req.into_inner())?;
|
||||
Ok(extism_pdk::Json(result))
|
||||
}
|
||||
#[extism_pdk::plugin_fn]
|
||||
pub fn nd_playlist_generator_get_playlist(
|
||||
req: extism_pdk::Json<$crate::playlistgenerator::GetPlaylistRequest>
|
||||
) -> extism_pdk::FnResult<extism_pdk::Json<$crate::playlistgenerator::GetPlaylistResponse>> {
|
||||
let plugin = <$plugin_type>::default();
|
||||
let result = $crate::playlistgenerator::PlaylistGenerator::get_playlist(&plugin, req.into_inner())?;
|
||||
Ok(extism_pdk::Json(result))
|
||||
}
|
||||
};
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue