annotate 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
rev   line source
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@72 10 import {AvailableLibraries} from "./feature-extraction.service";
dev@226 11 import {
dev@226 12 DedicatedWorkerGlobalScope,
dev@226 13 WebWorkerStreamingServer
dev@226 14 } from "piper/servers/WebWorkerStreamingServer";
dev@226 15 import {
dev@226 16 PiperStreamingService,
dev@226 17 StreamingResponse,
dev@226 18 StreamingService
dev@226 19 } from "piper/StreamingService";
dev@226 20 import {Observable} from "rxjs/Observable";
dev@44 21
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@226 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@226 72 private services: Map<LibraryKey, PiperStreamingService>;
dev@72 73 private remoteLibraries: Map<LibraryKey, LibraryUri>;
dev@226 74 private server: WebWorkerStreamingServer;
dev@226 75 private service: AggregateStreamingService;
dev@40 76
dev@226 77 constructor(workerScope: DedicatedWorkerGlobalScope,
dev@226 78 private requireJs: RequireJs) {
dev@40 79 this.workerScope = workerScope;
dev@226 80 this.services = new Map<LibraryKey, PiperStreamingService>();
dev@72 81 this.remoteLibraries = new Map<LibraryKey, LibraryUri>();
dev@226 82 this.service = new AggregateStreamingService();
dev@226 83 this.setupImportLibraryListener();
dev@226 84 this.server = new WebWorkerStreamingServer(
dev@226 85 this.workerScope,
dev@226 86 this.service
dev@72 87 );
dev@226 88 }
dev@72 89
dev@226 90 private setupImportLibraryListener(): void {
dev@44 91 this.workerScope.onmessage = (ev: MessageEvent) => {
dev@64 92 const sendResponse = (result) => {
dev@64 93 this.workerScope.postMessage({
dev@64 94 method: ev.data.method,
dev@64 95 result: result
dev@64 96 });
dev@64 97 };
dev@44 98 switch (ev.data.method) {
dev@72 99 case 'import':
dev@72 100 const key: LibraryKey = ev.data.params;
dev@72 101 if (this.remoteLibraries.has(key)) {
dev@72 102 this.requireJs([this.remoteLibraries.get(key)], (plugin) => {
dev@226 103 this.services.set(
dev@72 104 key,
dev@226 105 new PiperStreamingService(
dev@226 106 new PiperVampService(plugin.createLibrary())
dev@226 107 )
dev@72 108 ); // TODO won't always be an emscripten module
dev@226 109 this.service.addService(key, this.services.get(key));
dev@226 110 this.service.list({}).then(sendResponse);
dev@72 111 });
dev@72 112 } else {
dev@72 113 console.error('Non registered library key.'); // TODO handle error
dev@72 114 }
dev@72 115 break;
dev@72 116 case 'addRemoteLibraries': // TODO rename
dev@72 117 const available: AvailableLibraries = ev.data.params;
dev@72 118 Object.keys(available).forEach(key => {
dev@72 119 this.remoteLibraries.set(key, available[key]);
dev@72 120 });
dev@44 121 }
dev@44 122 };
dev@40 123 }
dev@40 124 }