      1 /** The minplayer namespace. */
      2 var minplayer = minplayer || {};
      3
      4 /** Define the controller object. */
      5 minplayer.controller = minplayer.controller || {};
      6
      7 /**
      8  * @constructor
      9  * @extends minplayer.display
     10  * @class This is the base minplayer controller.  Other controllers can derive
     11  * from the base and either build on top of it or simply define the elements
     12  * that this base controller uses.
     13  *
     14  * @param {object} context The jQuery context.
     15  * @param {object} options This components options.
     16  */
     17 minplayer.controller.base = function(context, options) {
     18
     19   // Derive from display
     20   minplayer.display.call(this, 'controller', context, options);
     21 };
     22
     23 // Define the prototype for all controllers.
     24 var controllersBase = minplayer.controller.base;
     25
     26 /** Derive from minplayer.display. */
     27 minplayer.controller.base.prototype = new minplayer.display();
     28
     29 /** Reset the constructor. */
     30 minplayer.controller.base.prototype.constructor = minplayer.controller.base;
     31
     32 /**
     33  * A static function that will format a time value into a string time format.
     34  *
     35  * @param {integer} time An integer value of time.
     36  * @return {string} A string representation of the time.
     37  */
     38 minplayer.formatTime = function(time) {
     39   time = time || 0;
     40   var seconds = 0, minutes = 0, hour = 0, timeString = '';
     41
     42   hour = Math.floor(time / 3600);
     43   time -= (hour * 3600);
     44   minutes = Math.floor(time / 60);
     45   time -= (minutes * 60);
     46   seconds = Math.floor(time % 60);
     47
     48   if (hour) {
     49     timeString += String(hour);
     50     timeString += ':';
     51   }
     52
     53   timeString += (minutes >= 10) ? String(minutes) : ('0' + String(minutes));
     54   timeString += ':';
     55   timeString += (seconds >= 10) ? String(seconds) : ('0' + String(seconds));
     56   return {time: timeString, units: ''};
     57 };
     58
     59 /**
     60  * @see minplayer.display#getElements
     61  * @return {object} The elements defined by this display.
     62  */
     63 minplayer.controller.base.prototype.getElements = function() {
     64   var elements = minplayer.display.prototype.getElements.call(this);
     65   return jQuery.extend(elements, {
     66     play: null,
     67     pause: null,
     68     fullscreen: null,
     69     seek: null,
     70     progress: null,
     71     volume: null,
     72     timer: null
     73   });
     74 };
     75
     76 /**
     77  * @see minplayer.plugin#construct
     78  */
     79 minplayer.controller.base.prototype.construct = function() {
     80
     81   // Call the minplayer plugin constructor.
     82   minplayer.display.prototype.construct.call(this);
     83
     84   // Keep track of if we are dragging...
     85   this.dragging = false;
     86
     87   // If they have a seek bar.
     88   if (this.elements.seek) {
     89
     90     // Create the seek bar slider control.
     91     this.seekBar = this.elements.seek.slider({
     92       range: 'min'
     93     });
     94   }
     95
     96   // If they have a volume bar.
     97   if (this.elements.volume) {
     98
     99     // Create the volume bar slider control.
    100     this.volumeBar = this.elements.volume.slider({
    101       range: 'min',
    102       orientation: 'vertical'
    103     });
    104   }
    105
    106   // Get the player plugin.
    107   this.get('player', function(player) {
    108
    109     // If they have a fullscreen button.
    110     if (this.elements.fullscreen) {
    111
    112       // Bind to the click event.
    113       this.elements.fullscreen.unbind().bind('click', function(e) {
    114
    115         // Toggle fullscreen mode.
    116         player.toggleFullScreen();
    117       }).css({'pointer' : 'hand'});
    118     }
    119   });
    120
    121   // Get the media plugin.
    122   this.get('media', function(media) {
    123
    124     var _this = this;
    125
    126     // If they have a pause button
    127     if (this.elements.pause) {
    128
    129       // Bind to the click on this button.
    130       this.elements.pause.unbind().bind('click', {obj: this}, function(e) {
    131         e.preventDefault();
    132         e.data.obj.playPause(false, media);
    133       });
    134
    135       // Bind to the pause event of the media.
    136       media.bind('pause', {obj: this}, function(e) {
    137         e.data.obj.setPlayPause(true);
    138       });
    139     }
    140
    141     // If they have a play button
    142     if (this.elements.play) {
    143
    144       // Bind to the click on this button.
    145       this.elements.play.unbind().bind('click', {obj: this}, function(e) {
    146         e.preventDefault();
    147         e.data.obj.playPause(true, media);
    148       });
    149
    150       // Bind to the play event of the media.
    151       media.bind('playing', {obj: this}, function(e) {
    152         e.data.obj.setPlayPause(false);
    153       });
    154     }
    155
    156     // If they have a duration, then trigger on duration change.
    157     if (this.elements.duration) {
    158
    159       // Bind to the duration change event.
    160       media.bind('durationchange', {obj: this}, function(e, data) {
    161         e.data.obj.setTimeString('duration', data.duration);
    162       });
    163
    164       // Set the timestring to the duration.
    165       media.getDuration(function(duration) {
    166         _this.setTimeString('duration', duration);
    167       });
    168     }
    169
    170     // If they have a progress element.
    171     if (this.elements.progress) {
    172
    173       // Bind to the progress event.
    174       media.bind('progress', {obj: this}, function(e, data) {
    175         var percent = data.total ? (data.loaded / data.total) * 100 : 0;
    176         e.data.obj.elements.progress.width(percent + '%');
    177       });
    178     }
    179
    180     // If they have a seek bar or timer, bind to the timeupdate.
    181     if (this.seekBar || this.elements.timer) {
    182
    183       // Bind to the time update event.
    184       media.bind('timeupdate', {obj: this}, function(e, data) {
    185         if (!e.data.obj.dragging) {
    186           var value = 0;
    187           if (data.duration) {
    188             value = (data.currentTime / data.duration) * 100;
    189           }
    190
    191           // Update the seek bar if it exists.
    192           if (e.data.obj.seekBar) {
    193             e.data.obj.seekBar.slider('option', 'value', value);
    194           }
    195
    196           e.data.obj.setTimeString('timer', data.currentTime);
    197         }
    198       });
    199     }
    200
    201     // If they have a seekBar element.
    202     if (this.seekBar) {
    203
    204       // Register the events for the control bar to control the media.
    205       this.seekBar.slider({
    206         start: function(event, ui) {
    207           _this.dragging = true;
    208         },
    209         stop: function(event, ui) {
    210           _this.dragging = false;
    211           media.getDuration(function(duration) {
    212             media.seek((ui.value / 100) * duration);
    213           });
    214         },
    215         slide: function(event, ui) {
    216           media.getDuration(function(duration) {
    217             var time = (ui.value / 100) * duration;
    218             if (!_this.dragging) {
    219               media.seek(time);
    220             }
    221             _this.setTimeString('timer', time);
    222           });
    223         }
    224       });
    225     }
    226
    227     // Setup the volume bar.
    228     if (this.volumeBar) {
    229
    230       // Create the slider.
    231       this.volumeBar.slider({
    232         slide: function(event, ui) {
    233           media.setVolume(ui.value / 100);
    234         }
    235       });
    236
    237       media.bind('volumeupdate', {obj: this}, function(event, vol) {
    238         event.data.obj.volumeBar.slider('option', 'value', (vol * 100));
    239       });
    240
    241       // Set the volume to match that of the player.
    242       media.getVolume(function(vol) {
    243         _this.volumeBar.slider('option', 'value', (vol * 100));
    244       });
    245     }
    246   });
    247
    248   // We are now ready.
    249   this.ready();
    250 };
    251
    252 /**
    253  * Sets the play and pause state of the control bar.
    254  *
    255  * @param {boolean} state TRUE - Show Play, FALSE - Show Pause.
    256  */
    257 minplayer.controller.base.prototype.setPlayPause = function(state) {
    258   var css = '';
    259   if (this.elements.play) {
    260     css = state ? 'inherit' : 'none';
    261     this.elements.play.css('display', css);
    262   }
    263   if (this.elements.pause) {
    264     css = state ? 'none' : 'inherit';
    265     this.elements.pause.css('display', css);
    266   }
    267 };
    268
    269 /**
    270  * Plays or pauses the media.
    271  *
    272  * @param {bool} state true => play, false => pause.
    273  * @param {object} media The media player object.
    274  */
    275 minplayer.controller.base.prototype.playPause = function(state, media) {
    276   var type = state ? 'play' : 'pause';
    277   this.display.trigger(type);
    278   this.setPlayPause(!state);
    279   if (media) {
    280     media[type]();
    281   }
    282 };
    283
    284 /**
    285  * Sets the time string on the control bar.
    286  *
    287  * @param {string} element The name of the element to set.
    288  * @param {number} time The total time amount to set.
    289  */
    290 minplayer.controller.base.prototype.setTimeString = function(element, time) {
    291   if (this.elements[element]) {
    292     this.elements[element].text(minplayer.formatTime(time).time);
    293   }
    294 };
    295