dev@40
|
1 /**
|
dev@40
|
2 * Created by lucas on 01/12/2016.
|
dev@40
|
3 */
|
dev@40
|
4
|
dev@88
|
5 import {PiperVampService, ListRequest, ListResponse} from 'piper';
|
dev@72
|
6 import {
|
dev@226
|
7 SimpleRequest
|
dev@72
|
8 } from 'piper/HigherLevelUtilities';
|
dev@44
|
9 import { VampExamplePlugins } from 'piper/ext/VampExamplePluginsModule';
|
dev@236
|
10 import {AvailableLibraries} from './feature-extraction.service';
|
dev@226
|
11 import {
|
dev@226
|
12 DedicatedWorkerGlobalScope,
|
dev@226
|
13 WebWorkerStreamingServer
|
dev@236
|
14 } from 'piper/servers/WebWorkerStreamingServer';
|
dev@226
|
15 import {
|
dev@226
|
16 PiperStreamingService,
|
dev@226
|
17 StreamingResponse,
|
dev@226
|
18 StreamingService
|
dev@236
|
19 } from 'piper/StreamingService';
|
dev@236
|
20 import {Observable} from 'rxjs/Observable';
|
dev@236
|
21 import {EmscriptenModule} from 'piper/PiperVampService';
|
dev@40
|
22
|
dev@40
|
23 interface MessageEvent {
|
dev@40
|
24 readonly data: any;
|
dev@40
|
25 }
|
dev@40
|
26
|
dev@72
|
27 type LibraryUri = string;
|
dev@72
|
28 type LibraryKey = string;
|
dev@72
|
29
|
dev@72
|
30 type RequireJs = (libs: string[], callback: (...libs: any[]) => void) => void;
|
dev@72
|
31
|
dev@226
|
32 class AggregateStreamingService implements StreamingService {
|
dev@226
|
33 private services: Map<LibraryKey, PiperStreamingService>;
|
dev@226
|
34
|
dev@226
|
35 constructor() {
|
dev@226
|
36 this.services = new Map<LibraryKey, PiperStreamingService>();
|
dev@226
|
37 this.services.set(
|
dev@226
|
38 'vamp-example-plugins',
|
dev@226
|
39 new PiperStreamingService(new PiperVampService(VampExamplePlugins()))
|
dev@226
|
40 );
|
dev@226
|
41 }
|
dev@226
|
42
|
dev@226
|
43 addService(key: LibraryKey, service: PiperStreamingService): void {
|
dev@226
|
44 this.services.set(key, service);
|
dev@226
|
45 }
|
dev@226
|
46
|
dev@226
|
47 list(request: ListRequest): Promise<ListResponse> {
|
dev@226
|
48 return Promise.all(
|
dev@226
|
49 [...this.services.values()].map(client => client.list({}))
|
dev@226
|
50 ).then(allAvailable => ({
|
dev@226
|
51 available: allAvailable.reduce(
|
dev@226
|
52 (all, current) => all.concat(current.available),
|
dev@226
|
53 []
|
dev@226
|
54 )
|
dev@226
|
55 })
|
dev@226
|
56 );
|
dev@226
|
57 }
|
dev@226
|
58
|
dev@226
|
59 process(request: SimpleRequest): Observable<StreamingResponse> {
|
dev@226
|
60 return undefined;
|
dev@226
|
61 }
|
dev@226
|
62
|
dev@226
|
63 collect(request: SimpleRequest): Observable<StreamingResponse> {
|
dev@226
|
64 const key = request.key.split(':')[0];
|
dev@226
|
65 return this.services.has(key) ?
|
dev@236
|
66 this.services.get(key).collect(request) : Observable.throw('Invalid key');
|
dev@226
|
67 }
|
dev@226
|
68 }
|
dev@226
|
69
|
dev@40
|
70 export default class FeatureExtractionWorker {
|
dev@226
|
71 private workerScope: DedicatedWorkerGlobalScope;
|
dev@72
|
72 private remoteLibraries: Map<LibraryKey, LibraryUri>;
|
dev@226
|
73 private server: WebWorkerStreamingServer;
|
dev@226
|
74 private service: AggregateStreamingService;
|
dev@40
|
75
|
dev@226
|
76 constructor(workerScope: DedicatedWorkerGlobalScope,
|
dev@226
|
77 private requireJs: RequireJs) {
|
dev@40
|
78 this.workerScope = workerScope;
|
dev@72
|
79 this.remoteLibraries = new Map<LibraryKey, LibraryUri>();
|
dev@226
|
80 this.service = new AggregateStreamingService();
|
dev@226
|
81 this.setupImportLibraryListener();
|
dev@226
|
82 this.server = new WebWorkerStreamingServer(
|
dev@226
|
83 this.workerScope,
|
dev@226
|
84 this.service
|
dev@72
|
85 );
|
dev@226
|
86 }
|
dev@72
|
87
|
dev@226
|
88 private setupImportLibraryListener(): void {
|
dev@229
|
89
|
dev@44
|
90 this.workerScope.onmessage = (ev: MessageEvent) => {
|
dev@64
|
91 const sendResponse = (result) => {
|
dev@64
|
92 this.workerScope.postMessage({
|
dev@64
|
93 method: ev.data.method,
|
dev@64
|
94 result: result
|
dev@64
|
95 });
|
dev@64
|
96 };
|
dev@44
|
97 switch (ev.data.method) {
|
dev@72
|
98 case 'import':
|
dev@72
|
99 const key: LibraryKey = ev.data.params;
|
dev@72
|
100 if (this.remoteLibraries.has(key)) {
|
dev@72
|
101 this.requireJs([this.remoteLibraries.get(key)], (plugin) => {
|
dev@229
|
102 // TODO a factory with more logic probably belongs in piper-js
|
dev@229
|
103 const lib: any | EmscriptenModule = plugin.createLibrary();
|
dev@229
|
104 const isEmscriptenModule = typeof lib.cwrap === 'function';
|
dev@229
|
105 const service = new PiperStreamingService(
|
dev@229
|
106 isEmscriptenModule ? new PiperVampService(lib) : lib // TODO
|
dev@229
|
107 );
|
dev@229
|
108 this.service.addService(key, service);
|
dev@226
|
109 this.service.list({}).then(sendResponse);
|
dev@72
|
110 });
|
dev@72
|
111 } else {
|
dev@72
|
112 console.error('Non registered library key.'); // TODO handle error
|
dev@72
|
113 }
|
dev@72
|
114 break;
|
dev@72
|
115 case 'addRemoteLibraries': // TODO rename
|
dev@72
|
116 const available: AvailableLibraries = ev.data.params;
|
dev@236
|
117 Object.keys(available).forEach(libraryKey => {
|
dev@236
|
118 this.remoteLibraries.set(libraryKey, available[libraryKey]);
|
dev@72
|
119 });
|
dev@44
|
120 }
|
dev@44
|
121 };
|
dev@40
|
122 }
|
dev@40
|
123 }
|