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