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