dev@40
|
1 /**
|
dev@40
|
2 * Created by lucas on 01/12/2016.
|
dev@40
|
3 */
|
dev@40
|
4
|
dev@72
|
5 import {EmscriptenProxy, ListRequest, ListResponse} from 'piper';
|
dev@72
|
6 import {
|
dev@72
|
7 PiperSimpleClient, SimpleRequest,
|
dev@72
|
8 SimpleResponse
|
dev@72
|
9 } from 'piper/HigherLevelUtilities';
|
dev@44
|
10 import { VampExamplePlugins } from 'piper/ext/VampExamplePluginsModule';
|
dev@72
|
11 import {AvailableLibraries} from "./feature-extraction.service";
|
dev@44
|
12
|
dev@40
|
13 // 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
|
14 interface WorkerGlobalScope {
|
dev@40
|
15 onmessage: (this: this, ev: MessageEvent) => any;
|
dev@40
|
16 postMessage(data: any): void;
|
dev@72
|
17 importScripts(uri: string): void;
|
dev@40
|
18 }
|
dev@40
|
19
|
dev@40
|
20 interface MessageEvent {
|
dev@40
|
21 readonly data: any;
|
dev@40
|
22 }
|
dev@40
|
23
|
dev@72
|
24 type LibraryUri = string;
|
dev@72
|
25 type LibraryKey = string;
|
dev@72
|
26
|
dev@72
|
27 interface Message {
|
dev@72
|
28 method: string;
|
dev@72
|
29 params: any;
|
dev@72
|
30 }
|
dev@72
|
31
|
dev@72
|
32 type RequireJs = (libs: string[], callback: (...libs: any[]) => void) => void;
|
dev@72
|
33
|
dev@40
|
34 export default class FeatureExtractionWorker {
|
dev@40
|
35 private workerScope: WorkerGlobalScope;
|
dev@75
|
36 private clients: Map<LibraryKey, PiperSimpleClient>;
|
dev@72
|
37 private remoteLibraries: Map<LibraryKey, LibraryUri>;
|
dev@40
|
38
|
dev@72
|
39 constructor(workerScope: WorkerGlobalScope, private requireJs: RequireJs) {
|
dev@40
|
40 this.workerScope = workerScope;
|
dev@72
|
41 this.clients = new Map<LibraryKey, PiperSimpleClient>();
|
dev@72
|
42 this.remoteLibraries = new Map<LibraryKey, LibraryUri>();
|
dev@72
|
43 this.clients.set(
|
dev@72
|
44 'vamp-example-plugins',
|
dev@72
|
45 new PiperSimpleClient(new EmscriptenProxy(VampExamplePlugins()))
|
dev@72
|
46 );
|
dev@72
|
47
|
dev@44
|
48 this.workerScope.onmessage = (ev: MessageEvent) => {
|
dev@64
|
49 const sendResponse = (result) => {
|
dev@64
|
50 this.workerScope.postMessage({
|
dev@64
|
51 method: ev.data.method,
|
dev@64
|
52 result: result
|
dev@64
|
53 });
|
dev@64
|
54 };
|
dev@44
|
55 switch (ev.data.method) {
|
dev@44
|
56 case 'list':
|
dev@72
|
57 this.list(ev.data.params)
|
dev@72
|
58 .then(sendResponse)
|
dev@72
|
59 .catch(err => console.error(err)); // TODO handle error
|
dev@47
|
60 break;
|
dev@47
|
61 case 'process':
|
dev@72
|
62 this.process(ev.data.params)
|
dev@72
|
63 .then(sendResponse)
|
dev@72
|
64 .catch(err => console.error(err)); // TODO handle error
|
dev@62
|
65 break;
|
dev@62
|
66 case 'collect':
|
dev@72
|
67 this.collect(ev.data.params)
|
dev@72
|
68 .then(sendResponse)
|
dev@72
|
69 .catch(err => console.error(err)); // TODO handle error
|
dev@72
|
70 break;
|
dev@72
|
71 case 'import':
|
dev@72
|
72 // this.workerScope.importScripts(ev.data.params);
|
dev@72
|
73 const key: LibraryKey = ev.data.params;
|
dev@72
|
74 if (this.remoteLibraries.has(key)) {
|
dev@72
|
75 this.requireJs([this.remoteLibraries.get(key)], (plugin) => {
|
dev@72
|
76 this.clients.set(
|
dev@72
|
77 key,
|
dev@72
|
78 new PiperSimpleClient(new EmscriptenProxy(plugin.createLibrary()))
|
dev@72
|
79 ); // TODO won't always be an emscripten module
|
dev@72
|
80 this.list({}).then(sendResponse);
|
dev@72
|
81 });
|
dev@72
|
82 } else {
|
dev@72
|
83 console.error('Non registered library key.'); // TODO handle error
|
dev@72
|
84 }
|
dev@72
|
85 break;
|
dev@72
|
86 case 'addRemoteLibraries': // TODO rename
|
dev@72
|
87 const available: AvailableLibraries = ev.data.params;
|
dev@72
|
88 Object.keys(available).forEach(key => {
|
dev@72
|
89 this.remoteLibraries.set(key, available[key]);
|
dev@72
|
90 });
|
dev@44
|
91 }
|
dev@44
|
92 };
|
dev@40
|
93 }
|
dev@44
|
94
|
dev@72
|
95 private list(request: ListRequest): Promise<ListResponse> {
|
dev@72
|
96 // TODO actually pay attention to ListRequest
|
dev@72
|
97 return Promise.all([...this.clients.values()].map(client => client.list({})))
|
dev@72
|
98 .then(allAvailable => {
|
dev@72
|
99 return {
|
dev@72
|
100 available: allAvailable.reduce(
|
dev@72
|
101 (all, current) => all.concat(current.available),
|
dev@72
|
102 []
|
dev@72
|
103 )
|
dev@72
|
104 };
|
dev@72
|
105 });
|
dev@72
|
106 }
|
dev@72
|
107
|
dev@72
|
108 // TODO reduce dupe
|
dev@72
|
109 private process(request: SimpleRequest): Promise<SimpleResponse> {
|
dev@72
|
110 const key: LibraryKey = request.key.split(':')[0];
|
dev@72
|
111 const client: PiperSimpleClient = this.clients.get(key);
|
dev@72
|
112 return client ? client.process(request) : Promise.reject("Invalid plugin library key.");
|
dev@72
|
113 }
|
dev@72
|
114
|
dev@72
|
115 private collect(request: SimpleRequest): Promise<SimpleResponse> {
|
dev@72
|
116 const key: LibraryKey = request.key.split(':')[0];
|
dev@72
|
117 const client: PiperSimpleClient = this.clients.get(key);
|
dev@72
|
118 return client ? client.collect(request) : Promise.reject("Invalid plugin library key.");
|
dev@72
|
119 }
|
dev@40
|
120 }
|