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";
20 var currentMediaList = $("#audioMediaList");
21 var audioMediaListLoaded = false;
22 var videoMediaListLoaded = false;
23 var imageMediaListLoaded = false;
27 var vidIcon = new Image();
28 var imgIcon = new Image();
29 var musicIcon = new Image();
30 var imagesLoaded = false;
33 var playOnConnect = false;
39 var nightMode = false;
40 var waitingToResumeVideo = false; //Media has been paused by exterior forces. If set to true, resume previous media when given the signal.
46 var mainMenuTitleTemplateLandscape = {"font" : "oblique bolder 30pt arial", "lineWidth" : 9.5, "fillStyle" : "black", "strokeStyle" : "white", "textAlign" : "left",
47 "largeShadow" : 8, "shadowOffsetX" : 0, "shadowOffsetY" : 0, "shadowBlur" : 45, "shadowColor" : "rgba(255, 187, 0, 0.4)"};
49 var mainMenuTitleTemplate = {"font" : "oblique bolder 40pt arial", "lineWidth" : 9.5, "fillStyle" : "black", "strokeStyle" : "white", "textAlign" : "left",
50 "largeShadow" : 8, "shadowOffsetX" : 0, "shadowOffsetY" : 0, "shadowBlur" : 45, "shadowColor" : "rgba(255, 187, 0, 0.4)"};
52 var mainTrackTemplateLandscape = {"font" : "bold 20pt Arial", "lineWidth" : 7.5, "fillStyle" : "black", "strokeStyle" : "white", "textAlign" : "left",
53 "largeShadow" : 8, "shadowOffsetX" : 0, "shadowOffsetY" : 0, "shadowBlur" : 45, "shadowColor" : "rgba(255, 187, 0, 0.5))"};
55 var mainTrackTemplate = {"font" : "bold 30pt Arial", "lineWidth" : 7.5, "fillStyle" : "black", "strokeStyle" : "white", "textAlign" : "left",
56 "largeShadow" : 8, "shadowOffsetX" : 0, "shadowOffsetY" : 0, "shadowBlur" : 45, "shadowColor" : "rgba(255, 187, 0, 0.5))"};
58 var timeTemplate = {"font" : "bold 25pt Arial", "lineWidth" : 7.5, "fillStyle" : "black", "strokeStyle" : "white", "textAlign" : "left",
59 "largeShadow" : 8, "shadowOffsetX" : 0, "shadowOffsetY" : 0, "shadowBlur" : 45, "shadowColor" : "rgba(255, 187, 0, 0.5))"};
61 var mediaTextTemplate2 = {"font" : "bold 20pt 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 mediaTextTemplate3 = {"font" : "bold 20pt Arial", "lineWidth" : 3.0, "fillStyle" : "white", "strokeStyle" : "rgba(100, 0, 0, 1.0)", "textAlign" : "left"};
66 var trackTextTemplate = {"font" : "bold 16pt Arial", "lineWidth" : 3.0, "fillStyle" : "white", "strokeStyle" : "black", "textAlign" : "left"};
68 var mediaTextTemplate2Landscape = {"font" : "bold 13pt Arial", "lineWidth" : 10.0, "fillStyle" : "white", "strokeStyle" : "rgba(0, 0, 0, 1.0)", "textAlign" : "left",
69 "shadowOffsetX" : 0, "shadowOffsetY" : 0, "shadowBlur" : 0, "shadowColor" : "rgba(0, 0, 0, 1.0)"};
71 var mediaTextTemplate3Landscape = {"font" : "bold 13pt Arial", "lineWidth" : 3.0, "fillStyle" : "white", "strokeStyle" : "rgba(100, 0, 0, 1.0)", "textAlign" : "left"};
73 var trackTextTemplateLandscape = {"font" : "bold 11pt Arial", "lineWidth" : 3.0, "fillStyle" : "white", "strokeStyle" : "black", "textAlign" : "left"};
76 var mediaTextTemplate = {"font" : "bold 20pt Arial", "fillStyle" : "", "textAlign" : "left",
77 "shadowOffsetX" : 0, "shadowOffsetY" : 0, "shadowBlur" : 12, "shadowColor" : "red"};
81 console.log("Content discovery failed");
84 function setupSpeech()
86 console.log("MediaPlayer in setupSpeech");
88 speechObj = tizen.speech;
89 speechObj.vocalizeString(" ");
93 var speechEventListener = {
94 onaudiostart: function(){console.log("MediaPlayer: onaudiostart received");},
95 onsoundstart: function(){console.log("MediaPlayer: onsoundstart received");},
96 onspeechstart: function(){console.log("MediaPlayer: onspeechstart received");},
97 onspeechend: function(){console.log("MediaPlayer: onspeechend received");},
98 onsoundend: function(){console.log("MediaPlayer: onsoundend received");},
99 onaudioend: function(){console.log("MediaPlayer: onaudioend received");},
100 onresult: function(result){
102 console.log("MediaPlayer: onresult received");
104 for (var i = 0; i < result.length; i++)
106 console.log("MediaPlayer: forloop, command = " + result[i]);
107 var commandFound = false;
136 onnomatch: function(result){console.log("MediaPlayer: onnomatch received ");},
137 onerror: function(error){console.log("MediaPlayer: onerror received");},
138 onstart: function(){console.log("MediaPlayer: onstart received");},
139 onend: function(){console.log("MediaPlayer: onend received");}
142 speechObj.setCBListener(speechEventListener);
147 console.log("MediaPlayer setupSpeech FAILED + " + err.message);
152 function onAudioContentLoaded(newContent)
154 if (!newContent || newContent.length === 0)
156 console.log("MediaPlayer: some content failed to load, trying again for " + audioPlayer.type);
157 audioPlayer.clearContent();
158 setTimeout(function(){getMedia(onAudioContentLoaded, "AUDIO");}, 3000);
163 audioPlayer.updateContent(newContent, true);
164 audioPlayer.onContentLoaded();
168 function onVideoContentLoaded(newContent)
170 if (!newContent || newContent.length === 0)
172 console.log("MediaPlayer: some content failed to load, trying again for " + videoPlayer.type);
173 videoPlayer.clearContent();
174 setTimeout(function(){getMedia(onVideoContentLoaded, "VIDEO");}, 3000);
179 videoPlayer.updateContent(newContent, true);
180 videoPlayer.onContentLoaded();
184 function onImageContentLoaded(newContent)
186 if (!newContent || newContent.length === 0)
188 console.log("MediaPlayer: some content failed to load, trying again for " + imagePlayer.type);
189 imagePlayer.clearContent();
190 setTimeout(function(){getMedia(onImageContentLoaded, "IMAGE");}, 3000);
195 imagePlayer.updateContent(newContent, true);
196 imagePlayer.onContentLoaded();
200 function getMedia(callback, filterType)
202 console.log("MediaPlayer in getMedia");
203 var manager = tizen.content;
206 var filter = new tizen.AttributeFilter("type", "EXACTLY", filterType);
207 manager.find(callback, onError, null, filter);
210 console.log("MediaPlayer failed to receive media, tizen.content is unavailable");
213 function showMediaMenu()
215 console.log("MediaPlayer in showMediaMenu");
216 $(".navButton").show();
218 switch(currentPlayer.type)
221 $("#mediaName").show();
222 $("#trackTime").show();
223 $(".sortButton").show();
224 currentPlayer.show();
226 if (screenOrientation === "landscape" )
227 $("#audioMediaList").addClass("landscape");
229 $("#audioMediaList").removeClass("landscape");
231 $("#audioMediaList").show();
236 currentPlayer.show();
237 //setTimeout(function(){currentPlayer.show()}, 800); //The video element can't be faded, so wait a moment before showing
242 currentPlayer.show();
246 console.log("Invalid player type");
251 function showMediaList()
253 console.log("MediaPlayer in showMediaList");
255 if (currentMediaList.is(":visible"))
256 currentMediaList.hide();
259 currentMediaList.show();
263 function changeMenu(menuButtonId)
265 console.log("MediaPlayer in changeMenu");
266 var clickedButton = $("#" + menuButtonId);
267 var buttonWidth = clickedButton.width();
268 var buttonHeight = clickedButton.height();
269 var buttonBottom = clickedButton.css("bottom");
270 var buttonRight = clickedButton.css("right");
273 //Animate the clicked button slightly
274 clickedButton.animate({
275 bottom: screenOrientation === "portrait" ? "+=0" : "+=50",
276 right: screenOrientation === "portrait" ? "+=50" : "+=0",
280 //Reset the size once done
282 clickedButton.width(buttonWidth);
283 clickedButton.height(buttonHeight);
285 if (screenOrientation === "portrait")
286 clickedButton.css({"right": buttonRight});
288 clickedButton.css({"bottom": buttonBottom});
292 $(".mainButton").hide();
296 case ("mainMusicButton"):
297 speechObj.vocalizeString("Music player");
298 currentMenu = "audio";
299 currentPlayer = audioPlayer;
300 currentMediaList = $("#audioMediaList");
301 localStorage.prevMenu = "mainMusicButton";
303 if (audioPlayer.currentAudioContent && audioPlayer.currentAudioContent.contentURI)
305 localStorage.prevAudioTrack = audioPlayer.currentAudioContent.contentURI
306 localStorage.prevAudioTime = audioPlayer.playerControls.currentTime;
309 localStorage.prevVideo = undefined;
310 localStorage.prevVideoTime = undefined;
312 if (!audioMediaListLoaded)
313 audioPlayer.fillMediaList();
318 case ("mainVideoButton"):
319 speechObj.vocalizeString("Video player");
320 currentMenu = "video";
321 currentPlayer = videoPlayer;
322 currentMediaList = $("#videoMediaList");
323 localStorage.prevMenu = "mainVideoButton";
325 if (videoPlayer.currentVideoContent && videoPlayer.currentVideoContent.contentURI)
327 localStorage.prevVideo = videoPlayer.currentVideoContent.contentURI
328 localStorage.prevVideoTime = videoPlayer.playerControls.currentTime;
331 localStorage.prevAudioTime = undefined;
332 localStorage.prevAudioTrack = undefined;
334 if (!videoMediaListLoaded)
335 videoPlayer.fillMediaList();
340 case ("mainImageButton"):
341 speechObj.vocalizeString("Picture viewer");
342 currentMenu = "image";
343 currentPlayer = imagePlayer;
344 currentMediaList = $("#imageMediaList");
345 localStorage.prevMenu = "mainImageButton";
347 if (!imageMediaListLoaded)
348 imagePlayer.fillMediaList();
353 console.log("Error: No menu by that name");
358 function showMainMenu()
360 console.log("MediaPlayer in showMainMenu, clearing all localStorage...");
361 currentMenu = "main";
362 localStorage.prevMenu = "MAIN";
363 localStorage.prevAudioTime = undefined;
364 localStorage.prevAudioTrack = undefined;
365 localStorage.prevVideo = undefined;
366 localStorage.prevVideoTime = undefined;
367 localStorage.prevImage = undefined;
369 currentPlayer.pause();
371 //If the media list is showing, hide it. Remove the mediaListAudioList class if it exists so that it will resize properly
372 if (currentMediaList.is(":visible"))
373 currentMediaList.hide();
375 $(".navButton").hide();
376 $(".sortButton").hide();
377 $("#mediaName").hide();
378 $("#trackTime").hide();
380 $(".mainButton").css({"opacity": "100"});
381 $(".mainButton").show();
384 function sortByAlpha(contentToSort)
386 currentPlayer.sortByAlpha();
389 function sortByArtist(contentToSort)
391 currentPlayer.sortByArtist();
394 function sortByAlbum(contentToSort)
396 currentPlayer.sortByAlbum();
399 /**************************************** NAVIGATION FUNCTIONS *******************************************/
401 // This function is called once a file being loaded is ready to play
402 function playLoadedMedia()
404 audioPlayer.playLoadedMedia();
407 function videoLoaded()
409 videoPlayer.videoLoaded();
412 function playButtonClick()
414 console.log("MediaPlayer in playButtonClick");
415 if (!currentPlayer.playing())
416 currentPlayer.play();
418 currentPlayer.pause();
421 function pauseButtonClick()
423 console.log("MediaPlayer in pauseButtonClick");
424 if (currentPlayer.playing())
426 currentPlayer.pause();
430 function backButtonClick()
432 console.log("MediaPlayer in backButtonClick");
433 currentPlayer.previous();
437 function nextButtonClick()
439 console.log("MediaPlayer in nextButtonClick");
440 currentPlayer.next();
443 /**************************************** END NAVIGATION FUNCTIONS *******************************************/
445 function resizeMainMenu()
447 console.log("MediaPlayer in resizeMainMenu");
449 currentMediaList.hide();
450 screenWidth = window.innerWidth;
451 screenHeight = window.innerHeight;
452 screenOrientation = screenWidth < screenHeight ? "portrait" : "landscape";
453 iconWidth = screenOrientation === "portrait" ? screenHeight / 4 : screenWidth / 4;
456 $(".mainButton").width(iconWidth + "px");
457 $(".mainButton").height(iconWidth + "px");
459 var iconsTop = screenOrientation === "portrait" ? ((screenHeight - (iconWidth * 3)) / 2) - (padding * 3) : (screenHeight - iconWidth) / 2;
461 if (screenOrientation === "portrait")
462 $("#mainMenuButtons").css({"top": iconsTop + "px", "left" : (screenWidth / 2) - (iconWidth /2) - padding + "px", "width" : "50%"});
465 $("#mainMenuButtons").css({"top": iconsTop + "px", "left" : ((iconWidth / 2) - (padding * 3)) + "px", "width" : "100%"});
466 $("#sortButtons").addClass("landscape");
470 function resizePlayerPage()
472 console.log("MediaPlayer in resizePlayerPage");
474 screenWidth = window.innerWidth;
475 screenHeight = window.innerHeight;
478 var buttonWidth = screenOrientation === "portrait" ? screenHeight * 0.05 : screenWidth * 0.05;
480 $("#backButton").css({"width": buttonWidth + "px", "height": buttonWidth + "px", "top": padding + "px", "left": ((screenWidth / 2) - (buttonWidth *3)) + "px"});
481 $("#nextButton").css({"width": buttonWidth + "px", "height": buttonWidth + "px", "top": padding + "px", "left": ((screenWidth / 2) + (buttonWidth *2)) + "px"});
482 $("#returnButton").css({"width": buttonWidth + "px", "height": buttonWidth + "px", "top": padding + "px", "left": padding + "px"});
483 $("#listButton").css({"width": buttonWidth + "px", "height": buttonWidth + "px", "top": padding + "px", "left": (screenWidth - buttonWidth - padding * 2) + "px"});
484 $("#playButton").css({"width": buttonWidth * 1.15 + "px", "height": buttonWidth * 1.15 + "px", "top": padding * 0.3 + "px", "left": (screenWidth / 2) - (buttonWidth / 2) + "px"});
486 trackTimeCanvas.width = mediaNameCanvas.width = (screenWidth);
487 trackTimeCanvas.height = mediaNameCanvas.height = (screenHeight * 0.34) - (buttonWidth + (2 * padding));
488 trackTimeCanvas.style.top = mediaNameCanvas.style.top = (buttonWidth + (2 * padding) ) + "px";
489 trackTimeCanvas.style.left = mediaNameCanvas.style.left = "0px";
491 var sortButtonTop = (buttonWidth + (2 * padding) ) + mediaNameCanvas.height - (buttonWidth * 1.3);
492 var sortButtonWidth = buttonWidth * 2.5;
493 var buttonSpacing = screenWidth / 5;
495 mediaListItemW = $("#videoMediaList").width() * 0.92;
496 mediaListItemH = $("#videoMediaList").height() / 10;
501 console.log("MediaPlayer in resizeAll");
507 * swipe - Handles swipe events. Currently it just acts as another way to hit the next / back buttons, but
508 * it could be expanded to other things in the future.
511 function swipe(direction, object)
513 console.log("MediaPlayer in swipe");
517 if (direction === "right")
519 else if (direction === "left")
528 function toggleNightMode(nightModeValue)
530 if (nightMode !== nightModeValue)
532 Array.prototype.forEach.call (document.querySelectorAll ('*'), function (el) {el.classList.toggle('night');});
533 nightMode = nightModeValue;
539 console.log("MediaPlayer in init");
541 musicIcon.src = "images/musicIcon.png";
542 vidIcon.src = "images/videoIcon.png";
543 imgIcon.src = "images/imageIcon.png";
544 mediaNameCanvas = document.getElementById("mediaName");
545 mediaNameCTX = mediaNameCanvas.getContext("2d");
546 trackTimeCanvas = document.getElementById("trackTime");
547 trackTimeCTX = trackTimeCanvas.getContext("2d");
548 playBarHeight = mediaNameCanvas.height;
549 boxWidth = playBarHeight * 0.75;
550 textStartX = boxWidth + 50;
552 var vehicle = tizen.vehicle;
555 /* Subscribe to AMB NightMode signal, and switch colors
556 * upon receipt of the signal
559 if (vehicle && vehicle !== undefined)
561 var getVal = vehicle.get("NightMode");
563 //Check that NightMode returned a value before trying to hook up to it
566 toggleNightMode(getVal.nightMode);
569 /* Subscribe to AMB NightMode signal, and switch colors
570 * upon receipt of the signal
573 vehicle.subscribe("NightMode",function(value) {
574 console.log("MediaPlayer: Day / Night mode changed to " + value.nightMode);
575 toggleNightMode(value.nightMode);
579 /* Subscribe to AMB DrivingMode signal, and pause video
580 * upon receipt of the signal
584 vehicle.subscribe("DrivingMode",function(value) {
585 console.log("MediaPlayer: DrivingMode changed to " + value.drivingMode);
587 if (value.drivingMode > 0 && currentPlayer.type === "video" && currentPlayer.playing())
589 console.log("MediaPlayer: pausing video due to vehicle motion");
590 currentPlayer.pause();
591 waitingToResumeVideo = true;
593 else if (value.drivingMode === 0 && currentPlayer.type === "video" && waitingToResumeVideo)
595 console.log("MediaPlayer: vehicle has stopped, resuming video");
596 currentPlayer.play();
597 waitingToResumeVideo = false;
602 //Setup voice control
606 console.log("MediaPlayer: Speech Recognition not running, voice control will be unavailable");
608 vocalizeString: function(item) { console.log(item); }
612 audioPlayer = new MediaPlayer("audio");
613 videoPlayer = new MediaPlayer("video");
614 imagePlayer = new MediaPlayer("image");
615 currentPlayer = audioPlayer;
617 //Resize all items and search for local media
620 if (localStorage.prevMenu && localStorage.prevMenu !== "MAIN")
621 changeMenu(localStorage.prevMenu)
625 getMedia(onAudioContentLoaded, "AUDIO");
626 getMedia(onVideoContentLoaded, "VIDEO");
627 getMedia(onImageContentLoaded, "IMAGE");
629 //Check if DLNA plugin is installed. If so, scan for media.
630 if (tizen.mediaserver)
632 //Currently no success signal, so continue trying until a server is found. Once that
633 //happens, clear the stopServerSearch interval
635 stopServerSearch = setInterval(function(){console.log("MediaPlayer searching for remote media..."); tizen.mediaserver.scanNetwork(foundMediaServer);}, 5000);
638 console.log("MediaPlayer: No DLNA server running, using local media only...");
640 //Prevent highlighting
641 window.ondragstart = function() { return false; }
643 $(window).bind('resize', resizeAll);
645 //Simple swipe detection
646 $("#mediaName").mousedown(function(e){mouseDownEvent = e;});
647 $("#mediaName").mouseup(function(e){
648 if (Math.abs(mouseDownEvent.clientY - e.clientY) < 100)
650 if (Math.abs(mouseDownEvent.clientX - e.clientX) > 100)
652 if (mouseDownEvent.clientX > e.clientX)
653 swipe("left", "mediaName");
655 swipe("right", "mediaName");
660 document.getElementById('videoPlayer').addEventListener("playing", function() {
661 $("#playButton").toggleClass('playing', true);
662 $("#navigationButtons").hide();
664 document.getElementById('videoPlayer').addEventListener("pause", function() {
665 $("#playButton").toggleClass('playing', false);
666 $("#navigationButtons").show();
668 document.getElementById('videoPlayer').addEventListener("ended", function() {
669 $("#playButton").toggleClass('playing', false);
670 $("#navigationButtons").show();
672 document.getElementById('audioPlayer').addEventListener("playing", function() {
673 $("#playButton").toggleClass('playing', true);
675 document.getElementById('audioPlayer').addEventListener("pause", function() {
676 $("#playButton").toggleClass('playing', false);
678 document.getElementById('audioPlayer').addEventListener("ended", function() {
679 $("#playButton").toggleClass('playing', false);
681 document.getElementById('imagePlayer').addEventListener("click", function() {
682 if (!imagePlayer.playing)
689 // pause the slideshow and fade in the controls
691 $("#navigationButtons").show();
696 $(document).ready(function () {