SendSpin Multi-Room Audio Renderer Integration - #2
Open
kiwipaulrob wants to merge 214 commits into
Open
Conversation
Causes MPD lsinfo to fail with a parse error and affects several scripts. - playerlib.js renderFolderView(): data-path element needs encodeHTMLEntities() - PHP scripts containing lsinfo commands need escapeDblQuotes()
This commit adds SendSpin client support to moOde, allowing it to act as a synchronized audio endpoint in a SendSpin multi-room system (e.g., Music Assistant). Features: - Configure → Renderers UI integration - Service ON/OFF toggle with auto-save - Custom endpoint name configuration - Manual restart with confirmation dialog - MPD coexistence (auto-stop/resume) - Direct hardware ALSA configuration (avoids dmix IPC issues) - Systemd timeout for reliable startup - All code quality fixes applied (safe array access, proper escaping) Installation: curl -fsSL .../moode-sendspin-installer.sh | sudo bash Or minimal install: curl -fsSL ... | sudo bash -s -- --minimal Tested on moOde 9.4.2 with Music Assistant 2.x Release 1: Core integration
…aDSP, buffer tuning Release 2 builds on the core integration (Release 1) with: Features: - Now playing metadata display (title, artist, album, cover art) via SendSpin hook-start/hook-stop environment variables - Two-way volume synchronisation with Music Assistant via hook-set-volume + reverse sync CLI - CamillaDSP loopback support (auto-detects DSP state, routes through hw:Loopback when enabled, direct hw when disabled) - ALSA buffer tuning (period_time 1160, buffer_time 4640) for sub-millisecond sync precision - Version check and update button (checks PyPI for newer versions) - Systemd hardening (LimitRTPRIO, LimitMEMLOCK for real-time priority) - Pre-play and post-play hooks (spspre.sh, spspost.sh) Files added: - hooks/sendspin-metadata.sh - Metadata capture from SENDSPIN_* env vars - hooks/sendspin-volume-sync.sh - Volume sync (MA -> moOde + reverse) - hooks/spspre.sh - Pre-play: CamillaDSP detection + ALSA routing - hooks/spspost.sh - Post-play: state cleanup - hooks/sendspin-version-check.sh - PyPI version comparison - etc/alsa/conf.d/sendspin.conf - Buffer-tuned ALSA config - moode-sendspin-r2-installer.sh - R2 installer with --check/--uninstall - SENDSPIN_RELEASE2_ROADMAP.md - Full feature roadmap Dependencies: - Release 1 (sendspin-integration) must be installed - SendSpin CLI 7.5.0+ (hook support) - moOde 9.4.2+ Builds on sendspin-integration branch
… block The nested-brace ALSA syntax (type hw / card N / device N) was not being parsed correctly by ALSA on the Pi, causing the sendspin PCM device to not register. Switched to the string-based format used by moOde's own config files (pcm 'plughw:0,0') which works reliably. Also removed period_time/buffer_time from ALSA config - these parameters are not valid in the slave block of type plug and were causing the PCM definition to be rejected entirely. Tested on Pi: service stable, port 8928 listening, Music Assistant connected successfully after fix.
- Python daemon connects as metadata@v1 client (no audio playback) - Uses aiosendspin ClientListener + SendspinClient from sendspin-cli venv - Receives track metadata (title, artist, album, artwork_url, progress) directly from SendSpin protocol - works with ANY server - Writes to moOde's ~~~ metadata format - Downloads cover art automatically - Runs on separate port 8929 (audio daemon stays on 8928) - Includes systemd service file Based on SendSpin protocol spec: github.com/Sendspin/spec Hook-based approach abandoned - hooks only pass connection info, not track metadata. This is the correct 'metadata sink' pattern.
Wraps the incoming WebSocket with a logging proxy that captures every TEXT and BINARY message before the aiosendspin parser processes it. This will reveal exactly what Music Assistant sends on track changes, connection, and playback state transitions. Also syncs debug logging level and per-field attribute dumps with the version already deployed on the Pi.
…k data Music Assistant does not populate the SendSpin metadata@v1 role fields. All metadata arrives null. Confirmed via raw WebSocket message logging. Solution: Poll Home Assistant REST API (media_player.moode_sendspin entity) every 3 seconds for title, artist, album, duration, and artwork URL. Cover art downloaded via HA proxy URL and cached locally. SendSpin listener kept for connection monitoring only. HA polling runs independently of SendSpin connection state. Tested: track changes captured in real-time, cover art downloading correctly.
- SENDSPIN_RELEASE2_ROADMAP.md: Feature 1 marked DONE with full implementation details, actual vs planned approach, verified working status, updated deps - SENDSPIN_PR.md: Future Enhancement section replaced with implemented solution description including MA bug details and HA polling workaround - README-sendspin.md: Release 2 file listing updated, added metadata sink section with how-it-works, requirements, and service management commands
- Rewrite sendspin-display.js: poll metadata endpoint directly, drop broken engineCmd hook - Fix metadata-sink: re-write file if cleared externally (spspost.sh race) - Add --hardware-volume false to sendspin.service (software volume for SMSL DAC) - Create moode-worker.service systemd unit (replace rc.local for worker.php) - Create ssp-config.php + ssp-config.html (SendSpin settings page with version/update) - Add Edit button to SendSpin section in ren-config.html - Fix overlay CSS: pointer-events for click-through, vmin-responsive cover sizing - Restore spspre.sh original ALSA config (remove softvol attempt)
… BUG-03 restart on save, BUG-04 DB read order, ISSUE-01 session via stored ID, ISSUE-04 absolute path, ISSUE-05 async update, ISSUE-06 session fallback on ssp, MINOR-04 input validation, STRUCT-06 PIDFile cleanup
…SUE-03: Add cfg_sendspin table and service regeneration to installer
…IN after merge, fix uninstall cleanup
…at_bitmask dedup fix
…rsion, checkSendspinUpdate, updateSendspin, generateSendspinService, getSendspinMetadata)
…php include (3 new installer components)
… daemon in installer
… no HA dependency
…uth, MA_TOKEN support
…onflict with worker
…rers disappearing
…ource, parse response as list
…fix progress field, strip empty titles
…e, use HA_TOKEN instead
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
SendSpin Multi-Room Audio Client for moOde
Metadata Architecture (final)
Fallback: Device detection (fuser) → "Now Playing" indicator
Future: SendSpin protocol metadata@v1 listener is built and dormant — activates when MA populates the role fields
19 installer components | Clean architecture
Key Features
_audioout— same ALSA device as AirPlay/Spotify/MPDNOT READY FOR UPSTREAM — needs fresh-install test