2397a497ec2ae0601a7a73b50d5613230fb923dd
[profile/ivi/MediaPlayer.git] / js / audioPlayer.js
1 /*
2  * Copyright (c) 2013, Intel Corporation.
3  *
4  * This program is licensed under the terms and conditions of the
5  * Apache License, version 2.0.  The full text of the Apache License is at
6  * http://www.apache.org/licenses/LICENSE-2.0
7  *
8  */
9
10 var mainArtistText;
11 var songDurationSec;
12
13 AudioPlayer = function()
14 {
15         this.clearAudioTimeInterval = undefined;
16         this.currentAudioContent = undefined;
17 }
18
19 /*
20  * Play function for when play button is clicked
21  */
22
23 AudioPlayer.prototype.play = function()
24 {
25         console.log("MediaPlayer in AudioPlayer::play");
26
27         if (this.currentFileLoaded)
28         {
29                 if (this.playerControls.paused)
30                 {
31                         this.playerControls.play();
32
33                         //Start tracking the current time of the media.  This is used to play from previous position on restart.
34                         //Currently this isn't supported for remote files
35                         if (!this.content[this.listIndex].remoteFile)
36                         {
37                                 var timeoutFunction = function()
38                                 {
39                                         localStorage.prevAudioTime = this.playerControls.currentTime;
40                                         this.updateTrackTime();
41                                 }
42
43                                 this.clearAudioTimeInterval = setInterval(timeoutFunction.bind(this),500);
44                         }
45                 }
46         }
47         else
48                 console.log(this.content[this.listIndex].artists[0] + " : " + this.content[this.listIndex].title + " can't play yet, it hasn't loaded");
49 }
50
51 /*
52  * Pause function for when pause button is clicked
53  */
54
55 AudioPlayer.prototype.pause = function()
56 {
57         if (!this.playerControls.paused)
58         {
59                 this.playerControls.pause();
60                 clearInterval(this.clearAudioTimeInterval);
61         }
62 }
63
64 /*
65  * Next function for when next button is clicked
66  */
67
68 AudioPlayer.prototype.next = function()
69 {
70         if (this.content)
71         {
72                 if (this.content.length > (this.listIndex + 1))
73                         this.listIndex++;
74                 else
75                         this.listIndex = 0;
76
77                 this.load(this.listIndex, true);
78         }
79 }
80
81 /*
82  * Previous function for when previous button is clicked
83  */
84
85 AudioPlayer.prototype.previous = function()
86 {
87         if (this.content)
88         {
89                 if (this.listIndex > 0 )
90                         this.listIndex--;
91                 else
92                         this.listIndex = this.content.length - 1;
93
94                 this.load(this.listIndex, true);
95         }
96 }
97
98 /*
99  * Returns play state
100  */
101
102 AudioPlayer.prototype.playing = function()
103 {
104         return !(this.playerControls.paused);
105 }
106
107 /*
108  * Load the file located at the index.  If play is true, play immediately once file is loaded
109  */
110
111 AudioPlayer.prototype.load = function(index, play)
112 {
113         this.listIndex = index;
114         this.loadAndPlay = play;
115         this.playerControls.pause();
116         this.updateMediaName(this.content[this.listIndex].artists[0], this.content[this.listIndex].title, this.content[this.listIndex].coverArt);
117         $("#audioSrc").attr("src", this.content[this.listIndex].contentURI);
118         this.playerControls.load();
119 }
120
121 /*
122  * Redraws the media bar with the new artist, title, and cover album
123  */
124
125 AudioPlayer.prototype.updateMediaName = function(newArtist, newTitle, newCover)
126 {
127         playBarHeight = mediaNameCanvas.height;
128         boxWidth = playBarHeight * 0.75;
129         textStartX = boxWidth + 50;
130         songDurationSec = this.playerControls.duration;
131         mediaNameCTX.clearRect(0,0,mediaNameCanvas.width, mediaNameCanvas.height);
132
133         mediaNameCTX.fillStyle="rgba(30,30,30,0.5)";
134         mediaNameCTX.strokeStyle="rgba(130,130,130,1)";
135         mediaNameCTX.lineWidth = 5;
136         mediaNameCTX.fillRect(0,0,mediaNameCanvas.width, playBarHeight);
137         mediaNameCTX.strokeRect(-20,0,mediaNameCanvas.width + 40, playBarHeight);
138
139         if (newCover === undefined || newCover.naturalWidth === undefined || newCover.naturalWidth <= 0)
140         {
141                 newCover = musicIcon;
142         }
143
144         mediaNameCTX.drawImage(newCover, 20, (playBarHeight - boxWidth) / 2, boxWidth, boxWidth);
145
146         if (screenOrientation === "portrait")
147         {
148                 var trackText = new TextObject(mediaNameCTX,{"text" : newTitle, "xLoc" : textStartX, "yLoc" : 70 , "zLoc" : 0,
149                                                         "width" : mediaNameCanvas.width - textStartX, "height" : 50, "lineHeight" : 65, "wordWrap" : true});
150
151                 trackText.applyTemplate(mainMenuTitleTemplate);
152
153                 mainArtistText = new TextObject(mediaNameCTX,{"text" : newArtist, "xLoc" : textStartX, "yLoc" : 70, "zLoc" : 0,
154                                                                 "width" : mediaNameCanvas.width - textStartX, "height" : 50, "lineHeight" : 50, "wordWrap" : true});
155
156                 mainArtistText.applyTemplate(mainTrackTemplate);
157         }
158         else
159         {
160                 var trackText = new TextObject(mediaNameCTX,{"text" : newTitle, "xLoc" : textStartX, "yLoc" : 50 , "zLoc" : 0,
161                                                                 "width" : mediaNameCanvas.width - textStartX, "height" : 30, "lineHeight" : 30, "wordWrap" : true});
162                 trackText.applyTemplate(mainMenuTitleTemplateLandscape);
163                 mainArtistText = new TextObject(mediaNameCTX,{"text" : newArtist, "xLoc" : textStartX, "yLoc" : 50, "zLoc" : 0,
164                                                                 "width" : mediaNameCanvas.width - textStartX, "height" : 30, "lineHeight" : 30, "wordWrap" : true});
165                 mainArtistText.applyTemplate(mainTrackTemplateLandscape);
166         }
167
168         trackText.drawObj();
169         trackText.drawLargeShadow();
170         mainArtistText.yLoc += trackText.height;
171         mainArtistText.drawObj();
172
173         this.updateTrackTime();
174 }
175
176 /*
177  * Redraws the current track time
178  */
179
180 AudioPlayer.prototype.updateTrackTime = function()
181 {
182         playBarHeight = mediaNameCanvas.height;
183         boxWidth = playBarHeight * 0.75;
184         textStartX = boxWidth + 50;
185         var timeText = '';
186         var songDurationSec = Math.floor(this.playerControls.duration % 60) > 9 ? Math.floor(this.playerControls.duration % 60) : '0' + Math.floor(this.playerControls.duration % 60);
187         var songDurationMin = Math.floor(this.playerControls.duration / 60) > 9 ?  Math.floor(this.playerControls.duration / 60) : '0' +  Math.floor(this.playerControls.duration / 60);
188         var songCurrentMin = Math.floor(this.playerControls.currentTime / 60) > 9 ? Math.floor(this.playerControls.currentTime / 60) :  '0' + Math.floor(this.playerControls.currentTime / 60);
189         var songCurrentSec = Math.floor(this.playerControls.currentTime % 60) > 9 ? Math.floor(this.playerControls.currentTime % 60) : '0' + Math.floor(this.playerControls.currentTime % 60);
190
191         if ((songCurrentMin !== undefined && songCurrentSec !== undefined) && (!isNaN(songCurrentMin) && !isNaN(songCurrentSec)))
192                 timeText += songCurrentMin + ':' + songCurrentSec + ' / ';
193         else
194                 timeText += "00:00 / ";
195
196         if ((songDurationSec !== undefined && songDurationMin !== undefined) && (!isNaN(songDurationMin) && !isNaN(songDurationSec)))
197                 timeText += songDurationMin + ':' + songDurationSec;
198         else
199                 timeText += "00:00";
200
201
202         var trackTimeText = new TextObject(trackTimeCTX,{"text" : timeText, "xLoc" : textStartX, "yLoc" : 50, "zLoc" : 0,
203                                                                 "width" : mediaNameCanvas.width - textStartX, "height" : 20, "lineHeight" : 20, "wordWrap" : false});
204
205         trackTimeText.applyTemplate(timeTemplate);
206         trackTimeCTX.clearRect(0, 0, trackTimeCanvas.width, trackTimeCanvas.height);
207
208         trackTimeText.yLoc = ((playBarHeight - boxWidth) / 2) + boxWidth;
209         trackTimeText.drawObj();
210 }
211
212 /*
213  * Plays the currently loaded media file
214  */
215
216 AudioPlayer.prototype.playLoadedMedia = function()
217 {
218         console.log("MediaPlayer in playLoadedMedia");
219         this.currentFileLoaded = true;
220
221         //Only store track to localStorage if it's a local file, and current menu is the Audio menu
222         if (!this.content[this.listIndex].remoteFile && localStorage.prevMenu === "mainMusicButton")
223         {
224                 localStorage.prevAudioTrack = this.content[this.listIndex].contentURI;
225         }
226         else
227         {
228                 localStorage.prevAudioTime = undefined;
229                 localStorage.prevAudioTrack = undefined;
230         }
231
232         this.currentAudioContent = this.content[this.listIndex];
233
234         if (this.loadPrevAudio)
235         {
236                 this.playerControls.currentTime = localStorage.prevAudioTime;
237                 this.loadPrevAudio = false;
238                 this.play();
239         }
240
241         if (this.loadAndPlay)
242         {
243                 this.play();
244                 this.loadAndPlay = false;
245         }
246
247         this.updateMediaName(this.content[this.listIndex].artists[0], this.content[this.listIndex].title, this.content[this.listIndex].coverArt);
248         this.currentFileLoaded = true;
249 }
250
251 /*
252  * Sort the file list alphabetically
253  */
254
255 AudioPlayer.prototype.sortByAlpha = function()
256 {
257         console.log("MediaPlayer in sortByAlpha");
258
259         this.emptyTimeouts();
260
261         this.content.sort(function (a,b)
262         {
263                 var first = a.title.toLowerCase();
264                 var second = b.title.toLowerCase();
265
266                 if (first < second)
267                         return -1;
268                 if (first > second)
269                         return 1;
270
271                 return 0;
272         });
273
274         this.fillMediaList();
275 }
276
277 /*
278  * Sort the file list by artist name
279  */
280
281 AudioPlayer.prototype.sortByArtist = function()
282 {
283         console.log("MediaPlayer in sortByArtist");
284
285         this.emptyTimeouts();
286
287         this.content.sort(function (a,b)
288         {
289                 var first = a.artists[0].toLowerCase();
290                 var second = b.artists[0].toLowerCase();
291
292                 if (first < second)
293                         return -1;
294                 if (first > second)
295                         return 1;
296
297                 return 0;
298         });
299
300         this.fillMediaList();
301 }
302
303 /*
304  * Sort the file list by album name
305  */
306
307 AudioPlayer.prototype.sortByAlbum =function()
308 {
309         console.log("MediaPlayer in sortByAlbum");
310
311         this.emptyTimeouts();
312
313         this.content.sort(function (a,b)
314         {
315                 var first = a.album.toLowerCase();
316                 var second = b.album.toLowerCase();
317
318                 if (first < second)
319                         return -1;
320                 if (first > second)
321                         return 1;
322
323                 return 0;
324         });
325
326         this.fillMediaList();
327 }
328
329 /*
330  * Callback for when the local content has been successfully read using tizen.content.
331  */
332
333 AudioPlayer.prototype.onContentLoaded = function()
334 {
335         try
336         {
337                 if (localStorage.prevAudioTrack && localStorage.prevAudioTrack !== "undefined")
338                 {
339                         for (var i = 0; i < this.content.length; i++)
340                         {
341
342                                 if (this.content[i].contentURI === localStorage.prevAudioTrack)
343                                 {
344                                         this.listIndex = i;
345                                         console.log("MediaPlayer: Previous audio found, loading " + this.content[this.listIndex].contentURI);
346                                         this.loadPrevAudio = true;
347                                         this.fillMediaList();
348                                         this.load(i, true);
349                                 }
350                         }
351                 }
352                 else
353                 {
354                         console.log("MediaPlayer: No previous audio found, loading first");
355                         this.load(0, false);
356                         this.updateMediaName(this.content[this.listIndex].artists[0], this.content[this.listIndex].title, this.content[this.listIndex].coverArt);
357
358                         if (currentMenu === "audio")
359                                 this.fillMediaList();
360                 }
361
362                 var imgSources = [];
363
364                 for (var i = 0; i < this.content.length; i++)
365                 {
366                         var iconURI = (this.content[i].thumbnailURIs !== undefined && this.content[i].thumbnailURIs !== null) ? this.content[i].thumbnailURIs[0] : "images/musicIcon.png";
367                         this.content[i].coverArtURI = iconURI;
368                 }
369
370                 loadImages();
371         }
372         catch (err)
373         {
374                 console.log("MediaPlayer: Error when parsing audioContent");
375         }
376 }
377
378 /*
379  * Create and draw an item in the media list
380  */
381
382 AudioPlayer.prototype.makeListItem = function(j, k)
383 {
384         var canvasH = mediaListItemH * 0.95 ;
385
386     for (var i = j; (i < (j+k) && i < this.content.length); i++)
387     {
388             //Check if album art is done loading, if not draw default until it is
389              if (this.content[i].artists === undefined)
390              {
391                 this.content[i].artists = new Array();
392                 this.content[i].artists[0] = "Unknown";
393              }
394
395              var trackText = {"text" : this.content[i].title, "xLoc" : canvasH + 20, "yLoc" : canvasH / 2.5 , "zLoc" : 0};
396          var artistText = {"text" : this.content[i].artists[0], "xLoc" : canvasH + 20, "yLoc" : canvasH / 1.1 , "zLoc" : 0};
397
398             if (this.content[i].coverArt && this.content[i].coverArt.complete)
399                 this.makeListBar(this.content[i].coverArt, i, artistText, trackText);
400             else
401                 this.makeListBar(musicIcon, i, artistText, trackText);
402
403                 // Set callback function for the new list item
404                 $("#" + this.type + "CanvasNum" + i).click(function () {
405                         try
406                         {
407                                 audioPlayer.load($(this).parent().parent().index(), true);
408                         }
409                         catch(err)
410                         {
411                                 console.log("MediaPlayer: load audio error " + err.message);
412                         }
413                 });
414     }
415 }