mirror of
https://github.com/captbaritone/webamp.git
synced 2026-07-28 12:36:35 +00:00
add more maki objects and functions for corner amp to work (#826)
* add more maki objects and functions for corner amp to work * fix functions to lower case / add unimplemented warning
This commit is contained in:
parent
6454952812
commit
cc386e05ae
16 changed files with 273 additions and 48 deletions
|
|
@ -7,33 +7,6 @@ const System = require("./runtime/System");
|
|||
const runtime = require("./runtime");
|
||||
const interpret = require("./maki-interpreter/interpreter");
|
||||
|
||||
// const runtime = require("./maki-interpreter/runtime");
|
||||
// const System = require("./maki-interpreter/runtime/System");
|
||||
// const interpret = require("./maki-interpreter/interpreter");
|
||||
|
||||
const IGNORE_IDS = new Set([
|
||||
// The maki script shows/hides these depending on which corner you are in
|
||||
"main2",
|
||||
"main3",
|
||||
"main4",
|
||||
"Title2",
|
||||
"Title3",
|
||||
"Title4",
|
||||
"mask2",
|
||||
"mask3",
|
||||
"mask4",
|
||||
"placeholder", // This looks like something related to an EQ window
|
||||
"Scaler",
|
||||
"toggle",
|
||||
"presets",
|
||||
"auto",
|
||||
// These need the maki script to get sized
|
||||
"volumethumb",
|
||||
"seekfull",
|
||||
"seek1",
|
||||
"Repeat",
|
||||
]);
|
||||
|
||||
const SkinContext = React.createContext(null);
|
||||
|
||||
async function getSkin() {
|
||||
|
|
@ -49,6 +22,26 @@ async function getSkin() {
|
|||
return await initialize(zip, skinXml);
|
||||
}
|
||||
|
||||
function Container(props) {
|
||||
const { id, children, default_x, default_y, default_visible } = props;
|
||||
const style = {
|
||||
position: "absolute",
|
||||
};
|
||||
if (default_x !== undefined) {
|
||||
style.left = Number(default_x);
|
||||
}
|
||||
if (default_y !== undefined) {
|
||||
style.top = Number(default_y);
|
||||
}
|
||||
if (default_visible !== undefined) {
|
||||
style.display = default_visible ? "block" : "none";
|
||||
}
|
||||
return <div
|
||||
data-node-type="container"
|
||||
data-node-id={id}
|
||||
style={style}>{children}</div>;
|
||||
}
|
||||
|
||||
function Layout({
|
||||
id,
|
||||
background,
|
||||
|
|
@ -105,13 +98,25 @@ function Layer({ id, image, children, x, y }) {
|
|||
if (y !== undefined) {
|
||||
params.top = Number(y);
|
||||
}
|
||||
if (img.x !== undefined) {
|
||||
params.backgroundPositionX = -Number(img.x);
|
||||
}
|
||||
if (img.y !== undefined) {
|
||||
params.backgroundPositionY = -Number(img.y);
|
||||
}
|
||||
if (img.w !== undefined) {
|
||||
params.width = Number(img.w);
|
||||
}
|
||||
if (img.h !== undefined) {
|
||||
params.height = Number(img.h);
|
||||
}
|
||||
return (
|
||||
<>
|
||||
<img
|
||||
data-node-type="Layer"
|
||||
data-node-id={id}
|
||||
src={img.imgUrl}
|
||||
style={Object.assign({ position: "absolute" }, params)}
|
||||
style={{ position: "absolute", ...params }}
|
||||
/>
|
||||
{children}
|
||||
</>
|
||||
|
|
@ -189,6 +194,7 @@ function Group(props) {
|
|||
}
|
||||
|
||||
const NODE_NAME_TO_COMPONENT = {
|
||||
container: Container,
|
||||
layout: Layout,
|
||||
layer: Layer,
|
||||
button: Button,
|
||||
|
|
@ -200,9 +206,6 @@ const NODE_NAME_TO_COMPONENT = {
|
|||
function XmlNode({ node }) {
|
||||
const attributes = node.xmlNode.attributes;
|
||||
const name = node.xmlNode.name;
|
||||
if (attributes && IGNORE_IDS.has(attributes.id)) {
|
||||
return null;
|
||||
}
|
||||
if (name == null || name === "groupdef") {
|
||||
// name is null is likely a comment
|
||||
return null;
|
||||
|
|
@ -210,7 +213,7 @@ function XmlNode({ node }) {
|
|||
const Component = NODE_NAME_TO_COMPONENT[name];
|
||||
const childNodes = node.children || [];
|
||||
const children = childNodes.map((childNode, i) => (
|
||||
<XmlNode key={i} node={childNode} />
|
||||
childNode.visible && <XmlNode key={i} node={childNode} />
|
||||
));
|
||||
if (Component == null) {
|
||||
console.warn("Unknown node type", name);
|
||||
|
|
@ -238,7 +241,7 @@ function App() {
|
|||
if (node.xmlNode.file.endsWith("standardframe.maki")) {
|
||||
break;
|
||||
}
|
||||
const scriptGroup = Utils.findParentNodeOfType(node, ["group", "WinampAbstractionLayer"]);
|
||||
const scriptGroup = Utils.findParentNodeOfType(node, ["group", "WinampAbstractionLayer", "WasabiXML"]);
|
||||
const system = new System(scriptGroup);
|
||||
await interpret({ runtime, data: node.xmlNode.script, system, log: false });
|
||||
return node;
|
||||
|
|
@ -256,6 +259,7 @@ function App() {
|
|||
return <h1>Loading...</h1>;
|
||||
}
|
||||
const { root, registry } = data;
|
||||
|
||||
return (
|
||||
<SkinContext.Provider value={registry.images}>
|
||||
<XmlNode node={root} />
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ function quote(str) {
|
|||
export default function Variable({ variable }) {
|
||||
let type = "UNKOWN";
|
||||
switch (variable.typeName) {
|
||||
case "OBJECT":
|
||||
case "OBJECT": {
|
||||
const obj = runtime[variable.type];
|
||||
if (obj == null) {
|
||||
type = "Unknown object";
|
||||
|
|
@ -15,6 +15,16 @@ export default function Variable({ variable }) {
|
|||
type = obj.getclassname();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "SUBCLASS": {
|
||||
const obj = runtime[variable.type.type];
|
||||
if (obj == null) {
|
||||
type = "Unknown object";
|
||||
} else {
|
||||
type = obj.getClassName();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "STRING": {
|
||||
const value = variable.getValue();
|
||||
return `${variable.typeName}(${value == null ? "NULL" : quote(value)})`;
|
||||
|
|
|
|||
|
|
@ -2,9 +2,13 @@ import * as Utils from "./utils";
|
|||
const MakiObject = require("./runtime/MakiObject");
|
||||
const WinampAbstractionLayer = require("./runtime/WinampAbstractionLayer");
|
||||
const Layout = require('./runtime/Layout');
|
||||
const Layer = require('./runtime/Layer');
|
||||
const Container = require('./runtime/Container');
|
||||
const Group = require("./runtime/Group");
|
||||
const Button = require("./runtime/Button");
|
||||
const ToggleButton = require("./runtime/ToggleButton");
|
||||
const Text = require("./runtime/Text");
|
||||
const Status = require("./runtime/Status");
|
||||
|
||||
function splitValues(str) {
|
||||
return str.split(",").map(parseFloat);
|
||||
|
|
@ -144,7 +148,7 @@ const parsers = {
|
|||
return new MakiObject(node, parent);
|
||||
},
|
||||
color: noop,
|
||||
layer: noop,
|
||||
layer: (node, parent) => new Layer(node, parent),
|
||||
layoutstatus: noop,
|
||||
hideobject: noop,
|
||||
button: (node, parent) => new Button(node, parent),
|
||||
|
|
@ -199,10 +203,9 @@ const parsers = {
|
|||
},
|
||||
truetypefont: noop,
|
||||
component: noop,
|
||||
text: noop,
|
||||
layer: noop,
|
||||
togglebutton: noop,
|
||||
status: noop,
|
||||
text: (node, parent) => new Text(node, parent),
|
||||
togglebutton: (node, parent) => new ToggleButton(node, parent),
|
||||
status: (node, parent) => new Status(node, parent),
|
||||
slider: noop,
|
||||
bitmapfont: noop,
|
||||
vis: noop,
|
||||
|
|
@ -221,7 +224,6 @@ const parsers = {
|
|||
nstatesbutton: noop,
|
||||
songticker: noop,
|
||||
menu: noop,
|
||||
status: noop,
|
||||
albumart: noop,
|
||||
playlistplus: noop,
|
||||
async script(node, parent, registry, zip) {
|
||||
|
|
|
|||
|
|
@ -138,6 +138,9 @@ function* interpret(start, program, stack = []) {
|
|||
methodName = methodName.toLowerCase();
|
||||
|
||||
const klass = classes[classesOffset];
|
||||
if (!klass) {
|
||||
throw new Error("Need to add a missing class to runtime");
|
||||
}
|
||||
// This is a bit awkward. Because the variables are stored on the stack
|
||||
// before the object, we have to find the number of arguments without
|
||||
// actually having access to the object instance.
|
||||
|
|
@ -145,10 +148,12 @@ function* interpret(start, program, stack = []) {
|
|||
|
||||
const methodArgs = [];
|
||||
while (argCount--) {
|
||||
methodArgs.push(stack.pop().getValue());
|
||||
const a = stack.pop();
|
||||
const aValue = a instanceof Variable ? a.getValue() : a;
|
||||
methodArgs.push(aValue);
|
||||
}
|
||||
const variable = stack.pop();
|
||||
const obj = variable.getValue();
|
||||
const obj = variable instanceof Variable ? variable.getValue() : variable;
|
||||
stack.push(obj[methodName](...methodArgs));
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,12 @@
|
|||
const MakiObject = require("./MakiObject");
|
||||
const { findDescendantByTypeAndId } = require("../utils");
|
||||
const { findDescendantByTypeAndId, unimplementedWarning } = require("../utils");
|
||||
|
||||
class GuiObject extends MakiObject {
|
||||
constructor(node, parent) {
|
||||
super(node, parent);
|
||||
|
||||
this.visible = true;
|
||||
}
|
||||
/**
|
||||
* getclassname()
|
||||
*
|
||||
|
|
@ -14,6 +19,10 @@ class GuiObject extends MakiObject {
|
|||
findobject(id) {
|
||||
return findDescendantByTypeAndId(this, null, id);
|
||||
}
|
||||
getobject(id) {
|
||||
// Not sure this is correct, but it is my understanding this is just an alias
|
||||
return this.findobject(id);
|
||||
}
|
||||
init(newRoot) {
|
||||
newRoot.js_addChild(this);
|
||||
return this;
|
||||
|
|
@ -32,6 +41,36 @@ class GuiObject extends MakiObject {
|
|||
getparent() {
|
||||
return this.parent;
|
||||
}
|
||||
|
||||
show() {
|
||||
this.visible = true;
|
||||
}
|
||||
|
||||
hide() {
|
||||
this.visible = false;
|
||||
}
|
||||
|
||||
gettop() {
|
||||
unimplementedWarning('gettop');
|
||||
return 5;
|
||||
}
|
||||
|
||||
getheight() {
|
||||
unimplementedWarning('getheight');
|
||||
return 100;
|
||||
}
|
||||
|
||||
getwidth() {
|
||||
unimplementedWarning('getwidth');
|
||||
return 100;
|
||||
}
|
||||
|
||||
resize(x, y, w, h) {
|
||||
this.xmlNode.attributes.x = x;
|
||||
this.xmlNode.attributes.y = y;
|
||||
this.xmlNode.attributes.w = w;
|
||||
this.xmlNode.attributes.h = h;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = GuiObject;
|
||||
|
|
|
|||
15
experiments/modern/src/runtime/Layer.js
Normal file
15
experiments/modern/src/runtime/Layer.js
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
const GuiObject = require("./GuiObject");
|
||||
|
||||
class Layer extends GuiObject {
|
||||
/**
|
||||
* getclassname()
|
||||
*
|
||||
* Returns the class name for the object.
|
||||
* @ret The class name.
|
||||
*/
|
||||
static getclassname() {
|
||||
return "Layer";
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Layer;
|
||||
|
|
@ -14,6 +14,15 @@ class Layout extends GuiObject {
|
|||
getcontainer() {
|
||||
return findParentNodeOfType(this, ["container"]);;
|
||||
}
|
||||
|
||||
resize(x, y, w, h) {
|
||||
this.xmlNode.attributes.x = x;
|
||||
this.xmlNode.attributes.y = y;
|
||||
this.xmlNode.attributes.minimum_w = w;
|
||||
this.xmlNode.attributes.maximum_w = w;
|
||||
this.xmlNode.attributes.minimum_h = h;
|
||||
this.xmlNode.attributes.maximum_h = h;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Layout;
|
||||
|
|
|
|||
15
experiments/modern/src/runtime/List.js
Normal file
15
experiments/modern/src/runtime/List.js
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
const GuiObject = require("./GuiObject");
|
||||
|
||||
class List extends GuiObject {
|
||||
/**
|
||||
* getclassname()
|
||||
*
|
||||
* Returns the class name for the object.
|
||||
* @ret The class name.
|
||||
*/
|
||||
static getclassname() {
|
||||
return "List";
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = List;
|
||||
28
experiments/modern/src/runtime/PopupMenu.js
Normal file
28
experiments/modern/src/runtime/PopupMenu.js
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
const GuiObject = require("./GuiObject");
|
||||
const { unimplementedWarning } = require("../utils");
|
||||
|
||||
class PopupMenu extends GuiObject {
|
||||
/**
|
||||
* getclassname()
|
||||
*
|
||||
* Returns the class name for the object.
|
||||
* @ret The class name.
|
||||
*/
|
||||
static getclassname() {
|
||||
return "PopupMenu";
|
||||
}
|
||||
addcommand(txt, id, checked, disabled) {
|
||||
unimplementedWarning('addcommand');
|
||||
}
|
||||
addseparator() {
|
||||
unimplementedWarning('addseparator');
|
||||
}
|
||||
checkcommand(id, check) {
|
||||
unimplementedWarning('checkcommand');
|
||||
}
|
||||
popatmouse() {
|
||||
unimplementedWarning('popatmouse');
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = PopupMenu;
|
||||
15
experiments/modern/src/runtime/Slider.js
Normal file
15
experiments/modern/src/runtime/Slider.js
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
const GuiObject = require("./GuiObject");
|
||||
|
||||
class Slider extends GuiObject {
|
||||
/**
|
||||
* getClassName()
|
||||
*
|
||||
* Returns the class name for the object.
|
||||
* @ret The class name.
|
||||
*/
|
||||
static getClassName() {
|
||||
return "Slider";
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Slider;
|
||||
15
experiments/modern/src/runtime/Status.js
Normal file
15
experiments/modern/src/runtime/Status.js
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
const GuiObject = require("./GuiObject");
|
||||
|
||||
class Status extends GuiObject {
|
||||
/**
|
||||
* getclassname()
|
||||
*
|
||||
* Returns the class name for the object.
|
||||
* @ret The class name.
|
||||
*/
|
||||
static getclassname() {
|
||||
return "Status";
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Status;
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
const Group = require("./Group");
|
||||
const MakiObject = require("./MakiObject");
|
||||
const { findDescendantByTypeAndId } = require("../utils");
|
||||
const { findDescendantByTypeAndId, unimplementedWarning } = require("../utils");
|
||||
|
||||
class System extends MakiObject {
|
||||
constructor(scriptGroup = new Group()) {
|
||||
|
|
@ -37,14 +37,38 @@ class System extends MakiObject {
|
|||
return "5.666";
|
||||
}
|
||||
gettoken(str, separator, tokennum) {
|
||||
unimplementedWarning('gettoken');
|
||||
return "Some Token String";
|
||||
}
|
||||
getparam() {
|
||||
unimplementedWarning('getparam');
|
||||
return "Some String";
|
||||
}
|
||||
messagebox(message, msgtitle, flag, notanymoreId) {
|
||||
console.log({ message, msgtitle, flag, notanymoreId });
|
||||
}
|
||||
integertostring(value) {
|
||||
return value.toString();
|
||||
}
|
||||
getprivateint(section, item, defvalue) {
|
||||
unimplementedWarning('getprivateint');
|
||||
return defvalue;
|
||||
}
|
||||
setprivateint(section, item, defvalue) {
|
||||
unimplementedWarning('setprivateint');
|
||||
}
|
||||
getleftvumeter() {
|
||||
unimplementedWarning('getleftvumeter');
|
||||
return 0.5;
|
||||
}
|
||||
getrightvumeter() {
|
||||
unimplementedWarning('getrightvumeter');
|
||||
return 0.5;
|
||||
}
|
||||
getvolume() {
|
||||
unimplementedWarning('getvolume');
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = System;
|
||||
|
|
|
|||
15
experiments/modern/src/runtime/Text.js
Normal file
15
experiments/modern/src/runtime/Text.js
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
const GuiObject = require("./GuiObject");
|
||||
|
||||
class Text extends GuiObject {
|
||||
/**
|
||||
* getclassname()
|
||||
*
|
||||
* Returns the class name for the object.
|
||||
* @ret The class name.
|
||||
*/
|
||||
static getclassname() {
|
||||
return "Text";
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Text;
|
||||
15
experiments/modern/src/runtime/ToggleButton.js
Normal file
15
experiments/modern/src/runtime/ToggleButton.js
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
const Button = require("./Button");
|
||||
|
||||
class ToggleButton extends Button {
|
||||
/**
|
||||
* getclassname()
|
||||
*
|
||||
* Returns the class name for the object.
|
||||
* @ret The class name.
|
||||
*/
|
||||
static getclassname() {
|
||||
return "ToggleButton";
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = ToggleButton;
|
||||
|
|
@ -1,24 +1,31 @@
|
|||
const System = require("./System");
|
||||
const Button = require("./Button");
|
||||
const ToggleButton = require("./ToggleButton");
|
||||
const Group = require("./Group");
|
||||
const Layout = require('./Layout');
|
||||
const Layer = require('./Layer');
|
||||
const PopupMenu = require('./PopupMenu');
|
||||
const List = require('./List');
|
||||
const Status = require('./Status');
|
||||
const Text = require('./Text');
|
||||
const Container = require('./Container');
|
||||
const GuiObject = require("./GuiObject");
|
||||
const MakiObject = require("./MakiObject");
|
||||
|
||||
class PopupMenu {}
|
||||
class List {}
|
||||
|
||||
const runtime = {
|
||||
"516549714a510d87b5a6e391e7f33532": MakiObject,
|
||||
d6f50f6449b793fa66baf193983eaeef: System,
|
||||
"45be95e5419120725fbb5c93fd17f1f9": Group,
|
||||
"4ee3e1994becc636bc78cd97b028869c": GuiObject,
|
||||
"698eddcd4fec8f1e44f9129b45ff09f9": Button,
|
||||
b4dccfff4bcc81fe0f721b96ff0fbed5: ToggleButton,
|
||||
f4787af44ef7b2bb4be7fb9c8da8bea9: PopupMenu,
|
||||
e90dc47b4ae7840d0b042cb0fcf775d2: Container,
|
||||
"60906d4e482e537e94cc04b072568861": Layout,
|
||||
b2023ab54ba1434d6359aebec6f30375: List,
|
||||
"5ab9fa1545579a7d5765c8aba97cc6a6": Layer,
|
||||
"0f08c9404b23af39c4b8f38059bb7e8f": Status,
|
||||
efaa867241fa310ea985dcb74bcb5b52: Text,
|
||||
};
|
||||
|
||||
module.exports = runtime;
|
||||
|
|
|
|||
|
|
@ -97,6 +97,10 @@ export async function inlineIncludes(xml, zip) {
|
|||
});
|
||||
}
|
||||
|
||||
export function unimplementedWarning(name) {
|
||||
console.warn(`Executing unimplemented MAKI function: ${name}`);
|
||||
}
|
||||
|
||||
// Operations on trees
|
||||
export function findParentNodeOfType(node, type) {
|
||||
let n = node;
|
||||
|
|
@ -114,10 +118,13 @@ export function findDescendantByTypeAndId(node, type, id) {
|
|||
return null;
|
||||
}
|
||||
|
||||
const idLC = id.toLowerCase();
|
||||
for(let i = 0; i < node.children.length; i++) {
|
||||
const child = node.children[i];
|
||||
if ((!type || child.xmlNode.name === type) &&
|
||||
(child.xmlNode.attributes !== undefined && child.xmlNode.attributes.id === id)) {
|
||||
(child.xmlNode.attributes !== undefined &&
|
||||
child.xmlNode.attributes.id !== undefined &&
|
||||
child.xmlNode.attributes.id.toLowerCase() === idLC)) {
|
||||
return child;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue