Add Modello Common libraries to web-ui-fw; version up
[profile/ivi/sdk/web-ide-resources.git] / web-ui-fw / 0.0.2 / 0.0.2_Common / original / css / car / components / audioPlayer / audioPlayer.js
1 /*global Utils */
2
3 /**
4  * @module CarTheme
5  **/
6 (function ($) {
7     "use strict";
8      /**
9      * Represents HTML5 audio element which is utilizing Audio Service API to get/set status of currently playing song (tested with wav audio files).
10      * Audio resources are passed to the player as an array of songs and stored in {{#crossLink "AudioPlayer/model:property"}}{{/crossLink}} property.
11      *
12      * This class requires following components:
13      *
14      * * {{#crossLink "ButtonControlsObj"}}{{/crossLink}} component
15      *
16      * Audio player is extended by option to set buttons to control audio playback (play/pause, next, previous, shuffle, repeat), time progress bar, spectrum analyzer, info panel, volume control.
17      *
18      * Use following snippet to include component in your `index.html` file:
19      *
20      *     <script type="text/javascript" src="./css/car/components/audioPlayer/audioPlayer.js"></script>
21      *
22      * and following code to initialize:
23      *
24      *     $('#multimediaPlayer').audioAPI('init', [], "#audioPlayer", "#videoPlayer");
25      *
26      * @class AudioPlayer
27      * @constructor
28      */
29     var AudioPlayer = {
30             thisObj: null,
31             /**
32              * Array of song objects. Every song object is expected to have album, artist, name, path and image properties.
33              * @property model
34              * @type {Array}
35              * @default null
36              */
37             model: [],
38             /**
39              * HTML audio or video DOM element.
40              * @property player
41              * @type {Any}
42              * @default null
43              */
44             player: null,
45             playerType: "AUDIO",
46             /**
47              * HTML audio DOM element.
48              * @property audio
49              * @type {Audio}
50              * @default null
51              */
52             audio: null,
53             /**
54              * HTML video DOM element.
55              * @property video
56              * @type {Video}
57              * @default null
58              */
59             video: null,
60             /**
61              * Indicates if audio timeupdate event listener was registered.
62              * @property timeUpdateListenerLoaded
63              * @type {Boolean}
64              * @default false
65              */
66             timeUpdateListenerLoaded: false,
67             /**
68              * Instance of audio service API.
69              * @property audioPlayerService
70              * @type {AudioService}
71              * @default null
72              */
73             audioPlayerService: null,
74
75             /**
76              * Selector of audio control buttons (play/pause, next, previous, shuffle, repeat).
77              * @property ctrlButtonsSelector
78              * @default null
79              */
80             ctrlButtonsSelector: null,
81             /**
82              * Selector of audio time progress bar.
83              * @property timeProgressBarSelelector
84              * @default null
85              */
86             timeProgressBarSelelector: null,
87             /**
88              * Selector of audio spectrum analyzer.
89              * @property spectrumAnalyzerSelelector
90              * @default null
91              */
92             spectrumAnalyzerSelelector: null,
93             /**
94              * Selector of audio info panel.
95              * @property infoPanelSelector
96              * @default null
97              */
98             infoPanelSelector: null,
99             /**
100              * Selector of audio thumbnail image.
101              * @property thumbnailSelector
102              * @default null
103              */
104             thumbnailSelector: null,
105             /**
106              * Selector of audio volume control.
107              * @property volumeControlSelector
108              * @default null
109              */
110             volumeControlSelector: null,
111             /**
112              * Indicates if repeat option of audio/video player is turned on.
113              * @property repeatOn
114              * @type {Boolean}
115              * @default false
116              */
117             repeatOn: false,
118             /**
119              * Indicates if shuffle option of audio player is turned on.
120              * @property shuffleOn
121              * @type {Boolean}
122              * @default false
123              */
124             shuffleOn: false,
125             /**
126              * Indicates if audio/video is playing (is not paused).
127              * @property playOn
128              * @type {Boolean}
129              * @default false
130              */
131             playOn: false,
132             /**
133              * Indicates the index of the loaded audio/video.
134              * @property index
135              * @type {Number}
136              * @default 0
137              */
138             index: 0,
139             /**
140              * Indicates the current playback position in percentage (0% - 100%) in the loaded audio/video.
141              * @property position
142              * @type {Number}
143              * @default 0
144              */
145             position: 0,
146             /**
147              * Indicates the current playback position in the loaded audio/video.
148              * @property currentTime
149              * @type {Number}
150              * @default 0
151              */
152             currentTime: 0,
153             /**
154              * Indicates the length of the loaded audio/video.
155              * @property duration
156              * @type {Number}
157              * @default 0
158              */
159             duration: 0,
160             /**
161              * Indicates the volume in percentage (0% - 100%) of the loaded audio/video.
162              * @property volume
163              * @type {Number}
164              * @default 0
165              */
166             volume: 100,
167             indexChangedCallback: null,
168             /**
169              * Sets the audio spectrum analyzer selector.
170              *
171              * @method setSpectrumAnalyzerSelector
172              * @param selector {String} Audio spectrum analyzer selector.
173              */
174             setSpectrumAnalyzerSelector: function (selector) {
175                 AudioPlayer.spectrumAnalyzerSelelector = selector;
176             },
177             /**
178              * Sets the audio control buttons selector.
179              *
180              * @method setControlButtonsSelector
181              * @param selector {String} Audio control buttons selector.
182              */
183             setControlButtonsSelector: function (selector) {
184                 AudioPlayer.ctrlButtonsSelector = selector;
185             },
186             /**
187              * Sets the audio time progress bar selector.
188              *
189              * @method setTimeProgressBarSelector
190              * @param selector {String} Audio time progress bar selector.
191              */
192             setTimeProgressBarSelector: function (selector) {
193                 AudioPlayer.timeProgressBarSelelector = selector;
194             },
195             /**
196              * Sets the audio info panel selector.
197              *
198              * @method setInfoPanelSelector
199              * @param selector {String} Audio info panel selector.
200              */
201             setInfoPanelSelector: function (selector) {
202                 AudioPlayer.infoPanelSelector = selector;
203             },
204             /**
205              * Sets the audio info panel selector.
206              *
207              * @method setThumbnailSelector
208              * @param selector {String} Audio info panel selector.
209              */
210             setThumbnailSelector: function (selector) {
211                 AudioPlayer.thumbnailSelector = selector;
212             },
213             /**
214              * Sets the audio volume control selector.
215              *
216              * @method setVolumeControlSelector
217              * @param selector {String} Audio volume control selector.
218              */
219             setVolumeControlSelector: function (selector) {
220                 AudioPlayer.volumeControlSelector = selector;
221             },
222             addIndexChangeListener: function(indexChangeCallback) {
223                 AudioPlayer.indexChangeCallback = indexChangeCallback;
224             },
225             /**
226              * Initializes the audio player user interface, binds the audio controls (control buttons, volume control, time progress bar, ...), adds audio events listeners,
227              * gets the status from audio service API, loads appropriate song from passed model/playlist and updates the UI.
228              *
229              * @method init
230              * @param modelLib {Array} Array of audio songs.
231              */
232             init: function (modelLib, audioPlayerSelector, videoPlayerSelector) {
233                 AudioPlayer.thisObj = this;
234                 if (!!modelLib && modelLib.length) {
235                     AudioPlayer.model = modelLib;
236                 }
237                 if (!!audioPlayerSelector && audioPlayerSelector !== "") {
238                     AudioPlayer.audio = $(audioPlayerSelector).get(0);
239                 }
240                 if (!!videoPlayerSelector && videoPlayerSelector !== "") {
241                     AudioPlayer.video = $(videoPlayerSelector).get(0);
242                 }
243                 if (!!AudioPlayer.audio) {
244                     AudioPlayer.player = AudioPlayer.audio;
245                     AudioPlayer.playerType = "AUDIO";
246                 } else if (!!AudioPlayer.video) {
247                     AudioPlayer.player = AudioPlayer.video;
248                     AudioPlayer.playerType = "VIDEO";
249                 }
250
251                 if (AudioPlayer.ctrlButtonsSelector !== null) {
252                     $(AudioPlayer.ctrlButtonsSelector).buttonControls('initAudioPlayerButtons');
253                     $(AudioPlayer.ctrlButtonsSelector).unbind();
254                     $(AudioPlayer.ctrlButtonsSelector).bind('previousSong', function () {
255                         console.log("previousSong clicked");
256                         AudioPlayer.previous();
257                     });
258                     $(AudioPlayer.ctrlButtonsSelector).bind('nextSong', function () {
259                         console.log("nextSong clicked");
260                         AudioPlayer.next();
261                     });
262                     $(AudioPlayer.ctrlButtonsSelector).bind('playSong', function () {
263                         console.log("playSong clicked");
264                         AudioPlayer.playOn = !AudioPlayer.playOn;
265                         AudioPlayer.playPause(AudioPlayer.playOn);
266                     });
267                     $(AudioPlayer.ctrlButtonsSelector).bind('shuffleSong', function () {
268                         console.log("shuffleSong clicked");
269                         AudioPlayer.shuffleOn = !AudioPlayer.shuffleOn;
270                         AudioPlayer.updateUIControls();
271                     });
272                     $(AudioPlayer.ctrlButtonsSelector).bind('repeatSong', function () {
273                         console.log("repeatSong clicked");
274                         AudioPlayer.repeatOn = !AudioPlayer.repeatOn;
275                         AudioPlayer.updateUIControls();
276                     });
277                 }
278
279                 if (AudioPlayer.volumeControlSelector !== null) {
280                     $(AudioPlayer.volumeControlSelector).noUiSlider({
281                         range: [0, 100],
282                         step: 1,
283                         start: 50,
284                         handles: 1,
285                         connect: "lower",
286                         orientation: "horizontal",
287                         slide: function (aaa, ccc) {
288                             var volumeSlider = parseInt($(AudioPlayer.volumeControlSelector).val(), 10);
289                             console.log("new volume: " + volumeSlider);
290                             AudioPlayer.volume = volumeSlider;
291                             AudioPlayer.setAudioVolume(volumeSlider);
292                         }
293                     });
294                     AudioPlayer.setAudioVolume(50);
295                 }
296
297                 if (AudioPlayer.timeProgressBarSelelector !== null) {
298                     $(AudioPlayer.timeProgressBarSelelector).timeProgressBar("init");
299                     $(AudioPlayer.timeProgressBarSelelector).bind('positionChanged', function (e, data) {
300                         console.log("positionChanged " + data.position);
301                         AudioPlayer.setAudioPosition(data.position);
302                     });
303                 }
304
305                 AudioPlayer.registerPlayerListeners(AudioPlayer.audio, "AUDIO");
306                 AudioPlayer.registerPlayerListeners(AudioPlayer.video, "VIDEO");
307
308                 AudioPlayer.updateUIControls();
309             },
310             registerPlayerListeners: function(player, type) {
311                 if (!!player) {
312                     player.addEventListener('canplay', function () {
313                         console.log("canplay " + type);
314                         AudioPlayer.playPause(AudioPlayer.playOn);
315                     }, false);
316
317                     player.addEventListener('canplaythrough', function () {
318                         console.log("canplaythrough " + type);
319                         AudioPlayer.playPause(AudioPlayer.playOn);
320                     }, false);
321
322                     player.addEventListener('play', function () {
323                         console.log("play " + type);
324                     }, false);
325
326                     player.addEventListener('playing', function () {
327                         console.log("playing " + type);
328                     }, false);
329
330                     player.addEventListener('error', function () {
331                         console.log("error " + type);
332                     }, false);
333
334                     player.addEventListener('waiting', function () {
335                         console.log("waiting " + type);
336                     }, false);
337
338                     player.addEventListener('timeupdate', function () {
339                         //console.log("timeupdate " + type + " " + player.currentTime + " " + player.duration);
340                         if (!!player.currentTime && !isNaN(player.currentTime) && player.currentTime !== "Infinity" && player.currentTime > 0 &&
341                             !!player.duration && !isNaN(player.duration) && player.duration !== "Infinity" && player.duration > 0) {
342                             AudioPlayer.currentTime = player.currentTime;
343                             AudioPlayer.duration = player.duration;
344                         }
345
346                         AudioPlayer.updateProgressInfoPanel();
347                         AudioPlayer.spectrumAnalyzer(AudioPlayer.playOn);
348                     }, false);
349
350                     player.addEventListener('ended', function () {
351                         AudioPlayer.next();
352                     });
353                 }
354             },
355             playAudioContent: function(audioContent, indexToPlay, play, type) {
356                 if (!!AudioPlayer.player) {
357                     AudioPlayer.player.pause();
358                     AudioPlayer.player.src = "";
359                 }
360                 AudioPlayer.model = audioContent;
361                 AudioPlayer.playOn = play;
362                 AudioPlayer.playerType = type;
363                 if (type === "AUDIO") {
364                     AudioPlayer.player = AudioPlayer.audio;
365                 } else if (type === "VIDEO") {
366                     AudioPlayer.player = AudioPlayer.video;
367                 }
368                 AudioPlayer.loadAudio(indexToPlay);
369             },
370             /**
371              * Updates the audio UI controls and panels according to loaded song and audio status.
372              *
373              * @method updateUIControls
374              */
375             updateUIControls: function () {
376                 AudioPlayer.playPauseButtons(AudioPlayer.playOn);
377                 AudioPlayer.shuffleButton(AudioPlayer.shuffleOn);
378                 AudioPlayer.repeatButton(AudioPlayer.repeatOn);
379                 AudioPlayer.nextButton(AudioPlayer.index, AudioPlayer.repeatOn, AudioPlayer.shuffleOn);
380                 AudioPlayer.previousButton(AudioPlayer.index, AudioPlayer.repeatOn, AudioPlayer.shuffleOn);
381                 AudioPlayer.spectrumAnalyzer(AudioPlayer.playOn);
382                 AudioPlayer.volumeControl(AudioPlayer.volume);
383                 AudioPlayer.updateAudioInfoPanel(AudioPlayer.index);
384                 AudioPlayer.updateProgressInfoPanel();
385             },
386             /**
387              * Sets the audio play/pause button to active/inactive state.
388              *
389              * @method playPauseButtons
390              * @param isPaused {Boolean} State of play/pause button.
391              */
392             playPauseButtons: function (isPaused) {
393                 if (AudioPlayer.ctrlButtonsSelector !== null) {
394                     if (isPaused) {
395                         $(AudioPlayer.ctrlButtonsSelector).buttonControls('buttonPauseActive');
396                     } else {
397                         $(AudioPlayer.ctrlButtonsSelector).buttonControls('buttonPlayActive');
398                     }
399                 }
400             },
401             /**
402              * Sets the audio shuffle button to active/inactive state.
403              *
404              * @method shuffleButton
405              * @param isActive {Boolean} State of shuffle button.
406              */
407             shuffleButton: function (isActive) {
408                 if (AudioPlayer.ctrlButtonsSelector !== null) {
409                     if (isActive) {
410                         $(AudioPlayer.ctrlButtonsSelector).buttonControls('buttonShuffleActive');
411                     } else {
412                         $(AudioPlayer.ctrlButtonsSelector).buttonControls('buttonShuffleInactive');
413                     }
414                 }
415             },
416             /**
417              * Sets the audio repeat button to active/inactive state.
418              *
419              * @method repeatButton
420              * @param isActive {Boolean} State of repeat button.
421              */
422             repeatButton: function (isActive) {
423                 if (AudioPlayer.ctrlButtonsSelector !== null) {
424                     if (isActive) {
425                         $(AudioPlayer.ctrlButtonsSelector).buttonControls('buttonRepeatActive');
426                     } else {
427                         $(AudioPlayer.ctrlButtonsSelector).buttonControls('buttonRepeatInactive');
428                     }
429                 }
430             },
431             /**
432              * Sets the audio next button to active/inactive state.
433              *
434              * @method nextButton
435              * @param index {Number} Index of the song.
436              * @param repeat {Boolean} State of the repeat option.
437              * @param shuffle {Boolean} State of the shuffle option.
438              */
439             nextButton: function (index, repeat, shuffle) {
440                 if (AudioPlayer.ctrlButtonsSelector !== null) {
441                     if (repeat || shuffle || index < AudioPlayer.model.length - 1) {
442                         $(AudioPlayer.ctrlButtonsSelector).buttonControls('buttonNextActive');
443                     } else {
444                         $(AudioPlayer.ctrlButtonsSelector).buttonControls('buttonNextInactive');
445                     }
446                 }
447             },
448             /**
449              * Sets the audio previous button to active/inactive state.
450              *
451              * @method previousButton
452              * @param index {Number} Index of the song.
453              * @param repeat {Boolean} State of the repeat option.
454              * @param shuffle {Boolean} State of the shuffle option.
455              */
456             previousButton: function (index, repeat, shuffle) {
457                 if (AudioPlayer.ctrlButtonsSelector !== null) {
458                     if (repeat || shuffle || index > 0) {
459                         $(AudioPlayer.ctrlButtonsSelector).buttonControls('buttonPreviousActive');
460                     } else {
461                         $(AudioPlayer.ctrlButtonsSelector).buttonControls('buttonPreviousInactive');
462                     }
463                 }
464             },
465             /**
466              * Sets the audio spectrum analyzer to active/inactive state.
467              *
468              * @method spectrumAnalyzer
469              * @param playOn {Boolean} State of the audio playback.
470              */
471             spectrumAnalyzer: function (playOn) {
472                 if (AudioPlayer.spectrumAnalyzerSelelector !== null) {
473                     if (playOn) {
474                         $(AudioPlayer.spectrumAnalyzerSelelector).spectrumAnalyzer('spectrumAnalyzerRandomize');
475                     } else {
476                         $(AudioPlayer.spectrumAnalyzerSelelector).spectrumAnalyzer('clearSpectrumAnalyzer');
477                     }
478                 }
479             },
480             /**
481              * Sets the audio volume control.
482              *
483              * @method volumeControl
484              * @param volume {Number} Volume of the audio in percentage (0% - 100%).
485              */
486             volumeControl: function (volume) {
487                 if (volume > 100) {
488                     volume = 100;
489                 } else if (volume < 0) {
490                     volume = 0;
491                 }
492                 AudioPlayer.volume = volume;
493                 if (AudioPlayer.volumeControlSelector !== null) {
494                     $(AudioPlayer.volumeControlSelector).val(volume);
495                 }
496                 AudioPlayer.setAudioVolume(volume);
497             },
498             /**
499              * Sets the audio volume.
500              *
501              * @method setAudioVolume
502              * @param volume {Number} Volume of the audio in percentage (0% - 100%).
503              */
504             setAudioVolume: function (volume) {
505                 if (volume > 100) {
506                     volume = 100;
507                 } else if (volume < 0) {
508                     volume = 0;
509                 }
510                 AudioPlayer.volume = volume;
511                 AudioPlayer.player.volume =  volume / 100;
512             },
513             /**
514              * Updates the audio info panel (artist, album, name).
515              *
516              * @method updateAudioInfoPanel
517              * @param index {Number} Index of the song.
518              */
519             updateAudioInfoPanel: function (index) {
520                 if (AudioPlayer.model.length && index >= 0 && index < AudioPlayer.model.length ) {
521                     var audioContent = AudioPlayer.model[index],
522                         objInfo = {};
523
524                     if (!!audioContent) {
525                         if (AudioPlayer.infoPanelSelector !== null) {
526                             objInfo.title = 'NOW PLAYING';
527                             objInfo.artist = Utils.getArtistName(audioContent);
528                             objInfo.album = Utils.getAlbumName(audioContent);
529                             objInfo.name = Utils.getMediaItemTitle(audioContent);
530                             $(AudioPlayer.infoPanelSelector).infoPanel('show', objInfo);
531                         }
532                         if (AudioPlayer.thumbnailSelector !== null) {
533                             $(AudioPlayer.thumbnailSelector).get(0).src = Utils.getThumbnailPath(audioContent, AudioPlayer.playerType);
534                         }
535                     }
536                 }
537             },
538             /**
539              * Updates the audio time progress bar.
540              *
541              * @method updateProgressInfoPanel
542              */
543             updateProgressInfoPanel: function () {
544                 if (AudioPlayer.duration < 0) {
545                     AudioPlayer.duration = 0;
546                 }
547
548                 if (AudioPlayer.currentTime < 0) {
549                     AudioPlayer.currentTime = 0;
550                 }
551
552                 if (AudioPlayer.currentTime > AudioPlayer.duration) {
553                     AudioPlayer.currentTime = AudioPlayer.duration;
554                 }
555
556                 AudioPlayer.position = (AudioPlayer.currentTime / AudioPlayer.duration) * 100;
557
558                 if (AudioPlayer.position < 0) {
559                     AudioPlayer.position = 0;
560                 }
561
562                 if (AudioPlayer.position > 100) {
563                     AudioPlayer.position = 100;
564                 }
565
566                 var remainingTime = AudioPlayer.duration - AudioPlayer.currentTime,
567                     durationMins = Math.floor(remainingTime / 60, 10),
568                     durationSecs = Math.round(remainingTime) - durationMins * 60,
569                     estimationTime = '-' + durationMins + ':' + (durationSecs > 9 ? durationSecs : '0' + durationSecs),
570                     initProgressBarObj = {
571                         count: AudioPlayer.model.length,
572                         index: AudioPlayer.model.length <= 0 ? 0 : AudioPlayer.index + 1,
573                         estimation: estimationTime,
574                         position: AudioPlayer.position
575                     };
576
577                 if (AudioPlayer.timeProgressBarSelelector !== null) {
578                     $(AudioPlayer.timeProgressBarSelelector).timeProgressBar("show", initProgressBarObj);
579                 }
580             },
581             /**
582              * Sets and loads the audio source.
583              *
584              * @method loadAudio
585              * @param index {Number} Index of the song.
586              */
587             loadAudio: function (index, delay) {
588                 if (!AudioPlayer.model.length || index < 0 || index > AudioPlayer.model.length - 1 || !AudioPlayer.player) {
589                     return;
590                 }
591
592                 AudioPlayer.player.pause();
593                 AudioPlayer.player.src = "";
594                 AudioPlayer.index = index;
595                 AudioPlayer.position = 0;
596                 AudioPlayer.currentTime = 0;
597                 AudioPlayer.duration = 0;
598
599                 var audioContent = AudioPlayer.model[index];
600
601                 if (!!audioContent) {
602                     if (!!audioContent.contentURI && audioContent.contentURI !== "") {
603                         if (typeof(delay) === 'undefined') {
604                             AudioPlayer.player.src = audioContent.contentURI;
605                             AudioPlayer.player.load();
606                         } else {
607                             setTimeout(function() {
608                                 AudioPlayer.player.src = audioContent.contentURI;
609                                 AudioPlayer.player.load();
610                             }, delay);
611                         }
612                     }
613                     if (!!audioContent.duration && audioContent.duration >= 0) {
614                         AudioPlayer.duration = audioContent.duration / 1000;
615                     }
616                 }
617                 AudioPlayer.updateUIControls();
618             },
619             play: function (index) {
620                 if (index !== AudioPlayer.index) {
621                     AudioPlayer.loadAudio(index);
622                 }
623             },
624             /**
625              * Sets the position/current time of loaded song.
626              *
627              * @method setAudioPosition
628              * @param position {Number} Position in percentage of song.
629              */
630             setAudioPosition: function (position) {
631                 if (position > 100) {
632                     position = 100;
633                 } else if (position < 0) {
634                     position = 0;
635                 }
636                 AudioPlayer.currentTime = position / 100 * AudioPlayer.duration;
637                 if (!!AudioPlayer.player) {
638                     AudioPlayer.player.currentTime = AudioPlayer.currentTime;
639                 }
640                 AudioPlayer.updateProgressInfoPanel();
641             },
642             /**
643              * Starts/pauses playback of the song.
644              *
645              * @method playPause
646              * @param playing {Boolean} State of song playback.
647              */
648             playPause: function (playing) {
649                 AudioPlayer.playOn = playing;
650                 if (!!AudioPlayer.player && AudioPlayer.player.currentSrc !== "") {
651                     if (AudioPlayer.playOn) {
652                         AudioPlayer.player.play();
653                     } else {
654                         AudioPlayer.player.pause();
655                     }
656                 } else {
657                     AudioPlayer.playOn = false;
658                 }
659                 AudioPlayer.updateUIControls();
660             },
661             /**
662              * Sets next, random (if shuffle is on) index of song or first index (if repeat is on) and loads it from model.
663              *
664              * @method next
665              */
666             next: function () {
667                 if (AudioPlayer.model.length) {
668                     var newIndex = AudioPlayer.index, previousIndex = AudioPlayer.index;
669
670                     if (AudioPlayer.shuffleOn) {
671                         while (newIndex === AudioPlayer.index) {
672                             newIndex = Math.floor((Math.random() * AudioPlayer.model.length));
673                         }
674                     } else if (AudioPlayer.repeatOn && AudioPlayer.index >= AudioPlayer.model.length - 1) {
675                         newIndex = 0;
676                     } else if (AudioPlayer.index < AudioPlayer.model.length - 1) {
677                         newIndex = AudioPlayer.index + 1;
678                     } else {
679                         AudioPlayer.playOn = false;
680                     }
681
682                     if (newIndex !== previousIndex && !!AudioPlayer.indexChangeCallback) {
683                         AudioPlayer.indexChangeCallback(newIndex);
684                     }
685
686                     AudioPlayer.loadAudio(newIndex, 150);
687                 }
688             },
689             /**
690              * Sets previous, random (if shuffle is on) index of song or last index (if repeat is on) and loads it from model.
691              *
692              * @method previous
693              */
694             previous: function () {
695                 if (AudioPlayer.model.length) {
696                     var newIndex = AudioPlayer.index, previousIndex = AudioPlayer.index;
697
698                     if (AudioPlayer.shuffleOn) {
699                         while (newIndex === AudioPlayer.index) {
700                             newIndex = Math.floor((Math.random() * AudioPlayer.model.length));
701                         }
702                     } else if (AudioPlayer.repeatOn && AudioPlayer.index <= 0) {
703                         newIndex = AudioPlayer.model.length - 1;
704                     } else if (AudioPlayer.index > 0) {
705                         newIndex = AudioPlayer.index - 1;
706                     }
707
708                     if (newIndex !== previousIndex && !!AudioPlayer.indexChangeCallback) {
709                         AudioPlayer.indexChangeCallback(newIndex);
710                     }
711
712                     AudioPlayer.loadAudio(newIndex, 150);
713                 }
714             },
715             getCurrentPlayerType: function () {
716                 return AudioPlayer.playerType;
717             }
718         };
719
720     /**
721      * jQuery extension method for {{#crossLink "AudioPlayer"}}{{/crossLink}} plugin.
722      * @param method {Object|jQuery selector} Identificator (name) of method or jQuery selector.
723      * @method audioAPI
724      * @for jQuery
725      * @return Result of called method.
726      */
727     $.fn.audioAPI = function (method) {
728         // Method calling logic
729         if (AudioPlayer[method]) {
730             return AudioPlayer[method].apply(this, Array.prototype.slice.call(arguments, 1));
731         }
732
733         if (typeof method === 'object' || !method) {
734             return AudioPlayer.init.apply(this, arguments);
735         }
736
737         $.error('Method ' + method + ' does not exist on jQuery.audioAPI');
738     };
739 }(jQuery));