Updated Modello Common libraries; 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                     var volStart = 50;
281                     if(localStorage && localStorage.volume)
282                     {
283                         volStart = localStorage.volume;
284                     }
285                     $(AudioPlayer.volumeControlSelector).noUiSlider({
286                         range: [0, 100],
287                         step: 1,
288                         start: volStart,
289                         handles: 1,
290                         connect: "lower",
291                         orientation: "horizontal",
292                         slide: function (aaa, ccc) {
293                             var volumeSlider = parseInt($(AudioPlayer.volumeControlSelector).val(), 10);
294                             console.log("new volume: " + volumeSlider);
295                             AudioPlayer.volume = volumeSlider;
296                             AudioPlayer.setAudioVolume(volumeSlider);
297                         }
298                     });
299                     AudioPlayer.setAudioVolume(volStart);
300                 }
301
302                 if (AudioPlayer.timeProgressBarSelelector !== null) {
303                     $(AudioPlayer.timeProgressBarSelelector).timeProgressBar("init");
304                     $(AudioPlayer.timeProgressBarSelelector).bind('positionChanged', function (e, data) {
305                         console.log("positionChanged " + data.position);
306                         AudioPlayer.setAudioPosition(data.position);
307                     });
308                 }
309
310                 AudioPlayer.registerPlayerListeners(AudioPlayer.audio, "AUDIO");
311                 AudioPlayer.registerPlayerListeners(AudioPlayer.video, "VIDEO");
312
313                 AudioPlayer.updateUIControls();
314             },
315             registerPlayerListeners: function(player, type) {
316                 if (!!player) {
317                     player.addEventListener('canplay', function () {
318                         console.log("canplay " + type);
319                         AudioPlayer.playPause(AudioPlayer.playOn);
320                     }, false);
321
322                     player.addEventListener('canplaythrough', function () {
323                         console.log("canplaythrough " + type);
324                         AudioPlayer.playPause(AudioPlayer.playOn);
325                     }, false);
326
327                     player.addEventListener('play', function () {
328                         console.log("play " + type);
329                     }, false);
330
331                     player.addEventListener('playing', function () {
332                         console.log("playing " + type);
333                     }, false);
334
335                     player.addEventListener('error', function () {
336                         console.log("error " + type);
337                     }, false);
338
339                     player.addEventListener('waiting', function () {
340                         console.log("waiting " + type);
341                     }, false);
342
343                     player.addEventListener('timeupdate', function () {
344                         //console.log("timeupdate " + type + " " + player.currentTime + " " + player.duration);
345                         if (!!player.currentTime && !isNaN(player.currentTime) && player.currentTime !== "Infinity" && player.currentTime > 0 &&
346                             !!player.duration && !isNaN(player.duration) && player.duration !== "Infinity" && player.duration > 0) {
347                             AudioPlayer.currentTime = player.currentTime;
348                             AudioPlayer.duration = player.duration;
349                         }
350
351                         AudioPlayer.updateProgressInfoPanel();
352                         AudioPlayer.spectrumAnalyzer(AudioPlayer.playOn);
353                     }, false);
354
355                     player.addEventListener('ended', function () {
356                         AudioPlayer.next();
357                     });
358                 }
359             },
360             playAudioContent: function(audioContent, indexToPlay, play, type) {
361                 if (!!AudioPlayer.player) {
362                     AudioPlayer.player.pause();
363                     AudioPlayer.player.src = "";
364                 }
365                 AudioPlayer.model = audioContent;
366                 AudioPlayer.playOn = play;
367                 AudioPlayer.playerType = type;
368                 if (type === "AUDIO") {
369                     AudioPlayer.player = AudioPlayer.audio;
370                 } else if (type === "VIDEO") {
371                     AudioPlayer.player = AudioPlayer.video;
372                 }
373                 AudioPlayer.loadAudio(indexToPlay);
374             },
375             /**
376              * Updates the audio UI controls and panels according to loaded song and audio status.
377              *
378              * @method updateUIControls
379              */
380             updateUIControls: function () {
381                 AudioPlayer.playPauseButtons(AudioPlayer.playOn);
382                 AudioPlayer.shuffleButton(AudioPlayer.shuffleOn);
383                 AudioPlayer.repeatButton(AudioPlayer.repeatOn);
384                 AudioPlayer.nextButton(AudioPlayer.index, AudioPlayer.repeatOn, AudioPlayer.shuffleOn);
385                 AudioPlayer.previousButton(AudioPlayer.index, AudioPlayer.repeatOn, AudioPlayer.shuffleOn);
386                 AudioPlayer.spectrumAnalyzer(AudioPlayer.playOn);
387                 AudioPlayer.volumeControl(AudioPlayer.volume);
388                 AudioPlayer.updateAudioInfoPanel(AudioPlayer.index);
389                 AudioPlayer.updateProgressInfoPanel();
390             },
391             /**
392              * Sets the audio play/pause button to active/inactive state.
393              *
394              * @method playPauseButtons
395              * @param isPaused {Boolean} State of play/pause button.
396              */
397             playPauseButtons: function (isPaused) {
398                 if (AudioPlayer.ctrlButtonsSelector !== null) {
399                     if (isPaused) {
400                         $(AudioPlayer.ctrlButtonsSelector).buttonControls('buttonPauseActive');
401                     } else {
402                         $(AudioPlayer.ctrlButtonsSelector).buttonControls('buttonPlayActive');
403                     }
404                 }
405             },
406             /**
407              * Sets the audio shuffle button to active/inactive state.
408              *
409              * @method shuffleButton
410              * @param isActive {Boolean} State of shuffle button.
411              */
412             shuffleButton: function (isActive) {
413                 if (AudioPlayer.ctrlButtonsSelector !== null) {
414                     if (isActive) {
415                         $(AudioPlayer.ctrlButtonsSelector).buttonControls('buttonShuffleActive');
416                     } else {
417                         $(AudioPlayer.ctrlButtonsSelector).buttonControls('buttonShuffleInactive');
418                     }
419                 }
420             },
421             /**
422              * Sets the audio repeat button to active/inactive state.
423              *
424              * @method repeatButton
425              * @param isActive {Boolean} State of repeat button.
426              */
427             repeatButton: function (isActive) {
428                 if (AudioPlayer.ctrlButtonsSelector !== null) {
429                     if (isActive) {
430                         $(AudioPlayer.ctrlButtonsSelector).buttonControls('buttonRepeatActive');
431                     } else {
432                         $(AudioPlayer.ctrlButtonsSelector).buttonControls('buttonRepeatInactive');
433                     }
434                 }
435             },
436             /**
437              * Sets the audio next button to active/inactive state.
438              *
439              * @method nextButton
440              * @param index {Number} Index of the song.
441              * @param repeat {Boolean} State of the repeat option.
442              * @param shuffle {Boolean} State of the shuffle option.
443              */
444             nextButton: function (index, repeat, shuffle) {
445                 if (AudioPlayer.ctrlButtonsSelector !== null) {
446                     if (repeat || shuffle || index < AudioPlayer.model.length - 1) {
447                         $(AudioPlayer.ctrlButtonsSelector).buttonControls('buttonNextActive');
448                     } else {
449                         $(AudioPlayer.ctrlButtonsSelector).buttonControls('buttonNextInactive');
450                     }
451                 }
452             },
453             /**
454              * Sets the audio previous button to active/inactive state.
455              *
456              * @method previousButton
457              * @param index {Number} Index of the song.
458              * @param repeat {Boolean} State of the repeat option.
459              * @param shuffle {Boolean} State of the shuffle option.
460              */
461             previousButton: function (index, repeat, shuffle) {
462                 if (AudioPlayer.ctrlButtonsSelector !== null) {
463                     if (repeat || shuffle || index > 0) {
464                         $(AudioPlayer.ctrlButtonsSelector).buttonControls('buttonPreviousActive');
465                     } else {
466                         $(AudioPlayer.ctrlButtonsSelector).buttonControls('buttonPreviousInactive');
467                     }
468                 }
469             },
470             /**
471              * Sets the audio spectrum analyzer to active/inactive state.
472              *
473              * @method spectrumAnalyzer
474              * @param playOn {Boolean} State of the audio playback.
475              */
476             spectrumAnalyzer: function (playOn) {
477                 if (AudioPlayer.spectrumAnalyzerSelelector !== null) {
478                     if (playOn) {
479                         $(AudioPlayer.spectrumAnalyzerSelelector).spectrumAnalyzer('spectrumAnalyzerRandomize');
480                     } else {
481                         $(AudioPlayer.spectrumAnalyzerSelelector).spectrumAnalyzer('clearSpectrumAnalyzer');
482                     }
483                 }
484             },
485             /**
486              * Sets the audio volume control.
487              *
488              * @method volumeControl
489              * @param volume {Number} Volume of the audio in percentage (0% - 100%).
490              */
491             volumeControl: function (volume) {
492                 if (volume > 100) {
493                     volume = 100;
494                 } else if (volume < 0) {
495                     volume = 0;
496                 }
497                 AudioPlayer.volume = volume;
498                 if (AudioPlayer.volumeControlSelector !== null) {
499                     $(AudioPlayer.volumeControlSelector).val(volume);
500                 }
501                 AudioPlayer.setAudioVolume(volume);
502             },
503             /**
504              * Sets the audio volume.
505              *
506              * @method setAudioVolume
507              * @param volume {Number} Volume of the audio in percentage (0% - 100%).
508              */
509             setAudioVolume: function (volume) {
510                 if (volume > 100) {
511                     volume = 100;
512                 } else if (volume < 0) {
513                     volume = 0;
514                 }
515                 AudioPlayer.volume = volume;
516                 AudioPlayer.player.volume =  volume / 100;
517                 if(localStorage)
518                 {
519                     localStorage.volume = volume;
520                 }
521             },
522             /**
523              * Updates the audio info panel (artist, album, name).
524              *
525              * @method updateAudioInfoPanel
526              * @param index {Number} Index of the song.
527              */
528             updateAudioInfoPanel: function (index) {
529                 if (AudioPlayer.model.length && index >= 0 && index < AudioPlayer.model.length ) {
530                     var audioContent = AudioPlayer.model[index],
531                         objInfo = {};
532
533                     if (!!audioContent) {
534                         if (AudioPlayer.infoPanelSelector !== null) {
535                             objInfo.title = 'NOW PLAYING';
536                             objInfo.artist = Utils.getArtistName(audioContent);
537                             objInfo.album = Utils.getAlbumName(audioContent);
538                             objInfo.name = Utils.getMediaItemTitle(audioContent);
539                             $(AudioPlayer.infoPanelSelector).infoPanel('show', objInfo);
540                         }
541                         if (AudioPlayer.thumbnailSelector !== null) {
542                             $(AudioPlayer.thumbnailSelector).get(0).src = Utils.getThumbnailPath(audioContent, AudioPlayer.playerType);
543                         }
544                     }
545                 }
546             },
547             /**
548              * Updates the audio time progress bar.
549              *
550              * @method updateProgressInfoPanel
551              */
552             updateProgressInfoPanel: function () {
553                 if (AudioPlayer.duration < 0) {
554                     AudioPlayer.duration = 0;
555                 }
556
557                 if (AudioPlayer.currentTime < 0) {
558                     AudioPlayer.currentTime = 0;
559                 }
560
561                 if (AudioPlayer.currentTime > AudioPlayer.duration) {
562                     AudioPlayer.currentTime = AudioPlayer.duration;
563                 }
564
565                 AudioPlayer.position = (AudioPlayer.currentTime / AudioPlayer.duration) * 100;
566
567                 if (AudioPlayer.position < 0) {
568                     AudioPlayer.position = 0;
569                 }
570
571                 if (AudioPlayer.position > 100) {
572                     AudioPlayer.position = 100;
573                 }
574
575                 var remainingTime = AudioPlayer.duration - AudioPlayer.currentTime,
576                     durationMins = Math.floor(remainingTime / 60, 10),
577                     durationSecs = Math.round(remainingTime) - durationMins * 60,
578                     estimationTime = '-' + durationMins + ':' + (durationSecs > 9 ? durationSecs : '0' + durationSecs),
579                     initProgressBarObj = {
580                         count: AudioPlayer.model.length,
581                         index: AudioPlayer.model.length <= 0 ? 0 : AudioPlayer.index + 1,
582                         estimation: estimationTime,
583                         position: AudioPlayer.position
584                     };
585
586                 if (AudioPlayer.timeProgressBarSelelector !== null) {
587                     $(AudioPlayer.timeProgressBarSelelector).timeProgressBar("show", initProgressBarObj);
588                 }
589             },
590             /**
591              * Sets and loads the audio source.
592              *
593              * @method loadAudio
594              * @param index {Number} Index of the song.
595              */
596             loadAudio: function (index, delay) {
597                 if (!AudioPlayer.model.length || index < 0 || index > AudioPlayer.model.length - 1 || !AudioPlayer.player) {
598                     return;
599                 }
600
601                 AudioPlayer.player.pause();
602                 AudioPlayer.player.src = "";
603                 AudioPlayer.index = index;
604                 AudioPlayer.position = 0;
605                 AudioPlayer.currentTime = 0;
606                 AudioPlayer.duration = 0;
607
608                 var audioContent = AudioPlayer.model[index];
609
610                 if (!!audioContent) {
611                     if (!!audioContent.contentURI && audioContent.contentURI !== "") {
612                         if (typeof(delay) === 'undefined') {
613                             AudioPlayer.player.src = audioContent.contentURI;
614                             AudioPlayer.player.load();
615                         } else {
616                             setTimeout(function() {
617                                 AudioPlayer.player.src = audioContent.contentURI;
618                                 AudioPlayer.player.load();
619                             }, delay);
620                         }
621                     }
622                     if (!!audioContent.duration && audioContent.duration >= 0) {
623                         AudioPlayer.duration = audioContent.duration / 1000;
624                     }
625                 }
626                 AudioPlayer.updateUIControls();
627             },
628             play: function (index) {
629                 if (index !== AudioPlayer.index) {
630                     AudioPlayer.loadAudio(index);
631                 }
632             },
633             /**
634              * Sets the position/current time of loaded song.
635              *
636              * @method setAudioPosition
637              * @param position {Number} Position in percentage of song.
638              */
639             setAudioPosition: function (position) {
640                 if (position > 100) {
641                     position = 100;
642                 } else if (position < 0) {
643                     position = 0;
644                 }
645                 AudioPlayer.currentTime = position / 100 * AudioPlayer.duration;
646                 if (!!AudioPlayer.player) {
647                     AudioPlayer.player.currentTime = AudioPlayer.currentTime;
648                 }
649                 AudioPlayer.updateProgressInfoPanel();
650             },
651             /**
652              * Starts/pauses playback of the song.
653              *
654              * @method playPause
655              * @param playing {Boolean} State of song playback.
656              */
657             playPause: function (playing) {
658                 AudioPlayer.playOn = playing;
659                 if (!!AudioPlayer.player && AudioPlayer.player.currentSrc !== "") {
660                     if (AudioPlayer.playOn) {
661                         AudioPlayer.player.play();
662                     } else {
663                         AudioPlayer.player.pause();
664                     }
665                 } else {
666                     AudioPlayer.playOn = false;
667                 }
668                 AudioPlayer.updateUIControls();
669             },
670             /**
671              * Sets next, random (if shuffle is on) index of song or first index (if repeat is on) and loads it from model.
672              *
673              * @method next
674              */
675             next: function () {
676                 if (AudioPlayer.model.length) {
677                     var newIndex = AudioPlayer.index, previousIndex = AudioPlayer.index;
678
679                     if (AudioPlayer.shuffleOn) {
680                         while (newIndex === AudioPlayer.index) {
681                             newIndex = Math.floor((Math.random() * AudioPlayer.model.length));
682                         }
683                     } else if (AudioPlayer.repeatOn && AudioPlayer.index >= AudioPlayer.model.length - 1) {
684                         newIndex = 0;
685                     } else if (AudioPlayer.index < AudioPlayer.model.length - 1) {
686                         newIndex = AudioPlayer.index + 1;
687                     } else {
688                         AudioPlayer.playOn = false;
689                     }
690
691                     if (newIndex !== previousIndex && !!AudioPlayer.indexChangeCallback) {
692                         AudioPlayer.indexChangeCallback(newIndex);
693                     }
694
695                     AudioPlayer.loadAudio(newIndex, 150);
696                 }
697             },
698             /**
699              * Sets previous, random (if shuffle is on) index of song or last index (if repeat is on) and loads it from model.
700              *
701              * @method previous
702              */
703             previous: function () {
704                 if (AudioPlayer.model.length) {
705                     var newIndex = AudioPlayer.index, previousIndex = AudioPlayer.index;
706
707                     if (AudioPlayer.shuffleOn) {
708                         while (newIndex === AudioPlayer.index) {
709                             newIndex = Math.floor((Math.random() * AudioPlayer.model.length));
710                         }
711                     } else if (AudioPlayer.repeatOn && AudioPlayer.index <= 0) {
712                         newIndex = AudioPlayer.model.length - 1;
713                     } else if (AudioPlayer.index > 0) {
714                         newIndex = AudioPlayer.index - 1;
715                     }
716
717                     if (newIndex !== previousIndex && !!AudioPlayer.indexChangeCallback) {
718                         AudioPlayer.indexChangeCallback(newIndex);
719                     }
720
721                     AudioPlayer.loadAudio(newIndex, 150);
722                 }
723             },
724             getCurrentPlayerType: function () {
725                 return AudioPlayer.playerType;
726             }
727         };
728
729     /**
730      * jQuery extension method for {{#crossLink "AudioPlayer"}}{{/crossLink}} plugin.
731      * @param method {Object|jQuery selector} Identificator (name) of method or jQuery selector.
732      * @method audioAPI
733      * @for jQuery
734      * @return Result of called method.
735      */
736     $.fn.audioAPI = function (method) {
737         // Method calling logic
738         if (AudioPlayer[method]) {
739             return AudioPlayer[method].apply(this, Array.prototype.slice.call(arguments, 1));
740         }
741
742         if (typeof method === 'object' || !method) {
743             return AudioPlayer.init.apply(this, arguments);
744         }
745
746         $.error('Method ' + method + ' does not exist on jQuery.audioAPI');
747     };
748 }(jQuery));