# Now Playing Logger Plugin (Python) A Python example plugin that demonstrates the **Scheduler** and **SubsonicAPI** host services by periodically logging what is currently playing in Navidrome. ## Features - Uses `scheduler_schedulerecurring` host function to set up a recurring task - Uses `subsonicapi_call` host function to query the `getNowPlaying` API - Configurable cron expression and user via plugin config - Demonstrates Python host function imports using `@extism.import_fn` ## Prerequisites - [extism-py](https://github.com/extism/python-pdk) - Python PDK compiler ```bash curl -Ls https://raw.githubusercontent.com/extism/python-pdk/main/install.sh | bash ``` > **Note:** `extism-py` requires [Binaryen](https://github.com/WebAssembly/binaryen/) (`wasm-merge`, `wasm-opt`) to be installed. ## Building From the `plugins/examples` directory: ```bash make nowplaying-py.ndp ``` Or directly: ```bash extism-py plugin/__init__.py -o plugin.wasm zip -j nowplaying-py.ndp manifest.json plugin.wasm ``` ## Installation 1. Copy `nowplaying-py.ndp` to your Navidrome plugins folder 2. Enable plugins in `navidrome.toml`: ```toml [Plugins] Enabled = true Folder = "/path/to/plugins" ``` 3. Configure the plugin in the UI (Settings → Plugins → nowplaying-py) ## Configuration | Key | Description | Default | |--------|-------------------------------------|---------------| | `cron` | Cron expression for check frequency | `*/1 * * * *` | | `user` | Navidrome user for SubsonicAPI | `admin` | ## Testing Test the manifest: ```bash extism call nowplaying-py.wasm nd_manifest --wasi ``` ## Output When running, the plugin logs messages like: ``` 🎵 john is playing: Pink Floyd - Comfortably Numb (The Wall) 🎵 jane is playing: Radiohead - Paranoid Android (OK Computer) ``` Or when no one is playing: ``` 🎵 No users currently playing music ``` ## How It Works 1. **Initialization (`nd_on_init`)**: Reads the cron expression from config and schedules a recurring task using the Scheduler host service. 2. **Callback (`nd_scheduler_callback`)**: When the scheduled task fires, calls the SubsonicAPI `getNowPlaying` endpoint and logs the results. ## Host Function Usage (Python) This plugin demonstrates how to call Navidrome host functions from Python: ```python import extism import json # Import the host function @extism.import_fn("extism:host/user", "subsonicapi_call") def _subsonicapi_call(offset: int) -> int: """Raw host function - returns memory offset.""" ... # Wrapper for JSON marshalling def subsonicapi_call(uri: str) -> dict: request = {"uri": uri} request_bytes = json.dumps(request).encode('utf-8') request_mem = extism.memory.alloc(request_bytes) response_offset = _subsonicapi_call(request_mem.offset) response_mem = extism.memory.find(response_offset) response = json.loads(extism.memory.string(response_mem)) if response.get("error"): raise Exception(response["error"]) return json.loads(response.get("responseJSON", "{}")) ```