8398c9048d
code was modified slightly, so the code differs from the original downloadable 1.9.5 version
350 lines
8.4 KiB
JavaScript
350 lines
8.4 KiB
JavaScript
dojo.provide("dojox.av.FLAudio");
|
|
dojo.experimental("dojox.av.FLAudio");
|
|
dojo.require("dijit._Widget");
|
|
dojo.require("dojox.embed.Flash");
|
|
dojo.require("dojox.av._Media");
|
|
dojo.require("dojox.timing.doLater");
|
|
|
|
|
|
dojo.declare("dojox.av.FLAudio", null, {
|
|
|
|
// summary:
|
|
// Play MP3 files through the Flash SWF built in the
|
|
// DEFT project.
|
|
// description:
|
|
// This class is brand new, so there is a lot of
|
|
// functionality not yet available. The initial
|
|
// purpose is for playing "event" sounds like button
|
|
// clicks, and for loading and controlling multiple
|
|
// sounds at once. As of yet, streaming is not supported
|
|
// and polling the sounds for events during playback
|
|
// may still be missing information. Markup is not
|
|
// supported, as it may not be needed.
|
|
//
|
|
// TODO:
|
|
// Streaming, playback events, crossdomain, CDN support,
|
|
// (alternate SWF location), global volume, ID3 tag,
|
|
// factor out doLater, onLoadStatus needs work,
|
|
// play(position) / seek()
|
|
//
|
|
// example:
|
|
// | new dojox.av.FLAudio({
|
|
// | initialVolume:.7,
|
|
// | initialPan:0,
|
|
// | autoPlay:false
|
|
// | });
|
|
//
|
|
// id: String?
|
|
// The id of this widget and the id of the SWF movie.
|
|
id:"",
|
|
//
|
|
// initialVolume: Number
|
|
// From 0-1
|
|
// Sets volume for all files unless changed with doPlay
|
|
// or setVolume
|
|
initialVolume: 0.7,
|
|
//
|
|
// initialPan: Number
|
|
// From -1 to 1 (-1 is left, 1 is right, 0 is middle)
|
|
// Sets pan for all files unless changed with play
|
|
// or setPan
|
|
initialPan: 0,
|
|
//
|
|
// autoPlay: Boolean
|
|
// If true, all files will play upon load. If false,
|
|
// they load and wait for doPlay() command.
|
|
//
|
|
// isDebug: Boolean?
|
|
// Setting to true tells the SWF to output log messages to Firebug.
|
|
isDebug: false,
|
|
//
|
|
// statusInterval: Number
|
|
// How often in milliseconds that the status of the
|
|
// player is checked - both load and play
|
|
statusInterval:200,
|
|
//
|
|
// _swfPath: Uri
|
|
// The path to the video player SWF resource
|
|
_swfPath: dojo.moduleUrl("dojox.av", "resources/audio.swf"),
|
|
//
|
|
//
|
|
constructor: function(/*Object*/options){
|
|
dojo.mixin(this, options || {});
|
|
if(!this.id){ this.id = "flaudio_"+new Date().getTime(); }
|
|
this.domNode = dojo.doc.createElement("div");
|
|
dojo.style(this.domNode, {
|
|
postion:"relative",
|
|
width:"1px",
|
|
height:"1px",
|
|
top:"1px",
|
|
left:"1px"
|
|
});
|
|
dojo.body().appendChild(this.domNode);
|
|
this.init();
|
|
},
|
|
|
|
init: function(){
|
|
// summary:
|
|
// Initialize the media.
|
|
//
|
|
//
|
|
this._subs = [];
|
|
this.initialVolume = this._normalizeVolume(this.initialVolume);
|
|
|
|
var args = {
|
|
path:this._swfPath.uri,
|
|
width:"1px",
|
|
height:"1px",
|
|
minimumVersion:9, // this may need to be 10, not sure
|
|
expressInstall:true,
|
|
params:{
|
|
wmode:"transparent"
|
|
},
|
|
// only pass in simple variables - no deep objects
|
|
vars:{
|
|
id:this.id,
|
|
autoPlay:this.autoPlay,
|
|
initialVolume:this.initialVolume,
|
|
initialPan:this.initialPan,
|
|
statusInterval:this.statusInterval,
|
|
isDebug:this.isDebug
|
|
}
|
|
};
|
|
|
|
this._sub("mediaError", "onError");
|
|
this._sub("filesProgress", "onLoadStatus");
|
|
this._sub("filesAllLoaded", "onAllLoaded");
|
|
this._sub("mediaPosition", "onPlayStatus");
|
|
this._sub("mediaMeta", "onID3");
|
|
|
|
this._flashObject = new dojox.embed.Flash(args, this.domNode);
|
|
this._flashObject.onError = function(err){
|
|
console.warn("Flash Error:", err);
|
|
alert(err);
|
|
};
|
|
this._flashObject.onLoad = dojo.hitch(this, function(mov){
|
|
this.flashMedia = mov;
|
|
this.isPlaying = this.autoPlay;
|
|
this.isStopped = !this.autoPlay;
|
|
this.onLoad(this.flashMedia);
|
|
});
|
|
},
|
|
|
|
// ============== //
|
|
// Loading Files //
|
|
// ============== //
|
|
|
|
load: function(/*Object*/options){
|
|
// summary:
|
|
// Adds a media object to the playlist
|
|
// ***This can be called repeatedly to add multiple items.
|
|
// options: Object
|
|
// url: String
|
|
// (required) path to MP3 media
|
|
// url must be absolute or relative to SWF,
|
|
// not dojo or the html. An effort will be made
|
|
// to fix incorrect paths.
|
|
// id: String
|
|
// (optional) an identifier to later determine
|
|
// which media to control.
|
|
// returns:
|
|
// The normalized url, which can be used to identify the
|
|
// audio.
|
|
//
|
|
if(dojox.timing.doLater(this.flashMedia, this)){ return false; }
|
|
if(!options.url){
|
|
throw new Error("An url is required for loading media");
|
|
return false;
|
|
}else{
|
|
options.url = this._normalizeUrl(options.url);
|
|
}
|
|
this.flashMedia.load(options);
|
|
|
|
return options.url; // String
|
|
},
|
|
|
|
// ============================= //
|
|
// Methods to control the sound //
|
|
// ============================= //
|
|
|
|
doPlay: function(/*Object*/options){
|
|
// summary:
|
|
// Tell media to play, based on
|
|
// the options passed.
|
|
// options: Object
|
|
// volume: Number
|
|
// Sets the volume
|
|
// pan: Number
|
|
// Sets left/right pan
|
|
// index:Number OR id:String OR url:String
|
|
// Choose one of the above to indentify
|
|
// the media you wish to control. id is
|
|
// set by you. index is the order in which
|
|
// media was added (zero based)
|
|
// NOTE: lack of an identifier will default
|
|
// to first (or only) item.
|
|
// NOTE: Can't name this method "play()" as it causes
|
|
// an IE error.
|
|
this.flashMedia.doPlay(options);
|
|
},
|
|
|
|
pause: function(/*Object*/options){
|
|
// summary:
|
|
// Tell media to pause, based on identifier in
|
|
// the options passed.
|
|
// options: Object
|
|
// index:Number OR id:String OR url:String
|
|
// See doPlay()
|
|
//
|
|
this.flashMedia.pause(options);
|
|
},
|
|
|
|
stop: function(/*Object*/options){
|
|
// summary:
|
|
// Tell media to stop, based on identifier in
|
|
// the options passed.
|
|
// options:
|
|
// index:Number OR id:String OR url:String
|
|
// See doPlay()
|
|
//
|
|
this.flashMedia.doStop(options);
|
|
},
|
|
|
|
setVolume: function(/*Object*/options){
|
|
// summary:
|
|
// Set media volume, based on identifier in
|
|
// the options passed.
|
|
// options:
|
|
// volume: Number
|
|
// 0 to 1
|
|
// index:Number OR id:String OR url:String
|
|
// See doPlay()
|
|
//
|
|
this.flashMedia.setVolume(options);
|
|
},
|
|
|
|
setPan: function(/*Object*/options){
|
|
// summary:
|
|
// Set media pan, based on identifier in
|
|
// the options passed.
|
|
// options:
|
|
// pan:Number
|
|
// -1 to 1
|
|
// index:Number OR id:String OR url:String
|
|
// See doPlay()
|
|
//
|
|
this.flashMedia.setPan(options);
|
|
},
|
|
|
|
getVolume: function(/*Object*/options){
|
|
// summary:
|
|
// Get media volume, based on identifier in
|
|
// the options passed.
|
|
// options:
|
|
// index:Number OR id:String OR url:String
|
|
// See doPlay()
|
|
//
|
|
return this.flashMedia.getVolume(options);
|
|
},
|
|
|
|
getPan: function(/*Object*/options){
|
|
// summary:
|
|
// Set media pan, based on identifier in
|
|
// the options passed.
|
|
// options:
|
|
// index:Number OR id:String OR url:String
|
|
// See doPlay()
|
|
//
|
|
return this.flashMedia.getPan(options);
|
|
},
|
|
|
|
|
|
// ============= //
|
|
// Sound Events //
|
|
// ============= //
|
|
onError: function(msg){
|
|
// summary:
|
|
// stub fired when an error occurs
|
|
console.warn("SWF ERROR:", msg)
|
|
},
|
|
|
|
onLoadStatus: function(/*Array*/events){
|
|
// summary:
|
|
},
|
|
|
|
onAllLoaded: function(){
|
|
// summary:
|
|
// stub fired
|
|
},
|
|
|
|
onPlayStatus: function(/*Array*/events){
|
|
// summary:
|
|
},
|
|
|
|
onLoad: function(){
|
|
// summary:
|
|
// stub fired when SWF is ready
|
|
},
|
|
onID3: function(evt){
|
|
// summary:
|
|
// Fired when the ID3 data is received.
|
|
},
|
|
|
|
|
|
|
|
destroy: function(){
|
|
// summary:
|
|
// destroys flash
|
|
if(!this.flashMedia){
|
|
this._cons.push(dojo.connect(this, "onLoad", this, "destroy"));
|
|
return;
|
|
}
|
|
dojo.forEach(this._subs, function(s){
|
|
dojo.unsubscribe(s);
|
|
});
|
|
dojo.forEach(this._cons, function(c){
|
|
dojo.disconnect(c);
|
|
});
|
|
this._flashObject.destroy();
|
|
//dojo._destroyElement(this.flashDiv);
|
|
},
|
|
|
|
|
|
|
|
_sub: function(topic, method){
|
|
// summary:
|
|
// helper for subscribing to topics
|
|
dojo.subscribe(this.id+"/"+topic, this, method);
|
|
},
|
|
|
|
_normalizeVolume: function(vol){
|
|
// summary:
|
|
// Ensures volume is less than one
|
|
//
|
|
if(vol>1){
|
|
while(vol>1){
|
|
vol*=.1
|
|
}
|
|
}
|
|
return vol;
|
|
},
|
|
|
|
_normalizeUrl: function(_url){
|
|
// summary:
|
|
// Checks that path is relative to HTML file or
|
|
// convertes it to an absolute path.
|
|
//
|
|
if(_url && _url.toLowerCase().indexOf("http")<0){
|
|
//
|
|
// Appears to be a relative path. Attempt to convert it to absolute,
|
|
// so it will better target the SWF.
|
|
var loc = window.location.href.split("/");
|
|
loc.pop();
|
|
loc = loc.join("/")+"/";
|
|
|
|
_url = loc+_url;
|
|
}
|
|
return _url;
|
|
}
|
|
|
|
});
|