view src/app/services/feature-extraction/feature-extraction.service.ts @ 62:2171dd56756c

Use VampTestPlugin for now. Also set up Collect method calls for the worker. Currently use the same stream for both process and collect extraction.
author Lucas Thompson <dev@lucas.im>
date Fri, 09 Dec 2016 14:06:04 +0000
parents 8619f25ff52a
children 270f59ef3b83
line wrap: on
line source
import {Injectable} from '@angular/core';
import {
  ListResponse, ListRequest
} from "piper";
import {SimpleRequest, FeatureCollection} from "piper/HigherLevelUtilities";
import {FeatureList} from "piper/Feature";
import {Subject} from "rxjs/Subject";
import {Observable} from "rxjs";

interface RequestMessage<RequestType> {
  method: string;
  params: RequestType;
}

interface ResponseMessage<ResponseType> {
  method: string;
  result: ResponseType;
}

export type Extracted = FeatureList | FeatureCollection;

@Injectable()
export class FeatureExtractionService {

  private worker: Worker;
  private featuresExtracted: Subject<Extracted>;
  featuresExtracted$: Observable<Extracted>;

  constructor() {
    this.worker = new Worker('bootstrap-feature-extraction-worker.js');
    this.featuresExtracted = new Subject<Extracted>();
    this.featuresExtracted$ = this.featuresExtracted.asObservable();
  }

  list(): Promise<ListResponse> {
    return this.request<ListRequest, ListResponse>(
      {method: 'list', params: {}},
      (ev: MessageEvent) => ev.data.result.available !== undefined
    ).then(msg => msg.result);
  }

  process(request: SimpleRequest): Promise<FeatureList> {
    return this.request<SimpleRequest, FeatureList>(
      {method: 'process', params: request},
      (ev: MessageEvent) => ev.data.method === 'process'
    ).then(msg => {
      this.featuresExtracted.next(msg.result);
      return msg.result;
    });
  }

  collect(request: SimpleRequest): Promise<FeatureCollection> {
    return this.request<SimpleRequest, FeatureCollection>(
      {method: 'collect', params: request},
      (ev: MessageEvent) => ev.data.method === 'collect'
    ).then(msg => {
      this.featuresExtracted.next(msg.result);
      return msg.result;
    });
  }

  private request<Req, Res>(request: RequestMessage<Req>,
                            predicate: (ev: MessageEvent) => boolean)
  : Promise<ResponseMessage<Res>> {
    return new Promise(res => {
      const listener = (ev: MessageEvent) => {
        this.worker.removeEventListener('message', listener);
        if (predicate(ev))
          res(ev.data);
      };
      this.worker.addEventListener('message', listener);
      this.worker.postMessage(request);
    }).catch(err => console.error(err));
  }
}