mirror of
https://codeberg.org/vlw/monkeydo.git
synced 2025-09-13 15:53:40 +02:00
126 lines
No EOL
3 KiB
JavaScript
126 lines
No EOL
3 KiB
JavaScript
// Task manager for Monkeydo dedicated workers (monkeys)
|
|
|
|
import * as Comlink from "https://unpkg.com/comlink/dist/esm/comlink.mjs";
|
|
|
|
export default class MonkeyMaster {
|
|
constructor() {
|
|
this.comlink = null;
|
|
|
|
this.ready = false;
|
|
// Tasks will be queued here on runtime if the worker isn't ready
|
|
this.queue = {
|
|
_flags: [],
|
|
set flag(flag) {
|
|
this._flags.push(flag);
|
|
},
|
|
// Attempt to send all queued flags
|
|
sendAllFlags: () => {
|
|
// Copy flags and clear queue
|
|
const flags = [...this.queue._flags];
|
|
this.queue._flags = [];
|
|
flags.forEach(flag => this.setFlag(...flag));
|
|
}
|
|
};
|
|
}
|
|
|
|
// Import worker relative to this module
|
|
getWorkerPath() {
|
|
const name = "Monkey.js";
|
|
const url = new URL(import.meta.url);
|
|
|
|
// Replace pathname of this file with worker
|
|
const path = url.pathname.split("/");
|
|
path[path.length - 1] = name;
|
|
|
|
url.pathname = path.join("/");
|
|
return url.toString();
|
|
}
|
|
|
|
async init() {
|
|
// Spawn and wrap dedicated worker with Comlink
|
|
const worker = new Worker(this.getWorkerPath());
|
|
worker.addEventListener("message",event => {
|
|
if(event.data[0] !== "TASK") return;
|
|
this.do(event.data);
|
|
});
|
|
|
|
const Monkey = Comlink.wrap(worker);
|
|
this.comlink = await new Monkey();
|
|
|
|
// Wait for comlink to initialize proxy and send queued flags
|
|
return await new Promise((resolve,reject) => {
|
|
if(!this.comlink) reject("Failed to open proxy to worker");
|
|
|
|
this.ready = true;
|
|
this.queue.sendAllFlags();
|
|
resolve();
|
|
});
|
|
}
|
|
|
|
// Return a flag array index by name
|
|
flagStringToIndex(flag) {
|
|
const flags = [
|
|
"MANIFEST_LOADED",
|
|
"PLAYING"
|
|
];
|
|
|
|
|
|
// Translate string to index
|
|
if(typeof flag === "string" || flag < 0) {
|
|
flag = flags.indexOf(flag.toUpperCase());
|
|
if(flag < 0) return;
|
|
}
|
|
|
|
// Check that key is in bounds
|
|
if(flag < 0 || flags > flags.length - 1) {
|
|
throw new Error(`Array key '${flag}' out of range`);
|
|
}
|
|
return flag;
|
|
}
|
|
|
|
async getFlag(flag) {
|
|
const key = this.flagStringToIndex(flag);
|
|
return await this.comlink.flag(key);
|
|
}
|
|
|
|
// Set or queue worker runtime flag
|
|
async setFlag(flag,value) {
|
|
const key = this.flagStringToIndex(flag);
|
|
if(!this.ready) {
|
|
this.queue.flag = [key,value];
|
|
return;
|
|
}
|
|
|
|
// Tell worker to update flag by key
|
|
const update = await this.comlink.flag(key,value);
|
|
if(!update) {
|
|
this.queue.flag = [key,value];
|
|
}
|
|
return update;
|
|
}
|
|
|
|
// Load a Monkeydo manifest by URL or JSON string
|
|
async loadManifest(manifest) {
|
|
if(!this.ready) await this.init();
|
|
return await new Promise((resolve,reject) => {
|
|
let load = null;
|
|
try {
|
|
const url = new URL(manifest);
|
|
load = this.comlink.fetchManifest(url.toString());
|
|
}
|
|
catch {
|
|
load = this.comlink.loadManifest(manifest);
|
|
}
|
|
load.then(() => resolve())
|
|
.catch(() => reject("Failed to load manifest"));
|
|
});
|
|
}
|
|
|
|
// Start playback of a loaded manifest
|
|
async start() {
|
|
// Set playstate if no value is present already
|
|
const loop = await this.getFlag("playing");
|
|
if(loop < 1) await this.setFlag("playing",1);
|
|
return await this.comlink.next();
|
|
}
|
|
} |