Mercurial > hg > ugly-duckling
view src/app/services/feature-extraction/feature-extraction.service.ts @ 509:041468f553e1 tip master
Merge pull request #57 from LucasThompson/fix/session-stack-max-call-stack
Fix accidental recursion in PersistentStack
author | Lucas Thompson <LucasThompson@users.noreply.github.com> |
---|---|
date | Mon, 27 Nov 2017 11:04:30 +0000 |
parents | c39df81c4dae |
children |
line wrap: on
line source
import {Injectable, Inject} from '@angular/core'; import { ListResponse } from 'piper-js/core'; import { OneShotExtractionRequest as SimpleRequest, } from 'piper-js/one-shot'; import {Subject} from 'rxjs/Subject'; import {Observable} from 'rxjs/Observable'; import {Http} from '@angular/http'; import { countingIdProvider, WebWorkerStreamingClient, RequestId } from 'piper-js/web-worker'; import {collect, StreamingConfiguration} from 'piper-js/streaming'; import { KnownShapedFeature, toKnownShape } from '../../visualisations/FeatureUtilities'; import {NotificationService} from '../notifications/notifications.service'; type RepoUri = string; export interface AvailableLibraries { [libraryKey: string]: RepoUri; } export interface Progress { id: RequestId; value: number; // between 0 and 100, for material-ui } export interface ExtractionResult { id: RequestId; result: KnownShapedFeature; unit?: string; } @Injectable() export class FeatureExtractionService { private worker: Worker; private featuresExtracted: Subject<ExtractionResult>; featuresExtracted$: Observable<ExtractionResult>; private librariesUpdated: Subject<ListResponse>; librariesUpdated$: Observable<ListResponse>; private progressUpdated: Subject<Progress>; progressUpdated$: Observable<Progress>; private client: WebWorkerStreamingClient; constructor(private http: Http, @Inject('PiperRepoUri') private repositoryUri: RepoUri, private notifier: NotificationService) { this.worker = new Worker('bootstrap-feature-extraction-worker.js'); this.featuresExtracted = new Subject<ExtractionResult>(); this.featuresExtracted$ = this.featuresExtracted.asObservable(); this.librariesUpdated = new Subject<ListResponse>(); this.librariesUpdated$ = this.librariesUpdated.asObservable(); this.progressUpdated = new Subject<Progress>(); this.progressUpdated$ = this.progressUpdated.asObservable(); this.worker.addEventListener('message', (ev: MessageEvent) => { const isValidResponse = ev.data.method === 'import' && ev.data.result && ev.data.result.available ; if (isValidResponse) { (ev as Event).stopImmediatePropagation(); this.librariesUpdated.next(ev.data.result); } }, true); this.client = new WebWorkerStreamingClient( this.worker, countingIdProvider(0) ); } list(): Promise<ListResponse> { return this.client.list({}); } extract(analysisItemId: string, request: SimpleRequest): Promise<ExtractionResult> { let config: StreamingConfiguration; return collect(this.client.process(request), val => { if (val.configuration) { config = val.configuration; } const progress = val.progress; if (progress.totalBlockCount > 0) { this.progressUpdated.next({ id: analysisItemId, value: (progress.processedBlockCount / progress.totalBlockCount) * 100 }); } }).then(features => { const shaped = toKnownShape({ features: features, outputDescriptor: config.outputDescriptor }); const result = config.outputDescriptor.configured.unit ? { id: analysisItemId, result: shaped, unit: shaped.shape === 'notes' ? 'MIDI note' : config.outputDescriptor.configured.unit } : { id: analysisItemId, result: shaped }; this.featuresExtracted.next(result); return result; }); } updateAvailableLibraries(): void { this.http.get(this.repositoryUri) .toPromise() // just turn into a promise for now to subscribe / execute .then(res => { this.worker.postMessage({ method: 'addRemoteLibraries', params: res.json() }); }) .catch(err => this.notifier.displayError(err)); } load(libraryKey: string): void { this.worker.postMessage({method: 'import', params: libraryKey}); } }