eb-player 2.0.17 → 2.0.18

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.
@@ -4,7 +4,7 @@
4
4
  (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.EBPlayer = {}));
5
5
  })(this, (function (exports) { 'use strict';
6
6
 
7
- var __EB_PLAYER_VERSION__ = "2.0.17";
7
+ var __EB_PLAYER_VERSION__ = "2.0.18";
8
8
 
9
9
  /**
10
10
  * Finite State Machine for player playback state transitions.
@@ -19,7 +19,10 @@
19
19
  * - idle -> loading: initial load or post-stall reload
20
20
  * - loading -> playing | error: stream starts or fails
21
21
  * - playing -> paused | buffering | ended | error: normal playback events
22
- * - paused -> playing | loading | idle: resume or stop
22
+ * - paused -> playing | loading | idle | buffering: resume or stop
23
+ * - paused -> buffering is needed when resuming a paused (live) stream where
24
+ * the browser fires 'waiting' before 'playing' (Safari live segment edge);
25
+ * without it the FSM strands at 'paused' while the video actually plays
23
26
  * - buffering -> playing | paused | idle | error: buffer recovered, user pause, or stall
24
27
  * - buffering -> idle is needed for the stall-watchdog recovery path (kick off reload)
25
28
  * - buffering -> paused is needed for live stream support (user pauses during buffer)
@@ -30,7 +33,7 @@
30
33
  idle: ['loading'],
31
34
  loading: ['playing', 'buffering', 'paused', 'error', 'idle'],
32
35
  playing: ['paused', 'buffering', 'ended', 'error', 'idle'],
33
- paused: ['playing', 'loading', 'idle'],
36
+ paused: ['playing', 'loading', 'idle', 'buffering'],
34
37
  buffering: ['playing', 'paused', 'idle', 'error'],
35
38
  error: ['loading', 'idle'],
36
39
  ended: ['loading', 'idle']
@@ -175,7 +178,11 @@
175
178
  if (previousValue === value) {
176
179
  return true;
177
180
  }
178
- rawTarget[String(key)] = value;
181
+ // Assign and notify subscribers.
182
+ // Cast the typed StateMap target to a mutable record so the unknown value
183
+ // can be written through the Proxy set trap.
184
+ const writable = rawTarget;
185
+ writable[String(key)] = value;
179
186
  impl.notify(key, value, previousValue);
180
187
  return true;
181
188
  }
@@ -2794,8 +2801,8 @@
2794
2801
  }, { signal: this.signal });
2795
2802
  }
2796
2803
  template() {
2797
- const playlist = this.state?.playlist ?? [];
2798
- const currentEpisode = this.state?.currentEpisode ?? 0;
2804
+ const playlist = this.state.playlist;
2805
+ const currentEpisode = this.state.currentEpisode;
2799
2806
  if (playlist.length === 0)
2800
2807
  return b ``;
2801
2808
  return b `
@@ -2861,7 +2868,7 @@
2861
2868
  }, { signal: this.signal });
2862
2869
  }
2863
2870
  template() {
2864
- const programs = this.state?.epgPrograms ?? [];
2871
+ const programs = this.state.epgPrograms;
2865
2872
  return b `
2866
2873
  <div class="eb-snrt-carousel">
2867
2874
  ${programs.map((program) => b `
@@ -5471,6 +5478,9 @@
5471
5478
  if (this.state) {
5472
5479
  this.state.error = message;
5473
5480
  }
5481
+ // hls.js nulls its media on a fatal keySystemError; signal so the
5482
+ // P2P SDK is torn down before it loops on a null media element.
5483
+ this.bus?.emit('error-fatal', { code: 'DRM', message });
5474
5484
  }
5475
5485
  });
5476
5486
  }
@@ -6185,12 +6195,23 @@
6185
6195
  this.lib.start();
6186
6196
  // Clean up on abort
6187
6197
  signal.addEventListener('abort', () => {
6188
- if (this.lib !== null && typeof this.lib.stop === 'function') {
6189
- this.lib.stop();
6190
- }
6191
- this.lib = null;
6198
+ this.stop();
6192
6199
  }, { once: true });
6193
6200
  }
6201
+ /**
6202
+ * Stop and detach the P2P SDK. Idempotent.
6203
+ *
6204
+ * Called on AbortSignal teardown, and eagerly on an unrecoverable engine
6205
+ * error: hls.js nulls its media element on a fatal keySystemError, so a
6206
+ * still-running eblib instance would keep polling `media.currentTime` and
6207
+ * throw in a loop until full dispose.
6208
+ */
6209
+ stop() {
6210
+ if (this.lib !== null && typeof this.lib.stop === 'function') {
6211
+ this.lib.stop();
6212
+ }
6213
+ this.lib = null;
6214
+ }
6194
6215
  }
6195
6216
 
6196
6217
  /**
@@ -6512,6 +6533,7 @@
6512
6533
  inst.engine.detach();
6513
6534
  inst.engine = null;
6514
6535
  }
6536
+ inst.p2p = null;
6515
6537
  inst.controller.dispose();
6516
6538
  }
6517
6539
  // ---------------------------------------------------------------------------
@@ -6583,6 +6605,7 @@
6583
6605
  controller,
6584
6606
  engine: null,
6585
6607
  snapshotDestroy: null,
6608
+ p2p: null,
6586
6609
  container
6587
6610
  };
6588
6611
  instances.set(container, inst);
@@ -6606,7 +6629,10 @@
6606
6629
  // P2P integration: wire EasyBroadcast SDK when config.lib and config.manager are set
6607
6630
  if (mergedConfig.lib && mergedConfig.manager && video !== null) {
6608
6631
  const isDash = src.includes('.mpd') && mergedConfig.dashjs !== false;
6632
+ // Stop any P2P SDK from a previous open() before attaching a new one
6633
+ inst.p2p?.stop();
6609
6634
  const p2pManager = new P2PManager();
6635
+ inst.p2p = p2pManager;
6610
6636
  // Wait for the engine driver to be created before integrating P2P
6611
6637
  engine.driverReady.then(() => {
6612
6638
  return p2pManager.integrate({
@@ -6732,6 +6758,13 @@
6732
6758
  }, 2000);
6733
6759
  }, 500);
6734
6760
  });
6761
+ // On an unrecoverable engine error (e.g. fatal DRM keySystemError), tear down
6762
+ // the P2P SDK. hls.js nulls its media element, so a still-running eblib would
6763
+ // otherwise loop on `media.currentTime`. The engine has already surfaced the
6764
+ // clean error via state.error and stopped its stall watchdog.
6765
+ controller.bus.on('error-fatal', () => {
6766
+ inst.p2p?.stop();
6767
+ }, { signal: controller.signal });
6735
6768
  // Auto-open the stream if src is provided in config (matches legacy player behaviour
6736
6769
  // where consumers call start({ src: '...' }) and expect playback to begin immediately).
6737
6770
  // When autoplay is false, defer open() until the user requests play — this avoids
@@ -6802,7 +6835,8 @@
6802
6835
  // ---------------------------------------------------------------------------
6803
6836
  if (typeof window !== 'undefined') {
6804
6837
  console.info(`%cEBPlayer v${VERSION}`, 'color: #1FA9DD; font-weight: bold');
6805
- window.EBPlayer = { start, stop, destroy, AVAILABLE_THEMES, THEME_LAYOUTS, version: VERSION };
6838
+ const win = window;
6839
+ win.EBPlayer = { start, stop, destroy, AVAILABLE_THEMES, THEME_LAYOUTS, version: VERSION };
6806
6840
  }
6807
6841
 
6808
6842
  /**