Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Augment iAudioTrack with useful state change events #117

Open
wants to merge 5 commits into
base: 3.0
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Add several useful events on IAudioTrack for its state changes
  • Loading branch information
codinronan committed May 5, 2017
commit e06c6dc1b9c9f9547ad9dd0127fb92e7a7a61b32
164 changes: 111 additions & 53 deletions dist/ionic-audio-cordova-track.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import {IAudioTrack} from './ionic-audio-interfaces';
import {Injectable} from '@angular/core';
import {IAudioTrack, IAudioTrackError} from './ionic-audio-interfaces';
import {Injectable, EventEmitter} from '@angular/core';

declare let Media: any;

/**
* Cordova Media audio track
*
*
* @export
* @class CordovaAudioTrack
* @constructor
Expand All @@ -16,120 +16,176 @@ export class CordovaAudioTrack implements IAudioTrack {
private audio: any;
public isPlaying: boolean = false;
public isFinished: boolean = false;
public isLoaded: boolean = false;
private _progress: number = 0;
private _completed: number = 0;
private _duration: number;
private _id: number;
private _isLoading: boolean;
private _hasLoaded: boolean;
private _timer: any;


/**
* Notifies when the track has loaded
*
* @property onPlayBegin
* @type {EventEmitter}
*/
onLoaded: EventEmitter<IAudioTrack> = new EventEmitter();

/**
* Notifies when playback has begun
*
* @property onPlayBegin
* @type {EventEmitter}
*/
onPlaying: EventEmitter<IAudioTrack> = new EventEmitter();

/**
* Notifies when playback has begun
*
* @property onPlayBegin
* @type {EventEmitter}
*/
onStop: EventEmitter<IAudioTrack> = new EventEmitter();

/**
* Notifies when playback has completed
*
* @property onPlayBegin
* @type {EventEmitter}
*/
onFinished: EventEmitter<IAudioTrack> = new EventEmitter();

/**
* Notifies when playback has begun
*
* @property onPlayBegin
* @type {EventEmitter}
*/
onProgressChange: EventEmitter<IAudioTrack> = new EventEmitter();

/**
* Notifies when the media has experienced an error
*
* @property onPlayBegin
* @type {EventEmitter}
*/
onError: EventEmitter<IAudioTrackError> = new EventEmitter();

constructor(public src: string) {
if (window['cordova'] === undefined || window['Media'] === undefined) {
console.log('Cordova Media is not available');
return;
};
this.createAudio();

this.createAudio();
}

private createAudio() {
this.audio = new Media(this.src, () => {
console.log('Finished playback');
this.stopTimer();
this.isFinished = true;
this.isFinished = true;
this.onFinished.emit(this);
this.destroy(); // TODO add parameter to control whether to release audio on stop or finished
}, (err) => {
console.log(`Audio error => track ${this.src}`, err);
console.log(`Audio error => track ${this.src}`, err);
this.onError.emit({track: this, error: err});
}, (status) => {
switch (status) {
case Media.MEDIA_STARTING:
console.log(`Loaded track ${this.src}`);
this._hasLoaded = true;
this.isLoaded = true;
this.onLoaded.emit(this);
break;
case Media.MEDIA_RUNNING:
console.log(`Playing track ${this.src}`);
this.isPlaying = true;
this._isLoading = false;
break;
this._isLoading = false;
this.onPlaying.emit(this);
break;
case Media.MEDIA_PAUSED:
this.isPlaying = false;
break
case Media.MEDIA_STOPPED:
this.isPlaying = false;
this.onStop.emit(this);
break;
}
});
});
}

private startTimer() {
this._timer = setInterval(() => {
this._timer = setInterval(() => {
if (this._duration===undefined || this._duration < 0) {
this._duration = Math.round(this.audio.getDuration()*100)/100;
}
}

this.audio.getCurrentPosition((position) => {
if (position > -1) {
this._progress = Math.round(position*100)/100;
this._completed = this._duration > 0 ? Math.round(this._progress / this._duration * 100)/100 : 0;
this._completed = this._duration > 0 ? Math.round(this._progress / this._duration * 100)/100 : 0;
this.onProgressChange.emit(this);
}
}, (e) => {
console.log("Error getting position", e);
}
);
}, 1000);
}, 1000);
}

private stopTimer() {
clearInterval(this._timer);
}

/** public members */

/**
* Gets the track id
*
*
* @property id
* @type {number}
*/
public get id() : number {
return this._id;
}

/**
* Sets the track id
*
*
* @property id
*/
public set id(v : number) {
this._id = v;
}

/**
* Gets the track duration, or -1 if it cannot be determined
*
*
* @property duration
* @readonly
* @type {number}
*/
public get duration() : number {
return this._duration;
}

/**
* Gets current track time (progress)
*
*
* @property progress
* @readonly
* @type {number}
*/
public get progress() : number {
return this._progress;
}
}

/**
* Gets current track progress as a percentage
*
*
* @property completed
* @readonly
* @type {number}
Expand All @@ -141,105 +197,107 @@ export class CordovaAudioTrack implements IAudioTrack {
/**
* Gets any errors logged by HTML5 audio
*
* @property error
* @property error
* @readonly
* @type {MediaError}
*/
public get error() : MediaError {
return this.audio.error;
}

/**
* Gets a boolean value indicating whether the current source can be played
*
*
* @property canPlay
* @readonly
* @type {boolean}
*/
public get canPlay() : boolean {
return true;
}

/**
* Gets a boolean value indicating whether the track is in loading state
*
*
* @property isLoading
* @readonly
* @type {boolean}
*/
public get isLoading() : boolean {
return this._isLoading;
}

/**
* Gets a boolean value indicating whether the track has finished loading
*
* @property hadLoaded
* @property hadLoaded
* @readonly
* @type {boolean}
*/
public get hasLoaded() : boolean {
return this._hasLoaded;
}

/**
* Plays current track
*
*
* @method play
*/
play() {
if (!this.audio) {
this.createAudio();
this.createAudio();
}

if (!this._hasLoaded) {
console.log(`Loading track ${this.src}`);
this._isLoading = true;
}

this.audio.play();
this.startTimer();
}

/**
* Pauses current track
*
* @method pause
* @method pause
*/
pause() {
if (!this.isPlaying) return;
console.log(`Pausing track ${this.src}`);
this.audio.pause();
this.stopTimer();
this.stopTimer();
}

/**
* Stops current track and releases audio
*
* @method stop
* @method stop
*/
stop() {
this.audio.stop(); // calls Media onSuccess callback
}

/**
* Seeks to a new position within the track
*
* @method seekTo
* @method seekTo
* @param {number} time the new position (milliseconds) to seek to
*/
seekTo(time: number) {
// Cordova Media reports duration and progress as seconds, so we need to multiply by 1000
this.audio.seekTo(time*1000);
}

/**
* Releases audio resources
*
*
* @method destroy
*/
destroy() {
this.audio.release();
this.isLoaded = false;
this._hasLoaded = false;
this.audio.release();
console.log(`Released track ${this.src}`);
}
}
}
Loading