diff src/app/Session.ts @ 460:ccce2c09502e

Manually cherry-pick various refactoring efforts from feature/basic-session-loading
author Lucas Thompson <dev@lucas.im>
date Fri, 30 Jun 2017 10:41:30 +0100
parents
children 2624bb55dbf6
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/app/Session.ts	Fri Jun 30 10:41:30 2017 +0100
@@ -0,0 +1,134 @@
+/**
+ * Created by lucast on 08/06/2017.
+ */
+import {
+  Item,
+  RootAudioItem
+} from './analysis-item/AnalysisItem';
+
+export const exampleSession: SerialisedNotebook = {
+  root: {
+    id: '1',
+    hasSharedTimeline: true,
+    title: 'Drum Loop',
+    description: 'Remotely hosted audio file',
+    uri: 'https://piper-audio.github.io/waves-ui-piper/examples/assets/drum-loop.wav'
+  },
+  analyses: [
+    {
+      id: '2',
+      hasSharedTimeline: true,
+      extractorKey: 'vamp-example-plugins:amplitudefollower',
+      outputId: 'amplitude',
+      title: 'Amplitude',
+      description: 'amplitude'
+    },
+    {
+      id: '3',
+      hasSharedTimeline: true,
+      extractorKey: 'vamp-example-plugins:powerspectrum',
+      outputId: 'powerspectrum',
+      title: 'Simple Power Spectrum',
+      description: 'powerspectrum'
+    },
+
+  ]
+};
+
+export interface SerialisedAnalysisItem extends Item {
+  extractorKey: string;
+  outputId: string;
+}
+
+export interface SerialisedNotebook {
+  root: RootAudioItem;
+  analyses: SerialisedAnalysisItem[];
+}
+
+export type ResourceRetriever = (url: string) => Promise<Blob>;
+
+export const downloadResource: ResourceRetriever = async (url) => {
+  const response = await fetch(url);
+  const mimeType = response.headers.get('content-type');
+  // Safari's fetch.blob implementation doesn't populate the type property
+  // causing the audio player to fail due to an unsupported type.
+  // Manually create a blob from an array buffer and the content type in
+  // the response object
+  const arrayBufferToBlob = async () => {
+    const arrayBuffer = await response.arrayBuffer();
+    return new Blob([arrayBuffer], {type: mimeType});
+  };
+  return mimeType ? arrayBufferToBlob() : response.blob();
+};
+
+export class PersistentStack<T> {
+  private stack: T[];
+  private history: T[][];
+
+  constructor() {
+    this.stack = [];
+    this.history = [];
+  }
+
+  shift(): T {
+    this.history.push([...this.stack]);
+    const item = this.stack[0];
+    this.stack = this.stack.slice(1);
+    return item;
+  }
+
+  unshift(item: T): number {
+    this.history.push([...this.stack]);
+    this.stack = [item, ...this.stack];
+    return this.stack.length;
+  }
+
+  findIndex(predicate: (value: T,
+                        index: number,
+                        array: T[]) => boolean): number {
+    return this.stack.findIndex(predicate);
+  }
+
+  filter(predicate: (value: T, index: number, array: T[]) => boolean): T[] {
+    return this.stack.filter(predicate);
+  }
+
+  get(index: number): T {
+    return this.stack[index];
+  }
+
+  set(index: number, value: T) {
+    this.history.push([...this.stack]);
+    this.stack = [
+      ...this.stack.slice(0, index),
+      value,
+      ...this.stack.slice(index + 1)
+    ];
+  }
+
+  map<U>(transform: (value: T, index: number, array: T[]) => U): U[] {
+    return this.stack.map(transform);
+  }
+
+  reduce<U>(reducer: (previousValue: U,
+                      currentValue: T,
+                      currentIndex: number,
+                      array: T[]) => U,
+            initialValue: U): U {
+    return this.stack.reduce(reducer, initialValue);
+  }
+
+  remove(...indices: number[]) {
+    this.history.push([...this.stack]);
+    this.stack = this.stack.reduce((acc, item, i) => {
+      if (!indices.includes(i)) {
+        acc.push(item);
+      }
+      return acc;
+    }, [] as T[]);
+  }
+
+  toIterable(): Iterable<T> {
+    return this.stack;
+  }
+}