dev@40: /** dev@40: * Created by lucas on 01/12/2016. dev@40: */ dev@40: dev@72: import {EmscriptenProxy, ListRequest, ListResponse} from 'piper'; dev@72: import { dev@72: PiperSimpleClient, SimpleRequest, dev@72: SimpleResponse dev@72: } from 'piper/HigherLevelUtilities'; dev@44: import { VampExamplePlugins } from 'piper/ext/VampExamplePluginsModule'; dev@72: import {AvailableLibraries} from "./feature-extraction.service"; dev@44: dev@40: // TODO TypeScript has a .d.ts file for webworkers, but for some reason it clashes with the typings for dom and causes compiler errors dev@40: interface WorkerGlobalScope { dev@40: onmessage: (this: this, ev: MessageEvent) => any; dev@40: postMessage(data: any): void; dev@72: importScripts(uri: string): void; dev@40: } dev@40: dev@40: interface MessageEvent { dev@40: readonly data: any; dev@40: } dev@40: dev@72: type LibraryUri = string; dev@72: type LibraryKey = string; dev@72: dev@72: interface Message { dev@72: method: string; dev@72: params: any; dev@72: } dev@72: dev@72: type RequireJs = (libs: string[], callback: (...libs: any[]) => void) => void; dev@72: dev@40: export default class FeatureExtractionWorker { dev@40: private workerScope: WorkerGlobalScope; dev@75: private clients: Map; dev@72: private remoteLibraries: Map; dev@40: dev@72: constructor(workerScope: WorkerGlobalScope, private requireJs: RequireJs) { dev@40: this.workerScope = workerScope; dev@72: this.clients = new Map(); dev@72: this.remoteLibraries = new Map(); dev@72: this.clients.set( dev@72: 'vamp-example-plugins', dev@72: new PiperSimpleClient(new EmscriptenProxy(VampExamplePlugins())) dev@72: ); dev@72: dev@44: this.workerScope.onmessage = (ev: MessageEvent) => { dev@64: const sendResponse = (result) => { dev@64: this.workerScope.postMessage({ dev@64: method: ev.data.method, dev@64: result: result dev@64: }); dev@64: }; dev@44: switch (ev.data.method) { dev@44: case 'list': dev@72: this.list(ev.data.params) dev@72: .then(sendResponse) dev@72: .catch(err => console.error(err)); // TODO handle error dev@47: break; dev@47: case 'process': dev@72: this.process(ev.data.params) dev@72: .then(sendResponse) dev@72: .catch(err => console.error(err)); // TODO handle error dev@62: break; dev@62: case 'collect': dev@72: this.collect(ev.data.params) dev@72: .then(sendResponse) dev@72: .catch(err => console.error(err)); // TODO handle error dev@72: break; dev@72: case 'import': dev@72: // this.workerScope.importScripts(ev.data.params); dev@72: const key: LibraryKey = ev.data.params; dev@72: if (this.remoteLibraries.has(key)) { dev@72: this.requireJs([this.remoteLibraries.get(key)], (plugin) => { dev@72: this.clients.set( dev@72: key, dev@72: new PiperSimpleClient(new EmscriptenProxy(plugin.createLibrary())) dev@72: ); // TODO won't always be an emscripten module dev@72: this.list({}).then(sendResponse); dev@72: }); dev@72: } else { dev@72: console.error('Non registered library key.'); // TODO handle error dev@72: } dev@72: break; dev@72: case 'addRemoteLibraries': // TODO rename dev@72: const available: AvailableLibraries = ev.data.params; dev@72: Object.keys(available).forEach(key => { dev@72: this.remoteLibraries.set(key, available[key]); dev@72: }); dev@44: } dev@44: }; dev@40: } dev@44: dev@72: private list(request: ListRequest): Promise { dev@72: // TODO actually pay attention to ListRequest dev@72: return Promise.all([...this.clients.values()].map(client => client.list({}))) dev@72: .then(allAvailable => { dev@72: return { dev@72: available: allAvailable.reduce( dev@72: (all, current) => all.concat(current.available), dev@72: [] dev@72: ) dev@72: }; dev@72: }); dev@72: } dev@72: dev@72: // TODO reduce dupe dev@72: private process(request: SimpleRequest): Promise { dev@72: const key: LibraryKey = request.key.split(':')[0]; dev@72: const client: PiperSimpleClient = this.clients.get(key); dev@72: return client ? client.process(request) : Promise.reject("Invalid plugin library key."); dev@72: } dev@72: dev@72: private collect(request: SimpleRequest): Promise { dev@72: const key: LibraryKey = request.key.split(':')[0]; dev@72: const client: PiperSimpleClient = this.clients.get(key); dev@72: return client ? client.collect(request) : Promise.reject("Invalid plugin library key."); dev@72: } dev@40: }