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:
jberg 2019-08-02 15:29:16 -07:00 committed by GitHub
parent 6454952812
commit cc386e05ae
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
16 changed files with 273 additions and 48 deletions

View file

@ -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} />

View file

@ -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)})`;

View file

@ -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) {

View file

@ -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;
}

View file

@ -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;

View 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;

View file

@ -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;

View 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;

View 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;

View 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;

View 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;

View file

@ -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;

View 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;

View 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;

View file

@ -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;

View file

@ -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;
}
}