synxed-sdk 0.3.18 → 0.3.19
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.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +2 -2
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import*as
|
|
1
|
+
import*as $ from'protobufjs';import {Howl}from'howler';var me=`
|
|
2
2
|
syntax = "proto3";
|
|
3
3
|
|
|
4
4
|
enum ContentKind {
|
|
@@ -133,7 +133,7 @@ message SdkServerEnvelope {
|
|
|
133
133
|
SdkServerVoiceAudio voiceAudio = 5;
|
|
134
134
|
}
|
|
135
135
|
}
|
|
136
|
-
`,$=j.parse(me).root,D=$.lookupType("SdkClientEnvelope"),H=$.lookupType("SdkServerEnvelope"),R=(r=>(r[r.UNSPECIFIED=0]="UNSPECIFIED",r[r.SONG=1]="SONG",r[r.PLAYLIST=2]="PLAYLIST",r[r.CATEGORY=3]="CATEGORY",r[r.RADIO=4]="RADIO",r[r.VOICE=5]="VOICE",r))(R||{}),B=(o=>(o[o.VOICE_UNSPECIFIED=0]="VOICE_UNSPECIFIED",o[o.VOICE_START=1]="VOICE_START",o[o.VOICE_CHUNK=2]="VOICE_CHUNK",o[o.VOICE_END=3]="VOICE_END",o[o.VOICE_CANCEL=4]="VOICE_CANCEL",o))(B||{}),Y=(a=>(a[a.UNSPECIFIED=0]="UNSPECIFIED",a[a.UNAUTHORIZED=1]="UNAUTHORIZED",a[a.VALIDATION_ERROR=2]="VALIDATION_ERROR",a[a.NOT_FOUND=3]="NOT_FOUND",a[a.PROCESSING=4]="PROCESSING",a[a.SERVICE_UNAVAILABLE=5]="SERVICE_UNAVAILABLE",a[a.BAD_PROTOBUF=6]="BAD_PROTOBUF",a))(Y||{});var S=class{static encodeClientEnvelope(t){let e=D.create(t);return D.encode(e).finish()}static decodeServerEnvelope(t){let e=H.decode(t);return H.toObject(e,{enums:String,longs:String,bytes:String,defaults:true,oneofs:true})}};var m=class{constructor(){this.listeners=new Map;}on(t,e){this.listeners.has(t)||this.listeners.set(t,new Set),this.listeners.get(t).add(e);}off(t,e){let i=this.listeners.get(t);i&&i.delete(e);}once(t,e){let i=((...n)=>{e(...n),this.off(t,i);});this.on(t,i);}emit(t,...e){let i=this.listeners.get(t);i&&i.forEach(n=>n(...e));}removeAllListeners(){this.listeners.clear();}};var G=false;function X(s){G=s;}function v(...s){G&&console.debug("[Synxed]",...s);}function u(...s){console.warn("[Synxed]",...s);}function J(s,t){let i=(s.endsWith("/")?s.slice(0,-1):s).replace(/^http:/,"ws:").replace(/^https:/,"wss:"),n=new URL(`${i}/sdk`);return n.searchParams.set("apiKey",t),n.toString()}var w=class extends m{constructor(){super(...arguments);this.ws=null;this.connectPromise=null;this.keepaliveTimer=null;}startKeepalive(){this.stopKeepalive(),this.keepaliveTimer=setInterval(()=>{this.sendAnalytics({eventType:"sdk_keepalive",positionMs:0});},25e3);}stopKeepalive(){this.keepaliveTimer!==null&&(clearInterval(this.keepaliveTimer),this.keepaliveTimer=null);}connect(e,i){if(this.ws&&(this.ws.readyState===WebSocket.OPEN||this.ws.readyState===WebSocket.CONNECTING))return;let n=J(i,e);v("Opening native WebSocket",n.replace(/apiKey=[^&]+/,"apiKey=***")),this.ws=new WebSocket(n),this.ws.binaryType="arraybuffer",this.ws.onopen=()=>{this.connectPromise=null,this.startKeepalive(),this.emit("connected");},this.ws.onclose=o=>{let r=o.reason||`code ${o.code}`;this.stopKeepalive(),this.ws=null,this.connectPromise=null,this.emit("disconnected",r);},this.ws.onerror=()=>{this.emit("error",new Error("WebSocket connection error"));},this.ws.onmessage=o=>{try{let{data:r}=o;if(!(r instanceof ArrayBuffer))return;let a=S.decodeServerEnvelope(new Uint8Array(r));this.emit("message",a);}catch(r){this.emit("error",new Error(`Failed to decode message: ${r}`));}};}async waitForConnection(){if(v("Waiting for connection\u2026"),this.ws?.readyState===WebSocket.OPEN){v("Already connected");return}if(!this.ws)throw new Error("WebSocket not initialized. Call connect() first.");return this.connectPromise?this.connectPromise:(this.connectPromise=new Promise((e,i)=>{let n=this.ws;if(n.readyState===WebSocket.OPEN){e();return}let o=()=>{v("WebSocket connected"),l(),e();},r=()=>{u("WebSocket connection error"),l(),i(new Error("WebSocket connection failed"));},a=()=>{l(),i(new Error("WebSocket closed before connection was established"));},l=()=>{n.removeEventListener("open",o),n.removeEventListener("error",r),n.removeEventListener("close",a);};n.addEventListener("open",o),n.addEventListener("error",r),n.addEventListener("close",a);}),this.connectPromise)}disconnect(){this.ws&&(this.ws.onclose=null,this.ws.close(),this.ws=null,this.connectPromise=null,this.stopKeepalive());}sendInit(e){if(!this.isConnected)throw new Error("WebSocket not connected");v("Sending init packet",e),this.sendBytes(S.encodeClientEnvelope({init:e}));}sendControl(e){this.isConnected&&this.sendBytes(S.encodeClientEnvelope({control:e}));}sendAnalytics(e){this.isConnected&&this.sendBytes(S.encodeClientEnvelope({analytics:e}));}sendVoice(e){this.isConnected&&this.sendBytes(S.encodeClientEnvelope({voice:e}));}get isConnected(){return this.ws?.readyState===WebSocket.OPEN}sendBytes(e){if(!this.ws||this.ws.readyState!==WebSocket.OPEN)throw new Error("WebSocket not connected");this.ws.send(e);}};var V=class extends m{constructor(){super();this.howl=null;this.hls=null;this.audioEl=null;this.updateTimer=null;this.loadGeneration=0;}async load(e,i){let n=++this.loadGeneration;this.teardownPlayback(),this.emit("loading"),v("AudioEngine loading",{url:e,isHls:i});let o=/^((?!chrome|android).)*safari/i.test(navigator.userAgent);if(i&&!o)try{let{default:r}=await import('hls.js');if(r.isSupported()){v("Using Hls.js for playback");let a=new r({xhrSetup:c=>{c.setRequestHeader("ngrok-skip-browser-warning","true");}}),l=new Audio;return new Promise((c,h)=>{let p=()=>n!==this.loadGeneration,g=()=>{p()||(this.emit("playing"),this.startTimeUpdateLoop());},b=()=>{p()||(this.emit("paused"),this.stopTimeUpdateLoop());},T=()=>{p()||(this.emit("ended"),this.stopTimeUpdateLoop());},I=()=>{p()||this.emit("loaded");},ve=()=>{p()||(u("HLS audio element error"),this.emit("error",new Error("HLS playback failed")));};l.addEventListener("play",g),l.addEventListener("pause",b),l.addEventListener("ended",T),l.addEventListener("loadedmetadata",I),l.addEventListener("error",ve),a.on(r.Events.MANIFEST_PARSED,()=>{p()||(this.emit("loaded"),c());}),a.on(r.Events.ERROR,(Ee,U)=>{p()||U.fatal&&(u("Fatal HLS error",U),h(U));}),a.loadSource(e),a.attachMedia(l),this.hls=a,this.audioEl=l;})}}catch(r){u("hls.js not available, falling back to native playback",r);}return new Promise((r,a)=>{let l=()=>n!==this.loadGeneration;this.howl=new Howl({src:[e],html5:true,format:i?["m3u8"]:void 0,onload:()=>{l()||(v("AudioEngine loaded"),this.emit("loaded"),r());},onloaderror:(c,h)=>{l()||(u("AudioEngine load error",h),a(h));},onplay:()=>{l()||(this.emit("playing"),this.startTimeUpdateLoop());},onpause:()=>{l()||(this.emit("paused"),this.stopTimeUpdateLoop());},onstop:()=>{l()||(this.emit("stopped"),this.stopTimeUpdateLoop());},onend:()=>{l()||(this.emit("ended"),this.stopTimeUpdateLoop());}});})}play(){this.audioEl?this.audioEl.play().catch(e=>u("Play failed",e)):this.howl?.play();}pause(){this.audioEl?this.audioEl.pause():this.howl?.pause();}stop(){this.loadGeneration+=1,this.teardownPlayback(),this.emit("stopped");}seek(e){this.audioEl?this.audioEl.currentTime=e/1e3:this.howl?.seek(e/1e3);}setVolume(e){this.audioEl&&(this.audioEl.volume=e),this.howl&&this.howl.volume(e);}get duration(){return this.audioEl?this.audioEl.duration*1e3:(this.howl?.duration()||0)*1e3}get currentTime(){return this.audioEl?this.audioEl.currentTime*1e3:(this.howl?.seek()||0)*1e3}teardownPlayback(){if(this.hls){try{this.hls.destroy();}catch{}this.hls=null;}this.audioEl&&(this.audioEl.pause(),this.audioEl.removeAttribute("src"),this.audioEl.load(),this.audioEl=null),this.howl&&(this.howl.stop(),this.howl.unload(),this.howl=null),this.stopTimeUpdateLoop();}startTimeUpdateLoop(){this.stopTimeUpdateLoop();let e=()=>{(this.audioEl?!this.audioEl.paused:this.howl?.playing())&&(this.emit("timeupdate",{currentTime:this.currentTime,duration:this.duration}),this.updateTimer=requestAnimationFrame(e));};this.updateTimer=requestAnimationFrame(e);}stopTimeUpdateLoop(){this.updateTimer!==null&&(cancelAnimationFrame(this.updateTimer),this.updateTimer=null);}};var _=class extends m{constructor(){super();this.queue=[];this.currentIndex=-1;}setQueue(e,i){this.queue=e,this.currentIndex=typeof i=="number"&&i>=0&&i<e.length?i:e.length>0?0:-1,this.emit("queueUpdated",this.queue),this.getCurrentTrack()&&this.emit("trackChanged",this.getCurrentTrack());}getCurrentTrack(){return this.currentIndex>=0&&this.currentIndex<this.queue.length?this.queue[this.currentIndex]:null}next(){if(this.currentIndex<this.queue.length-1){this.currentIndex++;let e=this.getCurrentTrack();return this.emit("trackChanged",e),e}return null}previous(){if(this.currentIndex>0){this.currentIndex--;let e=this.getCurrentTrack();return this.emit("trackChanged",e),e}return null}skipTo(e){if(e>=0&&e<this.queue.length){this.currentIndex=e;let i=this.getCurrentTrack();return this.emit("trackChanged",i),i}return null}reset(){this.queue=[],this.currentIndex=-1,this.emit("queueUpdated",[]);}get hasNext(){return this.currentIndex<this.queue.length-1}get hasPrevious(){return this.currentIndex>0}get queueSnapshot(){return [...this.queue]}get currentIndexSnapshot(){return this.currentIndex}};var x=class extends Error{constructor(e,i){super(e);this.code=i;this.name="SynxedError";}},O=class extends x{constructor(t){super(t),this.name="SynxedConnectionError";}},C=class extends x{constructor(t){super(typeof t=="string"?t:"Playback failed"),this.name="SynxedPlaybackError";}},Q=class extends x{constructor(t){super(t),this.name="SynxedProtocolError";}};function W(s,...t){for(let e of t){let i=s[e];if(typeof i=="string"&&i.length>0)return i}}function ye(s,...t){for(let e of t){let i=s[e];if(typeof i=="number"&&Number.isFinite(i))return i;if(typeof i=="string"&&i!==""&&!Number.isNaN(Number(i)))return Number(i)}}function Z(s){let t=s.initAck??s.init_ack;if(!t||typeof t!="object")return null;let e=t,i=W(e,"playbackUrl","playback_url");return i?{sessionId:W(e,"sessionId","session_id")??"",playbackUrl:i,isHls:!!(e.isHls??e.is_hls),heartbeatIntervalMs:ye(e,"heartbeatIntervalMs","heartbeat_interval_ms")??0,contentSummary:W(e,"contentSummary","content_summary")}:null}function ge(s){if(!s||typeof s!="object")return null;let t=s,e=t.id;if(typeof e!="string"||!e.trim())return null;let i=t.kind==="internal"?"internal":"catalog",n=t.albumArt??t.album_art;return {id:e.trim(),kind:i,title:typeof t.title=="string"?t.title:void 0,artist:typeof t.artist=="string"?t.artist:void 0,duration:typeof t.duration=="number"?t.duration:void 0,albumArt:typeof n=="string"?n:void 0}}function ee(s,t){if(!s?.trim())return null;let e;try{e=JSON.parse(s);}catch{return null}if(!e||typeof e!="object")return null;let i=e;if(i.type==="live_radio"||t===4)return {tracks:[{id:"synxed-radio",kind:"catalog",title:typeof i.station=="string"&&i.station.trim()?i.station.trim():"Synxed Radio",artist:""}],currentIndex:0};let o=i.tracks;if(!Array.isArray(o)||o.length===0)return null;let r=[];for(let c of o){let h=ge(c);h&&r.push(h);}if(r.length===0)return null;let a=typeof i.currentIndex=="number"?i.currentIndex:typeof i.current_index=="number"?i.current_index:0,l=Math.max(0,Math.min(Math.floor(a),r.length-1));return {tracks:r,currentIndex:l}}function f(s,...t){for(let e of t){let i=s[e];if(typeof i=="string")return i}return ""}function te(s,...t){for(let e of t){let i=s[e];if(typeof i=="boolean")return i}return false}function ie(s,...t){for(let e of t){let i=s[e];if(typeof i=="number"&&Number.isFinite(i))return i;if(typeof i=="string"&&i.trim()){let n=Number(i);if(Number.isFinite(n))return n}}return 0}function ne(s){let t=s.ad;if(!t||typeof t!="object")return null;let e=t,i=f(e,"playbackUrl","playback_url");return i?{adId:f(e,"adId","ad_id"),campaignId:f(e,"campaignId","campaign_id"),playbackUrl:i,isHls:te(e,"isHls","is_hls")||i.includes(".m3u8"),durationSeconds:ie(e,"durationSeconds","duration_seconds")||15,isSkippable:te(e,"isSkippable","is_skippable"),skipAfterSeconds:ie(e,"skipAfterSeconds","skip_after_seconds"),ctaType:f(e,"ctaType","cta_type"),ctaValue:f(e,"ctaValue","cta_value"),brandName:f(e,"brandName","brand_name"),creativeName:f(e,"creativeName","creative_name"),companionBannerUrl:f(e,"companionBannerUrl","companion_banner_url"),campaignName:f(e,"campaignName","campaign_name")}:null}var N="audio/pcm;rate=16000",k="audio/mpeg";function se(s,t){let e=/rate=(\d+)/i.exec(s);if(!e)return t;let i=Number(e[1]);return Number.isFinite(i)&&i>0?i:t}function P(s,...t){for(let e of t){let i=s[e];if(typeof i=="string")return i}return ""}function re(s){let t=s.voiceAck??s.voice_ack;if(!t||typeof t!="object")return null;let e=t,i=P(e,"status");return i?{status:i,transcript:P(e,"transcript")||void 0,playlistCode:P(e,"playlistCode","playlist_code")||void 0,playlistName:P(e,"playlistName","playlist_name")||void 0}:null}function ae(s){let t=s.voiceAudio??s.voice_audio;if(!t||typeof t!="object")return null;let e=t,i=e.audioData??e.audio_data,n=P(e,"mimeType","mime_type")||k,o=!!(e.isFinal??e.is_final),r;if(typeof i=="string"){let a=atob(i),l=a.length;r=new Uint8Array(l);for(let c=0;c<l;c++)r[c]=a.charCodeAt(c);}else if(i instanceof Uint8Array)r=i;else return null;return {audioData:r,mimeType:n,isFinal:o}}var M=class{constructor(){this.audioContext=null;this.nextStartTime=0;this.defaultSampleRate=24e3;this.encodedChunks=[];this.encodedMimeType=k;this.activeSource=null;this.playbackPromise=null;}initContext(t){this.audioContext||(this.audioContext=new(window.AudioContext||window.webkitAudioContext)({sampleRate:t}),this.nextStartTime=this.audioContext.currentTime);}enqueueChunk(t,e=k){if(!e.startsWith("audio/pcm")){this.encodedMimeType=e,this.encodedChunks.push(new Uint8Array(t));return}try{let i=se(e,this.defaultSampleRate);if(this.initContext(i),!this.audioContext)return;let n=new Int16Array(t.buffer,t.byteOffset,t.byteLength/2),o=new Float32Array(n.length);for(let c=0;c<n.length;c++)o[c]=n[c]/32768;let r=this.audioContext.createBuffer(1,o.length,i);r.getChannelData(0).set(o);let a=this.audioContext.createBufferSource();this.activeSource=a,a.buffer=r,a.connect(this.audioContext.destination);let l=this.audioContext.currentTime;this.nextStartTime<l&&(this.nextStartTime=l+.05),a.start(this.nextStartTime),this.nextStartTime+=r.duration;}catch(i){u("VoiceResponsePlayer failed to enqueue chunk",i);}}finish(t=this.encodedMimeType){if(!this.encodedChunks.length)return this.playbackPromise??Promise.resolve();let e=this.encodedChunks.splice(0);return this.encodedMimeType=t||k,this.playbackPromise=this.playEncoded(e,this.encodedMimeType).finally(()=>{this.playbackPromise=null;}),this.playbackPromise}async playEncoded(t,e){if(this.initContext(this.defaultSampleRate),!this.audioContext)return;this.audioContext.state==="suspended"&&await this.audioContext.resume().catch(()=>{});let i=t.map(r=>{let a=new Uint8Array(r.byteLength);return a.set(r),a.buffer}),n=new Blob(i,{type:e}),o=await this.audioContext.decodeAudioData(await n.arrayBuffer());await new Promise((r,a)=>{if(!this.audioContext){r();return}let l=this.audioContext.createBufferSource();this.activeSource=l,l.buffer=o,l.connect(this.audioContext.destination),l.onended=()=>{this.activeSource===l&&(this.activeSource=null),r();};try{l.start();}catch(c){this.activeSource===l&&(this.activeSource=null),a(c);}});}stop(){if(this.activeSource){try{this.activeSource.stop();}catch{}this.activeSource=null;}this.encodedChunks=[],this.playbackPromise=null,this.audioContext&&(this.audioContext.close().catch(()=>{}),this.audioContext=null),this.nextStartTime=0;}};var be="https://cdn.jsdelivr.net/npm/@ricky0123/vad-web@0.0.29/dist/",Se="https://cdn.jsdelivr.net/npm/onnxruntime-web@1.22.0/dist/";async function xe(){let s=await import('@ricky0123/vad-web'),t=s.MicVAD??s.default?.MicVAD;if(!t)throw new Error("MicVAD export missing from @ricky0123/vad-web \u2014 check bundler resolves the package");return t}var A=class extends m{constructor(){super(...arguments);this.capturing=false;this.mimeType=N;this.micVad=null;this.vadBaseAssetPath=be;this.onnxWasmBasePath=Se;this.userSpeaking=false;this.chunkSequence=0;}get isCapturing(){return this.capturing}get isUserSpeaking(){return this.userSpeaking}async preloadModels(e={}){this.applyOptions(e),await this.ensureMicVad();}applyOptions(e){e.vadBaseAssetPath&&(this.vadBaseAssetPath=e.vadBaseAssetPath),e.onnxWasmBasePath&&(this.onnxWasmBasePath=e.onnxWasmBasePath);}setUserSpeaking(e){this.userSpeaking!==e&&(this.userSpeaking=e,this.emit("userSpeakingChange",e));}async ensureMicVad(){if(this.micVad)return;let i=await(await xe()).new({baseAssetPath:this.vadBaseAssetPath,onnxWASMBasePath:this.onnxWasmBasePath,positiveSpeechThreshold:.5,negativeSpeechThreshold:.35,redemptionMs:500,minSpeechMs:250,onFrameProcessed:(n,o)=>{if(!this.capturing)return;let r=new Int16Array(o.length);for(let a=0;a<o.length;a++){let l=Math.max(-1,Math.min(1,o[a]));r[a]=l<0?l*32768:l*32767;}this.chunkSequence+=1,this.emit("chunk",new Uint8Array(r.buffer),this.chunkSequence);},onSpeechStart:()=>{this.capturing&&(this.setUserSpeaking(true),this.emit("speechStart"));},onSpeechEnd:()=>{this.capturing&&(this.setUserSpeaking(false),this.emit("speechEnd"));}});i.pause(),this.micVad=i;}async start(e={}){if(this.capturing)return this.mimeType;this.applyOptions(e),this.chunkSequence=0,this.setUserSpeaking(false);try{await this.ensureMicVad(),this.capturing=!0,this.micVad.start();}catch(i){this.capturing=false;let n=i instanceof Error?i:new Error(String(i));u("Voice capture failed to start",n),this.emit("error",n);}return this.mimeType}async stop(){this.capturing=false,this.setUserSpeaking(false),this.micVad&&this.micVad.pause();}cancel(){this.capturing=false,this.setUserSpeaking(false),this.micVad&&this.micVad.pause();}};var L=class extends m{constructor(e){super();this.status="idle";this.volume=.8;this.activeContentKind=0;this.heartbeatTimer=null;this.adPlaying=false;this._currentAd=null;this._voiceState="idle";this.voiceMimeType="audio/webm";this.pendingPlaybackLoad=null;this.voiceAutoEndOnSilence=true;this.pausedForVoice=false;this._voiceUserSpeaking=false;this.voiceResponseDismissed=false;this.voicePlaybackPromise=null;this.config=e,X(!!e.debug),this.transport=new w,this.audio=new V,this.playlist=new _,this.voiceCapture=new A,this.voiceResponsePlayer=new M,this.setupListeners(),this.voiceCapture.preloadModels(this.config.voice),e.autoConnect&&this.connect();}get currentTrack(){return this.playlist.getCurrentTrack()}get contentKind(){return this.activeContentKind}get currentAd(){return this._currentAd}get isAdPlaying(){return this.adPlaying}canSkipAd(){return !this.adPlaying||!this._currentAd?.isSkippable?false:Math.floor(this.audio.currentTime*1e3)>=this._currentAd.skipAfterSeconds*1e3}getAdSkipCountdownSeconds(){if(!this.adPlaying||!this._currentAd?.isSkippable)return null;let e=Math.floor(this.audio.currentTime*1e3),i=this._currentAd.skipAfterSeconds*1e3;return e>=i?0:Math.ceil((i-e)/1e3)}get voiceState(){return this._voiceState}get voiceUserSpeaking(){return this._voiceUserSpeaking}controlPositionMs(){return this.activeContentKind===4?0:this.positionMsForAnalytics()}setupListeners(){this.transport.on("connected",()=>this.emit("connected")),this.transport.on("disconnected",e=>this.emit("disconnected",e)),this.transport.on("error",e=>this.emit("error",new O(e.message))),this.transport.on("message",e=>this.handleServerMessage(e)),this.audio.on("playing",()=>this.updateStatus("playing")),this.audio.on("paused",()=>this.updateStatus("paused")),this.audio.on("stopped",()=>{!this.adPlaying&&this._voiceState==="idle"&&this.updateStatus("idle");}),this.audio.on("loading",()=>this.updateStatus("loading")),this.audio.on("error",e=>{if(this.adPlaying){u("Ad playback error \u2014 waiting for next track",e);return}this.emit("error",new C(e));}),this.audio.on("timeupdate",e=>{this.emit("timeUpdate",e),this.adPlaying&&this._currentAd&&this.emitAdSkipUpdate(e.currentTime);}),this.audio.on("ended",()=>this.handleTrackEnded()),this.playlist.on("trackChanged",e=>this.emit("trackChange",e)),this.playlist.on("queueUpdated",e=>this.emit("queueUpdated",e)),this.voiceCapture.on("chunk",(e,i)=>{this.transport.sendVoice({action:2,audioData:e,mimeType:this.voiceMimeType,sequence:i,listenerId:this.voiceListenerId,deviceType:this.config.deviceType,gameContext:this.config.gameContext});}),this.voiceCapture.on("error",e=>{this.setVoiceState("error"),this.emit("error",new x(e.message,"VOICE_CAPTURE_FAILED"));}),this.voiceCapture.on("speechStart",()=>{this.emit("voiceSpeechStart");}),this.voiceCapture.on("speechEnd",()=>{this.emit("voiceSpeechEnd"),this.voiceAutoEndOnSilence&&this._voiceState==="listening"&&this.endVoiceHold();}),this.voiceCapture.on("userSpeakingChange",e=>{this._voiceUserSpeaking=e,this.emit("voiceUserSpeakingChange",e);});}resolveVoiceOptions(e={}){return {...this.config.voice,...e}}connect(){this.transport.connect(this.config.apiKey,this.config.serverUrl);}buildInitExtras(){let e={};return this.config.gameContext?.trim()&&(e.gameContext=this.config.gameContext.trim()),this.config.deviceType?.trim()&&(e.deviceType=this.config.deviceType.trim()),e}async playSong(e){this.transport.isConnected||this.connect(),await this.transport.waitForConnection(),this.voiceResponseDismissed=false,this.activeContentKind=1,this.transport.sendInit({contentKind:1,catalogTrackId:e.catalogTrackId,internalTrackId:e.internalTrackId,listenerId:e.listenerId,...this.buildInitExtras()});}async playPlaylist(e){this.transport.isConnected||this.connect(),await this.transport.waitForConnection(),this.voiceResponseDismissed=false,this.activeContentKind=2,this.transport.sendInit({contentKind:2,playlistCode:e.playlistCode,listenerId:e.listenerId,...this.buildInitExtras()});}async playRadio(e={}){this.transport.isConnected||this.connect(),await this.transport.waitForConnection(),this.voiceResponseDismissed=false,this.activeContentKind=4,this.transport.sendInit({contentKind:4,listenerId:e.listenerId,...this.buildInitExtras()});}async beginVoiceHold(e={}){if(this._voiceState==="listening"||this._voiceState==="processing"||this._voiceState==="responding")return;let i=this.resolveVoiceOptions(e);this.voiceAutoEndOnSilence=i.autoEndOnSilence!==false,this._voiceUserSpeaking=false,this.voiceResponseDismissed=false,this.transport.isConnected||this.connect(),await this.transport.waitForConnection(),this.voiceListenerId=i.listenerId?.trim()||void 0,this.pausedForVoice=this.status==="playing",this.pausedForVoice&&this.pause(),this.voiceResponsePlayer.stop(),this.setVoiceState("listening"),this.voiceMimeType=await this.voiceCapture.start({maxDurationMs:i.maxDurationMs}),this.transport.sendVoice({action:1,mimeType:this.voiceMimeType||N,listenerId:this.voiceListenerId,...this.buildInitExtras()});}async endVoiceHold(){this._voiceState==="listening"&&(this._voiceUserSpeaking=false,this.emit("voiceUserSpeakingChange",false),this.setVoiceState("processing"),await this.voiceCapture.stop(),this.transport.sendVoice({action:3,mimeType:this.voiceMimeType,listenerId:this.voiceListenerId,...this.buildInitExtras()}));}cancelVoiceHold(){this._voiceState==="listening"&&(this._voiceUserSpeaking=false,this.voiceCapture.cancel(),this.transport.sendVoice({action:4,mimeType:this.voiceMimeType,listenerId:this.voiceListenerId,...this.buildInitExtras()}),this.setVoiceState("idle"));}dismissVoiceAndResume(){this.voiceResponseDismissed=true,this.voiceResponsePlayer.stop(),this._voiceState==="listening"?this.cancelVoiceHold():(this._voiceState==="processing"||this._voiceState==="responding")&&(this.transport.sendVoice({action:4,mimeType:this.voiceMimeType,listenerId:this.voiceListenerId,...this.buildInitExtras()}),this.setVoiceState("idle")),this.pausedForVoice&&(this.resume(),this.pausedForVoice=false);}get isVoiceUiActive(){return this._voiceState==="listening"||this._voiceState==="processing"||this._voiceState==="responding"}pause(){this.audio.pause(),this.transport.sendControl({action:2,positionMs:this.controlPositionMs()});}resume(){this.audio.play(),this.transport.sendControl({action:1,positionMs:this.controlPositionMs()});}stop(){this.audio.stop(),this.transport.sendControl({action:3,positionMs:this.controlPositionMs()});}skip(){if(this.activeContentKind===4)return;if(this.adPlaying){this.skipAd();return}if(this.playlist.queueSnapshot.length>1){this.transport.sendControl({action:5,positionMs:this.controlPositionMs()}),this.updateStatus("loading");return}let e=this.playlist.next();e&&this.playSong(e.kind==="internal"?{internalTrackId:e.id}:{catalogTrackId:e.id});}previous(){if(this.activeContentKind===4)return;if(this.playlist.queueSnapshot.length>1){this.transport.sendControl({action:6,positionMs:this.controlPositionMs()}),this.updateStatus("loading");return}let e=this.playlist.previous();e&&this.playSong(e.kind==="internal"?{internalTrackId:e.id}:{catalogTrackId:e.id});}skipTo(e){if(this.activeContentKind===4)return;let i=this.playlist.skipTo(e);i&&this.playSong(i.kind==="internal"?{internalTrackId:i.id}:{catalogTrackId:i.id});}seek(e){this.activeContentKind===4||this.adPlaying||(this.audio.seek(e),this.transport.sendControl({action:4,positionMs:e}));}setVolume(e){this.volume=Math.max(0,Math.min(1,e)),this.audio.setVolume(this.volume);}positionMsForAnalytics(e){return typeof e=="number"?Math.max(0,Math.min(4294967295,Math.floor(e))):Math.max(0,Math.min(4294967295,Math.floor(this.audio.currentTime)))}emitAnalytics(e,i,n){this.transport.sendAnalytics({eventType:e,positionMs:this.positionMsForAnalytics(i),extraJson:n?JSON.stringify(n):void 0});}clearHeartbeat(){this.heartbeatTimer!==null&&(clearInterval(this.heartbeatTimer),this.heartbeatTimer=null);}startHeartbeat(e){this.clearHeartbeat();let i=Number(e);!i||i<1e3||(this.heartbeatTimer=setInterval(()=>{let n=this.activeContentKind===4?0:this.positionMsForAnalytics();this.emitAnalytics("heartbeat",n);},i));}applyContentSummary(e){let i=ee(e,this.activeContentKind);if(i){this.playlist.setQueue(i.tracks,i.currentIndex);return}e?.trim()&&u("Could not parse contentSummary; queue metadata unavailable.");}emitAdSkipUpdate(e){if(!this._currentAd)return;let i=this._currentAd.skipAfterSeconds*1e3,n=this._currentAd.isSkippable&&e>=i,o=n?0:Math.ceil((i-e)/1e3),r={ad:this._currentAd,canSkip:n,countdownSeconds:o};this.emit("adSkipUpdate",r);}setVoiceState(e){this._voiceState=e,this.emit("voiceStateChange",e);}handleVoiceAck(e){let i=e.status;if(i==="cancelled"){this._voiceState!=="idle"&&this.setVoiceState("idle");return}if(!this.voiceResponseDismissed){if(i==="listening"){this._voiceState==="idle"&&this.setVoiceState("listening");return}if(i==="processing"){(this._voiceState==="listening"||this._voiceState==="idle")&&this.setVoiceState("processing");return}if(i==="ready"){this.activeContentKind=2;let n={status:i,transcript:e.transcript,playlistCode:e.playlistCode,playlistName:e.playlistName};this.setVoiceState("ready"),this.emit("voiceResult",n);return}this.emit("voiceResult",{status:i,transcript:e.transcript,playlistCode:e.playlistCode,playlistName:e.playlistName});}}async handleServerMessage(e){v("Received server message",e);let i=re(e);if(i){this.handleVoiceAck(i);return}let n=ae(e);if(n){if(this.voiceResponseDismissed)return;this._voiceState==="processing"&&this.setVoiceState("responding"),n.audioData.length>0&&this.voiceResponsePlayer.enqueueChunk(n.audioData,n.mimeType),n.isFinal&&(this.voicePlaybackPromise=this.voiceResponsePlayer.finish(n.mimeType).catch(l=>{u("Voice response playback failed",l);}).finally(()=>{this.voicePlaybackPromise=null;}));return}let o=ne(e);if(o){await this.handleAdPlayback(o);return}let r=Z(e);if(r){if(this.voiceResponseDismissed)return;await this.startContentPlayback(r);return}let a=e.error;if(a&&typeof a=="object"){let l=a,c=typeof l.message=="string"?l.message:"Unknown server error",h=typeof l.code=="string"?l.code:void 0;(this._voiceState==="processing"||this._voiceState==="listening"||this._voiceState==="responding")&&this.setVoiceState("error"),this.emit("error",new x(c,h));}}async startContentPlayback(e){if(this.adPlaying&&this._currentAd){let n=this._currentAd;this.adPlaying=false,this._currentAd=null,this.emit("adEnd",n);}else this.adPlaying=false,this._currentAd=null;this.voicePlaybackPromise&&!this.voiceResponseDismissed&&await this.voicePlaybackPromise,(this._voiceState==="ready"||this._voiceState==="processing"||this._voiceState==="responding")&&this.setVoiceState("idle"),this.pausedForVoice=false,this.voiceResponsePlayer.stop(),v("Loading playback",{url:e.playbackUrl,isHls:e.isHls});let i=this.audio.load(e.playbackUrl,e.isHls);this.pendingPlaybackLoad=i;try{if(await i,this.pendingPlaybackLoad!==i)return;this.audio.play(),this.emitAnalytics("stream_start",this.activeContentKind===4?0:void 0),this.startHeartbeat(e.heartbeatIntervalMs),this.applyContentSummary(e.contentSummary);}catch(n){if(this.pendingPlaybackLoad!==i)return;this.emit("error",new C(n));}finally{this.pendingPlaybackLoad===i&&(this.pendingPlaybackLoad=null);}}async handleAdPlayback(e){this.pendingPlaybackLoad&&await this.pendingPlaybackLoad.catch(()=>{}),this.audio.stop(),this.adPlaying=true,this._currentAd={adId:e.adId,campaignId:e.campaignId,brandName:e.brandName,creativeName:e.creativeName,durationSeconds:e.durationSeconds,isSkippable:e.isSkippable,skipAfterSeconds:e.skipAfterSeconds,ctaType:e.ctaType,ctaValue:e.ctaValue,companionBannerUrl:e.companionBannerUrl,campaignName:e.campaignName},v("Loading ad playback",{url:e.playbackUrl,isHls:e.isHls});try{await this.audio.load(e.playbackUrl,e.isHls),this.audio.play(),this.emit("adStart",this._currentAd),this.emitAdSkipUpdate(0);}catch(i){let n=this._currentAd;this.adPlaying=false,this._currentAd=null,n&&this.emit("adEnd",n),u("Ad load failed",i),this.updateStatus("loading");}}skipAd(){if(!this.adPlaying||!this._currentAd||!this._currentAd.isSkippable)return;let e=Math.floor(this.audio.currentTime*1e3);if(e<this._currentAd.skipAfterSeconds*1e3)return;let i=this._currentAd;this.adPlaying=false,this._currentAd=null,this.audio.stop(),this.emit("adEnd",i),this.emitAnalytics("ad_skip",e),this.updateStatus("loading");}clickAd(){if(!this.adPlaying||!this._currentAd)return;let e=Math.floor(this.audio.currentTime*1e3);this.emitAnalytics("ad_cta_click",e),this._currentAd.ctaValue&&window.open(this._currentAd.ctaValue,"_blank");}handleTrackEnded(){if(this.activeContentKind!==4){if(this.adPlaying&&this._currentAd){let e=this._currentAd;this.audio.stop(),this.emitAnalytics("ad_complete",Math.floor(this.audio.currentTime*1e3)),this.emit("adEnd",e),this.adPlaying=false,this._currentAd=null,this.updateStatus("loading");return}if(this.playlist.queueSnapshot.length>1){this.emitAnalytics("track_complete",Math.floor(this.audio.duration*1e3)),this.updateStatus("loading");return}if(this.activeContentKind===1||this.activeContentKind===2){this.emitAnalytics("track_complete",Math.floor(this.audio.duration*1e3)),this.updateStatus("loading");return}this.updateStatus("idle");}}updateStatus(e){this.status=e,this.emit("stateChange",{status:e,currentTrack:this.playlist.getCurrentTrack(),currentTime:this.audio.currentTime,duration:this.audio.duration,volume:this.volume});}destroy(){this.clearHeartbeat(),this.cancelVoiceHold(),this.voiceResponsePlayer.stop(),this.audio.stop(),this.transport.disconnect(),this.playlist.reset(),this.removeAllListeners();}};async function K(s,t){let i=`${s.replace(/\/$/,"")}/radio/now-playing`;try{let n=await fetch(i,{...t,headers:{Accept:"application/json",...t?.headers}});if(!n.ok)return null;let r=(await n.json())?.data;return !r?.title||typeof r.title!="string"?null:{title:r.title,station:typeof r.station=="string"?r.station:void 0,isLive:typeof r.isLive=="boolean"?r.isLive:void 0}}catch{return null}}function d(s,t){let e=document.createElement(s);if(t?.className&&(e.className=t.className),t?.attrs)for(let[i,n]of Object.entries(t.attrs))e.setAttribute(i,n);return t?.style&&Object.assign(e.style,t.style),t?.text&&(e.textContent=t.text),t?.html&&(e.innerHTML=t.html),t?.onClick&&e.addEventListener("click",t.onClick),t?.children&&t.children.forEach(i=>e.appendChild(i)),e}function y(s,t=20){let e=document.createElementNS("http://www.w3.org/2000/svg","svg");e.setAttribute("width",String(t)),e.setAttribute("height",String(t)),e.setAttribute("viewBox","0 0 24 24"),e.setAttribute("fill","currentColor"),e.setAttribute("aria-hidden","true");let i=document.createElementNS("http://www.w3.org/2000/svg","path");return i.setAttribute("d",s),e.appendChild(i),e}var F="M8 5v14l11-7L8 5z",oe="M6 5h4v14H6V5zm8 0h4v14h-4V5z",E="M6 18l8.5-6L6 6v12zM16 6v12h2V6h-2z",le="M6 6h2v12H6V6zm11.5 12L9 12l8.5-6v12z";function de(){let s="synxed-web-player-styles";if(document.getElementById(s))return;let t=document.createElement("style");t.id=s,t.textContent=`
|
|
136
|
+
`,j=$.parse(me).root,D=j.lookupType("SdkClientEnvelope"),H=j.lookupType("SdkServerEnvelope"),R=(r=>(r[r.UNSPECIFIED=0]="UNSPECIFIED",r[r.SONG=1]="SONG",r[r.PLAYLIST=2]="PLAYLIST",r[r.CATEGORY=3]="CATEGORY",r[r.RADIO=4]="RADIO",r[r.VOICE=5]="VOICE",r))(R||{}),B=(o=>(o[o.VOICE_UNSPECIFIED=0]="VOICE_UNSPECIFIED",o[o.VOICE_START=1]="VOICE_START",o[o.VOICE_CHUNK=2]="VOICE_CHUNK",o[o.VOICE_END=3]="VOICE_END",o[o.VOICE_CANCEL=4]="VOICE_CANCEL",o))(B||{}),Y=(a=>(a[a.UNSPECIFIED=0]="UNSPECIFIED",a[a.UNAUTHORIZED=1]="UNAUTHORIZED",a[a.VALIDATION_ERROR=2]="VALIDATION_ERROR",a[a.NOT_FOUND=3]="NOT_FOUND",a[a.PROCESSING=4]="PROCESSING",a[a.SERVICE_UNAVAILABLE=5]="SERVICE_UNAVAILABLE",a[a.BAD_PROTOBUF=6]="BAD_PROTOBUF",a))(Y||{});var S=class{static encodeClientEnvelope(t){let e=D.create(t);return D.encode(e).finish()}static decodeServerEnvelope(t){let e=H.decode(t);return H.toObject(e,{enums:String,longs:String,bytes:String,defaults:true,oneofs:true})}};var m=class{constructor(){this.listeners=new Map;}on(t,e){this.listeners.has(t)||this.listeners.set(t,new Set),this.listeners.get(t).add(e);}off(t,e){let i=this.listeners.get(t);i&&i.delete(e);}once(t,e){let i=((...n)=>{e(...n),this.off(t,i);});this.on(t,i);}emit(t,...e){let i=this.listeners.get(t);i&&i.forEach(n=>n(...e));}removeAllListeners(){this.listeners.clear();}};var G=false;function X(s){G=s;}function v(...s){G&&console.debug("[Synxed]",...s);}function u(...s){console.warn("[Synxed]",...s);}function J(s,t){let i=(s.endsWith("/")?s.slice(0,-1):s).replace(/^http:/,"ws:").replace(/^https:/,"wss:"),n=new URL(`${i}/sdk`);return n.searchParams.set("apiKey",t),n.toString()}var w=class extends m{constructor(){super(...arguments);this.ws=null;this.connectPromise=null;this.keepaliveTimer=null;}startKeepalive(){this.stopKeepalive(),this.keepaliveTimer=setInterval(()=>{this.sendAnalytics({eventType:"sdk_keepalive",positionMs:0});},25e3);}stopKeepalive(){this.keepaliveTimer!==null&&(clearInterval(this.keepaliveTimer),this.keepaliveTimer=null);}connect(e,i){if(this.ws&&(this.ws.readyState===WebSocket.OPEN||this.ws.readyState===WebSocket.CONNECTING))return;let n=J(i,e);v("Opening native WebSocket",n.replace(/apiKey=[^&]+/,"apiKey=***")),this.ws=new WebSocket(n),this.ws.binaryType="arraybuffer",this.ws.onopen=()=>{this.connectPromise=null,this.startKeepalive(),this.emit("connected");},this.ws.onclose=o=>{let r=o.reason?`${o.reason} (code ${o.code}, clean ${o.wasClean})`:`code ${o.code}, clean ${o.wasClean}`;this.stopKeepalive(),this.ws=null,this.connectPromise=null,this.emit("disconnected",r);},this.ws.onerror=()=>{this.emit("error",new Error("WebSocket connection error"));},this.ws.onmessage=o=>{try{let{data:r}=o;if(!(r instanceof ArrayBuffer))return;let a=S.decodeServerEnvelope(new Uint8Array(r));this.emit("message",a);}catch(r){this.emit("error",new Error(`Failed to decode message: ${r}`));}};}async waitForConnection(){if(v("Waiting for connection\u2026"),this.ws?.readyState===WebSocket.OPEN){v("Already connected");return}if(!this.ws)throw new Error("WebSocket not initialized. Call connect() first.");return this.connectPromise?this.connectPromise:(this.connectPromise=new Promise((e,i)=>{let n=this.ws;if(n.readyState===WebSocket.OPEN){e();return}let o=()=>{v("WebSocket connected"),l(),e();},r=()=>{u("WebSocket connection error"),l(),i(new Error("WebSocket connection failed"));},a=()=>{l(),i(new Error("WebSocket closed before connection was established"));},l=()=>{n.removeEventListener("open",o),n.removeEventListener("error",r),n.removeEventListener("close",a);};n.addEventListener("open",o),n.addEventListener("error",r),n.addEventListener("close",a);}),this.connectPromise)}disconnect(){this.ws&&(this.ws.onclose=null,this.ws.close(),this.ws=null,this.connectPromise=null,this.stopKeepalive());}sendInit(e){if(!this.isConnected)throw new Error("WebSocket not connected");v("Sending init packet",e),this.sendBytes(S.encodeClientEnvelope({init:e}));}sendControl(e){this.isConnected&&this.sendBytes(S.encodeClientEnvelope({control:e}));}sendAnalytics(e){this.isConnected&&this.sendBytes(S.encodeClientEnvelope({analytics:e}));}sendVoice(e){this.isConnected&&this.sendBytes(S.encodeClientEnvelope({voice:e}));}get isConnected(){return this.ws?.readyState===WebSocket.OPEN}sendBytes(e){if(!this.ws||this.ws.readyState!==WebSocket.OPEN)throw new Error("WebSocket not connected");this.ws.send(e);}};var V=class extends m{constructor(){super();this.howl=null;this.hls=null;this.audioEl=null;this.updateTimer=null;this.loadGeneration=0;}async load(e,i){let n=++this.loadGeneration;this.teardownPlayback(),this.emit("loading"),v("AudioEngine loading",{url:e,isHls:i});let o=/^((?!chrome|android).)*safari/i.test(navigator.userAgent);if(i&&!o)try{let{default:r}=await import('hls.js');if(r.isSupported()){v("Using Hls.js for playback");let a=new r({xhrSetup:c=>{c.setRequestHeader("ngrok-skip-browser-warning","true");}}),l=new Audio;return new Promise((c,h)=>{let p=()=>n!==this.loadGeneration,g=()=>{p()||(this.emit("playing"),this.startTimeUpdateLoop());},b=()=>{p()||(this.emit("paused"),this.stopTimeUpdateLoop());},T=()=>{p()||(this.emit("ended"),this.stopTimeUpdateLoop());},I=()=>{p()||this.emit("loaded");},ve=()=>{p()||(u("HLS audio element error"),this.emit("error",new Error("HLS playback failed")));};l.addEventListener("play",g),l.addEventListener("pause",b),l.addEventListener("ended",T),l.addEventListener("loadedmetadata",I),l.addEventListener("error",ve),a.on(r.Events.MANIFEST_PARSED,()=>{p()||(this.emit("loaded"),c());}),a.on(r.Events.ERROR,(Ee,U)=>{p()||U.fatal&&(u("Fatal HLS error",U),h(U));}),a.loadSource(e),a.attachMedia(l),this.hls=a,this.audioEl=l;})}}catch(r){u("hls.js not available, falling back to native playback",r);}return new Promise((r,a)=>{let l=()=>n!==this.loadGeneration;this.howl=new Howl({src:[e],html5:true,format:i?["m3u8"]:void 0,onload:()=>{l()||(v("AudioEngine loaded"),this.emit("loaded"),r());},onloaderror:(c,h)=>{l()||(u("AudioEngine load error",h),a(h));},onplay:()=>{l()||(this.emit("playing"),this.startTimeUpdateLoop());},onpause:()=>{l()||(this.emit("paused"),this.stopTimeUpdateLoop());},onstop:()=>{l()||(this.emit("stopped"),this.stopTimeUpdateLoop());},onend:()=>{l()||(this.emit("ended"),this.stopTimeUpdateLoop());}});})}play(){this.audioEl?this.audioEl.play().catch(e=>u("Play failed",e)):this.howl?.play();}pause(){this.audioEl?this.audioEl.pause():this.howl?.pause();}stop(){this.loadGeneration+=1,this.teardownPlayback(),this.emit("stopped");}seek(e){this.audioEl?this.audioEl.currentTime=e/1e3:this.howl?.seek(e/1e3);}setVolume(e){this.audioEl&&(this.audioEl.volume=e),this.howl&&this.howl.volume(e);}get duration(){return this.audioEl?this.audioEl.duration*1e3:(this.howl?.duration()||0)*1e3}get currentTime(){return this.audioEl?this.audioEl.currentTime*1e3:(this.howl?.seek()||0)*1e3}teardownPlayback(){if(this.hls){try{this.hls.destroy();}catch{}this.hls=null;}this.audioEl&&(this.audioEl.pause(),this.audioEl.removeAttribute("src"),this.audioEl.load(),this.audioEl=null),this.howl&&(this.howl.stop(),this.howl.unload(),this.howl=null),this.stopTimeUpdateLoop();}startTimeUpdateLoop(){this.stopTimeUpdateLoop();let e=()=>{(this.audioEl?!this.audioEl.paused:this.howl?.playing())&&(this.emit("timeupdate",{currentTime:this.currentTime,duration:this.duration}),this.updateTimer=requestAnimationFrame(e));};this.updateTimer=requestAnimationFrame(e);}stopTimeUpdateLoop(){this.updateTimer!==null&&(cancelAnimationFrame(this.updateTimer),this.updateTimer=null);}};var _=class extends m{constructor(){super();this.queue=[];this.currentIndex=-1;}setQueue(e,i){this.queue=e,this.currentIndex=typeof i=="number"&&i>=0&&i<e.length?i:e.length>0?0:-1,this.emit("queueUpdated",this.queue),this.getCurrentTrack()&&this.emit("trackChanged",this.getCurrentTrack());}getCurrentTrack(){return this.currentIndex>=0&&this.currentIndex<this.queue.length?this.queue[this.currentIndex]:null}next(){if(this.currentIndex<this.queue.length-1){this.currentIndex++;let e=this.getCurrentTrack();return this.emit("trackChanged",e),e}return null}previous(){if(this.currentIndex>0){this.currentIndex--;let e=this.getCurrentTrack();return this.emit("trackChanged",e),e}return null}skipTo(e){if(e>=0&&e<this.queue.length){this.currentIndex=e;let i=this.getCurrentTrack();return this.emit("trackChanged",i),i}return null}reset(){this.queue=[],this.currentIndex=-1,this.emit("queueUpdated",[]);}get hasNext(){return this.currentIndex<this.queue.length-1}get hasPrevious(){return this.currentIndex>0}get queueSnapshot(){return [...this.queue]}get currentIndexSnapshot(){return this.currentIndex}};var x=class extends Error{constructor(e,i){super(e);this.code=i;this.name="SynxedError";}},O=class extends x{constructor(t){super(t),this.name="SynxedConnectionError";}},C=class extends x{constructor(t){super(typeof t=="string"?t:"Playback failed"),this.name="SynxedPlaybackError";}},Q=class extends x{constructor(t){super(t),this.name="SynxedProtocolError";}};function W(s,...t){for(let e of t){let i=s[e];if(typeof i=="string"&&i.length>0)return i}}function ye(s,...t){for(let e of t){let i=s[e];if(typeof i=="number"&&Number.isFinite(i))return i;if(typeof i=="string"&&i!==""&&!Number.isNaN(Number(i)))return Number(i)}}function Z(s){let t=s.initAck??s.init_ack;if(!t||typeof t!="object")return null;let e=t,i=W(e,"playbackUrl","playback_url");return i?{sessionId:W(e,"sessionId","session_id")??"",playbackUrl:i,isHls:!!(e.isHls??e.is_hls),heartbeatIntervalMs:ye(e,"heartbeatIntervalMs","heartbeat_interval_ms")??0,contentSummary:W(e,"contentSummary","content_summary")}:null}function ge(s){if(!s||typeof s!="object")return null;let t=s,e=t.id;if(typeof e!="string"||!e.trim())return null;let i=t.kind==="internal"?"internal":"catalog",n=t.albumArt??t.album_art;return {id:e.trim(),kind:i,title:typeof t.title=="string"?t.title:void 0,artist:typeof t.artist=="string"?t.artist:void 0,duration:typeof t.duration=="number"?t.duration:void 0,albumArt:typeof n=="string"?n:void 0}}function ee(s,t){if(!s?.trim())return null;let e;try{e=JSON.parse(s);}catch{return null}if(!e||typeof e!="object")return null;let i=e;if(i.type==="live_radio"||t===4)return {tracks:[{id:"synxed-radio",kind:"catalog",title:typeof i.station=="string"&&i.station.trim()?i.station.trim():"Synxed Radio",artist:""}],currentIndex:0};let o=i.tracks;if(!Array.isArray(o)||o.length===0)return null;let r=[];for(let c of o){let h=ge(c);h&&r.push(h);}if(r.length===0)return null;let a=typeof i.currentIndex=="number"?i.currentIndex:typeof i.current_index=="number"?i.current_index:0,l=Math.max(0,Math.min(Math.floor(a),r.length-1));return {tracks:r,currentIndex:l}}function f(s,...t){for(let e of t){let i=s[e];if(typeof i=="string")return i}return ""}function te(s,...t){for(let e of t){let i=s[e];if(typeof i=="boolean")return i}return false}function ie(s,...t){for(let e of t){let i=s[e];if(typeof i=="number"&&Number.isFinite(i))return i;if(typeof i=="string"&&i.trim()){let n=Number(i);if(Number.isFinite(n))return n}}return 0}function ne(s){let t=s.ad;if(!t||typeof t!="object")return null;let e=t,i=f(e,"playbackUrl","playback_url");return i?{adId:f(e,"adId","ad_id"),campaignId:f(e,"campaignId","campaign_id"),playbackUrl:i,isHls:te(e,"isHls","is_hls")||i.includes(".m3u8"),durationSeconds:ie(e,"durationSeconds","duration_seconds")||15,isSkippable:te(e,"isSkippable","is_skippable"),skipAfterSeconds:ie(e,"skipAfterSeconds","skip_after_seconds"),ctaType:f(e,"ctaType","cta_type"),ctaValue:f(e,"ctaValue","cta_value"),brandName:f(e,"brandName","brand_name"),creativeName:f(e,"creativeName","creative_name"),companionBannerUrl:f(e,"companionBannerUrl","companion_banner_url"),campaignName:f(e,"campaignName","campaign_name")}:null}var N="audio/pcm;rate=16000",k="audio/mpeg";function se(s,t){let e=/rate=(\d+)/i.exec(s);if(!e)return t;let i=Number(e[1]);return Number.isFinite(i)&&i>0?i:t}function P(s,...t){for(let e of t){let i=s[e];if(typeof i=="string")return i}return ""}function re(s){let t=s.voiceAck??s.voice_ack;if(!t||typeof t!="object")return null;let e=t,i=P(e,"status");return i?{status:i,transcript:P(e,"transcript")||void 0,playlistCode:P(e,"playlistCode","playlist_code")||void 0,playlistName:P(e,"playlistName","playlist_name")||void 0}:null}function ae(s){let t=s.voiceAudio??s.voice_audio;if(!t||typeof t!="object")return null;let e=t,i=e.audioData??e.audio_data,n=P(e,"mimeType","mime_type")||k,o=!!(e.isFinal??e.is_final),r;if(typeof i=="string"){let a=atob(i),l=a.length;r=new Uint8Array(l);for(let c=0;c<l;c++)r[c]=a.charCodeAt(c);}else if(i instanceof Uint8Array)r=i;else return null;return {audioData:r,mimeType:n,isFinal:o}}var M=class{constructor(){this.audioContext=null;this.nextStartTime=0;this.defaultSampleRate=24e3;this.encodedChunks=[];this.encodedMimeType=k;this.activeSource=null;this.playbackPromise=null;}initContext(t){this.audioContext||(this.audioContext=new(window.AudioContext||window.webkitAudioContext)({sampleRate:t}),this.nextStartTime=this.audioContext.currentTime);}enqueueChunk(t,e=k){if(!e.startsWith("audio/pcm")){this.encodedMimeType=e,this.encodedChunks.push(new Uint8Array(t));return}try{let i=se(e,this.defaultSampleRate);if(this.initContext(i),!this.audioContext)return;let n=new Int16Array(t.buffer,t.byteOffset,t.byteLength/2),o=new Float32Array(n.length);for(let c=0;c<n.length;c++)o[c]=n[c]/32768;let r=this.audioContext.createBuffer(1,o.length,i);r.getChannelData(0).set(o);let a=this.audioContext.createBufferSource();this.activeSource=a,a.buffer=r,a.connect(this.audioContext.destination);let l=this.audioContext.currentTime;this.nextStartTime<l&&(this.nextStartTime=l+.05),a.start(this.nextStartTime),this.nextStartTime+=r.duration;}catch(i){u("VoiceResponsePlayer failed to enqueue chunk",i);}}finish(t=this.encodedMimeType){if(!this.encodedChunks.length)return this.playbackPromise??Promise.resolve();let e=this.encodedChunks.splice(0);return this.encodedMimeType=t||k,this.playbackPromise=this.playEncoded(e,this.encodedMimeType).finally(()=>{this.playbackPromise=null;}),this.playbackPromise}async playEncoded(t,e){if(this.initContext(this.defaultSampleRate),!this.audioContext)return;this.audioContext.state==="suspended"&&await this.audioContext.resume().catch(()=>{});let i=t.map(r=>{let a=new Uint8Array(r.byteLength);return a.set(r),a.buffer}),n=new Blob(i,{type:e}),o=await this.audioContext.decodeAudioData(await n.arrayBuffer());await new Promise((r,a)=>{if(!this.audioContext){r();return}let l=this.audioContext.createBufferSource();this.activeSource=l,l.buffer=o,l.connect(this.audioContext.destination),l.onended=()=>{this.activeSource===l&&(this.activeSource=null),r();};try{l.start();}catch(c){this.activeSource===l&&(this.activeSource=null),a(c);}});}stop(){if(this.activeSource){try{this.activeSource.stop();}catch{}this.activeSource=null;}this.encodedChunks=[],this.playbackPromise=null,this.audioContext&&(this.audioContext.close().catch(()=>{}),this.audioContext=null),this.nextStartTime=0;}};var be="https://cdn.jsdelivr.net/npm/@ricky0123/vad-web@0.0.29/dist/",Se="https://cdn.jsdelivr.net/npm/onnxruntime-web@1.22.0/dist/";async function xe(){let s=await import('@ricky0123/vad-web'),t=s.MicVAD??s.default?.MicVAD;if(!t)throw new Error("MicVAD export missing from @ricky0123/vad-web \u2014 check bundler resolves the package");return t}var A=class extends m{constructor(){super(...arguments);this.capturing=false;this.mimeType=N;this.micVad=null;this.vadBaseAssetPath=be;this.onnxWasmBasePath=Se;this.userSpeaking=false;this.chunkSequence=0;}get isCapturing(){return this.capturing}get isUserSpeaking(){return this.userSpeaking}async preloadModels(e={}){this.applyOptions(e),await this.ensureMicVad();}applyOptions(e){e.vadBaseAssetPath&&(this.vadBaseAssetPath=e.vadBaseAssetPath),e.onnxWasmBasePath&&(this.onnxWasmBasePath=e.onnxWasmBasePath);}setUserSpeaking(e){this.userSpeaking!==e&&(this.userSpeaking=e,this.emit("userSpeakingChange",e));}async ensureMicVad(){if(this.micVad)return;let i=await(await xe()).new({baseAssetPath:this.vadBaseAssetPath,onnxWASMBasePath:this.onnxWasmBasePath,positiveSpeechThreshold:.5,negativeSpeechThreshold:.35,redemptionMs:500,minSpeechMs:250,onFrameProcessed:(n,o)=>{if(!this.capturing)return;let r=new Int16Array(o.length);for(let a=0;a<o.length;a++){let l=Math.max(-1,Math.min(1,o[a]));r[a]=l<0?l*32768:l*32767;}this.chunkSequence+=1,this.emit("chunk",new Uint8Array(r.buffer),this.chunkSequence);},onSpeechStart:()=>{this.capturing&&(this.setUserSpeaking(true),this.emit("speechStart"));},onSpeechEnd:()=>{this.capturing&&(this.setUserSpeaking(false),this.emit("speechEnd"));}});i.pause(),this.micVad=i;}async start(e={}){if(this.capturing)return this.mimeType;this.applyOptions(e),this.chunkSequence=0,this.setUserSpeaking(false);try{await this.ensureMicVad(),this.capturing=!0,this.micVad.start();}catch(i){this.capturing=false;let n=i instanceof Error?i:new Error(String(i));throw u("Voice capture failed to start",n),this.emit("error",n),n}return this.mimeType}async stop(){this.capturing=false,this.setUserSpeaking(false),this.micVad&&this.micVad.pause();}cancel(){this.capturing=false,this.setUserSpeaking(false),this.micVad&&this.micVad.pause();}};var L=class extends m{constructor(e){super();this.status="idle";this.volume=.8;this.activeContentKind=0;this.heartbeatTimer=null;this.adPlaying=false;this._currentAd=null;this._voiceState="idle";this.voiceMimeType="audio/webm";this.pendingPlaybackLoad=null;this.voiceAutoEndOnSilence=true;this.pausedForVoice=false;this._voiceUserSpeaking=false;this.voiceResponseDismissed=false;this.voicePlaybackPromise=null;this.config=e,X(!!e.debug),this.transport=new w,this.audio=new V,this.playlist=new _,this.voiceCapture=new A,this.voiceResponsePlayer=new M,this.setupListeners(),this.voiceCapture.preloadModels(this.config.voice),e.autoConnect&&this.connect();}get currentTrack(){return this.playlist.getCurrentTrack()}get contentKind(){return this.activeContentKind}get currentAd(){return this._currentAd}get isAdPlaying(){return this.adPlaying}canSkipAd(){return !this.adPlaying||!this._currentAd?.isSkippable?false:Math.floor(this.audio.currentTime*1e3)>=this._currentAd.skipAfterSeconds*1e3}getAdSkipCountdownSeconds(){if(!this.adPlaying||!this._currentAd?.isSkippable)return null;let e=Math.floor(this.audio.currentTime*1e3),i=this._currentAd.skipAfterSeconds*1e3;return e>=i?0:Math.ceil((i-e)/1e3)}get voiceState(){return this._voiceState}get voiceUserSpeaking(){return this._voiceUserSpeaking}controlPositionMs(){return this.activeContentKind===4?0:this.positionMsForAnalytics()}setupListeners(){this.transport.on("connected",()=>this.emit("connected")),this.transport.on("disconnected",e=>{(this._voiceState==="listening"||this._voiceState==="processing"||this._voiceState==="responding")&&(this.voiceCapture.cancel(),this.voiceResponsePlayer.stop(),this._voiceUserSpeaking=false,this.emit("voiceUserSpeakingChange",false),this.setVoiceState("idle"),this.pausedForVoice=false),this.emit("disconnected",e);}),this.transport.on("error",e=>this.emit("error",new O(e.message))),this.transport.on("message",e=>this.handleServerMessage(e)),this.audio.on("playing",()=>this.updateStatus("playing")),this.audio.on("paused",()=>this.updateStatus("paused")),this.audio.on("stopped",()=>{!this.adPlaying&&this._voiceState==="idle"&&this.updateStatus("idle");}),this.audio.on("loading",()=>this.updateStatus("loading")),this.audio.on("error",e=>{if(this.adPlaying){u("Ad playback error \u2014 waiting for next track",e);return}this.emit("error",new C(e));}),this.audio.on("timeupdate",e=>{this.emit("timeUpdate",e),this.adPlaying&&this._currentAd&&this.emitAdSkipUpdate(e.currentTime);}),this.audio.on("ended",()=>this.handleTrackEnded()),this.playlist.on("trackChanged",e=>this.emit("trackChange",e)),this.playlist.on("queueUpdated",e=>this.emit("queueUpdated",e)),this.voiceCapture.on("chunk",(e,i)=>{this.transport.sendVoice({action:2,audioData:e,mimeType:this.voiceMimeType,sequence:i,listenerId:this.voiceListenerId,deviceType:this.config.deviceType,gameContext:this.config.gameContext});}),this.voiceCapture.on("error",e=>{this.setVoiceState("error"),this.emit("error",new x(e.message,"VOICE_CAPTURE_FAILED"));}),this.voiceCapture.on("speechStart",()=>{this.emit("voiceSpeechStart");}),this.voiceCapture.on("speechEnd",()=>{this.emit("voiceSpeechEnd"),this.voiceAutoEndOnSilence&&this._voiceState==="listening"&&this.endVoiceHold();}),this.voiceCapture.on("userSpeakingChange",e=>{this._voiceUserSpeaking=e,this.emit("voiceUserSpeakingChange",e);});}resolveVoiceOptions(e={}){return {...this.config.voice,...e}}connect(){this.transport.connect(this.config.apiKey,this.config.serverUrl);}buildInitExtras(){let e={};return this.config.gameContext?.trim()&&(e.gameContext=this.config.gameContext.trim()),this.config.deviceType?.trim()&&(e.deviceType=this.config.deviceType.trim()),e}async playSong(e){this.transport.isConnected||this.connect(),await this.transport.waitForConnection(),this.voiceResponseDismissed=false,this.activeContentKind=1,this.transport.sendInit({contentKind:1,catalogTrackId:e.catalogTrackId,internalTrackId:e.internalTrackId,listenerId:e.listenerId,...this.buildInitExtras()});}async playPlaylist(e){this.transport.isConnected||this.connect(),await this.transport.waitForConnection(),this.voiceResponseDismissed=false,this.activeContentKind=2,this.transport.sendInit({contentKind:2,playlistCode:e.playlistCode,listenerId:e.listenerId,...this.buildInitExtras()});}async playRadio(e={}){this.transport.isConnected||this.connect(),await this.transport.waitForConnection(),this.voiceResponseDismissed=false,this.activeContentKind=4,this.transport.sendInit({contentKind:4,listenerId:e.listenerId,...this.buildInitExtras()});}async beginVoiceHold(e={}){if(this._voiceState==="listening"||this._voiceState==="processing"||this._voiceState==="responding")return;let i=this.resolveVoiceOptions(e);this.voiceAutoEndOnSilence=i.autoEndOnSilence!==false,this._voiceUserSpeaking=false,this.voiceResponseDismissed=false,this.transport.isConnected||this.connect(),await this.transport.waitForConnection(),this.voiceListenerId=i.listenerId?.trim()||void 0,this.pausedForVoice=this.status==="playing",this.pausedForVoice&&this.pause(),this.voiceResponsePlayer.stop(),this.setVoiceState("listening");try{this.voiceMimeType=await this.voiceCapture.start({maxDurationMs:i.maxDurationMs});}catch{this.pausedForVoice&&(this.pausedForVoice=false,this.resume());return}this.transport.sendVoice({action:1,mimeType:this.voiceMimeType||N,listenerId:this.voiceListenerId,...this.buildInitExtras()});}async endVoiceHold(){this._voiceState==="listening"&&(this._voiceUserSpeaking=false,this.emit("voiceUserSpeakingChange",false),this.setVoiceState("processing"),await this.voiceCapture.stop(),this.transport.sendVoice({action:3,mimeType:this.voiceMimeType,listenerId:this.voiceListenerId,...this.buildInitExtras()}));}cancelVoiceHold(){this._voiceState==="listening"&&(this._voiceUserSpeaking=false,this.voiceCapture.cancel(),this.transport.sendVoice({action:4,mimeType:this.voiceMimeType,listenerId:this.voiceListenerId,...this.buildInitExtras()}),this.setVoiceState("idle"));}dismissVoiceAndResume(){this.voiceResponseDismissed=true,this.voiceResponsePlayer.stop(),this._voiceState==="listening"?this.cancelVoiceHold():(this._voiceState==="processing"||this._voiceState==="responding")&&(this.transport.sendVoice({action:4,mimeType:this.voiceMimeType,listenerId:this.voiceListenerId,...this.buildInitExtras()}),this.setVoiceState("idle")),this.pausedForVoice&&(this.resume(),this.pausedForVoice=false);}get isVoiceUiActive(){return this._voiceState==="listening"||this._voiceState==="processing"||this._voiceState==="responding"}pause(){this.audio.pause(),this.transport.sendControl({action:2,positionMs:this.controlPositionMs()});}resume(){this.audio.play(),this.transport.sendControl({action:1,positionMs:this.controlPositionMs()});}stop(){this.audio.stop(),this.transport.sendControl({action:3,positionMs:this.controlPositionMs()});}skip(){if(this.activeContentKind===4)return;if(this.adPlaying){this.skipAd();return}if(this.playlist.queueSnapshot.length>1){this.transport.sendControl({action:5,positionMs:this.controlPositionMs()}),this.updateStatus("loading");return}let e=this.playlist.next();e&&this.playSong(e.kind==="internal"?{internalTrackId:e.id}:{catalogTrackId:e.id});}previous(){if(this.activeContentKind===4)return;if(this.playlist.queueSnapshot.length>1){this.transport.sendControl({action:6,positionMs:this.controlPositionMs()}),this.updateStatus("loading");return}let e=this.playlist.previous();e&&this.playSong(e.kind==="internal"?{internalTrackId:e.id}:{catalogTrackId:e.id});}skipTo(e){if(this.activeContentKind===4)return;let i=this.playlist.skipTo(e);i&&this.playSong(i.kind==="internal"?{internalTrackId:i.id}:{catalogTrackId:i.id});}seek(e){this.activeContentKind===4||this.adPlaying||(this.audio.seek(e),this.transport.sendControl({action:4,positionMs:e}));}setVolume(e){this.volume=Math.max(0,Math.min(1,e)),this.audio.setVolume(this.volume);}positionMsForAnalytics(e){return typeof e=="number"?Math.max(0,Math.min(4294967295,Math.floor(e))):Math.max(0,Math.min(4294967295,Math.floor(this.audio.currentTime)))}emitAnalytics(e,i,n){this.transport.sendAnalytics({eventType:e,positionMs:this.positionMsForAnalytics(i),extraJson:n?JSON.stringify(n):void 0});}clearHeartbeat(){this.heartbeatTimer!==null&&(clearInterval(this.heartbeatTimer),this.heartbeatTimer=null);}startHeartbeat(e){this.clearHeartbeat();let i=Number(e);!i||i<1e3||(this.heartbeatTimer=setInterval(()=>{let n=this.activeContentKind===4?0:this.positionMsForAnalytics();this.emitAnalytics("heartbeat",n);},i));}applyContentSummary(e){let i=ee(e,this.activeContentKind);if(i){this.playlist.setQueue(i.tracks,i.currentIndex);return}e?.trim()&&u("Could not parse contentSummary; queue metadata unavailable.");}emitAdSkipUpdate(e){if(!this._currentAd)return;let i=this._currentAd.skipAfterSeconds*1e3,n=this._currentAd.isSkippable&&e>=i,o=n?0:Math.ceil((i-e)/1e3),r={ad:this._currentAd,canSkip:n,countdownSeconds:o};this.emit("adSkipUpdate",r);}setVoiceState(e){this._voiceState=e,this.emit("voiceStateChange",e);}handleVoiceAck(e){let i=e.status;if(i==="cancelled"){this._voiceState!=="idle"&&this.setVoiceState("idle");return}if(!this.voiceResponseDismissed){if(i==="listening"){this._voiceState==="idle"&&this.setVoiceState("listening");return}if(i==="processing"){(this._voiceState==="listening"||this._voiceState==="idle")&&this.setVoiceState("processing");return}if(i==="ready"){this.activeContentKind=2;let n={status:i,transcript:e.transcript,playlistCode:e.playlistCode,playlistName:e.playlistName};this.setVoiceState("ready"),this.emit("voiceResult",n);return}this.emit("voiceResult",{status:i,transcript:e.transcript,playlistCode:e.playlistCode,playlistName:e.playlistName});}}async handleServerMessage(e){v("Received server message",e);let i=re(e);if(i){this.handleVoiceAck(i);return}let n=ae(e);if(n){if(this.voiceResponseDismissed)return;this._voiceState==="processing"&&this.setVoiceState("responding"),n.audioData.length>0&&this.voiceResponsePlayer.enqueueChunk(n.audioData,n.mimeType),n.isFinal&&(this.voicePlaybackPromise=this.voiceResponsePlayer.finish(n.mimeType).catch(l=>{u("Voice response playback failed",l);}).finally(()=>{this.voicePlaybackPromise=null;}));return}let o=ne(e);if(o){await this.handleAdPlayback(o);return}let r=Z(e);if(r){if(this.voiceResponseDismissed)return;await this.startContentPlayback(r);return}let a=e.error;if(a&&typeof a=="object"){let l=a,c=typeof l.message=="string"?l.message:"Unknown server error",h=typeof l.code=="string"?l.code:void 0;(this._voiceState==="processing"||this._voiceState==="listening"||this._voiceState==="responding")&&this.setVoiceState("error"),this.emit("error",new x(c,h));}}async startContentPlayback(e){if(this.adPlaying&&this._currentAd){let n=this._currentAd;this.adPlaying=false,this._currentAd=null,this.emit("adEnd",n);}else this.adPlaying=false,this._currentAd=null;this.voicePlaybackPromise&&!this.voiceResponseDismissed&&await this.voicePlaybackPromise,(this._voiceState==="ready"||this._voiceState==="processing"||this._voiceState==="responding")&&this.setVoiceState("idle"),this.pausedForVoice=false,this.voiceResponsePlayer.stop(),v("Loading playback",{url:e.playbackUrl,isHls:e.isHls});let i=this.audio.load(e.playbackUrl,e.isHls);this.pendingPlaybackLoad=i;try{if(await i,this.pendingPlaybackLoad!==i)return;this.audio.play(),this.emitAnalytics("stream_start",this.activeContentKind===4?0:void 0),this.startHeartbeat(e.heartbeatIntervalMs),this.applyContentSummary(e.contentSummary);}catch(n){if(this.pendingPlaybackLoad!==i)return;this.emit("error",new C(n));}finally{this.pendingPlaybackLoad===i&&(this.pendingPlaybackLoad=null);}}async handleAdPlayback(e){this.pendingPlaybackLoad&&await this.pendingPlaybackLoad.catch(()=>{}),this.audio.stop(),this.adPlaying=true,this._currentAd={adId:e.adId,campaignId:e.campaignId,brandName:e.brandName,creativeName:e.creativeName,durationSeconds:e.durationSeconds,isSkippable:e.isSkippable,skipAfterSeconds:e.skipAfterSeconds,ctaType:e.ctaType,ctaValue:e.ctaValue,companionBannerUrl:e.companionBannerUrl,campaignName:e.campaignName},v("Loading ad playback",{url:e.playbackUrl,isHls:e.isHls});try{await this.audio.load(e.playbackUrl,e.isHls),this.audio.play(),this.emit("adStart",this._currentAd),this.emitAdSkipUpdate(0);}catch(i){let n=this._currentAd;this.adPlaying=false,this._currentAd=null,n&&this.emit("adEnd",n),u("Ad load failed",i),this.updateStatus("loading");}}skipAd(){if(!this.adPlaying||!this._currentAd||!this._currentAd.isSkippable)return;let e=Math.floor(this.audio.currentTime*1e3);if(e<this._currentAd.skipAfterSeconds*1e3)return;let i=this._currentAd;this.adPlaying=false,this._currentAd=null,this.audio.stop(),this.emit("adEnd",i),this.emitAnalytics("ad_skip",e),this.updateStatus("loading");}clickAd(){if(!this.adPlaying||!this._currentAd)return;let e=Math.floor(this.audio.currentTime*1e3);this.emitAnalytics("ad_cta_click",e),this._currentAd.ctaValue&&window.open(this._currentAd.ctaValue,"_blank");}handleTrackEnded(){if(this.activeContentKind!==4){if(this.adPlaying&&this._currentAd){let e=this._currentAd;this.audio.stop(),this.emitAnalytics("ad_complete",Math.floor(this.audio.currentTime*1e3)),this.emit("adEnd",e),this.adPlaying=false,this._currentAd=null,this.updateStatus("loading");return}if(this.playlist.queueSnapshot.length>1){this.emitAnalytics("track_complete",Math.floor(this.audio.duration*1e3)),this.updateStatus("loading");return}if(this.activeContentKind===1||this.activeContentKind===2){this.emitAnalytics("track_complete",Math.floor(this.audio.duration*1e3)),this.updateStatus("loading");return}this.updateStatus("idle");}}updateStatus(e){this.status=e,this.emit("stateChange",{status:e,currentTrack:this.playlist.getCurrentTrack(),currentTime:this.audio.currentTime,duration:this.audio.duration,volume:this.volume});}destroy(){this.clearHeartbeat(),this.cancelVoiceHold(),this.voiceResponsePlayer.stop(),this.audio.stop(),this.transport.disconnect(),this.playlist.reset(),this.removeAllListeners();}};async function K(s,t){let i=`${s.replace(/\/$/,"")}/radio/now-playing`;try{let n=await fetch(i,{...t,headers:{Accept:"application/json",...t?.headers}});if(!n.ok)return null;let r=(await n.json())?.data;return !r?.title||typeof r.title!="string"?null:{title:r.title,station:typeof r.station=="string"?r.station:void 0,isLive:typeof r.isLive=="boolean"?r.isLive:void 0}}catch{return null}}function d(s,t){let e=document.createElement(s);if(t?.className&&(e.className=t.className),t?.attrs)for(let[i,n]of Object.entries(t.attrs))e.setAttribute(i,n);return t?.style&&Object.assign(e.style,t.style),t?.text&&(e.textContent=t.text),t?.html&&(e.innerHTML=t.html),t?.onClick&&e.addEventListener("click",t.onClick),t?.children&&t.children.forEach(i=>e.appendChild(i)),e}function y(s,t=20){let e=document.createElementNS("http://www.w3.org/2000/svg","svg");e.setAttribute("width",String(t)),e.setAttribute("height",String(t)),e.setAttribute("viewBox","0 0 24 24"),e.setAttribute("fill","currentColor"),e.setAttribute("aria-hidden","true");let i=document.createElementNS("http://www.w3.org/2000/svg","path");return i.setAttribute("d",s),e.appendChild(i),e}var F="M8 5v14l11-7L8 5z",oe="M6 5h4v14H6V5zm8 0h4v14h-4V5z",E="M6 18l8.5-6L6 6v12zM16 6v12h2V6h-2z",le="M6 6h2v12H6V6zm11.5 12L9 12l8.5-6v12z";function de(){let s="synxed-web-player-styles";if(document.getElementById(s))return;let t=document.createElement("style");t.id=s,t.textContent=`
|
|
137
137
|
@keyframes synxed-wp-spin { from { transform: rotate(0); } to { transform: rotate(360deg); } }
|
|
138
138
|
@keyframes synxed-wp-vbar {
|
|
139
139
|
0%, 100% { transform: scaleY(0.28); opacity: 0.45; }
|