synxed-sdk 0.3.5 → 0.3.10

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.d.mts CHANGED
@@ -154,6 +154,7 @@ declare class SynxedPlayer extends EventEmitter<SynxedEvents> {
154
154
  private voiceAutoEndOnSilence;
155
155
  private pausedForVoice;
156
156
  private _voiceUserSpeaking;
157
+ private voiceResponseDismissed;
157
158
  constructor(config: SynxedConfig);
158
159
  get currentTrack(): TrackInfo | null;
159
160
  /** Active playback init kind from the last `play*` call (RADIO, PLAYLIST, SONG, …). */
@@ -280,36 +281,22 @@ interface VoiceCaptureOptions {
280
281
  onnxWasmBasePath?: string;
281
282
  }
282
283
  /**
283
- * Silero VAD capture pre-warmed MicVAD instance, pause/reuse between holds.
284
+ * Mic capture via @ricky0123/vad-web same callbacks as the official demo:
285
+ * onSpeechStart / onSpeechEnd + streaming frames while the user talks.
284
286
  */
285
287
  declare class VoiceCaptureManager extends EventEmitter<VoiceCaptureEvents> {
286
288
  private capturing;
287
289
  private mimeType;
288
290
  private micVad;
289
- private initPromise;
290
291
  private vadBaseAssetPath;
291
292
  private onnxWasmBasePath;
292
- private speechEndEmitted;
293
293
  private userSpeaking;
294
- private maxDurationTimer;
295
294
  private chunkSequence;
296
295
  get isCapturing(): boolean;
297
296
  get isUserSpeaking(): boolean;
298
297
  preloadModels(options?: VoiceCaptureOptions): Promise<void>;
299
298
  private applyOptions;
300
- private toCaptureError;
301
- private clearMaxDurationTimer;
302
299
  private setUserSpeaking;
303
- private handleFrame;
304
- private handleSpeechStart;
305
- private handleSpeechEnd;
306
- /**
307
- * Pause the underlying MicVAD instance.
308
- * @param operation - caller context for logs and error messages
309
- * @param wasCapturing - whether capture was active before teardown
310
- * @param reportError - emit `error` to listeners when pause fails
311
- */
312
- private pauseMicVad;
313
300
  private ensureMicVad;
314
301
  start(options?: VoiceCaptureOptions): Promise<string>;
315
302
  stop(): Promise<void>;
@@ -425,7 +412,7 @@ declare class SynxedWebPlayer {
425
412
  private buildVisualizer;
426
413
  private decoLines;
427
414
  private initEngine;
428
- /** Press-and-hold DJ avatar to stream voice; release or silence auto-ends capture. */
415
+ /** Hold DJ avatar to arm voice; VAD silence decides when the command is done. */
429
416
  private wireAvatarVoiceHold;
430
417
  private isVoiceUiOpen;
431
418
  private dismissVoiceUi;
package/dist/index.d.ts CHANGED
@@ -154,6 +154,7 @@ declare class SynxedPlayer extends EventEmitter<SynxedEvents> {
154
154
  private voiceAutoEndOnSilence;
155
155
  private pausedForVoice;
156
156
  private _voiceUserSpeaking;
157
+ private voiceResponseDismissed;
157
158
  constructor(config: SynxedConfig);
158
159
  get currentTrack(): TrackInfo | null;
159
160
  /** Active playback init kind from the last `play*` call (RADIO, PLAYLIST, SONG, …). */
@@ -280,36 +281,22 @@ interface VoiceCaptureOptions {
280
281
  onnxWasmBasePath?: string;
281
282
  }
282
283
  /**
283
- * Silero VAD capture pre-warmed MicVAD instance, pause/reuse between holds.
284
+ * Mic capture via @ricky0123/vad-web same callbacks as the official demo:
285
+ * onSpeechStart / onSpeechEnd + streaming frames while the user talks.
284
286
  */
285
287
  declare class VoiceCaptureManager extends EventEmitter<VoiceCaptureEvents> {
286
288
  private capturing;
287
289
  private mimeType;
288
290
  private micVad;
289
- private initPromise;
290
291
  private vadBaseAssetPath;
291
292
  private onnxWasmBasePath;
292
- private speechEndEmitted;
293
293
  private userSpeaking;
294
- private maxDurationTimer;
295
294
  private chunkSequence;
296
295
  get isCapturing(): boolean;
297
296
  get isUserSpeaking(): boolean;
298
297
  preloadModels(options?: VoiceCaptureOptions): Promise<void>;
299
298
  private applyOptions;
300
- private toCaptureError;
301
- private clearMaxDurationTimer;
302
299
  private setUserSpeaking;
303
- private handleFrame;
304
- private handleSpeechStart;
305
- private handleSpeechEnd;
306
- /**
307
- * Pause the underlying MicVAD instance.
308
- * @param operation - caller context for logs and error messages
309
- * @param wasCapturing - whether capture was active before teardown
310
- * @param reportError - emit `error` to listeners when pause fails
311
- */
312
- private pauseMicVad;
313
300
  private ensureMicVad;
314
301
  start(options?: VoiceCaptureOptions): Promise<string>;
315
302
  stop(): Promise<void>;
@@ -425,7 +412,7 @@ declare class SynxedWebPlayer {
425
412
  private buildVisualizer;
426
413
  private decoLines;
427
414
  private initEngine;
428
- /** Press-and-hold DJ avatar to stream voice; release or silence auto-ends capture. */
415
+ /** Hold DJ avatar to arm voice; VAD silence decides when the command is done. */
429
416
  private wireAvatarVoiceHold;
430
417
  private isVoiceUiOpen;
431
418
  private dismissVoiceUi;
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- 'use strict';var j=require('protobufjs'),howler=require('howler');function _interopNamespace(e){if(e&&e.__esModule)return e;var n=Object.create(null);if(e){Object.keys(e).forEach(function(k){if(k!=='default'){var d=Object.getOwnPropertyDescriptor(e,k);Object.defineProperty(n,k,d.get?d:{enumerable:true,get:function(){return e[k]}});}})}n.default=e;return Object.freeze(n)}var j__namespace=/*#__PURE__*/_interopNamespace(j);var vt=`
1
+ 'use strict';var $=require('protobufjs'),howler=require('howler');function _interopNamespace(e){if(e&&e.__esModule)return e;var n=Object.create(null);if(e){Object.keys(e).forEach(function(k){if(k!=='default'){var d=Object.getOwnPropertyDescriptor(e,k);Object.defineProperty(n,k,d.get?d:{enumerable:true,get:function(){return e[k]}});}})}n.default=e;return Object.freeze(n)}var $__namespace=/*#__PURE__*/_interopNamespace($);var mt=`
2
2
  syntax = "proto3";
3
3
 
4
4
  enum ContentKind {
@@ -132,12 +132,12 @@ message SdkServerEnvelope {
132
132
  SdkServerVoiceAudio voiceAudio = 5;
133
133
  }
134
134
  }
135
- `,Y=j__namespace.parse(vt).root,H=Y.lookupType("SdkClientEnvelope"),D=Y.lookupType("SdkServerEnvelope"),R=(s=>(s[s.UNSPECIFIED=0]="UNSPECIFIED",s[s.SONG=1]="SONG",s[s.PLAYLIST=2]="PLAYLIST",s[s.CATEGORY=3]="CATEGORY",s[s.RADIO=4]="RADIO",s[s.VOICE=5]="VOICE",s))(R||{}),B=(n=>(n[n.VOICE_UNSPECIFIED=0]="VOICE_UNSPECIFIED",n[n.VOICE_START=1]="VOICE_START",n[n.VOICE_CHUNK=2]="VOICE_CHUNK",n[n.VOICE_END=3]="VOICE_END",n))(B||{}),G=(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))(G||{});var S=class{static encodeClientEnvelope(i){let t=H.create(i);return H.encode(t).finish()}static decodeServerEnvelope(i){let t=D.decode(i);return D.toObject(t,{enums:String,longs:String,bytes:String,defaults:true,oneofs:true})}};var v=class{constructor(){this.listeners=new Map;}on(i,t){this.listeners.has(i)||this.listeners.set(i,new Set),this.listeners.get(i).add(t);}off(i,t){let e=this.listeners.get(i);e&&e.delete(t);}once(i,t){let e=((...n)=>{t(...n),this.off(i,e);});this.on(i,e);}emit(i,...t){let e=this.listeners.get(i);e&&e.forEach(n=>n(...t));}removeAllListeners(){this.listeners.clear();}};var X=false;function J(r){X=r;}function m(...r){X&&console.debug("[Synxed]",...r);}function h(...r){console.warn("[Synxed]",...r);}function Q(r,i){let e=(r.endsWith("/")?r.slice(0,-1):r).replace(/^http:/,"ws:").replace(/^https:/,"wss:"),n=new URL(`${e}/sdk`);return n.searchParams.set("apiKey",i),n.toString()}var E=class extends v{constructor(){super(...arguments);this.ws=null;this.connectPromise=null;}connect(t,e){if(this.ws&&(this.ws.readyState===WebSocket.OPEN||this.ws.readyState===WebSocket.CONNECTING))return;let n=Q(e,t);m("Opening native WebSocket",n.replace(/apiKey=[^&]+/,"apiKey=***")),this.ws=new WebSocket(n),this.ws.binaryType="arraybuffer",this.ws.onopen=()=>{this.connectPromise=null,this.emit("connected");},this.ws.onclose=o=>{let s=o.reason||`code ${o.code}`;this.ws=null,this.connectPromise=null,this.emit("disconnected",s);},this.ws.onerror=()=>{this.emit("error",new Error("WebSocket connection error"));},this.ws.onmessage=o=>{try{let{data:s}=o;if(!(s instanceof ArrayBuffer))return;let a=S.decodeServerEnvelope(new Uint8Array(s));this.emit("message",a);}catch(s){this.emit("error",new Error(`Failed to decode message: ${s}`));}};}async waitForConnection(){if(m("Waiting for connection\u2026"),this.ws?.readyState===WebSocket.OPEN){m("Already connected");return}if(!this.ws)throw new Error("WebSocket not initialized. Call connect() first.");return this.connectPromise?this.connectPromise:(this.connectPromise=new Promise((t,e)=>{let n=this.ws;if(n.readyState===WebSocket.OPEN){t();return}let o=()=>{m("WebSocket connected"),l(),t();},s=()=>{h("WebSocket connection error"),l(),e(new Error("WebSocket connection failed"));},a=()=>{l(),e(new Error("WebSocket closed before connection was established"));},l=()=>{n.removeEventListener("open",o),n.removeEventListener("error",s),n.removeEventListener("close",a);};n.addEventListener("open",o),n.addEventListener("error",s),n.addEventListener("close",a);}),this.connectPromise)}disconnect(){this.ws&&(this.ws.onclose=null,this.ws.close(),this.ws=null,this.connectPromise=null);}sendInit(t){if(!this.isConnected)throw new Error("WebSocket not connected");m("Sending init packet",t),this.sendBytes(S.encodeClientEnvelope({init:t}));}sendControl(t){this.isConnected&&this.sendBytes(S.encodeClientEnvelope({control:t}));}sendAnalytics(t){this.isConnected&&this.sendBytes(S.encodeClientEnvelope({analytics:t}));}sendVoice(t){this.isConnected&&this.sendBytes(S.encodeClientEnvelope({voice:t}));}get isConnected(){return this.ws?.readyState===WebSocket.OPEN}sendBytes(t){if(!this.ws||this.ws.readyState!==WebSocket.OPEN)throw new Error("WebSocket not connected");this.ws.send(t);}};var _=class extends v{constructor(){super();this.howl=null;this.hls=null;this.audioEl=null;this.updateTimer=null;this.loadGeneration=0;}async load(t,e){let n=++this.loadGeneration;this.teardownPlayback(),this.emit("loading"),m("AudioEngine loading",{url:t,isHls:e});let o=/^((?!chrome|android).)*safari/i.test(navigator.userAgent);if(e&&!o)try{let{default:s}=await import('hls.js');if(s.isSupported()){m("Using Hls.js for playback");let a=new s({xhrSetup:c=>{c.setRequestHeader("ngrok-skip-browser-warning","true");}}),l=new Audio;return new Promise((c,u)=>{let p=()=>n!==this.loadGeneration,y=()=>{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");},mt=()=>{p()||(h("HLS audio element error"),this.emit("error",new Error("HLS playback failed")));};l.addEventListener("play",y),l.addEventListener("pause",b),l.addEventListener("ended",T),l.addEventListener("loadedmetadata",I),l.addEventListener("error",mt),a.on(s.Events.MANIFEST_PARSED,()=>{p()||(this.emit("loaded"),c());}),a.on(s.Events.ERROR,(kt,U)=>{p()||U.fatal&&(h("Fatal HLS error",U),u(U));}),a.loadSource(t),a.attachMedia(l),this.hls=a,this.audioEl=l;})}}catch(s){h("hls.js not available, falling back to native playback",s);}return new Promise((s,a)=>{let l=()=>n!==this.loadGeneration;this.howl=new howler.Howl({src:[t],html5:true,format:e?["m3u8"]:void 0,onload:()=>{l()||(m("AudioEngine loaded"),this.emit("loaded"),s());},onloaderror:(c,u)=>{l()||(h("AudioEngine load error",u),a(u));},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(t=>h("Play failed",t)):this.howl?.play();}pause(){this.audioEl?this.audioEl.pause():this.howl?.pause();}stop(){this.loadGeneration+=1,this.teardownPlayback(),this.emit("stopped");}seek(t){this.audioEl?this.audioEl.currentTime=t/1e3:this.howl?.seek(t/1e3);}setVolume(t){this.audioEl&&(this.audioEl.volume=t),this.howl&&this.howl.volume(t);}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 t=()=>{(this.audioEl?!this.audioEl.paused:this.howl?.playing())&&(this.emit("timeupdate",{currentTime:this.currentTime,duration:this.duration}),this.updateTimer=requestAnimationFrame(t));};this.updateTimer=requestAnimationFrame(t);}stopTimeUpdateLoop(){this.updateTimer!==null&&(cancelAnimationFrame(this.updateTimer),this.updateTimer=null);}};var V=class extends v{constructor(){super();this.queue=[];this.currentIndex=-1;}setQueue(t,e){this.queue=t,this.currentIndex=typeof e=="number"&&e>=0&&e<t.length?e:t.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 t=this.getCurrentTrack();return this.emit("trackChanged",t),t}return null}previous(){if(this.currentIndex>0){this.currentIndex--;let t=this.getCurrentTrack();return this.emit("trackChanged",t),t}return null}skipTo(t){if(t>=0&&t<this.queue.length){this.currentIndex=t;let e=this.getCurrentTrack();return this.emit("trackChanged",e),e}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(t,e){super(t);this.code=e;this.name="SynxedError";}},O=class extends x{constructor(i){super(i),this.name="SynxedConnectionError";}},w=class extends x{constructor(i){super(typeof i=="string"?i:"Playback failed"),this.name="SynxedPlaybackError";}},Z=class extends x{constructor(i){super(i),this.name="SynxedProtocolError";}};function W(r,...i){for(let t of i){let e=r[t];if(typeof e=="string"&&e.length>0)return e}}function gt(r,...i){for(let t of i){let e=r[t];if(typeof e=="number"&&Number.isFinite(e))return e;if(typeof e=="string"&&e!==""&&!Number.isNaN(Number(e)))return Number(e)}}function tt(r){let i=r.initAck??r.init_ack;if(!i||typeof i!="object")return null;let t=i,e=W(t,"playbackUrl","playback_url");return e?{sessionId:W(t,"sessionId","session_id")??"",playbackUrl:e,isHls:!!(t.isHls??t.is_hls),heartbeatIntervalMs:gt(t,"heartbeatIntervalMs","heartbeat_interval_ms")??0,contentSummary:W(t,"contentSummary","content_summary")}:null}function yt(r){if(!r||typeof r!="object")return null;let i=r,t=i.id;if(typeof t!="string"||!t.trim())return null;let e=i.kind==="internal"?"internal":"catalog",n=i.albumArt??i.album_art;return {id:t.trim(),kind:e,title:typeof i.title=="string"?i.title:void 0,artist:typeof i.artist=="string"?i.artist:void 0,duration:typeof i.duration=="number"?i.duration:void 0,albumArt:typeof n=="string"?n:void 0}}function et(r,i){if(!r?.trim())return null;let t;try{t=JSON.parse(r);}catch{return null}if(!t||typeof t!="object")return null;let e=t;if(e.type==="live_radio"||i===4)return {tracks:[{id:"synxed-radio",kind:"catalog",title:typeof e.station=="string"&&e.station.trim()?e.station.trim():"Synxed Radio",artist:""}],currentIndex:0};let o=e.tracks;if(!Array.isArray(o)||o.length===0)return null;let s=[];for(let c of o){let u=yt(c);u&&s.push(u);}if(s.length===0)return null;let a=typeof e.currentIndex=="number"?e.currentIndex:typeof e.current_index=="number"?e.current_index:0,l=Math.max(0,Math.min(Math.floor(a),s.length-1));return {tracks:s,currentIndex:l}}function f(r,...i){for(let t of i){let e=r[t];if(typeof e=="string")return e}return ""}function it(r,...i){for(let t of i){let e=r[t];if(typeof e=="boolean")return e}return false}function nt(r,...i){for(let t of i){let e=r[t];if(typeof e=="number"&&Number.isFinite(e))return e;if(typeof e=="string"&&e.trim()){let n=Number(e);if(Number.isFinite(n))return n}}return 0}function rt(r){let i=r.ad;if(!i||typeof i!="object")return null;let t=i,e=f(t,"playbackUrl","playback_url");return e?{adId:f(t,"adId","ad_id"),campaignId:f(t,"campaignId","campaign_id"),playbackUrl:e,isHls:it(t,"isHls","is_hls")||e.includes(".m3u8"),durationSeconds:nt(t,"durationSeconds","duration_seconds")||15,isSkippable:it(t,"isSkippable","is_skippable"),skipAfterSeconds:nt(t,"skipAfterSeconds","skip_after_seconds"),ctaType:f(t,"ctaType","cta_type"),ctaValue:f(t,"ctaValue","cta_value"),brandName:f(t,"brandName","brand_name"),creativeName:f(t,"creativeName","creative_name"),companionBannerUrl:f(t,"companionBannerUrl","companion_banner_url"),campaignName:f(t,"campaignName","campaign_name")}:null}var N="audio/pcm;rate=16000",C="audio/pcm;rate=24000";function K(r,i){let t=/rate=(\d+)/i.exec(r);if(!t)return i;let e=Number(t[1]);return Number.isFinite(e)&&e>0?e:i}function A(r,...i){for(let t of i){let e=r[t];if(typeof e=="string")return e}return ""}function st(r){let i=r.voiceAck??r.voice_ack;if(!i||typeof i!="object")return null;let t=i,e=A(t,"status");return e?{status:e,transcript:A(t,"transcript")||void 0,playlistCode:A(t,"playlistCode","playlist_code")||void 0,playlistName:A(t,"playlistName","playlist_name")||void 0}:null}function at(r){let i=r.voiceAudio??r.voice_audio;if(!i||typeof i!="object")return null;let t=i,e=t.audioData??t.audio_data,n=A(t,"mimeType","mime_type")||C,o=!!(t.isFinal??t.is_final),s;if(typeof e=="string"){let a=atob(e),l=a.length;s=new Uint8Array(l);for(let c=0;c<l;c++)s[c]=a.charCodeAt(c);}else if(e instanceof Uint8Array)s=e;else return null;return {audioData:s,mimeType:n,isFinal:o}}var M=class{constructor(){this.audioContext=null;this.nextStartTime=0;this.defaultSampleRate=K(C,24e3);}initContext(i){this.audioContext||(this.audioContext=new(window.AudioContext||window.webkitAudioContext)({sampleRate:i}),this.nextStartTime=this.audioContext.currentTime);}enqueueChunk(i,t=C){try{let e=K(t,this.defaultSampleRate);if(this.initContext(e),!this.audioContext)return;let n=new Int16Array(i.buffer,i.byteOffset,i.byteLength/2),o=new Float32Array(n.length);for(let c=0;c<n.length;c++)o[c]=n[c]/32768;let s=this.audioContext.createBuffer(1,o.length,e);s.getChannelData(0).set(o);let a=this.audioContext.createBufferSource();a.buffer=s,a.connect(this.audioContext.destination);let l=this.audioContext.currentTime;this.nextStartTime<l&&(this.nextStartTime=l+.05),a.start(this.nextStartTime),this.nextStartTime+=s.duration;}catch(e){h("VoiceResponsePlayer failed to enqueue chunk",e);}}stop(){this.audioContext&&(this.audioContext.close().catch(()=>{}),this.audioContext=null),this.nextStartTime=0;}};var bt="https://cdn.jsdelivr.net/npm/@ricky0123/vad-web@0.0.29/dist/",St="https://cdn.jsdelivr.net/npm/onnxruntime-web@1.22.0/dist/",P=class extends v{constructor(){super(...arguments);this.capturing=false;this.mimeType=N;this.micVad=null;this.initPromise=null;this.vadBaseAssetPath=bt;this.onnxWasmBasePath=St;this.speechEndEmitted=false;this.userSpeaking=false;this.maxDurationTimer=null;this.chunkSequence=0;}get isCapturing(){return this.capturing}get isUserSpeaking(){return this.userSpeaking}async preloadModels(t={}){this.applyOptions(t);try{await this.ensureMicVad();}catch(e){let n=this.toCaptureError(e,"Failed to preload voice capture models");throw h(n.message,e),n}}applyOptions(t){t.vadBaseAssetPath&&(this.vadBaseAssetPath=t.vadBaseAssetPath),t.onnxWasmBasePath&&(this.onnxWasmBasePath=t.onnxWasmBasePath);}toCaptureError(t,e){return t instanceof Error?new Error(`${e}: ${t.message}`):new Error(`${e}: ${String(t)}`)}clearMaxDurationTimer(){this.maxDurationTimer!==null&&(clearTimeout(this.maxDurationTimer),this.maxDurationTimer=null);}setUserSpeaking(t){this.userSpeaking!==t&&(this.userSpeaking=t,this.emit("userSpeakingChange",t));}handleFrame(t){if(!this.capturing||this.speechEndEmitted)return;let e=new Int16Array(t.length);for(let n=0;n<t.length;n++){let o=Math.max(-1,Math.min(1,t[n]));e[n]=o<0?o*32768:o*32767;}this.chunkSequence+=1,this.emit("chunk",new Uint8Array(e.buffer),this.chunkSequence);}handleSpeechStart(){this.capturing&&(this.speechEndEmitted=false,this.setUserSpeaking(true),this.emit("speechStart"));}handleSpeechEnd(){!this.capturing||this.speechEndEmitted||(this.speechEndEmitted=true,this.setUserSpeaking(false),this.emit("speechEnd"));}pauseMicVad(t,e,n){if(this.micVad)try{this.micVad.pause();}catch(o){let s=this.toCaptureError(o,`Microphone pause failed during ${t}`);h(s.message,o),e&&n?this.emit("error",s):e&&h("Voice capture may still be active in the browser after stop; release the mic hold and retry if audio issues persist.");}}async ensureMicVad(){if(!this.micVad){if(this.initPromise){await this.initPromise;return}this.initPromise=(async()=>{try{let{MicVAD:t}=await import('@ricky0123/vad-web'),e=await t.new({baseAssetPath:this.vadBaseAssetPath,onnxWASMBasePath:this.onnxWasmBasePath,positiveSpeechThreshold:.5,negativeSpeechThreshold:.35,redemptionMs:500,minSpeechMs:250,onFrameProcessed:(n,o)=>{this.handleFrame(o);},onSpeechStart:()=>this.handleSpeechStart(),onSpeechEnd:()=>this.handleSpeechEnd()});try{e.pause();}catch(n){throw this.toCaptureError(n,"Failed to pause MicVAD after initialization")}this.micVad=e;}catch(t){throw this.initPromise=null,t}})(),await this.initPromise;}}async start(t={}){if(this.capturing)return this.mimeType;this.applyOptions(t),this.speechEndEmitted=false,this.chunkSequence=0,this.setUserSpeaking(false),this.clearMaxDurationTimer();try{if(await this.ensureMicVad(),!this.micVad)throw new Error("VAD failed to initialize");this.capturing=!0;try{this.micVad.start();}catch(n){throw this.capturing=!1,this.toCaptureError(n,"Failed to start microphone capture")}let e=t.maxDurationMs??3e4;e>0&&(this.maxDurationTimer=setTimeout(()=>{this.capturing&&this.handleSpeechEnd();},e));}catch(e){this.capturing=false;let n=this.toCaptureError(e,"Failed to initialize voice capture");h(n.message,e),this.emit("error",n);}return this.mimeType}async stop(){this.clearMaxDurationTimer();let t=this.capturing;this.capturing=false,this.setUserSpeaking(false),this.pauseMicVad("stop",t,false);}cancel(){this.clearMaxDurationTimer();let t=this.capturing;this.capturing=false,this.speechEndEmitted=false,this.setUserSpeaking(false),this.pauseMicVad("cancel",t,true);}};var L=class extends v{constructor(t){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.config=t,J(!!t.debug),this.transport=new E,this.audio=new _,this.playlist=new V,this.voiceCapture=new P,this.voiceResponsePlayer=new M,this.setupListeners(),this.voiceCapture.preloadModels(this.config.voice),t.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 t=Math.floor(this.audio.currentTime*1e3),e=this._currentAd.skipAfterSeconds*1e3;return t>=e?0:Math.ceil((e-t)/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",t=>this.emit("disconnected",t)),this.transport.on("error",t=>this.emit("error",new O(t.message))),this.transport.on("message",t=>this.handleServerMessage(t)),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",t=>{if(this.adPlaying){h("Ad playback error \u2014 waiting for next track",t);return}this.emit("error",new w(t));}),this.audio.on("timeupdate",t=>{this.emit("timeUpdate",t),this.adPlaying&&this._currentAd&&this.emitAdSkipUpdate(t.currentTime);}),this.audio.on("ended",()=>this.handleTrackEnded()),this.playlist.on("trackChanged",t=>this.emit("trackChange",t)),this.playlist.on("queueUpdated",t=>this.emit("queueUpdated",t)),this.voiceCapture.on("chunk",(t,e)=>{this.transport.sendVoice({action:2,audioData:t,mimeType:this.voiceMimeType,sequence:e,listenerId:this.voiceListenerId,deviceType:this.config.deviceType,gameContext:this.config.gameContext});}),this.voiceCapture.on("error",t=>{this.setVoiceState("error"),this.emit("error",new x(t.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",t=>{this._voiceUserSpeaking=t,this.emit("voiceUserSpeakingChange",t);});}resolveVoiceOptions(t={}){return {...this.config.voice,...t}}connect(){this.transport.connect(this.config.apiKey,this.config.serverUrl);}buildInitExtras(){let t={};return this.config.gameContext?.trim()&&(t.gameContext=this.config.gameContext.trim()),this.config.deviceType?.trim()&&(t.deviceType=this.config.deviceType.trim()),t}async playSong(t){this.transport.isConnected||this.connect(),await this.transport.waitForConnection(),this.activeContentKind=1,this.transport.sendInit({contentKind:1,catalogTrackId:t.catalogTrackId,internalTrackId:t.internalTrackId,listenerId:t.listenerId,...this.buildInitExtras()});}async playPlaylist(t){this.transport.isConnected||this.connect(),await this.transport.waitForConnection(),this.activeContentKind=2,this.transport.sendInit({contentKind:2,playlistCode:t.playlistCode,listenerId:t.listenerId,...this.buildInitExtras()});}async playRadio(t={}){this.transport.isConnected||this.connect(),await this.transport.waitForConnection(),this.activeContentKind=4,this.transport.sendInit({contentKind:4,listenerId:t.listenerId,...this.buildInitExtras()});}async beginVoiceHold(t={}){if(this._voiceState==="listening"||this._voiceState==="processing"||this._voiceState==="responding")return;let e=this.resolveVoiceOptions(t);this.voiceAutoEndOnSilence=e.autoEndOnSilence!==false,this._voiceUserSpeaking=false,this.transport.isConnected||this.connect(),await this.transport.waitForConnection(),this.voiceListenerId=e.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:e.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.setVoiceState("idle"));}dismissVoiceAndResume(){this._voiceState==="listening"&&this.cancelVoiceHold(),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 t=this.playlist.next();t&&this.playSong(t.kind==="internal"?{internalTrackId:t.id}:{catalogTrackId:t.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 t=this.playlist.previous();t&&this.playSong(t.kind==="internal"?{internalTrackId:t.id}:{catalogTrackId:t.id});}skipTo(t){if(this.activeContentKind===4)return;let e=this.playlist.skipTo(t);e&&this.playSong(e.kind==="internal"?{internalTrackId:e.id}:{catalogTrackId:e.id});}seek(t){this.activeContentKind===4||this.adPlaying||(this.audio.seek(t),this.transport.sendControl({action:4,positionMs:t}));}setVolume(t){this.volume=Math.max(0,Math.min(1,t)),this.audio.setVolume(this.volume);}positionMsForAnalytics(t){return typeof t=="number"?Math.max(0,Math.min(4294967295,Math.floor(t))):Math.max(0,Math.min(4294967295,Math.floor(this.audio.currentTime)))}emitAnalytics(t,e,n){this.transport.sendAnalytics({eventType:t,positionMs:this.positionMsForAnalytics(e),extraJson:n?JSON.stringify(n):void 0});}clearHeartbeat(){this.heartbeatTimer!==null&&(clearInterval(this.heartbeatTimer),this.heartbeatTimer=null);}startHeartbeat(t){this.clearHeartbeat();let e=Number(t);!e||e<1e3||(this.heartbeatTimer=setInterval(()=>{let n=this.activeContentKind===4?0:this.positionMsForAnalytics();this.emitAnalytics("heartbeat",n);},e));}applyContentSummary(t){let e=et(t,this.activeContentKind);if(e){this.playlist.setQueue(e.tracks,e.currentIndex);return}t?.trim()&&h("Could not parse contentSummary; queue metadata unavailable.");}emitAdSkipUpdate(t){if(!this._currentAd)return;let e=this._currentAd.skipAfterSeconds*1e3,n=this._currentAd.isSkippable&&t>=e,o=n?0:Math.ceil((e-t)/1e3),s={ad:this._currentAd,canSkip:n,countdownSeconds:o};this.emit("adSkipUpdate",s);}setVoiceState(t){this._voiceState=t,this.emit("voiceStateChange",t);}handleVoiceAck(t){let e=t.status;if(e==="listening"){this._voiceState==="idle"&&this.setVoiceState("listening");return}if(e==="processing"){(this._voiceState==="listening"||this._voiceState==="idle")&&this.setVoiceState("processing");return}if(e==="ready"){this.activeContentKind=2;let n={status:e,transcript:t.transcript,playlistCode:t.playlistCode,playlistName:t.playlistName};this.setVoiceState("ready"),this.emit("voiceResult",n);return}this.emit("voiceResult",{status:e,transcript:t.transcript,playlistCode:t.playlistCode,playlistName:t.playlistName});}async handleServerMessage(t){m("Received server message",t);let e=st(t);if(e){this.handleVoiceAck(e);return}let n=at(t);if(n){this._voiceState==="processing"&&this.setVoiceState("responding"),n.audioData.length>0&&this.voiceResponsePlayer.enqueueChunk(n.audioData,n.mimeType);return}let o=rt(t);if(o){await this.handleAdPlayback(o);return}let s=tt(t);if(s){await this.startContentPlayback(s);return}let a=t.error;if(a&&typeof a=="object"){let l=a,c=typeof l.message=="string"?l.message:"Unknown server error",u=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,u));}}async startContentPlayback(t){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._voiceState==="ready"||this._voiceState==="processing"||this._voiceState==="responding")&&this.setVoiceState("idle"),this.pausedForVoice=false,this.voiceResponsePlayer.stop(),m("Loading playback",{url:t.playbackUrl,isHls:t.isHls});let e=this.audio.load(t.playbackUrl,t.isHls);this.pendingPlaybackLoad=e;try{if(await e,this.pendingPlaybackLoad!==e)return;this.audio.play(),this.emitAnalytics("stream_start",this.activeContentKind===4?0:void 0),this.startHeartbeat(t.heartbeatIntervalMs),this.applyContentSummary(t.contentSummary);}catch(n){if(this.pendingPlaybackLoad!==e)return;this.emit("error",new w(n));}finally{this.pendingPlaybackLoad===e&&(this.pendingPlaybackLoad=null);}}async handleAdPlayback(t){this.pendingPlaybackLoad&&await this.pendingPlaybackLoad.catch(()=>{}),this.audio.stop(),this.adPlaying=true,this._currentAd={adId:t.adId,campaignId:t.campaignId,brandName:t.brandName,creativeName:t.creativeName,durationSeconds:t.durationSeconds,isSkippable:t.isSkippable,skipAfterSeconds:t.skipAfterSeconds,ctaType:t.ctaType,ctaValue:t.ctaValue,companionBannerUrl:t.companionBannerUrl,campaignName:t.campaignName},m("Loading ad playback",{url:t.playbackUrl,isHls:t.isHls});try{await this.audio.load(t.playbackUrl,t.isHls),this.audio.play(),this.emit("adStart",this._currentAd),this.emitAdSkipUpdate(0);}catch(e){let n=this._currentAd;this.adPlaying=false,this._currentAd=null,n&&this.emit("adEnd",n),h("Ad load failed",e),this.updateStatus("loading");}}skipAd(){if(!this.adPlaying||!this._currentAd||!this._currentAd.isSkippable)return;let t=Math.floor(this.audio.currentTime*1e3);if(t<this._currentAd.skipAfterSeconds*1e3)return;let e=this._currentAd;this.adPlaying=false,this._currentAd=null,this.audio.stop(),this.emit("adEnd",e),this.emitAnalytics("ad_skip",t),this.updateStatus("loading");}clickAd(){if(!this.adPlaying||!this._currentAd)return;let t=Math.floor(this.audio.currentTime*1e3);this.emitAnalytics("ad_cta_click",t),this._currentAd.ctaValue&&window.open(this._currentAd.ctaValue,"_blank");}handleTrackEnded(){if(this.activeContentKind!==4){if(this.adPlaying&&this._currentAd){let t=this._currentAd;this.audio.stop(),this.emitAnalytics("ad_complete",Math.floor(this.audio.currentTime*1e3)),this.emit("adEnd",t),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(t){this.status=t,this.emit("stateChange",{status:t,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 F(r,i){let e=`${r.replace(/\/$/,"")}/radio/now-playing`;try{let n=await fetch(e,{...i,headers:{Accept:"application/json",...i?.headers}});if(!n.ok)return null;let s=(await n.json())?.data;return !s?.title||typeof s.title!="string"?null:{title:s.title,station:typeof s.station=="string"?s.station:void 0,isLive:typeof s.isLive=="boolean"?s.isLive:void 0}}catch{return null}}function d(r,i){let t=document.createElement(r);if(i?.className&&(t.className=i.className),i?.attrs)for(let[e,n]of Object.entries(i.attrs))t.setAttribute(e,n);return i?.style&&Object.assign(t.style,i.style),i?.text&&(t.textContent=i.text),i?.html&&(t.innerHTML=i.html),i?.onClick&&t.addEventListener("click",i.onClick),i?.children&&i.children.forEach(e=>t.appendChild(e)),t}function g(r,i=20){let t=document.createElementNS("http://www.w3.org/2000/svg","svg");t.setAttribute("width",String(i)),t.setAttribute("height",String(i)),t.setAttribute("viewBox","0 0 24 24"),t.setAttribute("fill","currentColor"),t.setAttribute("aria-hidden","true");let e=document.createElementNS("http://www.w3.org/2000/svg","path");return e.setAttribute("d",r),t.appendChild(e),t}var z="M8 5v14l11-7L8 5z",ot="M6 5h4v14H6V5zm8 0h4v14h-4V5z",k="M6 18l8.5-6L6 6v12zM16 6v12h2V6h-2z",lt="M6 6h2v12H6V6zm11.5 12L9 12l8.5-6v12z";function dt(){let r="synxed-web-player-styles";if(document.getElementById(r))return;let i=document.createElement("style");i.id=r,i.textContent=`
135
+ `,Y=$__namespace.parse(mt).root,D=Y.lookupType("SdkClientEnvelope"),H=Y.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=(n=>(n[n.VOICE_UNSPECIFIED=0]="VOICE_UNSPECIFIED",n[n.VOICE_START=1]="VOICE_START",n[n.VOICE_CHUNK=2]="VOICE_CHUNK",n[n.VOICE_END=3]="VOICE_END",n))(B||{}),G=(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))(G||{});var S=class{static encodeClientEnvelope(e){let t=D.create(e);return D.encode(t).finish()}static decodeServerEnvelope(e){let t=H.decode(e);return H.toObject(t,{enums:String,longs:String,bytes:String,defaults:true,oneofs:true})}};var m=class{constructor(){this.listeners=new Map;}on(e,t){this.listeners.has(e)||this.listeners.set(e,new Set),this.listeners.get(e).add(t);}off(e,t){let i=this.listeners.get(e);i&&i.delete(t);}once(e,t){let i=((...n)=>{t(...n),this.off(e,i);});this.on(e,i);}emit(e,...t){let i=this.listeners.get(e);i&&i.forEach(n=>n(...t));}removeAllListeners(){this.listeners.clear();}};var X=false;function J(s){X=s;}function v(...s){X&&console.debug("[Synxed]",...s);}function u(...s){console.warn("[Synxed]",...s);}function Q(s,e){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",e),n.toString()}var E=class extends m{constructor(){super(...arguments);this.ws=null;this.connectPromise=null;}connect(t,i){if(this.ws&&(this.ws.readyState===WebSocket.OPEN||this.ws.readyState===WebSocket.CONNECTING))return;let n=Q(i,t);v("Opening native WebSocket",n.replace(/apiKey=[^&]+/,"apiKey=***")),this.ws=new WebSocket(n),this.ws.binaryType="arraybuffer",this.ws.onopen=()=>{this.connectPromise=null,this.emit("connected");},this.ws.onclose=o=>{let r=o.reason||`code ${o.code}`;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((t,i)=>{let n=this.ws;if(n.readyState===WebSocket.OPEN){t();return}let o=()=>{v("WebSocket connected"),l(),t();},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);}sendInit(t){if(!this.isConnected)throw new Error("WebSocket not connected");v("Sending init packet",t),this.sendBytes(S.encodeClientEnvelope({init:t}));}sendControl(t){this.isConnected&&this.sendBytes(S.encodeClientEnvelope({control:t}));}sendAnalytics(t){this.isConnected&&this.sendBytes(S.encodeClientEnvelope({analytics:t}));}sendVoice(t){this.isConnected&&this.sendBytes(S.encodeClientEnvelope({voice:t}));}get isConnected(){return this.ws?.readyState===WebSocket.OPEN}sendBytes(t){if(!this.ws||this.ws.readyState!==WebSocket.OPEN)throw new Error("WebSocket not connected");this.ws.send(t);}};var V=class extends m{constructor(){super();this.howl=null;this.hls=null;this.audioEl=null;this.updateTimer=null;this.loadGeneration=0;}async load(t,i){let n=++this.loadGeneration;this.teardownPlayback(),this.emit("loading"),v("AudioEngine loading",{url:t,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,y=()=>{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");},vt=()=>{p()||(u("HLS audio element error"),this.emit("error",new Error("HLS playback failed")));};l.addEventListener("play",y),l.addEventListener("pause",b),l.addEventListener("ended",T),l.addEventListener("loadedmetadata",I),l.addEventListener("error",vt),a.on(r.Events.MANIFEST_PARSED,()=>{p()||(this.emit("loaded"),c());}),a.on(r.Events.ERROR,(Et,U)=>{p()||U.fatal&&(u("Fatal HLS error",U),h(U));}),a.loadSource(t),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 howler.Howl({src:[t],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(t=>u("Play failed",t)):this.howl?.play();}pause(){this.audioEl?this.audioEl.pause():this.howl?.pause();}stop(){this.loadGeneration+=1,this.teardownPlayback(),this.emit("stopped");}seek(t){this.audioEl?this.audioEl.currentTime=t/1e3:this.howl?.seek(t/1e3);}setVolume(t){this.audioEl&&(this.audioEl.volume=t),this.howl&&this.howl.volume(t);}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 t=()=>{(this.audioEl?!this.audioEl.paused:this.howl?.playing())&&(this.emit("timeupdate",{currentTime:this.currentTime,duration:this.duration}),this.updateTimer=requestAnimationFrame(t));};this.updateTimer=requestAnimationFrame(t);}stopTimeUpdateLoop(){this.updateTimer!==null&&(cancelAnimationFrame(this.updateTimer),this.updateTimer=null);}};var _=class extends m{constructor(){super();this.queue=[];this.currentIndex=-1;}setQueue(t,i){this.queue=t,this.currentIndex=typeof i=="number"&&i>=0&&i<t.length?i:t.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 t=this.getCurrentTrack();return this.emit("trackChanged",t),t}return null}previous(){if(this.currentIndex>0){this.currentIndex--;let t=this.getCurrentTrack();return this.emit("trackChanged",t),t}return null}skipTo(t){if(t>=0&&t<this.queue.length){this.currentIndex=t;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(t,i){super(t);this.code=i;this.name="SynxedError";}},O=class extends x{constructor(e){super(e),this.name="SynxedConnectionError";}},w=class extends x{constructor(e){super(typeof e=="string"?e:"Playback failed"),this.name="SynxedPlaybackError";}},Z=class extends x{constructor(e){super(e),this.name="SynxedProtocolError";}};function W(s,...e){for(let t of e){let i=s[t];if(typeof i=="string"&&i.length>0)return i}}function gt(s,...e){for(let t of e){let i=s[t];if(typeof i=="number"&&Number.isFinite(i))return i;if(typeof i=="string"&&i!==""&&!Number.isNaN(Number(i)))return Number(i)}}function tt(s){let e=s.initAck??s.init_ack;if(!e||typeof e!="object")return null;let t=e,i=W(t,"playbackUrl","playback_url");return i?{sessionId:W(t,"sessionId","session_id")??"",playbackUrl:i,isHls:!!(t.isHls??t.is_hls),heartbeatIntervalMs:gt(t,"heartbeatIntervalMs","heartbeat_interval_ms")??0,contentSummary:W(t,"contentSummary","content_summary")}:null}function yt(s){if(!s||typeof s!="object")return null;let e=s,t=e.id;if(typeof t!="string"||!t.trim())return null;let i=e.kind==="internal"?"internal":"catalog",n=e.albumArt??e.album_art;return {id:t.trim(),kind:i,title:typeof e.title=="string"?e.title:void 0,artist:typeof e.artist=="string"?e.artist:void 0,duration:typeof e.duration=="number"?e.duration:void 0,albumArt:typeof n=="string"?n:void 0}}function et(s,e){if(!s?.trim())return null;let t;try{t=JSON.parse(s);}catch{return null}if(!t||typeof t!="object")return null;let i=t;if(i.type==="live_radio"||e===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=yt(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,...e){for(let t of e){let i=s[t];if(typeof i=="string")return i}return ""}function it(s,...e){for(let t of e){let i=s[t];if(typeof i=="boolean")return i}return false}function nt(s,...e){for(let t of e){let i=s[t];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 st(s){let e=s.ad;if(!e||typeof e!="object")return null;let t=e,i=f(t,"playbackUrl","playback_url");return i?{adId:f(t,"adId","ad_id"),campaignId:f(t,"campaignId","campaign_id"),playbackUrl:i,isHls:it(t,"isHls","is_hls")||i.includes(".m3u8"),durationSeconds:nt(t,"durationSeconds","duration_seconds")||15,isSkippable:it(t,"isSkippable","is_skippable"),skipAfterSeconds:nt(t,"skipAfterSeconds","skip_after_seconds"),ctaType:f(t,"ctaType","cta_type"),ctaValue:f(t,"ctaValue","cta_value"),brandName:f(t,"brandName","brand_name"),creativeName:f(t,"creativeName","creative_name"),companionBannerUrl:f(t,"companionBannerUrl","companion_banner_url"),campaignName:f(t,"campaignName","campaign_name")}:null}var N="audio/pcm;rate=16000",A="audio/pcm;rate=24000";function K(s,e){let t=/rate=(\d+)/i.exec(s);if(!t)return e;let i=Number(t[1]);return Number.isFinite(i)&&i>0?i:e}function C(s,...e){for(let t of e){let i=s[t];if(typeof i=="string")return i}return ""}function rt(s){let e=s.voiceAck??s.voice_ack;if(!e||typeof e!="object")return null;let t=e,i=C(t,"status");return i?{status:i,transcript:C(t,"transcript")||void 0,playlistCode:C(t,"playlistCode","playlist_code")||void 0,playlistName:C(t,"playlistName","playlist_name")||void 0}:null}function at(s){let e=s.voiceAudio??s.voice_audio;if(!e||typeof e!="object")return null;let t=e,i=t.audioData??t.audio_data,n=C(t,"mimeType","mime_type")||A,o=!!(t.isFinal??t.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=K(A,24e3);}initContext(e){this.audioContext||(this.audioContext=new(window.AudioContext||window.webkitAudioContext)({sampleRate:e}),this.nextStartTime=this.audioContext.currentTime);}enqueueChunk(e,t=A){try{let i=K(t,this.defaultSampleRate);if(this.initContext(i),!this.audioContext)return;let n=new Int16Array(e.buffer,e.byteOffset,e.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();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);}}stop(){this.audioContext&&(this.audioContext.close().catch(()=>{}),this.audioContext=null),this.nextStartTime=0;}};var bt="https://cdn.jsdelivr.net/npm/@ricky0123/vad-web@0.0.29/dist/",St="https://cdn.jsdelivr.net/npm/onnxruntime-web@1.22.0/dist/";async function xt(){let s=await import('@ricky0123/vad-web'),e=s.MicVAD??s.default?.MicVAD;if(!e)throw new Error("MicVAD export missing from @ricky0123/vad-web \u2014 check bundler resolves the package");return e}var P=class extends m{constructor(){super(...arguments);this.capturing=false;this.mimeType=N;this.micVad=null;this.vadBaseAssetPath=bt;this.onnxWasmBasePath=St;this.userSpeaking=false;this.chunkSequence=0;}get isCapturing(){return this.capturing}get isUserSpeaking(){return this.userSpeaking}async preloadModels(t={}){this.applyOptions(t),await this.ensureMicVad();}applyOptions(t){t.vadBaseAssetPath&&(this.vadBaseAssetPath=t.vadBaseAssetPath),t.onnxWasmBasePath&&(this.onnxWasmBasePath=t.onnxWasmBasePath);}setUserSpeaking(t){this.userSpeaking!==t&&(this.userSpeaking=t,this.emit("userSpeakingChange",t));}async ensureMicVad(){if(this.micVad)return;let i=await(await xt()).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(t={}){if(this.capturing)return this.mimeType;this.applyOptions(t),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(t){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.config=t,J(!!t.debug),this.transport=new E,this.audio=new V,this.playlist=new _,this.voiceCapture=new P,this.voiceResponsePlayer=new M,this.setupListeners(),this.voiceCapture.preloadModels(this.config.voice),t.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 t=Math.floor(this.audio.currentTime*1e3),i=this._currentAd.skipAfterSeconds*1e3;return t>=i?0:Math.ceil((i-t)/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",t=>this.emit("disconnected",t)),this.transport.on("error",t=>this.emit("error",new O(t.message))),this.transport.on("message",t=>this.handleServerMessage(t)),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",t=>{if(this.adPlaying){u("Ad playback error \u2014 waiting for next track",t);return}this.emit("error",new w(t));}),this.audio.on("timeupdate",t=>{this.emit("timeUpdate",t),this.adPlaying&&this._currentAd&&this.emitAdSkipUpdate(t.currentTime);}),this.audio.on("ended",()=>this.handleTrackEnded()),this.playlist.on("trackChanged",t=>this.emit("trackChange",t)),this.playlist.on("queueUpdated",t=>this.emit("queueUpdated",t)),this.voiceCapture.on("chunk",(t,i)=>{this.transport.sendVoice({action:2,audioData:t,mimeType:this.voiceMimeType,sequence:i,listenerId:this.voiceListenerId,deviceType:this.config.deviceType,gameContext:this.config.gameContext});}),this.voiceCapture.on("error",t=>{this.setVoiceState("error"),this.emit("error",new x(t.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",t=>{this._voiceUserSpeaking=t,this.emit("voiceUserSpeakingChange",t);});}resolveVoiceOptions(t={}){return {...this.config.voice,...t}}connect(){this.transport.connect(this.config.apiKey,this.config.serverUrl);}buildInitExtras(){let t={};return this.config.gameContext?.trim()&&(t.gameContext=this.config.gameContext.trim()),this.config.deviceType?.trim()&&(t.deviceType=this.config.deviceType.trim()),t}async playSong(t){this.transport.isConnected||this.connect(),await this.transport.waitForConnection(),this.activeContentKind=1,this.transport.sendInit({contentKind:1,catalogTrackId:t.catalogTrackId,internalTrackId:t.internalTrackId,listenerId:t.listenerId,...this.buildInitExtras()});}async playPlaylist(t){this.transport.isConnected||this.connect(),await this.transport.waitForConnection(),this.activeContentKind=2,this.transport.sendInit({contentKind:2,playlistCode:t.playlistCode,listenerId:t.listenerId,...this.buildInitExtras()});}async playRadio(t={}){this.transport.isConnected||this.connect(),await this.transport.waitForConnection(),this.activeContentKind=4,this.transport.sendInit({contentKind:4,listenerId:t.listenerId,...this.buildInitExtras()});}async beginVoiceHold(t={}){if(this._voiceState==="listening"||this._voiceState==="processing"||this._voiceState==="responding")return;let i=this.resolveVoiceOptions(t);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.setVoiceState("idle"));}dismissVoiceAndResume(){this.voiceResponseDismissed=true,this.voiceResponsePlayer.stop(),this._voiceState==="listening"&&this.cancelVoiceHold(),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 t=this.playlist.next();t&&this.playSong(t.kind==="internal"?{internalTrackId:t.id}:{catalogTrackId:t.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 t=this.playlist.previous();t&&this.playSong(t.kind==="internal"?{internalTrackId:t.id}:{catalogTrackId:t.id});}skipTo(t){if(this.activeContentKind===4)return;let i=this.playlist.skipTo(t);i&&this.playSong(i.kind==="internal"?{internalTrackId:i.id}:{catalogTrackId:i.id});}seek(t){this.activeContentKind===4||this.adPlaying||(this.audio.seek(t),this.transport.sendControl({action:4,positionMs:t}));}setVolume(t){this.volume=Math.max(0,Math.min(1,t)),this.audio.setVolume(this.volume);}positionMsForAnalytics(t){return typeof t=="number"?Math.max(0,Math.min(4294967295,Math.floor(t))):Math.max(0,Math.min(4294967295,Math.floor(this.audio.currentTime)))}emitAnalytics(t,i,n){this.transport.sendAnalytics({eventType:t,positionMs:this.positionMsForAnalytics(i),extraJson:n?JSON.stringify(n):void 0});}clearHeartbeat(){this.heartbeatTimer!==null&&(clearInterval(this.heartbeatTimer),this.heartbeatTimer=null);}startHeartbeat(t){this.clearHeartbeat();let i=Number(t);!i||i<1e3||(this.heartbeatTimer=setInterval(()=>{let n=this.activeContentKind===4?0:this.positionMsForAnalytics();this.emitAnalytics("heartbeat",n);},i));}applyContentSummary(t){let i=et(t,this.activeContentKind);if(i){this.playlist.setQueue(i.tracks,i.currentIndex);return}t?.trim()&&u("Could not parse contentSummary; queue metadata unavailable.");}emitAdSkipUpdate(t){if(!this._currentAd)return;let i=this._currentAd.skipAfterSeconds*1e3,n=this._currentAd.isSkippable&&t>=i,o=n?0:Math.ceil((i-t)/1e3),r={ad:this._currentAd,canSkip:n,countdownSeconds:o};this.emit("adSkipUpdate",r);}setVoiceState(t){this._voiceState=t,this.emit("voiceStateChange",t);}handleVoiceAck(t){let i=t.status;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:t.transcript,playlistCode:t.playlistCode,playlistName:t.playlistName};this.setVoiceState("ready"),this.emit("voiceResult",n);return}this.emit("voiceResult",{status:i,transcript:t.transcript,playlistCode:t.playlistCode,playlistName:t.playlistName});}async handleServerMessage(t){v("Received server message",t);let i=rt(t);if(i){this.handleVoiceAck(i);return}let n=at(t);if(n){if(this.voiceResponseDismissed)return;this._voiceState==="processing"&&this.setVoiceState("responding"),n.audioData.length>0&&this.voiceResponsePlayer.enqueueChunk(n.audioData,n.mimeType);return}let o=st(t);if(o){await this.handleAdPlayback(o);return}let r=tt(t);if(r){await this.startContentPlayback(r);return}let a=t.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(t){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._voiceState==="ready"||this._voiceState==="processing"||this._voiceState==="responding")&&this.setVoiceState("idle"),this.pausedForVoice=false,this.voiceResponsePlayer.stop(),v("Loading playback",{url:t.playbackUrl,isHls:t.isHls});let i=this.audio.load(t.playbackUrl,t.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(t.heartbeatIntervalMs),this.applyContentSummary(t.contentSummary);}catch(n){if(this.pendingPlaybackLoad!==i)return;this.emit("error",new w(n));}finally{this.pendingPlaybackLoad===i&&(this.pendingPlaybackLoad=null);}}async handleAdPlayback(t){this.pendingPlaybackLoad&&await this.pendingPlaybackLoad.catch(()=>{}),this.audio.stop(),this.adPlaying=true,this._currentAd={adId:t.adId,campaignId:t.campaignId,brandName:t.brandName,creativeName:t.creativeName,durationSeconds:t.durationSeconds,isSkippable:t.isSkippable,skipAfterSeconds:t.skipAfterSeconds,ctaType:t.ctaType,ctaValue:t.ctaValue,companionBannerUrl:t.companionBannerUrl,campaignName:t.campaignName},v("Loading ad playback",{url:t.playbackUrl,isHls:t.isHls});try{await this.audio.load(t.playbackUrl,t.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 t=Math.floor(this.audio.currentTime*1e3);if(t<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",t),this.updateStatus("loading");}clickAd(){if(!this.adPlaying||!this._currentAd)return;let t=Math.floor(this.audio.currentTime*1e3);this.emitAnalytics("ad_cta_click",t),this._currentAd.ctaValue&&window.open(this._currentAd.ctaValue,"_blank");}handleTrackEnded(){if(this.activeContentKind!==4){if(this.adPlaying&&this._currentAd){let t=this._currentAd;this.audio.stop(),this.emitAnalytics("ad_complete",Math.floor(this.audio.currentTime*1e3)),this.emit("adEnd",t),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(t){this.status=t,this.emit("stateChange",{status:t,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 F(s,e){let i=`${s.replace(/\/$/,"")}/radio/now-playing`;try{let n=await fetch(i,{...e,headers:{Accept:"application/json",...e?.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,e){let t=document.createElement(s);if(e?.className&&(t.className=e.className),e?.attrs)for(let[i,n]of Object.entries(e.attrs))t.setAttribute(i,n);return e?.style&&Object.assign(t.style,e.style),e?.text&&(t.textContent=e.text),e?.html&&(t.innerHTML=e.html),e?.onClick&&t.addEventListener("click",e.onClick),e?.children&&e.children.forEach(i=>t.appendChild(i)),t}function g(s,e=20){let t=document.createElementNS("http://www.w3.org/2000/svg","svg");t.setAttribute("width",String(e)),t.setAttribute("height",String(e)),t.setAttribute("viewBox","0 0 24 24"),t.setAttribute("fill","currentColor"),t.setAttribute("aria-hidden","true");let i=document.createElementNS("http://www.w3.org/2000/svg","path");return i.setAttribute("d",s),t.appendChild(i),t}var z="M8 5v14l11-7L8 5z",ot="M6 5h4v14H6V5zm8 0h4v14h-4V5z",k="M6 18l8.5-6L6 6v12zM16 6v12h2V6h-2z",lt="M6 6h2v12H6V6zm11.5 12L9 12l8.5-6v12z";function dt(){let s="synxed-web-player-styles";if(document.getElementById(s))return;let e=document.createElement("style");e.id=s,e.textContent=`
136
136
  @keyframes synxed-wp-spin { from { transform: rotate(0); } to { transform: rotate(360deg); } }
137
137
  @keyframes synxed-wp-vbar {
138
138
  0%, 100% { transform: scaleY(0.28); opacity: 0.45; }
139
139
  50% { transform: scaleY(1); opacity: 1; }
140
140
  }
141
- `,document.head.appendChild(i);}function ct(r){let i=[" \u2014 "," \u2013 "," - "," \u2014"," \u2013"," -"];for(let t of i){let e=r.indexOf(t);if(e>0)return {title:r.slice(0,e).trim(),artist:r.slice(e+t.length).trim()}}return {title:r.trim()}}function pt(r="bottom-center",i=16,t=16){let e={position:"fixed",zIndex:"50"};switch(r){case "top-left":return {...e,top:`${t}px`,left:`${i}px`};case "top-right":return {...e,top:`${t}px`,right:`${i}px`};case "bottom-left":return {...e,bottom:`${t}px`,left:`${i}px`};case "bottom-right":return {...e,bottom:`${t}px`,right:`${i}px`};default:return {...e,bottom:`${t}px`,left:"50%",transform:"translateX(-50%)"}}}function ht(r={}){return {accent:r.accent??"#22c55e",accentMuted:r.accentMuted??r.accent??"#22c55e",background:r.background??"#051107",backgroundInner:r.backgroundInner??"#0a1f10",border:r.border??"rgba(34, 197, 94, 0.35)",text:r.text??"#ffffff",textMuted:r.textMuted??"rgba(255,255,255,0.35)",stationText:r.stationText??"rgba(34, 197, 94, 0.85)",liveDot:r.liveDot??"#CCFF00",glow:r.glow??"rgba(34, 197, 94, 0.35)"}}function ut(r,i){r.style.setProperty("--sw-accent",i.accent),r.style.setProperty("--sw-accent-muted",i.accentMuted),r.style.setProperty("--sw-bg",i.background),r.style.setProperty("--sw-bg-inner",i.backgroundInner),r.style.setProperty("--sw-border",i.border),r.style.setProperty("--sw-text",i.text),r.style.setProperty("--sw-text-muted",i.textMuted),r.style.setProperty("--sw-station",i.stationText),r.style.setProperty("--sw-live",i.liveDot),r.style.setProperty("--sw-glow",i.glow);}var q="https://cdn.synxed.com/avater-image/avatar.svg",xt="https://cdn.synxed.com/avater-image/AI%20Star%20UI%20animation.gif",$=class r{constructor(i){this.engine=null;this.pollTimer=null;this.destroyed=false;this.isPlaying=false;this.currentTrack=null;this.nowPlaying=null;this.currentAd=null;this.skipBtn=null;this.avatarImgEl=null;this.avatarTextEl=null;this.avatarRing=null;this.titleEl=null;this.artistInlineEl=null;this.artistBlockEl=null;this.footerEl=null;this.playBtn=null;this.avatarVoiceHolding=false;this.suppressMiniClick=false;this.voiceAvatarPreview=false;this.voiceHoldActivated=false;this.voiceUiDismissed=false;this.voiceUserSpeaking=false;this.voiceHadSpeech=false;this.voiceHoldTimer=null;this.defaultVoiceHoldMs=450;this.options={mode:"wide",attribution:"Synxed",nowPlayingPollMs:12e3,powerByLabel:"Powered by Synxed",enableVoice:true,...i},this.theme=ht(this.options.theme),this.ownsRoot=!i.container,this.root=i.container??document.createElement("div"),this.ownsRoot&&document.body.appendChild(this.root),dt(),this.mountShell(),this.initEngine(),this.options.source.type==="radio"&&this.startNowPlayingPoll();}static mount(i){return new r(i)}get player(){return this.engine}get element(){return this.root}destroy(){this.destroyed||(this.destroyed=true,this.stopNowPlayingPoll(),this.engine?.destroy(),this.engine=null,this.ownsRoot&&this.root.remove());}get voiceEnabled(){return this.options.enableVoice!==false}get isRadio(){return this.options.source.type==="radio"}get mode(){return this.options.mode??"wide"}mountShell(){let{position:i={},className:t,style:e}=this.options,n=i.placement??"bottom-center",o=i.offsetX??16,s=i.offsetY??(n==="bottom-center"?24:16);this.root.className=t??"",this.root.dataset.synxedWebPlayer=this.mode,ut(this.root,this.theme),Object.assign(this.root.style,pt(n,o,s)),e&&Object.assign(this.root.style,e),this.root.replaceChildren(),this.mode==="mini"?this.buildMini():this.mode==="large"?this.buildLarge():this.buildWide(),this.refreshLabels(),this.setPlayingVisual(this.isPlaying),this.options.draggable&&this.ownsRoot&&this.makeDraggable();}makeDraggable(){let i=false,t=false,e=0,n=0,o=0,s=0,a=u=>{let p=u,y=p.target;if(y.closest("[data-synxed-avatar-ring]")||this.avatarVoiceHolding||this.mode!=="mini"&&y.closest("button, a, input"))return;i=true,t=false;let b=this.root.getBoundingClientRect();o=b.left,s=b.top,this.root.style.bottom="auto",this.root.style.right="auto",this.root.style.transform="none",this.root.style.margin="0",this.root.style.left=`${o}px`,this.root.style.top=`${s}px`,"touches"in p?(e=p.touches[0].clientX,n=p.touches[0].clientY):(e=p.clientX,n=p.clientY),document.addEventListener("mousemove",l,{passive:false}),document.addEventListener("mouseup",c),document.addEventListener("touchmove",l,{passive:false}),document.addEventListener("touchend",c);},l=u=>{if(!i)return;u.preventDefault();let p=u,y,b;"touches"in p?(y=p.touches[0].clientX,b=p.touches[0].clientY):(y=p.clientX,b=p.clientY);let T=y-e,I=b-n;(Math.abs(T)>3||Math.abs(I)>3)&&(t=true),this.root.style.left=`${o+T}px`,this.root.style.top=`${s+I}px`;},c=()=>{i=false,document.removeEventListener("mousemove",l),document.removeEventListener("mouseup",c),document.removeEventListener("touchmove",l),document.removeEventListener("touchend",c),setTimeout(()=>{t=false;},0);};this.root.style.cursor="grab",this.root.addEventListener("mousedown",a),this.root.addEventListener("touchstart",a,{passive:false}),this.root.addEventListener("click",u=>{t&&(u.stopPropagation(),u.preventDefault());},true);}buildAvatar(i,t=false){let e=d("div",{style:{position:"relative",flexShrink:"0"}});this.avatarRing=d("div",{attrs:{"data-synxed-avatar-ring":"true"},style:{width:`${i}px`,height:`${i}px`,borderRadius:"50%",border:"3px solid var(--sw-accent)",padding:"3px",boxShadow:"0 0 24px var(--sw-glow), 0 0 48px rgba(0,0,0,0.25)",background:"var(--sw-bg)",boxSizing:"border-box"}});let n=d("div",{style:{width:"100%",height:"100%",borderRadius:"50%",background:"var(--sw-bg-inner)",overflow:"hidden"}});return this.avatarImgEl=d("img",{attrs:{src:q,alt:"Synxed DJ"},style:{width:"100%",height:"100%",objectFit:"cover",objectPosition:"top",transform:this.mode==="wide"?"scale(1.15)":"scale(1.12)",display:"block"}}),this.avatarTextEl=d("div",{text:"S",style:{width:"100%",height:"100%",display:"none",alignItems:"center",justifyContent:"center",color:"var(--sw-accent)",fontWeight:"900",fontSize:`${Math.round(i*.28)}px`}}),n.appendChild(this.avatarImgEl),n.appendChild(this.avatarTextEl),n.style.cursor=this.voiceEnabled?"pointer":"default",n.addEventListener("click",o=>{if(this.isVoiceUiOpen()){o.stopPropagation(),this.dismissVoiceUi();return}this.currentAd&&this.engine&&(o.stopPropagation(),this.engine.clickAd());}),this.voiceEnabled&&(this.avatarRing.style.touchAction="none",this.avatarRing.setAttribute("aria-label","Hold to speak to DJ")),this.avatarRing.appendChild(n),e.appendChild(this.avatarRing),e.appendChild(d("span",{style:{position:"absolute",...t?{top:"4px",left:"4px"}:{bottom:"6px",left:"6px"},width:t?"10px":"12px",height:t?"10px":"12px",borderRadius:"50%",background:"var(--sw-live)",border:"2px solid var(--sw-bg)",boxShadow:"0 0 8px var(--sw-live)"}})),e}buildMini(){let t=d("div",{attrs:{role:"button",tabindex:"0","aria-label":"Synxed mini player \u2014 tap to play, hold to speak","data-synxed-mini-shell":"true"},style:{position:"relative",padding:"0",cursor:"pointer",background:"transparent"}});t.addEventListener("keydown",e=>{e.key!=="Enter"&&e.key!==" "||(e.preventDefault(),!this.suppressMiniClick&&!this.avatarVoiceHolding&&this.handleMiniActivate());}),t.addEventListener("click",()=>{if(!this.suppressMiniClick){if(this.isVoiceUiOpen()){this.dismissVoiceUi();return}this.avatarVoiceHolding||this.handleMiniActivate();}}),t.appendChild(this.buildAvatar(72)),this.root.appendChild(t);}handleMiniActivate(){if(this.isVoiceUiOpen()){this.dismissVoiceUi();return}this.options.onMiniClick?this.options.onMiniClick():this.togglePlay();}buildWide(){let t="0 8px 40px var(--sw-glow), 0 0 0 1px var(--sw-border)";this.root.style.width="min(calc(100vw - 20px), 560px)";let e=d("div",{style:{position:"relative",display:"flex",alignItems:"center",width:"100%"}}),n=Math.max(90*.42,40);e.appendChild(d("div",{style:{position:"absolute",top:"8px",bottom:"8px",left:`${n}px`,right:"0",background:"var(--sw-bg)",border:"1px solid var(--sw-border)",borderRadius:"28px 20px 20px 28px",boxShadow:t,overflow:"hidden"},children:[d("div",{style:{position:"absolute",inset:"0",background:"linear-gradient(90deg, color-mix(in srgb, var(--sw-accent) 12%, transparent), transparent)",pointerEvents:"none"}})]}));let o=this.buildAvatar(90);Object.assign(o.style,{position:"relative",zIndex:"1",marginLeft:"-2px"}),e.appendChild(o);let s=d("div",{style:{position:"relative",zIndex:"1",flex:"1",minWidth:"0",marginLeft:"14px",padding:"18px 8px"}}),a=d("div",{style:{display:"flex",alignItems:"baseline",gap:"8px",overflow:"hidden"}});this.titleEl=d("h3",{style:{margin:"0",fontSize:"clamp(15px, 2.8vw, 20px)",fontWeight:"900",color:"var(--sw-text)",overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"}}),a.appendChild(this.titleEl),this.artistInlineEl=d("span",{style:{fontSize:"clamp(12px, 2.4vw, 15px)",fontWeight:"300",color:"var(--sw-text-muted)",overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap",display:"none"}}),a.appendChild(this.artistInlineEl),s.appendChild(a),this.footerEl=d("p",{style:{margin:"8px 0 0",fontSize:"9px",fontWeight:"700",color:"var(--sw-text-muted)",letterSpacing:"0.18em",textTransform:"uppercase",overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"}}),s.appendChild(this.footerEl),e.appendChild(s);let l=d("div",{style:{position:"relative",zIndex:"1",flexShrink:"0",display:"flex",alignItems:"center",gap:"14px",paddingRight:"16px"}});this.playBtn=this.createPlayButton(52),l.appendChild(this.playBtn),this.isRadio||(this.skipBtn=d("button",{attrs:{type:"button","aria-label":"Skip"},style:{border:"none",background:"transparent",color:"var(--sw-text-muted)",display:"flex",cursor:"pointer",fontSize:"13px",fontWeight:"bold"},onClick:()=>this.handleSkipClick(),children:[g(k,22)]}),l.appendChild(this.skipBtn)),l.appendChild(this.decoLines()),e.appendChild(l),this.root.appendChild(e);}buildLarge(){this.root.style.width="min(calc(100vw - 24px), 380px)";let t=d("div",{style:{borderRadius:"24px",border:"1px solid var(--sw-border)",background:"var(--sw-bg)",boxShadow:"0 8px 40px var(--sw-glow), 0 0 0 1px var(--sw-border)",padding:"16px",display:"flex",flexDirection:"column",gap:"14px",fontFamily:"system-ui, -apple-system, Segoe UI, Roboto, sans-serif"}}),e=d("div",{style:{display:"flex",gap:"12px",alignItems:"center",minWidth:"0"}});e.appendChild(this.buildAvatar(96,true));let n=d("div",{style:{minWidth:"0",flex:"1"}});this.titleEl=d("h3",{style:{margin:"0",fontSize:"18px",fontWeight:"900",color:"var(--sw-text)",overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"}}),n.appendChild(this.titleEl),this.artistBlockEl=d("p",{style:{margin:"6px 0 0",fontSize:"13px",fontWeight:"700",color:"var(--sw-accent-muted)",letterSpacing:"0.08em",textTransform:"uppercase",overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap",display:"none"}}),n.appendChild(this.artistBlockEl),this.footerEl=d("p",{style:{margin:"6px 0 0",fontSize:"10px",fontWeight:"700",color:"var(--sw-station)",letterSpacing:"0.18em",textTransform:"uppercase",overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"}}),n.appendChild(this.footerEl),e.appendChild(n),t.appendChild(e),t.appendChild(this.buildVisualizer()),t.appendChild(d("p",{text:this.options.powerByLabel??"Powered by Synxed",style:{margin:"0",fontSize:"9px",fontWeight:"600",color:"var(--sw-text-muted)",letterSpacing:"0.12em",textTransform:"uppercase",textAlign:"center"}}));let o=d("div",{style:{display:"flex",alignItems:"center",justifyContent:"center",gap:"18px"}});this.isRadio||o.appendChild(d("button",{attrs:{type:"button","aria-label":"Previous"},style:this.roundControlStyle(),onClick:()=>this.engine?.previous(),children:[g(lt,22)]})),this.playBtn=this.createPlayButton(56),o.appendChild(this.playBtn),this.isRadio||(this.skipBtn=d("button",{attrs:{type:"button","aria-label":"Skip"},style:{...this.roundControlStyle(),fontSize:"12px",fontWeight:"bold"},onClick:()=>this.handleSkipClick(),children:[g(k,22)]}),o.appendChild(this.skipBtn)),t.appendChild(o),this.root.appendChild(t);}roundControlStyle(){return {width:"46px",height:"46px",borderRadius:"50%",border:"1px solid var(--sw-border)",background:"rgba(255,255,255,0.04)",color:"var(--sw-text)",display:"flex",alignItems:"center",justifyContent:"center",cursor:"pointer"}}createPlayButton(i){return d("button",{attrs:{type:"button","aria-label":"Play"},style:{width:`${i}px`,height:`${i}px`,borderRadius:"50%",border:"none",background:"var(--sw-accent)",color:"#0a0a0a",display:"flex",alignItems:"center",justifyContent:"center",cursor:"pointer",boxShadow:"0 0 18px var(--sw-glow)",flexShrink:"0"},onClick:()=>this.togglePlay(),children:[g(z,i>=56?22:20)]})}buildVisualizer(){let i=d("div",{style:{display:"flex",alignItems:"flex-end",gap:"4px",height:"52px",padding:"8px 4px",borderRadius:"14px",border:"1px solid var(--sw-border)",overflow:"hidden"}});for(let t=0;t<24;t++)i.appendChild(d("span",{style:{flex:"1",minWidth:"3px",height:"100%",borderRadius:"4px",background:"linear-gradient(180deg, var(--sw-accent), transparent)",transformOrigin:"center bottom",animation:`synxed-wp-vbar ${1+t%5*.12}s ease-in-out infinite`,animationDelay:`${t*.04}s`,opacity:"0.85"}}));return i}decoLines(){let i=d("div",{style:{display:"flex",flexDirection:"column",gap:"3px",opacity:"0.22"}});return i.appendChild(d("span",{style:{display:"block",width:"16px",height:"2px",borderRadius:"999px",background:"var(--sw-text)",transform:"translateX(3px)"}})),i.appendChild(d("span",{style:{display:"block",width:"16px",height:"2px",borderRadius:"999px",background:"var(--sw-text)"}})),i}initEngine(){let{apiKey:i,serverUrl:t,source:e}=this.options,n=new L({apiKey:i,serverUrl:t,autoConnect:true,debug:this.options.debug,voice:this.options.voice});this.engine=n;let o=a=>{this.isPlaying=a.status==="playing",a.currentTrack&&(this.currentTrack=a.currentTrack),this.setPlayingVisual(this.isPlaying),this.refreshLabels(),!this.currentAd&&!this.engine?.isAdPlaying&&(this.restoreTrackSkipButton(),this.refreshAvatarImage());};n.on("stateChange",o),n.on("trackChange",a=>{this.currentTrack=a,this.avatarImageBeforeAd=void 0,this.refreshLabels(),!this.currentAd&&!this.engine?.isAdPlaying&&(this.restoreTrackSkipButton(),this.refreshAvatarImage());}),n.on("adStart",a=>{this.avatarImageBeforeAd=this.getContentAvatarUrl(),this.voiceAvatarPreview=false,this.voiceHoldActivated=false,this.currentAd=a,this.refreshLabels(),this.updateAvatar();}),n.on("adSkipUpdate",a=>this.applyAdSkipUi(a)),n.on("adEnd",()=>{this.currentAd=null,this.voiceAvatarPreview=false,this.refreshLabels(),this.updateAvatar(),this.restoreTrackSkipButton();}),n.on("voiceStateChange",a=>this.applyVoiceVisual(a)),n.on("voiceUserSpeakingChange",a=>{this.voiceUserSpeaking=a,a&&(this.voiceHadSpeech=true),this.applyVoiceRing();}),(e.type==="radio"?()=>n.playRadio():()=>n.playPlaylist({playlistCode:e.playlistCode}))().catch(()=>{}),this.voiceEnabled&&this.wireAvatarVoiceHold();}wireAvatarVoiceHold(){if(!this.avatarRing)return;let i=this.avatarRing,t=this.options.voiceHoldMs??this.defaultVoiceHoldMs,e=()=>{this.voiceHoldTimer!==null&&(clearTimeout(this.voiceHoldTimer),this.voiceHoldTimer=null);},n=a=>{if(!(this.currentAd||!this.engine)){if(this.isVoiceUiOpen()){a.preventDefault(),a.stopPropagation(),this.dismissVoiceUi();return}a.preventDefault(),a.stopPropagation(),i.setPointerCapture(a.pointerId),this.avatarVoiceHolding=true,this.voiceHoldActivated=false,e(),this.voiceHoldTimer=setTimeout(()=>{this.voiceHoldTimer=null,!(!this.avatarVoiceHolding||!this.engine)&&(this.voiceHoldActivated=true,this.voiceUiDismissed=false,this.voiceAvatarPreview=true,this.voiceUserSpeaking=false,this.voiceHadSpeech=false,this.applyVoiceRing(),this.refreshAvatarImage(),this.engine.beginVoiceHold({listenerId:this.options.listenerId}).catch(()=>{this.resetVoiceHoldState();}));},t);}},o=a=>{this.currentAd||a.stopPropagation();};i.addEventListener("mousedown",o),i.addEventListener("touchstart",o,{passive:false});let s=()=>{if(e(),!this.avatarVoiceHolding||(this.avatarVoiceHolding=false,!this.voiceHoldActivated))return;this.mode==="mini"&&(this.suppressMiniClick=true,setTimeout(()=>{this.suppressMiniClick=false;},320)),this.engine?.voiceState==="listening"&&this.engine?.endVoiceHold();};i.addEventListener("pointerdown",n),i.addEventListener("pointerup",s),i.addEventListener("pointerleave",s),i.addEventListener("pointercancel",s);}isVoiceUiOpen(){return !this.voiceEnabled||this.currentAd||this.voiceUiDismissed?false:this.voiceHoldActivated||this.voiceAvatarPreview?true:!!this.engine?.isVoiceUiActive}dismissVoiceUi(){this.engine?.dismissVoiceAndResume(),this.resetVoiceHoldState(),this.voiceUiDismissed=true,this.applyVoiceVisual(this.engine?.voiceState??"idle"),this.refreshAvatarImage();}resetVoiceHoldState(){this.voiceHoldTimer!==null&&(clearTimeout(this.voiceHoldTimer),this.voiceHoldTimer=null),this.avatarVoiceHolding=false,this.voiceHoldActivated=false,this.voiceAvatarPreview=false,this.voiceUserSpeaking=false,this.voiceHadSpeech=false;}applyVoiceRing(){if(!this.avatarRing)return;let i=this.engine?.voiceState??"idle";if(i==="processing"){this.avatarRing.style.animation="",this.avatarRing.style.borderColor="#ef4444",this.avatarRing.style.boxShadow="0 0 20px rgba(239,68,68,0.5), 0 0 40px rgba(239,68,68,0.2)";return}if(i==="responding"){this.avatarRing.style.animation="",this.avatarRing.style.borderColor="#06b6d4",this.avatarRing.style.boxShadow="0 0 20px rgba(6,182,212,0.5), 0 0 40px rgba(6,182,212,0.2)";return}if(i==="listening"){this.voiceHadSpeech&&!this.voiceUserSpeaking?(this.avatarRing.style.animation="",this.avatarRing.style.borderColor="#ef4444",this.avatarRing.style.boxShadow="0 0 20px rgba(239,68,68,0.5), 0 0 40px rgba(239,68,68,0.2)"):(this.avatarRing.style.animation="",this.avatarRing.style.borderColor="#3b82f6",this.avatarRing.style.boxShadow="0 0 20px rgba(59,130,246,0.55), 0 0 40px rgba(59,130,246,0.25)");return}this.avatarRing.style.borderColor="",this.avatarRing.style.boxShadow="0 0 24px var(--sw-glow), 0 0 48px rgba(0,0,0,0.25)",this.setPlayingVisual(this.isPlaying);}applyVoiceVisual(i){this.avatarRing&&((i==="idle"||i==="ready"||i==="error")&&(this.avatarVoiceHolding||(this.voiceAvatarPreview=false),(i==="ready"||i==="idle")&&(this.voiceUiDismissed=false,this.voiceUserSpeaking=false,this.voiceHadSpeech=false)),(i==="listening"||i==="processing"||i==="responding")&&(this.voiceUiDismissed=false),this.applyVoiceRing(),this.refreshAvatarImage());}isVoiceAvatarActive(){if(!this.voiceEnabled||this.currentAd||this.voiceUiDismissed)return false;if(this.voiceAvatarPreview)return true;let i=this.engine?.voiceState;return i==="listening"||i==="processing"||i==="responding"}getContentAvatarUrl(){return q}getAvatarImageUrl(){return this.currentAd?.companionBannerUrl?this.currentAd.companionBannerUrl:this.isVoiceAvatarActive()?xt:this.avatarImageBeforeAd?this.avatarImageBeforeAd:q}refreshAvatarImage(){let i=this.getAvatarImageUrl(),t=this.isVoiceAvatarActive();i&&this.avatarImgEl?(this.avatarImgEl.getAttribute("src")!==i&&this.avatarImgEl.setAttribute("src",i),this.avatarImgEl.style.display="block",t?(this.avatarImgEl.style.objectFit="cover",this.avatarImgEl.style.objectPosition="center",this.avatarImgEl.style.transform="scale(1)",this.avatarImgEl.style.padding="",this.avatarImgEl.style.background="var(--sw-bg-inner)"):(this.avatarImgEl.style.objectFit="cover",this.avatarImgEl.style.objectPosition="top",this.avatarImgEl.style.transform=this.mode==="wide"?"scale(1.15)":"scale(1.12)",this.avatarImgEl.style.padding="",this.avatarImgEl.style.background=""),this.avatarTextEl&&(this.avatarTextEl.style.display="none")):(this.avatarImgEl&&(this.avatarImgEl.style.display="none"),this.avatarTextEl&&(this.avatarTextEl.style.display="flex"));}startNowPlayingPoll(){let i=async()=>{let t=await F(this.options.serverUrl);!this.destroyed&&t&&(this.nowPlaying=t,this.refreshLabels());};i(),this.pollTimer=setInterval(i,this.options.nowPlayingPollMs??12e3);}stopNowPlayingPoll(){this.pollTimer!==null&&(clearInterval(this.pollTimer),this.pollTimer=null);}handleSkipClick(){let i=this.engine;if(i){if(this.currentAd){i.canSkipAd()&&i.skipAd();return}i.skip();}}applyAdSkipUi(i){if(!this.skipBtn)return;let{ad:t,canSkip:e,countdownSeconds:n}=i;if(!t.isSkippable){this.skipBtn.disabled=true,this.skipBtn.textContent="",this.skipBtn.replaceChildren(g(k,22));return}if(!e){this.skipBtn.disabled=true,this.skipBtn.replaceChildren(),this.skipBtn.textContent=`${n}s`;return}this.skipBtn.disabled=false,this.skipBtn.textContent="",this.skipBtn.replaceChildren(g(k,22));}restoreTrackSkipButton(){this.skipBtn&&(this.skipBtn.disabled=false,this.skipBtn.textContent="",this.skipBtn.replaceChildren(g(k,22)),this.skipBtn.setAttribute("aria-label","Skip"));}displayLine(){return this.currentAd?{title:this.currentAd.campaignName||"Advertisement",artist:this.currentAd.creativeName}:this.isRadio&&this.nowPlaying?.title?ct(this.nowPlaying.title):this.currentTrack?.title?{title:this.currentTrack.title,artist:this.currentTrack.artist}:{title:"Loading\u2026"}}refreshLabels(){let i=this.displayLine();if(this.titleEl&&(this.titleEl.textContent=i.title),this.artistInlineEl){let t=!!i.artist;this.artistInlineEl.style.display=t?"inline":"none",t&&(this.artistInlineEl.textContent=i.artist);}if(this.artistBlockEl){let t=!!i.artist;this.artistBlockEl.style.display=t?"block":"none",t&&(this.artistBlockEl.textContent=i.artist);}if(this.footerEl)if(this.currentAd)this.footerEl.textContent="Advertisement \xB7 Synxed Player";else {let t=this.isRadio&&(this.nowPlaying?.station??this.currentTrack?.title??"Synxed Radio");this.footerEl.textContent=t&&this.isRadio?`${t} \xB7 Synxed Player`:"Synxed Player";}}updateAvatar(){if(this.refreshAvatarImage(),this.avatarRing){let i=this.avatarRing.firstChild;i&&(i.style.cursor=this.currentAd||this.voiceEnabled?"pointer":"default");}}setPlayingVisual(i){this.avatarRing&&(this.avatarRing.style.animation=i?"synxed-wp-spin 4s linear infinite":""),this.playBtn&&(this.playBtn.replaceChildren(g(i?ot:z,20)),this.playBtn.setAttribute("aria-label",i?"Pause":"Play"));}togglePlay(){this.engine&&(this.isPlaying?this.engine.pause():this.engine.resume());}};
142
- exports.ContentKind=R;exports.ErrorCode=G;exports.SdkVoiceAction=B;exports.SynxedConnectionError=O;exports.SynxedError=x;exports.SynxedPlaybackError=w;exports.SynxedPlayer=L;exports.SynxedProtocolError=Z;exports.SynxedWebPlayer=$;exports.TransportManager=E;exports.VoiceCaptureManager=P;exports.buildSdkWebSocketUrl=Q;exports.fetchRadioNowPlaying=F;//# sourceMappingURL=index.js.map
141
+ `,document.head.appendChild(e);}function ct(s){let e=[" \u2014 "," \u2013 "," - "," \u2014"," \u2013"," -"];for(let t of e){let i=s.indexOf(t);if(i>0)return {title:s.slice(0,i).trim(),artist:s.slice(i+t.length).trim()}}return {title:s.trim()}}function pt(s="bottom-center",e=16,t=16){let i={position:"fixed",zIndex:"50"};switch(s){case "top-left":return {...i,top:`${t}px`,left:`${e}px`};case "top-right":return {...i,top:`${t}px`,right:`${e}px`};case "bottom-left":return {...i,bottom:`${t}px`,left:`${e}px`};case "bottom-right":return {...i,bottom:`${t}px`,right:`${e}px`};default:return {...i,bottom:`${t}px`,left:"50%",transform:"translateX(-50%)"}}}function ht(s={}){return {accent:s.accent??"#22c55e",accentMuted:s.accentMuted??s.accent??"#22c55e",background:s.background??"#051107",backgroundInner:s.backgroundInner??"#0a1f10",border:s.border??"rgba(34, 197, 94, 0.35)",text:s.text??"#ffffff",textMuted:s.textMuted??"rgba(255,255,255,0.35)",stationText:s.stationText??"rgba(34, 197, 94, 0.85)",liveDot:s.liveDot??"#CCFF00",glow:s.glow??"rgba(34, 197, 94, 0.35)"}}function ut(s,e){s.style.setProperty("--sw-accent",e.accent),s.style.setProperty("--sw-accent-muted",e.accentMuted),s.style.setProperty("--sw-bg",e.background),s.style.setProperty("--sw-bg-inner",e.backgroundInner),s.style.setProperty("--sw-border",e.border),s.style.setProperty("--sw-text",e.text),s.style.setProperty("--sw-text-muted",e.textMuted),s.style.setProperty("--sw-station",e.stationText),s.style.setProperty("--sw-live",e.liveDot),s.style.setProperty("--sw-glow",e.glow);}var q="https://cdn.synxed.com/avater-image/avatar.svg",kt="https://cdn.synxed.com/avater-image/AI%20Star%20UI%20animation.gif",j=class s{constructor(e){this.engine=null;this.pollTimer=null;this.destroyed=false;this.isPlaying=false;this.currentTrack=null;this.nowPlaying=null;this.currentAd=null;this.skipBtn=null;this.avatarImgEl=null;this.avatarTextEl=null;this.avatarRing=null;this.titleEl=null;this.artistInlineEl=null;this.artistBlockEl=null;this.footerEl=null;this.playBtn=null;this.avatarVoiceHolding=false;this.suppressMiniClick=false;this.voiceAvatarPreview=false;this.voiceHoldActivated=false;this.voiceUiDismissed=false;this.voiceUserSpeaking=false;this.voiceHadSpeech=false;this.voiceHoldTimer=null;this.defaultVoiceHoldMs=450;this.options={mode:"wide",attribution:"Synxed",nowPlayingPollMs:12e3,powerByLabel:"Powered by Synxed",enableVoice:true,...e},this.theme=ht(this.options.theme),this.ownsRoot=!e.container,this.root=e.container??document.createElement("div"),this.ownsRoot&&document.body.appendChild(this.root),dt(),this.mountShell(),this.initEngine(),this.options.source.type==="radio"&&this.startNowPlayingPoll();}static mount(e){return new s(e)}get player(){return this.engine}get element(){return this.root}destroy(){this.destroyed||(this.destroyed=true,this.stopNowPlayingPoll(),this.engine?.destroy(),this.engine=null,this.ownsRoot&&this.root.remove());}get voiceEnabled(){return this.options.enableVoice!==false}get isRadio(){return this.options.source.type==="radio"}get mode(){return this.options.mode??"wide"}mountShell(){let{position:e={},className:t,style:i}=this.options,n=e.placement??"bottom-center",o=e.offsetX??16,r=e.offsetY??(n==="bottom-center"?24:16);this.root.className=t??"",this.root.dataset.synxedWebPlayer=this.mode,ut(this.root,this.theme),Object.assign(this.root.style,pt(n,o,r)),i&&Object.assign(this.root.style,i),this.root.replaceChildren(),this.mode==="mini"?this.buildMini():this.mode==="large"?this.buildLarge():this.buildWide(),this.refreshLabels(),this.setPlayingVisual(this.isPlaying),this.options.draggable&&this.ownsRoot&&this.makeDraggable();}makeDraggable(){let e=false,t=false,i=0,n=0,o=0,r=0,a=h=>{let p=h,y=p.target;if(y.closest("[data-synxed-avatar-ring]")||this.avatarVoiceHolding||this.mode!=="mini"&&y.closest("button, a, input"))return;e=true,t=false;let b=this.root.getBoundingClientRect();o=b.left,r=b.top,this.root.style.bottom="auto",this.root.style.right="auto",this.root.style.transform="none",this.root.style.margin="0",this.root.style.left=`${o}px`,this.root.style.top=`${r}px`,"touches"in p?(i=p.touches[0].clientX,n=p.touches[0].clientY):(i=p.clientX,n=p.clientY),document.addEventListener("mousemove",l,{passive:false}),document.addEventListener("mouseup",c),document.addEventListener("touchmove",l,{passive:false}),document.addEventListener("touchend",c);},l=h=>{if(!e)return;h.preventDefault();let p=h,y,b;"touches"in p?(y=p.touches[0].clientX,b=p.touches[0].clientY):(y=p.clientX,b=p.clientY);let T=y-i,I=b-n;(Math.abs(T)>3||Math.abs(I)>3)&&(t=true),this.root.style.left=`${o+T}px`,this.root.style.top=`${r+I}px`;},c=()=>{e=false,document.removeEventListener("mousemove",l),document.removeEventListener("mouseup",c),document.removeEventListener("touchmove",l),document.removeEventListener("touchend",c),setTimeout(()=>{t=false;},0);};this.root.style.cursor="grab",this.root.addEventListener("mousedown",a),this.root.addEventListener("touchstart",a,{passive:false}),this.root.addEventListener("click",h=>{t&&(h.stopPropagation(),h.preventDefault());},true);}buildAvatar(e,t=false){let i=d("div",{style:{position:"relative",flexShrink:"0"}});this.avatarRing=d("div",{attrs:{"data-synxed-avatar-ring":"true"},style:{width:`${e}px`,height:`${e}px`,borderRadius:"50%",border:"3px solid var(--sw-accent)",padding:"3px",boxShadow:"0 0 24px var(--sw-glow), 0 0 48px rgba(0,0,0,0.25)",background:"var(--sw-bg)",boxSizing:"border-box",userSelect:"none",webkitUserSelect:"none"}}),this.avatarRing.style.setProperty("-webkit-touch-callout","none");let n=d("div",{style:{width:"100%",height:"100%",borderRadius:"50%",background:"var(--sw-bg-inner)",overflow:"hidden",userSelect:"none",webkitUserSelect:"none"}});return n.style.setProperty("-webkit-touch-callout","none"),this.avatarImgEl=d("img",{attrs:{src:q,alt:"Synxed DJ",draggable:"false"},style:{width:"100%",height:"100%",objectFit:"cover",objectPosition:"top",transform:this.mode==="wide"?"scale(1.15)":"scale(1.12)",display:"block",pointerEvents:"none",userSelect:"none",webkitUserSelect:"none"}}),this.avatarImgEl.style.setProperty("-webkit-touch-callout","none"),this.avatarTextEl=d("div",{text:"S",style:{width:"100%",height:"100%",display:"none",alignItems:"center",justifyContent:"center",color:"var(--sw-accent)",fontWeight:"900",fontSize:`${Math.round(e*.28)}px`}}),n.appendChild(this.avatarImgEl),n.appendChild(this.avatarTextEl),n.style.cursor=this.voiceEnabled?"pointer":"default",n.addEventListener("click",o=>{if(this.isVoiceUiOpen()){o.stopPropagation(),this.dismissVoiceUi();return}this.currentAd&&this.engine&&(o.stopPropagation(),this.engine.clickAd());}),n.addEventListener("contextmenu",o=>o.preventDefault()),n.addEventListener("dragstart",o=>o.preventDefault()),n.addEventListener("selectstart",o=>o.preventDefault()),this.voiceEnabled&&(this.avatarRing.style.touchAction="none",this.avatarRing.addEventListener("contextmenu",o=>o.preventDefault()),this.avatarRing.addEventListener("dragstart",o=>o.preventDefault()),this.avatarRing.addEventListener("selectstart",o=>o.preventDefault()),this.avatarRing.setAttribute("aria-label","Hold to speak to DJ")),this.avatarRing.appendChild(n),i.appendChild(this.avatarRing),i.appendChild(d("span",{style:{position:"absolute",...t?{top:"4px",left:"4px"}:{bottom:"6px",left:"6px"},width:t?"10px":"12px",height:t?"10px":"12px",borderRadius:"50%",background:"var(--sw-live)",border:"2px solid var(--sw-bg)",boxShadow:"0 0 8px var(--sw-live)"}})),i}buildMini(){let t=d("div",{attrs:{role:"button",tabindex:"0","aria-label":"Synxed mini player \u2014 tap to play, hold to speak","data-synxed-mini-shell":"true"},style:{position:"relative",padding:"0",cursor:"pointer",background:"transparent"}});t.addEventListener("keydown",i=>{i.key!=="Enter"&&i.key!==" "||(i.preventDefault(),!this.suppressMiniClick&&!this.avatarVoiceHolding&&this.handleMiniActivate());}),t.addEventListener("click",()=>{if(!this.suppressMiniClick){if(this.isVoiceUiOpen()){this.dismissVoiceUi();return}this.avatarVoiceHolding||this.handleMiniActivate();}}),t.appendChild(this.buildAvatar(72)),this.root.appendChild(t);}handleMiniActivate(){if(this.isVoiceUiOpen()){this.dismissVoiceUi();return}this.options.onMiniClick?this.options.onMiniClick():this.togglePlay();}buildWide(){let t="0 8px 40px var(--sw-glow), 0 0 0 1px var(--sw-border)";this.root.style.width="min(calc(100vw - 20px), 560px)";let i=d("div",{style:{position:"relative",display:"flex",alignItems:"center",width:"100%"}}),n=Math.max(90*.42,40);i.appendChild(d("div",{style:{position:"absolute",top:"8px",bottom:"8px",left:`${n}px`,right:"0",background:"var(--sw-bg)",border:"1px solid var(--sw-border)",borderRadius:"28px 20px 20px 28px",boxShadow:t,overflow:"hidden"},children:[d("div",{style:{position:"absolute",inset:"0",background:"linear-gradient(90deg, color-mix(in srgb, var(--sw-accent) 12%, transparent), transparent)",pointerEvents:"none"}})]}));let o=this.buildAvatar(90);Object.assign(o.style,{position:"relative",zIndex:"1",marginLeft:"-2px"}),i.appendChild(o);let r=d("div",{style:{position:"relative",zIndex:"1",flex:"1",minWidth:"0",marginLeft:"14px",padding:"18px 8px"}}),a=d("div",{style:{display:"flex",alignItems:"baseline",gap:"8px",overflow:"hidden"}});this.titleEl=d("h3",{style:{margin:"0",fontSize:"clamp(15px, 2.8vw, 20px)",fontWeight:"900",color:"var(--sw-text)",overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"}}),a.appendChild(this.titleEl),this.artistInlineEl=d("span",{style:{fontSize:"clamp(12px, 2.4vw, 15px)",fontWeight:"300",color:"var(--sw-text-muted)",overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap",display:"none"}}),a.appendChild(this.artistInlineEl),r.appendChild(a),this.footerEl=d("p",{style:{margin:"8px 0 0",fontSize:"9px",fontWeight:"700",color:"var(--sw-text-muted)",letterSpacing:"0.18em",textTransform:"uppercase",overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"}}),r.appendChild(this.footerEl),i.appendChild(r);let l=d("div",{style:{position:"relative",zIndex:"1",flexShrink:"0",display:"flex",alignItems:"center",gap:"14px",paddingRight:"16px"}});this.playBtn=this.createPlayButton(52),l.appendChild(this.playBtn),this.isRadio||(this.skipBtn=d("button",{attrs:{type:"button","aria-label":"Skip"},style:{border:"none",background:"transparent",color:"var(--sw-text-muted)",display:"flex",cursor:"pointer",fontSize:"13px",fontWeight:"bold"},onClick:()=>this.handleSkipClick(),children:[g(k,22)]}),l.appendChild(this.skipBtn)),l.appendChild(this.decoLines()),i.appendChild(l),this.root.appendChild(i);}buildLarge(){this.root.style.width="min(calc(100vw - 24px), 380px)";let t=d("div",{style:{borderRadius:"24px",border:"1px solid var(--sw-border)",background:"var(--sw-bg)",boxShadow:"0 8px 40px var(--sw-glow), 0 0 0 1px var(--sw-border)",padding:"16px",display:"flex",flexDirection:"column",gap:"14px",fontFamily:"system-ui, -apple-system, Segoe UI, Roboto, sans-serif"}}),i=d("div",{style:{display:"flex",gap:"12px",alignItems:"center",minWidth:"0"}});i.appendChild(this.buildAvatar(96,true));let n=d("div",{style:{minWidth:"0",flex:"1"}});this.titleEl=d("h3",{style:{margin:"0",fontSize:"18px",fontWeight:"900",color:"var(--sw-text)",overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"}}),n.appendChild(this.titleEl),this.artistBlockEl=d("p",{style:{margin:"6px 0 0",fontSize:"13px",fontWeight:"700",color:"var(--sw-accent-muted)",letterSpacing:"0.08em",textTransform:"uppercase",overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap",display:"none"}}),n.appendChild(this.artistBlockEl),this.footerEl=d("p",{style:{margin:"6px 0 0",fontSize:"10px",fontWeight:"700",color:"var(--sw-station)",letterSpacing:"0.18em",textTransform:"uppercase",overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"}}),n.appendChild(this.footerEl),i.appendChild(n),t.appendChild(i),t.appendChild(this.buildVisualizer()),t.appendChild(d("p",{text:this.options.powerByLabel??"Powered by Synxed",style:{margin:"0",fontSize:"9px",fontWeight:"600",color:"var(--sw-text-muted)",letterSpacing:"0.12em",textTransform:"uppercase",textAlign:"center"}}));let o=d("div",{style:{display:"flex",alignItems:"center",justifyContent:"center",gap:"18px"}});this.isRadio||o.appendChild(d("button",{attrs:{type:"button","aria-label":"Previous"},style:this.roundControlStyle(),onClick:()=>this.engine?.previous(),children:[g(lt,22)]})),this.playBtn=this.createPlayButton(56),o.appendChild(this.playBtn),this.isRadio||(this.skipBtn=d("button",{attrs:{type:"button","aria-label":"Skip"},style:{...this.roundControlStyle(),fontSize:"12px",fontWeight:"bold"},onClick:()=>this.handleSkipClick(),children:[g(k,22)]}),o.appendChild(this.skipBtn)),t.appendChild(o),this.root.appendChild(t);}roundControlStyle(){return {width:"46px",height:"46px",borderRadius:"50%",border:"1px solid var(--sw-border)",background:"rgba(255,255,255,0.04)",color:"var(--sw-text)",display:"flex",alignItems:"center",justifyContent:"center",cursor:"pointer"}}createPlayButton(e){return d("button",{attrs:{type:"button","aria-label":"Play"},style:{width:`${e}px`,height:`${e}px`,borderRadius:"50%",border:"none",background:"var(--sw-accent)",color:"#0a0a0a",display:"flex",alignItems:"center",justifyContent:"center",cursor:"pointer",boxShadow:"0 0 18px var(--sw-glow)",flexShrink:"0"},onClick:()=>this.togglePlay(),children:[g(z,e>=56?22:20)]})}buildVisualizer(){let e=d("div",{style:{display:"flex",alignItems:"flex-end",gap:"4px",height:"52px",padding:"8px 4px",borderRadius:"14px",border:"1px solid var(--sw-border)",overflow:"hidden"}});for(let t=0;t<24;t++)e.appendChild(d("span",{style:{flex:"1",minWidth:"3px",height:"100%",borderRadius:"4px",background:"linear-gradient(180deg, var(--sw-accent), transparent)",transformOrigin:"center bottom",animation:`synxed-wp-vbar ${1+t%5*.12}s ease-in-out infinite`,animationDelay:`${t*.04}s`,opacity:"0.85"}}));return e}decoLines(){let e=d("div",{style:{display:"flex",flexDirection:"column",gap:"3px",opacity:"0.22"}});return e.appendChild(d("span",{style:{display:"block",width:"16px",height:"2px",borderRadius:"999px",background:"var(--sw-text)",transform:"translateX(3px)"}})),e.appendChild(d("span",{style:{display:"block",width:"16px",height:"2px",borderRadius:"999px",background:"var(--sw-text)"}})),e}initEngine(){let{apiKey:e,serverUrl:t,source:i}=this.options,n=new L({apiKey:e,serverUrl:t,autoConnect:true,debug:this.options.debug,voice:this.options.voice});this.engine=n;let o=a=>{this.isPlaying=a.status==="playing",a.currentTrack&&(this.currentTrack=a.currentTrack),this.setPlayingVisual(this.isPlaying),this.refreshLabels(),!this.currentAd&&!this.engine?.isAdPlaying&&(this.restoreTrackSkipButton(),this.refreshAvatarImage());};n.on("stateChange",o),n.on("trackChange",a=>{this.currentTrack=a,this.avatarImageBeforeAd=void 0,this.refreshLabels(),!this.currentAd&&!this.engine?.isAdPlaying&&(this.restoreTrackSkipButton(),this.refreshAvatarImage());}),n.on("adStart",a=>{this.avatarImageBeforeAd=this.getContentAvatarUrl(),this.voiceAvatarPreview=false,this.voiceHoldActivated=false,this.currentAd=a,this.refreshLabels(),this.updateAvatar();}),n.on("adSkipUpdate",a=>this.applyAdSkipUi(a)),n.on("adEnd",()=>{this.currentAd=null,this.voiceAvatarPreview=false,this.refreshLabels(),this.updateAvatar(),this.restoreTrackSkipButton();}),n.on("voiceStateChange",a=>this.applyVoiceVisual(a)),n.on("voiceUserSpeakingChange",a=>{this.voiceUserSpeaking=a,a&&(this.voiceHadSpeech=true),this.applyVoiceRing();}),(i.type==="radio"?()=>n.playRadio():()=>n.playPlaylist({playlistCode:i.playlistCode}))().catch(()=>{}),this.voiceEnabled&&this.wireAvatarVoiceHold();}wireAvatarVoiceHold(){if(!this.avatarRing)return;let e=this.avatarRing,t=this.options.voiceHoldMs??this.defaultVoiceHoldMs,i=()=>{this.voiceHoldTimer!==null&&(clearTimeout(this.voiceHoldTimer),this.voiceHoldTimer=null);},n=a=>{if(!(this.currentAd||!this.engine)){if(this.isVoiceUiOpen()){a.preventDefault(),a.stopPropagation(),this.dismissVoiceUi();return}a.preventDefault(),a.stopPropagation(),e.setPointerCapture(a.pointerId),this.avatarVoiceHolding=true,this.voiceHoldActivated=false,i(),this.voiceHoldTimer=setTimeout(()=>{this.voiceHoldTimer=null,!(!this.avatarVoiceHolding||!this.engine)&&(this.voiceHoldActivated=true,this.voiceUiDismissed=false,this.voiceAvatarPreview=true,this.voiceUserSpeaking=false,this.voiceHadSpeech=false,this.applyVoiceRing(),this.refreshAvatarImage(),this.engine.beginVoiceHold({listenerId:this.options.listenerId}).catch(()=>{this.resetVoiceHoldState();}));},t);}},o=a=>{this.currentAd||a.stopPropagation();};e.addEventListener("mousedown",o),e.addEventListener("touchstart",o,{passive:false});let r=()=>{i(),this.avatarVoiceHolding&&(this.avatarVoiceHolding=false,this.voiceHoldActivated&&(this.mode==="mini"&&(this.suppressMiniClick=true,setTimeout(()=>{this.suppressMiniClick=false;},320)),!this.voiceHadSpeech&&this.engine?.voiceState==="listening"&&(this.engine.cancelVoiceHold(),this.resetVoiceHoldState(),this.refreshAvatarImage())));};e.addEventListener("pointerdown",n),e.addEventListener("pointerup",r),e.addEventListener("pointerleave",r),e.addEventListener("pointercancel",r);}isVoiceUiOpen(){return !this.voiceEnabled||this.currentAd||this.voiceUiDismissed?false:this.voiceHoldActivated||this.voiceAvatarPreview?true:!!this.engine?.isVoiceUiActive}dismissVoiceUi(){this.engine?.dismissVoiceAndResume(),this.resetVoiceHoldState(),this.voiceUiDismissed=true,this.applyVoiceRing(),this.refreshAvatarImage();}resetVoiceHoldState(){this.voiceHoldTimer!==null&&(clearTimeout(this.voiceHoldTimer),this.voiceHoldTimer=null),this.avatarVoiceHolding=false,this.voiceHoldActivated=false,this.voiceAvatarPreview=false,this.voiceUserSpeaking=false,this.voiceHadSpeech=false;}applyVoiceRing(){if(!this.avatarRing)return;if(this.voiceUiDismissed){this.avatarRing.style.borderColor="",this.avatarRing.style.boxShadow="0 0 24px var(--sw-glow), 0 0 48px rgba(0,0,0,0.25)",this.setPlayingVisual(this.isPlaying);return}let e=this.engine?.voiceState??"idle";if(e==="processing"){this.avatarRing.style.animation="",this.avatarRing.style.borderColor="#ef4444",this.avatarRing.style.boxShadow="0 0 20px rgba(239,68,68,0.5), 0 0 40px rgba(239,68,68,0.2)";return}if(e==="responding"){this.avatarRing.style.animation="",this.avatarRing.style.borderColor="#06b6d4",this.avatarRing.style.boxShadow="0 0 20px rgba(6,182,212,0.5), 0 0 40px rgba(6,182,212,0.2)";return}if(e==="listening"){this.voiceHadSpeech&&!this.voiceUserSpeaking?(this.avatarRing.style.animation="",this.avatarRing.style.borderColor="#ef4444",this.avatarRing.style.boxShadow="0 0 20px rgba(239,68,68,0.5), 0 0 40px rgba(239,68,68,0.2)"):(this.avatarRing.style.animation="",this.avatarRing.style.borderColor="#3b82f6",this.avatarRing.style.boxShadow="0 0 20px rgba(59,130,246,0.55), 0 0 40px rgba(59,130,246,0.25)");return}this.avatarRing.style.borderColor="",this.avatarRing.style.boxShadow="0 0 24px var(--sw-glow), 0 0 48px rgba(0,0,0,0.25)",this.setPlayingVisual(this.isPlaying);}applyVoiceVisual(e){this.avatarRing&&((e==="idle"||e==="ready"||e==="error")&&(this.avatarVoiceHolding||(this.voiceAvatarPreview=false),(e==="ready"||e==="idle")&&(this.voiceUiDismissed=false,this.voiceUserSpeaking=false,this.voiceHadSpeech=false)),e==="listening"&&(this.voiceUiDismissed=false),this.applyVoiceRing(),this.refreshAvatarImage());}isVoiceAvatarActive(){if(!this.voiceEnabled||this.currentAd||this.voiceUiDismissed)return false;if(this.voiceAvatarPreview)return true;let e=this.engine?.voiceState;return e==="listening"||e==="processing"||e==="responding"}getContentAvatarUrl(){return q}getAvatarImageUrl(){return this.currentAd?.companionBannerUrl?this.currentAd.companionBannerUrl:this.isVoiceAvatarActive()?kt:this.avatarImageBeforeAd?this.avatarImageBeforeAd:q}refreshAvatarImage(){let e=this.getAvatarImageUrl(),t=this.isVoiceAvatarActive();e&&this.avatarImgEl?(this.avatarImgEl.getAttribute("src")!==e&&this.avatarImgEl.setAttribute("src",e),this.avatarImgEl.style.display="block",t?(this.avatarImgEl.style.objectFit="cover",this.avatarImgEl.style.objectPosition="center",this.avatarImgEl.style.transform="scale(1)",this.avatarImgEl.style.padding="",this.avatarImgEl.style.background="var(--sw-bg-inner)"):(this.avatarImgEl.style.objectFit="cover",this.avatarImgEl.style.objectPosition="top",this.avatarImgEl.style.transform=this.mode==="wide"?"scale(1.15)":"scale(1.12)",this.avatarImgEl.style.padding="",this.avatarImgEl.style.background=""),this.avatarTextEl&&(this.avatarTextEl.style.display="none")):(this.avatarImgEl&&(this.avatarImgEl.style.display="none"),this.avatarTextEl&&(this.avatarTextEl.style.display="flex"));}startNowPlayingPoll(){let e=async()=>{let t=await F(this.options.serverUrl);!this.destroyed&&t&&(this.nowPlaying=t,this.refreshLabels());};e(),this.pollTimer=setInterval(e,this.options.nowPlayingPollMs??12e3);}stopNowPlayingPoll(){this.pollTimer!==null&&(clearInterval(this.pollTimer),this.pollTimer=null);}handleSkipClick(){let e=this.engine;if(e){if(this.currentAd){e.canSkipAd()&&e.skipAd();return}e.skip();}}applyAdSkipUi(e){if(!this.skipBtn)return;let{ad:t,canSkip:i,countdownSeconds:n}=e;if(!t.isSkippable){this.skipBtn.disabled=true,this.skipBtn.textContent="",this.skipBtn.replaceChildren(g(k,22));return}if(!i){this.skipBtn.disabled=true,this.skipBtn.replaceChildren(),this.skipBtn.textContent=`${n}s`;return}this.skipBtn.disabled=false,this.skipBtn.textContent="",this.skipBtn.replaceChildren(g(k,22));}restoreTrackSkipButton(){this.skipBtn&&(this.skipBtn.disabled=false,this.skipBtn.textContent="",this.skipBtn.replaceChildren(g(k,22)),this.skipBtn.setAttribute("aria-label","Skip"));}displayLine(){return this.currentAd?{title:this.currentAd.campaignName||"Advertisement",artist:this.currentAd.creativeName}:this.isRadio&&this.nowPlaying?.title?ct(this.nowPlaying.title):this.currentTrack?.title?{title:this.currentTrack.title,artist:this.currentTrack.artist}:{title:"Loading\u2026"}}refreshLabels(){let e=this.displayLine();if(this.titleEl&&(this.titleEl.textContent=e.title),this.artistInlineEl){let t=!!e.artist;this.artistInlineEl.style.display=t?"inline":"none",t&&(this.artistInlineEl.textContent=e.artist);}if(this.artistBlockEl){let t=!!e.artist;this.artistBlockEl.style.display=t?"block":"none",t&&(this.artistBlockEl.textContent=e.artist);}if(this.footerEl)if(this.currentAd)this.footerEl.textContent="Advertisement \xB7 Synxed Player";else {let t=this.isRadio&&(this.nowPlaying?.station??this.currentTrack?.title??"Synxed Radio");this.footerEl.textContent=t&&this.isRadio?`${t} \xB7 Synxed Player`:"Synxed Player";}}updateAvatar(){if(this.refreshAvatarImage(),this.avatarRing){let e=this.avatarRing.firstChild;e&&(e.style.cursor=this.currentAd||this.voiceEnabled?"pointer":"default");}}setPlayingVisual(e){this.avatarRing&&(this.avatarRing.style.animation=e?"synxed-wp-spin 4s linear infinite":""),this.playBtn&&(this.playBtn.replaceChildren(g(e?ot:z,20)),this.playBtn.setAttribute("aria-label",e?"Pause":"Play"));}togglePlay(){this.engine&&(this.isPlaying?this.engine.pause():this.engine.resume());}};
142
+ exports.ContentKind=R;exports.ErrorCode=G;exports.SdkVoiceAction=B;exports.SynxedConnectionError=O;exports.SynxedError=x;exports.SynxedPlaybackError=w;exports.SynxedPlayer=L;exports.SynxedProtocolError=Z;exports.SynxedWebPlayer=j;exports.TransportManager=E;exports.VoiceCaptureManager=P;exports.buildSdkWebSocketUrl=Q;exports.fetchRadioNowPlaying=F;//# sourceMappingURL=index.js.map
143
143
  //# sourceMappingURL=index.js.map