synxed-sdk 0.3.4 → 0.3.7

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
@@ -106,6 +106,8 @@ interface SynxedEvents {
106
106
  voiceSpeechStart: () => void;
107
107
  /** Silence detected after speech — user stopped talking. */
108
108
  voiceSpeechEnd: () => void;
109
+ /** Live mic speech activity from VAD (true while user is talking). */
110
+ voiceUserSpeakingChange: (speaking: boolean) => void;
109
111
  error: (error: Error) => void;
110
112
  connected: () => void;
111
113
  disconnected: (reason: string) => void;
@@ -151,6 +153,7 @@ declare class SynxedPlayer extends EventEmitter<SynxedEvents> {
151
153
  private pendingPlaybackLoad;
152
154
  private voiceAutoEndOnSilence;
153
155
  private pausedForVoice;
156
+ private _voiceUserSpeaking;
154
157
  constructor(config: SynxedConfig);
155
158
  get currentTrack(): TrackInfo | null;
156
159
  /** Active playback init kind from the last `play*` call (RADIO, PLAYLIST, SONG, …). */
@@ -162,6 +165,8 @@ declare class SynxedPlayer extends EventEmitter<SynxedEvents> {
162
165
  /** Seconds until skip unlocks; `0` when skip is available; `null` when not in a skippable ad. */
163
166
  getAdSkipCountdownSeconds(): number | null;
164
167
  get voiceState(): VoiceState;
168
+ /** True while VAD detects the user is actively speaking during a voice hold. */
169
+ get voiceUserSpeaking(): boolean;
165
170
  private controlPositionMs;
166
171
  private setupListeners;
167
172
  private resolveVoiceOptions;
@@ -267,6 +272,7 @@ interface VoiceCaptureEvents {
267
272
  error: (error: Error) => void;
268
273
  speechStart: () => void;
269
274
  speechEnd: () => void;
275
+ userSpeakingChange: (speaking: boolean) => void;
270
276
  }
271
277
  interface VoiceCaptureOptions {
272
278
  maxDurationMs?: number;
@@ -274,16 +280,23 @@ interface VoiceCaptureOptions {
274
280
  onnxWasmBasePath?: string;
275
281
  }
276
282
  /**
277
- * Captures microphone audio using Silero VAD natively.
278
- * Waits for the user to finish talking, then emits the complete audio segment.
283
+ * Mic capture via @ricky0123/vad-web same callbacks as the official demo:
284
+ * onSpeechStart / onSpeechEnd + streaming frames while the user talks.
279
285
  */
280
286
  declare class VoiceCaptureManager extends EventEmitter<VoiceCaptureEvents> {
281
287
  private capturing;
282
288
  private mimeType;
283
289
  private micVad;
284
- private speechEndEmitted;
290
+ private vadBaseAssetPath;
291
+ private onnxWasmBasePath;
292
+ private userSpeaking;
293
+ private chunkSequence;
285
294
  get isCapturing(): boolean;
295
+ get isUserSpeaking(): boolean;
286
296
  preloadModels(options?: VoiceCaptureOptions): Promise<void>;
297
+ private applyOptions;
298
+ private setUserSpeaking;
299
+ private ensureMicVad;
287
300
  start(options?: VoiceCaptureOptions): Promise<string>;
288
301
  stop(): Promise<void>;
289
302
  cancel(): void;
@@ -370,6 +383,8 @@ declare class SynxedWebPlayer {
370
383
  private voiceAvatarPreview;
371
384
  private voiceHoldActivated;
372
385
  private voiceUiDismissed;
386
+ private voiceUserSpeaking;
387
+ private voiceHadSpeech;
373
388
  private voiceHoldTimer;
374
389
  private readonly defaultVoiceHoldMs;
375
390
  /** Avatar to restore after an ad (DJ / album art — not ad or voice AI). */
@@ -401,6 +416,7 @@ declare class SynxedWebPlayer {
401
416
  private isVoiceUiOpen;
402
417
  private dismissVoiceUi;
403
418
  private resetVoiceHoldState;
419
+ private applyVoiceRing;
404
420
  private applyVoiceVisual;
405
421
  private isVoiceAvatarActive;
406
422
  private getContentAvatarUrl;
package/dist/index.d.ts CHANGED
@@ -106,6 +106,8 @@ interface SynxedEvents {
106
106
  voiceSpeechStart: () => void;
107
107
  /** Silence detected after speech — user stopped talking. */
108
108
  voiceSpeechEnd: () => void;
109
+ /** Live mic speech activity from VAD (true while user is talking). */
110
+ voiceUserSpeakingChange: (speaking: boolean) => void;
109
111
  error: (error: Error) => void;
110
112
  connected: () => void;
111
113
  disconnected: (reason: string) => void;
@@ -151,6 +153,7 @@ declare class SynxedPlayer extends EventEmitter<SynxedEvents> {
151
153
  private pendingPlaybackLoad;
152
154
  private voiceAutoEndOnSilence;
153
155
  private pausedForVoice;
156
+ private _voiceUserSpeaking;
154
157
  constructor(config: SynxedConfig);
155
158
  get currentTrack(): TrackInfo | null;
156
159
  /** Active playback init kind from the last `play*` call (RADIO, PLAYLIST, SONG, …). */
@@ -162,6 +165,8 @@ declare class SynxedPlayer extends EventEmitter<SynxedEvents> {
162
165
  /** Seconds until skip unlocks; `0` when skip is available; `null` when not in a skippable ad. */
163
166
  getAdSkipCountdownSeconds(): number | null;
164
167
  get voiceState(): VoiceState;
168
+ /** True while VAD detects the user is actively speaking during a voice hold. */
169
+ get voiceUserSpeaking(): boolean;
165
170
  private controlPositionMs;
166
171
  private setupListeners;
167
172
  private resolveVoiceOptions;
@@ -267,6 +272,7 @@ interface VoiceCaptureEvents {
267
272
  error: (error: Error) => void;
268
273
  speechStart: () => void;
269
274
  speechEnd: () => void;
275
+ userSpeakingChange: (speaking: boolean) => void;
270
276
  }
271
277
  interface VoiceCaptureOptions {
272
278
  maxDurationMs?: number;
@@ -274,16 +280,23 @@ interface VoiceCaptureOptions {
274
280
  onnxWasmBasePath?: string;
275
281
  }
276
282
  /**
277
- * Captures microphone audio using Silero VAD natively.
278
- * Waits for the user to finish talking, then emits the complete audio segment.
283
+ * Mic capture via @ricky0123/vad-web same callbacks as the official demo:
284
+ * onSpeechStart / onSpeechEnd + streaming frames while the user talks.
279
285
  */
280
286
  declare class VoiceCaptureManager extends EventEmitter<VoiceCaptureEvents> {
281
287
  private capturing;
282
288
  private mimeType;
283
289
  private micVad;
284
- private speechEndEmitted;
290
+ private vadBaseAssetPath;
291
+ private onnxWasmBasePath;
292
+ private userSpeaking;
293
+ private chunkSequence;
285
294
  get isCapturing(): boolean;
295
+ get isUserSpeaking(): boolean;
286
296
  preloadModels(options?: VoiceCaptureOptions): Promise<void>;
297
+ private applyOptions;
298
+ private setUserSpeaking;
299
+ private ensureMicVad;
287
300
  start(options?: VoiceCaptureOptions): Promise<string>;
288
301
  stop(): Promise<void>;
289
302
  cancel(): void;
@@ -370,6 +383,8 @@ declare class SynxedWebPlayer {
370
383
  private voiceAvatarPreview;
371
384
  private voiceHoldActivated;
372
385
  private voiceUiDismissed;
386
+ private voiceUserSpeaking;
387
+ private voiceHadSpeech;
373
388
  private voiceHoldTimer;
374
389
  private readonly defaultVoiceHoldMs;
375
390
  /** Avatar to restore after an ad (DJ / album art — not ad or voice AI). */
@@ -401,6 +416,7 @@ declare class SynxedWebPlayer {
401
416
  private isVoiceUiOpen;
402
417
  private dismissVoiceUi;
403
418
  private resetVoiceHoldState;
419
+ private applyVoiceRing;
404
420
  private applyVoiceVisual;
405
421
  private isVoiceAvatarActive;
406
422
  private getContentAvatarUrl;
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 ft=`
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
- `,$=j__namespace.parse(ft).root,U=$.lookupType("SdkClientEnvelope"),H=$.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||{}),D=(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))(D||{}),Y=(a=>(a[a.UNSPECIFIED=0]="UNSPECIFIED",a[a.UNAUTHORIZED=1]="UNAUTHORIZED",a[a.VALIDATION_ERROR=2]="VALIDATION_ERROR",a[a.NOT_FOUND=3]="NOT_FOUND",a[a.PROCESSING=4]="PROCESSING",a[a.SERVICE_UNAVAILABLE=5]="SERVICE_UNAVAILABLE",a[a.BAD_PROTOBUF=6]="BAD_PROTOBUF",a))(Y||{});var S=class{static encodeClientEnvelope(e){let t=U.create(e);return U.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 v=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 G=false;function X(r){G=r;}function m(...r){G&&console.debug("[Synxed]",...r);}function h(...r){console.warn("[Synxed]",...r);}function J(r,e){let i=(r.endsWith("/")?r.slice(0,-1):r).replace(/^http:/,"ws:").replace(/^https:/,"wss:"),n=new URL(`${i}/sdk`);return n.searchParams.set("apiKey",e),n.toString()}var E=class extends v{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=J(i,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,i)=>{let n=this.ws;if(n.readyState===WebSocket.OPEN){t();return}let o=()=>{m("WebSocket connected"),l(),t();},s=()=>{h("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",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,i){let n=++this.loadGeneration;this.teardownPlayback(),this.emit("loading"),m("AudioEngine loading",{url:t,isHls:i});let o=/^((?!chrome|android).)*safari/i.test(navigator.userAgent);if(i&&!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,p)=>{let u=()=>n!==this.loadGeneration,g=()=>{u()||(this.emit("playing"),this.startTimeUpdateLoop());},b=()=>{u()||(this.emit("paused"),this.stopTimeUpdateLoop());},T=()=>{u()||(this.emit("ended"),this.stopTimeUpdateLoop());},I=()=>{u()||this.emit("loaded");},vt=()=>{u()||(h("HLS audio element error"),this.emit("error",new Error("HLS playback failed")));};l.addEventListener("play",g),l.addEventListener("pause",b),l.addEventListener("ended",T),l.addEventListener("loadedmetadata",I),l.addEventListener("error",vt),a.on(s.Events.MANIFEST_PARSED,()=>{u()||(this.emit("loaded"),c());}),a.on(s.Events.ERROR,(kt,M)=>{u()||M.fatal&&(h("Fatal HLS error",M),p(M));}),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:i?["m3u8"]:void 0,onload:()=>{l()||(m("AudioEngine loaded"),this.emit("loaded"),s());},onloaderror:(c,p)=>{l()||(h("AudioEngine load error",p),a(p));},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 O=class extends v{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";}},N=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";}},Q=class extends x{constructor(e){super(e),this.name="SynxedProtocolError";}};function B(r,...e){for(let t of e){let i=r[t];if(typeof i=="string"&&i.length>0)return i}}function gt(r,...e){for(let t of e){let i=r[t];if(typeof i=="number"&&Number.isFinite(i))return i;if(typeof i=="string"&&i!==""&&!Number.isNaN(Number(i)))return Number(i)}}function Z(r){let e=r.initAck??r.init_ack;if(!e||typeof e!="object")return null;let t=e,i=B(t,"playbackUrl","playback_url");return i?{sessionId:B(t,"sessionId","session_id")??"",playbackUrl:i,isHls:!!(t.isHls??t.is_hls),heartbeatIntervalMs:gt(t,"heartbeatIntervalMs","heartbeat_interval_ms")??0,contentSummary:B(t,"contentSummary","content_summary")}:null}function bt(r){if(!r||typeof r!="object")return null;let e=r,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 tt(r,e){if(!r?.trim())return null;let t;try{t=JSON.parse(r);}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 s=[];for(let c of o){let p=bt(c);p&&s.push(p);}if(s.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),s.length-1));return {tracks:s,currentIndex:l}}function f(r,...e){for(let t of e){let i=r[t];if(typeof i=="string")return i}return ""}function et(r,...e){for(let t of e){let i=r[t];if(typeof i=="boolean")return i}return false}function it(r,...e){for(let t of e){let i=r[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 nt(r){let e=r.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:et(t,"isHls","is_hls")||i.includes(".m3u8"),durationSeconds:it(t,"durationSeconds","duration_seconds")||15,isSkippable:et(t,"isSkippable","is_skippable"),skipAfterSeconds:it(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 rt="audio/pcm;rate=16000",A="audio/pcm;rate=24000";function W(r,e){let t=/rate=(\d+)/i.exec(r);if(!t)return e;let i=Number(t[1]);return Number.isFinite(i)&&i>0?i:e}function C(r,...e){for(let t of e){let i=r[t];if(typeof i=="string")return i}return ""}function st(r){let e=r.voiceAck??r.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(r){let e=r.voiceAudio??r.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),s;if(typeof i=="string"){let a=atob(i),l=a.length;s=new Uint8Array(l);for(let c=0;c<l;c++)s[c]=a.charCodeAt(c);}else if(i instanceof Uint8Array)s=i;else return null;return {audioData:s,mimeType:n,isFinal:o}}var V=class{constructor(){this.audioContext=null;this.nextStartTime=0;this.defaultSampleRate=W(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=W(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 s=this.audioContext.createBuffer(1,o.length,i);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(i){h("VoiceResponsePlayer failed to enqueue chunk",i);}}stop(){this.audioContext&&(this.audioContext.close().catch(()=>{}),this.audioContext=null),this.nextStartTime=0;}};var ot="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=rt;this.micVad=null;this.speechEndEmitted=false;}get isCapturing(){return this.capturing}async preloadModels(t={}){setTimeout(async()=>{try{let{utils:i}=await import('@ricky0123/vad-web'),n=t.vadBaseAssetPath??ot;fetch(`${n}silero_vad_legacy.onnx`).catch(()=>{}),fetch(`${n}vad.worklet.bundle.min.js`).catch(()=>{});}catch(i){h("Failed to silently preload VAD models",i);}},5e3);}async start(t={}){if(this.capturing)return this.mimeType;this.speechEndEmitted=false,this.capturing=true;try{let{MicVAD:i}=await import('@ricky0123/vad-web'),n=0;this.micVad=await i.new({baseAssetPath:t.vadBaseAssetPath??ot,onnxWASMBasePath:t.onnxWasmBasePath??St,positiveSpeechThreshold:.5,negativeSpeechThreshold:.35,redemptionMs:500,minSpeechMs:250,onFrameProcessed:(o,s)=>{if(!this.capturing||this.speechEndEmitted)return;let a=new Int16Array(s.length);for(let c=0;c<s.length;c++){let p=Math.max(-1,Math.min(1,s[c]));a[c]=p<0?p*32768:p*32767;}let l=new Uint8Array(a.buffer);n++,this.emit("chunk",l,n);},onSpeechStart:()=>{this.capturing&&this.emit("speechStart");},onSpeechEnd:()=>{!this.capturing||this.speechEndEmitted||(this.speechEndEmitted=!0,this.emit("speechEnd"));}}),this.micVad.start();}catch(i){this.capturing=false,this.emit("error",new Error(`Failed to init VAD: ${i}`));}return this.mimeType}async stop(){this.cancel();}cancel(){if(this.capturing=false,this.micVad){try{this.micVad.pause();}catch{}try{this.micVad.destroy();}catch{}this.micVad=null;}}};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.config=t,X(!!t.debug),this.transport=new E,this.audio=new _,this.playlist=new O,this.voiceCapture=new P,this.voiceResponsePlayer=new V,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}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 N(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,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();});}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.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.voiceMimeType=await this.voiceCapture.start({maxDurationMs:i.maxDurationMs}),this.transport.sendVoice({action:1,mimeType:this.voiceMimeType,listenerId:this.voiceListenerId,...this.buildInitExtras()}),this.setVoiceState("listening");}async endVoiceHold(){this._voiceState==="listening"&&(await this.voiceCapture.stop(),this.transport.sendVoice({action:3,mimeType:this.voiceMimeType,listenerId:this.voiceListenerId,...this.buildInitExtras()}),this.setVoiceState("processing"));}cancelVoiceHold(){this._voiceState==="listening"&&(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 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=tt(t,this.activeContentKind);if(i){this.playlist.setQueue(i.tracks,i.currentIndex);return}t?.trim()&&h("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),s={ad:this._currentAd,canSkip:n,countdownSeconds:o};this.emit("adSkipUpdate",s);}setVoiceState(t){this._voiceState=t,this.emit("voiceStateChange",t);}handleVoiceAck(t){let i=t.status;if(i==="listening"){this.setVoiceState("listening");return}if(i==="processing"){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){m("Received server message",t);let i=st(t);if(i){this.handleVoiceAck(i);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=nt(t);if(o){await this.handleAdPlayback(o);return}let s=Z(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",p=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,p));}}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 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},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(i){let n=this._currentAd;this.adPlaying=false,this._currentAd=null,n&&this.emit("adEnd",n),h("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 K(r,e){let i=`${r.replace(/\/$/,"")}/radio/now-playing`;try{let n=await fetch(i,{...e,headers:{Accept:"application/json",...e?.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,e){let t=document.createElement(r);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 y(r,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",r),t.appendChild(i),t}var F="M8 5v14l11-7L8 5z",lt="M6 5h4v14H6V5zm8 0h4v14h-4V5z",k="M6 18l8.5-6L6 6v12zM16 6v12h2V6h-2z",dt="M6 6h2v12H6V6zm11.5 12L9 12l8.5-6v12z";function ct(){let r="synxed-web-player-styles";if(document.getElementById(r))return;let e=document.createElement("style");e.id=r,e.textContent=`
135
+ `,Y=$__namespace.parse(mt).root,H=Y.lookupType("SdkClientEnvelope"),D=Y.lookupType("SdkServerEnvelope"),V=(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))(V||{}),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=H.create(e);return H.encode(t).finish()}static decodeServerEnvelope(e){let t=D.decode(e);return D.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 R=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.config=t,J(!!t.debug),this.transport=new E,this.audio=new R,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.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._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){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(e);}function pt(r){let e=[" \u2014 "," \u2013 "," - "," \u2014"," \u2013"," -"];for(let t of e){let i=r.indexOf(t);if(i>0)return {title:r.slice(0,i).trim(),artist:r.slice(i+t.length).trim()}}return {title:r.trim()}}function ut(r="bottom-center",e=16,t=16){let i={position:"fixed",zIndex:"50"};switch(r){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(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 mt(r,e){r.style.setProperty("--sw-accent",e.accent),r.style.setProperty("--sw-accent-muted",e.accentMuted),r.style.setProperty("--sw-bg",e.background),r.style.setProperty("--sw-bg-inner",e.backgroundInner),r.style.setProperty("--sw-border",e.border),r.style.setProperty("--sw-text",e.text),r.style.setProperty("--sw-text-muted",e.textMuted),r.style.setProperty("--sw-station",e.stationText),r.style.setProperty("--sw-live",e.liveDot),r.style.setProperty("--sw-glow",e.glow);}var z="https://cdn.synxed.com/avater-image/avatar.svg",xt="https://cdn.synxed.com/avater-image/AI%20Star%20UI%20animation.gif",q=class r{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.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),ct(),this.mountShell(),this.initEngine(),this.options.source.type==="radio"&&this.startNowPlayingPoll();}static mount(e){return new r(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,s=e.offsetY??(n==="bottom-center"?24:16);this.root.className=t??"",this.root.dataset.synxedWebPlayer=this.mode,mt(this.root,this.theme),Object.assign(this.root.style,ut(n,o,s)),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,s=0,a=p=>{let u=p,g=u.target;if(g.closest("[data-synxed-avatar-ring]")||this.avatarVoiceHolding||this.mode!=="mini"&&g.closest("button, a, input"))return;e=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 u?(i=u.touches[0].clientX,n=u.touches[0].clientY):(i=u.clientX,n=u.clientY),document.addEventListener("mousemove",l,{passive:false}),document.addEventListener("mouseup",c),document.addEventListener("touchmove",l,{passive:false}),document.addEventListener("touchend",c);},l=p=>{if(!e)return;p.preventDefault();let u=p,g,b;"touches"in u?(g=u.touches[0].clientX,b=u.touches[0].clientY):(g=u.clientX,b=u.clientY);let T=g-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=`${s+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",p=>{t&&(p.stopPropagation(),p.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"}});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:z,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(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());}),this.voiceEnabled&&(this.avatarRing.style.touchAction="none",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 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),i.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:[y(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:[y(dt,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:[y(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:[y(F,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)),(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.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 s=()=>{if(i(),!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();};e.addEventListener("pointerdown",n),e.addEventListener("pointerup",s),e.addEventListener("pointerleave",s),e.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;}applyVoiceVisual(e){this.avatarRing&&((e==="idle"||e==="ready"||e==="error")&&(this.avatarVoiceHolding||(this.voiceAvatarPreview=false),(e==="ready"||e==="idle")&&(this.voiceUiDismissed=false)),(e==="listening"||e==="processing"||e==="responding")&&(this.voiceUiDismissed=false),e==="listening"?(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)"):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)"):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)"):(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)),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 z}getAvatarImageUrl(){return this.currentAd?.companionBannerUrl?this.currentAd.companionBannerUrl:this.isVoiceAvatarActive()?xt:this.avatarImageBeforeAd?this.avatarImageBeforeAd:z}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 K(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(y(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(y(k,22));}restoreTrackSkipButton(){this.skipBtn&&(this.skipBtn.disabled=false,this.skipBtn.textContent="",this.skipBtn.replaceChildren(y(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?pt(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(y(e?lt:F,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=Y;exports.SdkVoiceAction=D;exports.SynxedConnectionError=N;exports.SynxedError=x;exports.SynxedPlaybackError=w;exports.SynxedPlayer=L;exports.SynxedProtocolError=Q;exports.SynxedWebPlayer=q;exports.TransportManager=E;exports.VoiceCaptureManager=P;exports.buildSdkWebSocketUrl=J;exports.fetchRadioNowPlaying=K;//# 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"}});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(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());}),this.voiceEnabled&&(this.avatarRing.style.touchAction="none",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=()=>{if(i(),!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();};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.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 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"||e==="processing"||e==="responding")&&(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=V;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