1 /** The minplayer namespace. */
  2 var minplayer = minplayer || {};
  3 
  4 /** All the media player implementations */
  5 minplayer.players = minplayer.players || {};
  6 
  7 /**
  8  * @constructor
  9  * @extends minplayer.display
 10  * @class The HTML5 media player implementation.
 11  *
 12  * @param {object} context The jQuery context.
 13  * @param {object} options This components options.
 14  */
 15 minplayer.players.html5 = function(context, options) {
 16 
 17   // Derive players base.
 18   minplayer.players.base.call(this, context, options);
 19 };
 20 
 21 /** Derive from minplayer.players.base. */
 22 minplayer.players.html5.prototype = new minplayer.players.base();
 23 
 24 /** Reset the constructor. */
 25 minplayer.players.html5.prototype.constructor = minplayer.players.html5;
 26 
 27 /**
 28  * @see minplayer.players.base#getPriority
 29  * @return {number} The priority of this media player.
 30  */
 31 minplayer.players.html5.getPriority = function() {
 32   return 10;
 33 };
 34 
 35 /**
 36  * @see minplayer.players.base#canPlay
 37  * @return {boolean} If this player can play this media type.
 38  */
 39 minplayer.players.html5.canPlay = function(file) {
 40   switch (file.mimetype) {
 41     case 'video/ogg':
 42       return !!minplayer.playTypes.videoOGG;
 43     case 'video/mp4':
 44       return !!minplayer.playTypes.videoH264;
 45     case 'video/x-webm':
 46     case 'video/webm':
 47     case 'application/octet-stream':
 48       return !!minplayer.playTypes.videoWEBM;
 49     case 'audio/ogg':
 50       return !!minplayer.playTypes.audioOGG;
 51     case 'audio/mpeg':
 52       return !!minplayer.playTypes.audioMP3;
 53     case 'audio/mp4':
 54       return !!minplayer.playTypes.audioMP4;
 55     default:
 56       return false;
 57   }
 58 };
 59 
 60 /**
 61  * @see minplayer.plugin.construct
 62  */
 63 minplayer.players.html5.prototype.construct = function() {
 64 
 65   // Call base constructor.
 66   minplayer.players.base.prototype.construct.call(this);
 67 
 68   // Store the this pointer...
 69   var _this = this;
 70 
 71   // For the HTML5 player, we will just pass events along...
 72   if (this.player) {
 73 
 74     this.player.addEventListener('abort', function() {
 75       _this.trigger('abort');
 76     }, false);
 77     this.player.addEventListener('loadstart', function() {
 78       _this.onReady();
 79     }, false);
 80     this.player.addEventListener('loadeddata', function() {
 81       _this.onLoaded();
 82     }, false);
 83     this.player.addEventListener('loadedmetadata', function() {
 84       _this.onLoaded();
 85     }, false);
 86     this.player.addEventListener('canplaythrough', function() {
 87       _this.onLoaded();
 88     }, false);
 89     this.player.addEventListener('ended', function() {
 90       _this.onComplete();
 91     }, false);
 92     this.player.addEventListener('pause', function() {
 93       _this.onPaused();
 94     }, false);
 95     this.player.addEventListener('play', function() {
 96       _this.onPlaying();
 97     }, false);
 98     this.player.addEventListener('playing', function() {
 99       _this.onPlaying();
100     }, false);
101     this.player.addEventListener('error', function() {
102       _this.trigger('error', 'An error occured - ' + this.error.code);
103     }, false);
104     this.player.addEventListener('waiting', function() {
105       _this.onWaiting();
106     }, false);
107     this.player.addEventListener('durationchange', function() {
108       _this.duration.set(this.duration);
109       _this.trigger('durationchange', {duration: this.duration});
110     }, false);
111     this.player.addEventListener('progress', function(event) {
112       _this.bytesTotal.set(event.total);
113       _this.bytesLoaded.set(event.loaded);
114     }, false);
115   }
116 };
117 
118 /**
119  * @see minplayer.players.base#playerFound
120  * @return {boolean} TRUE - if the player is in the DOM, FALSE otherwise.
121  */
122 minplayer.players.html5.prototype.playerFound = function() {
123   return (this.display.find(this.mediaFile.type).length > 0);
124 };
125 
126 /**
127  * @see minplayer.players.base#create
128  * @return {object} The media player entity.
129  */
130 minplayer.players.html5.prototype.create = function() {
131   minplayer.players.base.prototype.create.call(this);
132   var element = jQuery(document.createElement(this.mediaFile.type))
133   .attr(this.options.attributes)
134   .append(
135     jQuery(document.createElement('source')).attr({
136       'src': this.mediaFile.path
137     })
138   );
139 
140   // Fix the fluid width and height.
141   element.eq(0)[0].setAttribute('width', '100%');
142   element.eq(0)[0].setAttribute('height', '100%');
143   return element;
144 };
145 
146 /**
147  * @see minplayer.players.base#getPlayer
148  * @return {object} The media player object.
149  */
150 minplayer.players.html5.prototype.getPlayer = function() {
151   return this.options.elements.media.eq(0)[0];
152 };
153 
154 /**
155  * @see minplayer.players.base#load
156  */
157 minplayer.players.html5.prototype.load = function(file) {
158 
159   if (file && this.isReady()) {
160 
161     // Get the current source.
162     var src = this.options.elements.media.attr('src');
163 
164     // If the source is different.
165     if (src != file.path) {
166 
167       // Change the source...
168       var code = '<source src="' + file.path + '" ';
169       code += 'type="' + file.mimetype + '"';
170       code += file.codecs ? ' codecs="' + file.path + '">' : '>';
171       this.options.elements.media.attr('src', '').empty().html(code);
172     }
173   }
174 
175   // Always call the base first on load...
176   minplayer.players.base.prototype.load.call(this, file);
177 };
178 
179 /**
180  * @see minplayer.players.base#play
181  */
182 minplayer.players.html5.prototype.play = function() {
183   minplayer.players.base.prototype.play.call(this);
184   if (this.isReady()) {
185     this.player.play();
186   }
187 };
188 
189 /**
190  * @see minplayer.players.base#pause
191  */
192 minplayer.players.html5.prototype.pause = function() {
193   minplayer.players.base.prototype.pause.call(this);
194   if (this.isReady()) {
195     this.player.pause();
196   }
197 };
198 
199 /**
200  * @see minplayer.players.base#stop
201  */
202 minplayer.players.html5.prototype.stop = function() {
203   minplayer.players.base.prototype.stop.call(this);
204   if (this.isReady()) {
205     this.player.pause();
206     this.player.src = '';
207   }
208 };
209 
210 /**
211  * @see minplayer.players.base#seek
212  */
213 minplayer.players.html5.prototype.seek = function(pos) {
214   minplayer.players.base.prototype.seek.call(this, pos);
215   if (this.isReady()) {
216     this.player.currentTime = pos;
217   }
218 };
219 
220 /**
221  * @see minplayer.players.base#setVolume
222  */
223 minplayer.players.html5.prototype.setVolume = function(vol) {
224   minplayer.players.base.prototype.setVolume.call(this, vol);
225   if (this.isReady()) {
226     this.player.volume = vol;
227   }
228 };
229 
230 /**
231  * @see minplayer.players.base#getVolume
232  */
233 minplayer.players.html5.prototype.getVolume = function(callback) {
234   if (this.isReady()) {
235     callback(this.player.volume);
236   }
237 };
238 
239 /**
240  * @see minplayer.players.base#getDuration
241  */
242 minplayer.players.html5.prototype.getDuration = function(callback) {
243   if (this.isReady()) {
244     callback(this.player.duration);
245   }
246 };
247 
248 /**
249  * @see minplayer.players.base#getCurrentTime
250  */
251 minplayer.players.html5.prototype.getCurrentTime = function(callback) {
252   if (this.isReady()) {
253     callback(this.player.currentTime);
254   }
255 };
256 
257 /**
258  * @see minplayer.players.base#getBytesLoaded
259  */
260 minplayer.players.html5.prototype.getBytesLoaded = function(callback) {
261   if (this.isReady()) {
262     var loaded = 0;
263 
264     // Check several different possibilities.
265     if (this.bytesLoaded.value) {
266       loaded = this.bytesLoaded.value;
267     }
268     else if (this.player.buffered &&
269         this.player.buffered.length > 0 &&
270         this.player.buffered.end &&
271         this.player.duration) {
272       loaded = this.player.buffered.end(0);
273     }
274     else if (this.player.bytesTotal != undefined &&
275              this.player.bytesTotal > 0 &&
276              this.player.bufferedBytes != undefined) {
277       loaded = this.player.bufferedBytes;
278     }
279 
280     // Return the loaded amount.
281     callback(loaded);
282   }
283 };
284 
285 /**
286  * @see minplayer.players.base#getBytesTotal
287  */
288 minplayer.players.html5.prototype.getBytesTotal = function(callback) {
289   if (this.isReady()) {
290 
291     var total = 0;
292 
293     // Check several different possibilities.
294     if (this.bytesTotal.value) {
295       total = this.bytesTotal.value;
296     }
297     else if (this.player.buffered &&
298         this.player.buffered.length > 0 &&
299         this.player.buffered.end &&
300         this.player.duration) {
301       total = this.player.duration;
302     }
303     else if (this.player.bytesTotal != undefined &&
304              this.player.bytesTotal > 0 &&
305              this.player.bufferedBytes != undefined) {
306       total = this.player.bytesTotal;
307     }
308 
309     // Return the loaded amount.
310     callback(total);
311   }
312 };
313