// Classic script runs before deferred modules, retaining initial host callbacks. window.rhineWallpaperHost = { properties: {}, fps: 30, paused: false }; let resolveInitialWallpaperProperties; window.rhineWallpaperPropertiesReady = new Promise(resolve => { resolveInitialWallpaperProperties = resolve; }); window.wallpaperPropertyListener = { applyUserProperties(properties) { Object.assign(window.rhineWallpaperHost.properties, properties); window.dispatchEvent(new CustomEvent("rhine-wallpaper-properties", { detail: properties })); resolveInitialWallpaperProperties(); }, applyGeneralProperties(properties) { if (Number.isFinite(properties.fps) && properties.fps > 0) window.rhineWallpaperHost.fps = properties.fps; }, setPaused(paused) { window.rhineWallpaperHost.paused = !!paused; window.dispatchEvent(new Event("rhine-wallpaper-pause")); }, }; // A normal HTTP preview has no native property callback. The actual file-based // wallpaper must wait for the host, regardless of how late its callback arrives. if (location.protocol !== "file:" && typeof window.wallpaperRegisterAudioListener !== "function") setTimeout(() => resolveInitialWallpaperProperties(), 0); // Register immediately: the host may deliver media before the module is ready. window.rhineWallpaperMedia = {}; window.rhineWallpaperSpectrum = { samples: [], time: 0 }; if (typeof window.wallpaperRegisterAudioListener === "function") { window.wallpaperRegisterAudioListener(function wallpaperAudioListener(samples) { if (!samples || samples.length !== 128) return; window.rhineWallpaperSpectrum = { samples: Array.from(samples, function (value) { return Number.isFinite(value) ? Math.max(0, Math.min(1, value)) : 0; }), time: performance.now() / 1000, }; }); } for (const kind of ["Status", "Properties", "Thumbnail", "Playback", "Timeline"]) { const register = window["wallpaperRegisterMedia" + kind + "Listener"]; if (typeof register === "function") register(function (event) { window.rhineWallpaperMedia[kind.toLowerCase()] = event; // These are independent change-only channels, not a track snapshot. // A player may send artwork/timeline before text, or reuse the same art // across tracks without another thumbnail callback. Only their own events // can replace/clear those values; a text update must not erase them. if (kind === "Playback") { const constants = window.wallpaperMediaIntegration || {}; window.rhineWallpaperMedia.playing = event.state === (constants.PLAYBACK_PLAYING ?? constants.playback?.PLAYING ?? 1); } window.dispatchEvent(new Event("rhine-wallpaper-media")); }); }