148 lines
3.2 KiB
JavaScript

let _id = 0;
class WorkerAudio {
id = ++_id;
callbacks = {};
get src() {
return this._src;
}
set src(str) {
if (this._src !== str) {
this._src = str;
audioWorkerAdapter.call(this.id, 4, str);
}
}
_src = "";
get loop() {
return this._loop;
}
set loop(v) {
if (this._loop !== v) {
this._loop = v;
audioWorkerAdapter.call(this.id, 5, v);
}
}
_loop = false;
get volume() {
return this._volume;
}
set volume(v) {
if (this._volume !== v) {
this._volume = v;
audioWorkerAdapter.call(this.id, 6, v);
}
}
_volume = 1;
// 只读,从 Worker 单向同步值,由于是异步的,部分值会先模拟
duration = 0;
currentTime = 0;
paused = true;
constructor() {
audioWorkerAdapter.create(this);
}
play() {
this.paused = false;
audioWorkerAdapter.call(this.id, 0, null);
}
pause() {
this.paused = true;
audioWorkerAdapter.call(this.id, 1, null);
}
seek(position) {
this.paused = false;
this.currentTime = position;
audioWorkerAdapter.call(this.id, 2, position);
}
stop() {
this.paused = true;
audioWorkerAdapter.call(this.id, 3, null);
}
destroy() {
this.paused = true;
audioWorkerAdapter.destroy(this.id);
}
}
[
"Canplay",
"Ended",
"Error",
"Pause",
"Play",
"Seeked",
"Seeking",
"Stop",
"TimeUpdate",
"Waiting",
].forEach(name => {
WorkerAudio.prototype["on" + name] = function (callback) {
audioWorkerAdapter.on(this.id, name, callback);
};
WorkerAudio.prototype["off" + name] = function (callback) {
audioWorkerAdapter.off(this.id, name, callback);
};
});
var audioWorkerAdapter = {
audios: {},
create(audio) {
this.audios[audio.id] = audio;
worker.audio.create([audio.id]);
},
call(id, type, arg) {
worker.audio.call([id, type, arg]);
},
on(id, type, callback) {
this.audios[id].callbacks[type] = callback;
worker.audio.on([id, type]);
},
off(id, type, callback) {
delete this.audios[id].callbacks[type];
worker.audio.off([id, type]);
},
onCallback(args, cmdId, callback) {
const id = args[0];
const type = args[1];
const data = args[2];
this.audios[id].callbacks[type](data);
},
onUpdate(args, cmdId, callback) {
// struct: [id, duration, currentTime, paused, ...id2, duration2]
const infos = args[0];
for (let i = 0; i < infos.length; i += 4) {
const id = infos[i];
const duration = infos[i + 1];
const currentTime = infos[i + 2];
const paused = infos[i + 3];
const audio = this.audios[id];
audio.duration = duration;
audio.currentTime = currentTime;
audio.paused = paused;
}
},
destroy(id) {
worker.audio.destroy([id]);
delete this.audios[id];
},
};
globalThis.WorkerAudio = WorkerAudio;
module.exports = audioWorkerAdapter;