@scarlett-player/core 0.4.1 → 0.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e={current:null};function t(t){e.current=t,exports.currentEffect=t}function r(){return e.current}exports.currentEffect=null;class s{constructor(e){this.subscribers=new Set,this.value=e}get(){return exports.currentEffect&&this.subscribers.add(exports.currentEffect),this.value}set(e){Object.is(this.value,e)||(this.value=e,this.notify())}update(e){this.set(e(this.value))}subscribe(e){return this.subscribers.add(e),()=>this.subscribers.delete(e)}notify(){this.subscribers.forEach(e=>{try{e()}catch(t){console.error("[Scarlett Player] Error in signal subscriber:",t)}})}destroy(){this.subscribers.clear()}getSubscriberCount(){return this.subscribers.size}}function i(e){return new s(e)}class n{constructor(e){this.dirty=!0,this.subscribers=new Set,this.dependencies=new Set,this.computation=e,this.invalidateCallback=()=>this.invalidate()}get(){if(this.dirty){const e=r();t(this.invalidateCallback);try{this.value=this.computation(),this.dirty=!1}finally{t(e)}}return exports.currentEffect&&this.subscribers.add(exports.currentEffect),this.value}invalidate(){const e=this.dirty;this.dirty=!0,(!e||this.subscribers.size>0)&&this.notifySubscribers()}subscribe(e){return this.subscribers.add(e),()=>this.subscribers.delete(e)}notifySubscribers(){this.subscribers.forEach(e=>{try{e()}catch(t){console.error("[Scarlett Player] Error in computed subscriber:",t)}})}destroy(){this.dependencies.forEach(e=>e()),this.dependencies.clear(),this.subscribers.clear(),this.value=void 0,this.dirty=!0}getSubscriberCount(){return this.subscribers.size}}const a={playbackState:"idle",playing:!1,paused:!0,ended:!1,buffering:!1,waiting:!1,seeking:!1,currentTime:0,duration:NaN,buffered:null,bufferedAmount:0,mediaType:"unknown",source:null,title:"",poster:"",volume:1,muted:!1,playbackRate:1,fullscreen:!1,pip:!1,controlsVisible:!0,qualities:[],currentQuality:null,audioTracks:[],currentAudioTrack:null,textTracks:[],currentTextTrack:null,live:!1,liveEdge:!0,seekableRange:null,liveLatency:0,lowLatencyMode:!1,chapters:[],currentChapter:null,error:null,bandwidth:0,autoplay:!1,loop:!1,airplayAvailable:!1,airplayActive:!1,chromecastAvailable:!1,chromecastActive:!1,interacting:!1,hovering:!1,focused:!1};class o{constructor(e){this.signals=new Map,this.changeSubscribers=new Set,this.initializeSignals(e)}initializeSignals(e){const t={...a,...e};for(const[r,s]of Object.entries(t)){const e=r,t=i(s);t.subscribe(()=>{this.notifyChangeSubscribers(e)}),this.signals.set(e,t)}}get(e){const t=this.signals.get(e);if(!t)throw new Error(`[StateManager] Unknown state key: ${e}`);return t}getValue(e){return this.get(e).get()}set(e,t){this.get(e).set(t)}update(e){for(const[t,r]of Object.entries(e)){const e=t;this.signals.has(e)&&this.set(e,r)}}subscribeToKey(e,t){const r=this.get(e);return r.subscribe(()=>{t(r.get())})}subscribe(e){return this.changeSubscribers.add(e),()=>this.changeSubscribers.delete(e)}notifyChangeSubscribers(e){const t=this.get(e).get(),r={key:e,value:t,previousValue:t};this.changeSubscribers.forEach(e=>{try{e(r)}catch(t){console.error("[StateManager] Error in change subscriber:",t)}})}reset(){this.update(a)}resetKey(e){const t=a[e];this.set(e,t)}snapshot(){const e={};for(const[t,r]of this.signals)e[t]=r.get();return Object.freeze(e)}getSubscriberCount(e){return this.signals.get(e)?.getSubscriberCount()??0}destroy(){this.signals.forEach(e=>e.destroy()),this.signals.clear(),this.changeSubscribers.clear()}}const l={maxListeners:100,async:!1,interceptors:!0};class u{constructor(e){this.listeners=new Map,this.onceListeners=new Map,this.interceptors=new Map,this.options={...l,...e}}on(e,t){this.listeners.has(e)||this.listeners.set(e,new Set);return this.listeners.get(e).add(t),this.checkMaxListeners(e),()=>this.off(e,t)}once(e,t){this.onceListeners.has(e)||this.onceListeners.set(e,new Set);const r=this.onceListeners.get(e);return r.add(t),this.listeners.has(e)||this.listeners.set(e,new Set),()=>{r.delete(t)}}off(e,t){const r=this.listeners.get(e);r&&(r.delete(t),0===r.size&&this.listeners.delete(e));const s=this.onceListeners.get(e);s&&(s.delete(t),0===s.size&&this.onceListeners.delete(e))}emit(e,t){const r=this.runInterceptors(e,t);if(null===r)return;const s=this.listeners.get(e);if(s){Array.from(s).forEach(e=>{this.safeCallHandler(e,r)})}const i=this.onceListeners.get(e);if(i){Array.from(i).forEach(e=>{this.safeCallHandler(e,r)}),this.onceListeners.delete(e)}}async emitAsync(e,t){const r=await this.runInterceptorsAsync(e,t);if(null===r)return;const s=this.listeners.get(e);if(s){const e=Array.from(s).map(e=>this.safeCallHandlerAsync(e,r));await Promise.all(e)}const i=this.onceListeners.get(e);if(i){const t=Array.from(i).map(e=>this.safeCallHandlerAsync(e,r));await Promise.all(t),this.onceListeners.delete(e)}}intercept(e,t){if(!this.options.interceptors)return()=>{};this.interceptors.has(e)||this.interceptors.set(e,new Set);const r=this.interceptors.get(e);return r.add(t),()=>{r.delete(t),0===r.size&&this.interceptors.delete(e)}}removeAllListeners(e){e?(this.listeners.delete(e),this.onceListeners.delete(e)):(this.listeners.clear(),this.onceListeners.clear())}listenerCount(e){return(this.listeners.get(e)?.size??0)+(this.onceListeners.get(e)?.size??0)}destroy(){this.listeners.clear(),this.onceListeners.clear(),this.interceptors.clear()}runInterceptors(e,t){if(!this.options.interceptors)return t;const r=this.interceptors.get(e);if(!r||0===r.size)return t;let s=t;for(const n of r)try{if(s=n(s),null===s)return null}catch(i){console.error("[EventBus] Error in interceptor:",i)}return s}async runInterceptorsAsync(e,t){if(!this.options.interceptors)return t;const r=this.interceptors.get(e);if(!r||0===r.size)return t;let s=t;for(const n of r)try{const e=n(s);if(s=e instanceof Promise?await e:e,null===s)return null}catch(i){console.error("[EventBus] Error in interceptor:",i)}return s}safeCallHandler(e,t){try{e(t)}catch(r){console.error("[EventBus] Error in event handler:",r)}}async safeCallHandlerAsync(e,t){try{const r=e(t);r instanceof Promise&&await r}catch(r){console.error("[EventBus] Error in event handler:",r)}}checkMaxListeners(e){const t=this.listenerCount(e);t>this.options.maxListeners&&console.warn(`[EventBus] Max listeners (${this.options.maxListeners}) exceeded for event: ${e}. Current count: ${t}. This may indicate a memory leak.`)}}const c=["debug","info","warn","error"],h=e=>{const t=`${e.scope?`[${e.scope}]`:"[ScarlettPlayer]"} ${e.message}`,r=e.metadata??"";switch(e.level){case"debug":console.debug(t,r);break;case"info":console.info(t,r);break;case"warn":console.warn(t,r);break;case"error":console.error(t,r)}};class g{constructor(e){this.level=e?.level??"warn",this.scope=e?.scope,this.enabled=e?.enabled??!0,this.handlers=e?.handlers??[h]}child(e){return new g({level:this.level,scope:this.scope?`${this.scope}:${e}`:e,enabled:this.enabled,handlers:this.handlers})}debug(e,t){this.log("debug",e,t)}info(e,t){this.log("info",e,t)}warn(e,t){this.log("warn",e,t)}error(e,t){this.log("error",e,t)}setLevel(e){this.level=e}setEnabled(e){this.enabled=e}addHandler(e){this.handlers.push(e)}removeHandler(e){const t=this.handlers.indexOf(e);-1!==t&&this.handlers.splice(t,1)}log(e,t,r){if(!this.enabled||!this.shouldLog(e))return;const s={level:e,message:t,timestamp:Date.now(),scope:this.scope,metadata:r};for(const n of this.handlers)try{n(s)}catch(i){console.error("[Logger] Handler error:",i)}}shouldLog(e){return c.indexOf(e)>=c.indexOf(this.level)}}var d=(e=>(e.SOURCE_NOT_SUPPORTED="SOURCE_NOT_SUPPORTED",e.SOURCE_LOAD_FAILED="SOURCE_LOAD_FAILED",e.PROVIDER_NOT_FOUND="PROVIDER_NOT_FOUND",e.PROVIDER_SETUP_FAILED="PROVIDER_SETUP_FAILED",e.PLUGIN_SETUP_FAILED="PLUGIN_SETUP_FAILED",e.PLUGIN_NOT_FOUND="PLUGIN_NOT_FOUND",e.PLAYBACK_FAILED="PLAYBACK_FAILED",e.MEDIA_DECODE_ERROR="MEDIA_DECODE_ERROR",e.MEDIA_NETWORK_ERROR="MEDIA_NETWORK_ERROR",e.UNKNOWN_ERROR="UNKNOWN_ERROR",e))(d||{});class p{constructor(e,t,r){this.errors=[],this.eventBus=e,this.logger=t,this.maxHistory=r?.maxHistory??10}handle(e,t){const r=this.normalizeError(e,t);return this.addToHistory(r),this.logError(r),this.eventBus.emit("error",r),r}throw(e,t,r){const s={code:e,message:t,fatal:r?.fatal??this.isFatalCode(e),timestamp:Date.now(),context:r?.context,originalError:r?.originalError};return this.handle(s,r?.context)}getHistory(){return[...this.errors]}getLastError(){return this.errors[this.errors.length-1]??null}clearHistory(){this.errors=[]}hasFatalError(){return this.errors.some(e=>e.fatal)}normalizeError(e,t){return this.isPlayerError(e)?{...e,context:{...e.context,...t}}:{code:this.getErrorCode(e),message:e.message,fatal:this.isFatal(e),timestamp:Date.now(),context:t,originalError:e}}getErrorCode(e){const t=e.message.toLowerCase();return t.includes("network")?"MEDIA_NETWORK_ERROR":t.includes("decode")?"MEDIA_DECODE_ERROR":t.includes("source")?"SOURCE_LOAD_FAILED":t.includes("plugin")?"PLUGIN_SETUP_FAILED":t.includes("provider")?"PROVIDER_SETUP_FAILED":"UNKNOWN_ERROR"}isFatal(e){return this.isFatalCode(this.getErrorCode(e))}isFatalCode(e){return["SOURCE_NOT_SUPPORTED","PROVIDER_NOT_FOUND","MEDIA_DECODE_ERROR"].includes(e)}isPlayerError(e){return"object"==typeof e&&null!==e&&"code"in e&&"message"in e&&"fatal"in e&&"timestamp"in e}addToHistory(e){this.errors.push(e),this.errors.length>this.maxHistory&&this.errors.shift()}logError(e){const t=`[${e.code}] ${e.message}`;e.fatal?this.logger.error(t,{code:e.code,context:e.context}):this.logger.warn(t,{code:e.code,context:e.context})}}class y{constructor(e,t){this.cleanupFns=[],this.pluginId=e,this.stateManager=t.stateManager,this.eventBus=t.eventBus,this.container=t.container,this.getPluginFn=t.getPlugin,this.logger={debug:(r,s)=>t.logger.debug(`[${e}] ${r}`,s),info:(r,s)=>t.logger.info(`[${e}] ${r}`,s),warn:(r,s)=>t.logger.warn(`[${e}] ${r}`,s),error:(r,s)=>t.logger.error(`[${e}] ${r}`,s)}}getState(e){return this.stateManager.getValue(e)}setState(e,t){this.stateManager.set(e,t)}on(e,t){return this.eventBus.on(e,t)}off(e,t){this.eventBus.off(e,t)}emit(e,t){this.eventBus.emit(e,t)}getPlugin(e){return this.getPluginFn(e)}onDestroy(e){this.cleanupFns.push(e)}subscribeToState(e){return this.stateManager.subscribe(e)}runCleanups(){for(const t of this.cleanupFns)try{t()}catch(e){this.logger.error("Cleanup function failed",{error:e})}this.cleanupFns=[]}getCleanupFns(){return this.cleanupFns}}class f{constructor(e,t,r,s){this.plugins=new Map,this.eventBus=e,this.stateManager=t,this.logger=r,this.container=s.container}register(e,t){if(this.plugins.has(e.id))throw new Error(`Plugin "${e.id}" is already registered`);this.validatePlugin(e);const r=new y(e.id,{stateManager:this.stateManager,eventBus:this.eventBus,logger:this.logger,container:this.container,getPlugin:e=>this.getReadyPlugin(e)});this.plugins.set(e.id,{plugin:e,state:"registered",config:t,cleanupFns:[],api:r}),this.logger.info(`Plugin registered: ${e.id}`),this.eventBus.emit("plugin:registered",{name:e.id,type:e.type})}async unregister(e){const t=this.plugins.get(e);t&&("ready"===t.state&&await this.destroyPlugin(e),this.plugins.delete(e),this.logger.info(`Plugin unregistered: ${e}`))}async initAll(){const e=this.resolveDependencyOrder();for(const t of e)await this.initPlugin(t)}async initPlugin(e){const t=this.plugins.get(e);if(!t)throw new Error(`Plugin "${e}" not found`);if("ready"!==t.state){if("initializing"===t.state)throw new Error(`Plugin "${e}" is already initializing (possible circular dependency)`);for(const r of t.plugin.dependencies||[]){const t=this.plugins.get(r);if(!t)throw new Error(`Plugin "${e}" depends on missing plugin "${r}"`);"ready"!==t.state&&await this.initPlugin(r)}try{if(t.state="initializing",t.plugin.onStateChange){const e=this.stateManager.subscribe(t.plugin.onStateChange.bind(t.plugin));t.api.onDestroy(e)}if(t.plugin.onError){const e=this.eventBus.on("error",e=>{t.plugin.onError?.(e.originalError||new Error(e.message))});t.api.onDestroy(e)}await t.plugin.init(t.api,t.config),t.state="ready",this.logger.info(`Plugin ready: ${e}`),this.eventBus.emit("plugin:active",{name:e})}catch(r){throw t.state="error",t.error=r,this.logger.error(`Plugin init failed: ${e}`,{error:r}),this.eventBus.emit("plugin:error",{name:e,error:r}),r}}}async destroyAll(){const e=this.resolveDependencyOrder().reverse();for(const t of e)await this.destroyPlugin(t)}async destroyPlugin(e){const t=this.plugins.get(e);if(t&&"ready"===t.state)try{await t.plugin.destroy(),t.api.runCleanups(),t.state="registered",this.logger.info(`Plugin destroyed: ${e}`),this.eventBus.emit("plugin:destroyed",{name:e})}catch(r){this.logger.error(`Plugin destroy failed: ${e}`,{error:r}),t.state="registered"}}getPlugin(e){const t=this.plugins.get(e);return t?t.plugin:null}getReadyPlugin(e){const t=this.plugins.get(e);return"ready"===t?.state?t.plugin:null}hasPlugin(e){return this.plugins.has(e)}getPluginState(e){return this.plugins.get(e)?.state??null}getPluginIds(){return Array.from(this.plugins.keys())}getReadyPlugins(){return Array.from(this.plugins.values()).filter(e=>"ready"===e.state).map(e=>e.plugin)}getPluginsByType(e){return Array.from(this.plugins.values()).filter(t=>t.plugin.type===e).map(e=>e.plugin)}selectProvider(e){const t=this.getPluginsByType("provider");for(const r of t){const t=r.canPlay;if("function"==typeof t&&t(e))return r}return null}resolveDependencyOrder(){const e=new Set,t=new Set,r=[],s=(i,n=[])=>{if(e.has(i))return;if(t.has(i)){const e=[...n,i].join(" -> ");throw new Error(`Circular dependency detected: ${e}`)}const a=this.plugins.get(i);if(a){t.add(i);for(const e of a.plugin.dependencies||[])this.plugins.has(e)&&s(e,[...n,i]);t.delete(i),e.add(i),r.push(i)}};for(const i of this.plugins.keys())s(i);return r}validatePlugin(e){if(!e.id||"string"!=typeof e.id)throw new Error("Plugin must have a valid id");if(!e.name||"string"!=typeof e.name)throw new Error(`Plugin "${e.id}" must have a valid name`);if(!e.version||"string"!=typeof e.version)throw new Error(`Plugin "${e.id}" must have a valid version`);if(!e.type||"string"!=typeof e.type)throw new Error(`Plugin "${e.id}" must have a valid type`);if("function"!=typeof e.init)throw new Error(`Plugin "${e.id}" must have an init() method`);if("function"!=typeof e.destroy)throw new Error(`Plugin "${e.id}" must have a destroy() method`)}}class m{constructor(e){if(this._currentProvider=null,this.destroyed=!1,this.seekingWhilePlaying=!1,this.seekResumeTimeout=null,"string"==typeof e.container){const t=document.querySelector(e.container);if(!(t&&t instanceof HTMLElement))throw new Error(`ScarlettPlayer: container not found: ${e.container}`);this.container=t}else{if(!(e.container instanceof HTMLElement))throw new Error("ScarlettPlayer requires a valid HTMLElement container or CSS selector");this.container=e.container}if(this.initialSrc=e.src,this.eventBus=new u,this.stateManager=new o({autoplay:e.autoplay??!1,loop:e.loop??!1,volume:e.volume??1,muted:e.muted??!1,poster:e.poster??""}),this.logger=new g({level:e.logLevel??"warn",scope:"ScarlettPlayer"}),this.errorHandler=new p(this.eventBus,this.logger),this.pluginManager=new f(this.eventBus,this.stateManager,this.logger,{container:this.container}),e.plugins)for(const t of e.plugins)this.pluginManager.register(t);this.logger.info("ScarlettPlayer initialized",{autoplay:e.autoplay,plugins:e.plugins?.length??0}),this.eventBus.emit("player:ready",void 0)}async init(){this.checkDestroyed();for(const[e,t]of this.pluginManager.plugins)"provider"!==t.plugin.type&&"registered"===t.state&&await this.pluginManager.initPlugin(e);return this.initialSrc&&await this.load(this.initialSrc),Promise.resolve()}async load(e){this.checkDestroyed();try{if(this.logger.info("Loading source",{source:e}),this.stateManager.update({playing:!1,paused:!0,ended:!1,buffering:!0,currentTime:0,duration:0,bufferedAmount:0,playbackState:"loading"}),this._currentProvider){const e=this._currentProvider.id;this.logger.info("Destroying previous provider",{provider:e}),await this.pluginManager.destroyPlugin(e),this._currentProvider=null}const t=this.pluginManager.selectProvider(e);if(!t)return void this.errorHandler.throw(d.PROVIDER_NOT_FOUND,`No provider found for source: ${e}`,{fatal:!0,context:{source:e}});this._currentProvider=t,this.logger.info("Provider selected",{provider:t.id}),await this.pluginManager.initPlugin(t.id),this.stateManager.set("source",{src:e,type:this.detectMimeType(e)}),"function"==typeof t.loadSource&&await t.loadSource(e),this.stateManager.getValue("autoplay")&&await this.play()}catch(t){this.errorHandler.handle(t,{operation:"load",source:e})}}async play(){this.checkDestroyed();try{this.logger.debug("Play requested"),this.eventBus.emit("playback:play",void 0)}catch(e){this.errorHandler.handle(e,{operation:"play"})}}pause(){this.checkDestroyed();try{this.logger.debug("Pause requested"),this.seekingWhilePlaying=!1,null!==this.seekResumeTimeout&&(clearTimeout(this.seekResumeTimeout),this.seekResumeTimeout=null),this.eventBus.emit("playback:pause",void 0)}catch(e){this.errorHandler.handle(e,{operation:"pause"})}}seek(e){this.checkDestroyed();try{this.logger.debug("Seek requested",{time:e});this.stateManager.getValue("playing")&&(this.seekingWhilePlaying=!0),null!==this.seekResumeTimeout&&(clearTimeout(this.seekResumeTimeout),this.seekResumeTimeout=null),this.eventBus.emit("playback:seeking",{time:e}),this.stateManager.set("currentTime",e),this.seekingWhilePlaying&&(this.seekResumeTimeout=setTimeout(()=>{this.seekingWhilePlaying&&this.stateManager.getValue("playing")&&(this.logger.debug("Resuming playback after seek"),this.seekingWhilePlaying=!1,this.eventBus.emit("playback:play",void 0)),this.seekResumeTimeout=null},300))}catch(t){this.errorHandler.handle(t,{operation:"seek",time:e})}}setVolume(e){this.checkDestroyed();const t=Math.max(0,Math.min(1,e));this.stateManager.set("volume",t),this.eventBus.emit("volume:change",{volume:t,muted:this.stateManager.getValue("muted")})}setMuted(e){this.checkDestroyed(),this.stateManager.set("muted",e),this.eventBus.emit("volume:mute",{muted:e})}setPlaybackRate(e){this.checkDestroyed(),this.stateManager.set("playbackRate",e),this.eventBus.emit("playback:ratechange",{rate:e})}setAutoplay(e){this.checkDestroyed(),this.stateManager.set("autoplay",e),this.logger.debug("Autoplay set",{autoplay:e})}on(e,t){return this.checkDestroyed(),this.eventBus.on(e,t)}once(e,t){return this.checkDestroyed(),this.eventBus.once(e,t)}getPlugin(e){return this.checkDestroyed(),this.pluginManager.getPlugin(e)}registerPlugin(e){this.checkDestroyed(),this.pluginManager.register(e)}getState(){return this.checkDestroyed(),this.stateManager.snapshot()}getQualities(){if(this.checkDestroyed(),!this._currentProvider)return[];const e=this._currentProvider;return"function"==typeof e.getLevels?e.getLevels():[]}setQuality(e){if(this.checkDestroyed(),!this._currentProvider)return void this.logger.warn("No provider available for quality change");const t=this._currentProvider;"function"==typeof t.setLevel&&(t.setLevel(e),this.eventBus.emit("quality:change",{quality:-1===e?"auto":`level-${e}`,auto:-1===e}))}getCurrentQuality(){if(this.checkDestroyed(),!this._currentProvider)return-1;const e=this._currentProvider;return"function"==typeof e.getCurrentLevel?e.getCurrentLevel():-1}async requestFullscreen(){this.checkDestroyed();try{this.container.requestFullscreen?await this.container.requestFullscreen():this.container.webkitRequestFullscreen&&await this.container.webkitRequestFullscreen(),this.stateManager.set("fullscreen",!0),this.eventBus.emit("fullscreen:change",{fullscreen:!0})}catch(e){this.logger.error("Fullscreen request failed",{error:e})}}async exitFullscreen(){this.checkDestroyed();try{document.exitFullscreen?await document.exitFullscreen():document.webkitExitFullscreen&&await document.webkitExitFullscreen(),this.stateManager.set("fullscreen",!1),this.eventBus.emit("fullscreen:change",{fullscreen:!1})}catch(e){this.logger.error("Exit fullscreen failed",{error:e})}}async toggleFullscreen(){this.fullscreen?await this.exitFullscreen():await this.requestFullscreen()}requestAirPlay(){this.checkDestroyed();const e=this.pluginManager.getPlugin("airplay");e&&"function"==typeof e.showPicker?e.showPicker():this.logger.warn("AirPlay plugin not available")}async requestChromecast(){this.checkDestroyed();const e=this.pluginManager.getPlugin("chromecast");e&&"function"==typeof e.requestSession?await e.requestSession():this.logger.warn("Chromecast plugin not available")}stopCasting(){this.checkDestroyed();const e=this.pluginManager.getPlugin("airplay");e&&"function"==typeof e.stop&&e.stop();const t=this.pluginManager.getPlugin("chromecast");t&&"function"==typeof t.stopSession&&t.stopSession()}seekToLive(){this.checkDestroyed();if(!this.stateManager.getValue("live"))return void this.logger.warn("Not a live stream");if(this._currentProvider){const e=this._currentProvider;if("function"==typeof e.getLiveInfo){const t=e.getLiveInfo();if(void 0!==t?.liveSyncPosition)return void this.seek(t.liveSyncPosition)}}const e=this.stateManager.getValue("duration");e>0&&this.seek(e)}destroy(){this.destroyed||(this.logger.info("Destroying player"),null!==this.seekResumeTimeout&&(clearTimeout(this.seekResumeTimeout),this.seekResumeTimeout=null),this.eventBus.emit("player:destroy",void 0),this.pluginManager.destroyAll(),this.eventBus.destroy(),this.stateManager.destroy(),this.destroyed=!0,this.logger.info("Player destroyed"))}get playing(){return this.stateManager.getValue("playing")}get paused(){return this.stateManager.getValue("paused")}get currentTime(){return this.stateManager.getValue("currentTime")}get duration(){return this.stateManager.getValue("duration")}get volume(){return this.stateManager.getValue("volume")}get muted(){return this.stateManager.getValue("muted")}get playbackRate(){return this.stateManager.getValue("playbackRate")}get bufferedAmount(){return this.stateManager.getValue("bufferedAmount")}get currentProvider(){return this._currentProvider}get fullscreen(){return this.stateManager.getValue("fullscreen")}get live(){return this.stateManager.getValue("live")}get autoplay(){return this.stateManager.getValue("autoplay")}checkDestroyed(){if(this.destroyed)throw new Error("Cannot call methods on destroyed player")}detectMimeType(e){const t=e.split(".").pop()?.toLowerCase();switch(t){case"m3u8":return"application/x-mpegURL";case"mpd":return"application/dash+xml";case"mp4":default:return"video/mp4";case"webm":return"video/webm";case"ogg":return"video/ogg"}}}exports.Computed=n,exports.ErrorCode=d,exports.ErrorHandler=p,exports.EventBus=u,exports.Logger=g,exports.PluginAPI=y,exports.PluginManager=f,exports.ScarlettPlayer=m,exports.Signal=s,exports.StateManager=o,exports.computed=function(e){return new n(e)},exports.createLogger=function(e){return new g({scope:e})},exports.createPlayer=async function(e){const t=new m(e);return await t.init(),t},exports.effect=function(e){const r=()=>{t(r);try{e()}catch(s){throw console.error("[Scarlett Player] Error in effect:",s),s}finally{t(null)}};return r(),()=>{}},exports.getCurrentEffect=r,exports.setCurrentEffect=t,exports.signal=i;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e={current:null};function t(t){e.current=t,exports.currentEffect=t}function r(){return e.current}exports.currentEffect=null;class s{constructor(e){this.subscribers=new Set,this.value=e}get(){return exports.currentEffect&&this.subscribers.add(exports.currentEffect),this.value}set(e){Object.is(this.value,e)||(this.value=e,this.notify())}update(e){this.set(e(this.value))}subscribe(e){return this.subscribers.add(e),()=>this.subscribers.delete(e)}notify(){this.subscribers.forEach(e=>{try{e()}catch(t){console.error("[Scarlett Player] Error in signal subscriber:",t)}})}destroy(){this.subscribers.clear()}getSubscriberCount(){return this.subscribers.size}}function i(e){return new s(e)}class n{constructor(e){this.dirty=!0,this.subscribers=new Set,this.dependencies=new Set,this.computation=e,this.invalidateCallback=()=>this.invalidate()}get(){if(this.dirty){const e=r();t(this.invalidateCallback);try{this.value=this.computation(),this.dirty=!1}finally{t(e)}}return exports.currentEffect&&this.subscribers.add(exports.currentEffect),this.value}invalidate(){const e=this.dirty;this.dirty=!0,(!e||this.subscribers.size>0)&&this.notifySubscribers()}subscribe(e){return this.subscribers.add(e),()=>this.subscribers.delete(e)}notifySubscribers(){this.subscribers.forEach(e=>{try{e()}catch(t){console.error("[Scarlett Player] Error in computed subscriber:",t)}})}destroy(){this.dependencies.forEach(e=>e()),this.dependencies.clear(),this.subscribers.clear(),this.value=void 0,this.dirty=!0}getSubscriberCount(){return this.subscribers.size}}const a={playbackState:"idle",playing:!1,paused:!0,ended:!1,buffering:!1,waiting:!1,seeking:!1,currentTime:0,duration:NaN,buffered:null,bufferedAmount:0,mediaType:"unknown",source:null,title:"",poster:"",volume:1,muted:!1,playbackRate:1,fullscreen:!1,pip:!1,controlsVisible:!0,qualities:[],currentQuality:null,audioTracks:[],currentAudioTrack:null,textTracks:[],currentTextTrack:null,live:!1,liveEdge:!0,seekableRange:null,liveLatency:0,lowLatencyMode:!1,chapters:[],currentChapter:null,error:null,bandwidth:0,autoplay:!1,loop:!1,airplayAvailable:!1,airplayActive:!1,chromecastAvailable:!1,chromecastActive:!1,thumbnails:null,interacting:!1,hovering:!1,focused:!1};class o{constructor(e){this.signals=new Map,this.changeSubscribers=new Set,this.initializeSignals(e)}initializeSignals(e){const t={...a,...e};for(const[r,s]of Object.entries(t)){const e=r,t=i(s);t.subscribe(()=>{this.notifyChangeSubscribers(e)}),this.signals.set(e,t)}}get(e){const t=this.signals.get(e);if(!t)throw new Error(`[StateManager] Unknown state key: ${e}`);return t}getValue(e){return this.get(e).get()}set(e,t){this.get(e).set(t)}update(e){for(const[t,r]of Object.entries(e)){const e=t;this.signals.has(e)&&this.set(e,r)}}subscribeToKey(e,t){const r=this.get(e);return r.subscribe(()=>{t(r.get())})}subscribe(e){return this.changeSubscribers.add(e),()=>this.changeSubscribers.delete(e)}notifyChangeSubscribers(e){const t=this.get(e).get(),r={key:e,value:t,previousValue:t};this.changeSubscribers.forEach(e=>{try{e(r)}catch(t){console.error("[StateManager] Error in change subscriber:",t)}})}reset(){this.update(a)}resetKey(e){const t=a[e];this.set(e,t)}snapshot(){const e={};for(const[t,r]of this.signals)e[t]=r.get();return Object.freeze(e)}getSubscriberCount(e){return this.signals.get(e)?.getSubscriberCount()??0}destroy(){this.signals.forEach(e=>e.destroy()),this.signals.clear(),this.changeSubscribers.clear()}}const l={maxListeners:100,async:!1,interceptors:!0};class u{constructor(e){this.listeners=new Map,this.onceListeners=new Map,this.interceptors=new Map,this.options={...l,...e}}on(e,t){this.listeners.has(e)||this.listeners.set(e,new Set);return this.listeners.get(e).add(t),this.checkMaxListeners(e),()=>this.off(e,t)}once(e,t){this.onceListeners.has(e)||this.onceListeners.set(e,new Set);const r=this.onceListeners.get(e);return r.add(t),this.listeners.has(e)||this.listeners.set(e,new Set),()=>{r.delete(t)}}off(e,t){const r=this.listeners.get(e);r&&(r.delete(t),0===r.size&&this.listeners.delete(e));const s=this.onceListeners.get(e);s&&(s.delete(t),0===s.size&&this.onceListeners.delete(e))}emit(e,t){const r=this.runInterceptors(e,t);if(null===r)return;const s=this.listeners.get(e);if(s){Array.from(s).forEach(e=>{this.safeCallHandler(e,r)})}const i=this.onceListeners.get(e);if(i){Array.from(i).forEach(e=>{this.safeCallHandler(e,r)}),this.onceListeners.delete(e)}}async emitAsync(e,t){const r=await this.runInterceptorsAsync(e,t);if(null===r)return;const s=this.listeners.get(e);if(s){const e=Array.from(s).map(e=>this.safeCallHandlerAsync(e,r));await Promise.all(e)}const i=this.onceListeners.get(e);if(i){const t=Array.from(i).map(e=>this.safeCallHandlerAsync(e,r));await Promise.all(t),this.onceListeners.delete(e)}}intercept(e,t){if(!this.options.interceptors)return()=>{};this.interceptors.has(e)||this.interceptors.set(e,new Set);const r=this.interceptors.get(e);return r.add(t),()=>{r.delete(t),0===r.size&&this.interceptors.delete(e)}}removeAllListeners(e){e?(this.listeners.delete(e),this.onceListeners.delete(e)):(this.listeners.clear(),this.onceListeners.clear())}listenerCount(e){return(this.listeners.get(e)?.size??0)+(this.onceListeners.get(e)?.size??0)}destroy(){this.listeners.clear(),this.onceListeners.clear(),this.interceptors.clear()}runInterceptors(e,t){if(!this.options.interceptors)return t;const r=this.interceptors.get(e);if(!r||0===r.size)return t;let s=t;for(const n of r)try{if(s=n(s),null===s)return null}catch(i){console.error("[EventBus] Error in interceptor:",i)}return s}async runInterceptorsAsync(e,t){if(!this.options.interceptors)return t;const r=this.interceptors.get(e);if(!r||0===r.size)return t;let s=t;for(const n of r)try{const e=n(s);if(s=e instanceof Promise?await e:e,null===s)return null}catch(i){console.error("[EventBus] Error in interceptor:",i)}return s}safeCallHandler(e,t){try{e(t)}catch(r){console.error("[EventBus] Error in event handler:",r)}}async safeCallHandlerAsync(e,t){try{const r=e(t);r instanceof Promise&&await r}catch(r){console.error("[EventBus] Error in event handler:",r)}}checkMaxListeners(e){const t=this.listenerCount(e);t>this.options.maxListeners&&console.warn(`[EventBus] Max listeners (${this.options.maxListeners}) exceeded for event: ${e}. Current count: ${t}. This may indicate a memory leak.`)}}const c=["debug","info","warn","error"],h=e=>{const t=`${e.scope?`[${e.scope}]`:"[ScarlettPlayer]"} ${e.message}`,r=e.metadata??"";switch(e.level){case"debug":console.debug(t,r);break;case"info":console.info(t,r);break;case"warn":console.warn(t,r);break;case"error":console.error(t,r)}};class g{constructor(e){this.level=e?.level??"warn",this.scope=e?.scope,this.enabled=e?.enabled??!0,this.handlers=e?.handlers??[h]}child(e){return new g({level:this.level,scope:this.scope?`${this.scope}:${e}`:e,enabled:this.enabled,handlers:this.handlers})}debug(e,t){this.log("debug",e,t)}info(e,t){this.log("info",e,t)}warn(e,t){this.log("warn",e,t)}error(e,t){this.log("error",e,t)}setLevel(e){this.level=e}setEnabled(e){this.enabled=e}addHandler(e){this.handlers.push(e)}removeHandler(e){const t=this.handlers.indexOf(e);-1!==t&&this.handlers.splice(t,1)}log(e,t,r){if(!this.enabled||!this.shouldLog(e))return;const s={level:e,message:t,timestamp:Date.now(),scope:this.scope,metadata:r};for(const n of this.handlers)try{n(s)}catch(i){console.error("[Logger] Handler error:",i)}}shouldLog(e){return c.indexOf(e)>=c.indexOf(this.level)}}var d=(e=>(e.SOURCE_NOT_SUPPORTED="SOURCE_NOT_SUPPORTED",e.SOURCE_LOAD_FAILED="SOURCE_LOAD_FAILED",e.PROVIDER_NOT_FOUND="PROVIDER_NOT_FOUND",e.PROVIDER_SETUP_FAILED="PROVIDER_SETUP_FAILED",e.PLUGIN_SETUP_FAILED="PLUGIN_SETUP_FAILED",e.PLUGIN_NOT_FOUND="PLUGIN_NOT_FOUND",e.PLAYBACK_FAILED="PLAYBACK_FAILED",e.MEDIA_DECODE_ERROR="MEDIA_DECODE_ERROR",e.MEDIA_NETWORK_ERROR="MEDIA_NETWORK_ERROR",e.UNKNOWN_ERROR="UNKNOWN_ERROR",e))(d||{});class p{constructor(e,t,r){this.errors=[],this.eventBus=e,this.logger=t,this.maxHistory=r?.maxHistory??10}handle(e,t){const r=this.normalizeError(e,t);return this.addToHistory(r),this.logError(r),this.eventBus.emit("error",r),r}throw(e,t,r){const s={code:e,message:t,fatal:r?.fatal??this.isFatalCode(e),timestamp:Date.now(),context:r?.context,originalError:r?.originalError};return this.handle(s,r?.context)}getHistory(){return[...this.errors]}getLastError(){return this.errors[this.errors.length-1]??null}clearHistory(){this.errors=[]}hasFatalError(){return this.errors.some(e=>e.fatal)}normalizeError(e,t){return this.isPlayerError(e)?{...e,context:{...e.context,...t}}:{code:this.getErrorCode(e),message:e.message,fatal:this.isFatal(e),timestamp:Date.now(),context:t,originalError:e}}getErrorCode(e){const t=e.message.toLowerCase();return t.includes("network")?"MEDIA_NETWORK_ERROR":t.includes("decode")?"MEDIA_DECODE_ERROR":t.includes("source")?"SOURCE_LOAD_FAILED":t.includes("plugin")?"PLUGIN_SETUP_FAILED":t.includes("provider")?"PROVIDER_SETUP_FAILED":"UNKNOWN_ERROR"}isFatal(e){return this.isFatalCode(this.getErrorCode(e))}isFatalCode(e){return["SOURCE_NOT_SUPPORTED","PROVIDER_NOT_FOUND","MEDIA_DECODE_ERROR"].includes(e)}isPlayerError(e){return"object"==typeof e&&null!==e&&"code"in e&&"message"in e&&"fatal"in e&&"timestamp"in e}addToHistory(e){this.errors.push(e),this.errors.length>this.maxHistory&&this.errors.shift()}logError(e){const t=`[${e.code}] ${e.message}`;e.fatal?this.logger.error(t,{code:e.code,context:e.context}):this.logger.warn(t,{code:e.code,context:e.context})}}class y{constructor(e,t){this.cleanupFns=[],this.pluginId=e,this.stateManager=t.stateManager,this.eventBus=t.eventBus,this.container=t.container,this.getPluginFn=t.getPlugin,this.logger={debug:(r,s)=>t.logger.debug(`[${e}] ${r}`,s),info:(r,s)=>t.logger.info(`[${e}] ${r}`,s),warn:(r,s)=>t.logger.warn(`[${e}] ${r}`,s),error:(r,s)=>t.logger.error(`[${e}] ${r}`,s)}}getState(e){return this.stateManager.getValue(e)}setState(e,t){this.stateManager.set(e,t)}on(e,t){return this.eventBus.on(e,t)}off(e,t){this.eventBus.off(e,t)}emit(e,t){this.eventBus.emit(e,t)}getPlugin(e){return this.getPluginFn(e)}onDestroy(e){this.cleanupFns.push(e)}subscribeToState(e){return this.stateManager.subscribe(e)}runCleanups(){for(const t of this.cleanupFns)try{t()}catch(e){this.logger.error("Cleanup function failed",{error:e})}this.cleanupFns=[]}getCleanupFns(){return this.cleanupFns}}class f{constructor(e,t,r,s){this.plugins=new Map,this.eventBus=e,this.stateManager=t,this.logger=r,this.container=s.container}register(e,t){if(this.plugins.has(e.id))throw new Error(`Plugin "${e.id}" is already registered`);this.validatePlugin(e);const r=new y(e.id,{stateManager:this.stateManager,eventBus:this.eventBus,logger:this.logger,container:this.container,getPlugin:e=>this.getReadyPlugin(e)});this.plugins.set(e.id,{plugin:e,state:"registered",config:t,cleanupFns:[],api:r}),this.logger.info(`Plugin registered: ${e.id}`),this.eventBus.emit("plugin:registered",{name:e.id,type:e.type})}async unregister(e){const t=this.plugins.get(e);t&&("ready"===t.state&&await this.destroyPlugin(e),this.plugins.delete(e),this.logger.info(`Plugin unregistered: ${e}`))}async initAll(){const e=this.resolveDependencyOrder();for(const t of e)await this.initPlugin(t)}async initPlugin(e){const t=this.plugins.get(e);if(!t)throw new Error(`Plugin "${e}" not found`);if("ready"!==t.state){if("initializing"===t.state)throw new Error(`Plugin "${e}" is already initializing (possible circular dependency)`);for(const r of t.plugin.dependencies||[]){const t=this.plugins.get(r);if(!t)throw new Error(`Plugin "${e}" depends on missing plugin "${r}"`);"ready"!==t.state&&await this.initPlugin(r)}try{if(t.state="initializing",t.plugin.onStateChange){const e=this.stateManager.subscribe(t.plugin.onStateChange.bind(t.plugin));t.api.onDestroy(e)}if(t.plugin.onError){const e=this.eventBus.on("error",e=>{t.plugin.onError?.(e.originalError||new Error(e.message))});t.api.onDestroy(e)}await t.plugin.init(t.api,t.config),t.state="ready",this.logger.info(`Plugin ready: ${e}`),this.eventBus.emit("plugin:active",{name:e})}catch(r){throw t.state="error",t.error=r,this.logger.error(`Plugin init failed: ${e}`,{error:r}),this.eventBus.emit("plugin:error",{name:e,error:r}),r}}}async destroyAll(){const e=this.resolveDependencyOrder().reverse();for(const t of e)await this.destroyPlugin(t)}async destroyPlugin(e){const t=this.plugins.get(e);if(t&&"ready"===t.state)try{await t.plugin.destroy(),t.api.runCleanups(),t.state="registered",this.logger.info(`Plugin destroyed: ${e}`),this.eventBus.emit("plugin:destroyed",{name:e})}catch(r){this.logger.error(`Plugin destroy failed: ${e}`,{error:r}),t.state="registered"}}getPlugin(e){const t=this.plugins.get(e);return t?t.plugin:null}getReadyPlugin(e){const t=this.plugins.get(e);return"ready"===t?.state?t.plugin:null}hasPlugin(e){return this.plugins.has(e)}getPluginState(e){return this.plugins.get(e)?.state??null}getPluginIds(){return Array.from(this.plugins.keys())}getReadyPlugins(){return Array.from(this.plugins.values()).filter(e=>"ready"===e.state).map(e=>e.plugin)}getPluginsByType(e){return Array.from(this.plugins.values()).filter(t=>t.plugin.type===e).map(e=>e.plugin)}selectProvider(e){const t=this.getPluginsByType("provider");for(const r of t){const t=r.canPlay;if("function"==typeof t&&t(e))return r}return null}resolveDependencyOrder(){const e=new Set,t=new Set,r=[],s=(i,n=[])=>{if(e.has(i))return;if(t.has(i)){const e=[...n,i].join(" -> ");throw new Error(`Circular dependency detected: ${e}`)}const a=this.plugins.get(i);if(a){t.add(i);for(const e of a.plugin.dependencies||[])this.plugins.has(e)&&s(e,[...n,i]);t.delete(i),e.add(i),r.push(i)}};for(const i of this.plugins.keys())s(i);return r}validatePlugin(e){if(!e.id||"string"!=typeof e.id)throw new Error("Plugin must have a valid id");if(!e.name||"string"!=typeof e.name)throw new Error(`Plugin "${e.id}" must have a valid name`);if(!e.version||"string"!=typeof e.version)throw new Error(`Plugin "${e.id}" must have a valid version`);if(!e.type||"string"!=typeof e.type)throw new Error(`Plugin "${e.id}" must have a valid type`);if("function"!=typeof e.init)throw new Error(`Plugin "${e.id}" must have an init() method`);if("function"!=typeof e.destroy)throw new Error(`Plugin "${e.id}" must have a destroy() method`)}}class m{constructor(e){if(this._currentProvider=null,this.destroyed=!1,this.seekingWhilePlaying=!1,this.seekResumeTimeout=null,"string"==typeof e.container){const t=document.querySelector(e.container);if(!(t&&t instanceof HTMLElement))throw new Error(`ScarlettPlayer: container not found: ${e.container}`);this.container=t}else{if(!(e.container instanceof HTMLElement))throw new Error("ScarlettPlayer requires a valid HTMLElement container or CSS selector");this.container=e.container}if(this.initialSrc=e.src,this.eventBus=new u,this.stateManager=new o({autoplay:e.autoplay??!1,loop:e.loop??!1,volume:e.volume??1,muted:e.muted??!1,poster:e.poster??""}),this.logger=new g({level:e.logLevel??"warn",scope:"ScarlettPlayer"}),this.errorHandler=new p(this.eventBus,this.logger),this.pluginManager=new f(this.eventBus,this.stateManager,this.logger,{container:this.container}),e.plugins)for(const t of e.plugins)this.pluginManager.register(t);this.logger.info("ScarlettPlayer initialized",{autoplay:e.autoplay,plugins:e.plugins?.length??0}),this.eventBus.emit("player:ready",void 0)}async init(){this.checkDestroyed();for(const[e,t]of this.pluginManager.plugins)"provider"!==t.plugin.type&&"registered"===t.state&&await this.pluginManager.initPlugin(e);return this.initialSrc&&await this.load(this.initialSrc),Promise.resolve()}async load(e){this.checkDestroyed();try{if(this.logger.info("Loading source",{source:e}),this.stateManager.update({playing:!1,paused:!0,ended:!1,buffering:!0,currentTime:0,duration:0,bufferedAmount:0,playbackState:"loading"}),this._currentProvider){const e=this._currentProvider.id;this.logger.info("Destroying previous provider",{provider:e}),await this.pluginManager.destroyPlugin(e),this._currentProvider=null}const t=this.pluginManager.selectProvider(e);if(!t)return void this.errorHandler.throw(d.PROVIDER_NOT_FOUND,`No provider found for source: ${e}`,{fatal:!0,context:{source:e}});this._currentProvider=t,this.logger.info("Provider selected",{provider:t.id}),await this.pluginManager.initPlugin(t.id),this.stateManager.set("source",{src:e,type:this.detectMimeType(e)}),"function"==typeof t.loadSource&&await t.loadSource(e),this.stateManager.getValue("autoplay")&&await this.play()}catch(t){this.errorHandler.handle(t,{operation:"load",source:e})}}async play(){this.checkDestroyed();try{this.logger.debug("Play requested"),this.eventBus.emit("playback:play",void 0)}catch(e){this.errorHandler.handle(e,{operation:"play"})}}pause(){this.checkDestroyed();try{this.logger.debug("Pause requested"),this.seekingWhilePlaying=!1,null!==this.seekResumeTimeout&&(clearTimeout(this.seekResumeTimeout),this.seekResumeTimeout=null),this.eventBus.emit("playback:pause",void 0)}catch(e){this.errorHandler.handle(e,{operation:"pause"})}}seek(e){this.checkDestroyed();try{this.logger.debug("Seek requested",{time:e});this.stateManager.getValue("playing")&&(this.seekingWhilePlaying=!0),null!==this.seekResumeTimeout&&(clearTimeout(this.seekResumeTimeout),this.seekResumeTimeout=null),this.eventBus.emit("playback:seeking",{time:e}),this.stateManager.set("currentTime",e),this.seekingWhilePlaying&&(this.seekResumeTimeout=setTimeout(()=>{this.seekingWhilePlaying&&this.stateManager.getValue("playing")&&(this.logger.debug("Resuming playback after seek"),this.seekingWhilePlaying=!1,this.eventBus.emit("playback:play",void 0)),this.seekResumeTimeout=null},300))}catch(t){this.errorHandler.handle(t,{operation:"seek",time:e})}}setVolume(e){this.checkDestroyed();const t=Math.max(0,Math.min(1,e));this.stateManager.set("volume",t),this.eventBus.emit("volume:change",{volume:t,muted:this.stateManager.getValue("muted")})}setMuted(e){this.checkDestroyed(),this.stateManager.set("muted",e),this.eventBus.emit("volume:mute",{muted:e})}setPlaybackRate(e){this.checkDestroyed(),this.stateManager.set("playbackRate",e),this.eventBus.emit("playback:ratechange",{rate:e})}setAutoplay(e){this.checkDestroyed(),this.stateManager.set("autoplay",e),this.logger.debug("Autoplay set",{autoplay:e})}on(e,t){return this.checkDestroyed(),this.eventBus.on(e,t)}once(e,t){return this.checkDestroyed(),this.eventBus.once(e,t)}getPlugin(e){return this.checkDestroyed(),this.pluginManager.getPlugin(e)}registerPlugin(e){this.checkDestroyed(),this.pluginManager.register(e)}getState(){return this.checkDestroyed(),this.stateManager.snapshot()}getQualities(){if(this.checkDestroyed(),!this._currentProvider)return[];const e=this._currentProvider;return"function"==typeof e.getLevels?e.getLevels():[]}setQuality(e){if(this.checkDestroyed(),!this._currentProvider)return void this.logger.warn("No provider available for quality change");const t=this._currentProvider;"function"==typeof t.setLevel&&(t.setLevel(e),this.eventBus.emit("quality:change",{quality:-1===e?"auto":`level-${e}`,auto:-1===e}))}getCurrentQuality(){if(this.checkDestroyed(),!this._currentProvider)return-1;const e=this._currentProvider;return"function"==typeof e.getCurrentLevel?e.getCurrentLevel():-1}async requestFullscreen(){this.checkDestroyed();try{this.container.requestFullscreen?await this.container.requestFullscreen():this.container.webkitRequestFullscreen&&await this.container.webkitRequestFullscreen(),this.stateManager.set("fullscreen",!0),this.eventBus.emit("fullscreen:change",{fullscreen:!0})}catch(e){this.logger.error("Fullscreen request failed",{error:e})}}async exitFullscreen(){this.checkDestroyed();try{document.exitFullscreen?await document.exitFullscreen():document.webkitExitFullscreen&&await document.webkitExitFullscreen(),this.stateManager.set("fullscreen",!1),this.eventBus.emit("fullscreen:change",{fullscreen:!1})}catch(e){this.logger.error("Exit fullscreen failed",{error:e})}}async toggleFullscreen(){this.fullscreen?await this.exitFullscreen():await this.requestFullscreen()}requestAirPlay(){this.checkDestroyed();const e=this.pluginManager.getPlugin("airplay");e&&"function"==typeof e.showPicker?e.showPicker():this.logger.warn("AirPlay plugin not available")}async requestChromecast(){this.checkDestroyed();const e=this.pluginManager.getPlugin("chromecast");e&&"function"==typeof e.requestSession?await e.requestSession():this.logger.warn("Chromecast plugin not available")}stopCasting(){this.checkDestroyed();const e=this.pluginManager.getPlugin("airplay");e&&"function"==typeof e.stop&&e.stop();const t=this.pluginManager.getPlugin("chromecast");t&&"function"==typeof t.stopSession&&t.stopSession()}seekToLive(){this.checkDestroyed();if(!this.stateManager.getValue("live"))return void this.logger.warn("Not a live stream");if(this._currentProvider){const e=this._currentProvider;if("function"==typeof e.getLiveInfo){const t=e.getLiveInfo();if(void 0!==t?.liveSyncPosition)return void this.seek(t.liveSyncPosition)}}const e=this.stateManager.getValue("duration");e>0&&this.seek(e)}destroy(){this.destroyed||(this.logger.info("Destroying player"),null!==this.seekResumeTimeout&&(clearTimeout(this.seekResumeTimeout),this.seekResumeTimeout=null),this.eventBus.emit("player:destroy",void 0),this.pluginManager.destroyAll(),this.eventBus.destroy(),this.stateManager.destroy(),this.destroyed=!0,this.logger.info("Player destroyed"))}get playing(){return this.stateManager.getValue("playing")}get paused(){return this.stateManager.getValue("paused")}get currentTime(){return this.stateManager.getValue("currentTime")}get duration(){return this.stateManager.getValue("duration")}get volume(){return this.stateManager.getValue("volume")}get muted(){return this.stateManager.getValue("muted")}get playbackRate(){return this.stateManager.getValue("playbackRate")}get bufferedAmount(){return this.stateManager.getValue("bufferedAmount")}get currentProvider(){return this._currentProvider}get fullscreen(){return this.stateManager.getValue("fullscreen")}get live(){return this.stateManager.getValue("live")}get autoplay(){return this.stateManager.getValue("autoplay")}checkDestroyed(){if(this.destroyed)throw new Error("Cannot call methods on destroyed player")}detectMimeType(e){const t=e.split(".").pop()?.toLowerCase();switch(t){case"m3u8":return"application/x-mpegURL";case"mpd":return"application/dash+xml";case"mp4":default:return"video/mp4";case"webm":return"video/webm";case"ogg":return"video/ogg"}}}exports.Computed=n,exports.ErrorCode=d,exports.ErrorHandler=p,exports.EventBus=u,exports.Logger=g,exports.PluginAPI=y,exports.PluginManager=f,exports.ScarlettPlayer=m,exports.Signal=s,exports.StateManager=o,exports.computed=function(e){return new n(e)},exports.createLogger=function(e){return new g({scope:e})},exports.createPlayer=async function(e){const t=new m(e);return await t.init(),t},exports.effect=function(e){const r=()=>{t(r);try{e()}catch(s){throw console.error("[Scarlett Player] Error in effect:",s),s}finally{t(null)}};return r(),()=>{}},exports.getCurrentEffect=r,exports.setCurrentEffect=t,exports.signal=i;
2
2
  //# sourceMappingURL=index.cjs.map