dev@74: import {Injectable, Inject} from '@angular/core'; dev@47: import { dev@226: ListResponse dev@497: } from 'piper-js/core'; dev@64: import { dev@497: OneShotExtractionRequest as SimpleRequest, dev@497: } from 'piper-js/one-shot'; dev@236: import {Subject} from 'rxjs/Subject'; dev@236: import {Observable} from 'rxjs/Observable'; dev@324: import {Http} from '@angular/http'; dev@226: import { dev@226: countingIdProvider, dev@497: WebWorkerStreamingClient, dev@497: RequestId dev@497: } from 'piper-js/web-worker'; dev@497: import {collect, StreamingConfiguration} from 'piper-js/streaming'; dev@349: import { dev@349: KnownShapedFeature, dev@349: toKnownShape dev@349: } from '../../visualisations/FeatureUtilities'; dev@494: import {NotificationService} from '../notifications/notifications.service'; dev@40: dev@74: type RepoUri = string; dev@74: export interface AvailableLibraries { dev@74: [libraryKey: string]: RepoUri; dev@74: } dev@74: dev@226: export interface Progress { dev@226: id: RequestId; dev@226: value: number; // between 0 and 100, for material-ui dev@226: } dev@226: dev@350: export interface ExtractionResult { dev@350: id: RequestId; dev@350: result: KnownShapedFeature; dev@396: unit?: string; dev@350: } dev@350: dev@40: @Injectable() dev@40: export class FeatureExtractionService { dev@40: dev@40: private worker: Worker; dev@350: private featuresExtracted: Subject; dev@350: featuresExtracted$: Observable; dev@74: private librariesUpdated: Subject; dev@74: librariesUpdated$: Observable; dev@226: private progressUpdated: Subject; dev@226: progressUpdated$: Observable; dev@226: private client: WebWorkerStreamingClient; dev@44: dev@236: constructor(private http: Http, dev@494: @Inject('PiperRepoUri') private repositoryUri: RepoUri, dev@494: private notifier: NotificationService) { dev@40: this.worker = new Worker('bootstrap-feature-extraction-worker.js'); dev@350: this.featuresExtracted = new Subject(); dev@51: this.featuresExtracted$ = this.featuresExtracted.asObservable(); dev@74: this.librariesUpdated = new Subject(); dev@74: this.librariesUpdated$ = this.librariesUpdated.asObservable(); dev@226: this.progressUpdated = new Subject(); dev@226: this.progressUpdated$ = this.progressUpdated.asObservable(); dev@74: this.worker.addEventListener('message', (ev: MessageEvent) => { dev@74: const isValidResponse = ev.data.method === 'import' dev@226: && ev.data.result && ev.data.result.available ; dev@74: if (isValidResponse) { dev@226: (ev as Event).stopImmediatePropagation(); dev@74: this.librariesUpdated.next(ev.data.result); dev@74: } dev@226: }, true); dev@226: dev@226: this.client = new WebWorkerStreamingClient( dev@226: this.worker, dev@226: countingIdProvider(0) dev@236: ); dev@40: } dev@40: dev@47: list(): Promise { dev@326: return this.client.list({}); dev@40: } dev@40: dev@350: extract(analysisItemId: string, dev@350: request: SimpleRequest): Promise { dev@305: let config: StreamingConfiguration; dev@305: return collect(this.client.process(request), val => { dev@305: if (val.configuration) { dev@305: config = val.configuration; dev@305: } dev@305: const progress = val.progress; dev@305: if (progress.totalBlockCount > 0) { dev@305: this.progressUpdated.next({ dev@305: id: analysisItemId, dev@305: value: (progress.processedBlockCount / progress.totalBlockCount) * 100 dev@305: }); dev@305: } dev@305: }).then(features => { dev@349: const shaped = toKnownShape({ dev@305: features: features, dev@305: outputDescriptor: config.outputDescriptor dev@226: }); dev@396: const result = config.outputDescriptor.configured.unit ? { dev@396: id: analysisItemId, dev@396: result: shaped, dev@396: unit: shaped.shape === 'notes' ? dev@396: 'MIDI note' : config.outputDescriptor.configured.unit dev@396: } : { dev@350: id: analysisItemId, dev@350: result: shaped dev@350: }; dev@350: this.featuresExtracted.next(result); dev@350: return result; dev@305: }); dev@62: } dev@62: dev@324: updateAvailableLibraries(): void { dev@324: this.http.get(this.repositoryUri) dev@324: .toPromise() // just turn into a promise for now to subscribe / execute dev@324: .then(res => { dev@74: this.worker.postMessage({ dev@74: method: 'addRemoteLibraries', dev@324: params: res.json() dev@349: }); dev@74: }) dev@494: .catch(err => this.notifier.displayError(err)); dev@74: } dev@74: dev@74: load(libraryKey: string): void { dev@74: this.worker.postMessage({method: 'import', params: libraryKey}); dev@74: } dev@40: }