2 * Copyright (c) 2013, Intel Corporation.
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
10 var currentMenu = "main";
12 var resizeCB = resizeMainMenu;
15 var screenOrientation;
18 var contentType = "AUDIO";
24 var currentPlayerType = "AUDIO";
25 var currentPlayerControls;
31 var vidIcon = new Image();
32 var imgIcon = new Image();
33 var musicIcon = new Image();
34 var imagesLoaded = false;
38 var loadAndPlay = false;
40 var currentFileLoaded = false;
44 var mainMenuTitleTemplateLandscape = {"font" : "oblique bolder 30pt arial", "lineWidth" : 9.5, "fillStyle" : "black", "strokeStyle" : "white", "textAlign" : "left",
45 "largeShadow" : 8, "shadowOffsetX" : 0, "shadowOffsetY" : 0, "shadowBlur" : 45, "shadowColor" : "rgba(255, 187, 0, 0.4)"};
47 var mainMenuTitleTemplate = {"font" : "oblique bolder 40pt arial", "lineWidth" : 9.5, "fillStyle" : "black", "strokeStyle" : "white", "textAlign" : "left",
48 "largeShadow" : 8, "shadowOffsetX" : 0, "shadowOffsetY" : 0, "shadowBlur" : 45, "shadowColor" : "rgba(255, 187, 0, 0.4)"};
50 var mainTrackTemplateLandscape = {"font" : "bold 20pt Arial", "lineWidth" : 7.5, "fillStyle" : "black", "strokeStyle" : "white", "textAlign" : "left",
51 "largeShadow" : 8, "shadowOffsetX" : 0, "shadowOffsetY" : 0, "shadowBlur" : 45, "shadowColor" : "rgba(255, 187, 0, 0.5))"};
53 var mainTrackTemplate = {"font" : "bold 30pt Arial", "lineWidth" : 7.5, "fillStyle" : "black", "strokeStyle" : "white", "textAlign" : "left",
54 "largeShadow" : 8, "shadowOffsetX" : 0, "shadowOffsetY" : 0, "shadowBlur" : 45, "shadowColor" : "rgba(255, 187, 0, 0.5))"};
56 var mediaTextTemplate2 = {"font" : "bold 20pt Arial", "lineWidth" : 10.0, "fillStyle" : "white", "strokeStyle" : "rgba(0, 0, 0, 1.0)", "textAlign" : "left",
57 "shadowOffsetX" : 0, "shadowOffsetY" : 0, "shadowBlur" : 0, "shadowColor" : "rgba(0, 0, 0, 1.0)"};
59 var mediaTextTemplate3 = {"font" : "bold 20pt Arial", "lineWidth" : 3.0, "fillStyle" : "white", "strokeStyle" : "rgba(100, 0, 0, 1.0)", "textAlign" : "left"};
61 var trackTextTemplate = {"font" : "bold 16pt Arial", "lineWidth" : 3.0, "fillStyle" : "white", "strokeStyle" : "black", "textAlign" : "left"};
63 var mediaTextTemplate2Landscape = {"font" : "bold 15pt Arial", "lineWidth" : 10.0, "fillStyle" : "white", "strokeStyle" : "rgba(0, 0, 0, 1.0)", "textAlign" : "left",
64 "shadowOffsetX" : 0, "shadowOffsetY" : 0, "shadowBlur" : 0, "shadowColor" : "rgba(0, 0, 0, 1.0)"};
66 var mediaTextTemplate3Landscape = {"font" : "bold 15pt Arial", "lineWidth" : 3.0, "fillStyle" : "white", "strokeStyle" : "rgba(100, 0, 0, 1.0)", "textAlign" : "left"};
68 var trackTextTemplateLandscape = {"font" : "bold 11pt Arial", "lineWidth" : 3.0, "fillStyle" : "white", "strokeStyle" : "black", "textAlign" : "left"};
71 var mediaTextTemplate = {"font" : "bold 20pt Arial", "fillStyle" : "", "textAlign" : "left",
72 "shadowOffsetX" : 0, "shadowOffsetY" : 0, "shadowBlur" : 12, "shadowColor" : "red"};
76 console.log("Content discovery failed");
79 function loadImages(callback)
84 for (var src in audioContent)
88 for (var src in audioContent)
92 audioContent[src].coverArt = new Image();
93 audioContent[src].coverArt.onload = function(){
95 if (++loadedImages >= numImages) {
97 callback(audioContent);
101 audioContent[src].coverArt.onerror = function(e){
102 audioContent[src].coverArt.src = "images/musicIcon.png";
105 audioContent[src].coverArt.src = (audioContent[src].coverArtURI !== undefined && audioContent[src].coverArtURI !== "") ? audioContent[src].coverArtURI : "images/musicIcon.png";
109 console.log("Failed to load audio cover image");
114 function updateMediaName(newArtist, newTitle, newCover)
116 var playBarHeight = mediaNameCanvas.height;
117 var boxWidth = playBarHeight * 0.75;
118 mediaNameCTX.clearRect(0,0,mediaNameCanvas.width, mediaNameCanvas.height);
120 if (currentPlayerType === "AUDIO")
123 var alphaJump = 0.01;
127 mediaNameCTX.fillStyle="rgba(30,30,30,0.5)";
128 mediaNameCTX.strokeStyle="rgba(130,130,130,1)";
129 mediaNameCTX.lineWidth = 5;
130 mediaNameCTX.fillRect(0,0,mediaNameCanvas.width, playBarHeight);
131 mediaNameCTX.strokeRect(-20,0,mediaNameCanvas.width + 40, playBarHeight);
133 if (newCover === undefined || newCover.naturalWidth === undefined || newCover.naturalWidth <= 0)
135 newCover = musicIcon;
138 mediaNameCTX.drawImage(newCover, 20, (playBarHeight - boxWidth) / 2, boxWidth, boxWidth);
140 if (screenOrientation === "portrait")
142 var textStartX = boxWidth + 50;
143 var trackText = new TextObject(mediaNameCTX,{"text" : newTitle, "xLoc" : textStartX, "yLoc" : 70 , "zLoc" : 0,
144 "width" : mediaNameCanvas.width - textStartX, "height" : 50, "lineHeight" : 50, "wordWrap" : true});
145 trackText.applyTemplate(mainMenuTitleTemplate);
146 var artistText = new TextObject(mediaNameCTX,{"text" : newArtist, "xLoc" : textStartX, "yLoc" : 70 + trackText.height, "zLoc" : 0,
147 "width" : mediaNameCanvas.width - textStartX, "height" : 50, "lineHeight" : 50, "wordWrap" : true});
148 artistText.applyTemplate(mainTrackTemplate);
149 artistText.yLoc = 70 + trackText.height;
153 var textStartX = boxWidth + 50;
154 var trackText = new TextObject(mediaNameCTX,{"text" : newTitle, "xLoc" : textStartX, "yLoc" : 50 , "zLoc" : 0,
155 "width" : mediaNameCanvas.width - textStartX, "height" : 30, "lineHeight" : 30, "wordWrap" : true});
156 trackText.applyTemplate(mainMenuTitleTemplateLandscape);
157 var artistText = new TextObject(mediaNameCTX,{"text" : newArtist, "xLoc" : textStartX, "yLoc" : 50, "zLoc" : 0,
158 "width" : mediaNameCanvas.width - textStartX, "height" : 30, "lineHeight" : 30, "wordWrap" : true});
159 artistText.applyTemplate(mainTrackTemplateLandscape);
160 artistText.yLoc = 50 + trackText.height;
164 trackText.drawLargeShadow();
165 artistText.drawObj();
170 function fillMediaList(contentList)
172 //Don't try and fill an empty content list or an audio list that hasn't finished loading the thumbnails
173 if (contentList === undefined || contentList === null || contentList.length <=0 || (contentList === audioContent && !imagesLoaded))
178 var iconImg = new Image();
179 var canvasW = mediaListItemW;
180 var canvasH = mediaListItemH * 0.95 ;
182 $("#mediaListItems").empty();
183 var lightColor = false;
184 for (var i=0; i < contentList.length; i++)
188 $("#mediaListItems").append("<li><a href='#'>" +
189 "<canvas id=canvasNum" + i + " width=" + canvasW + " height=" + canvasH + "> </canvas>" +
195 $("#mediaListItems").append("<li><a href='#' class='lightColor'>" +
196 "<canvas id=canvasNum" + i + " width=" + canvasW + " height=" + canvasH + "> </canvas>" +
201 lightColor = !lightColor;
203 currentCanvas = document.getElementById("canvasNum"+ i);
204 currentCTX = currentCanvas.getContext("2d");
206 // Set callback function for the new list item
207 $("#canvasNum"+i).click(function () {
208 listIndex = $(this).parent().parent().index();
210 switch (currentPlayerType)
215 $("#playButton").attr("src","images/playButton.png");
217 updateMediaName(audioContent[listIndex].artists[0], audioContent[listIndex].title, audioContent[listIndex].coverArt);
218 $("#audioSrc").attr("src", audioContent[listIndex].contentURI);
224 console.log("updateMediaName error: " + err.message);
231 $("#playButton").attr("src","images/playButton.png");
232 updateMediaName(videoContent[listIndex].artists[0], audioContent[listIndex].title, vidIcon);
233 $("#videoSrc").attr("src", videoContent[listIndex].contentURI);
235 $("#mediaList").fadeOut(300);
239 console.log("updateMediaName error: " + err.message);
246 $("#playButton").attr("src","images/playButton.png");
247 $("#imagePlayer").css("background", "url(" + imageContent[listIndex].contentURI + ") no-repeat center");
248 $("#imagePlayer").css("background-size", "contain");
249 $("#mediaList").fadeOut(300);
253 console.log("updateMediaName error: " + err.message);
262 switch (currentPlayerType)
265 currentCTX.drawImage(audioContent[i].coverArt, 0, 0, canvasH, canvasH );
266 var trackText = new TextObject(currentCTX,{"text" : contentList[i].title, "xLoc" : canvasH + 20, "yLoc" : canvasH / 2.5 , "zLoc" : 0});
267 var artistText = new TextObject(currentCTX,{"text" : contentList[i].artists[0], "xLoc" : canvasH + 20, "yLoc" : canvasH / 1.1 , "zLoc" : 0});
271 currentCTX.drawImage(vidIcon, 0, 0, canvasH, canvasH );
272 var artistText = new TextObject(currentCTX,{"text" : contentList[i].artists[0], "xLoc" : canvasH + 20, "yLoc" : canvasH / 2.5 , "zLoc" : 0});
273 var trackText = new TextObject(currentCTX,{"text" : contentList[i].title, "xLoc" : canvasH + 20, "yLoc" : canvasH / 1.1 , "zLoc" : 0});
277 currentCTX.drawImage(imgIcon, 0, 0, canvasH, canvasH );
278 var artistText = new TextObject(currentCTX,{"text" : contentList[i].title, "xLoc" : canvasH + 20, "yLoc" : canvasH / 2.5 , "zLoc" : 0});
279 var trackText = new TextObject(currentCTX,{"text" : " ", "xLoc" : canvasH + 20, "yLoc" : canvasH / 1.1 , "zLoc" : 0});
286 var mediaTextTemp1 = screenOrientation === "portrait" ? mediaTextTemplate2 : mediaTextTemplate2Landscape;
287 var mediaTextTemp2 = screenOrientation === "portrait" ? mediaTextTemplate3 : mediaTextTemplate3Landscape;
288 var trackTextTemp = screenOrientation === "portrait" ? trackTextTemplate : trackTextTemplateLandscape;
290 trackText.applyTemplate(mediaTextTemp1);
292 trackText.applyTemplate(mediaTextTemp2);
295 artistText.applyTemplate(trackTextTemp);
296 artistText.drawObj();
299 $("#mediaListItems li").css({"width" : mediaListItemW + "px", "height" : mediaListItemH + "px", "margin-bottom" : "10px"});
302 function onContentItemArraySuccess(content)
304 var emptyContent = true;
306 if (!content || content === undefined || content.length <= 0)
307 console.log("Invalid content for " + contentType);
310 emptyContent = false;
321 audioContent = content;
322 sortByAlpha(audioContent);
324 $("#audioSrc").attr("src", audioContent[0].contentURI);
329 for (var i = 0; i < audioContent.length; i++)
331 var iconURI = (audioContent[i].thumbnailURIs !== undefined && audioContent[i].thumbnailURIs !== null) ? audioContent[i].thumbnailURIs[0] : "images/musicIcon.png";
332 audioContent[i].coverArtURI = iconURI;
335 loadImages(fillMediaList);
340 console.log("Error when parsing audioContent");
344 contentType = "VIDEO";
350 videoContent = content;
351 $("#videoSrc").attr("src", videoContent[0].contentURI);
353 contentType = "IMAGE";
359 imageContent = content;
360 $("#imagePlayer").css("background", "url(" + imageContent[0].contentURI + ") no-repeat center");
361 $("#imagePlayer").css("background-size", "contain");
363 contentType = undefined;
367 console.log("Undefined content search type");
368 nextContentType = undefined;
372 if (contentType !== undefined)
373 getMedia(contentType);
376 function getMedia(mediaType)
378 var manager = tizen.content;
380 var filter = new tizen.AttributeFilter("type", "EXACTLY", mediaType);
381 manager.find(onContentItemArraySuccess, onError, null, filter);
384 function showMediaMenu()
386 $(".navButton").fadeIn(800);
388 switch(currentPlayerType)
394 updateMediaName(audioContent[listIndex].artists[0], audioContent[listIndex].title, audioContent[listIndex].coverArt);
398 console.log("updateMediaName failed for showMediaMenu (audio) : " + err.message);
401 $("#mediaName").fadeIn(800);
402 $(".sortButton").fadeIn(800);
403 currentPlayer.fadeIn(800);
405 $("#mediaList").addClass("mediaListAudioList");
407 if (screenOrientation === "landscape" )
408 $("#mediaList").addClass("landscape");
410 $("#mediaList").removeClass("landscape");
412 $("#mediaList").fadeIn(800);
417 setTimeout(function(){currentPlayer.show()}, 800); //The video element can't be faded, so wait a moment before showing
422 currentPlayer.fadeIn(800);
426 console.log("Invalid player type");
431 function showMediaList()
433 if ($("#mediaList").is(":visible"))
434 $("#mediaList").fadeOut(300);
437 fillMediaList(currentContent);
438 $("#mediaList").fadeIn(300);
442 function changeMenu(menuButtonId)
444 var clickedButton = $("#" + menuButtonId);
445 var buttonWidth = clickedButton.width();
446 var buttonHeight = clickedButton.height();
447 var buttonBottom = clickedButton.css("bottom");
448 var buttonRight = clickedButton.css("right");
450 //Animate the clicked button slightly
451 clickedButton.animate({
452 bottom: screenOrientation === "portrait" ? "+=0" : "+=50",
453 right: screenOrientation === "portrait" ? "+=50" : "+=0",
457 //Reset the size once done
459 clickedButton.width(buttonWidth);
460 clickedButton.height(buttonHeight);
462 if (screenOrientation === "portrait")
463 clickedButton.css({"right": buttonRight});
465 clickedButton.css({"bottom": buttonBottom});
469 $(".mainButton").fadeOut(300);
473 case ("mainMusicButton"):
474 currentMenu = "audio";
475 currentPlayer = $("#audioPlayer");
476 currentPlayerControls = document.getElementById("audioPlayer");
477 currentPlayerType = "AUDIO";
478 currentContent = audioContent;
482 case ("mainVideoButton"):
483 currentMenu = "video";
484 currentPlayer = $("#videoPlayer");
485 currentPlayerControls = document.getElementById("videoPlayer");
486 currentPlayerType = "VIDEO";
487 currentContent = videoContent;
491 case ("mainImageButton"):
492 currentMenu = "image";
493 currentPlayer = $("#imagePlayer");
494 currentPlayerControls = imageControls;
495 currentPlayerType = "IMAGE";
496 currentContent = imageContent;
500 console.log("Error: No menu by that name");
505 function showMainMenu()
507 currentMenu = "main";
508 currentPlayerControls.pause();
510 $("#playButton").attr("src","images/playButton.png");
512 //If the media list is showing, hide it. Remove the mediaListAudioList class if it exists so that it will resize properly
513 if ($("#mediaList").is(":visible"))
514 $("#mediaList").fadeOut(300, function(){$("#mediaList").removeClass("mediaListAudioList");});
516 $(".navButton").fadeOut(300);
517 $(".sortButton").fadeOut(300);
518 $("#mediaName").fadeOut(300);
520 if (currentPlayerType !== "VIDEO")
521 currentPlayer.fadeOut(300);
523 currentPlayer.hide();
526 $(".mainButton").css({"opacity": "100"});
527 $(".mainButton").fadeIn(800);
530 function sortByAlpha(contentToSort)
532 //If contentToSort is undefined it's because the request came from the sortBy buttons
533 if (contentToSort === undefined)
534 contentToSort = audioContent;
536 contentToSort.sort(function (a,b) {
537 var first = a.title.toLowerCase();
538 var second = b.title.toLowerCase();
548 fillMediaList(contentToSort);
551 function sortByArtist(contentToSort)
553 if (contentToSort === undefined)
554 contentToSort = audioContent;
556 contentToSort.sort(function (a,b) {
557 var first = a.artists[0].toLowerCase();
558 var second = b.artists[0].toLowerCase();
568 fillMediaList(contentToSort);
571 function sortByAlbum(contentToSort)
573 if (contentToSort === undefined)
574 contentToSort = audioContent;
576 contentToSort.sort(function (a,b) {
577 var first = a.album.toLowerCase();
578 var second = b.album.toLowerCase();
588 fillMediaList(contentToSort);
590 /**************************************** NAVIGATION FUNCTIONS *******************************************/
592 function startLoadTimer()
594 if (loadTimer !== undefined)
595 clearTimeout(loadTimer);
597 loadTimer = setTimeout(
599 if (currentMenu != "main")
600 $("#playButton").attr("src","images/playButton.png");
601 alert("File failed to load! - " + audioContent[listIndex].artists[0] + " : " + audioContent[listIndex].title);
602 currentFileLoaded = false;
606 function playLoadedMedia()
608 currentFileLoaded = true;
610 if (loadTimer !== undefined)
611 clearTimeout(loadTimer);
615 currentPlayerControls.play();
616 $("#playButton").attr("src","images/pauseButton.png");
621 function playButtonClick()
623 if (currentFileLoaded)
625 if (currentPlayerControls.paused)
627 currentPlayerControls.play();
628 $("#playButton").attr("src","images/pauseButton.png");
632 currentPlayerControls.pause();
633 $("#playButton").attr("src","images/playButton.png");
637 alert(audioContent[listIndex].artists[0] + " : " + audioContent[listIndex].title + " failed to load, please select another file");
640 function backButtonClick()
642 switch (currentPlayerType)
650 listIndex = imageContent.length - 1;
655 $("#audioSrc").attr("src", audioContent[listIndex].contentURI);
656 updateMediaName(audioContent[listIndex].artists[0], audioContent[listIndex].title, audioContent[listIndex].coverArt);
668 videoIndex = imageContent.length - 1;
670 if ($("#mediaList").is(":visible"))
673 $("#playButton").attr("src","images/playButton.png");
674 $("#videoSrc").attr("src", videoContent[videoIndex].contentURI);
685 imageIndex = imageContent.length - 1;
687 $("#imagePlayer").css("background", "url(" + imageContent[imageIndex].contentURI + ") no-repeat center");
688 $("#imagePlayer").css("background-size", "contain");
693 console.log("Content failure");
699 function nextButtonClick()
701 switch (currentPlayerType)
706 if (audioContent.length > (listIndex + 1))
714 $("#audioSrc").attr("src", audioContent[listIndex].contentURI);
715 updateMediaName(audioContent[listIndex].artists[0], audioContent[listIndex].title, audioContent[listIndex].coverArt);
724 if (videoContent.length > (videoIndex + 1))
730 $("#playButton").attr("src","images/playButton.png");
731 $("#videoSrc").attr("src", videoContent[videoIndex].contentURI);
739 if (imageContent.length > (imageIndex + 1))
744 $("#imagePlayer").css("background", "url(" + imageContent[imageIndex].contentURI + ") no-repeat center");
745 $("#imagePlayer").css("background-size", "contain");
750 console.log("Content failure");
755 /**************************************** END NAVIGATION FUNCTIONS *******************************************/
757 function resizeMainMenu()
759 $("#mediaList").fadeOut(0);
760 screenWidth = window.innerWidth;
761 screenHeight = window.innerHeight;
762 screenOrientation = screenWidth < screenHeight ? "portrait" : "landscape";
763 iconWidth = screenOrientation === "portrait" ? screenHeight / 4 : screenWidth / 4;
766 $(".mainButton").width(iconWidth + "px");
767 $(".mainButton").height(iconWidth + "px");
769 var iconsTop = screenOrientation === "portrait" ? ((screenHeight - (iconWidth * 3)) / 2) - (padding * 3) : (screenHeight - iconWidth) / 2;
771 if (screenOrientation === "portrait")
772 $("#mainMenuButtons").css({"top": iconsTop + "px", "left" : (screenWidth / 2) - (iconWidth /2) - padding + "px", "width" : "50%"});
775 $("#mainMenuButtons").css({"top": iconsTop + "px", "left" : ((iconWidth / 2) - (padding * 3)) + "px", "width" : "100%"});
776 $("#sortButtons").addClass("landscape");
780 function resizePlayerPage()
782 audioPlayer = document.getElementById("audioPlayer");
783 videoPlayer = document.getElementById("videoPlayer");
784 screenWidth = window.innerWidth;
785 screenHeight = window.innerHeight;
788 var buttonWidth = screenOrientation === "portrait" ? screenHeight * 0.05 : screenWidth * 0.05;
790 $("#backButton").css({"width": buttonWidth + "px", "height": buttonWidth + "px", "top": padding + "px", "left": ((screenWidth / 2) - (buttonWidth *3)) + "px"});
791 $("#nextButton").css({"width": buttonWidth + "px", "height": buttonWidth + "px", "top": padding + "px", "left": ((screenWidth / 2) + (buttonWidth *2)) + "px"});
792 $("#returnButton").css({"width": buttonWidth + "px", "height": buttonWidth + "px", "top": padding + "px", "left": padding + "px"});
793 $("#listButton").css({"width": buttonWidth + "px", "height": buttonWidth + "px", "top": padding + "px", "left": (screenWidth - buttonWidth - padding * 2) + "px"});
794 $("#playButton").css({"width": buttonWidth * 1.3 + "px", "height": buttonWidth * 1.3 + "px", "top": padding * 0.3 + "px", "left": (screenWidth / 2) - (buttonWidth / 2) + "px"});
796 mediaNameCanvas.width = (screenWidth);
797 mediaNameCanvas.height = (screenHeight * 0.34) - (buttonWidth + (2 * padding));
798 mediaNameCanvas.style.top = (buttonWidth + (2 * padding) ) + "px";
799 mediaNameCanvas.style.left = "0px";
801 var sortButtonTop = (buttonWidth + (2 * padding) ) + mediaNameCanvas.height - (buttonWidth * 1.3);
802 var sortButtonWidth = buttonWidth * 2.5;
803 var buttonSpacing = screenWidth / 5;
805 mediaListItemW = $("#mediaList").width() * 0.92;
806 mediaListItemH = $("#mediaList").height() / 10;
816 * swipe - Handles swipe events. Currently it just acts as another way to hit the next / back buttons, but
817 * it could be expanded to other things in the future.
820 function swipe(direction, object)
826 if (direction === "right")
828 else if (direction === "left")
839 musicIcon.src = "images/musicIcon.png";
840 vidIcon.src = "images/videoIcon.png";
841 imgIcon.src = "images/imageIcon.png";
842 imageControls = new ImageControls();
844 mediaNameCanvas = document.getElementById("mediaName");
845 mediaNameCTX = mediaNameCanvas.getContext("2d");
847 //Resize all items and search for local media
849 getMedia(contentType);
851 //Prevent highlighting
852 window.ondragstart = function() { return false; }
854 $(window).bind('resize', resizeAll);
856 //Simple swipe detection
857 $("#mediaName").mousedown(function(e){mouseDownEvent = e;});
858 $("#mediaName").mouseup(function(e){
859 if (Math.abs(mouseDownEvent.clientY - e.clientY) < 100)
861 if (Math.abs(mouseDownEvent.clientX - e.clientX) > 100)
863 if (mouseDownEvent.clientX > e.clientX)
864 swipe("left", "mediaName");
866 swipe("right", "mediaName");
872 $(document).ready(function () {