This file captures the current working shape of the app so future work can resume quickly.
The .NET 10 MVP is working end-to-end with:
- Samsung TV: discovery, browse, cover art, playback
- Lyngdorf amplifier: discovery, browse, playback
Primary runtime projects:
Phylet- Web API host and DLNA endpoints
Phylet.Data- SQLite persistence, runtime device configuration, and current library service
Test projects:
Phylet.Tests- host/controller coverage
Phylet.Data.Tests- data/configuration/library coverage
Host-side components:
Services/SsdpService.cs- SSDP listener + M-SEARCH responses
NOTIFY ssdp:aliveandssdp:byebye- Auto-resolves LAN-advertised base URL from active listen address and preferred outbound interface
Controllers/DeviceDescriptionController.cs/description.xml
Controllers/ContentDirectoryController.cs/ContentDirectory/scpd.xml/upnp/control/contentdirectorySOAP actions/upnp/event/contentdirectorySUBSCRIBE/UNSUBSCRIBE
Controllers/ConnectionManagerController.cs/ConnectionManager/scpd.xml/upnp/control/connectionmanager/upnp/event/connectionmanagerSUBSCRIBE/UNSUBSCRIBE
Controllers/MediaController.csGET|HEAD /media/audio/{trackId}with range supportGET|HEAD /media/image/{albumId}with range support
Services/DidlBuilder.cs- DIDL-Lite browse responses
protocolInfowith DLNA fieldsres@sizewhen file exists
Services/EventSubscriptionService.cs- basic SID/timeout handling for event subscriptions
Services/StartupDiagnosticsService.cs- startup self-check logging for effective config + media presence
Data-side components:
Configuration/DeviceConfigurationInitializer.cs- applies SQLite migrations at startup
- generates/persists device UUID on first run
- loads runtime device config snapshot
Configuration/DatabasePathResolver.cs- OS-appropriate app-data default DB location
- supports override via
Storage:DatabasePath
Configuration/MediaPathResolver.cs- validates the configured media root
- resolves media file paths relative to the configured root
Library/LibraryService.cs- SQLite-backed browse/query layer for Artists, Albums, Files, media resources, and library statistics
Library/LibraryScanner.cs- startup library scan
- read-only metadata import into SQLite
- tolerates per-file failures and continues scanning
- Keep
HEADenabled on media endpoints; Samsung requires this in practice. - Keep DLNA media response headers:
transferMode.dlna.orgcontentFeatures.dlna.org
- Keep DIDL
res@size; several clients depend on it. - Keep event subscription endpoints returning valid
SID+TIMEOUT.
See Phylet/appsettings*.json:
Dlna:ManufacturerandDlna:ModelNamestay in appsettingsDlna:DefaultSubscriptionTimeoutSecondscontrols SUBSCRIBE timeoutStorage:DatabasePathoptionally overrides the SQLite file pathStorage:MediaPathoptionally overrides the media rootDeviceUuidandFriendlyNameare persisted in SQLite and initialized on first startup
Docker defaults:
Storage__DatabasePath=/data/phylet.dbStorage__MediaPath=/media
CI and publishing:
.github/workflows/docker-publish.yml- runs
dotnet test --configuration Release --no-restore - builds
linux/amd64andlinux/arm64 - publishes
ghcr.io/<owner>/phyleton pushes tomainandv*tags
- runs
- Repetitive request-level logs are
Debug. - High-signal service logs remain
Information. - Unsupported SSDP search targets are
Debug(not warning noise).
Expected files in Phylet/MediaTest/:
track1.mp3track2.mp3cover.jpg
Development MediaTest is only a fallback fixture. The real library model is SQLite-backed and scanned from the configured media root.
High-level architecture notes:
docs/ARCHITECTURE.md
Protocol baseline is currently described in:
docs/INTEROP_CONTRACT.md
When resuming, update that file if wire-level behavior changes.