changeset 16:7e3ab6f8792f

Rough waveform loading, issues exist regarding communicating changes from child components (unless using the current workaround with explicit zone running)... investigating.
author Lucas Thompson <dev@lucas.im>
date Thu, 27 Oct 2016 17:08:57 +0100
parents 0571cf863026
children ff964b28a272
files src/app/app.component.html src/app/app.component.ts src/app/audio-file-open/audio-file-open.component.ts src/app/waveform/waveform.component.ts
diffstat 4 files changed, 92 insertions(+), 12 deletions(-) [+]
line wrap: on
line diff
--- a/src/app/app.component.html	Thu Oct 27 14:44:37 2016 +0100
+++ b/src/app/app.component.html	Thu Oct 27 17:08:57 2016 +0100
@@ -4,7 +4,7 @@
   <span class="app-toolbar-filler"></span>
 
 
-  <app-audio-file-open></app-audio-file-open>
+  <app-audio-file-open (audioLoaded)="onAudioLoaded($event)"></app-audio-file-open>
   <!-- menu opens when trigger button is clicked -->
   <button md-icon-button [md-menu-trigger-for]="menu">
     <md-icon>more_vert</md-icon>
@@ -18,6 +18,10 @@
 <md-sidenav-layout>
   <md-sidenav align="end" mode="side" opened>
     <md-slider></md-slider>
+    <button md-icon-button (click)="testRef()">
+      <md-icon>face</md-icon>
+    </button>
+    <h1>{{count}}</h1>
   </md-sidenav>
-  <app-waveform></app-waveform>
+  <app-waveform [audioBuffer]="audioBuffer"></app-waveform>
 </md-sidenav-layout>
--- a/src/app/app.component.ts	Thu Oct 27 14:44:37 2016 +0100
+++ b/src/app/app.component.ts	Thu Oct 27 17:08:57 2016 +0100
@@ -1,4 +1,4 @@
-import {Component, Inject} from '@angular/core';
+import {Component, Inject, NgZone} from '@angular/core';
 import {MailService} from "./mail.service";
 
 @Component({
@@ -9,12 +9,28 @@
 export class AppComponent {
   title = 'Ugly';
 
+  count = 0;
+  audioBuffer: AudioBuffer = undefined;
+
   constructor(
     private mail: MailService,
-    @Inject('piper-server-uri') private serverUri
+    @Inject('piper-server-uri') private serverUri,
+    private zone: NgZone
   ) {}
 
   onUpdate(id, text) {
     this.mail.update(id, text);
   }
+
+  onAudioLoaded(buffer: AudioBuffer) {
+    this.zone.run(() => { // TODO why the f does this only recognise changes immediately (and not the next tick) inside zone.run?
+      console.log("audio loaded");
+      this.audioBuffer = buffer;
+      this.count++;
+    });
+  }
+
+  testRef() {
+    this.count++;
+  }
 }
--- a/src/app/audio-file-open/audio-file-open.component.ts	Thu Oct 27 14:44:37 2016 +0100
+++ b/src/app/audio-file-open/audio-file-open.component.ts	Thu Oct 27 17:08:57 2016 +0100
@@ -1,4 +1,7 @@
-import {Component, OnInit, ViewChild, ElementRef} from '@angular/core';
+import {
+  Component, OnInit, ViewChild, ElementRef, Output,
+  EventEmitter
+} from '@angular/core';
 
 interface AudioContextConstructor {
   new(): AudioContext
@@ -17,10 +20,13 @@
 export class AudioFileOpenComponent implements OnInit {
 
   @ViewChild('open') open: ElementRef;
+  @Output() audioLoaded: EventEmitter<AudioBuffer>;
 
   private audioContext: AudioContext;
 
   constructor() {
+    this.audioLoaded = new EventEmitter<AudioBuffer>();
+
     // TODO make a service which provides the AudioContext?
     const factory: WindowAudioContext = (window as WindowAudioContext);
     this.audioContext = new (factory.AudioContext || factory.webkitAudioContext)();
@@ -34,7 +40,7 @@
       const reader: FileReader = new FileReader();
       reader.onload = (event: any) => {
         this.audioContext.decodeAudioData(event.target.result, buffer => {
-          console.log(buffer);
+          this.audioLoaded.emit(buffer);
         });
       };
       reader.readAsArrayBuffer(files[0]);
--- a/src/app/waveform/waveform.component.ts	Thu Oct 27 14:44:37 2016 +0100
+++ b/src/app/waveform/waveform.component.ts	Thu Oct 27 17:08:57 2016 +0100
@@ -1,39 +1,93 @@
 import {
   Component, OnInit, ViewChild, ElementRef,
-  AfterViewInit
+  AfterViewInit, OnChanges, SimpleChanges, Input
 } from '@angular/core';
 
-declare var wavesUI: any;
+declare var wavesUI: any; // TODO non-global app scope import
 
 @Component({
   selector: 'app-waveform',
   templateUrl: './waveform.component.html',
   styleUrls: ['./waveform.component.css']
 })
-export class WaveformComponent implements OnInit, AfterViewInit {
+export class WaveformComponent implements OnInit, AfterViewInit, OnChanges {
   @ViewChild('track') trackDiv: ElementRef;
 
+  private _audioBuffer: AudioBuffer = undefined;
+
+  @Input()
+  set audioBuffer(buffer: AudioBuffer) {
+    console.log("setter");
+    this._audioBuffer = buffer || undefined;
+  }
+
+  get audioBuffer(): AudioBuffer {
+    return this._audioBuffer;
+  }
+
+
+
+  private timeline: any; // TODO what type is it?
+
   constructor() {
-    console.log(wavesUI.core);
   }
 
   ngOnInit() {}
 
   ngAfterViewInit(): void {
+    // const track: HTMLElement = this.trackDiv.nativeElement;
+    // const duration: number = 1.0;
+    // const height: number = track.getBoundingClientRect().height;
+    // const width: number = track.getBoundingClientRect().width;
+    // const pixelsPerSecond = width / duration;
+    // const timeline = new wavesUI.core.Timeline(pixelsPerSecond, width);
+    // timeline.createTrack(track, height, 'main');
+    //
+    // // time axis
+    // const timeAxis = new wavesUI.helpers.TimeAxisLayer({
+    //   height: height,
+    //   top: 10,
+    //   color: 'gray'
+    // });
+    //
+    // timeline.addLayer(timeAxis, 'main', 'default', true);
+    // timeline.state = new wavesUI.states.CenteredZoomState(timeline);
+  }
+
+  ngOnChanges(changes: SimpleChanges): void {
+    console.log("ng changes");
+    if (changes.hasOwnProperty("audioBuffer")) { // why wouldn't it?
+      if (changes["audioBuffer"].currentValue)
+        this.renderWaveform(changes["audioBuffer"].currentValue);
+    }
+  }
+
+  renderWaveform(buffer: AudioBuffer) {
+    // TODO reduce dupe from original timeline state, anyway to actually not instantiate new timeline?
+    console.log("render wave");
     const track: HTMLElement = this.trackDiv.nativeElement;
-    const duration: number = 1.0;
+    const duration: number = buffer.duration;
     const height: number = track.getBoundingClientRect().height;
     const width: number = track.getBoundingClientRect().width;
     const pixelsPerSecond = width / duration;
-    const timeline: any = new wavesUI.core.Timeline(pixelsPerSecond, width);
+    const timeline = new wavesUI.core.Timeline(pixelsPerSecond, width);
     timeline.createTrack(track, height, 'main');
+
     // time axis
     const timeAxis = new wavesUI.helpers.TimeAxisLayer({
       height: height,
       top: 10,
       color: 'gray'
     });
+
     timeline.addLayer(timeAxis, 'main', 'default', true);
     timeline.state = new wavesUI.states.CenteredZoomState(timeline);
+    // TODO dispose of the existing layer?
+    const waveformLayer = new wavesUI.helpers.WaveformLayer(buffer, {
+      height: 600,
+      color: 'darkblue'
+    });
+    timeline.addLayer(waveformLayer, 'main');
   }
+
 }