remove redundant restAPI
Build Plugin / build (push) Successful in 2m46s
Release Plugin / build-and-release (push) Successful in 2m44s

playback is controlled by state machine
This commit is contained in:
2025-12-30 14:37:27 +01:00
parent 29cd6dfaeb
commit a199fe452c
9 changed files with 824 additions and 523 deletions
+91 -31
View File
@@ -31,15 +31,15 @@ JellyLMS enables Jellyfin to stream audio to LMS, which acts as a multi-room spe
│ │ Library │──┼────────►│ LmsApiClient │────────►│ │ Players │ │
│ │ (Audio) │ │ │ │ │ │ (Zones) │ │
│ └───────────┘ │ │ ┌───────────┐ │ │ └───────────┘ │
│ │ │ │ Session │ │ │ │
│ ┌───────────┐ │ │ │ Manager │ │ │ ┌───────────┐ │
│ │ Queue │──┼────────►│ └───────────┘ │────────►│ │ Sync │ │
│ │ │ │ │ │ │ │ Groups │ │
│ └───────────┘ │ │ ─────────── │ │ └───────────┘ │
│ │ │ │ REST API │ │ │ │
│ ┌───────────┐ │ │ │Controller │ │ │ │
│ │ Playback │──┼────────►│ └───────────┘ │ │ │
│ │ Controls │ │ │ │ │ │
│ │ │ │ Session │ │ │ │
│ ┌───────────┐ │ │ │Controller │ │ │ ┌───────────┐ │
│ │ Queue │──┼────────►│ │ (State │ │────────►│ │ Sync │ │
│ │ │ │ │ │ Machine) │ │ │ │ Groups │ │
│ └───────────┘ │ │ ─────────── │ │ └───────────┘ │
│ │ │ │ │ │
│ ┌───────────┐ │ │ ┌───────────┐ │ │ │
│ │ Playback │──┼────────►│ │ REST API │ │ │ │
│ │ Controls │ │ │ └───────────┘ │ │ │
│ └───────────┘ │ └─────────────────┘ └─────────────────┘
└─────────────────┘
```
@@ -48,8 +48,9 @@ JellyLMS enables Jellyfin to stream audio to LMS, which acts as a multi-room spe
- **Player Discovery**: Automatically discovers all LMS players/zones
- **Multi-Room Sync**: Create and manage sync groups for synchronized playback across multiple rooms
- **Playback Control**: Play, pause, stop, seek, and volume control forwarded to LMS
- **Playback Control**: Play, pause, stop, seek, and volume control via Jellyfin's "Play On" (cast) interface
- **Stream Bridging**: Generates audio stream URLs from Jellyfin for LMS to consume
- **Robust State Machine**: Ensures proper sequencing of playback operations with automatic retry and timeout handling
## Screenshots
@@ -76,9 +77,62 @@ Create and manage synchronized playback groups for multi-room audio:
## Requirements
- Jellyfin Server 10.10.0 or later
- .NET 8.0 Runtime
- .NET 9.0 Runtime
- Logitech Media Server (LMS) with JSON-RPC API enabled (default on port 9000)
## Playback Architecture
JellyLMS uses Jellyfin's native "Play On" (cast) interface to control LMS players. When you select an LMS player from Jellyfin's cast menu, playback is managed through a robust state machine that ensures reliable operation.
### State Machine
The playback controller uses a state machine to ensure proper sequencing of operations:
```
┌────────┐
│ Idle │ (device connected, no media)
└───┬────┘
│ Play command
┌────────┐
┌────►│Loading │◄────┐
│ └───┬────┘ │
│ │ │ Seek (HTTP streaming
│ LMS confirms │ restarts stream)
│ mode="play" │
│ ▼ │
┌───────┐ │ ┌────────┐ │
│ Error │◄────┼─────│Playing │─────┘
└───┬───┘ │ └───┬────┘
│ │ │ Pause
retry │ ▼
│ │ ┌────────┐
└─────────┼─────│ Paused │
│ └───┬────┘
│ │ Seek (native LMS)
│ ▼
│ ┌────────┐
└─────│Seeking │
└────────┘
From any state: Stop → Stopped
```
### How Playback Works
1. **Cast Request**: User selects an LMS player from Jellyfin's "Play On" menu
2. **Loading**: Plugin sends play command to LMS and transitions to Loading state
3. **Confirmation**: Plugin polls LMS until playback is confirmed (mode="play")
4. **Playing**: Playback is active; progress is synced between Jellyfin and LMS
5. **Controls**: Play, pause, seek, and volume commands are forwarded to LMS
### Error Handling
The state machine includes automatic retry with exponential backoff:
- **Timeout errors**: Auto-retry up to 2 times (500ms → 1s delay)
- **Network errors**: Auto-retry up to 2 times
- **LMS errors**: No retry, transition to Error state
## Installation
### Manual Installation
@@ -101,7 +155,7 @@ cd jellyLMS
dotnet build Jellyfin.Plugin.JellyLMS.sln -c Release
# The DLL will be in:
# Jellyfin.Plugin.JellyLMS/bin/Release/net8.0/
# Jellyfin.Plugin.JellyLMS/bin/Release/net9.0/
```
## Configuration
@@ -116,41 +170,45 @@ dotnet build Jellyfin.Plugin.JellyLMS.sln -c Release
| Connection Timeout | Timeout for LMS API calls (seconds) | `10` |
| Enable Auto Sync | Automatically sync players when creating groups | `true` |
| Default Player | MAC address of the default player | (none) |
| Use Direct File Path | Enable direct file access instead of HTTP streaming | `false` |
### Advanced Settings (State Machine)
| Setting | Description | Default |
|---------|-------------|---------|
| Loading Timeout | Max time to wait for LMS to start playback (seconds) | `5` |
| Seek Timeout | Max time to wait for seek to complete (seconds) | `3` |
| Transition Poll Interval | How often to poll LMS during state transitions (ms) | `300` |
| Max Auto Retries | Number of automatic retries for transient failures | `2` |
3. Click "Test Connection" to verify connectivity to LMS
4. Use "Discover Players" to see available LMS players
## API Endpoints
The plugin exposes REST API endpoints under `/JellyLms/`:
The plugin exposes REST API endpoints under `/JellyLms/` for player and sync group management.
**Note:** Playback control (play, pause, seek, volume) is handled through Jellyfin's native "Play On" (cast) interface, not through REST endpoints.
### Players
- `GET /JellyLms/Players` - List all LMS players
- `GET /JellyLms/Players/{mac}` - Get specific player details
- `POST /JellyLms/Players/Refresh` - Refresh player list from LMS
- `POST /JellyLms/Players/{mac}/PowerOn` - Power on a player
- `POST /JellyLms/Players/{mac}/PowerOff` - Power off a player
- `POST /JellyLms/Players/{mac}/Volume` - Set player volume
### Sync Groups
- `GET /JellyLms/SyncGroups` - List all sync groups
- `POST /JellyLms/SyncGroups` - Create a new sync group
- `DELETE /JellyLms/SyncGroups/{masterMac}` - Dissolve a sync group
- `DELETE /JellyLms/SyncGroups/{masterMac}/Players/{slaveMac}` - Remove player from group
- `DELETE /JellyLms/SyncGroups/Players/{mac}` - Remove player from its sync group
### Sessions
### Utilities
- `GET /JellyLms/Sessions` - List active playback sessions
- `POST /JellyLms/Sessions` - Start a new playback session
- `POST /JellyLms/Sessions/{id}/Pause` - Pause playback
- `POST /JellyLms/Sessions/{id}/Resume` - Resume playback
- `POST /JellyLms/Sessions/{id}/Stop` - Stop playback
- `POST /JellyLms/Sessions/{id}/Seek` - Seek to position
- `POST /JellyLms/Sessions/{id}/Volume` - Set volume
### Status
- `GET /JellyLms/Status` - Get LMS connection status
- `POST /JellyLms/TestConnection` - Test LMS connectivity
- `GET /JellyLms/DiscoverPaths` - Discover file paths for direct file access configuration
## LMS Setup
@@ -218,15 +276,17 @@ Jellyfin.Plugin.JellyLMS/
│ ├── PluginConfiguration.cs # Plugin settings
│ └── configPage.html # Dashboard configuration UI
├── Api/
│ └── JellyLmsController.cs # REST API endpoints
│ └── JellyLmsController.cs # REST API endpoints (players, sync groups)
├── Services/
│ ├── ILmsApiClient.cs # LMS API interface
│ ├── LmsApiClient.cs # LMS JSON-RPC client
│ ├── LmsPlayerManager.cs # Player discovery & sync
── LmsSessionManager.cs # Playback session management
── LmsSessionController.cs # Playback control (ISessionController)
│ ├── PlaybackStateMachine.cs # State machine for playback lifecycle
│ └── LmsStatusPoller.cs # Polls LMS to confirm state transitions
└── Models/
├── LmsPlayer.cs # Player model
├── LmsPlaybackSession.cs # Session state model
├── LmsPlaybackSession.cs # Session state (incl. PlaybackState enum)
└── LmsApiModels.cs # JSON-RPC DTOs
```
@@ -237,7 +297,7 @@ Jellyfin.Plugin.JellyLMS/
dotnet build Jellyfin.Plugin.JellyLMS.sln
# Copy to Jellyfin plugins directory
cp Jellyfin.Plugin.JellyLMS/bin/Debug/net8.0/Jellyfin.Plugin.JellyLMS.dll \
cp Jellyfin.Plugin.JellyLMS/bin/Debug/net9.0/Jellyfin.Plugin.JellyLMS.dll \
~/.local/share/jellyfin/plugins/JellyLMS/
# Restart Jellyfin to load the plugin