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;
42 var mainMenuTitleTemplateLandscape = {"font" : "oblique bolder 30pt arial", "lineWidth" : 9.5, "fillStyle" : "black", "strokeStyle" : "white", "textAlign" : "left",
43 "largeShadow" : 8, "shadowOffsetX" : 0, "shadowOffsetY" : 0, "shadowBlur" : 45, "shadowColor" : "rgba(255, 187, 0, 0.4)"};
45 var mainMenuTitleTemplate = {"font" : "oblique bolder 40pt arial", "lineWidth" : 9.5, "fillStyle" : "black", "strokeStyle" : "white", "textAlign" : "left",
46 "largeShadow" : 8, "shadowOffsetX" : 0, "shadowOffsetY" : 0, "shadowBlur" : 45, "shadowColor" : "rgba(255, 187, 0, 0.4)"};
48 var mainTrackTemplateLandscape = {"font" : "bold 20pt Arial", "lineWidth" : 7.5, "fillStyle" : "black", "strokeStyle" : "white", "textAlign" : "left",
49 "largeShadow" : 8, "shadowOffsetX" : 0, "shadowOffsetY" : 0, "shadowBlur" : 45, "shadowColor" : "rgba(255, 187, 0, 0.5))"};
51 var mainTrackTemplate = {"font" : "bold 30pt Arial", "lineWidth" : 7.5, "fillStyle" : "black", "strokeStyle" : "white", "textAlign" : "left",
52 "largeShadow" : 8, "shadowOffsetX" : 0, "shadowOffsetY" : 0, "shadowBlur" : 45, "shadowColor" : "rgba(255, 187, 0, 0.5))"};
54 var mediaTextTemplate2 = {"font" : "bold 20pt Arial", "lineWidth" : 10.0, "fillStyle" : "white", "strokeStyle" : "rgba(0, 0, 0, 1.0)", "textAlign" : "left",
55 "shadowOffsetX" : 0, "shadowOffsetY" : 0, "shadowBlur" : 0, "shadowColor" : "rgba(0, 0, 0, 1.0)"};
57 var mediaTextTemplate3 = {"font" : "bold 20pt Arial", "lineWidth" : 3.0, "fillStyle" : "white", "strokeStyle" : "rgba(100, 0, 0, 1.0)", "textAlign" : "left"};
59 var trackTextTemplate = {"font" : "bold 16pt Arial", "lineWidth" : 3.0, "fillStyle" : "white", "strokeStyle" : "black", "textAlign" : "left"};
61 var mediaTextTemplate2Landscape = {"font" : "bold 15pt Arial", "lineWidth" : 10.0, "fillStyle" : "white", "strokeStyle" : "rgba(0, 0, 0, 1.0)", "textAlign" : "left",
62 "shadowOffsetX" : 0, "shadowOffsetY" : 0, "shadowBlur" : 0, "shadowColor" : "rgba(0, 0, 0, 1.0)"};
64 var mediaTextTemplate3Landscape = {"font" : "bold 15pt Arial", "lineWidth" : 3.0, "fillStyle" : "white", "strokeStyle" : "rgba(100, 0, 0, 1.0)", "textAlign" : "left"};
66 var trackTextTemplateLandscape = {"font" : "bold 11pt Arial", "lineWidth" : 3.0, "fillStyle" : "white", "strokeStyle" : "black", "textAlign" : "left"};
69 var mediaTextTemplate = {"font" : "bold 20pt Arial", "fillStyle" : "", "textAlign" : "left",
70 "shadowOffsetX" : 0, "shadowOffsetY" : 0, "shadowBlur" : 12, "shadowColor" : "red"};
74 console.log("Content discovery failed");
77 function loadImages(callback)
82 for (var src in audioContent)
86 for (var src in audioContent)
90 audioContent[src].coverArt = new Image();
91 audioContent[src].coverArt.onload = function(){
93 if (++loadedImages >= numImages) {
95 callback(audioContent);
99 audioContent[src].coverArt.onerror = function(e){
100 audioContent[src].coverArt.src = "images/musicButton.png";
103 audioContent[src].coverArt.src = (audioContent[src].coverArtURI !== undefined && audioContent[src].coverArtURI !== "") ? audioContent[src].coverArtURI : "images/musicButton.png";
107 console.log("Failed to load audio cover image");
112 function updateMediaName(newArtist, newTitle, newCover)
114 var playBarHeight = mediaNameCanvas.height;
115 var boxWidth = playBarHeight * 0.75;
116 mediaNameCTX.clearRect(0,0,mediaNameCanvas.width, mediaNameCanvas.height);
118 if (currentPlayerType === "AUDIO")
121 var alphaJump = 0.01;
125 mediaNameCTX.fillStyle="rgba(30,30,30,0.5)";
126 mediaNameCTX.strokeStyle="rgba(130,130,130,1)";
127 mediaNameCTX.lineWidth = 5;
128 mediaNameCTX.fillRect(0,0,mediaNameCanvas.width, playBarHeight);
129 mediaNameCTX.strokeRect(-20,0,mediaNameCanvas.width + 40, playBarHeight);
131 if (newCover === undefined || newCover.naturalWidth === undefined || newCover.naturalWidth <= 0)
133 newCover = musicIcon;
136 mediaNameCTX.drawImage(newCover, 20, (playBarHeight - boxWidth) / 2, boxWidth, boxWidth);
138 if (screenOrientation === "portrait")
140 var textStartX = boxWidth + 50;
141 var trackText = new TextObject(mediaNameCTX,{"text" : newTitle, "xLoc" : textStartX, "yLoc" : 70 , "zLoc" : 0, "width" : mediaNameCanvas.width - textStartX, "height" : 50, "lineHeight" : 50, "wordWrap" : true});
142 trackText.applyTemplate(mainMenuTitleTemplate);
143 var artistText = new TextObject(mediaNameCTX,{"text" : newArtist, "xLoc" : textStartX, "yLoc" : 70 + trackText.height, "zLoc" : 0, "width" : mediaNameCanvas.width - textStartX, "height" : 50, "lineHeight" : 50, "wordWrap" : true});
144 artistText.applyTemplate(mainTrackTemplate);
145 artistText.yLoc = 70 + trackText.height;
149 var textStartX = boxWidth + 50;
150 var trackText = new TextObject(mediaNameCTX,{"text" : newTitle, "xLoc" : textStartX, "yLoc" : 50 , "zLoc" : 0, "width" : mediaNameCanvas.width - textStartX, "height" : 30, "lineHeight" : 30, "wordWrap" : true});
151 trackText.applyTemplate(mainMenuTitleTemplateLandscape);
152 var artistText = new TextObject(mediaNameCTX,{"text" : newArtist, "xLoc" : textStartX, "yLoc" : 50, "zLoc" : 0, "width" : mediaNameCanvas.width - textStartX, "height" : 30, "lineHeight" : 30, "wordWrap" : true});
153 artistText.applyTemplate(mainTrackTemplateLandscape);
154 artistText.yLoc = 50 + trackText.height;
158 trackText.drawLargeShadow();
159 artistText.drawObj();
164 function fillMediaList(contentList)
166 //Don't try and fill an empty content list or an audio list that hasn't finished loading the thumbnails
167 if (contentList.length <=0 || (contentList === audioContent && !imagesLoaded))
172 var iconImg = new Image();
173 var canvasW = mediaListItemW;
174 var canvasH = mediaListItemH * 0.95 ;
176 $("#mediaListItems").empty();
177 var lightColor = false;
178 for (var i=0; i < contentList.length; i++)
182 $("#mediaListItems").append("<li><a href='#'>" +
183 "<canvas id=canvasNum" + i + " width=" + canvasW + " height=" + canvasH + "> </canvas>" +
189 $("#mediaListItems").append("<li><a href='#' class='lightColor'>" +
190 "<canvas id=canvasNum" + i + " width=" + canvasW + " height=" + canvasH + "> </canvas>" +
195 lightColor = !lightColor;
197 currentCanvas = document.getElementById("canvasNum"+ i);
198 currentCTX = currentCanvas.getContext("2d");
200 // Set callback function for the new list item
201 $("#canvasNum"+i).click(function () {
202 listIndex = $(this).parent().parent().index();
204 switch (currentPlayerType)
209 updateMediaName(audioContent[listIndex].artists[0], audioContent[listIndex].title, audioContent[listIndex].coverArt);
210 $("#audioSrc").attr("src", audioContent[listIndex].contentURI);
215 console.log("updateMediaName error: " + err.message);
222 updateMediaName(videoContent[listIndex].artists[0], audioContent[listIndex].title, vidIcon);
223 $("#videoSrc").attr("src", videoContent[listIndex].contentURI);
225 $("#mediaList").fadeOut(300);
229 console.log("updateMediaName error: " + err.message);
236 $("#imagePlayer").css("background", "url(" + imageContent[listIndex].contentURI + ") no-repeat center");
237 $("#imagePlayer").css("background-size", "contain");
238 $("#mediaList").fadeOut(300);
242 console.log("updateMediaName error: " + err.message);
251 switch (currentPlayerType)
254 currentCTX.drawImage(audioContent[i].coverArt, 0, 0, canvasH, canvasH );
255 var trackText = new TextObject(currentCTX,{"text" : contentList[i].title, "xLoc" : canvasH + 20, "yLoc" : canvasH / 2.5 , "zLoc" : 0});
256 var artistText = new TextObject(currentCTX,{"text" : contentList[i].artists[0], "xLoc" : canvasH + 20, "yLoc" : canvasH / 1.1 , "zLoc" : 0});
260 currentCTX.drawImage(vidIcon, 0, 0, canvasH, canvasH );
261 var artistText = new TextObject(currentCTX,{"text" : contentList[i].artists[0], "xLoc" : canvasH + 20, "yLoc" : canvasH / 2.5 , "zLoc" : 0});
262 var trackText = new TextObject(currentCTX,{"text" : contentList[i].title, "xLoc" : canvasH + 20, "yLoc" : canvasH / 1.1 , "zLoc" : 0});
266 currentCTX.drawImage(imgIcon, 0, 0, canvasH, canvasH );
267 var artistText = new TextObject(currentCTX,{"text" : contentList[i].title, "xLoc" : canvasH + 20, "yLoc" : canvasH / 2.5 , "zLoc" : 0});
268 var trackText = new TextObject(currentCTX,{"text" : " ", "xLoc" : canvasH + 20, "yLoc" : canvasH / 1.1 , "zLoc" : 0});
275 var mediaTextTemp1 = screenOrientation === "portrait" ? mediaTextTemplate2 : mediaTextTemplate2Landscape;
276 var mediaTextTemp2 = screenOrientation === "portrait" ? mediaTextTemplate3 : mediaTextTemplate3Landscape;
277 var trackTextTemp = screenOrientation === "portrait" ? trackTextTemplate : trackTextTemplateLandscape;
279 trackText.applyTemplate(mediaTextTemp1);
281 trackText.applyTemplate(mediaTextTemp2);
284 artistText.applyTemplate(trackTextTemp);
285 artistText.drawObj();
288 $("#mediaListItems li").css({"width" : mediaListItemW + "px", "height" : mediaListItemH + "px", "margin-bottom" : "10px"});
291 function onContentItemArraySuccess(content)
293 var emptyContent = true;
295 if (!content || content === undefined || content.length <= 0)
296 console.log("Invalid content for " + contentType);
299 emptyContent = false;
310 audioContent = content;
311 sortByAlpha(audioContent);
313 $("#audioSrc").attr("src", audioContent[0].contentURI);
316 for (var i = 0; i < audioContent.length; i++)
318 var iconURI = (audioContent[i].thumbnailURIs !== undefined && audioContent[i].thumbnailURIs !== null) ? audioContent[i].thumbnailURIs[0] : "images/musicButton.png";
319 audioContent[i].coverArtURI = iconURI;
322 loadImages(fillMediaList);
327 console.log("Error when parsing audioContent");
331 contentType = "VIDEO";
337 videoContent = content;
338 $("#videoSrc").attr("src", videoContent[0].contentURI);
340 contentType = "IMAGE";
346 imageContent = content;
347 $("#imagePlayer").css("background", "url(" + imageContent[0].contentURI + ") no-repeat center");
348 $("#imagePlayer").css("background-size", "contain");
350 contentType = undefined;
354 console.log("Undefined content search type");
355 nextContentType = undefined;
359 if (contentType !== undefined)
360 getMedia(contentType);
363 function getMedia(mediaType)
365 var manager = tizen.content;
367 var filter = new tizen.AttributeFilter("type", "EXACTLY", mediaType);
368 manager.find(onContentItemArraySuccess, onError, null, filter);
371 function showMediaMenu()
373 $(".navButton").fadeIn(800);
375 switch(currentPlayerType)
381 updateMediaName(audioContent[listIndex].artists[0], audioContent[listIndex].title, audioContent[listIndex].coverArt);
385 console.log("updateMediaName failed for showMediaMenu (audio) : " + err.message);
388 $("#mediaName").fadeIn(800);
389 $(".sortButton").fadeIn(800);
390 currentPlayer.fadeIn(800);
392 $("#mediaList").addClass("mediaListAudioList");
394 if (screenOrientation === "landscape" )
395 $("#mediaList").addClass("landscape");
397 $("#mediaList").removeClass("landscape");
399 $("#mediaList").fadeIn(800);
404 setTimeout(function(){currentPlayer.show()}, 800); //The video element can't be faded, so wait a moment before showing
409 currentPlayer.fadeIn(800);
413 console.log("Invalid player type");
418 function showMediaList()
420 if ($("#mediaList").is(":visible"))
421 $("#mediaList").fadeOut(300);
424 fillMediaList(currentContent);
425 $("#mediaList").fadeIn(300);
429 function changeMenu(menuButtonId)
431 var clickedButton = $("#" + menuButtonId);
432 var buttonWidth = clickedButton.width();
433 var buttonHeight = clickedButton.height();
434 var buttonBottom = clickedButton.css("bottom");
435 var buttonRight = clickedButton.css("right");
437 //Animate the clicked button slightly
438 clickedButton.animate({
439 bottom: screenOrientation === "portrait" ? "+=0" : "+=50",
440 right: screenOrientation === "portrait" ? "+=50" : "+=0",
444 //Reset the size once done
446 clickedButton.width(buttonWidth);
447 clickedButton.height(buttonHeight);
449 if (screenOrientation === "portrait")
450 clickedButton.css({"right": buttonRight});
452 clickedButton.css({"bottom": buttonBottom});
456 $(".mainButton").fadeOut(300);
460 case ("mainMusicButton"):
461 currentPlayer = $("#audioPlayer");
462 currentPlayerControls = document.getElementById("audioPlayer");
463 currentPlayerType = "AUDIO";
464 currentContent = audioContent;
468 case ("mainVideoButton"):
469 currentPlayer = $("#videoPlayer");
470 currentPlayerControls = document.getElementById("videoPlayer");
471 currentPlayerType = "VIDEO";
472 currentContent = videoContent;
476 case ("mainImageButton"):
477 currentPlayer = $("#imagePlayer");
478 currentPlayerControls = imageControls;
479 currentPlayerType = "IMAGE";
480 currentContent = imageContent;
484 console.log("Error: No menu by that name");
489 function showMainMenu()
491 currentPlayerControls.pause();
493 $("#playButton").attr("src","images/playButton.png");
495 //If the media list is showing, hide it. Remove the mediaListAudioList class if it exists so that it will resize properly
496 if ($("#mediaList").is(":visible"))
497 $("#mediaList").fadeOut(300, function(){$("#mediaList").removeClass("mediaListAudioList");});
499 $(".navButton").fadeOut(300);
500 $(".sortButton").fadeOut(300);
501 $("#mediaName").fadeOut(300);
503 if (currentPlayerType !== "VIDEO")
504 currentPlayer.fadeOut(300);
506 currentPlayer.hide();
509 $(".mainButton").css({"opacity": "100"});
510 $(".mainButton").fadeIn(800);
513 function sortByAlpha(contentToSort)
515 //If contentToSort is undefined it's because the request came from the sortBy buttons
516 if (contentToSort === undefined)
517 contentToSort = audioContent;
519 contentToSort.sort(function (a,b) {
520 var first = a.title.toLowerCase();
521 var second = b.title.toLowerCase();
531 fillMediaList(contentToSort);
534 function sortByArtist(contentToSort)
536 if (contentToSort === undefined)
537 contentToSort = audioContent;
539 contentToSort.sort(function (a,b) {
540 var first = a.artists[0].toLowerCase();
541 var second = b.artists[0].toLowerCase();
551 fillMediaList(contentToSort);
554 function sortByAlbum(contentToSort)
556 if (contentToSort === undefined)
557 contentToSort = audioContent;
559 contentToSort.sort(function (a,b) {
560 var first = a.album.toLowerCase();
561 var second = b.album.toLowerCase();
571 fillMediaList(contentToSort);
573 /**************************************** NAVIGATION FUNCTIONS *******************************************/
575 function playButtonClick()
577 if (currentPlayerControls.paused)
579 currentPlayerControls.play();
580 $("#playButton").attr("src","images/pauseButton.png");
584 currentPlayerControls.pause();
585 $("#playButton").attr("src","images/playButton.png");
589 function backButtonClick()
591 switch (currentPlayerType)
599 listIndex = imageContent.length - 1;
602 $("#playButton").attr("src","images/playButton.png");
604 $("#audioSrc").attr("src", audioContent[listIndex].contentURI);
605 updateMediaName(audioContent[listIndex].artists[0], audioContent[listIndex].title, audioContent[listIndex].coverArt);
616 videoIndex = imageContent.length - 1;
618 if ($("#mediaList").is(":visible"))
621 $("#playButton").attr("src","images/playButton.png");
622 $("#videoSrc").attr("src", videoContent[videoIndex].contentURI);
633 imageIndex = imageContent.length - 1;
635 $("#imagePlayer").css("background", "url(" + imageContent[imageIndex].contentURI + ") no-repeat center");
636 $("#imagePlayer").css("background-size", "contain");
641 console.log("Content failure");
647 function nextButtonClick()
649 switch (currentPlayerType)
654 if (audioContent.length > (listIndex + 1))
660 $("#playButton").attr("src","images/playButton.png");
661 $("#audioSrc").attr("src", audioContent[listIndex].contentURI);
662 updateMediaName(audioContent[listIndex].artists[0], audioContent[listIndex].title, audioContent[listIndex].coverArt);
670 if (videoContent.length > (videoIndex + 1))
676 $("#playButton").attr("src","images/playButton.png");
677 $("#videoSrc").attr("src", videoContent[videoIndex].contentURI);
685 if (imageContent.length > (imageIndex + 1))
690 $("#imagePlayer").css("background", "url(" + imageContent[imageIndex].contentURI + ") no-repeat center");
691 $("#imagePlayer").css("background-size", "contain");
696 console.log("Content failure");
701 /**************************************** END NAVIGATION FUNCTIONS *******************************************/
703 function resizeMainMenu()
705 $("#mediaList").fadeOut(0);
706 screenWidth = window.innerWidth;
707 screenHeight = window.innerHeight;
708 screenOrientation = screenWidth < screenHeight ? "portrait" : "landscape";
709 iconWidth = screenOrientation === "portrait" ? screenHeight / 4 : screenWidth / 4;
712 $(".mainButton").width(iconWidth + "px");
713 $(".mainButton").height(iconWidth + "px");
715 var iconsTop = screenOrientation === "portrait" ? ((screenHeight - (iconWidth * 3)) / 2) - (padding * 3) : (screenHeight - iconWidth) / 2;
717 if (screenOrientation === "portrait")
718 $("#mainMenuButtons").css({"top": iconsTop + "px", "left" : (screenWidth / 2) - (iconWidth /2) - padding + "px", "width" : "50%"});
721 $("#mainMenuButtons").css({"top": iconsTop + "px", "left" : ((iconWidth / 2) - (padding * 3)) + "px", "width" : "100%"});
722 $("#sortButtons").addClass("landscape");
726 function resizePlayerPage()
728 audioPlayer = document.getElementById("audioPlayer");
729 videoPlayer = document.getElementById("videoPlayer");
730 screenWidth = window.innerWidth;
731 screenHeight = window.innerHeight;
734 var buttonWidth = screenOrientation === "portrait" ? screenHeight * 0.05 : screenWidth * 0.05;
736 $("#backButton").css({"width": buttonWidth + "px", "height": buttonWidth + "px", "top": padding + "px", "left": ((screenWidth / 2) - (buttonWidth *3)) + "px"});
737 $("#nextButton").css({"width": buttonWidth + "px", "height": buttonWidth + "px", "top": padding + "px", "left": ((screenWidth / 2) + (buttonWidth *2)) + "px"});
738 $("#returnButton").css({"width": buttonWidth + "px", "height": buttonWidth + "px", "top": padding + "px", "left": padding + "px"});
739 $("#listButton").css({"width": buttonWidth + "px", "height": buttonWidth + "px", "top": padding + "px", "left": (screenWidth - buttonWidth - padding * 2) + "px"});
740 $("#playButton").css({"width": buttonWidth * 1.3 + "px", "height": buttonWidth * 1.3 + "px", "top": padding * 0.3 + "px", "left": (screenWidth / 2) - (buttonWidth / 2) + "px"});
742 mediaNameCanvas.width = (screenWidth);
743 mediaNameCanvas.height = (screenHeight * 0.34) - (buttonWidth + (2 * padding));
744 mediaNameCanvas.style.top = (buttonWidth + (2 * padding) ) + "px";
745 mediaNameCanvas.style.left = "0px";
747 var sortButtonTop = (buttonWidth + (2 * padding) ) + mediaNameCanvas.height - (buttonWidth * 1.3);
748 var sortButtonWidth = buttonWidth * 2.5;
749 var buttonSpacing = screenWidth / 5;
751 mediaListItemW = $("#mediaList").width() * 0.92;
752 mediaListItemH = $("#mediaList").height() / 10;
762 * swipe - Handles swipe events. Currently it just acts as another way to hit the next / back buttons, but
763 * it could be expanded to other things in the future.
766 function swipe(direction, object)
772 if (direction === "right")
774 else if (direction === "left")
785 musicIcon.src = "images/musicButton.png";
786 vidIcon.src = "images/videoButton.png";
787 imgIcon.src = "images/imageButton.png";
788 imageControls = new ImageControls();
790 mediaNameCanvas = document.getElementById("mediaName");
791 mediaNameCTX = mediaNameCanvas.getContext("2d");
793 //Resize all items and search for local media
795 getMedia(contentType);
797 //Prevent highlighting
798 window.ondragstart = function() { return false; }
800 $(window).bind('resize', resizeAll);
802 //Simple swipe detection
803 $("#mediaName").mousedown(function(e){mouseDownEvent = e;});
804 $("#mediaName").mouseup(function(e){
805 if (Math.abs(mouseDownEvent.clientY - e.clientY) < 100)
807 if (Math.abs(mouseDownEvent.clientX - e.clientX) > 100)
809 if (mouseDownEvent.clientX > e.clientX)
810 swipe("left", "mediaName");
812 swipe("right", "mediaName");
818 $(document).ready(function () {