Mercurial > hg > ugly-duckling
comparison src/app/services/feature-extraction/FeatureExtractionWorker.ts @ 72:cb91d7e40068
Add a couple of methods to the worker for adding remote library repos (well, key value pairs of library keys and URIs to fetch the library from) - and one for actually importing the libraries (currently using RequireJS (<script> / importScripts(...) method tying into global AMD module registration) ). Also updated list method to concatenate the available outputs from all loaded libraries.
author | Lucas Thompson <dev@lucas.im> |
---|---|
date | Wed, 18 Jan 2017 10:18:10 +0000 |
parents | 270f59ef3b83 |
children | 8aa6830ea41d |
comparison
equal
deleted
inserted
replaced
71:0980eb001bde | 72:cb91d7e40068 |
---|---|
1 /** | 1 /** |
2 * Created by lucas on 01/12/2016. | 2 * Created by lucas on 01/12/2016. |
3 */ | 3 */ |
4 | 4 |
5 import { EmscriptenProxy } from 'piper'; | 5 import {EmscriptenProxy, ListRequest, ListResponse} from 'piper'; |
6 import { PiperSimpleClient } from 'piper/HigherLevelUtilities'; | 6 import { |
7 PiperSimpleClient, SimpleRequest, | |
8 SimpleResponse | |
9 } from 'piper/HigherLevelUtilities'; | |
7 import { VampExamplePlugins } from 'piper/ext/VampExamplePluginsModule'; | 10 import { VampExamplePlugins } from 'piper/ext/VampExamplePluginsModule'; |
11 import {AvailableLibraries} from "./feature-extraction.service"; | |
8 | 12 |
9 // TODO TypeScript has a .d.ts file for webworkers, but for some reason it clashes with the typings for dom and causes compiler errors | 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 |
10 interface WorkerGlobalScope { | 14 interface WorkerGlobalScope { |
11 onmessage: (this: this, ev: MessageEvent) => any; | 15 onmessage: (this: this, ev: MessageEvent) => any; |
12 postMessage(data: any): void; | 16 postMessage(data: any): void; |
17 importScripts(uri: string): void; | |
13 } | 18 } |
14 | 19 |
15 interface MessageEvent { | 20 interface MessageEvent { |
16 readonly data: any; | 21 readonly data: any; |
17 } | 22 } |
18 | 23 |
24 type LibraryUri = string; | |
25 type LibraryKey = string; | |
26 | |
27 interface Message { | |
28 method: string; | |
29 params: any; | |
30 } | |
31 | |
32 type RequireJs = (libs: string[], callback: (...libs: any[]) => void) => void; | |
33 | |
19 export default class FeatureExtractionWorker { | 34 export default class FeatureExtractionWorker { |
20 private workerScope: WorkerGlobalScope; | 35 private workerScope: WorkerGlobalScope; |
21 private piperClient: PiperSimpleClient; | 36 private clients: Map<string, PiperSimpleClient>; |
37 private remoteLibraries: Map<LibraryKey, LibraryUri>; | |
22 | 38 |
23 constructor(workerScope: WorkerGlobalScope) { | 39 constructor(workerScope: WorkerGlobalScope, private requireJs: RequireJs) { |
24 this.workerScope = workerScope; | 40 this.workerScope = workerScope; |
25 this.piperClient = new PiperSimpleClient(new EmscriptenProxy(VampExamplePlugins())); | 41 this.clients = new Map<LibraryKey, PiperSimpleClient>(); |
42 this.remoteLibraries = new Map<LibraryKey, LibraryUri>(); | |
43 this.clients.set( | |
44 'vamp-example-plugins', | |
45 new PiperSimpleClient(new EmscriptenProxy(VampExamplePlugins())) | |
46 ); | |
47 | |
26 this.workerScope.onmessage = (ev: MessageEvent) => { | 48 this.workerScope.onmessage = (ev: MessageEvent) => { |
27 const sendResponse = (result) => { | 49 const sendResponse = (result) => { |
28 this.workerScope.postMessage({ | 50 this.workerScope.postMessage({ |
29 method: ev.data.method, | 51 method: ev.data.method, |
30 result: result | 52 result: result |
31 }); | 53 }); |
32 }; | 54 }; |
33 switch (ev.data.method) { | 55 switch (ev.data.method) { |
34 case 'list': | 56 case 'list': |
35 this.piperClient.list({}).then(sendResponse); | 57 this.list(ev.data.params) |
58 .then(sendResponse) | |
59 .catch(err => console.error(err)); // TODO handle error | |
36 break; | 60 break; |
37 case 'process': | 61 case 'process': |
38 this.piperClient.process(ev.data.params).then(sendResponse); | 62 this.process(ev.data.params) |
63 .then(sendResponse) | |
64 .catch(err => console.error(err)); // TODO handle error | |
39 break; | 65 break; |
40 case 'collect': | 66 case 'collect': |
41 this.piperClient.collect(ev.data.params).then(sendResponse).catch(err => console.error(err)); | 67 this.collect(ev.data.params) |
68 .then(sendResponse) | |
69 .catch(err => console.error(err)); // TODO handle error | |
70 break; | |
71 case 'import': | |
72 // this.workerScope.importScripts(ev.data.params); | |
73 const key: LibraryKey = ev.data.params; | |
74 if (this.remoteLibraries.has(key)) { | |
75 this.requireJs([this.remoteLibraries.get(key)], (plugin) => { | |
76 this.clients.set( | |
77 key, | |
78 new PiperSimpleClient(new EmscriptenProxy(plugin.createLibrary())) | |
79 ); // TODO won't always be an emscripten module | |
80 this.list({}).then(sendResponse); | |
81 }); | |
82 } else { | |
83 console.error('Non registered library key.'); // TODO handle error | |
84 } | |
85 break; | |
86 case 'addRemoteLibraries': // TODO rename | |
87 const available: AvailableLibraries = ev.data.params; | |
88 Object.keys(available).forEach(key => { | |
89 this.remoteLibraries.set(key, available[key]); | |
90 }); | |
42 } | 91 } |
43 }; | 92 }; |
44 } | 93 } |
45 | 94 |
95 private list(request: ListRequest): Promise<ListResponse> { | |
96 // TODO actually pay attention to ListRequest | |
97 return Promise.all([...this.clients.values()].map(client => client.list({}))) | |
98 .then(allAvailable => { | |
99 return { | |
100 available: allAvailable.reduce( | |
101 (all, current) => all.concat(current.available), | |
102 [] | |
103 ) | |
104 }; | |
105 }); | |
106 } | |
107 | |
108 // TODO reduce dupe | |
109 private process(request: SimpleRequest): Promise<SimpleResponse> { | |
110 const key: LibraryKey = request.key.split(':')[0]; | |
111 const client: PiperSimpleClient = this.clients.get(key); | |
112 return client ? client.process(request) : Promise.reject("Invalid plugin library key."); | |
113 } | |
114 | |
115 private collect(request: SimpleRequest): Promise<SimpleResponse> { | |
116 const key: LibraryKey = request.key.split(':')[0]; | |
117 const client: PiperSimpleClient = this.clients.get(key); | |
118 return client ? client.collect(request) : Promise.reject("Invalid plugin library key."); | |
119 } | |
46 } | 120 } |