/* * Ext JS Library 0.30 * Copyright(c) 2006-2009, Ext JS, LLC. * licensing@extjs.com * * http://extjs.com/license */ Ext.ns('Ext.air'); Ext.air.MusicPlayer = Ext.extend(Ext.util.Observable, { /** * The currently active Sound. Read-only. * @type air.Sound * @property activeSound */ activeSound: null, /** * The currently active SoundChannel. Read-only. * @type air.SoundChannel * @property activeChannel */ activeChannel: null, /** * The currently active Transform. Read-only. * @type air.SoundTransform * @property activeTransform */ activeTransform: new air.SoundTransform(1, 0), // private pausePosition: 0, /** * @cfg {Number} progressInterval * How often to fire the progress event when playing music in milliseconds * Defaults to 500. */ progressInterval: 500, constructor: function(config) { config = config || {}; Ext.apply(this, config); this.addEvents( /** * @event stop */ 'stop', /** * @event pause */ 'pause', /** * @event play */ 'play', /** * @event load */ 'load', /** * @event id3info */ 'id3info', /** * @event complete */ 'complete', /** * @event progress */ 'progress', /** * @event skip */ 'skip' ); Ext.air.MusicPlayer.superclass.constructor.call(this, config); this.onSoundFinishedDelegate = this.onSoundFinished.createDelegate(this); this.onSoundLoadDelegate = this.onSoundLoad.createDelegate(this); this.onSoundID3LoadDelegate = this.onSoundID3Load.createDelegate(this); Ext.TaskMgr.start({ run: this.notifyProgress, scope: this, interval: this.progressInterval }); }, /** * Adjust the volume * @param {Object} percent * Ranges from 0 to 1 specifying volume of sound. */ adjustVolume: function(percent) { this.activeTransform.volume = percent; if (this.activeChannel) { this.activeChannel.soundTransform = this.activeTransform; } }, /** * Stop the player */ stop: function() { this.pausePosition = 0; if (this.activeChannel) { this.activeChannel.stop(); this.activeChannel = null; } if (this.activeSound) { this.activeSound.removeEventListener(air.Event.COMPLETE, this.onSoundLoadDelegate); this.activeSound.removeEventListener(air.Event.ID3, this.onSoundID3LoadDelegate); this.activeSound.removeEventListener(air.Event.SOUND_COMPLETE, this.onSoundFinishedDelegate); } }, /** * Pause the player if there is an activeChannel */ pause: function() { if (this.activeChannel) { this.pausePosition = this.activeChannel.position; this.activeChannel.stop(); } }, /** * Play a sound, if no url is specified will attempt to resume the activeSound * @param {String} url (optional) * Url resource to play */ play: function(url) { if (url) { this.stop(); var req = new air.URLRequest(url); this.activeSound = new air.Sound(); this.activeSound.addEventListener(air.Event.SOUND_COMPLETE, this.onSoundFinishedDelegate); this.activeSound.addEventListener(air.Event.COMPLETE, this.onSoundLoadDelegate); this.activeSound.addEventListener(air.Event.ID3, this.onSoundID3LoadDelegate); this.activeSound.load(req); } else { this.onSoundLoad(); } }, /** * Skip to a specific position in the song currently playing. * @param {Object} pos */ skipTo: function(pos) { if (this.activeChannel) { this.activeChannel.stop(); this.activeChannel = this.activeSound.play(pos); this.activeChannel.soundTransform = this.activeTransform; this.fireEvent('skip', this.activeChannel, this.activeSound, pos); } }, /** * Returns whether or not there is an active SoundChannel. */ hasActiveChannel: function() { return !!this.activeChannel; }, // private onSoundLoad: function(event) { if (this.activeSound) { if (this.activeChannel) { this.activeChannel.stop(); } this.activeChannel = this.activeSound.play(this.pausePosition); this.activeChannel.soundTransform = this.activeTransform; this.fireEvent('load', this.activeChannel, this.activeSound); } }, // private onSoundFinished: function(event) { // relay AIR event this.fireEvent('complete', event); }, // private onSoundID3Load: function(event) { this.activeSound.removeEventListener(air.Event.ID3, this.onSoundID3LoadDelegate); var id3 = event.target.id3; this.fireEvent('id3info', id3); }, // private notifyProgress: function() { if (this.activeChannel && this.activeSound) { var playbackPercent = 100 * (this.activeChannel.position / this.activeSound.length); // SOUND_COMPLETE does not seem to work consistently. if (playbackPercent > 99.7) { this.onSoundFinished(); } else { this.fireEvent('progress', this.activeChannel, this.activeSound); } } } });