Commit Graph

21 Commits

Author SHA1 Message Date
340c69cb2b ⬆️ ureq v2→v3, add continuous stream detection
- Updateurequest dependency from v2 to latest major (v3.14)
- Add ureq as optional dependency in pmoaudio-ext
- Introduce is_continuous flag to UriSource and PlayerState for proper StreamType handling (Finite vs Continuous)
- Implement detect_continuous_stream() with URL pattern matching and HTTP HEAD header inspection (ICY, chunked encoding)
- Update send_track_boundary() to accept StreamType parameter
2026-04-04 18:00:47 +02:00
8924552696 Add StreamType for multi-client support and improved UPnP control
- Introduce `Streamtype` enum (Continuous vs Finite) to distinguish radio streams from finite tracks
- Enrich `TrackBoundary` sync marker with stream type for proper pause behavior per mode (silence vs backpressure)
- Update all sources and sinks to pass `StreamType` when creating track boundaries
  - Radio Paradise, HTTP source → Continuous (infinite)
- Improve UPnP control architecture: pause sends silence for radio, blocks pipeline via backpressure for tracks
- Prepare groundwork for multi-client DSP architecture with shared source and per-DSP pipelines
2026-04-04 14:37:32 +02:00
0f0a8d1c91 deps: update esbuild to 0.27.4, rollup to 4.60.0, vite to 7.3.1
deps: update esbuild to 0.27.4, rollup to 4.60.0, vite to 7.3.1

- bump esbuild and all platform-specific binaries from 0.25.10 to 0.27.4
- bump rollup and all platform-specific binaries from 4.52.3 to 4.60.0
- bump vite from 7.1.7 to 7.3.1 (esbuild peer dep updated to ^0.27.0)
- bump dompurify from 3.2.7 to 3.3.3

web: improve cover image retry logic
- increase maxRetries default from 3 to 5
- reduce initial retryDelay from 1000ms to 500ms
- implement exponential backoff: delay = retryDelay * 2^(retryCount - 1)
- add detailed logging for retries and final failure

rust: minor cleanup
- remove unused imports (watch, Url, AudioSegment, SyncMarker)
- add tracing debug logs for cache file requests
- handle missing files gracefully with warning + client retry hint
- add #[allow(async_fn_in_trait)] where needed
2026-03-24 10:49:47 +01:00
d1be71ff47 Fix stream header invalidation and source task cleanup
Invalidate the cached OGG header immediately when restarting the FLAC encoder to prevent clients from receiving stale data.

Also improve the player source cleanup by draining the chunk receiver and adding a timeout when waiting for the emit task to finish, preventing potential hangs when the downstream pipeline is saturated.
2026-03-02 20:02:35 +01:00
2b0def806a Ajout de la gestion de la position en temps réel et amélioration de la gestion de la durée
Ajout de l'événement Position pour envoyer la position courante ~1/s pendant la lecture.

Modification de la gestion de la durée dans le registry pour ne pas écraser une durée déjà connue par la source (priorité à la source pour les flux radio).

Mise à jour du handler position_update pour utiliser update_duration au lieu de update_position, et suppression de la gestion de position_sec qui est maintenant gérée par PlayerEvent::Position.

Le serveur gère maintenant la position via les événements Position émis par PlayerSource, et la durée est uniquement utilisée comme fallback pour les sources sans durée connue.
2026-03-01 23:55:51 +01:00
f57754b5f8 Implémentation du PlayerSource pour le contrôle AVTransport UPnP
Ajout de PlayerSource avec contrôle complet AVTransport (Play/Pause/Stop/Seek/LoadUri) dans le pipeline audio

- Introduit PlayerSource comme nœud source audio avec gestion complète du cycle de vie UPnP
- Implémente les commandes LoadUri, LoadNextUri, Play, Pause, Stop, Seek
- Gestion des transitions gapless avec TrackBoundary pour un bitstream propre
- Révision du pipeline audio pour utiliser PlayerSource au lieu de la logique de contrôle existante
- Mise à jour des handlers UPnP pour utiliser PlayerHandle au lieu du canal de contrôle
- Suppression des anciennes commandes PipelineControl et logique de gestion de source
- Ajout de gestion d'événements PlayerEvent pour mise à jour de l'état UPnP
- Migration vers StreamingOggFlacSink pour la diffusion audio
2026-03-01 23:40:42 +01:00
306e691c61 Refactor WebRenderer to use server-side streaming with OGG-FLAC sink
This commit refactors the WebRenderer to use a server-side streaming architecture with OGG-FLAC sink instead of the previous WebSocket-based approach. The changes include:

- Replaced WebSocket communication with HTTP streaming using DirectOggFlacSink
- Implemented a new pipeline architecture with dedicated handlers for UPnP commands
- Added new modules for registration, registry, and streaming
- Updated the renderer to work with a pipeline control system
- Removed old WebSocket session management
- Added support for HTTP streaming with gapless playback
- Updated dependencies and features for the new architecture

The WebRenderer now acts as a MediaRenderer UPnP device that serves audio streams via HTTP endpoints, with commands relayed to the audio pipeline through a new control system.
2026-02-26 20:05:42 +01:00
ca36a102e5 Amélioration des pmoplaylist 2025-12-17 08:47:07 +01:00
0a03f72467 Changement du mécanisme d'attention sur les channels Radio Paradise. 2025-12-06 12:48:21 +01:00
9e8491710c debug du lecteur web 2025-12-06 12:48:21 +01:00
3d1673157b debug media server suite 2025-12-06 12:48:21 +01:00
e21fa5948e debug lectueur générique 2025-12-06 12:48:21 +01:00
9be6835ddc Ou encore un peu de factorisation dans les nœuds. 2025-11-17 22:21:56 +01:00
66416dafa8 Fin de la correction de l'implémentation par ChatGPT. 2025-11-16 21:34:16 +01:00
c81a4651d6 Simplification de la gestion des channels. 2025-11-16 08:34:20 +01:00
1c2d30cbe9 debuggage des stream 2025-11-15 12:21:30 +01:00
Claude
7e81a8e777 Add TimerNode for rate limiting and improve progressive cache handling
Changes:
- Add TimerNode (pmoaudio/src/nodes/timer_node.rs): Rate-limits audio chunk flow based on timestamps with configurable max_lead_time
- Integrate TimerNode into play_and_cache.rs pipeline: PlaylistSource → TimerNode (3s pacing) → AudioSink
- Improve EOF retry in playlist_source.rs: Wait for prebuffer (512KB) before decoding, retry on temporary EOF with 200ms delay
- Export TimerNode in pmoaudio lib.rs and nodes/mod.rs

Known issue: Cache files may still be truncated when TrackBoundary arrives before pump completes flushing.
This requires allowing parallel write tasks as suggested.
2025-11-07 13:44:25 +00:00
Claude
58e6753a81 Fix progressive cache: distinguish temporary EOF from real EOF
Problem:
- PlaylistSource reads cached files faster than FlacCacheSink writes them
- FLAC decoder encounters EOF and stops playback prematurely
- First track doesn't play completely (stops at prebuffer point ~600ms)
- Needed to differentiate:
  * Temporary EOF: file still being written (wait and retry)
  * Real EOF: file completely written (stop decoding)

Solution:
1. Added Cache::is_download_complete() method (pmocache/src/cache.rs:735)
   - Checks for existence of completion marker (.complete file)
   - Marker created only when file is fully written and closed
   - Fast synchronous check (no async overhead)

2. Modified decode_and_emit_track() (playlist_source.rs:337)
   - On EOF: check if completion marker exists
   - If no marker: file still being written → wait 50ms and retry read
   - If marker exists: file complete → finish decoding
   - Reduced wait from 100ms to 50ms for better responsiveness

Benefits:
 First track now plays completely (not just prebuffer portion)
 Progressive caching still works (playback starts at ~600ms)
 Proper EOF handling (no premature stops)
 Efficient polling (50ms retry interval)
 Works for both fresh downloads and cached files

Tested:
- Fresh download: EOF retries visible in logs every ~50ms
- File plays until completion marker created
- No premature track termination

Related to previous optimization (commit d8594e7) that made
prebuffer→playlist push immediate (76ms instead of 19s).
2025-11-07 13:10:35 +00:00
Claude
7fbb2c418b Fix progressive cache support in PlaylistSource
The PlaylistSource decoder was hitting EOF prematurely when reading
files that were still being downloaded (progressive cache). Instead
of stopping, it now checks if the download is still ongoing and waits
100ms before retrying.

This preserves the progressive cache behavior: playback can start as
soon as the prebuffer (512KB) is ready, and the decoder will
gracefully wait for more data to be written as the download continues.

Changes:
- Modified decode_and_emit_track() to accept cache and pk parameters
- When EOF is reached (read == 0), check if download is ongoing
- If download is ongoing, wait 100ms and retry instead of stopping
- Only break the loop when download is complete and EOF is reached

Fixes the issue where the decoder would stop prematurely on
partially downloaded files.
2025-11-07 05:58:27 +00:00
Claude
971f0ba9d6 test: Add comprehensive test coverage for PlaylistSource and ResamplingNode
This commit adds extensive unit and integration tests for the audio pipeline
components that were previously untested.

## ResamplingNode Tests (pmoaudio/src/nodes/resampling_node.rs)
- Added 7 test functions covering:
  - Helper function tests: extract_channels_i16/i24
  - Reconstruction tests: reconstruct_chunk_i16/i24
  - Logic tests: passthrough when sample rate matches
  - Async tests: verify sync markers pass through unchanged
  - Integration test: actual 44.1kHz → 48kHz resampling

## PlaylistSource Tests (pmoaudio-ext/src/sources/playlist_source.rs)
- Added 10 test functions covering:
  - Stream validation: valid/invalid channel counts and bit depths
  - PCM conversion: bytes_to_segment for I16/I24/I32 formats
  - Mono/stereo handling: verify channel duplication
  - Error handling: unsupported bit depth rejection
  - Type safety: compilation verification

## Bug Fixes
- Fixed imports: Node and NodeLogic moved from nodes to pipeline module
- Fixed AudioCache import: use pmoaudiocache::Cache with alias
- Fixed API calls in ResamplingNode:
  - BitDepth::from_audio_chunk() → match pattern
  - .stereo() → .get_frames()
  - .to_i32() → .as_i32() for I24
  - .sample_rate() → .get_sample_rate()

## Documentation
- Added INSTALL_LIBSOXR.md with detailed installation instructions
- Documents local libsoxr installation without sudo privileges
- Provides troubleshooting guide for build and test environments

All tests pass successfully (17 tests total: 7 ResamplingNode + 10 PlaylistSource).
2025-11-05 14:16:12 +00:00
Claude
6a7ba01102 feat: Add PlaylistSource and ResamplingNode for playlist playback
This commit implements a new audio source that reads from pmoplaylist
and streams tracks continuously, along with a resampling node to
normalize sample rates.

## New Components

### PlaylistSource (pmoaudio-ext)
- New source in pmoaudio-ext/src/sources/playlist_source.rs
- Reads from pmoplaylist ReadHandle
- Decodes tracks from audio cache (pmoaudiocache)
- Emits PCM with heterogeneous sample_rate and bit_depth
- Polls playlist when empty (configurable interval, default 100ms)
- Emits TrackBoundary markers between tracks
- Graceful shutdown with EndOfStream on stop
- Gated behind 'playlist' feature flag

**Design Philosophy:**
- Keeps each node simple (single responsibility)
- Emits raw PCM without format normalization
- Pipeline designer chooses how to handle heterogeneity
- Ideal for Radio Paradise (homogeneous streams)
- Requires ResamplingNode + ToI24Node for mixed playlists

### ResamplingNode (pmoaudio)
- Generic resampling node in pmoaudio/src/nodes/resampling_node.rs
- Normalizes variable sample rates to a target rate
- Uses libsoxr for high-quality resampling
- Automatically detects sample rate changes
- Recreates resampler as needed
- Preserves chunk type (I16/I24/I32/F32/F64)
- Quality adapts to bit depth (Medium/High/Very High)

## Architecture

PlaylistSource is placed in pmoaudio-ext to avoid circular dependencies:
- pmoaudio-ext depends on: pmoaudio, pmoplaylist, pmoaudiocache
- No reverse dependencies = clean dependency graph

## Configuration

### pmoaudio-ext/Cargo.toml
- Updated 'playlist' feature to include pmoaudiocache, pmocache, pmoflac
- Added sources module export

### pmoaudio
- Added resampling_node module
- Public export: ResamplingNode

## System Requirements

⚠️ **IMPORTANT**: libsoxr-dev must be installed for compilation

See INSTALL_NOTES.md for installation instructions per platform.

## Usage Example

```rust
// Radio Paradise (homogeneous 44.1kHz/16bit)
let mut source = PlaylistSource::new(playlist, cache);
let to_i24 = ToI24Node::new();
source.register(Box::new(to_i24));

// Mixed playlist (needs normalization)
let mut source = PlaylistSource::new(playlist, cache);
let mut resampler = ResamplingNode::new(48000);  // Force 48kHz
let to_i24 = ToI24Node::new();
source.register(Box::new(resampler));
resampler.register(Box::new(to_i24));
```

## Files Changed
- pmoaudio-ext/Cargo.toml: Update playlist feature
- pmoaudio-ext/src/lib.rs: Add sources module
- pmoaudio-ext/src/sources/mod.rs: New sources module
- pmoaudio-ext/src/sources/playlist_source.rs: New PlaylistSource (580 lines)
- pmoaudio/src/nodes/resampling_node.rs: New ResamplingNode (350 lines)
- pmoaudio/src/nodes/mod.rs: Register resampling_node
- pmoaudio/src/lib.rs: Export ResamplingNode
- INSTALL_NOTES.md: System requirements documentation

## Future Work
- GapInsertionNode (inserts silence between tracks)
- CrossfadeNode (fade-in/fade-out mixing)
- Examples (deferred until implementation validated)
2025-11-05 13:44:24 +00:00