# HG changeset patch # User Lucas Thompson # Date 1477584537 -3600 # Node ID 7e3ab6f8792f8acbe32597099881114a423a6a3c # Parent 0571cf863026bfd41f46503e3b29e1e09076ba8f Rough waveform loading, issues exist regarding communicating changes from child components (unless using the current workaround with explicit zone running)... investigating. diff -r 0571cf863026 -r 7e3ab6f8792f src/app/app.component.html --- 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 @@ - + +

{{count}}

- + diff -r 0571cf863026 -r 7e3ab6f8792f src/app/app.component.ts --- 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++; + } } diff -r 0571cf863026 -r 7e3ab6f8792f src/app/audio-file-open/audio-file-open.component.ts --- 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; private audioContext: AudioContext; constructor() { + this.audioLoaded = new EventEmitter(); + // 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]); diff -r 0571cf863026 -r 7e3ab6f8792f src/app/waveform/waveform.component.ts --- 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'); } + }