synxed-sdk 0.2.6 → 0.2.8

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/README.md CHANGED
@@ -1,13 +1,15 @@
1
1
  # Synxed SDK
2
2
 
3
- Add Synxed music to your website or app in a few minutes — playlists, live radio, voice commands, and a ready-made player UI.
3
+ Add Music to your website, Game or App in a few minutes — Stream Licensed Music, Create and manage playlists, Listen to live radio, voice commands to stream songs or create custom playlist, and a ready-made player UI
4
+
5
+ > Synxed has already paid for the right to make that music available, you do not need to pay any license fees, we handle that for you.
4
6
 
5
7
  [![npm version](https://img.shields.io/npm/v/synxed-sdk.svg)](https://www.npmjs.com/package/synxed-sdk)
6
8
 
7
9
  ## What you need
8
10
 
9
11
  1. A **Synxed API key** (from your Synxed developer account `https://portal.synxed.com`).
10
- 2. Your **API URL** (Our api url: `https://api.synxed.com`).
12
+ 2. Our **API URL** is `https://api.synxed.com`.
11
13
  3. A **playlist code**, **Single Song** or choose **live radio**.
12
14
 
13
15
  ## Install
package/dist/index.d.mts CHANGED
@@ -86,12 +86,6 @@ interface VoiceHoldOptions {
86
86
  listenerId?: string;
87
87
  /** Auto-end capture when the user stops talking. Default `true`. */
88
88
  autoEndOnSilence?: boolean;
89
- /** RMS level below which audio counts as silence (0–1). Default `0.018`. */
90
- silenceThreshold?: number;
91
- /** Ms of silence after speech before auto-end. Default `1500`. */
92
- silenceDurationMs?: number;
93
- /** Minimum speech ms before silence can trigger end. Default `400`. */
94
- minSpeechMs?: number;
95
89
  /** Max capture length in ms. Default `30000`. */
96
90
  maxDurationMs?: number;
97
91
  }
@@ -270,43 +264,46 @@ declare function fetchRadioNowPlaying(serverUrl: string, init?: RequestInit): Pr
270
264
  interface VoiceCaptureEvents {
271
265
  chunk: (data: Uint8Array, sequence: number) => void;
272
266
  error: (error: Error) => void;
273
- /** User started speaking (level crossed above silence threshold). */
274
267
  speechStart: () => void;
275
- /** User stopped speaking (silence after speech, or max duration reached). */
276
268
  speechEnd: () => void;
277
269
  }
278
270
  interface VoiceCaptureOptions {
279
- /** RMS level below which audio counts as silence (0–1). Default `0.018`. */
280
- silenceThreshold?: number;
281
- /** Ms of silence after speech before `speechEnd`. Default `1500`. */
282
- silenceDurationMs?: number;
283
- /** Minimum speech ms before silence can end capture. Default `400`. */
284
- minSpeechMs?: number;
285
271
  /** Safety cap — auto `speechEnd` after this many ms. Default `30000`. */
286
272
  maxDurationMs?: number;
287
- /** Monitor mic levels for end-of-speech. Default `true`. */
288
- detectSilence?: boolean;
273
+ /**
274
+ * Base URL where `@ricky0123/vad-web` model / worklet assets are served.
275
+ * Defaults to the jsDelivr CDN.
276
+ */
277
+ vadBaseAssetPath?: string;
278
+ /**
279
+ * Base URL where ONNX Runtime WASM binaries are served.
280
+ * Defaults to the jsDelivr CDN.
281
+ */
282
+ onnxWasmBasePath?: string;
289
283
  }
290
284
  /**
291
- * Native MediaRecorder capture with optional Web Audio silence detection.
285
+ * Captures microphone audio and buffers it locally. Once the user is finished
286
+ * talking (detected via Silero VAD), the complete audio file is emitted to the
287
+ * backend as a single chunk, followed by the stream termination.
292
288
  */
293
289
  declare class VoiceCaptureManager extends EventEmitter<VoiceCaptureEvents> {
294
290
  private stream;
295
- private recorder;
291
+ private audioContext;
292
+ private mediaStreamSource;
293
+ private processor;
294
+ private muteNode;
296
295
  private sequence;
297
296
  private capturing;
298
297
  private mimeType;
299
- private audioContext;
300
- private silenceRaf;
298
+ private micVad;
301
299
  private speechEndEmitted;
302
- private captureOptions;
303
300
  get isCapturing(): boolean;
304
301
  get activeMimeType(): string;
305
302
  start(options?: VoiceCaptureOptions): Promise<string>;
306
303
  stop(): Promise<void>;
307
304
  cancel(): void;
308
- private startSilenceMonitor;
309
- private stopSilenceMonitor;
305
+ private startVadMonitor;
306
+ private teardownVad;
310
307
  private releaseStream;
311
308
  }
312
309
 
package/dist/index.d.ts CHANGED
@@ -86,12 +86,6 @@ interface VoiceHoldOptions {
86
86
  listenerId?: string;
87
87
  /** Auto-end capture when the user stops talking. Default `true`. */
88
88
  autoEndOnSilence?: boolean;
89
- /** RMS level below which audio counts as silence (0–1). Default `0.018`. */
90
- silenceThreshold?: number;
91
- /** Ms of silence after speech before auto-end. Default `1500`. */
92
- silenceDurationMs?: number;
93
- /** Minimum speech ms before silence can trigger end. Default `400`. */
94
- minSpeechMs?: number;
95
89
  /** Max capture length in ms. Default `30000`. */
96
90
  maxDurationMs?: number;
97
91
  }
@@ -270,43 +264,46 @@ declare function fetchRadioNowPlaying(serverUrl: string, init?: RequestInit): Pr
270
264
  interface VoiceCaptureEvents {
271
265
  chunk: (data: Uint8Array, sequence: number) => void;
272
266
  error: (error: Error) => void;
273
- /** User started speaking (level crossed above silence threshold). */
274
267
  speechStart: () => void;
275
- /** User stopped speaking (silence after speech, or max duration reached). */
276
268
  speechEnd: () => void;
277
269
  }
278
270
  interface VoiceCaptureOptions {
279
- /** RMS level below which audio counts as silence (0–1). Default `0.018`. */
280
- silenceThreshold?: number;
281
- /** Ms of silence after speech before `speechEnd`. Default `1500`. */
282
- silenceDurationMs?: number;
283
- /** Minimum speech ms before silence can end capture. Default `400`. */
284
- minSpeechMs?: number;
285
271
  /** Safety cap — auto `speechEnd` after this many ms. Default `30000`. */
286
272
  maxDurationMs?: number;
287
- /** Monitor mic levels for end-of-speech. Default `true`. */
288
- detectSilence?: boolean;
273
+ /**
274
+ * Base URL where `@ricky0123/vad-web` model / worklet assets are served.
275
+ * Defaults to the jsDelivr CDN.
276
+ */
277
+ vadBaseAssetPath?: string;
278
+ /**
279
+ * Base URL where ONNX Runtime WASM binaries are served.
280
+ * Defaults to the jsDelivr CDN.
281
+ */
282
+ onnxWasmBasePath?: string;
289
283
  }
290
284
  /**
291
- * Native MediaRecorder capture with optional Web Audio silence detection.
285
+ * Captures microphone audio and buffers it locally. Once the user is finished
286
+ * talking (detected via Silero VAD), the complete audio file is emitted to the
287
+ * backend as a single chunk, followed by the stream termination.
292
288
  */
293
289
  declare class VoiceCaptureManager extends EventEmitter<VoiceCaptureEvents> {
294
290
  private stream;
295
- private recorder;
291
+ private audioContext;
292
+ private mediaStreamSource;
293
+ private processor;
294
+ private muteNode;
296
295
  private sequence;
297
296
  private capturing;
298
297
  private mimeType;
299
- private audioContext;
300
- private silenceRaf;
298
+ private micVad;
301
299
  private speechEndEmitted;
302
- private captureOptions;
303
300
  get isCapturing(): boolean;
304
301
  get activeMimeType(): string;
305
302
  start(options?: VoiceCaptureOptions): Promise<string>;
306
303
  stop(): Promise<void>;
307
304
  cancel(): void;
308
- private startSilenceMonitor;
309
- private stopSilenceMonitor;
305
+ private startVadMonitor;
306
+ private teardownVad;
310
307
  private releaseStream;
311
308
  }
312
309
 
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- 'use strict';var Y=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 Y__namespace=/*#__PURE__*/_interopNamespace(Y);var vt=`
1
+ 'use strict';var F=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 F__namespace=/*#__PURE__*/_interopNamespace(F);var ct=`
2
2
  syntax = "proto3";
3
3
 
4
4
  enum ContentKind {
@@ -117,20 +117,53 @@ message SdkServerAdPayload {
117
117
  string campaignName = 13;
118
118
  }
119
119
 
120
+ message SdkServerVoiceAudio {
121
+ bytes audioData = 1;
122
+ string mimeType = 2;
123
+ bool isFinal = 3;
124
+ }
125
+
120
126
  message SdkServerEnvelope {
121
127
  oneof payload {
122
128
  SdkServerInitAck initAck = 1;
123
129
  SdkServerError error = 2;
124
130
  SdkServerAdPayload ad = 3;
125
131
  SdkServerVoiceAck voiceAck = 4;
132
+ SdkServerVoiceAudio voiceAudio = 5;
126
133
  }
127
134
  }
128
- `,G=Y__namespace.parse(vt).root,D=G.lookupType("SdkClientEnvelope"),B=G.lookupType("SdkServerEnvelope"),O=(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))(O||{}),K=(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))(K||{}),X=(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))(X||{});var S=class{static encodeClientEnvelope(e){let t=D.create(e);return D.encode(t).finish()}static decodeServerEnvelope(e){let t=B.decode(e);return B.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 J=false;function Q(r){J=r;}function h(...r){J&&console.debug("[Synxed]",...r);}function f(...r){console.warn("[Synxed]",...r);}function Z(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 C=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=Z(i,t);h("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(h("Waiting for connection\u2026"),this.ws?.readyState===WebSocket.OPEN){h("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=()=>{h("WebSocket connected"),l(),t();},s=()=>{f("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");h("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 N=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"),h("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()){h("Using Hls.js for playback");let a=new s({xhrSetup:u=>{u.setRequestHeader("ngrok-skip-browser-warning","true");}}),l=new Audio;return new Promise((u,p)=>{let c=()=>n!==this.loadGeneration,y=()=>{c()||(this.emit("playing"),this.startTimeUpdateLoop());},m=()=>{c()||(this.emit("paused"),this.stopTimeUpdateLoop());},E=()=>{c()||(this.emit("ended"),this.stopTimeUpdateLoop());},k=()=>{c()||this.emit("loaded");},R=()=>{c()||(f("HLS audio element error"),this.emit("error",new Error("HLS playback failed")));};l.addEventListener("play",y),l.addEventListener("pause",m),l.addEventListener("ended",E),l.addEventListener("loadedmetadata",k),l.addEventListener("error",R),a.on(s.Events.MANIFEST_PARSED,()=>{c()||(this.emit("loaded"),u());}),a.on(s.Events.ERROR,(U,T)=>{c()||T.fatal&&(f("Fatal HLS error",T),p(T));}),a.loadSource(t),a.attachMedia(l),this.hls=a,this.audioEl=l;})}}catch(s){f("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()||(h("AudioEngine loaded"),this.emit("loaded"),s());},onloaderror:(u,p)=>{l()||(f("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=>f("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 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";}},M=class extends x{constructor(e){super(e),this.name="SynxedConnectionError";}},P=class extends x{constructor(e){super(typeof e=="string"?e:"Playback failed"),this.name="SynxedPlaybackError";}},tt=class extends x{constructor(e){super(e),this.name="SynxedProtocolError";}};function W(r,...e){for(let t of e){let i=r[t];if(typeof i=="string"&&i.length>0)return i}}function yt(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 et(r){let e=r.initAck??r.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:yt(t,"heartbeatIntervalMs","heartbeat_interval_ms")??0,contentSummary:W(t,"contentSummary","content_summary")}:null}function gt(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 it(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 u of o){let p=gt(u);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 g(r,...e){for(let t of e){let i=r[t];if(typeof i=="string")return i}return ""}function nt(r,...e){for(let t of e){let i=r[t];if(typeof i=="boolean")return i}return false}function rt(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 st(r){let e=r.ad;if(!e||typeof e!="object")return null;let t=e,i=g(t,"playbackUrl","playback_url");return i?{adId:g(t,"adId","ad_id"),campaignId:g(t,"campaignId","campaign_id"),playbackUrl:i,isHls:nt(t,"isHls","is_hls")||i.includes(".m3u8"),durationSeconds:rt(t,"durationSeconds","duration_seconds")||15,isSkippable:nt(t,"isSkippable","is_skippable"),skipAfterSeconds:rt(t,"skipAfterSeconds","skip_after_seconds"),ctaType:g(t,"ctaType","cta_type"),ctaValue:g(t,"ctaValue","cta_value"),brandName:g(t,"brandName","brand_name"),creativeName:g(t,"creativeName","creative_name"),companionBannerUrl:g(t,"companionBannerUrl","companion_banner_url"),campaignName:g(t,"campaignName","campaign_name")}:null}function L(r,...e){for(let t of e){let i=r[t];if(typeof i=="string")return i}return ""}function at(r){let e=r.voiceAck??r.voice_ack;if(!e||typeof e!="object")return null;let t=e,i=L(t,"status");return i?{status:i,transcript:L(t,"transcript")||void 0,playlistCode:L(t,"playlistCode","playlist_code")||void 0,playlistName:L(t,"playlistName","playlist_name")||void 0}:null}function ot(){let r=["audio/webm;codecs=opus","audio/webm","audio/ogg;codecs=opus","audio/mp4"];for(let e of r)if(MediaRecorder.isTypeSupported(e))return e;return "audio/webm"}var I=class extends v{constructor(){super(...arguments);this.stream=null;this.recorder=null;this.sequence=0;this.capturing=false;this.mimeType=ot();this.audioContext=null;this.silenceRaf=null;this.speechEndEmitted=false;this.captureOptions={};}get isCapturing(){return this.capturing}get activeMimeType(){return this.mimeType}async start(t={}){return this.capturing?this.mimeType:(this.captureOptions=t,this.speechEndEmitted=false,this.mimeType=ot(),this.sequence=0,this.stream=await navigator.mediaDevices.getUserMedia({audio:{echoCancellation:true,noiseSuppression:true,autoGainControl:true},video:false}),this.recorder=new MediaRecorder(this.stream,{mimeType:this.mimeType,audioBitsPerSecond:32e3}),this.recorder.ondataavailable=i=>{!this.capturing||!i.data.size||i.data.arrayBuffer().then(n=>{this.capturing&&(this.sequence+=1,this.emit("chunk",new Uint8Array(n),this.sequence));});},this.recorder.onerror=()=>{this.emit("error",new Error("Microphone capture failed"));},this.capturing=true,this.recorder.start(40),t.detectSilence!==false&&this.startSilenceMonitor(t),this.mimeType)}async stop(){if(!this.recorder||!this.capturing)return;this.capturing=false,this.stopSilenceMonitor();let t=this.recorder;await new Promise(i=>{if(t.state==="inactive"){this.releaseStream(),i();return}t.addEventListener("stop",()=>{this.releaseStream(),i();},{once:true});try{t.stop();}catch{this.releaseStream(),i();}});}cancel(){this.capturing=false,this.stopSilenceMonitor();let t=this.recorder;if(t&&t.state!=="inactive")try{t.stop();}catch{}this.releaseStream();}startSilenceMonitor(t){if(!this.stream)return;let i=t.silenceThreshold??.018,n=t.silenceDurationMs??1500,o=t.minSpeechMs??400,s=t.maxDurationMs??3e4,a=new AudioContext,l=a.createMediaStreamSource(this.stream),u=a.createAnalyser();u.fftSize=512,l.connect(u);let p=new Uint8Array(u.fftSize),c=false,y=0,m=null,E=Date.now(),k=()=>{this.speechEndEmitted||!this.capturing||(this.speechEndEmitted=true,this.emit("speechEnd"));},R=()=>{if(!this.capturing)return;u.getByteTimeDomainData(p);let U=0;for(let H=0;H<p.length;H++){let j=(p[H]-128)/128;U+=j*j;}let T=Math.sqrt(U/p.length),A=Date.now();if(A-E>=s){k();return}if(T>i)c||(c=true,y=A,this.emit("speechStart")),m=null;else if(c&&A-y>=o){if(m===null)m=A;else if(A-m>=n){k();return}}this.silenceRaf=requestAnimationFrame(R);};this.audioContext=a,this.silenceRaf=requestAnimationFrame(R);}stopSilenceMonitor(){this.silenceRaf!==null&&(cancelAnimationFrame(this.silenceRaf),this.silenceRaf=null),this.audioContext&&(this.audioContext.close(),this.audioContext=null);}releaseStream(){if(this.stream){for(let t of this.stream.getTracks())t.stop();this.stream=null;}this.recorder=null;}};var V=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,Q(!!t.debug),this.transport=new C,this.audio=new N,this.playlist=new _,this.voiceCapture=new I,this.setupListeners(),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 M(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){f("Ad playback error \u2014 waiting for next track",t);return}this.emit("error",new P(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")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.voiceMimeType=await this.voiceCapture.start({silenceThreshold:i.silenceThreshold,silenceDurationMs:i.silenceDurationMs,minSpeechMs:i.minSpeechMs,maxDurationMs:i.maxDurationMs,detectSilence:this.voiceAutoEndOnSilence}),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"}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=it(t,this.activeContentKind);if(i){this.playlist.setQueue(i.tracks,i.currentIndex);return}t?.trim()&&f("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){h("Received server message",t);let i=at(t);if(i){this.handleVoiceAck(i);return}let n=st(t);if(n){await this.handleAdPlayback(n);return}let o=et(t);if(o){await this.startContentPlayback(o);return}let s=t.error;if(s&&typeof s=="object"){let a=s,l=typeof a.message=="string"?a.message:"Unknown server error",u=typeof a.code=="string"?a.code:void 0;(this._voiceState==="processing"||this._voiceState==="listening")&&this.setVoiceState("error"),this.emit("error",new x(l,u));}}async startContentPlayback(t){if(this.adPlaying&&this._currentAd){let n=this._currentAd;this.adPlaying=false,this._currentAd=null,this.emit("adEnd",n);}else this.adPlaying=false,this._currentAd=null;(this._voiceState==="ready"||this._voiceState==="processing")&&this.setVoiceState("idle"),this.pausedForVoice=false,h("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 P(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},h("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),f("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.audio.stop(),this.transport.disconnect(),this.playlist.reset(),this.removeAllListeners();}};async function F(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 b(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 z="M8 5v14l11-7L8 5z",lt="M6 5h4v14H6V5zm8 0h4v14h-4V5z",w="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
+ `,z=F__namespace.parse(ct).root,L=z.lookupType("SdkClientEnvelope"),M=z.lookupType("SdkServerEnvelope"),P=(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))(P||{}),U=(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))(U||{}),j=(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))(j||{});var S=class{static encodeClientEnvelope(e){let t=L.create(e);return L.encode(t).finish()}static decodeServerEnvelope(e){let t=M.decode(e);return M.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 q=false;function $(s){q=s;}function m(...s){q&&console.debug("[Synxed]",...s);}function u(...s){console.warn("[Synxed]",...s);}function G(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 w=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=G(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 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(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"),d(),t();},r=()=>{u("WebSocket connection error"),d(),i(new Error("WebSocket connection failed"));},a=()=>{d(),i(new Error("WebSocket closed before connection was established"));},d=()=>{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");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 I=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:r}=await import('hls.js');if(r.isSupported()){m("Using Hls.js for playback");let a=new r({xhrSetup:h=>{h.setRequestHeader("ngrok-skip-browser-warning","true");}}),d=new Audio;return new Promise((h,p)=>{let c=()=>n!==this.loadGeneration,g=()=>{c()||(this.emit("playing"),this.startTimeUpdateLoop());},b=()=>{c()||(this.emit("paused"),this.stopTimeUpdateLoop());},C=()=>{c()||(this.emit("ended"),this.stopTimeUpdateLoop());},T=()=>{c()||this.emit("loaded");},dt=()=>{c()||(u("HLS audio element error"),this.emit("error",new Error("HLS playback failed")));};d.addEventListener("play",g),d.addEventListener("pause",b),d.addEventListener("ended",C),d.addEventListener("loadedmetadata",T),d.addEventListener("error",dt),a.on(r.Events.MANIFEST_PARSED,()=>{c()||(this.emit("loaded"),h());}),a.on(r.Events.ERROR,(yt,_)=>{c()||_.fatal&&(u("Fatal HLS error",_),p(_));}),a.loadSource(t),a.attachMedia(d),this.hls=a,this.audioEl=d;})}}catch(r){u("hls.js not available, falling back to native playback",r);}return new Promise((r,a)=>{let d=()=>n!==this.loadGeneration;this.howl=new howler.Howl({src:[t],html5:true,format:i?["m3u8"]:void 0,onload:()=>{d()||(m("AudioEngine loaded"),this.emit("loaded"),r());},onloaderror:(h,p)=>{d()||(u("AudioEngine load error",p),a(p));},onplay:()=>{d()||(this.emit("playing"),this.startTimeUpdateLoop());},onpause:()=>{d()||(this.emit("paused"),this.stopTimeUpdateLoop());},onstop:()=>{d()||(this.emit("stopped"),this.stopTimeUpdateLoop());},onend:()=>{d()||(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 N=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";}},V=class extends x{constructor(e){super(e),this.name="SynxedConnectionError";}},E=class extends x{constructor(e){super(typeof e=="string"?e:"Playback failed"),this.name="SynxedPlaybackError";}},Y=class extends x{constructor(e){super(e),this.name="SynxedProtocolError";}};function H(s,...e){for(let t of e){let i=s[t];if(typeof i=="string"&&i.length>0)return i}}function ut(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 X(s){let e=s.initAck??s.init_ack;if(!e||typeof e!="object")return null;let t=e,i=H(t,"playbackUrl","playback_url");return i?{sessionId:H(t,"sessionId","session_id")??"",playbackUrl:i,isHls:!!(t.isHls??t.is_hls),heartbeatIntervalMs:ut(t,"heartbeatIntervalMs","heartbeat_interval_ms")??0,contentSummary:H(t,"contentSummary","content_summary")}:null}function ht(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 J(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 h of o){let p=ht(h);p&&r.push(p);}if(r.length===0)return null;let a=typeof i.currentIndex=="number"?i.currentIndex:typeof i.current_index=="number"?i.current_index:0,d=Math.max(0,Math.min(Math.floor(a),r.length-1));return {tracks:r,currentIndex:d}}function f(s,...e){for(let t of e){let i=s[t];if(typeof i=="string")return i}return ""}function Q(s,...e){for(let t of e){let i=s[t];if(typeof i=="boolean")return i}return false}function Z(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 tt(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:Q(t,"isHls","is_hls")||i.includes(".m3u8"),durationSeconds:Z(t,"durationSeconds","duration_seconds")||15,isSkippable:Q(t,"isSkippable","is_skippable"),skipAfterSeconds:Z(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}function R(s,...e){for(let t of e){let i=s[t];if(typeof i=="string")return i}return ""}function et(s){let e=s.voiceAck??s.voice_ack;if(!e||typeof e!="object")return null;let t=e,i=R(t,"status");return i?{status:i,transcript:R(t,"transcript")||void 0,playlistCode:R(t,"playlistCode","playlist_code")||void 0,playlistName:R(t,"playlistName","playlist_name")||void 0}:null}var mt="https://cdn.jsdelivr.net/npm/@ricky0123/vad-web@0.0.29/dist/",vt="https://cdn.jsdelivr.net/npm/onnxruntime-web@1.22.0/dist/",A=class extends v{constructor(){super(...arguments);this.stream=null;this.audioContext=null;this.mediaStreamSource=null;this.processor=null;this.muteNode=null;this.sequence=0;this.capturing=false;this.mimeType="audio/pcm;rate=16000";this.micVad=null;this.speechEndEmitted=false;}get isCapturing(){return this.capturing}get activeMimeType(){return this.mimeType}async start(t={}){if(this.capturing)return this.mimeType;this.speechEndEmitted=false,this.mimeType="audio/pcm;rate=16000",this.sequence=0,this.stream=await navigator.mediaDevices.getUserMedia({audio:{echoCancellation:true,noiseSuppression:true,autoGainControl:true,channelCount:1},video:false}),this.audioContext=new(window.AudioContext||window.webkitAudioContext)({sampleRate:16e3});let i=`
136
+ class PcmProcessor extends AudioWorkletProcessor {
137
+ constructor() {
138
+ super();
139
+ this.buffer = new Int16Array(4096);
140
+ this.offset = 0;
141
+ }
142
+
143
+ process(inputs, outputs, parameters) {
144
+ const input = inputs[0];
145
+ if (!input || !input[0]) return true;
146
+
147
+ const channelData = input[0];
148
+ for (let i = 0; i < channelData.length; i++) {
149
+ let s = Math.max(-1, Math.min(1, channelData[i]));
150
+ this.buffer[this.offset++] = s < 0 ? s * 0x8000 : s * 0x7fff;
151
+
152
+ if (this.offset >= 4096) {
153
+ this.port.postMessage(this.buffer.buffer.slice(0));
154
+ this.offset = 0;
155
+ }
156
+ }
157
+ return true;
158
+ }
159
+ }
160
+ registerProcessor('pcm-processor', PcmProcessor);
161
+ `,n=new Blob([i],{type:"application/javascript"}),o=URL.createObjectURL(n);await this.audioContext.audioWorklet.addModule(o),this.mediaStreamSource=this.audioContext.createMediaStreamSource(this.stream),this.processor=new AudioWorkletNode(this.audioContext,"pcm-processor"),this.muteNode=this.audioContext.createGain(),this.muteNode.gain.value=0,this.processor.port.onmessage=r=>{this.capturing&&(this.sequence++,this.emit("chunk",new Uint8Array(r.data),this.sequence));},this.mediaStreamSource.connect(this.processor),this.processor.connect(this.muteNode),this.muteNode.connect(this.audioContext.destination),URL.revokeObjectURL(o),this.capturing=true;try{await this.startVadMonitor(t);}catch(r){this.emit("error",new Error(`Failed to initialize Voice Activity Detection: ${r instanceof Error?r.message:String(r)}`));}return this.mimeType}async stop(){this.capturing&&(this.capturing=false,this.teardownVad(),this.releaseStream());}cancel(){this.capturing=false,this.teardownVad(),this.releaseStream();}async startVadMonitor(t){let{MicVAD:i}=await import('@ricky0123/vad-web'),n=t.maxDurationMs??3e4,o=null,r=()=>{this.speechEndEmitted||!this.capturing||(this.speechEndEmitted=true,this.emit("speechEnd"));},a=await i.new({getStream:async()=>this.stream,baseAssetPath:t.vadBaseAssetPath??mt,onnxWASMBasePath:t.onnxWasmBasePath??vt,onSpeechStart:()=>{this.capturing&&(this.emit("speechStart"),o===null&&(o=setTimeout(()=>{r();},n)));},onSpeechEnd:()=>{o!==null&&(clearTimeout(o),o=null),r();}});this.micVad={start:()=>a.start(),pause:()=>a.pause(),destroy:()=>{o!==null&&(clearTimeout(o),o=null),a.destroy();}},this.micVad.start();}teardownVad(){if(this.micVad){try{this.micVad.pause();}catch(t){u("VAD pause failed during teardown",t);}try{this.micVad.destroy();}catch(t){u("VAD destroy failed during teardown",t);}this.micVad=null;}}releaseStream(){if(this.processor&&(this.processor.disconnect(),this.processor.port.onmessage=null,this.processor=null),this.muteNode&&(this.muteNode.disconnect(),this.muteNode=null),this.mediaStreamSource&&(this.mediaStreamSource.disconnect(),this.mediaStreamSource=null),this.audioContext&&(this.audioContext.close().catch(()=>{}),this.audioContext=null),this.stream){for(let t of this.stream.getTracks())t.stop();this.stream=null;}}};var O=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,$(!!t.debug),this.transport=new w,this.audio=new I,this.playlist=new N,this.voiceCapture=new A,this.setupListeners(),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 V(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 E(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")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.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"}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=J(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.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=et(t);if(i){this.handleVoiceAck(i);return}let n=tt(t);if(n){await this.handleAdPlayback(n);return}let o=X(t);if(o){await this.startContentPlayback(o);return}let r=t.error;if(r&&typeof r=="object"){let a=r,d=typeof a.message=="string"?a.message:"Unknown server error",h=typeof a.code=="string"?a.code:void 0;(this._voiceState==="processing"||this._voiceState==="listening")&&this.setVoiceState("error"),this.emit("error",new x(d,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.setVoiceState("idle"),this.pausedForVoice=false,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 E(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),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.audio.stop(),this.transport.disconnect(),this.playlist.reset(),this.removeAllListeners();}};async function D(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 l(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 y(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 B="M8 5v14l11-7L8 5z",it="M6 5h4v14H6V5zm8 0h4v14h-4V5z",k="M6 18l8.5-6L6 6v12zM16 6v12h2V6h-2z",nt="M6 6h2v12H6V6zm11.5 12L9 12l8.5-6v12z";function st(){let s="synxed-web-player-styles";if(document.getElementById(s))return;let e=document.createElement("style");e.id=s,e.textContent=`
129
162
  @keyframes synxed-wp-spin { from { transform: rotate(0); } to { transform: rotate(360deg); } }
130
163
  @keyframes synxed-wp-vbar {
131
164
  0%, 100% { transform: scaleY(0.28); opacity: 0.45; }
132
165
  50% { transform: scaleY(1); opacity: 1; }
133
166
  }
134
- `,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 q="https://cdn.synxed.com/avater-image/avatar.svg",bt="https://cdn.synxed.com/avater-image/generative-ai.svg",$=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 c=p,y=c.target;if(y.closest("[data-synxed-avatar-ring]")||this.avatarVoiceHolding||this.mode!=="mini"&&y.closest("button, a, input"))return;e=true,t=false;let m=this.root.getBoundingClientRect();o=m.left,s=m.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 c?(i=c.touches[0].clientX,n=c.touches[0].clientY):(i=c.clientX,n=c.clientY),document.addEventListener("mousemove",l,{passive:false}),document.addEventListener("mouseup",u),document.addEventListener("touchmove",l,{passive:false}),document.addEventListener("touchend",u);},l=p=>{if(!e)return;p.preventDefault();let c=p,y,m;"touches"in c?(y=c.touches[0].clientX,m=c.touches[0].clientY):(y=c.clientX,m=c.clientY);let E=y-i,k=m-n;(Math.abs(E)>3||Math.abs(k)>3)&&(t=true),this.root.style.left=`${o+E}px`,this.root.style.top=`${s+k}px`;},u=()=>{e=false,document.removeEventListener("mousemove",l),document.removeEventListener("mouseup",u),document.removeEventListener("touchmove",l),document.removeEventListener("touchend",u),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: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 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:[b(w,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:[b(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:[b(w,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:[b(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 V({apiKey:e,serverUrl:t,autoConnect:true});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")&&(this.voiceUiDismissed=false),e==="listening"?(this.avatarRing.style.animation="",this.avatarRing.style.borderColor="#ef4444",this.avatarRing.style.boxShadow="0 0 20px rgba(239,68,68,0.55), 0 0 40px rgba(239,68,68,0.25)"):e==="processing"?(this.avatarRing.style.animation="",this.avatarRing.style.borderColor="#6366f1",this.avatarRing.style.boxShadow="0 0 20px rgba(99,102,241,0.5), 0 0 40px rgba(99,102,241,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"}getContentAvatarUrl(){return q}getAvatarImageUrl(){return this.currentAd?.companionBannerUrl?this.currentAd.companionBannerUrl:this.isVoiceAvatarActive()?bt: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="contain",this.avatarImgEl.style.objectPosition="center",this.avatarImgEl.style.transform="scale(1)",this.avatarImgEl.style.padding="14%",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(b(w,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(b(w,22));}restoreTrackSkipButton(){this.skipBtn&&(this.skipBtn.disabled=false,this.skipBtn.textContent="",this.skipBtn.replaceChildren(b(w,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(b(e?lt:z,20)),this.playBtn.setAttribute("aria-label",e?"Pause":"Play"));}togglePlay(){this.engine&&(this.isPlaying?this.engine.pause():this.engine.resume());}};
135
- exports.ContentKind=O;exports.ErrorCode=X;exports.SdkVoiceAction=K;exports.SynxedConnectionError=M;exports.SynxedError=x;exports.SynxedPlaybackError=P;exports.SynxedPlayer=V;exports.SynxedProtocolError=tt;exports.SynxedWebPlayer=$;exports.TransportManager=C;exports.VoiceCaptureManager=I;exports.buildSdkWebSocketUrl=Z;exports.fetchRadioNowPlaying=F;//# sourceMappingURL=index.js.map
167
+ `,document.head.appendChild(e);}function rt(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 at(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 ot(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 lt(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 W="https://cdn.synxed.com/avater-image/avatar.svg",ft="https://cdn.synxed.com/avater-image/AI%20Star%20UI%20animation.gif",K=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.voiceHoldTimer=null;this.defaultVoiceHoldMs=450;this.options={mode:"wide",attribution:"Synxed",nowPlayingPollMs:12e3,powerByLabel:"Powered by Synxed",enableVoice:true,...e},this.theme=ot(this.options.theme),this.ownsRoot=!e.container,this.root=e.container??document.createElement("div"),this.ownsRoot&&document.body.appendChild(this.root),st(),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,lt(this.root,this.theme),Object.assign(this.root.style,at(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=p=>{let c=p,g=c.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,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 c?(i=c.touches[0].clientX,n=c.touches[0].clientY):(i=c.clientX,n=c.clientY),document.addEventListener("mousemove",d,{passive:false}),document.addEventListener("mouseup",h),document.addEventListener("touchmove",d,{passive:false}),document.addEventListener("touchend",h);},d=p=>{if(!e)return;p.preventDefault();let c=p,g,b;"touches"in c?(g=c.touches[0].clientX,b=c.touches[0].clientY):(g=c.clientX,b=c.clientY);let C=g-i,T=b-n;(Math.abs(C)>3||Math.abs(T)>3)&&(t=true),this.root.style.left=`${o+C}px`,this.root.style.top=`${r+T}px`;},h=()=>{e=false,document.removeEventListener("mousemove",d),document.removeEventListener("mouseup",h),document.removeEventListener("touchmove",d),document.removeEventListener("touchend",h),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=l("div",{style:{position:"relative",flexShrink:"0"}});this.avatarRing=l("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=l("div",{style:{width:"100%",height:"100%",borderRadius:"50%",background:"var(--sw-bg-inner)",overflow:"hidden"}});return this.avatarImgEl=l("img",{attrs:{src:W,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=l("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(l("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=l("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=l("div",{style:{position:"relative",display:"flex",alignItems:"center",width:"100%"}}),n=Math.max(90*.42,40);i.appendChild(l("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:[l("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=l("div",{style:{position:"relative",zIndex:"1",flex:"1",minWidth:"0",marginLeft:"14px",padding:"18px 8px"}}),a=l("div",{style:{display:"flex",alignItems:"baseline",gap:"8px",overflow:"hidden"}});this.titleEl=l("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=l("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=l("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 d=l("div",{style:{position:"relative",zIndex:"1",flexShrink:"0",display:"flex",alignItems:"center",gap:"14px",paddingRight:"16px"}});this.playBtn=this.createPlayButton(52),d.appendChild(this.playBtn),this.isRadio||(this.skipBtn=l("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)]}),d.appendChild(this.skipBtn)),d.appendChild(this.decoLines()),i.appendChild(d),this.root.appendChild(i);}buildLarge(){this.root.style.width="min(calc(100vw - 24px), 380px)";let t=l("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=l("div",{style:{display:"flex",gap:"12px",alignItems:"center",minWidth:"0"}});i.appendChild(this.buildAvatar(96,true));let n=l("div",{style:{minWidth:"0",flex:"1"}});this.titleEl=l("h3",{style:{margin:"0",fontSize:"18px",fontWeight:"900",color:"var(--sw-text)",overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"}}),n.appendChild(this.titleEl),this.artistBlockEl=l("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=l("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(l("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=l("div",{style:{display:"flex",alignItems:"center",justifyContent:"center",gap:"18px"}});this.isRadio||o.appendChild(l("button",{attrs:{type:"button","aria-label":"Previous"},style:this.roundControlStyle(),onClick:()=>this.engine?.previous(),children:[y(nt,22)]})),this.playBtn=this.createPlayButton(56),o.appendChild(this.playBtn),this.isRadio||(this.skipBtn=l("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 l("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(B,e>=56?22:20)]})}buildVisualizer(){let e=l("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(l("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=l("div",{style:{display:"flex",flexDirection:"column",gap:"3px",opacity:"0.22"}});return e.appendChild(l("span",{style:{display:"block",width:"16px",height:"2px",borderRadius:"999px",background:"var(--sw-text)",transform:"translateX(3px)"}})),e.appendChild(l("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 O({apiKey:e,serverUrl:t,autoConnect:true});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 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;}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")&&(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)"):(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"}getContentAvatarUrl(){return W}getAvatarImageUrl(){return this.currentAd?.companionBannerUrl?this.currentAd.companionBannerUrl:this.isVoiceAvatarActive()?ft:this.avatarImageBeforeAd?this.avatarImageBeforeAd:W}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 D(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?rt(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?it:B,20)),this.playBtn.setAttribute("aria-label",e?"Pause":"Play"));}togglePlay(){this.engine&&(this.isPlaying?this.engine.pause():this.engine.resume());}};
168
+ exports.ContentKind=P;exports.ErrorCode=j;exports.SdkVoiceAction=U;exports.SynxedConnectionError=V;exports.SynxedError=x;exports.SynxedPlaybackError=E;exports.SynxedPlayer=O;exports.SynxedProtocolError=Y;exports.SynxedWebPlayer=K;exports.TransportManager=w;exports.VoiceCaptureManager=A;exports.buildSdkWebSocketUrl=G;exports.fetchRadioNowPlaying=D;//# sourceMappingURL=index.js.map
136
169
  //# sourceMappingURL=index.js.map