avbridge 2.5.0 → 2.6.0

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.
@@ -33589,6 +33589,35 @@ async function loadBridge() {
33589
33589
  }
33590
33590
  }
33591
33591
 
33592
+ // src/util/time-ranges.ts
33593
+ function makeTimeRanges(ranges) {
33594
+ const frozen = ranges.slice();
33595
+ const impl = {
33596
+ get length() {
33597
+ return frozen.length;
33598
+ },
33599
+ start(index) {
33600
+ if (index < 0 || index >= frozen.length) {
33601
+ throw new DOMException(
33602
+ `TimeRanges.start: index ${index} out of range (length=${frozen.length})`,
33603
+ "IndexSizeError"
33604
+ );
33605
+ }
33606
+ return frozen[index][0];
33607
+ },
33608
+ end(index) {
33609
+ if (index < 0 || index >= frozen.length) {
33610
+ throw new DOMException(
33611
+ `TimeRanges.end: index ${index} out of range (length=${frozen.length})`,
33612
+ "IndexSizeError"
33613
+ );
33614
+ }
33615
+ return frozen[index][1];
33616
+ }
33617
+ };
33618
+ return impl;
33619
+ }
33620
+
33592
33621
  // src/strategies/hybrid/index.ts
33593
33622
  var READY_AUDIO_BUFFER_SECONDS = 0.3;
33594
33623
  var READY_TIMEOUT_SECONDS = 10;
@@ -33646,6 +33675,18 @@ async function createHybridSession(ctx, target, transport) {
33646
33675
  get: () => ctx.duration ?? NaN
33647
33676
  });
33648
33677
  }
33678
+ Object.defineProperty(target, "readyState", {
33679
+ configurable: true,
33680
+ get: () => {
33681
+ if (!renderer.hasFrames()) return 0;
33682
+ if (!audio.isPlaying() && audio.bufferAhead() <= 0 && !audio.isNoAudio()) return 1;
33683
+ return 2;
33684
+ }
33685
+ });
33686
+ Object.defineProperty(target, "seekable", {
33687
+ configurable: true,
33688
+ get: () => makeTimeRanges(ctx.duration && Number.isFinite(ctx.duration) && ctx.duration > 0 ? [[0, ctx.duration]] : [])
33689
+ });
33649
33690
  async function waitForBuffer() {
33650
33691
  const start = performance.now();
33651
33692
  while (true) {
@@ -33727,6 +33768,8 @@ async function createHybridSession(ctx, target, transport) {
33727
33768
  delete target.paused;
33728
33769
  delete target.volume;
33729
33770
  delete target.muted;
33771
+ delete target.readyState;
33772
+ delete target.seekable;
33730
33773
  } catch {
33731
33774
  }
33732
33775
  },
@@ -34250,6 +34293,18 @@ async function createFallbackSession(ctx, target, transport) {
34250
34293
  get: () => ctx.duration ?? NaN
34251
34294
  });
34252
34295
  }
34296
+ Object.defineProperty(target, "readyState", {
34297
+ configurable: true,
34298
+ get: () => {
34299
+ if (!renderer.hasFrames()) return 0;
34300
+ if (!audio.isPlaying() && audio.bufferAhead() <= 0 && !audio.isNoAudio()) return 1;
34301
+ return 2;
34302
+ }
34303
+ });
34304
+ Object.defineProperty(target, "seekable", {
34305
+ configurable: true,
34306
+ get: () => makeTimeRanges(ctx.duration && Number.isFinite(ctx.duration) && ctx.duration > 0 ? [[0, ctx.duration]] : [])
34307
+ });
34253
34308
  async function waitForBuffer() {
34254
34309
  const start = performance.now();
34255
34310
  let firstFrameAtMs = 0;
@@ -34352,6 +34407,8 @@ async function createFallbackSession(ctx, target, transport) {
34352
34407
  delete target.paused;
34353
34408
  delete target.volume;
34354
34409
  delete target.muted;
34410
+ delete target.readyState;
34411
+ delete target.seekable;
34355
34412
  } catch {
34356
34413
  }
34357
34414
  },
@@ -34978,7 +35035,13 @@ var AvbridgeVideoElement = class extends HTMLElementCtor {
34978
35035
  _strategy = null;
34979
35036
  _strategyClass = null;
34980
35037
  _audioTracks = [];
35038
+ /** Subtitle tracks reported by the active UnifiedPlayer (options.subtitles
35039
+ * + embedded container tracks + programmatic addSubtitle calls). */
34981
35040
  _subtitleTracks = [];
35041
+ /** Subtitle tracks derived from light-DOM `<track>` children. Maintained
35042
+ * by _syncTextTracks on every mutation. Merged into the public
35043
+ * `subtitleTracks` getter so the player's settings menu sees them. */
35044
+ _htmlTrackInfo = [];
34982
35045
  /**
34983
35046
  * External subtitle list forwarded to `createPlayer()` on the next
34984
35047
  * bootstrap. Setting this after bootstrap queues it for the next
@@ -35098,12 +35161,28 @@ var AvbridgeVideoElement = class extends HTMLElementCtor {
35098
35161
  _syncTextTracks() {
35099
35162
  const existing = this._videoEl.querySelectorAll("track");
35100
35163
  for (const t of Array.from(existing)) t.remove();
35164
+ this._htmlTrackInfo = [];
35165
+ let htmlIdx = 0;
35101
35166
  for (const child of Array.from(this.children)) {
35102
35167
  if (child.tagName === "TRACK") {
35103
- const clone = child.cloneNode(true);
35168
+ const track = child;
35169
+ const clone = track.cloneNode(true);
35104
35170
  this._videoEl.appendChild(clone);
35171
+ const src = track.getAttribute("src") ?? void 0;
35172
+ const format = src?.toLowerCase().endsWith(".srt") ? "srt" : "vtt";
35173
+ this._htmlTrackInfo.push({
35174
+ id: 1e4 + htmlIdx,
35175
+ format,
35176
+ language: track.srclang || track.getAttribute("label") || void 0,
35177
+ sidecarUrl: src
35178
+ });
35179
+ htmlIdx++;
35105
35180
  }
35106
35181
  }
35182
+ this._dispatch("trackschange", {
35183
+ audioTracks: this._audioTracks,
35184
+ subtitleTracks: this.subtitleTracks
35185
+ });
35107
35186
  }
35108
35187
  /** Internal src setter — separate from the property setter so the
35109
35188
  * attributeChangedCallback can use it without re-entering reflection. */
@@ -35431,7 +35510,7 @@ var AvbridgeVideoElement = class extends HTMLElementCtor {
35431
35510
  return this._audioTracks;
35432
35511
  }
35433
35512
  get subtitleTracks() {
35434
- return this._subtitleTracks;
35513
+ return this._htmlTrackInfo.length === 0 ? this._subtitleTracks : [...this._subtitleTracks, ...this._htmlTrackInfo];
35435
35514
  }
35436
35515
  /**
35437
35516
  * External subtitle files to attach when the source loads. Takes effect
@@ -35520,6 +35599,12 @@ var AvbridgeVideoElement = class extends HTMLElementCtor {
35520
35599
  getDiagnostics() {
35521
35600
  return this._player?.getDiagnostics() ?? null;
35522
35601
  }
35602
+ addEventListener(type, listener, options) {
35603
+ super.addEventListener(type, listener, options);
35604
+ }
35605
+ removeEventListener(type, listener, options) {
35606
+ super.removeEventListener(type, listener, options);
35607
+ }
35523
35608
  // ── Event helpers ──────────────────────────────────────────────────────
35524
35609
  _dispatch(name, detail) {
35525
35610
  this.dispatchEvent(new CustomEvent(name, { detail, bubbles: false }));