UNPKG

ngx-soundmanager2

Version:
637 lines 23.3 kB
/** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ import { Inject, Injectable, EventEmitter, Optional } from '@angular/core'; import { MusicPlayerEventConstants } from './music-player-events.constants'; import { MusicPlayerUtils } from './music-player.utils'; export class MusicPlayerService { /** * @param {?=} setupOptions */ constructor(setupOptions) { this.setupOptions = setupOptions; this.currentTrack = null; this.repeat = false; this.autoPlay = true; this.isPlaying = false; this.trackProgress = 0; this.volume = 90; this.playlist = []; this.musicPlayerEventEmitter = new EventEmitter(); this.musicPlayerMuteEventEmitter = new EventEmitter(); this.musicPlayerRepeatEventEmitter = new EventEmitter(); this.musicPlayerStopEventEmitter = new EventEmitter(); this.musicPlayerTrackEventEmitter = new EventEmitter(); this.musicPlayerVolumeEventEmitter = new EventEmitter(); this.init(setupOptions); } /** * Initialize soundmanager, * requires soundmanager2 to be loaded first * @param {?=} setupOptions * @return {?} */ init(setupOptions) { if (typeof soundManager === 'undefined') { alert('Please include SoundManager2 Library!'); } Object.assign(soundManager.setupOptions, setupOptions); soundManager.setupOptions.ignoreMobileRestrictions = true; this._soundObject = soundManager.setup({ preferFlash: false, // prefer 100% HTML5 mode, where both supported debugMode: false, // enable debugging output useHTML5Audio: true, // http://www.schillmania.com/projects/soundmanager2/doc/#soundmanager-usehtml5audio /** * @reference http://www.schillmania.com/projects/soundmanager2/doc/#sm-config * @description onready Events (Callbacks) * Queues an event callback/handler for successful initialization and "ready to use" state of SoundManager 2. * An optional scope parameter can be specified; if none, the callback is scoped to the window. * If onready() is called after successful initialization, the callback will be executed immediately. * The onready() queue is processed before soundManager.onload(). */ onready: () => { // Assign instance of this Angular MusicPlayerService to soundManager object // so that the SMSound Objects can access it soundManager.parent = this; // Ready to use; soundManager.createSound() etc. can now be called. // Emit event const /** @type {?} */ isSupported = soundManager.ok(); this.musicPlayerEventEmitter.emit({ event: MusicPlayerEventConstants.ANGULAR_PLAYER_READY, data: isSupported }); }, /** * @reference http://www.schillmania.com/projects/soundmanager2/doc/#sm-config * @description ontimeout Events (Callbacks) * Queues an event callback/handler for SM2 init failure, processed at (or immediately, * if added after) SM2 initialization has failed, just before soundManager.onerror() is called. * An optional scope parameter can be specified; if none, the callback is scoped to the window. * Additionally, a status object containing success and error->type parameters is passed as an argument to your callback. */ ontimeout: () => { alert('SM2 failed to start. Flash missing, blocked or security error?'); alert('The status is ' + this._soundObject.status.success + ', the error type is ' + this._soundObject.status.error.type); }, defaultOptions: { // set global default volume for all sound objects autoLoad: false, // enable automatic loading (otherwise .load() will call with .play()) autoPlay: false, // enable playing of file ASAP (much faster if "stream" is true) from: null, // position to start playback within a sound (msec), see demo loops: 1, // number of times to play the sound. Related: looping (API demo) multiShot: false, // let sounds "restart" or "chorus" when played multiple times.. multiShotEvents: false, // allow events (onfinish()) to fire for each shot, if supported. onid3: null, // callback function for "ID3 data is added/available" onload: null, // callback function for "load finished" onstop: null, // callback for "user stop" onfailure: 'nextTrack', // callback function for when playing fails onpause: null, // callback for "pause" onplay: null, // callback for "play" start onresume: null, // callback for "resume" (pause toggle) position: null, // offset (milliseconds) to seek to within downloaded sound. pan: 0, // "pan" settings, left-to-right, -100 to 100 stream: true, // allows playing before entire file has loaded (recommended) to: null, // position to end playback within a sound (msec), see demo type: 'audio/mp3', // MIME-like hint for canPlay() tests, eg. 'audio/mp3' usePolicyFile: false, // enable crossdomain.xml request for remote domains (for ID3/waveform access) volume: this.volume, // self-explanatory. 0-100, the latter being the max. /** * SMSound (sound instance) object instance event handler * @note Event handlers are scoped to the relevant sound object, * so the this keyword will point to the sound object on which * the event fired such that its properties can easily be accessed */ whileloading: function () { soundManager._writeDebug('sound ' + this.id + ' loading, ' + this.bytesLoaded + ' of ' + this.bytesTotal); const /** @type {?} */ trackLoaded = ((this.bytesLoaded / this.bytesTotal) * 100); const /** @type {?} */ musicPlayerService = soundManager.parent; if (musicPlayerService) { musicPlayerService.musicPlayerEventEmitter.emit({ event: MusicPlayerEventConstants.TRACK_LOADED, data: trackLoaded }); } }, /** * SMSound (sound instance) object instance event handler * @note Event handlers are scoped to the relevant sound object, * so the this keyword will point to the sound object on which * the event fired such that its properties can easily be accessed */ whileplaying: function () { soundManager._writeDebug('sound ' + this.id + ' playing, ' + this.position + ' of ' + this.duration); const /** @type {?} */ musicPlayerService = soundManager.parent; if (musicPlayerService) { // broadcast current playing track id musicPlayerService.currentTrack = this.id; try { musicPlayerService.trackProgress = ((this.position / this.duration) * 100); musicPlayerService.position = this.position; musicPlayerService.duration = this.duration; } catch (/** @type {?} */ error) { musicPlayerService.trackProgress = 0; musicPlayerService.position = 0; musicPlayerService.duration = 0; } const /** @type {?} */ trackEventData = { trackId: musicPlayerService.currentTrack, trackProgress: musicPlayerService.trackProgress, trackPosition: this.position, trackDuration: this.duration }; musicPlayerService.musicPlayerTrackEventEmitter.emit({ event: MusicPlayerEventConstants.TRACK_ID, data: trackEventData }); } }, /** * SMSound (sound instance) object instance event handler * @note Using ES6 and this refers to the Angular MusicPlayerService instances * instead of the SMSound object instance */ onfinish: () => { if (this.autoPlay === true) { this.nextTrack(); const /** @type {?} */ trackEventData = { trackId: this.currentTrack, trackProgress: this.trackProgress, trackDuration: 0, trackPosition: 0 }; this.musicPlayerTrackEventEmitter.emit({ event: MusicPlayerEventConstants.TRACK_ID, data: trackEventData }); } } } }); } /** * @param {?} key * @return {?} */ setCurrentTrack(key) { this.currentTrack = key; } /** * @return {?} */ getCurrentTrack() { return this.currentTrack; } /** * @return {?} */ currentTrackData() { const /** @type {?} */ trackId = this.getCurrentTrack(); const /** @type {?} */ currentKey = MusicPlayerUtils.IsInArray(this.playlist, trackId); return this.playlist[currentKey]; } /** * * @param {?=} key * @return {?} */ getPlaylist(key) { if (typeof key === 'undefined') { return this.playlist; } else { return this.playlist[key]; } } /** * * @param {?} track * @return {?} */ addToPlaylist(track) { this.playlist.push(track); // broadcast playlist this.musicPlayerEventEmitter.emit({ event: MusicPlayerEventConstants.PLAYER_PLAYLIST, data: this.playlist }); } /** * * @param {?} track * @return {?} */ addTrack(track) { // check if track itself is valid and if its url is playable if (!MusicPlayerUtils.IsTrackValid) { return null; } // check if song already does not exists then add to playlist const /** @type {?} */ inArrayKey = MusicPlayerUtils.IsInArray(this.getPlaylist(undefined), track.id); if (inArrayKey < 0) { // console.warn('song does not exists in playlist:', track); // add to sound manager soundManager.createSound({ id: track.id, url: track.url }); // add to playlist this.addToPlaylist(track); } return track.id; } /** * @param {?} song * @param {?} index * @return {?} */ removeSong(song, index) { // if this song is playing stop it if (song === this.currentTrack) { this.stop(); } // unload from soundManager soundManager.destroySound(song); // remove from playlist this.playlist.splice(index, 1); // once all done then broadcast this.musicPlayerEventEmitter.emit({ event: MusicPlayerEventConstants.PLAYER_PLAYLIST, data: this.playlist }); } /** * * @param {?} trackId * @param {?} isResume * @return {?} */ initPlayTrack(trackId, isResume) { if (isResume !== true) { // stop and unload currently playing track this.stop(); // set new track as current track this.setCurrentTrack(trackId); } // play it soundManager.play(trackId); const /** @type {?} */ trackEventData = { trackId: this.currentTrack, trackProgress: this.trackProgress, trackDuration: this.duration, trackPosition: 0 }; this.musicPlayerTrackEventEmitter.emit({ event: MusicPlayerEventConstants.TRACK_ID, data: trackEventData }); // set as playing this.isPlaying = true; this.musicPlayerEventEmitter.emit({ event: MusicPlayerEventConstants.MUSIC_IS_PLAYING, data: this.isPlaying }); } /** * Plays currently selected track * If the track is already playing, ignore event * @return {?} */ play() { if (!this.isPlaying) { let /** @type {?} */ trackToPlay = null; // check if no track loaded, else play loaded track if (this.getCurrentTrack() === null) { if (soundManager.soundIDs.length === 0) { return; } trackToPlay = soundManager.soundIDs[0]; this.initPlayTrack(trackToPlay, false); } else { trackToPlay = this.getCurrentTrack(); this.initPlayTrack(trackToPlay, true); } } } /** * Toggles Pause state * @return {?} */ pause() { this.isPlaying = !this.isPlaying; if (this.isPlaying) { soundManager.play(this.currentTrack); } else { soundManager.pause(this.getCurrentTrack()); } this.musicPlayerEventEmitter.emit({ event: MusicPlayerEventConstants.MUSIC_IS_PLAYING, data: this.isPlaying }); } /** * Stops audio playback and clears playback status * @return {?} */ stop() { // first pause it soundManager.pause(this.getCurrentTrack()); this.isPlaying = false; this.resetProgress(); const /** @type {?} */ trackEventData = { trackId: this.currentTrack, trackProgress: this.trackProgress, trackDuration: 0, trackPosition: 0 }; this.musicPlayerStopEventEmitter.emit({ event: MusicPlayerEventConstants.TRACK_STOP, data: trackEventData }); soundManager.stopAll(); soundManager.unload(this.getCurrentTrack()); } /** * Plays selected track * @param {?} trackId * @return {?} */ playTrack(trackId) { this.initPlayTrack(trackId, false); } /** * * @return {?} */ nextTrack() { if (this.getCurrentTrack() === null) { console.log('Please click on Play before this action'); return null; } const /** @type {?} */ currentTrackKey = MusicPlayerUtils.GetIndexByValue(soundManager.soundIDs, this.getCurrentTrack()); const /** @type {?} */ nextTrackKey = +currentTrackKey + 1; const /** @type {?} */ nextTrack = soundManager.soundIDs[nextTrackKey]; if (typeof nextTrack !== 'undefined') { this.playTrack(nextTrack); } else { // if no next track found if (this.repeat === true) { // start first track if repeat is on this.playTrack(soundManager.soundIDs[0]); } else { // breadcase not playing anything this.isPlaying = false; this.musicPlayerEventEmitter.emit({ event: MusicPlayerEventConstants.MUSIC_IS_PLAYING, data: this.isPlaying }); } } } /** * * @return {?} */ prevTrack() { if (this.getCurrentTrack() === null) { console.log('Please click on Play before this action'); return null; } const /** @type {?} */ currentTrackKey = MusicPlayerUtils.GetIndexByValue(soundManager.soundIDs, this.getCurrentTrack()); const /** @type {?} */ prevTrackKey = +currentTrackKey - 1; const /** @type {?} */ prevTrack = soundManager.soundIDs[prevTrackKey]; if (typeof prevTrack !== 'undefined') { this.playTrack(prevTrack); } else { console.warn('no prev track found!'); } } /** * Mute/Unmute audio * @return {?} */ mute() { if (soundManager.muted === true) { soundManager.unmute(); } else { soundManager.mute(); } this.musicPlayerMuteEventEmitter.emit({ event: MusicPlayerEventConstants.MUSIC_MUTE, data: soundManager.muted }); } /** * Mute Accessor * @return {?} */ getMuteStatus() { return soundManager.muted; } /** * * @return {?} */ repeatToggle() { if (this.repeat === true) { this.repeat = false; } else { this.repeat = true; } this.musicPlayerRepeatEventEmitter.emit({ event: MusicPlayerEventConstants.MUSIC_REPEAT, data: this.repeat }); return false; } /** * @return {?} */ getRepeatStatus() { return this.repeat; } /** * @return {?} */ getVolume() { return this.volume; } /** * * @param {?} increase * @return {?} */ adjustVolume(increase) { const /** @type {?} */ changeVolume = (volume) => { for (let /** @type {?} */ i = 0; i < soundManager.soundIDs.length; i++) { const /** @type {?} */ mySound = soundManager.getSoundById(soundManager.soundIDs[i]); mySound.setVolume(volume); } this.musicPlayerVolumeEventEmitter.emit({ event: MusicPlayerEventConstants.MUSIC_VOLUME, data: volume }); }; if (increase === true) { if (this.volume < 100) { this.volume = this.volume + 10; changeVolume(this.volume); } } else { if (this.volume > 0) { this.volume = this.volume - 10; changeVolume(this.volume); } } } /** * * @param {?} value * @return {?} */ adjustVolumeSlider(value) { const /** @type {?} */ changeVolume = (volume) => { for (let /** @type {?} */ i = 0; i < soundManager.soundIDs.length; i++) { const /** @type {?} */ mySound = soundManager.getSoundById(soundManager.soundIDs[i]); mySound.setVolume(volume); } this.musicPlayerVolumeEventEmitter.emit({ event: MusicPlayerEventConstants.MUSIC_VOLUME, data: volume }); }; changeVolume(value); } /** * * @param {?=} callback * @return {?} */ clearPlaylist(callback) { this.isPlaying = false; this.currentTrack = null; this.resetProgress(); // unload and destroy soundmanager sounds const /** @type {?} */ smIdsLength = soundManager.soundIDs.length; MusicPlayerUtils.AsyncLoop({ length: smIdsLength, functionToLoop: (loop /*, i: number*/) => { setTimeout(() => { // custom code soundManager.destroySound(soundManager.soundIDs[0]); // custom code loop(); }, 0); }, callback: () => { // callback custom code // clear playlist this.playlist = []; this.musicPlayerEventEmitter.emit({ event: MusicPlayerEventConstants.PLAYER_PLAYLIST, data: this.playlist }); if (callback) { // callback custom code callback(true); } } }); } /** * * @return {?} */ resetProgress() { this.trackProgress = 0; } /** * @return {?} */ isPlayingStatus() { return this.isPlaying; } } MusicPlayerService.decorators = [ { type: Injectable } ]; /** @nocollapse */ MusicPlayerService.ctorParameters = () => [ { type: Object, decorators: [{ type: Inject, args: ['setupOptions',] }, { type: Optional },] }, ]; function MusicPlayerService_tsickle_Closure_declarations() { /** @type {!Array<{type: !Function, args: (undefined|!Array<?>)}>} */ MusicPlayerService.decorators; /** * @nocollapse * @type {function(): !Array<(null|{type: ?, decorators: (undefined|!Array<{type: !Function, args: (undefined|!Array<?>)}>)})>} */ MusicPlayerService.ctorParameters; /** @type {?} */ MusicPlayerService.prototype.currentTrack; /** @type {?} */ MusicPlayerService.prototype.repeat; /** @type {?} */ MusicPlayerService.prototype.autoPlay; /** @type {?} */ MusicPlayerService.prototype.isPlaying; /** @type {?} */ MusicPlayerService.prototype.trackProgress; /** @type {?} */ MusicPlayerService.prototype.volume; /** @type {?} */ MusicPlayerService.prototype.position; /** @type {?} */ MusicPlayerService.prototype.duration; /** @type {?} */ MusicPlayerService.prototype.playlist; /** @type {?} */ MusicPlayerService.prototype.musicPlayerEventEmitter; /** @type {?} */ MusicPlayerService.prototype.musicPlayerMuteEventEmitter; /** @type {?} */ MusicPlayerService.prototype.musicPlayerRepeatEventEmitter; /** @type {?} */ MusicPlayerService.prototype.musicPlayerStopEventEmitter; /** @type {?} */ MusicPlayerService.prototype.musicPlayerTrackEventEmitter; /** @type {?} */ MusicPlayerService.prototype.musicPlayerVolumeEventEmitter; /** @type {?} */ MusicPlayerService.prototype._soundObject; /** @type {?} */ MusicPlayerService.prototype.setupOptions; } //# sourceMappingURL=music-player.service.js.map