@lox-audioserver/node-librespot 0.4.0 → 0.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lox-audioserver/node-librespot",
3
- "version": "0.4.0",
3
+ "version": "0.4.1",
4
4
  "description": "Node.js bindings for librespot (Spotify Connect) via N-API with prebuild support.",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
package/src/lib.rs CHANGED
@@ -513,6 +513,11 @@ impl Sink for ChannelSink {
513
513
  }
514
514
 
515
515
  fn stop(&mut self) -> SinkResult<()> {
516
+ // Reset pacing so the next start() (e.g. after Connect pause) is paced from now,
517
+ // not from the original stream_start. Without this the post-resume catch-up logic
518
+ // forwards minutes of decoded PCM at full speed.
519
+ self.start = None;
520
+ self.expected_elapsed = Duration::from_millis(0);
516
521
  Ok(())
517
522
  }
518
523
 
@@ -606,10 +611,20 @@ impl Sink for ChannelSink {
606
611
  if self.tx.try_send(bytes).is_err() {
607
612
  // Drop chunk if JS side is backpressured to avoid blocking the player thread.
608
613
  }
609
- let start = self.start.get_or_insert_with(Instant::now);
610
- self.expected_elapsed += duration;
611
- let target = *start + self.expected_elapsed;
612
614
  let now = Instant::now();
615
+ // If wall-clock has drifted far ahead of our expected timeline (a pause that didn't
616
+ // route through stop()/start(), a decoder stall, etc.), rebase pacing onto `now`.
617
+ // Otherwise `sleep_dur` saturates to 0 for the duration of the gap and the sink
618
+ // dumps the catch-up backlog at full speed downstream.
619
+ if let Some(start) = self.start {
620
+ if now > start + self.expected_elapsed + Duration::from_millis(200) {
621
+ self.start = None;
622
+ self.expected_elapsed = Duration::from_millis(0);
623
+ }
624
+ }
625
+ let start = *self.start.get_or_insert(now);
626
+ self.expected_elapsed += duration;
627
+ let target = start + self.expected_elapsed;
613
628
  let sleep_dur = target.saturating_duration_since(now);
614
629
  if !sleep_dur.is_zero() {
615
630
  sleep(sleep_dur);