diff src/app/services/feature-extraction/FeatureExtractionWorker.ts @ 226:4865567d9e43

Refactor feature extraction service to use piper streaming client/server. Change FeatureExtractionWorker accordingly and calling code.
author Lucas Thompson <dev@lucas.im>
date Fri, 21 Apr 2017 12:59:41 +0100
parents 4aa6b1266251
children efa23f33393b
line wrap: on
line diff
--- a/src/app/services/feature-extraction/FeatureExtractionWorker.ts	Fri Apr 21 12:58:55 2017 +0100
+++ b/src/app/services/feature-extraction/FeatureExtractionWorker.ts	Fri Apr 21 12:59:41 2017 +0100
@@ -4,18 +4,21 @@
 
 import {PiperVampService, ListRequest, ListResponse} from 'piper';
 import {
-  PiperSimpleClient, SimpleRequest,
-  SimpleResponse
+  SimpleRequest
 } from 'piper/HigherLevelUtilities';
 import { VampExamplePlugins } from 'piper/ext/VampExamplePluginsModule';
 import {AvailableLibraries} from "./feature-extraction.service";
+import {
+  DedicatedWorkerGlobalScope,
+  WebWorkerStreamingServer
+} from "piper/servers/WebWorkerStreamingServer";
+import {
+  PiperStreamingService,
+  StreamingResponse,
+  StreamingService
+} from "piper/StreamingService";
+import {Observable} from "rxjs/Observable";
 
-// TODO TypeScript has a .d.ts file for webworkers, but for some reason it clashes with the typings for dom and causes compiler errors
-interface WorkerGlobalScope {
-  onmessage: (this: this, ev: MessageEvent) => any;
-  postMessage(data: any): void;
-  importScripts(uri: string): void;
-}
 
 interface MessageEvent {
   readonly data: any;
@@ -26,20 +29,65 @@
 
 type RequireJs = (libs: string[], callback: (...libs: any[]) => void) => void;
 
+class AggregateStreamingService implements StreamingService {
+  private services: Map<LibraryKey, PiperStreamingService>;
+
+  constructor() {
+    this.services = new Map<LibraryKey, PiperStreamingService>();
+    this.services.set(
+      'vamp-example-plugins',
+      new PiperStreamingService(new PiperVampService(VampExamplePlugins()))
+    );
+  }
+
+  addService(key: LibraryKey, service: PiperStreamingService): void {
+    this.services.set(key, service);
+  }
+
+  list(request: ListRequest): Promise<ListResponse> {
+    return Promise.all(
+      [...this.services.values()].map(client => client.list({}))
+    ).then(allAvailable => ({
+        available: allAvailable.reduce(
+          (all, current) => all.concat(current.available),
+          []
+        )
+      })
+    );
+  }
+
+  process(request: SimpleRequest): Observable<StreamingResponse> {
+    return undefined;
+  }
+
+  collect(request: SimpleRequest): Observable<StreamingResponse> {
+    const key = request.key.split(':')[0];
+    return this.services.has(key) ?
+      this.services.get(key).collect(request) : Observable.throw("Invalid key");
+  }
+}
+
 export default class FeatureExtractionWorker {
-  private workerScope: WorkerGlobalScope;
-  private clients: Map<LibraryKey, PiperSimpleClient>;
+  private workerScope: DedicatedWorkerGlobalScope;
+  private services: Map<LibraryKey, PiperStreamingService>;
   private remoteLibraries: Map<LibraryKey, LibraryUri>;
+  private server: WebWorkerStreamingServer;
+  private service: AggregateStreamingService;
 
-  constructor(workerScope: WorkerGlobalScope, private requireJs: RequireJs) {
+  constructor(workerScope: DedicatedWorkerGlobalScope,
+              private requireJs: RequireJs) {
     this.workerScope = workerScope;
-    this.clients = new Map<LibraryKey, PiperSimpleClient>();
+    this.services = new Map<LibraryKey, PiperStreamingService>();
     this.remoteLibraries = new Map<LibraryKey, LibraryUri>();
-    this.clients.set(
-      'vamp-example-plugins',
-      new PiperSimpleClient(new PiperVampService(VampExamplePlugins()))
+    this.service = new AggregateStreamingService();
+    this.setupImportLibraryListener();
+    this.server = new WebWorkerStreamingServer(
+      this.workerScope,
+      this.service
     );
+  }
 
+  private setupImportLibraryListener(): void {
     this.workerScope.onmessage = (ev: MessageEvent) => {
       const sendResponse = (result) => {
         this.workerScope.postMessage({
@@ -48,31 +96,18 @@
         });
       };
       switch (ev.data.method) {
-        case 'list':
-          this.list(ev.data.params)
-            .then(sendResponse)
-            .catch(err => console.error(err)); // TODO handle error
-          break;
-        case 'process':
-          this.process(ev.data.params)
-            .then(sendResponse)
-            .catch(err => console.error(err)); // TODO handle error
-          break;
-        case 'collect':
-          this.collect(ev.data.params)
-            .then(sendResponse)
-            .catch(err => console.error(err)); // TODO handle error
-          break;
         case 'import':
-          // this.workerScope.importScripts(ev.data.params);
           const key: LibraryKey = ev.data.params;
           if (this.remoteLibraries.has(key)) {
             this.requireJs([this.remoteLibraries.get(key)], (plugin) => {
-              this.clients.set(
+              this.services.set(
                 key,
-                new PiperSimpleClient(new PiperVampService(plugin.createLibrary()))
+                new PiperStreamingService(
+                  new PiperVampService(plugin.createLibrary())
+                )
               ); // TODO won't always be an emscripten module
-              this.list({}).then(sendResponse);
+              this.service.addService(key, this.services.get(key));
+              this.service.list({}).then(sendResponse);
             });
           } else {
             console.error('Non registered library key.'); // TODO handle error
@@ -86,30 +121,4 @@
       }
     };
   }
-
-  private list(request: ListRequest): Promise<ListResponse> {
-    // TODO actually pay attention to ListRequest
-    return Promise.all([...this.clients.values()].map(client => client.list({})))
-      .then(allAvailable => {
-        return {
-          available: allAvailable.reduce(
-            (all, current) => all.concat(current.available),
-            []
-          )
-        };
-      });
-  }
-
-  // TODO reduce dupe
-  private process(request: SimpleRequest): Promise<SimpleResponse> {
-    const key: LibraryKey = request.key.split(':')[0];
-    const client: PiperSimpleClient = this.clients.get(key);
-    return client ? client.process(request) : Promise.reject("Invalid plugin library key.");
-  }
-
-  private collect(request: SimpleRequest): Promise<SimpleResponse> {
-    const key: LibraryKey = request.key.split(':')[0];
-    const client: PiperSimpleClient = this.clients.get(key);
-    return client ? client.collect(request) : Promise.reject("Invalid plugin library key.");
-  }
 }