diff --git a/packages/webamp-modern-2/src/UIRoot.ts b/packages/webamp-modern-2/src/UIRoot.ts index b2d1bb2a..ad6e4df0 100644 --- a/packages/webamp-modern-2/src/UIRoot.ts +++ b/packages/webamp-modern-2/src/UIRoot.ts @@ -188,7 +188,11 @@ export class UIRoot { return found ?? null; } - dispatch(action: string, param: string | null, actionTarget: string | null) { + dispatch( + action: string, + param: string | null | number, + actionTarget: string | null + ) { switch (action.toLowerCase()) { case "play": this.audio.play(); @@ -208,6 +212,9 @@ export class UIRoot { case "eject": this.audio.eject(); break; + case "seek": + this.audio.seekToPercent((param as number) / 255); + break; default: assume(false, `Unknown global action: ${action}`); } diff --git a/packages/webamp-modern-2/src/skin/AudioPlayer.ts b/packages/webamp-modern-2/src/skin/AudioPlayer.ts index 721bdcaf..9bc22d48 100644 --- a/packages/webamp-modern-2/src/skin/AudioPlayer.ts +++ b/packages/webamp-modern-2/src/skin/AudioPlayer.ts @@ -48,11 +48,19 @@ export class AudioPlayer { this._audio.currentTime = secs; } + seekToPercent(percent: number) { + this._audio.currentTime = this._audio.duration * percent; + } + // In seconds getCurrentTime(): number { return this._audio.currentTime; } + getCurrentTimePercent(): number { + return this._audio.currentTime / this._audio.duration; + } + onCurrentTimeChange(cb: () => void): () => void { const handler = () => cb(); this._audio.addEventListener("timeupdate", handler); @@ -62,6 +70,15 @@ export class AudioPlayer { return dispose; } + onSeek(cb: () => void): () => void { + const handler = () => cb(); + this._audio.addEventListener("seeked", handler); + const dispose = () => { + this._audio.removeEventListener("seeked", handler); + }; + return dispose; + } + // Current track length in seconds getLength(): number { return this._audio.duration; diff --git a/packages/webamp-modern-2/src/skin/makiClasses/Config.ts b/packages/webamp-modern-2/src/skin/makiClasses/Config.ts new file mode 100644 index 00000000..287c493e --- /dev/null +++ b/packages/webamp-modern-2/src/skin/makiClasses/Config.ts @@ -0,0 +1,10 @@ +import XmlObj from "../XmlObj"; +import ConfigItem from "./ConfigItem"; + +export default class Config extends XmlObj { + static GUID = "593dba224976d07771f452b90b405536"; + + newitem(itemName: string, itemGuid: string): ConfigItem { + return new ConfigItem(); + } +} diff --git a/packages/webamp-modern-2/src/skin/makiClasses/ConfigItem.ts b/packages/webamp-modern-2/src/skin/makiClasses/ConfigItem.ts new file mode 100644 index 00000000..8e10a605 --- /dev/null +++ b/packages/webamp-modern-2/src/skin/makiClasses/ConfigItem.ts @@ -0,0 +1,3 @@ +import XmlObj from "../XmlObj"; + +export default class ConfigItem extends XmlObj {} diff --git a/packages/webamp-modern-2/src/skin/makiClasses/Slider.ts b/packages/webamp-modern-2/src/skin/makiClasses/Slider.ts index bc2ab212..52e34eed 100644 --- a/packages/webamp-modern-2/src/skin/makiClasses/Slider.ts +++ b/packages/webamp-modern-2/src/skin/makiClasses/Slider.ts @@ -12,6 +12,7 @@ export default class Slider extends GuiObj { _thumb: string; _downThumb: string; _hoverThumb: string; + _action: string | null = null; _low: number; _high: number; _position: number = 0; @@ -100,6 +101,10 @@ export default class Slider extends GuiObj { // (int) Set the high-value boundary. Default is 255. this._high = num(value); break; + case "action": + // Undocumented on the Wiki + this._action = value; + break; default: return false; } @@ -115,6 +120,9 @@ export default class Slider extends GuiObj { UI_ROOT.vm.dispatch(this, "onsetposition", [ { type: "INT", value: newPos }, ]); + if (this._action) { + UI_ROOT.dispatch(this._action, this.getposition(), null); + } } _renderThumb() { diff --git a/packages/webamp-modern-2/src/skin/makiClasses/SystemObject.ts b/packages/webamp-modern-2/src/skin/makiClasses/SystemObject.ts index 4463b544..19d37b81 100644 --- a/packages/webamp-modern-2/src/skin/makiClasses/SystemObject.ts +++ b/packages/webamp-modern-2/src/skin/makiClasses/SystemObject.ts @@ -24,6 +24,11 @@ export default class SystemObject extends BaseObject { constructor(parsedScript: ParsedMaki) { super(); this._parsedScript = parsedScript; + UI_ROOT.audio.onSeek(() => { + UI_ROOT.vm.dispatch(this, "onseek", [ + { type: "INT", value: UI_ROOT.audio.getCurrentTimePercent() * 255 }, + ]); + }); } init() { diff --git a/packages/webamp-modern-2/src/skin/makiClasses/Text.ts b/packages/webamp-modern-2/src/skin/makiClasses/Text.ts index 890d5768..f92bb5ae 100644 --- a/packages/webamp-modern-2/src/skin/makiClasses/Text.ts +++ b/packages/webamp-modern-2/src/skin/makiClasses/Text.ts @@ -137,6 +137,11 @@ offsety - (int) Extra pixels to be added to or subtracted from the calculated x case "songname": this._displayValue = "Niente da Caprie (3"; break; + case "songtitle": + this._displayValue = "Niente da Caprie (3"; + break; + case "songbitrate": + case "songsamplerate": case "songinfo": this._displayValue = "112kbps stereo 44."; break; diff --git a/packages/webamp-modern-2/src/skin/parse.ts b/packages/webamp-modern-2/src/skin/parse.ts index 6893e15e..d24828b9 100644 --- a/packages/webamp-modern-2/src/skin/parse.ts +++ b/packages/webamp-modern-2/src/skin/parse.ts @@ -166,7 +166,8 @@ export default class SkinParser { case "wrapper": return this.traverseChildren(node); default: - throw new Error(`Unhandled XML node type: ${node.name}`); + console.warn(`Unhandled XML node type: ${node.name}`); + return; } } diff --git a/packages/webamp-modern-2/src/skin/resolver.ts b/packages/webamp-modern-2/src/skin/resolver.ts index c5afc68f..83a4f8a1 100644 --- a/packages/webamp-modern-2/src/skin/resolver.ts +++ b/packages/webamp-modern-2/src/skin/resolver.ts @@ -15,8 +15,12 @@ import Timer from "./makiClasses/Timer"; import Slider from "./makiClasses/Slider"; import Vis from "./makiClasses/Vis"; import GuiObj from "./makiClasses/GuiObj"; +import Config from "./makiClasses/Config"; +import ConfigItem from "./makiClasses/ConfigItem"; const CLASSES = [ + Config, + // ConfigItem, Button, SystemObject, Container,