mirror of
https://codeberg.org/vlw/monkeydo.git
synced 2025-09-13 15:53:40 +02:00
0.2.1
- Replaced `eval()` with namespaced method calls. - Created a class-scoped listener for incoming messages from worker - Renamed TaskManager to MonkeyManager
This commit is contained in:
parent
6991138f85
commit
4765f9dc17
4 changed files with 107 additions and 83 deletions
36
Monkeydo.mjs
36
Monkeydo.mjs
|
@ -1,10 +1,10 @@
|
||||||
import { default as MonkeyWorker } from "./worker/TaskManager.mjs";
|
import { default as MonkeyWorker } from "./worker/MonkeyManager.mjs";
|
||||||
|
|
||||||
export default class Monkeydo extends MonkeyWorker {
|
export default class Monkeydo extends MonkeyWorker {
|
||||||
constructor(manifest = false) {
|
constructor(methods = {},manifest = false) {
|
||||||
super();
|
super(methods);
|
||||||
this.monkeydo = {
|
this.monkeydo = {
|
||||||
version: "0.2.0",
|
version: "0.2.1",
|
||||||
debugLevel: 0,
|
debugLevel: 0,
|
||||||
// Flag if debugging is enabled, regardless of level
|
// Flag if debugging is enabled, regardless of level
|
||||||
get debug() {
|
get debug() {
|
||||||
|
@ -32,26 +32,20 @@ export default class Monkeydo extends MonkeyWorker {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
debug(...attachment) {
|
debug(...attachments) {
|
||||||
if(this.monkeydo.debug) {
|
if(this.monkeydo.debug) {
|
||||||
console.warn("-- Monkeydo debug -->",attachment);
|
console.warn("-- Monkeydo debug -->",attachments);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
play() {
|
// Loop playback; -1 or false = infinite
|
||||||
this.worker.postMessage(["SET_PLAYING",true]);
|
loop(times = -1) {
|
||||||
this.worker.addEventListener("message",message => eval(message.data));
|
// Typecast boolean to left shifted integer;
|
||||||
}
|
if(typeof times === "boolean") {
|
||||||
|
times = times ? -1 : 0;
|
||||||
pause() {
|
|
||||||
this.worker.postMessage(["SET_PLAYING",false]);
|
|
||||||
}
|
|
||||||
|
|
||||||
loop(times) {
|
|
||||||
if(!times || times === "infinite") {
|
|
||||||
times = -1;
|
|
||||||
}
|
}
|
||||||
|
times = times < 0 ? -1 : times;
|
||||||
this.setFlag("loop",times);
|
this.setFlag("loop",times);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -111,10 +105,6 @@ export default class Monkeydo extends MonkeyWorker {
|
||||||
|
|
||||||
// Hand over the loaded manifest to the MonkeyWorker task manager
|
// Hand over the loaded manifest to the MonkeyWorker task manager
|
||||||
const monkey = this.giveManifest();
|
const monkey = this.giveManifest();
|
||||||
monkey.then(() => this.play())
|
this.play();
|
||||||
.catch(error => {
|
|
||||||
this.debug(error);
|
|
||||||
throw new Error(errorPrefix + "Failed to post manifest to worker thread");
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -11,7 +11,7 @@ class Monkey {
|
||||||
loop: 0, // Loop n times; <0 = infinite
|
loop: 0, // Loop n times; <0 = infinite
|
||||||
}
|
}
|
||||||
|
|
||||||
this.i = 0;
|
this.i = 0; // Manifest iterator index
|
||||||
this.queue = {
|
this.queue = {
|
||||||
task: null,
|
task: null,
|
||||||
next: null
|
next: null
|
||||||
|
@ -20,10 +20,9 @@ class Monkey {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse task components and send them to main thread
|
// Parse task components and send them to main thread
|
||||||
run(data) {
|
run(task) {
|
||||||
this.i++; // Advance index
|
this.i++; // Advance index
|
||||||
postMessage(data);
|
postMessage(["TASK",task]);
|
||||||
console.log(this.i);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Interrupt timeout and put monkey to sleep
|
// Interrupt timeout and put monkey to sleep
|
||||||
|
@ -36,6 +35,7 @@ class Monkey {
|
||||||
}
|
}
|
||||||
|
|
||||||
play() {
|
play() {
|
||||||
|
// Stack playback as loops if flag is set
|
||||||
if(this.flags.playing) {
|
if(this.flags.playing) {
|
||||||
if(this.flags.stacking) {
|
if(this.flags.stacking) {
|
||||||
this.flags.loop++;
|
this.flags.loop++;
|
||||||
|
@ -49,9 +49,14 @@ class Monkey {
|
||||||
queueNext() {
|
queueNext() {
|
||||||
this.flags.playing = 1;
|
this.flags.playing = 1;
|
||||||
const data = this.data[this.i];
|
const data = this.data[this.i];
|
||||||
|
const task = {
|
||||||
|
wait: data[0],
|
||||||
|
func: data[1],
|
||||||
|
args: data.slice(2)
|
||||||
|
};
|
||||||
|
|
||||||
// Schedule the current task to run after the specified wait time
|
// Schedule the current task to run after the specified wait time
|
||||||
this.queue.task = setTimeout(() => this.run(data.do),data.wait);
|
this.queue.task = setTimeout(() => this.run(task),task.wait);
|
||||||
|
|
||||||
// We're out of tasks to schedule..
|
// We're out of tasks to schedule..
|
||||||
if(this.i >= this.dataLength) {
|
if(this.i >= this.dataLength) {
|
||||||
|
@ -62,13 +67,14 @@ class Monkey {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(this.flags.loop <= -1) {
|
// Decrement loop iterations if not infinite (negative int)
|
||||||
|
if(this.flags.loop > 0) {
|
||||||
this.flags.loop = this.flags.loop - 1;
|
this.flags.loop = this.flags.loop - 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Run this function again when the scheduled task will fire
|
// Run this function again when the scheduled task will fire
|
||||||
this.queue.next = setTimeout(() => this.queueNext(),data.wait);
|
this.queue.next = setTimeout(() => this.queueNext(),task.wait);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -82,20 +88,18 @@ onmessage = (message) => {
|
||||||
case "GIVE_MANIFEST":
|
case "GIVE_MANIFEST":
|
||||||
try {
|
try {
|
||||||
this.monkey = new Monkey(data);
|
this.monkey = new Monkey(data);
|
||||||
postMessage("OK");
|
postMessage(["RECEIVED_MANIFEST","OK"]);
|
||||||
}
|
}
|
||||||
catch(error) {
|
catch(error) {
|
||||||
postMessage(["MANIFEST_ERROR",error]);
|
postMessage(["RECEIVED_MANIFEST",error]);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// Set playstate
|
|
||||||
case "SET_PLAYING":
|
case "SET_PLAYING":
|
||||||
if(data === true) {
|
if(data === true) {
|
||||||
this.monkey.play();
|
this.monkey.play();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Treat data that isn't a TRUE boolean as an interrupt
|
|
||||||
this.monkey.interrupt();
|
this.monkey.interrupt();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -105,7 +109,6 @@ onmessage = (message) => {
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "SET_FLAG":
|
case "SET_FLAG":
|
||||||
console.log(data);
|
|
||||||
this.monkey.flags[data[0]] = data[1];
|
this.monkey.flags[data[0]] = data[1];
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
79
worker/MonkeyManager.mjs
Normal file
79
worker/MonkeyManager.mjs
Normal file
|
@ -0,0 +1,79 @@
|
||||||
|
// Task manager for Monkeydo dedicated workers
|
||||||
|
|
||||||
|
export default class MonkeyManager {
|
||||||
|
constructor(methods) {
|
||||||
|
// Object of scoped methods for this manifest
|
||||||
|
this.methods = {};
|
||||||
|
Object.assign(this.methods,methods);
|
||||||
|
|
||||||
|
// Get path of this file
|
||||||
|
let location = new URL(import.meta.url);
|
||||||
|
location = location.pathname.replace("MonkeyManager.mjs",""); // Get parent directory
|
||||||
|
|
||||||
|
// Spawn a dedicated worker for scheduling events from manifest
|
||||||
|
this.worker = new Worker(location + "Monkey.js");
|
||||||
|
this.worker.addEventListener("message",message => this.message(message));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get a status flag from the worker
|
||||||
|
async getFlag(flag) {
|
||||||
|
this.worker.postMessage(["GET_FLAG",flag]);
|
||||||
|
const response = await new Promise((resolve) => {
|
||||||
|
this.worker.addEventListener("message",message => resolve(message.data));
|
||||||
|
});
|
||||||
|
this.debug("GET_FLAG",flag,response);
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set a status flag for the worker
|
||||||
|
async setFlag(flag,value = 0) {
|
||||||
|
const flagExists = await this.getFlag(flag);
|
||||||
|
if(flagExists === null) {
|
||||||
|
this.debug(flagExists);
|
||||||
|
throw new Error("Flag does not not exist");
|
||||||
|
}
|
||||||
|
this.worker.postMessage(["SET_FLAG",[flag,value]]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call method from object and pass arguments
|
||||||
|
runTask(task) {
|
||||||
|
this.methods[task.func](...task.args);
|
||||||
|
}
|
||||||
|
|
||||||
|
play() {
|
||||||
|
this.worker.postMessage(["SET_PLAYING",true]);
|
||||||
|
}
|
||||||
|
|
||||||
|
pause() {
|
||||||
|
this.worker.postMessage(["SET_PLAYING",false]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pass manifest to worker and await response
|
||||||
|
async giveManifest() {
|
||||||
|
this.worker.postMessage(["GIVE_MANIFEST",this.manifest]);
|
||||||
|
|
||||||
|
const status = await new Promise((resolve,reject) => {
|
||||||
|
const ack = this.worker.addEventListener("message",message => {
|
||||||
|
if(message.data[0] !== "RECEIVED_MANIFEST") {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(message.data[1] !== "OK") {
|
||||||
|
reject(message.data);
|
||||||
|
}
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
this.worker.removeEventListener("message",ack);
|
||||||
|
});
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
message(message) {
|
||||||
|
const type = message.data[0] ? message.data[0] : message.data;
|
||||||
|
const data = message.data[1];
|
||||||
|
if(type !== "TASK") {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
this.runTask(data);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,48 +0,0 @@
|
||||||
// Task manager for Monkeydo dedicated workers
|
|
||||||
|
|
||||||
export default class TaskManager {
|
|
||||||
constructor() {
|
|
||||||
// Get path of this file
|
|
||||||
this.ready = false;
|
|
||||||
let location = new URL(import.meta.url);
|
|
||||||
location = location.pathname.replace("TaskManager.mjs",""); // Get parent directory
|
|
||||||
|
|
||||||
// Spawn a dedicated worker for scheduling events from manifest
|
|
||||||
this.worker = new Worker(location + "Monkey.js");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get a status flag from the worker
|
|
||||||
async getFlag(flag) {
|
|
||||||
this.worker.postMessage(["GET_FLAG",flag]);
|
|
||||||
const response = await new Promise((resolve) => {
|
|
||||||
this.worker.addEventListener("message",message => resolve(message.data));
|
|
||||||
});
|
|
||||||
return response;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set a status flag for the worker
|
|
||||||
async setFlag(flag,value = 0) {
|
|
||||||
const flagExists = await this.getFlag(flag);
|
|
||||||
if(!flagExists) {
|
|
||||||
this.debug(flagExists);
|
|
||||||
throw new Error("Flag does not not exist");
|
|
||||||
}
|
|
||||||
this.worker.postMessage(["SET_FLAG",[flag,value]]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Pass manifest to worker and await response
|
|
||||||
async giveManifest() {
|
|
||||||
this.worker.postMessage(["GIVE_MANIFEST",this.manifest]);
|
|
||||||
|
|
||||||
// Wait for the worker to install the manifest
|
|
||||||
const ack = await new Promise((resolve,reject) => {
|
|
||||||
this.worker.addEventListener("message",message => {
|
|
||||||
if(message.data !== "OK") {
|
|
||||||
reject(message.data);
|
|
||||||
}
|
|
||||||
resolve();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
return ack;
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Add table
Reference in a new issue