import { DOCUMENT } from '@angular/common'; import { Injectable, inject } from '@angular/core'; import { environment } from '../../../../../environments/environment'; export interface ExperimentalVlcPlayerOptions { container: HTMLElement; sourceUrl: string; filename: string; mime: string; } export interface ExperimentalVlcPlayerHandle { destroy?: () => void; } export interface ExperimentalVlcRuntime { createPlayer: (options: ExperimentalVlcPlayerOptions) => ExperimentalVlcPlayerHandle | Promise; isPlaceholder?: boolean; } declare global { interface Window { MetoYouVlcJs?: ExperimentalVlcRuntime; } } const VLC_RUNTIME_SCRIPT_URL = environment.experimentalMedia.vlcRuntimeScriptUrl; @Injectable({ providedIn: 'root' }) export class ExperimentalVlcRuntimeService { private readonly document = inject(DOCUMENT); private runtimeLoadPromise: Promise | null = null; async createPlayer(options: ExperimentalVlcPlayerOptions): Promise { const runtime = await this.loadRuntime(); if (runtime.isPlaceholder) { throw new Error('No VLC.js runtime is bundled. Use Open in Electron, or replace /vlcjs/metoyou-vlc-player.js with a real runtime adapter.'); } return runtime.createPlayer(options); } async hasBundledRuntime(): Promise { try { const runtime = await this.loadRuntime(); return !!runtime.createPlayer && !runtime.isPlaceholder; } catch { return false; } } private loadRuntime(): Promise { if (this.document.defaultView?.MetoYouVlcJs?.createPlayer) { return Promise.resolve(this.document.defaultView.MetoYouVlcJs); } this.runtimeLoadPromise ??= new Promise((resolve, reject) => { const script = this.document.createElement('script'); script.src = VLC_RUNTIME_SCRIPT_URL; script.async = true; script.onload = () => { const runtime = this.document.defaultView?.MetoYouVlcJs; if (!runtime?.createPlayer) { reject(new Error('The experimental VLC.js runtime did not register a MetoYouVlcJs.createPlayer adapter.')); return; } resolve(runtime); }; script.onerror = () => reject(new Error(`The experimental VLC.js runtime was not found at ${VLC_RUNTIME_SCRIPT_URL}.`)); this.document.head.appendChild(script); }); return this.runtimeLoadPromise; } }