ngx-kit 7.3.3 → 7.4.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.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ngx-kit-media-control.mjs","sources":["../../../projects/libs/media-control/utils/format-time.ts","../../../projects/libs/media-control/contracts/media-source.ts","../../../projects/libs/media-control/contracts/media-state.ts","../../../projects/libs/media-control/contracts/media-error.ts","../../../projects/libs/media-control/utils/capabilities.ts","../../../projects/libs/media-control/engines/native-media-engine.ts","../../../projects/libs/media-control/decoders/decoder.tokens.ts","../../../projects/libs/media-control/engines/media-engine-factory.ts","../../../projects/libs/media-control/facade/media-session.ts","../../../projects/libs/media-control/audio/web-audio-graph.ts","../../../projects/libs/media-control/decoders/decoder-registry.ts","../../../projects/libs/media-control/facade/ngx-media-facade.ts","../../../projects/libs/media-control/components/ngx-media-control.ts","../../../projects/libs/media-control/components/ngx-media-control.html","../../../projects/libs/media-control/decoders/wasm-decoder.base.ts","../../../projects/libs/media-control/providers/provide-ngx-media.ts","../../../projects/libs/media-control/public-api.ts","../../../projects/libs/media-control/ngx-kit-media-control.ts"],"sourcesContent":["/**\r\n * Format time in seconds as MM:SS\r\n * @param seconds number\r\n * @returns MM:SS\r\n */\r\nexport function formatTime(seconds: number) {\r\n if (Number.isNaN(+seconds) || seconds == Infinity) {\r\n seconds = 0; // return 'Unknown';\r\n }\r\n const minutes = Math.floor(seconds / 60);\r\n const remainingSeconds = Math.floor(seconds % 60);\r\n return `${minutes.toString().padStart(2, '0')}:${remainingSeconds.toString().padStart(2, '0')}`;\r\n}","/**\n * A single playable media item.\n *\n * `src` intentionally accepts the shapes a consumer already has lying around:\n * a remote/relative URL string, a `Blob`/`File` (turned into an object URL\n * internally and revoked on teardown), or a live `MediaStream`.\n */\nexport interface NgxMediaSource {\n /** Playback source. */\n src: string | Blob | File | MediaStream;\n /** MIME type, e.g. `audio/mpeg`, `video/mp4`. Helps capability detection avoid guessing from the extension. */\n type?: string;\n /** Optional codec string per RFC 6381, e.g. `avc1.42E01E,mp4a.40.2`. */\n codecs?: string;\n /** Display metadata, also used for Media Session integration. */\n title?: string;\n artist?: string;\n album?: string;\n /** Poster image for video. */\n poster?: string;\n /**\n * Separate download target. If omitted, falls back to `src` (only when\n * `src` is a string — Blob/File/MediaStream have no meaningful download URL\n * unless one is provided here).\n */\n downloadUrl?: string;\n /** Suggested file name for the download action. */\n downloadFileName?: string;\n /** Headers to send when the engine has to fetch this source itself (e.g. duration probing, WASM decoding). */\n requestHeaders?: HeadersInit;\n}\n\n/** A queue of sources plus the active index. Replaces the old bare `PlayList[]`. */\nexport interface NgxMediaPlaylist {\n items: NgxMediaSource[];\n currentIndex: number;\n}\n\n/**\n * @deprecated Use {@link NgxMediaSource} instead. Kept so existing `PlayList[]`\n * consumers keep compiling; `fileAddress`/`title` map 1:1 onto `src`/`title`.\n */\nexport class PlayList {\n title!: string;\n fileAddress!: string;\n}\n\nexport function playListToMediaSource(item: PlayList): NgxMediaSource {\n return { src: item.fileAddress, title: item.title };\n}\n\n/**\n * Content equality for `NgxMediaSource`/playlist arrays, not reference\n * equality. `src` strings compare by value; `Blob`/`File`/`MediaStream`\n * compare by identity (they can't be compared by content cheaply/safely).\n *\n * Every field that can change *downstream behavior* is compared —\n * `artist`/`album`/`poster` feed Media Session metadata, `downloadUrl`/\n * `downloadFileName` change what the download button actually does, and\n * `requestHeaders` changes what bytes a server returns for the same URL.\n * Fields that are purely cosmetic and never drive a decision (there\n * currently are none — if you add one, document why it's excluded here).\n *\n * This exists specifically so a consumer that re-creates an equivalent\n * array/object literal on every change-detection cycle (`[sources]=\"[{...}]\"`,\n * or a `.map()` derived from an otherwise-stable list) doesn't cause the\n * player to treat it as \"a new playlist\" and reload media on every tick —\n * see `computed(..., { equal: mediaSourcesEqual })` in `NgxMediaControl` and\n * the same guard in `NgxMediaFacade.setPlaylist`.\n */\nexport function mediaSourcesEqual(\n a: readonly NgxMediaSource[],\n b: readonly NgxMediaSource[],\n): boolean {\n if (a === b) return true;\n if (a.length !== b.length) return false;\n for (let i = 0; i < a.length; i++) {\n if (!mediaSourceEqual(a[i], b[i])) return false;\n }\n return true;\n}\n\nfunction mediaSourceEqual(a: NgxMediaSource, b: NgxMediaSource): boolean {\n if (a === b) return true;\n return (\n a.src === b.src && // strings compare by value; Blob/File/MediaStream by identity — both correct via `===`\n a.type === b.type &&\n a.codecs === b.codecs &&\n a.title === b.title &&\n a.artist === b.artist &&\n a.album === b.album &&\n a.poster === b.poster &&\n a.downloadUrl === b.downloadUrl &&\n a.downloadFileName === b.downloadFileName &&\n headersEqual(a.requestHeaders, b.requestHeaders)\n );\n}\n\nfunction headersEqual(a?: HeadersInit, b?: HeadersInit): boolean {\n if (a === b) return true;\n if (!a || !b) return false;\n const na = normalizeHeaders(a);\n const nb = normalizeHeaders(b);\n if (na.length !== nb.length) return false;\n for (let i = 0; i < na.length; i++) {\n if (na[i][0] !== nb[i][0] || na[i][1] !== nb[i][1]) return false;\n }\n return true;\n}\n\nfunction normalizeHeaders(h: HeadersInit): [string, string][] {\n const entries: [string, string][] =\n h instanceof Headers ? Array.from(h.entries()) : Array.isArray(h) ? (h as [string, string][]) : Object.entries(h as Record<string, string>);\n return entries.map(([k, v]) => [k.toLowerCase(), v] as [string, string]).sort((x, y) => (x[0] < y[0] ? -1 : x[0] > y[0] ? 1 : 0));\n}\n\n/**\n * Derives a display file name from a source, tolerating everything a real\n * URL can throw at `decodeURIComponent` (malformed `%` sequences, stray\n * `#`/`?`) instead of letting the player crash just because it tried to\n * make a pretty label. Never throws.\n */\nexport function extractMediaFileName(source: Pick<NgxMediaSource, 'src' | 'title'>): string {\n if (source.title) return source.title;\n if (typeof source.src !== 'string') {\n if (source.src instanceof File && source.src.name) return source.src.name;\n return 'no name';\n }\n try {\n const withoutHash = source.src.split('#')[0];\n const withoutQuery = withoutHash.split('?')[0];\n const lastSegment = withoutQuery.replace(/\\\\/g, '/').split('/').filter(Boolean).pop();\n if (!lastSegment) return 'no name';\n try {\n return decodeURIComponent(lastSegment);\n } catch {\n // Malformed percent-encoding (e.g. a lone \"%\" or \"%zz\") — fall back to\n // the raw, un-decoded segment rather than throwing.\n return lastSegment;\n }\n } catch {\n return 'no name';\n }\n}\n","/**\n * Exhaustive playback state machine. Only one state is active at a time;\n * transient conditions (buffering while playing, seeking while paused) are\n * modeled as their own states rather than boolean flags layered on top of\n * `playing`/`paused`, so `playing + destroyed` etc. cannot occur.\n */\nexport type NgxMediaPlaybackState =\n | 'idle'\n | 'loading'\n | 'ready'\n | 'playing'\n | 'paused'\n | 'buffering'\n | 'seeking'\n | 'ended'\n | 'error'\n | 'destroyed';\n\nexport interface NgxTimeRange {\n start: number;\n end: number;\n}\n\n/** Read-only snapshot of engine state, exposed to the UI as a signal. */\nexport interface NgxMediaState {\n playback: NgxMediaPlaybackState;\n currentTime: number;\n duration: number;\n buffered: readonly NgxTimeRange[];\n volume: number;\n muted: boolean;\n playbackRate: number;\n /** Only meaningful for video engines; undefined for audio-only. */\n videoWidth?: number;\n videoHeight?: number;\n}\n\nexport function initialMediaState(): NgxMediaState {\n return {\n playback: 'idle',\n currentTime: 0,\n duration: 0,\n buffered: [],\n volume: 1,\n muted: false,\n playbackRate: 1,\n };\n}\n\nconst VALID_TRANSITIONS: Record<NgxMediaPlaybackState, ReadonlySet<NgxMediaPlaybackState>> = {\n idle: new Set(['loading', 'destroyed']),\n loading: new Set(['ready', 'buffering', 'error', 'destroyed']),\n ready: new Set(['playing', 'seeking', 'loading', 'error', 'destroyed']),\n playing: new Set(['paused', 'buffering', 'seeking', 'ended', 'error', 'destroyed']),\n paused: new Set(['playing', 'seeking', 'loading', 'error', 'destroyed']),\n buffering: new Set(['playing', 'paused', 'error', 'destroyed']),\n seeking: new Set(['playing', 'paused', 'error', 'destroyed']),\n ended: new Set(['loading', 'playing', 'destroyed']),\n error: new Set(['loading', 'idle', 'destroyed']),\n destroyed: new Set([]),\n};\n\n/** Guards against illegal transitions (e.g. anything -> playing after destroyed). */\nexport function canTransition(from: NgxMediaPlaybackState, to: NgxMediaPlaybackState): boolean {\n if (from === to) return true;\n return VALID_TRANSITIONS[from].has(to);\n}\n","export type NgxMediaErrorCategory =\n | 'NETWORK'\n | 'UNSUPPORTED_FORMAT'\n | 'DECODER'\n | 'ABORTED'\n | 'AUTOPLAY_BLOCKED'\n | 'MEDIA'\n | 'PERMISSION'\n | 'BROWSER_UNSUPPORTED'\n | 'UNKNOWN';\n\nexport class NgxMediaError extends Error {\n constructor(\n readonly category: NgxMediaErrorCategory,\n message: string,\n /** Original DOM/browser error, if any — kept for `console.error`/telemetry, not surfaced to templates by default. */\n override readonly cause?: unknown,\n ) {\n super(message);\n this.name = 'NgxMediaError';\n }\n\n static fromMediaElementError(el: HTMLMediaElement): NgxMediaError {\n const err = el.error;\n const noSource = el.networkState === HTMLMediaElement.NETWORK_NO_SOURCE;\n if (noSource) {\n return new NgxMediaError('NETWORK', 'Could not load media source.', err);\n }\n switch (err?.code) {\n case MediaError.MEDIA_ERR_ABORTED:\n return new NgxMediaError('ABORTED', 'Media playback was aborted.', err);\n case MediaError.MEDIA_ERR_NETWORK:\n return new NgxMediaError('NETWORK', 'A network error interrupted media loading.', err);\n case MediaError.MEDIA_ERR_DECODE:\n return new NgxMediaError('DECODER', 'The media could not be decoded.', err);\n case MediaError.MEDIA_ERR_SRC_NOT_SUPPORTED:\n return new NgxMediaError('UNSUPPORTED_FORMAT', 'This media format/source is not supported.', err);\n default:\n return new NgxMediaError('UNKNOWN', 'An unknown media error occurred.', err);\n }\n }\n\n static autoplayBlocked(cause?: unknown): NgxMediaError {\n return new NgxMediaError(\n 'AUTOPLAY_BLOCKED',\n 'Playback was blocked by the browser autoplay policy; a user gesture is required.',\n cause,\n );\n }\n\n static unsupported(message: string): NgxMediaError {\n return new NgxMediaError('BROWSER_UNSUPPORTED', message);\n }\n\n static noDecoder(source: string): NgxMediaError {\n return new NgxMediaError(\n 'UNSUPPORTED_FORMAT',\n `No native support and no registered NGX_MEDIA_DECODER can handle \"${source}\".`,\n );\n }\n}\n","import { NgxMediaSource } from '../contracts/media-source';\n\n/** True only in a real browser context — guards every browser API access for SSR. */\nexport function isBrowser(): boolean {\n return typeof window !== 'undefined' && typeof document !== 'undefined';\n}\n\nexport function hasMediaSource(): boolean {\n return isBrowser() && 'MediaSource' in window;\n}\n\nexport function hasAudioContext(): boolean {\n return isBrowser() && ('AudioContext' in window || 'webkitAudioContext' in (window as any));\n}\n\nexport function getAudioContextCtor(): typeof AudioContext | undefined {\n if (!hasAudioContext()) return undefined;\n return (window as any).AudioContext ?? (window as any).webkitAudioContext;\n}\n\nexport function hasMediaSession(): boolean {\n return isBrowser() && 'mediaSession' in navigator;\n}\n\nexport function hasPictureInPicture(): boolean {\n return (\n isBrowser() &&\n typeof HTMLVideoElement !== 'undefined' &&\n 'requestPictureInPicture' in HTMLVideoElement.prototype &&\n // Safari exposes a document-level flag too; either is sufficient.\n (document as any).pictureInPictureEnabled !== false\n );\n}\n\nexport function hasFullscreen(): boolean {\n return isBrowser() && (document.fullscreenEnabled || (document as any).webkitFullscreenEnabled);\n}\n\n/**\n * Best-effort container/codec detection using `canPlayType`. Never trusts the\n * file extension alone: extension is only a last-resort hint when neither\n * `type` nor `codecs` was supplied.\n */\nexport function canPlayNatively(\n el: HTMLMediaElement,\n source: NgxMediaSource,\n): 'probably' | 'maybe' | '' {\n const mime = resolveMimeType(source);\n if (!mime) return 'maybe'; // unknown — let the native element try; it will fail fast via the `error` event if wrong.\n return el?.canPlayType(mime) as 'probably' | 'maybe' | '';\n}\n\nfunction resolveMimeType(source: NgxMediaSource): string | undefined {\n if (source.type) {\n return source.codecs ? `${source.type}; codecs=\"${source.codecs}\"` : source.type;\n }\n if (typeof source.src === 'string') {\n return extensionToMime(source.src);\n }\n if (source.src instanceof File && source.src.type) {\n return source.src.type;\n }\n if (source.src instanceof Blob && source.src.type) {\n return source.src.type;\n }\n return undefined;\n}\n\nconst EXT_MIME_MAP: Record<string, string> = {\n mp3: 'audio/mpeg',\n aac: 'audio/aac',\n wav: 'audio/wav',\n ogg: 'audio/ogg',\n oga: 'audio/ogg',\n opus: 'audio/ogg; codecs=opus',\n flac: 'audio/flac',\n m4a: 'audio/mp4',\n weba: 'audio/webm',\n mp4: 'video/mp4',\n m4v: 'video/mp4',\n webm: 'video/webm',\n mov: 'video/quicktime',\n ogv: 'video/ogg',\n};\n\n/** Extension is only ever a weak fallback hint, never treated as ground truth. */\nfunction extensionToMime(src: string): string | undefined {\n const clean = src.split(/[?#]/)[0];\n const ext = clean.split('.').pop()?.toLowerCase();\n return ext ? EXT_MIME_MAP[ext] : undefined;\n}\n","import { signal, Signal } from '@angular/core';\nimport { NgxMediaSource } from '../contracts/media-source';\nimport { initialMediaState, NgxMediaState, NgxTimeRange } from '../contracts/media-state';\nimport { NgxMediaError } from '../contracts/media-error';\nimport { NgxMediaEngine, NgxMediaKind } from './media-engine.interface';\nimport { canPlayNatively, getAudioContextCtor } from '../utils/capabilities';\n\ntype NativeLoadState = 'idle' | 'loading' | 'ready';\n\n/**\n * Source identity, not just a URL string: two loads with the same URL but\n * different `requestHeaders` MUST be treated as different sources (the\n * bytes the server returns can differ), while two loads with a fresh but\n * distinct `Blob`/`File`/`MediaStream` are only \"the same\" if it's the\n * literal same object reference — there's no cheap, safe way to diff their\n * content.\n */\ntype SourceIdentity =\n { kind: 'url'; key: string } | { kind: 'ref'; ref: Blob | File | MediaStream };\n\nfunction headersKey(headers?: HeadersInit): string {\n if (!headers) return '';\n const entries: [string, string][] =\n headers instanceof Headers\n ? Array.from(headers.entries())\n : Array.isArray(headers)\n ? (headers as [string, string][])\n : Object.entries(headers as Record<string, string>);\n return entries\n .map(([k, v]) => `${k.toLowerCase()}=${v}`)\n .sort()\n .join('&');\n}\n\nfunction computeIdentity(source: NgxMediaSource): SourceIdentity {\n if (typeof source.src === 'string') {\n return { kind: 'url', key: `${source.src}::${headersKey(source.requestHeaders)}` };\n }\n return { kind: 'ref', ref: source.src };\n}\n\nfunction sameIdentity(a: SourceIdentity | null, b: SourceIdentity | null): boolean {\n if (!a || !b || a.kind !== b.kind) return false;\n return a.kind === 'url'\n ? a.key === (b as { key: string }).key\n : a.ref === (b as { ref: unknown }).ref;\n}\n\nfunction rangesEqual(a: readonly NgxTimeRange[], b: readonly NgxTimeRange[]): boolean {\n if (a.length !== b.length) return false;\n for (let i = 0; i < a.length; i++) {\n if (a[i].start !== b[i].start || a[i].end !== b[i].end) return false;\n }\n return true;\n}\n\n/**\n * Default fast-path engine: plays through a real `<audio>`/`<video>` element.\n * Zero WASM, zero MediaSource — the browser's own decode pipeline does the work.\n *\n * Load semantics (the part that matters most for network behavior):\n * - `load()` is a real 3-state machine (idle/loading/ready) keyed on\n * {@link SourceIdentity}, not just a `readyState` snapshot:\n * same source + currently loading -> returns the SAME in-flight promise\n * same source + already loaded -> resolves immediately, no `el.load()` call\n * different source -> proceeds; the browser's own load\n * algorithm aborts whatever the\n * element was doing before\n * - Setting `el.src` already queues the browser's media load algorithm;\n * the immediate `el.load()` call right after does not cause a second\n * network request — its purpose is to make the abort-then-restart\n * synchronous (needed for older WebKit), not to \"load twice\". The state\n * machine above is what actually prevents redundant fetches across\n * repeated `load()` calls for the same source.\n *\n * Performance notes:\n * - `timeupdate`/`progress`/etc. fire far more often than the UI needs to\n * re-render; listeners run via `runOutsideAngular`, and `patch()` skips\n * the signal write entirely when nothing actually changed (including a\n * content-equal `buffered` array, which would otherwise allocate and\n * write on every `progress` tick even when the ranges didn't move).\n */\nexport class NativeMediaEngine implements NgxMediaEngine {\n readonly id = 'native';\n readonly kind: NgxMediaKind;\n\n private readonly _state = signal<NgxMediaState>(initialMediaState());\n readonly state: Signal<NgxMediaState> = this._state.asReadonly();\n\n private readonly el: HTMLMediaElement;\n private objectUrl: string | null = null;\n private destroyed = false;\n private readonly cleanupFns: Array<() => void> = [];\n\n private loadState: NativeLoadState = 'idle';\n private loadedIdentity: SourceIdentity | null = null;\n private pendingLoad: Promise<void> | null = null;\n private activeLoadController: AbortController | null = null;\n\n constructor(\n kind: NgxMediaKind,\n /** Provided by the facade so listener callbacks never re-enter Angular's zone. */\n private readonly runOutsideAngular: <T>(fn: () => T) => T = (fn) => fn(),\n existingElement?: HTMLMediaElement,\n preload: 'none' | 'metadata' | 'auto' = 'metadata',\n ) {\n this.kind = kind;\n this.el = existingElement ?? (document.createElement(kind) as HTMLMediaElement);\n this.el.preload = preload;\n this.el.setAttribute('playsinline', 'true');\n this.attachListeners();\n }\n\n get mediaElement(): HTMLMediaElement {\n return this.el;\n }\n\n async load(source: NgxMediaSource, abort?: AbortSignal): Promise<void> {\n this.assertNotDestroyed();\n const identity = computeIdentity(source);\n\n if (sameIdentity(identity, this.loadedIdentity)) {\n if (this.loadState === 'loading' && this.pendingLoad) {\n // Same source, still in flight — hand back the SAME promise instead\n // of starting a second (redundant) load for something already underway.\n return this.pendingLoad;\n }\n if (this.loadState === 'ready') {\n // Same source, already fully loaded — nothing to do, no `el.load()` call.\n return Promise.resolve();\n }\n }\n\n // A different source supersedes the previous load even when the caller\n // didn't provide/abort its own signal. This prevents stale\n // loadedmetadata/error events from resolving the new request.\n this.activeLoadController?.abort();\n const controller = new AbortController();\n const onExternalAbort = () => controller.abort();\n if (abort?.aborted) controller.abort();\n else abort?.addEventListener('abort', onExternalAbort, { once: true });\n\n const promise: Promise<void> = this.performLoad(source, identity, controller.signal).finally(\n () => {\n abort?.removeEventListener('abort', onExternalAbort);\n if (this.pendingLoad === promise) this.pendingLoad = null;\n if (this.activeLoadController === controller) this.activeLoadController = null;\n },\n );\n this.activeLoadController = controller;\n this.pendingLoad = promise;\n return promise;\n }\n\n private async performLoad(\n source: NgxMediaSource,\n identity: SourceIdentity,\n abort?: AbortSignal,\n ): Promise<void> {\n this.loadedIdentity = identity;\n this.loadState = 'loading';\n this.releaseObjectUrl();\n this.patch({ playback: 'loading', currentTime: 0, duration: 0, buffered: [] });\n\n try {\n if (abort?.aborted) throw new NgxMediaError('ABORTED', 'Load aborted.');\n\n const capability = canPlayNatively(this.el, source);\n if (capability === '') {\n throw NgxMediaError.noDecoder(typeof source.src === 'string' ? source.src : '[blob]');\n }\n\n const resolvedSrc = this.resolveSrc(source);\n await new Promise<void>((resolve, reject) => {\n const onReady = () => {\n cleanup();\n resolve();\n };\n const onError = () => {\n cleanup();\n reject(NgxMediaError.fromMediaElementError(this.el));\n };\n const onAbort = () => {\n cleanup();\n reject(new NgxMediaError('ABORTED', 'Load aborted.'));\n };\n const cleanup = () => {\n this.el.removeEventListener('loadedmetadata', onReady);\n this.el.removeEventListener('error', onError);\n abort?.removeEventListener('abort', onAbort);\n };\n this.el.addEventListener('loadedmetadata', onReady, { once: true });\n this.el.addEventListener('error', onError, { once: true });\n abort?.addEventListener('abort', onAbort, { once: true });\n\n if (abort?.aborted) {\n onAbort();\n return;\n }\n\n // Setting src/srcObject is enough to select the resource and avoids\n // immediately restarting the same selection algorithm with an extra\n // `load()` call. This is important for authenticated/redirected\n // resources where a restart can result in another network request.\n if (typeof MediaStream !== 'undefined' && source.src instanceof MediaStream) {\n (this.el as any).srcObject = source.src;\n } else {\n this.el.src = resolvedSrc;\n }\n });\n\n this.loadState = 'ready';\n } catch (err) {\n this.loadState = 'idle';\n this.loadedIdentity = null;\n throw err;\n }\n }\n\n async play(): Promise<void> {\n this.assertNotDestroyed();\n try {\n await this.el.play();\n } catch (err) {\n // NotAllowedError is the browser's autoplay-policy rejection.\n if (err instanceof DOMException && err.name === 'NotAllowedError') {\n this.patch({ playback: 'paused' });\n throw NgxMediaError.autoplayBlocked(err);\n }\n throw err;\n }\n }\n\n pause(): void {\n if (this.destroyed) return;\n this.el.pause();\n }\n\n seek(time: number): void {\n this.assertNotDestroyed();\n const clamped = Math.min(Math.max(time, 0), this.el.duration || time);\n this.patch({ playback: 'seeking' });\n this.el.currentTime = clamped;\n }\n\n setVolume(volume: number): void {\n this.el.volume = Math.min(Math.max(volume, 0), 1);\n }\n\n setMuted(muted: boolean): void {\n this.el.muted = muted;\n }\n\n setPlaybackRate(rate: number): void {\n this.el.playbackRate = Math.max(0.0625, rate);\n }\n\n destroy(): void {\n if (this.destroyed) return;\n this.destroyed = true;\n this.cleanupFns.forEach((fn) => fn());\n this.cleanupFns.length = 0;\n this.releaseObjectUrl();\n this.loadState = 'idle';\n this.loadedIdentity = null;\n this.pendingLoad = null;\n this.activeLoadController?.abort();\n this.activeLoadController = null;\n this.el.pause();\n this.el.removeAttribute('src');\n (this.el as any).srcObject = null;\n this.el.load();\n this.patch({ playback: 'destroyed' });\n }\n\n // --- internals -----------------------------------------------------------\n\n private resolveSrc(source: NgxMediaSource): string {\n if (typeof source.src === 'string') return source.src;\n if (source.src instanceof Blob) {\n this.objectUrl = URL.createObjectURL(source.src);\n return this.objectUrl;\n }\n return '';\n }\n\n private releaseObjectUrl(): void {\n if (this.objectUrl) {\n URL.revokeObjectURL(this.objectUrl);\n this.objectUrl = null;\n }\n }\n\n /** Skips the signal write entirely when every field in `partial` is already equal to current state. */\n private patch(partial: Partial<NgxMediaState>): void {\n this._state.update((s) => {\n let changed = false;\n for (const k in partial) {\n if ((partial as Record<string, unknown>)[k] !== (s as any)[k]) {\n changed = true;\n break;\n }\n }\n return changed ? { ...s, ...partial } : s;\n });\n }\n\n private bufferedRanges(): NgxTimeRange[] {\n const ranges: NgxTimeRange[] = [];\n const b = this.el.buffered;\n for (let i = 0; i < b.length; i++) {\n ranges.push({ start: b.start(i), end: b.end(i) });\n }\n return ranges;\n }\n\n private attachListeners(): void {\n this.runOutsideAngular(() => {\n const on = <K extends keyof HTMLMediaElementEventMap>(\n type: K,\n handler: (ev: HTMLMediaElementEventMap[K]) => void,\n ) => {\n this.el.addEventListener(type, handler as EventListener);\n this.cleanupFns.push(() => this.el.removeEventListener(type, handler as EventListener));\n };\n\n on('loadedmetadata', () => {\n this.patch({\n duration: Number.isFinite(this.el.duration) ? this.el.duration : 0,\n videoWidth: (this.el as HTMLVideoElement).videoWidth || undefined,\n videoHeight: (this.el as HTMLVideoElement).videoHeight || undefined,\n playback: 'ready',\n });\n // Deliberately NOT auto-probing an unknown duration here — see\n // `probeUnseekableDuration()` below for why that cost extra network\n // requests on every load. `durationchange` still updates the UI the\n // moment the browser resolves it on its own, at zero extra cost.\n });\n on('waiting', () => this.patch({ playback: 'buffering' }));\n on('playing', () => this.patch({ playback: 'playing' }));\n on('pause', () => {\n if (this._state().playback !== 'ended') this.patch({ playback: 'paused' });\n });\n on('ended', () => this.patch({ playback: 'ended' }));\n on('seeked', () =>\n this.patch({\n playback: this.el.paused ? 'paused' : 'playing',\n currentTime: this.el.currentTime,\n }),\n );\n on('timeupdate', () => this.patch({ currentTime: this.el.currentTime }));\n on('durationchange', () => {\n if (Number.isFinite(this.el.duration)) this.patch({ duration: this.el.duration });\n });\n on('progress', () => {\n const ranges = this.bufferedRanges();\n // `bufferedRanges()` always allocates a new array; only write the\n // signal (and thus schedule a render) if the ranges actually moved.\n if (!rangesEqual(ranges, this._state().buffered)) {\n this.patch({ buffered: ranges });\n }\n });\n on('volumechange', () => this.patch({ volume: this.el.volume, muted: this.el.muted }));\n on('ratechange', () => this.patch({ playbackRate: this.el.playbackRate }));\n on('error', () => this.patch({ playback: 'error' }));\n });\n }\n\n /**\n * Some servers/streams report `duration === Infinity` until more data\n * arrives. This forces the browser to resolve it immediately by seeking\n * near the end and back — which works, but each call costs 1-2 extra\n * HTTP range requests. No longer called automatically; opt-in for the\n * rare case where you genuinely need duration *immediately* rather than\n * letting `durationchange` update it naturally during normal playback.\n */\n async probeUnseekableDuration(): Promise<void> {\n if (this.destroyed) return;\n const original = this.el.currentTime;\n try {\n this.el.currentTime = 1e10;\n await new Promise<void>((resolve) => {\n const onChange = () => {\n this.el.removeEventListener('durationchange', onChange);\n resolve();\n };\n this.el.addEventListener('durationchange', onChange, { once: true });\n setTimeout(resolve, 1500); // don't hang forever on streams that never resolve it\n });\n } finally {\n if (!this.destroyed) this.el.currentTime = original;\n }\n }\n\n private assertNotDestroyed(): void {\n if (this.destroyed) {\n throw new NgxMediaError('ABORTED', `${this.id} engine method called after destroy().`);\n }\n }\n}\n\n/** True if an `AudioContext`-based duration probe is even worth attempting (SSR/very old browser guard). */\nexport function canProbeDuration(): boolean {\n return !!getAudioContextCtor();\n}\n","import { InjectionToken } from '@angular/core';\nimport { NgxMediaDecoder } from './decoder.interface';\nimport { NgxMediaSource } from '../contracts/media-source';\n\n/**\n * Multi-provider token: every decoder a consumer registers via\n * `provideNgxMediaDecoder()` is picked up automatically by the registry.\n *\n * IMPORTANT: this token intentionally has NO default factory. Angular does\n * not allow mixing a token's own default provider with externally\n * registered `multi: true` providers for the SAME token — doing so throws\n * at DI-construction time the moment a consumer actually registers a\n * decoder (a real, if latent, bug this fixes). The correct pattern for an\n * \"optionally empty\" multi token is `@Optional()` injection at the\n * consumption site (see `NgxMediaDecoderRegistry`), which yields `null`\n * when nothing has registered and an array when one or more have.\n */\nexport const NGX_MEDIA_DECODER = new InjectionToken<NgxMediaDecoder>('NGX_MEDIA_DECODER');\n\n/** Pluggable network layer so auth/signed URLs don't require coupling the core to HttpClient. */\nexport interface NgxMediaRequestHandler {\n request(source: NgxMediaSource, signal?: AbortSignal): Promise<Response>;\n}\n\nexport const NGX_MEDIA_REQUEST_HANDLER = new InjectionToken<NgxMediaRequestHandler>(\n 'NGX_MEDIA_REQUEST_HANDLER',\n {\n providedIn: 'root',\n factory: () => ({\n request: (source, signal) =>\n fetch(typeof source.src === 'string' ? source.src : '', {\n headers: source.requestHeaders,\n signal,\n }),\n }),\n },\n);\n\nexport interface NgxMediaConfig {\n /** Default preload hint for native engines. */\n preload: 'none' | 'metadata' | 'auto';\n /** Ceiling for the number of decoder `canDecode` probes run in parallel. */\n maxConcurrentDecoderProbes: number;\n}\n\nexport const NGX_MEDIA_CONFIG_DEFAULTS: NgxMediaConfig = {\n preload: 'metadata',\n maxConcurrentDecoderProbes: 3,\n};\n\nexport const NGX_MEDIA_CONFIG = new InjectionToken<NgxMediaConfig>('NGX_MEDIA_CONFIG', {\n providedIn: 'root',\n factory: () => ({ ...NGX_MEDIA_CONFIG_DEFAULTS }),\n});\n","import { Injectable, inject } from '@angular/core';\nimport { NgxMediaEngine, NgxMediaKind } from './media-engine.interface';\nimport { NativeMediaEngine } from './native-media-engine';\nimport { isBrowser } from '../utils/capabilities';\nimport { NGX_MEDIA_REQUEST_HANDLER } from '../decoders/decoder.tokens';\nimport { NgxMediaError } from '../contracts/media-error';\n\n/**\n * Only ever returns a native engine (not yet loaded). `canPlayType()`/\n * extension/mime are just a hint and can lie (fake extension, a container\n * the browser opens but can't actually decode) — the only reliable signal\n * is a real `load()` attempt actually failing. So the native-vs-decoder\n * decision is not made here; `NgxMediaFacade.resolveEngine()` tries native\n * first and falls back to the decoder registry on a genuine (format-level)\n * failure. This class stays responsible only for constructing engines.\n *\n * Synchronous on purpose: constructing a `NativeMediaEngine` never awaits\n * anything, so wrapping it in a `Promise` bought nothing but an extra\n * microtask on every load. Callers that still `await` this are unaffected.\n */\n@Injectable({ providedIn: 'root' })\nexport class NgxMediaEngineFactory {\n private readonly requestHandler = inject(NGX_MEDIA_REQUEST_HANDLER);\n\n create(\n kind: NgxMediaKind,\n runOutsideAngular: <T>(fn: () => T) => T,\n preload: 'none' | 'metadata' | 'auto' = 'metadata',\n ): NgxMediaEngine {\n if (!isBrowser()) {\n throw NgxMediaError.unsupported('Media engines can only be created in a browser context (SSR guard).');\n }\n return new NativeMediaEngine(kind, runOutsideAngular, undefined, preload);\n }\n\n /** Explicit opt-in path for callers that specifically want MSE (e.g. a decoder building on it). */\n async createMse(kind: NgxMediaKind): Promise<NgxMediaEngine> {\n const { MseMediaEngine } = await import('./mse-media-engine');\n return new MseMediaEngine(kind, this.requestHandler);\n }\n}\n","import { hasMediaSession } from '../utils/capabilities';\nimport { NgxMediaSource } from '../contracts/media-source';\n\nexport interface MediaSessionActions {\n play(): void;\n pause(): void;\n previous(): void;\n next(): void;\n seekBackward(seconds: number): void;\n seekForward(seconds: number): void;\n}\n\n/**\n * `navigator.mediaSession` is a single global the whole page shares. With\n * more than one `NgxMediaControl` on a page, whichever bound LAST naturally\n * owns it (a reasonable policy — that matches which one the OS media\n * controls should act on). The bug this fixes: without tracking who the\n * current owner actually is, destroying an OLDER player unconditionally\n * cleared every action handler, silently breaking the media session for\n * whichever player is currently active. `currentOwner` makes `unbind()` a\n * no-op unless the instance calling it is still the one that owns it.\n */\nlet currentOwner: NgxMediaSessionBridge | null = null;\n\n/** No-ops everywhere the API isn't supported; never throws. */\nexport class NgxMediaSessionBridge {\n private bound = false;\n\n bind(actions: MediaSessionActions): void {\n if (!hasMediaSession()) return;\n currentOwner = this;\n this.bound = true;\n const ms = navigator.mediaSession;\n const safe = (fn: () => void) => () => {\n try {\n fn();\n } catch {\n /* a handler throwing must never break media session integration */\n }\n };\n ms.setActionHandler('play', safe(actions.play));\n ms.setActionHandler('pause', safe(actions.pause));\n ms.setActionHandler('previoustrack', safe(actions.previous));\n ms.setActionHandler('nexttrack', safe(actions.next));\n ms.setActionHandler('seekbackward', (details) => actions.seekBackward(details.seekOffset ?? 10));\n ms.setActionHandler('seekforward', (details) => actions.seekForward(details.seekOffset ?? 10));\n }\n\n /** No-ops if a different (typically newer) instance currently owns the session — a stale player must never overwrite the active one's metadata. */\n setMetadata(source: NgxMediaSource): void {\n if (!hasMediaSession() || typeof MediaMetadata === 'undefined' || currentOwner !== this) return;\n navigator.mediaSession.metadata = new MediaMetadata({\n title: source.title ?? '',\n artist: source.artist ?? '',\n album: source.album ?? '',\n artwork: source.poster ? [{ src: source.poster }] : [],\n });\n }\n\n setPlaybackState(state: 'playing' | 'paused' | 'none'): void {\n if (!hasMediaSession() || currentOwner !== this) return;\n navigator.mediaSession.playbackState = state;\n }\n\n unbind(): void {\n if (!hasMediaSession() || !this.bound) return;\n this.bound = false;\n if (currentOwner !== this) {\n // A newer instance already took over ownership — clearing handlers\n // now would wipe out THEIR session, not ours. Nothing to do.\n return;\n }\n currentOwner = null;\n const ms = navigator.mediaSession;\n (['play', 'pause', 'previoustrack', 'nexttrack', 'seekbackward', 'seekforward'] as const).forEach(\n (action) => {\n try {\n ms.setActionHandler(action, null);\n } catch {\n /* older browsers may not support every action name */\n }\n },\n );\n }\n}\n","import { getAudioContextCtor } from '../utils/capabilities';\nimport { NgxMediaError } from '../contracts/media-error';\n\n/**\n * Optional processing graph: `<audio>/<video>` → MediaElementAudioSourceNode\n * → gain → (optional analyser) → destination.\n *\n * Never constructed unless a consumer asks for gain/analyser/effects — plain\n * playback never creates an `AudioContext`, respecting autoplay policy and\n * avoiding the \"one AudioContext per instance whether needed or not\" issue\n * in the original component.\n *\n * Autoplay note: this class never calls `resume()` on its own outside a\n * user-triggered `play()`/`connect()` call — bypassing the suspended-state\n * policy is explicitly out of scope.\n */\nexport class NgxWebAudioGraph {\n private ctx: AudioContext | null = null;\n private sourceNode: MediaElementAudioSourceNode | null = null;\n private gainNode: GainNode | null = null;\n private analyserNode: AnalyserNode | null = null;\n\n constructor(private readonly element: HTMLMediaElement) {}\n\n /** Idempotent — safe to call multiple times; only the first call does any work. */\n ensureConnected(): { context: AudioContext; gain: GainNode } {\n if (this.ctx && this.gainNode) return { context: this.ctx, gain: this.gainNode };\n\n const Ctor = getAudioContextCtor();\n if (!Ctor) throw NgxMediaError.unsupported('Web Audio API is not available in this browser.');\n\n this.ctx = new Ctor();\n this.sourceNode = this.ctx.createMediaElementSource(this.element);\n this.gainNode = this.ctx.createGain();\n this.sourceNode.connect(this.gainNode);\n this.gainNode.connect(this.ctx.destination);\n return { context: this.ctx, gain: this.gainNode };\n }\n\n setGain(value: number): void {\n if (this.gainNode) this.gainNode.gain.value = value;\n }\n\n getAnalyser(fftSize = 2048): AnalyserNode {\n if (!this.ctx || !this.gainNode) this.ensureConnected();\n if (!this.analyserNode) {\n this.analyserNode = this.ctx!.createAnalyser();\n this.analyserNode.fftSize = fftSize;\n this.gainNode!.connect(this.analyserNode);\n }\n return this.analyserNode;\n }\n\n async resumeOnUserGesture(): Promise<void> {\n if (this.ctx?.state === 'suspended') await this.ctx.resume();\n }\n\n destroy(): void {\n this.sourceNode?.disconnect();\n this.gainNode?.disconnect();\n this.analyserNode?.disconnect();\n // Do not call ctx.close() synchronously in destroy paths that might race a\n // pending resume(); schedule it and swallow errors from an already-closed context.\n this.ctx?.close().catch(() => {});\n this.ctx = null;\n this.sourceNode = null;\n this.gainNode = null;\n this.analyserNode = null;\n }\n}\n","import { Injectable, Optional, Inject, inject } from '@angular/core';\nimport { NGX_MEDIA_DECODER, NGX_MEDIA_CONFIG } from './decoder.tokens';\nimport { NgxMediaDecoder } from './decoder.interface';\nimport { NgxMediaSource } from '../contracts/media-source';\nimport { NgxMediaEngine } from '../engines/media-engine.interface';\nimport { NgxMediaError } from '../contracts/media-error';\n\n/** Emitted (via `onDecoderFailure`) whenever a decoder's `canDecode()` throws, so failures aren't silently invisible. */\nexport interface DecoderProbeFailure {\n decoderId: string;\n error: unknown;\n}\n\nfunction extensionOf(source: NgxMediaSource): string | undefined {\n if (typeof source.src !== 'string') return undefined;\n return source.src.split(/[?#]/)[0].split('.').pop()?.toLowerCase();\n}\n\n/**\n * Resolves a non-natively-playable source to a registered decoder, highest\n * `priority` first. Nothing here imports MSE/WASM code directly — decoders\n * bring their own (lazily, inside `createEngine`), so a consumer who never\n * registers a decoder never pays for one in their bundle.\n *\n * Probe strategy:\n * 1. Cheap synchronous pre-filter by `formats` (extension match) first —\n * a decoder that lists `formats: ['3gp']` is never even asked\n * `canDecode()` for an `.mp3` source.\n * 2. Remaining candidates are probed with bounded concurrency\n * (`maxConcurrentDecoderProbes`) rather than one at a time, so N\n * network/CPU-bound `canDecode()` checks don't serialize their latency.\n * 3. The whole probe is cancellable via `signal` (passed down from the\n * facade's per-load `AbortController`), so switching tracks quickly\n * doesn't leave abandoned probes burning CPU/network.\n */\n@Injectable({ providedIn: 'root' })\nexport class NgxMediaDecoderRegistry {\n private readonly decoders: readonly NgxMediaDecoder[];\n private readonly config = inject(NGX_MEDIA_CONFIG);\n\n /** Set by a consumer that wants visibility into swallowed decoder errors (logging/telemetry), instead of them being silently invisible. */\n onDecoderFailure: ((failure: DecoderProbeFailure) => void) | null = null;\n\n constructor(@Optional() @Inject(NGX_MEDIA_DECODER) decoders: NgxMediaDecoder[] | null) {\n this.decoders = [...(decoders ?? [])].sort((a, b) => (b.priority ?? 0) - (a.priority ?? 0));\n }\n\n async findDecoder(source: NgxMediaSource, signal?: AbortSignal): Promise<NgxMediaDecoder | undefined> {\n if (this.decoders.length === 0) return undefined;\n\n // Step 1: cheap, synchronous pre-filter. A decoder with a non-empty\n // `formats` list is only a candidate if the source's extension matches\n // (or the source has no discoverable extension at all, in which case we\n // can't rule it out cheaply and let it through to the real probe).\n const ext = extensionOf(source);\n const candidates = this.decoders.filter(\n (d) => d.formats.length === 0 || !ext || d.formats.includes(ext),\n );\n if (candidates.length === 0) return undefined;\n\n // Step 2 + 3: bounded-concurrency, cancellable probing, highest\n // priority first among each concurrent batch (candidates is already\n // priority-sorted, so batching preserves that order for the final pick).\n const limit = Math.max(1, this.config.maxConcurrentDecoderProbes);\n for (let i = 0; i < candidates.length; i += limit) {\n if (signal?.aborted) return undefined;\n const batch = candidates.slice(i, i + limit);\n const results = await Promise.all(\n batch.map(async (decoder) => {\n try {\n return (await decoder.canDecode(source, signal)) ? decoder : null;\n } catch (error) {\n if (signal?.aborted) return null;\n // A misbehaving decoder shouldn't block evaluating the rest,\n // but the failure is no longer silently swallowed.\n this.onDecoderFailure?.({ decoderId: decoder.id, error });\n return null;\n }\n }),\n );\n if (signal?.aborted) return undefined;\n const found = results.find((d): d is NgxMediaDecoder => d !== null);\n if (found) return found;\n }\n return undefined;\n }\n\n async createEngine(source: NgxMediaSource, signal?: AbortSignal): Promise<NgxMediaEngine> {\n const decoder = await this.findDecoder(source, signal);\n if (!decoder) {\n throw NgxMediaError.noDecoder(typeof source.src === 'string' ? source.src : '[blob]');\n }\n return decoder.createEngine(source, signal);\n }\n\n destroyAll(): void {\n this.decoders.forEach((d) => d.destroy());\n }\n}\n\n/** Injects the registry outside DI (e.g. from a factory function). */\nexport function injectDecoderRegistry(): NgxMediaDecoderRegistry {\n return inject(NgxMediaDecoderRegistry);\n}\n","import { computed, DestroyRef, inject, Injectable, NgZone, signal } from '@angular/core';\nimport { NgxMediaEngineFactory } from '../engines/media-engine-factory';\nimport { NgxMediaEngine, NgxMediaKind } from '../engines/media-engine.interface';\nimport { NgxMediaSource, mediaSourcesEqual } from '../contracts/media-source';\nimport { initialMediaState, NgxMediaState } from '../contracts/media-state';\nimport { NgxMediaError, NgxMediaErrorCategory } from '../contracts/media-error';\nimport { NgxMediaSessionBridge } from './media-session';\nimport { NgxWebAudioGraph } from '../audio/web-audio-graph';\nimport { isBrowser } from '../utils/capabilities';\nimport { NgxMediaDecoderRegistry } from '../decoders/decoder-registry';\n\n/** Categories where falling back to a decoder is actually the right call — i.e. the format/codec itself is the problem, not the network or a deliberate cancellation. */\nconst DECODER_FALLBACK_CATEGORIES: ReadonlySet<NgxMediaErrorCategory> = new Set(['UNSUPPORTED_FORMAT', 'DECODER']);\n\n/**\n * Everything the UI component needs, expressed as signals it can bind to\n * directly, plus imperative commands. This is the only class\n * `NgxMediaControl` talks to — it never touches an engine, a decoder, or the\n * DOM media element itself. Swapping native/MSE/WASM playback never touches\n * the component.\n */\n@Injectable()\nexport class NgxMediaFacade {\n private readonly zone = inject(NgZone);\n private readonly engineFactory = inject(NgxMediaEngineFactory);\n private readonly decoderRegistry = inject(NgxMediaDecoderRegistry);\n private readonly destroyRef = inject(DestroyRef);\n private readonly mediaSession = new NgxMediaSessionBridge();\n\n private webAudio: NgxWebAudioGraph | null = null;\n private loadAbort: AbortController | null = null;\n private kind: NgxMediaKind = 'audio';\n private preload: 'none' | 'metadata' | 'auto' = 'metadata';\n /**\n * Belt-and-suspenders alongside `AbortController`: not every operation a\n * superseded load might be mid-way through is actually cancellable (a\n * decoder's own internal work, a promise someone else is holding a\n * reference to, ...). Every `loadCurrent()` call captures the generation\n * counter at its start and checks it again before committing any result —\n * a stale generation means \"a newer load has already started\", full stop,\n * regardless of whether the stale one's `AbortSignal` was actually honored\n * by everything downstream.\n */\n private loadGeneration = 0;\n\n private readonly _playlist = signal<NgxMediaSource[]>([]);\n private readonly _currentIndex = signal(0);\n /** Holds the live engine instance; swapped whenever a new source loads. */\n private readonly _engine = signal<NgxMediaEngine | null>(null);\n private get engine(): NgxMediaEngine | null {\n return this._engine();\n }\n private readonly _error = signal<NgxMediaError | null>(null);\n\n readonly playlist = this._playlist.asReadonly();\n readonly currentIndex = this._currentIndex.asReadonly();\n /**\n * Reads through to the current engine's own state signal, so every native\n * media event (timeupdate, progress, ...) that the engine writes flows\n * straight through here with no polling, no manual refresh, and no risk of\n * going stale across an engine swap (native -> WASM fallback, etc.).\n *\n * When there is NO engine (playlist empty, or the engine was torn down\n * after a load failure) but `error()` is set, this reports `playback:\n * 'error'` rather than falling through to `idle` — otherwise `state()` and\n * `error()` would be two sources of truth that can disagree, and anything\n * built on `state().playback === 'error'` would silently miss real errors.\n */\n readonly state = computed<NgxMediaState>(() => {\n const engineState = this._engine()?.state();\n if (engineState) return engineState;\n if (this._error()) return { ...initialMediaState(), playback: 'error' };\n return initialMediaState();\n });\n readonly error = this._error.asReadonly();\n readonly currentSource = computed(() => this._playlist()[this._currentIndex()]);\n readonly mediaElement = computed(() => this._engine()?.mediaElement ?? null);\n\n constructor() {\n this.destroyRef.onDestroy(() => this.destroy());\n }\n\n /** Deterministic on a kind change: if a source is already active, immediately rebuilds the engine as the new kind (audio <-> video element) instead of leaving a stale-kind engine behind a UI that now expects the other one. */\n configure(kind: NgxMediaKind): void {\n if (this.kind === kind) return;\n this.kind = kind;\n if (this.currentSource()) {\n const wasPlaying = this.state().playback === 'playing';\n void this.loadCurrent(wasPlaying);\n }\n }\n\n /** Applies to loads started after this call — not retroactive to an element already created. */\n setPreload(preload: 'none' | 'metadata' | 'auto'): void {\n this.preload = preload;\n }\n\n setPlaylist(sources: NgxMediaSource[], startIndex = 0, autoLoad = true): void {\n // If the content genuinely hasn't changed, do nothing — not even\n // reset `currentIndex` to `startIndex`. A component effect that always\n // passes `startIndex=0` must not be able to yank a user who has\n // manually navigated (next/previous) back to track 0 just because it\n // happened to re-run with an equivalent (but reference-different) array.\n if (mediaSourcesEqual(this._playlist(), sources)) {\n return;\n }\n\n const clampedIndex = Math.min(Math.max(startIndex, 0), Math.max(sources.length - 1, 0));\n this._playlist.set(sources);\n this._currentIndex.set(clampedIndex);\n\n if (sources.length === 0) {\n // Nothing left to play — tear down whatever was active instead of\n // leaving stale audio/video playing with no playlist entry backing it.\n this.loadAbort?.abort();\n this.loadGeneration++;\n this.webAudio?.destroy();\n this.webAudio = null;\n this.engine?.destroy();\n this._engine.set(null);\n this._error.set(null);\n return;\n }\n\n if (autoLoad) void this.loadCurrent();\n }\n\n async loadCurrent(playAfter = false): Promise<void> {\n const source = this.currentSource();\n if (!source || !isBrowser()) return;\n\n this.loadAbort?.abort();\n const controller = new AbortController();\n this.loadAbort = controller;\n const generation = ++this.loadGeneration;\n this._error.set(null);\n\n let newEngine: NgxMediaEngine | null = null;\n try {\n newEngine = await this.resolveEngine(source, controller.signal);\n\n if (generation !== this.loadGeneration) {\n // Superseded while the new engine was being built (next/previous/\n // another loadCurrent started meanwhile). Never commit it, and\n // never touch the engine that IS current now — that belongs to the\n // newer, still-in-flight or already-committed load.\n newEngine.destroy();\n return;\n }\n\n // Transactional swap: the OLD engine is only destroyed once the NEW\n // one is confirmed ready. This means a failed next()/previous() never\n // interrupts what was already playing, and the player never sits in a\n // null/blank state just because the next track failed to load.\n const old = this.engine;\n this.webAudio?.destroy();\n this.webAudio = null; // a Web Audio graph attached to the OLD element must never be reused for the new one\n this._engine.set(newEngine);\n old?.destroy();\n\n this.mediaSession.setMetadata(source);\n this.bindMediaSession();\n if (playAfter) await this.play();\n } catch (err) {\n newEngine?.destroy();\n if (generation !== this.loadGeneration) return; // a newer load owns error/state now; this failure is stale\n const mediaError =\n err instanceof NgxMediaError ? err : new NgxMediaError('UNKNOWN', 'Failed to load media.', err);\n this._error.set(mediaError);\n }\n }\n\n /** Forces the current track to actually reload from scratch — e.g. a \"retry after error\" action — bypassing the engine's own idempotent-load skip (which is otherwise correct: selecting the same, already-loaded track should NOT re-fetch it). */\n async reloadCurrent(): Promise<void> {\n this.engine?.destroy();\n this._engine.set(null);\n await this.loadCurrent(true);\n }\n\n /**\n * Tries the native engine first (the normal fast path). Falls back to the\n * decoder registry ONLY when the failure category indicates the format\n * itself is the problem (`UNSUPPORTED_FORMAT`, `DECODER`) — never for\n * `NETWORK` (404/500/CORS/interrupted), `ABORTED`, or `PERMISSION`, where\n * retrying via a decoder would just repeat the same failing request\n * (or a fresh one to the same broken URL) for no benefit. This matters\n * because `canPlayType()`/extension/mime are only ever a hint and can be\n * wrong (a mislabeled or fake extension), so the decision to fall back\n * has to be made from the real failure, not guessed upfront.\n */\n private async resolveEngine(source: NgxMediaSource, signal: AbortSignal): Promise<NgxMediaEngine> {\n const native = this.engineFactory.create(this.kind, (fn) => this.zone.runOutsideAngular(fn), this.preload);\n try {\n await native.load(source, signal);\n return native;\n } catch (nativeErr) {\n native.destroy();\n if (signal.aborted) throw nativeErr; // deliberate cancellation, not a format failure — don't probe decoders\n if (!this.shouldFallbackToDecoder(nativeErr)) throw nativeErr;\n\n const decoder = await this.decoderRegistry.findDecoder(source, signal);\n if (!decoder) throw nativeErr;\n\n // The decoder returns an engine that's already loaded internally\n // (possibly against a transcoded blob, not the original source) — it\n // must NOT have `.load(source)` called on it again afterwards.\n return decoder.createEngine(source, signal);\n }\n }\n\n private shouldFallbackToDecoder(error: unknown): boolean {\n return error instanceof NgxMediaError && DECODER_FALLBACK_CATEGORIES.has(error.category);\n }\n\n async play(): Promise<void> {\n if (!this.engine) return;\n try {\n await this.engine.play();\n this.mediaSession.setPlaybackState('playing');\n } catch (err) {\n this._error.set(err instanceof NgxMediaError ? err : new NgxMediaError('UNKNOWN', 'Play failed.', err));\n }\n }\n\n pause(): void {\n if (!this.engine) return;\n this.engine.pause();\n this.mediaSession.setPlaybackState('paused');\n }\n\n togglePlayPause(): void {\n if (this.state().playback === 'playing') this.pause();\n else void this.play();\n }\n\n seek(time: number): void {\n this.engine?.seek(time);\n }\n\n skip(deltaSeconds: number): void {\n const t = this.state().currentTime + deltaSeconds;\n this.seek(Math.min(Math.max(t, 0), this.state().duration || t));\n }\n\n setVolume(volume: number): void {\n this.engine?.setVolume(volume);\n }\n\n setMuted(muted: boolean): void {\n this.engine?.setMuted(muted);\n }\n\n setPlaybackRate(rate: number): void {\n this.engine?.setPlaybackRate(rate);\n }\n\n async previous(): Promise<void> {\n const list = this._playlist();\n if (list.length === 0) return;\n const next = (this._currentIndex() - 1 + list.length) % list.length;\n this._currentIndex.set(next);\n await this.loadCurrent(true);\n }\n\n async next(): Promise<void> {\n const list = this._playlist();\n if (list.length === 0) return;\n const next = (this._currentIndex() + 1) % list.length;\n this._currentIndex.set(next);\n await this.loadCurrent(true);\n }\n\n async selectIndex(index: number): Promise<void> {\n if (index < 0 || index >= this._playlist().length) return;\n // The facade owns the active engine. If the requested index is already\n // backed by an engine, selecting it again is a no-op even if a custom\n // engine reports an unusual/implementation-specific state. An explicit\n // reloadCurrent() remains the opt-in way to restart the same source.\n const alreadyOnIt = index === this._currentIndex() && this.engine !== null;\n if (alreadyOnIt) {\n // Same track, already loaded — selecting it again must not trigger a\n // fresh network load. Use `reloadCurrent()` for an explicit restart.\n return;\n }\n this._currentIndex.set(index);\n await this.loadCurrent(true);\n }\n\n /** Lazily creates the Web Audio graph — never touched unless a consumer asks for it. Always tied to the CURRENT engine's element; invalidated automatically on every engine swap (see `loadCurrent`). */\n getWebAudioGraph(): NgxWebAudioGraph {\n const el = this.mediaElement();\n if (!el) throw new NgxMediaError('MEDIA', 'No active media element to attach a Web Audio graph to.');\n if (!this.webAudio) this.webAudio = new NgxWebAudioGraph(el);\n return this.webAudio;\n }\n\n private bindMediaSession(): void {\n this.mediaSession.bind({\n play: () => void this.play(),\n pause: () => this.pause(),\n previous: () => void this.previous(),\n next: () => void this.next(),\n seekBackward: (s) => this.skip(-s),\n seekForward: (s) => this.skip(s),\n });\n }\n\n destroy(): void {\n this.loadAbort?.abort();\n this.loadGeneration++;\n this.mediaSession.unbind();\n this.webAudio?.destroy();\n this.engine?.destroy();\n this._engine.set(null);\n }\n}\n","import {\n ChangeDetectionStrategy,\n Component,\n computed,\n DestroyRef,\n DOCUMENT,\n effect,\n ElementRef,\n inject,\n input,\n output,\n signal,\n viewChild,\n} from '@angular/core';\nimport { CommonModule } from '@angular/common';\nimport { formatTime } from '../utils/format-time';\nimport { NgxMediaSource, mediaSourcesEqual, extractMediaFileName } from '../contracts/media-source';\nimport { NgxMediaFacade } from '../facade/ngx-media-facade';\nimport { hasFullscreen, hasPictureInPicture, isBrowser } from '../utils/capabilities';\n\nexport type NgxMediaType = 'audio' | 'video' | 'both';\n\n@Component({\n standalone: true,\n selector: 'ngx-media-control',\n templateUrl: './ngx-media-control.html',\n styleUrls: ['./ngx-media-control.scss'],\n imports: [CommonModule],\n changeDetection: ChangeDetectionStrategy.OnPush,\n providers: [NgxMediaFacade],\n})\nexport class NgxMediaControl {\n // --- configuration ---------------------------------------------------\n /**\n * `'audio'` renders an audio-style control surface (no video frame).\n * `'video'` renders a video frame with fullscreen/PiP controls.\n * `'both'` renders the video frame but degrades gracefully to audio-only\n * controls when the active source has no video track.\n */\n readonly type = input<NgxMediaType>('audio');\n /**\n * Poster precedence: this input, when set, ALWAYS wins over a per-source\n * `poster` (useful for a fixed placeholder while sources vary). Leave it\n * unset to let each `NgxMediaSource.poster` take effect per track, and\n * clearing either one correctly clears the poster actually applied (see\n * the mount effect below) instead of leaving a stale image behind.\n */\n readonly poster = input<string | undefined>(undefined);\n\n // --- inputs preserved verbatim from NgxAudioControl -------------------\n readonly showList = input<boolean>(true);\n readonly download = input<boolean>(false);\n readonly showFileName = input<boolean>(true);\n readonly showSpeed = input<boolean>(true);\n readonly showVolume = input<boolean>(true);\n readonly linear = input<boolean>(false);\n readonly preload = input<'none' | 'metadata' | 'auto'>('metadata');\n /**\n * IMPORTANT, and different from earlier versions of this component: a\n * native `<audio>`/`<video src>` fetch cannot carry arbitrary request\n * headers — that's a browser platform limitation, not something this\n * library can paper over without fetching the whole file into a `Blob`\n * first (which defeats streaming/range-requests for anything but small\n * clips, and was explicitly the wrong default per the library's\n * performance goals). So `fetchHeaders` is applied as the DEFAULT\n * `requestHeaders` for any resolved source that doesn't specify its own\n * (see `resolvedSources` below) — it takes effect for sources that end\n * up on a decoder/MSE backend (which do fetch through\n * `NGX_MEDIA_REQUEST_HANDLER` and can carry headers), and has no effect\n * on plain natively-playable sources, which never go through a fetch at\n * all. Set headers per-source via `NgxMediaSource.requestHeaders`\n * whenever different tracks need different auth.\n */\n readonly fetchHeaders = input<HeadersInit | undefined>(undefined);\n /** Legacy simple form: bare URLs, one per playlist entry. Prefer `sources` for titles/artwork/per-track headers. */\n readonly fileList = input<string[]>();\n /** Preferred over `fileList`: full `NgxMediaSource` objects. */\n readonly sources = input<NgxMediaSource[]>();\n\n // --- outputs -----------------------------------------------------------\n readonly trackChange = output<NgxMediaSource>();\n readonly error = output<string>();\n\n private readonly doc = inject(DOCUMENT);\n private readonly destroyRef = inject(DestroyRef);\n protected readonly facade = inject(NgxMediaFacade);\n\n protected readonly containerRef = viewChild.required<ElementRef<HTMLElement>>('container');\n protected readonly videoHostRef = viewChild<ElementRef<HTMLElement>>('videoHost');\n\n protected readonly downloading = signal(false);\n protected readonly togglePlayList = signal(false);\n protected readonly isFullscreen = signal(false);\n\n /** Local seek preview — see the seek-slider handlers below for why the slider never binds `state().currentTime` directly while the user is dragging it. */\n protected readonly isSeeking = signal(false);\n protected readonly seekPreviewTime = signal(0);\n\n protected readonly state = this.facade.state;\n protected readonly playlist = this.facade.playlist;\n protected readonly currentIndex = this.facade.currentIndex;\n protected readonly currentSource = this.facade.currentSource;\n protected readonly playerError = this.facade.error;\n\n protected readonly effectiveKind = computed<'audio' | 'video'>(() =>\n this.type() === 'audio' ? 'audio' : 'video',\n );\n protected readonly displaySeekTime = computed(() =>\n this.isSeeking() ? this.seekPreviewTime() : this.state().currentTime,\n );\n protected readonly currentTimeDisplay = computed(() => formatTime(this.displaySeekTime()));\n protected readonly totalTimeDisplay = computed(() => formatTime(this.state().duration));\n protected readonly speedDisplay = computed(() => `${this.state().playbackRate.toFixed(2)}x`);\n protected readonly fileName = computed(() => {\n const source = this.currentSource();\n return source ? extractMediaFileName(source) : '';\n });\n protected readonly isPlaying = computed(() => this.state().playback === 'playing');\n protected readonly isBuffering = computed(\n () => this.state().playback === 'buffering' || this.state().playback === 'loading',\n );\n protected readonly hasLoadError = computed(() => this.state().playback === 'error');\n protected readonly errorMessage = computed(() => this.playerError()?.message ?? '');\n protected readonly canFullscreen = computed(() => this.effectiveKind() === 'video' && hasFullscreen());\n protected readonly canPip = computed(() => this.effectiveKind() === 'video' && hasPictureInPicture());\n\n /**\n * Derived from `sources()` OR `fileList()` (whichever the consumer used),\n * memoized by CONTENT rather than reference (`equal: mediaSourcesEqual`).\n * Angular's `input()` signal only compares by reference — a parent that\n * binds an inline literal, e.g. `[sources]=\"[{...}]\"`, or otherwise\n * re-derives an equivalent array on every change-detection pass, produces\n * a *new* array every tick. Without the custom `equal`, the effect below\n * would see \"a new value\" on every tick and reload media in a loop. A\n * content-equal `computed` keeps returning its previous, `===`-stable\n * value whenever the new content is equivalent, so the effect below\n * simply doesn't re-run.\n */\n protected readonly resolvedSources = computed<NgxMediaSource[]>(\n () => {\n const globalHeaders = this.fetchHeaders();\n const explicit = this.sources();\n if (explicit) {\n return explicit.map((m) => ({\n ...m,\n title: extractMediaFileName(m),\n requestHeaders: m.requestHeaders ?? globalHeaders,\n }));\n }\n const simple = this.fileList() ?? [];\n return simple.map((src) => ({\n src,\n title: extractMediaFileName({ src }),\n requestHeaders: globalHeaders,\n }));\n },\n { equal: mediaSourcesEqual },\n );\n\n /** Tracks what's actually mounted in `videoHostRef`, so the mount effect only touches the DOM (and re-registers listeners) when the element itself changes, not on every unrelated signal read. */\n private mountedElement: HTMLMediaElement | null = null;\n private dblClickHandler: (() => void) | null = null;\n private downloadResetTimeout: ReturnType<typeof setTimeout> | null = null;\n\n constructor() {\n effect(() => this.facade.configure(this.effectiveKind()));\n effect(() => this.facade.setPreload(this.preload()));\n\n // Rebuild the playlist whenever the consumer swaps sources to genuinely\n // different content (see `resolvedSources` above for why this doesn't\n // fire on every change-detection tick).\n effect(() => {\n this.facade.setPlaylist(this.resolvedSources(), 0, true);\n });\n\n effect(() => {\n const err = this.playerError();\n if (err) this.error.emit(err.message);\n });\n\n effect(() => {\n const source = this.currentSource();\n if (source) this.trackChange.emit(source);\n });\n\n if (isBrowser()) {\n const onFsChange = () => this.isFullscreen.set(!!this.doc.fullscreenElement);\n this.doc.addEventListener('fullscreenchange', onFsChange);\n this.destroyRef.onDestroy(() => this.doc.removeEventListener('fullscreenchange', onFsChange));\n }\n\n // The engine owns/creates its own <audio>/<video> element (so the UI\n // never has to know how playback happens). For video mode we mount that\n // element into the template's host div — but ONLY when the element\n // itself actually changed (a new engine was created). Poster updates,\n // or this effect simply re-running for an unrelated reason, must not\n // re-create the dblclick listener or churn the DOM by detaching and\n // reattaching an element that's already correctly mounted.\n effect(() => {\n const el = this.facade.mediaElement();\n const host = this.videoHostRef()?.nativeElement;\n const isVideo = this.effectiveKind() === 'video';\n const effectivePoster = this.poster() ?? this.currentSource()?.poster;\n\n if (!host || !isVideo || !el) {\n this.detachMountedElement(host);\n return;\n }\n\n if (el !== this.mountedElement) {\n this.detachMountedElement(host);\n host.replaceChildren();\n el.classList.add('ngx-media-video-element');\n el.setAttribute('playsinline', '');\n this.dblClickHandler = () => void this.toggleFullscreen();\n el.addEventListener('dblclick', this.dblClickHandler);\n host.appendChild(el);\n this.mountedElement = el;\n }\n\n // Property update only — never re-creates the listener or touches the DOM tree.\n (el as HTMLVideoElement).poster = effectivePoster ?? '';\n });\n\n this.destroyRef.onDestroy(() => {\n this.detachMountedElement(null);\n if (this.downloadResetTimeout) clearTimeout(this.downloadResetTimeout);\n });\n }\n\n private detachMountedElement(host: HTMLElement | null | undefined): void {\n if (this.mountedElement && this.dblClickHandler) {\n this.mountedElement.removeEventListener('dblclick', this.dblClickHandler);\n }\n this.mountedElement = null;\n this.dblClickHandler = null;\n host?.replaceChildren();\n }\n\n // --- transport controls (same method names as the legacy component) ---\n\n playPause(): void {\n this.facade.togglePlayPause();\n }\n\n play(): void {\n void this.facade.play();\n }\n\n stop(): void {\n this.facade.pause();\n }\n\n muteUnmute(): void {\n this.facade.setMuted(!this.state().muted);\n }\n\n /**\n * Seek strategy: dragging the slider only updates a local preview\n * (`seekPreviewTime`) — no `facade.seek()` call, so no HTTP range\n * request or media-pipeline seek happens per pixel of drag. The actual\n * seek fires once, on `change` (`onSeekCommit`), which browsers fire\n * both on pointer-release-after-drag AND after each discrete keyboard\n * adjustment — so keyboard accessibility (arrow keys) still seeks\n * immediately per keypress, it's only continuous dragging that's\n * coalesced into a single request.\n */\n onSeekInput(ev: Event): void {\n const value = +(ev.target as HTMLInputElement).value;\n this.isSeeking.set(true);\n this.seekPreviewTime.set(value);\n }\n\n onSeekCommit(ev: Event): void {\n const value = +(ev.target as HTMLInputElement).value;\n this.isSeeking.set(false);\n this.facade.seek(value);\n }\n\n skipTrack(seconds: number): void {\n this.facade.skip(seconds);\n }\n\n increaseSpeed(): void {\n this.facade.setPlaybackRate(Math.max(0.5, this.state().playbackRate + 0.25));\n }\n\n decreaseSpeed(): void {\n this.facade.setPlaybackRate(Math.max(0.5, this.state().playbackRate - 0.25));\n }\n\n changeVolume(ev: Event): void {\n this.facade.setVolume(+(ev.target as HTMLInputElement).value);\n }\n\n previous(): void {\n void this.facade.previous();\n }\n\n next(): void {\n void this.facade.next();\n }\n\n onClickPlayList(index: number): void {\n this.togglePlayList.set(false);\n void this.facade.selectIndex(index);\n }\n\n togglePlaylistPanel(): void {\n this.togglePlayList.update((v) => !v);\n }\n\n /** Force-reload the current track from scratch (e.g. a \"retry\" affordance after an error) rather than relying on selecting the same playlist entry, which deliberately does NOT reload an already-loaded track. */\n retryCurrent(): void {\n void this.facade.reloadCurrent();\n }\n\n downloadCurrentFile(): void {\n const source = this.currentSource();\n if (!source) return;\n const url = source.downloadUrl ?? (typeof source.src === 'string' ? source.src : undefined);\n if (!url) return;\n\n if (this.downloadResetTimeout) clearTimeout(this.downloadResetTimeout);\n this.downloading.set(true);\n const a = this.doc.createElement('a');\n a.style.display = 'none';\n a.href = url;\n a.download = source.downloadFileName ?? extractMediaFileName(source);\n this.doc.body.appendChild(a);\n a.click();\n a.remove();\n // The `download` attribute gives no completion signal (and for\n // cross-origin URLs, browsers may ignore it and navigate instead — see\n // README \"Security limitations\"). This timeout only resets the button's\n // busy state; it is not, and cannot be, a real completion check.\n this.downloadResetTimeout = setTimeout(() => {\n this.downloading.set(false);\n this.downloadResetTimeout = null;\n }, 1000);\n }\n\n // --- video-only capabilities --------------------------------------------\n\n async toggleFullscreen(): Promise<void> {\n if (!this.canFullscreen()) return;\n const el = this.containerRef().nativeElement;\n try {\n if (this.doc.fullscreenElement) {\n await this.doc.exitFullscreen();\n } else {\n await el.requestFullscreen();\n }\n } catch {\n // Fullscreen can be denied by the browser (e.g. no user gesture); fail silently, UI state stays accurate via the fullscreenchange listener.\n }\n }\n\n async togglePictureInPicture(): Promise<void> {\n const el = this.facade.mediaElement() as HTMLVideoElement | null;\n if (!el || !this.canPip()) return;\n try {\n if (this.doc.pictureInPictureElement) {\n await (this.doc as any).exitPictureInPicture();\n } else {\n await el.requestPictureInPicture();\n }\n } catch {\n // Not every video/browser combination supports PiP at call time; ignore.\n }\n }\n}\n","<div class=\"media-player\" [class.linear]=\"linear()\" [class.video-mode]=\"effectiveKind() === 'video'\" #container>\n @if (showFileName()) {\n <span class=\"file-info\">{{ fileName() }}</span>\n }\n\n @if (effectiveKind() === 'video') {\n <div class=\"video-host\" #videoHost></div>\n }\n\n <div class=\"controls\">\n <div class=\"time-seeker\">\n <span>{{ currentTimeDisplay() }}</span>\n <input\n class=\"seek-slider\"\n type=\"range\"\n min=\"0\"\n [max]=\"state().duration || 0\"\n [value]=\"displaySeekTime()\"\n step=\".1\"\n (input)=\"onSeekInput($event)\"\n (change)=\"onSeekCommit($event)\" />\n <span>{{ totalTimeDisplay() }}</span>\n @if (isBuffering()) {\n <div class=\"simp-buffer\"></div>\n }\n </div>\n <div class=\"buttons\">\n <button title=\"skip track -10\" (click)=\"skipTrack(-10)\">\n <svg viewBox=\"0 0 24 24\">\n <path d=\"M7 9l-3 -3l3 -3\"></path>\n <path d=\"M15.997 17.918a6.002 6.002 0 0 0 -.997 -11.918h-11\"></path>\n </svg>\n </button>\n\n @if (playlist().length > 1) {\n <button (click)=\"previous()\" title=\"previous\">\n <svg viewBox=\"0 0 24 24\">\n <path d=\"M20 5v14l-12 -7z\" />\n <path d=\"M4 5l0 14\" />\n </svg>\n </button>\n }\n\n <button\n (click)=\"playPause()\"\n [title]=\"hasLoadError() ? 'Error on load media source' : isPlaying() ? 'pause' : 'play'\"\n [disabled]=\"hasLoadError()\">\n @if (!isPlaying()) {\n <svg viewBox=\"0 0 24 24\">\n <path\n d=\"M18.8906 12.846C18.5371 14.189 16.8667 15.138 13.5257 17.0361C10.296 18.8709 8.6812 19.7884 7.37983 19.4196C6.8418 19.2671 6.35159 18.9776 5.95624 18.5787C5 17.6139 5 15.7426 5 12C5 8.2574 5 6.3861 5.95624 5.42132C6.35159 5.02245 6.8418 4.73288 7.37983 4.58042C8.6812 4.21165 10.296 5.12907 13.5257 6.96393C16.8667 8.86197 18.5371 9.811 18.8906 11.154C19.0365 11.7084 19.0365 12.2916 18.8906 12.846Z\" />\n </svg>\n } @else {\n <svg viewBox=\"0 0 24 24\">\n <path\n d=\"M4 7C4 5.58579 4 4.87868 4.43934 4.43934C4.87868 4 5.58579 4 7 4C8.41421 4 9.12132 4 9.56066 4.43934C10 4.87868 10 5.58579 10 7V17C10 18.4142 10 19.1213 9.56066 19.5607C9.12132 20 8.41421 20 7 20C5.58579 20 4.87868 20 4.43934 19.5607C4 19.1213 4 18.4142 4 17V7Z\" />\n <path\n d=\"M14 7C14 5.58579 14 4.87868 14.4393 4.43934C14.8787 4 15.5858 4 17 4C18.4142 4 19.1213 4 19.5607 4.43934C20 4.87868 20 5.58579 20 7V17C20 18.4142 20 19.1213 19.5607 19.5607C19.1213 20 18.4142 20 17 20C15.5858 20 14.8787 20 14.4393 19.5607C14 19.1213 14 18.4142 14 17V7Z\" />\n </svg>\n }\n </button>\n\n @if (playlist().length > 1) {\n <button (click)=\"next()\" title=\"next\">\n <svg viewBox=\"0 0 24 24\">\n <path d=\"M4 5v14l12 -7z\" />\n <path d=\"M20 5l0 14\" />\n </svg>\n </button>\n }\n <button title=\"skip track +10\" (click)=\"skipTrack(10)\">\n <svg viewBox=\"0 0 24 24\">\n <path d=\"M17 9l3 -3l-3 -3\" />\n <path d=\"M8 17.918a5.997 5.997 0 0 1 -5 -5.918a6 6 0 0 1 6 -6h11\" />\n </svg>\n </button>\n\n @if (showVolume()) {\n <div class=\"volume-control\">\n <button (click)=\"muteUnmute()\" title=\"mute volume\">\n @if (state().muted) {\n <svg viewBox=\"0 0 24 24\">\n <path\n d=\"M14 14.8135V9.18646C14 6.04126 14 4.46866 13.0747 4.0773C12.1494 3.68593 11.0603 4.79793 8.88232 7.02192C7.75439 8.17365 7.11085 8.42869 5.50604 8.42869C4.10257 8.42869 3.40084 8.42869 2.89675 8.77262C1.85035 9.48655 2.00852 10.882 2.00852 12C2.00852 13.118 1.85035 14.5134 2.89675 15.2274C3.40084 15.5713 4.10257 15.5713 5.50604 15.5713C7.11085 15.5713 7.75439 15.8264 8.88232 16.9781C11.0603 19.2021 12.1494 20.3141 13.0747 19.9227C14 19.5313 14 17.9587 14 14.8135Z\" />\n <path d=\"M18 10L22 14M18 14L22 10\" />\n </svg>\n } @else {\n <svg viewBox=\"0 0 24 24\">\n <path\n d=\"M14 14.8135V9.18646C14 6.04126 14 4.46866 13.0747 4.0773C12.1494 3.68593 11.0603 4.79793 8.88232 7.02192C7.75439 8.17365 7.11085 8.42869 5.50604 8.42869C4.10257 8.42869 3.40084 8.42869 2.89675 8.77262C1.85035 9.48655 2.00852 10.882 2.00852 12C2.00852 13.118 1.85035 14.5134 2.89675 15.2274C3.40084 15.5713 4.10257 15.5713 5.50604 15.5713C7.11085 15.5713 7.75439 15.8264 8.88232 16.9781C11.0603 19.2021 12.1494 20.3141 13.0747 19.9227C14 19.5313 14 17.9587 14 14.8135Z\" />\n <path d=\"M17 9C17.6254 9.81968 18 10.8634 18 12C18 13.1366 17.6254 14.1803 17 15\" />\n <path d=\"M20 7C21.2508 8.36613 22 10.1057 22 12C22 13.8943 21.2508 15.6339 20 17\" />\n </svg>\n }\n </button>\n <input\n class=\"volume-slider\"\n type=\"range\"\n min=\"0\"\n max=\"1\"\n step=\"0.01\"\n [value]=\"state().volume\"\n (input)=\"changeVolume($event)\" />\n </div>\n }\n @if (showSpeed()) {\n <div class=\"speed-control\">\n <button (click)=\"decreaseSpeed()\" title=\"decrease speed\">\n <svg viewBox=\"0 0 24 24\"><path d=\"M20 12L4 12\" /></svg>\n </button>\n <span class=\"speed-display\">{{ speedDisplay() }}</span>\n <button (click)=\"increaseSpeed()\" title=\"increase speed\">\n <svg viewBox=\"0 0 24 24\">\n <path d=\"M12 4V20\" />\n <path d=\"M4 12H20\" />\n </svg>\n </button>\n </div>\n }\n\n @if (canFullscreen()) {\n <button (click)=\"toggleFullscreen()\" title=\"fullscreen\">\n <svg viewBox=\"0 0 24 24\"><path d=\"M4 9V4h5M20 9V4h-5M4 15v5h5M20 15v5h-5\" /></svg>\n </button>\n }\n @if (canPip()) {\n <button (click)=\"togglePictureInPicture()\" title=\"picture in picture\">\n <svg viewBox=\"0 0 24 24\"><rect x=\"3\" y=\"4\" width=\"18\" height=\"14\" rx=\"1\"></rect><rect x=\"12\" y=\"11\" width=\"7\" height=\"5\" rx=\"1\"></rect></svg>\n </button>\n }\n\n <div class=\"spacer\"></div>\n @if (showList()) {\n <button (click)=\"togglePlaylistPanel()\" title=\"Play list\">\n <svg viewBox=\"0 0 24 24\">\n <path d=\"M2 3L20 3\" />\n <path d=\"M2 10L15 10\" />\n <path d=\"M2 17L9 17\" />\n </svg>\n </button>\n }\n @if (download()) {\n <button (click)=\"downloadCurrentFile()\" title=\"download\" [disabled]=\"downloading()\">\n <svg viewBox=\"0 0 24 24\">\n <path\n d=\"M12 14.5L12 4.5M12 14.5C11.2998 14.5 9.99153 12.5057 9.5 12M12 14.5C12.7002 14.5 14.0085 12.5057 14.5 12\" />\n <path d=\"M20 16.5C20 18.982 19.482 19.5 17 19.5H7C4.518 19.5 4 18.982 4 16.5\" />\n </svg>\n </button>\n }\n </div>\n </div>\n @if (errorMessage()) {\n <div class=\"error-message\">\n {{ errorMessage() }}\n <button (click)=\"retryCurrent()\" title=\"retry\">retry</button>\n </div>\n }\n</div>\n\n@if (togglePlayList()) {\n <div class=\"play-list\" [class.linear]=\"linear()\">\n @if (playlist().length === 0) {\n <div class=\"list-item disabled\">No any record</div>\n }\n @for (item of playlist(); track $index; let i = $index) {\n <div class=\"list-item\" [class.active]=\"i === currentIndex()\" (click)=\"onClickPlayList(i)\">\n {{ item.title }}\n </div>\n }\n </div>\n}\n","import { NgxMediaDecoder } from './decoder.interface';\nimport { NgxMediaSource } from '../contracts/media-source';\nimport { NgxMediaEngine, NgxMediaKind } from '../engines/media-engine.interface';\nimport { NgxMediaError } from '../contracts/media-error';\nimport { signal, Signal } from '@angular/core';\nimport { initialMediaState, NgxMediaState } from '../contracts/media-state';\n\n/**\n * Base class for WASM-backed decoders. It does the two things every such\n * decoder needs regardless of which codec module it wraps:\n *\n * 1. Lazily `import()`s the codec module on first real use, in a Web Worker\n * when a worker factory is supplied, so the (typically large) WASM binary\n * never enters the main bundle or the main thread's JS heap unless a\n * source actually needs it.\n * 2. Provides a cancellable, disposable lifecycle (`AbortSignal`-aware load,\n * `destroy()` terminates the worker / frees the WASM instance) that is\n * safe under overlap: a `destroy()` that lands while `loadModule()` is\n * still pending must not let that pending load \"resurrect\" a module\n * reference for a decoder instance that's already gone, and must not\n * let a subsequent `createEngine()` call kick off a SECOND concurrent\n * module load while the first is still in flight.\n *\n * This class intentionally does NOT ship a real codec — bundling e.g.\n * `@ffmpeg/ffmpeg` here would violate \"no WASM in the default bundle\" for\n * every consumer, including ones who never touch this file. Concrete\n * decoders (FLAC, WMA, a consumer's own 3GP decoder, ...) extend this and\n * supply `loadModule` + `buildEngine`.\n */\nexport abstract class NgxWasmDecoderBase implements NgxMediaDecoder {\n abstract readonly id: string;\n abstract readonly formats: readonly string[];\n priority = 0;\n\n private worker: Worker | null = null;\n private modulePromise: Promise<unknown> | null = null;\n /** Bumped by every `destroy()`; lets an in-flight `loadModule()`/`createEngine()` notice it's talking to a dead instance once it resolves. */\n private generation = 0;\n\n /** Import path/factory for the codec's WASM glue module. Not evaluated until first `canDecode()`/`createEngine()` call. */\n protected abstract loadModule(): Promise<unknown>;\n\n /** Optional: return a `Worker` to run decoding off the main thread. Omit for short clips where worker overhead isn't worth it. */\n protected createWorker?(): Worker;\n\n abstract canDecode(source: NgxMediaSource, signal?: AbortSignal): boolean | Promise<boolean>;\n\n /**\n * Subclasses implement the actual decode-to-playable-engine step once the\n * module (and optionally worker) are ready. Typical strategies:\n * - decode fully into an `AudioBuffer`, play via Web Audio (`AudioBufferSourceNode`)\n * - decode progressively, feed an MSE `SourceBuffer`\n */\n protected abstract buildEngine(\n source: NgxMediaSource,\n module: unknown,\n worker: Worker | null,\n signal?: AbortSignal,\n ): Promise<NgxMediaEngine>;\n\n async createEngine(source: NgxMediaSource, signal?: AbortSignal): Promise<NgxMediaEngine> {\n const myGeneration = this.generation;\n const module = await this.ensureModuleLoaded(myGeneration);\n\n if (signal?.aborted) throw new NgxMediaError('ABORTED', `${this.id}: decode cancelled before start.`);\n if (myGeneration !== this.generation) {\n throw new NgxMediaError('ABORTED', `${this.id}: decoder was destroyed while its module was loading.`);\n }\n if (this.createWorker && !this.worker) {\n this.worker = this.createWorker();\n }\n try {\n return await this.buildEngine(source, module, this.worker, signal);\n } catch (err) {\n // Preserve a category the caller already established (e.g. NETWORK\n // from fetching the source, ABORTED from a cancelled transcode,\n // UNSUPPORTED_FORMAT from a codec check) — only genuinely unknown\n // failures get relabeled as DECODER.\n if (err instanceof NgxMediaError) throw err;\n throw new NgxMediaError('DECODER', `${this.id}: failed to build a playable engine.`, err);\n }\n }\n\n private ensureModuleLoaded(myGeneration: number): Promise<unknown> {\n if (!this.modulePromise) {\n this.modulePromise = this.loadModule().catch((err) => {\n if (myGeneration === this.generation) this.modulePromise = null; // allow retry on next call rather than caching a permanent failure\n throw new NgxMediaError('DECODER', `${this.id}: WASM module failed to load.`, err);\n });\n }\n // Share the in-flight promise across concurrent createEngine() callers\n // instead of starting a second module load; but re-check generation\n // once it resolves, since `destroy()` may have run while we waited.\n return this.modulePromise.then((mod) => {\n if (myGeneration !== this.generation) {\n throw new NgxMediaError('ABORTED', `${this.id}: destroyed while its WASM module was loading.`);\n }\n return mod;\n });\n }\n\n destroy(): void {\n this.generation++;\n this.worker?.terminate();\n this.worker = null;\n this.modulePromise = null;\n }\n}\n\n/**\n * Minimal playable-engine wrapper around a fully-decoded `AudioBuffer`,\n * useful for WASM decoders that decode short clips completely up front\n * rather than streaming. Reuses the browser's own `AudioContext` playback\n * graph instead of a native `<audio>` element, since there's no compressed\n * file for the browser to play directly anymore.\n *\n * Playback-position bookkeeping: `offset` is the buffer-time position when\n * the current `AudioBufferSourceNode` was (re)started, `startedAt` is the\n * `AudioContext.currentTime` at that moment, and `rate` is the playback\n * rate in effect since then — so at any instant, position =\n * `offset + (ctx.currentTime - startedAt) * rate`. Every operation that\n * stops or restarts the source (pause, seek, rate change while playing,\n * replay after ended) re-baselines these three fields together so that\n * formula stays correct instead of drifting.\n */\nexport class DecodedBufferEngine implements NgxMediaEngine {\n readonly id: string;\n readonly kind: NgxMediaKind = 'audio';\n readonly mediaElement = null;\n\n private readonly _state = signal<NgxMediaState>(initialMediaState());\n readonly state: Signal<NgxMediaState> = this._state.asReadonly();\n\n private ctx: AudioContext;\n private source: AudioBufferSourceNode | null = null;\n private gain: GainNode;\n private startedAt = 0;\n private offset = 0;\n private rate = 1;\n private volume = 1;\n private muted = false;\n private rafId: number | null = null;\n /** Bumped every time a NEW `AudioBufferSourceNode` is created, so a stale `onended` from a node that was `.stop()`-ed (rather than actually finishing) can recognize it's obsolete and not overwrite newer state. */\n private playToken = 0;\n\n constructor(\n decoderId: string,\n ctx: AudioContext,\n private readonly buffer: AudioBuffer,\n ) {\n this.id = `wasm:${decoderId}`;\n this.ctx = ctx;\n this.gain = ctx.createGain();\n this.gain.connect(ctx.destination);\n this._state.update((s) => ({ ...s, duration: buffer.duration, playback: 'ready' }));\n }\n\n async play(): Promise<void> {\n if (this.ctx.state === 'suspended') await this.ctx.resume();\n\n if (this._state().playback === 'ended' || this.offset >= this.buffer.duration) {\n // Replaying after the buffer finished naturally (or after seeking\n // exactly to its end) must restart from zero and update the exposed\n // position immediately, before the next animation-frame tick.\n this.offset = 0;\n this._state.update((s) => ({ ...s, currentTime: 0 }));\n }\n\n const myToken = ++this.playToken;\n this.source = this.ctx.createBufferSource();\n this.source.buffer = this.buffer;\n this.source.playbackRate.value = this.rate;\n this.source.connect(this.gain);\n this.source.onended = () => {\n if (myToken !== this.playToken) return; // stopped intentionally (pause/seek/rate-change), not a real \"ended\"\n this.stopTimeTracking();\n this.offset = this.buffer.duration;\n this.source = null;\n this._state.update((s) => ({ ...s, playback: 'ended', currentTime: this.buffer.duration }));\n };\n this.startedAt = this.ctx.currentTime;\n this.source.start(0, this.offset);\n this._state.update((s) => ({ ...s, playback: 'playing' }));\n this.startTimeTracking();\n }\n\n pause(): void {\n if (!this.source) return;\n this.offset = this.currentPosition();\n this.playToken++; // the upcoming onended (if it fires at all) is now stale\n this.source.stop();\n this.source = null;\n this.stopTimeTracking();\n this._state.update((s) => ({ ...s, playback: 'paused', currentTime: this.offset }));\n }\n\n seek(time: number): void {\n const wasPlaying = this._state().playback === 'playing';\n this.offset = Math.min(Math.max(time, 0), this.buffer.duration);\n if (this.source) {\n this.playToken++; // stale-onended guard — this stop is intentional, not the buffer actually ending\n this.source.stop();\n this.source = null;\n }\n this._state.update((s) => ({ ...s, currentTime: this.offset, playback: wasPlaying ? s.playback : 'paused' }));\n if (wasPlaying) void this.play();\n }\n\n setVolume(volume: number): void {\n this.volume = Math.min(Math.max(volume, 0), 1);\n if (!this.muted) this.gain.gain.value = this.volume;\n this._state.update((s) => ({ ...s, volume: this.volume }));\n }\n\n setMuted(muted: boolean): void {\n this.muted = muted;\n this.gain.gain.value = muted ? 0 : this.volume;\n this._state.update((s) => ({ ...s, muted }));\n }\n\n setPlaybackRate(rate: number): void {\n if (this.source && this._state().playback === 'playing') {\n // Re-baseline position bookkeeping BEFORE changing rate, or the\n // offset+elapsed*rate formula would retroactively (and incorrectly)\n // apply the new rate to time that already played at the old one.\n this.offset = this.currentPosition();\n this.startedAt = this.ctx.currentTime;\n this.source.playbackRate.value = rate;\n }\n this.rate = rate;\n this._state.update((s) => ({ ...s, playbackRate: rate }));\n }\n\n async load(): Promise<void> {\n /* buffer is already decoded at construction time */\n }\n\n destroy(): void {\n this.playToken++;\n this.stopTimeTracking();\n this.source?.stop();\n this.source = null;\n this.gain.disconnect();\n this._state.update((s) => ({ ...s, playback: 'destroyed' }));\n }\n\n private currentPosition(): number {\n if (!this.source) return this.offset;\n return Math.min(this.offset + (this.ctx.currentTime - this.startedAt) * this.rate, this.buffer.duration);\n }\n\n /** Drives `currentTime` for the UI while actually playing — never runs during pause/ended/destroyed, so there's no animation loop burning frames when nothing is moving. */\n private startTimeTracking(): void {\n if (this.rafId !== null || typeof requestAnimationFrame === 'undefined') return;\n const tick = () => {\n if (this._state().playback !== 'playing') {\n this.rafId = null;\n return;\n }\n const t = this.currentPosition();\n if (t !== this._state().currentTime) {\n this._state.update((s) => ({ ...s, currentTime: t }));\n }\n this.rafId = requestAnimationFrame(tick);\n };\n this.rafId = requestAnimationFrame(tick);\n }\n\n private stopTimeTracking(): void {\n if (this.rafId !== null && typeof cancelAnimationFrame !== 'undefined') {\n cancelAnimationFrame(this.rafId);\n }\n this.rafId = null;\n }\n}\n","import { EnvironmentProviders, makeEnvironmentProviders, Provider, Type } from '@angular/core';\nimport {\n NGX_MEDIA_CONFIG,\n NGX_MEDIA_CONFIG_DEFAULTS,\n NGX_MEDIA_DECODER,\n NGX_MEDIA_REQUEST_HANDLER,\n NgxMediaConfig,\n NgxMediaRequestHandler,\n} from '../decoders/decoder.tokens';\nimport { NgxMediaDecoder } from '../decoders/decoder.interface';\n\n/**\n * Root-level setup: `bootstrapApplication(App, { providers: [provideNgxMedia({...})] })`.\n * The supplied config is merged over the library's own defaults, not\n * replacing them outright — `provideNgxMedia({ preload: 'auto' })` must not\n * silently drop `maxConcurrentDecoderProbes` and leave it `undefined`.\n */\nexport function provideNgxMedia(config?: Partial<NgxMediaConfig>): EnvironmentProviders {\n const merged: NgxMediaConfig = { ...NGX_MEDIA_CONFIG_DEFAULTS, ...config };\n return makeEnvironmentProviders([{ provide: NGX_MEDIA_CONFIG, useValue: merged }]);\n}\n\n/**\n * Registers a decoder plugin into the `NGX_MEDIA_DECODER` multi-provider\n * token. Accepts a class (instantiated via DI, so it can itself inject\n * services) or a ready-made instance for simple cases.\n *\n * bootstrapApplication(AppComponent, {\n * providers: [provideNgxMediaDecoder(My3gpDecoder)],\n * });\n */\nexport function provideNgxMediaDecoder(\n decoder: Type<NgxMediaDecoder> | NgxMediaDecoder,\n): EnvironmentProviders {\n const provider: Provider =\n typeof decoder === 'function'\n ? { provide: NGX_MEDIA_DECODER, useClass: decoder, multi: true }\n : { provide: NGX_MEDIA_DECODER, useValue: decoder, multi: true };\n return makeEnvironmentProviders([provider]);\n}\n\n/** Registers a custom network layer (auth headers, signed URLs, a non-fetch HTTP client, ...). */\nexport function provideNgxMediaRequestHandler(handler: NgxMediaRequestHandler): EnvironmentProviders {\n return makeEnvironmentProviders([{ provide: NGX_MEDIA_REQUEST_HANDLER, useValue: handler }]);\n}\n","// New primary component\nexport * from './components/ngx-media-control';\n\n// Contracts / types\nexport * from './contracts/media-source';\nexport * from './contracts/media-state';\nexport * from './contracts/media-error';\n\n// Engine contracts (public so advanced consumers can implement their own engine/decoder)\nexport * from './engines/media-engine.interface';\nexport * from './decoders/decoder.interface';\nexport * from './decoders/wasm-decoder.base';\n/**\n * `NativeMediaEngine` is otherwise an internal implementation detail, but\n * it's exported here for one specific reason: a WASM decoder that\n * transcodes an unsupported format into a natively-playable one (the\n * `@ffmpeg/ffmpeg` pattern — see `decoders/ffmpeg-transcode-decoder.example.ts`)\n * needs a way to hand the result back as a real `NgxMediaEngine`, and\n * wrapping a transcoded `Blob` in the same native `<audio>`/`<video>`\n * element the fast path already uses is simpler and more correct than\n * reimplementing playback. Decoder authors are the intended audience for\n * this export, not component consumers.\n */\nexport { NativeMediaEngine } from './engines/native-media-engine';\n\n// DI: tokens + provider helpers\nexport * from './decoders/decoder.tokens';\nexport * from './providers/provide-ngx-media';\n\n// Utilities consumers may find useful directly\nexport * from './utils/format-time';\nexport * from './utils/capabilities';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}