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.
45 var remoteMediaSearchAttempts = 0;
47 var mainMenuTitleTemplateLandscape = {"font" : "oblique bolder 18pt arial", "lineWidth" : 6.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 mainMenuTitleTemplate = {"font" : "oblique bolder 40pt arial", "lineWidth" : 9.5, "fillStyle" : "black", "strokeStyle" : "white", "textAlign" : "left",
51 "largeShadow" : 8, "shadowOffsetX" : 0, "shadowOffsetY" : 0, "shadowBlur" : 45, "shadowColor" : "rgba(255, 187, 0, 0.4)"};
53 var mainTrackTemplateLandscape = {"font" : "bold 16pt Arial", "lineWidth" : 4.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 mainTrackTemplate = {"font" : "bold 30pt Arial", "lineWidth" : 7.5, "fillStyle" : "black", "strokeStyle" : "white", "textAlign" : "left",
57 "largeShadow" : 8, "shadowOffsetX" : 0, "shadowOffsetY" : 0, "shadowBlur" : 45, "shadowColor" : "rgba(255, 187, 0, 0.5))"};
59 var timeTemplate = {"font" : "bold 25pt Arial", "lineWidth" : 7.5, "fillStyle" : "black", "strokeStyle" : "white", "textAlign" : "left",
60 "largeShadow" : 8, "shadowOffsetX" : 0, "shadowOffsetY" : 0, "shadowBlur" : 45, "shadowColor" : "rgba(255, 187, 0, 0.5))"};
62 var timeTemplateLandscape = {"font" : "bold 6pt Arial", "lineWidth" : 3.5, "fillStyle" : "black", "strokeStyle" : "white", "textAlign" : "left",
63 "largeShadow" : 8, "shadowOffsetX" : 0, "shadowOffsetY" : 0, "shadowBlur" : 45, "shadowColor" : "rgba(255, 187, 0, 0.5))"};
65 var mediaTextTemplate2 = {"font" : "bold 20pt Arial", "lineWidth" : 10.0, "fillStyle" : "white", "strokeStyle" : "rgba(0, 0, 0, 1.0)", "textAlign" : "left",
66 "shadowOffsetX" : 0, "shadowOffsetY" : 0, "shadowBlur" : 0, "shadowColor" : "rgba(0, 0, 0, 1.0)"};
68 var mediaTextTemplate3 = {"font" : "bold 20pt Arial", "lineWidth" : 3.0, "fillStyle" : "white", "strokeStyle" : "rgba(100, 0, 0, 1.0)", "textAlign" : "left"};
70 var trackTextTemplate = {"font" : "bold 16pt Arial", "lineWidth" : 3.0, "fillStyle" : "white", "strokeStyle" : "black", "textAlign" : "left"};
72 var mediaTextTemplate2Landscape = {"font" : "bold 13pt Arial", "lineWidth" : 10.0, "fillStyle" : "white", "strokeStyle" : "rgba(0, 0, 0, 1.0)", "textAlign" : "left",
73 "shadowOffsetX" : 0, "shadowOffsetY" : 0, "shadowBlur" : 0, "shadowColor" : "rgba(0, 0, 0, 1.0)"};
75 var mediaTextTemplate3Landscape = {"font" : "bold 13pt Arial", "lineWidth" : 3.0, "fillStyle" : "white", "strokeStyle" : "rgba(100, 0, 0, 1.0)", "textAlign" : "left"};
77 var trackTextTemplateLandscape = {"font" : "bold 11pt Arial", "lineWidth" : 3.0, "fillStyle" : "white", "strokeStyle" : "black", "textAlign" : "left"};
80 var mediaTextTemplate = {"font" : "bold 20pt Arial", "fillStyle" : "", "textAlign" : "left",
81 "shadowOffsetX" : 0, "shadowOffsetY" : 0, "shadowBlur" : 12, "shadowColor" : "red"};
85 console.log("Content discovery failed");
88 function setupSpeech()
90 console.log("MediaPlayer in setupSpeech");
92 speechObj = tizen.speech;
93 speechObj.vocalizeString(" ");
97 var speechEventListener = {
98 onaudiostart: function(){console.log("MediaPlayer: onaudiostart received");},
99 onsoundstart: function(){console.log("MediaPlayer: onsoundstart received");},
100 onspeechstart: function(){console.log("MediaPlayer: onspeechstart received");},
101 onspeechend: function(){console.log("MediaPlayer: onspeechend received");},
102 onsoundend: function(){console.log("MediaPlayer: onsoundend received");},
103 onaudioend: function(){console.log("MediaPlayer: onaudioend received");},
104 onresult: function(result){
106 console.log("MediaPlayer: onresult received");
108 for (var i = 0; i < result.length; i++)
110 console.log("MediaPlayer: forloop, command = " + result[i]);
111 var commandFound = false;
140 onnomatch: function(result){console.log("MediaPlayer: onnomatch received ");},
141 onerror: function(error){console.log("MediaPlayer: onerror received");},
142 onstart: function(){console.log("MediaPlayer: onstart received");},
143 onend: function(){console.log("MediaPlayer: onend received");}
146 speechObj.setCBListener(speechEventListener);
151 console.log("MediaPlayer setupSpeech FAILED + " + err.message);
156 function onAudioContentLoaded(newContent)
158 if (!newContent || newContent.length === 0)
160 console.log("MediaPlayer: some content failed to load, trying again for " + audioPlayer.type);
161 audioPlayer.clearContent();
162 setTimeout(function(){getMedia(onAudioContentLoaded, "AUDIO");}, 3000);
167 audioPlayer.updateContent(newContent, true);
168 audioPlayer.onContentLoaded();
172 function onVideoContentLoaded(newContent)
174 if (!newContent || newContent.length === 0)
176 console.log("MediaPlayer: some content failed to load, trying again for " + videoPlayer.type);
177 videoPlayer.clearContent();
178 setTimeout(function(){getMedia(onVideoContentLoaded, "VIDEO");}, 3000);
183 videoPlayer.updateContent(newContent, true);
184 videoPlayer.onContentLoaded();
188 function onImageContentLoaded(newContent)
190 if (!newContent || newContent.length === 0)
192 console.log("MediaPlayer: some content failed to load, trying again for " + imagePlayer.type);
193 imagePlayer.clearContent();
194 setTimeout(function(){getMedia(onImageContentLoaded, "IMAGE");}, 3000);
199 imagePlayer.updateContent(newContent, true);
200 imagePlayer.onContentLoaded();
204 function getMedia(callback, filterType)
206 console.log("MediaPlayer in getMedia");
207 var manager = tizen.content;
210 var filter = new tizen.AttributeFilter("type", "EXACTLY", filterType);
211 manager.find(callback, onError, null, filter);
214 console.log("MediaPlayer failed to receive media, tizen.content is unavailable");
217 function showMediaMenu()
219 console.log("MediaPlayer in showMediaMenu");
220 $(".navButton").show();
222 switch(currentPlayer.type)
225 $("#mediaName").show();
226 $("#trackTime").show();
227 $(".sortButton").show();
228 currentPlayer.show();
230 if (screenOrientation === "landscape" )
231 $("#audioMediaList").addClass("landscape");
233 $("#audioMediaList").removeClass("landscape");
235 $("#audioMediaList").show();
240 currentPlayer.show();
241 //setTimeout(function(){currentPlayer.show()}, 800); //The video element can't be faded, so wait a moment before showing
246 currentPlayer.show();
250 console.log("Invalid player type");
255 function showMediaList()
257 console.log("MediaPlayer in showMediaList");
259 if (currentMediaList.is(":visible"))
260 currentMediaList.hide();
263 currentMediaList.show();
267 function changeMenu(menuButtonId)
269 console.log("MediaPlayer in changeMenu");
270 var clickedButton = $("#" + menuButtonId);
271 var buttonWidth = clickedButton.width();
272 var buttonHeight = clickedButton.height();
273 var buttonBottom = clickedButton.css("bottom");
274 var buttonRight = clickedButton.css("right");
277 //Animate the clicked button slightly
278 clickedButton.animate({
279 bottom: screenOrientation === "portrait" ? "+=0" : "+=50",
280 right: screenOrientation === "portrait" ? "+=50" : "+=0",
284 //Reset the size once done
286 clickedButton.width(buttonWidth);
287 clickedButton.height(buttonHeight);
289 if (screenOrientation === "portrait")
290 clickedButton.css({"right": buttonRight});
292 clickedButton.css({"bottom": buttonBottom});
296 $(".mainButton").hide();
300 case ("mainMusicButton"):
301 speechObj.vocalizeString("Music player");
302 currentMenu = "audio";
303 currentPlayer = audioPlayer;
304 currentMediaList = $("#audioMediaList");
305 localStorage.prevMenu = "mainMusicButton";
307 if (audioPlayer.currentAudioContent && audioPlayer.currentAudioContent.contentURI)
309 localStorage.prevAudioTrack = audioPlayer.currentAudioContent.contentURI
310 localStorage.prevAudioTime = audioPlayer.playerControls.currentTime;
313 localStorage.prevVideo = undefined;
314 localStorage.prevVideoTime = undefined;
316 if (!audioMediaListLoaded)
317 audioPlayer.fillMediaList();
322 case ("mainVideoButton"):
323 speechObj.vocalizeString("Video player");
324 currentMenu = "video";
325 currentPlayer = videoPlayer;
326 currentMediaList = $("#videoMediaList");
327 localStorage.prevMenu = "mainVideoButton";
329 if (videoPlayer.currentVideoContent && videoPlayer.currentVideoContent.contentURI)
331 localStorage.prevVideo = videoPlayer.currentVideoContent.contentURI
332 localStorage.prevVideoTime = videoPlayer.playerControls.currentTime;
335 localStorage.prevAudioTime = undefined;
336 localStorage.prevAudioTrack = undefined;
338 if (!videoMediaListLoaded)
339 videoPlayer.fillMediaList();
344 case ("mainImageButton"):
345 speechObj.vocalizeString("Picture viewer");
346 currentMenu = "image";
347 currentPlayer = imagePlayer;
348 currentMediaList = $("#imageMediaList");
349 localStorage.prevMenu = "mainImageButton";
351 if (!imageMediaListLoaded)
352 imagePlayer.fillMediaList();
357 console.log("Error: No menu by that name");
362 function showMainMenu()
364 console.log("MediaPlayer in showMainMenu, clearing all localStorage...");
365 currentMenu = "main";
366 delete localStorage.prevMenu;
367 localStorage.prevAudioTime = undefined;
368 localStorage.prevAudioTrack = undefined;
369 localStorage.prevVideo = undefined;
370 localStorage.prevVideoTime = undefined;
371 localStorage.prevImage = undefined;
373 currentPlayer.pause();
375 //If the media list is showing, hide it. Remove the mediaListAudioList class if it exists so that it will resize properly
376 if (currentMediaList.is(":visible"))
377 currentMediaList.hide();
379 $(".navButton").hide();
380 $(".sortButton").hide();
381 $("#mediaName").hide();
382 $("#trackTime").hide();
384 $(".mainButton").css({"opacity": "100"});
385 $(".mainButton").show();
388 function sortByAlpha(contentToSort)
390 currentPlayer.sortByAlpha();
393 function sortByArtist(contentToSort)
395 currentPlayer.sortByArtist();
398 function sortByAlbum(contentToSort)
400 currentPlayer.sortByAlbum();
403 /**************************************** NAVIGATION FUNCTIONS *******************************************/
405 // This function is called once a file being loaded is ready to play
406 function playLoadedMedia()
408 audioPlayer.playLoadedMedia();
411 function videoLoaded()
413 videoPlayer.videoLoaded();
416 function playButtonClick()
418 console.log("MediaPlayer in playButtonClick");
419 if (!currentPlayer.playing())
420 currentPlayer.play();
422 currentPlayer.pause();
425 function pauseButtonClick()
427 console.log("MediaPlayer in pauseButtonClick");
428 if (currentPlayer.playing())
430 currentPlayer.pause();
434 function backButtonClick()
436 console.log("MediaPlayer in backButtonClick");
437 currentPlayer.previous();
441 function nextButtonClick()
443 console.log("MediaPlayer in nextButtonClick");
444 currentPlayer.next();
447 /**************************************** END NAVIGATION FUNCTIONS *******************************************/
449 function resizeMainMenu()
451 console.log("MediaPlayer in resizeMainMenu");
453 currentMediaList.hide();
454 screenWidth = window.innerWidth;
455 screenHeight = window.innerHeight;
456 screenOrientation = screenWidth < screenHeight ? "portrait" : "landscape";
457 iconWidth = screenOrientation === "portrait" ? screenHeight / 4 : screenWidth / 4;
460 $(".mainButton").width(iconWidth + "px");
461 $(".mainButton").height(iconWidth + "px");
463 var iconsTop = screenOrientation === "portrait" ? ((screenHeight - (iconWidth * 3)) / 2) - (padding * 3) : (screenHeight - iconWidth) / 2;
465 if (screenOrientation === "portrait")
466 $("#mainMenuButtons").css({"top": iconsTop + "px", "left" : (screenWidth / 2) - (iconWidth /2) - padding + "px", "width" : "50%"});
469 $("#mainMenuButtons").css({"top": iconsTop + "px", "left" : ((iconWidth / 2) - (padding * 3)) + "px", "width" : "100%"});
470 $("#sortButtons").addClass("landscape");
474 function resizePlayerPage()
476 console.log("MediaPlayer in resizePlayerPage");
478 screenWidth = window.innerWidth;
479 screenHeight = window.innerHeight;
482 var buttonWidth = screenOrientation === "portrait" ? screenHeight * 0.05 : screenWidth * 0.05;
484 $("#backButton").css({"width": buttonWidth + "px", "height": buttonWidth + "px", "top": padding + "px", "left": ((screenWidth / 2) - (buttonWidth *3)) + "px"});
485 $("#nextButton").css({"width": buttonWidth + "px", "height": buttonWidth + "px", "top": padding + "px", "left": ((screenWidth / 2) + (buttonWidth *2)) + "px"});
486 $("#returnButton").css({"width": buttonWidth + "px", "height": buttonWidth + "px", "top": padding + "px", "left": padding + "px"});
487 $("#listButton").css({"width": buttonWidth + "px", "height": buttonWidth + "px", "top": padding + "px", "left": (screenWidth - buttonWidth - padding * 2) + "px"});
488 $("#playButton").css({"width": buttonWidth * 1.15 + "px", "height": buttonWidth * 1.15 + "px", "top": padding * 0.3 + "px", "left": (screenWidth / 2) - (buttonWidth / 2) + "px"});
490 trackTimeCanvas.width = mediaNameCanvas.width = (screenWidth);
491 trackTimeCanvas.height = mediaNameCanvas.height = (screenHeight * 0.34) - (buttonWidth + (2 * padding));
492 trackTimeCanvas.style.top = mediaNameCanvas.style.top = (buttonWidth + (2 * padding) ) + "px";
493 trackTimeCanvas.style.left = mediaNameCanvas.style.left = "0px";
495 var sortButtonTop = (buttonWidth + (2 * padding) ) + mediaNameCanvas.height - (buttonWidth * 1.3);
496 var sortButtonWidth = buttonWidth * 2.5;
497 var buttonSpacing = screenWidth / 5;
499 mediaListItemW = $("#videoMediaList").width() * 0.92;
500 mediaListItemH = $("#videoMediaList").height() / 10;
505 console.log("MediaPlayer in resizeAll");
511 * swipe - Handles swipe events. Currently it just acts as another way to hit the next / back buttons, but
512 * it could be expanded to other things in the future.
515 function swipe(direction, object)
517 console.log("MediaPlayer in swipe");
521 if (direction === "right")
523 else if (direction === "left")
532 function toggleNightMode(nightModeValue)
534 if (nightMode !== nightModeValue)
536 Array.prototype.forEach.call (document.querySelectorAll ('*'), function (el) {el.classList.toggle('night');});
537 nightMode = nightModeValue;
543 console.log("MediaPlayer in init");
545 musicIcon.src = "images/musicIcon.png";
546 vidIcon.src = "images/videoIcon.png";
547 imgIcon.src = "images/imageIcon.png";
548 mediaNameCanvas = document.getElementById("mediaName");
549 mediaNameCTX = mediaNameCanvas.getContext("2d");
550 trackTimeCanvas = document.getElementById("trackTime");
551 trackTimeCTX = trackTimeCanvas.getContext("2d");
552 playBarHeight = mediaNameCanvas.height;
553 boxWidth = playBarHeight * 0.75;
554 textStartX = boxWidth + 50;
556 var vehicle = tizen.vehicle;
559 /* Subscribe to AMB NightMode signal, and switch colors
560 * upon receipt of the signal
563 if (vehicle && vehicle !== undefined)
565 var getVal = vehicle.get("NightMode");
567 //Check that NightMode returned a value before trying to hook up to it
570 toggleNightMode(getVal.nightMode);
573 /* Subscribe to AMB NightMode signal, and switch colors
574 * upon receipt of the signal
577 vehicle.subscribe("NightMode",function(value) {
578 console.log("MediaPlayer: Day / Night mode changed to " + value.nightMode);
579 toggleNightMode(value.nightMode);
583 /* Subscribe to AMB DrivingMode signal, and pause video
584 * upon receipt of the signal
588 vehicle.subscribe("DrivingMode",function(value) {
589 console.log("MediaPlayer: DrivingMode changed to " + value.drivingMode);
591 if (value.drivingMode > 0 && currentPlayer.type === "video" && currentPlayer.playing())
593 console.log("MediaPlayer: pausing video due to vehicle motion");
594 currentPlayer.pause();
595 waitingToResumeVideo = true;
597 else if (value.drivingMode === 0 && currentPlayer.type === "video" && waitingToResumeVideo)
599 console.log("MediaPlayer: vehicle has stopped, resuming video");
600 currentPlayer.play();
601 waitingToResumeVideo = false;
606 //Setup voice control
610 console.log("MediaPlayer: Speech Recognition not running, voice control will be unavailable");
612 vocalizeString: function(item) { console.log(item); }
616 audioPlayer = new MediaPlayer("audio");
617 videoPlayer = new MediaPlayer("video");
618 imagePlayer = new MediaPlayer("image");
619 currentPlayer = audioPlayer;
621 //Resize all items and search for local media
624 if (localStorage.prevMenu && localStorage.prevMenu !== undefined && localStorage.prevMenu !== "MAIN")
625 changeMenu(localStorage.prevMenu)
629 getMedia(onAudioContentLoaded, "AUDIO");
630 getMedia(onVideoContentLoaded, "VIDEO");
631 getMedia(onImageContentLoaded, "IMAGE");
633 //Check if DLNA plugin is installed. If so, scan for media.
634 if (tizen.mediaserver)
636 //Currently no success signal, so continue trying until a server is found. Once that
637 //happens, clear the stopServerSearch interval
639 stopServerSearch = setInterval(function(){
640 console.log("MediaPlayer searching for remote media...");
641 if (remoteMediaSearchAttempts < 5)
642 tizen.mediaserver.scanNetwork(foundMediaServer);
644 clearInterval(stopServerSearch);
645 remoteMediaSearchAttempts++;
649 console.log("MediaPlayer: No DLNA server running, using local media only...");
651 //Prevent highlighting
652 window.ondragstart = function() { return false; }
654 $(window).bind('resize', resizeAll);
656 //Simple swipe detection
657 $("#mediaName").mousedown(function(e){mouseDownEvent = e;});
658 $("#mediaName").mouseup(function(e){
659 if (Math.abs(mouseDownEvent.clientY - e.clientY) < 100)
661 if (Math.abs(mouseDownEvent.clientX - e.clientX) > 100)
663 if (mouseDownEvent.clientX > e.clientX)
664 swipe("left", "mediaName");
666 swipe("right", "mediaName");
671 document.getElementById('videoPlayer').addEventListener("playing", function() {
672 $("#playButton").toggleClass('playing', true);
673 $("#navigationButtons").hide();
675 document.getElementById('videoPlayer').addEventListener("pause", function() {
676 $("#playButton").toggleClass('playing', false);
677 $("#navigationButtons").show();
679 document.getElementById('videoPlayer').addEventListener("ended", function() {
680 $("#playButton").toggleClass('playing', false);
681 $("#navigationButtons").show();
683 document.getElementById('audioPlayer').addEventListener("playing", function() {
684 $("#playButton").toggleClass('playing', true);
686 document.getElementById('audioPlayer').addEventListener("pause", function() {
687 $("#playButton").toggleClass('playing', false);
689 document.getElementById('audioPlayer').addEventListener("ended", function() {
690 $("#playButton").toggleClass('playing', false);
692 document.getElementById('imagePlayer').addEventListener("click", function() {
693 if (!imagePlayer.playing)
700 // pause the slideshow and fade in the controls
702 $("#navigationButtons").show();
707 $(document).ready(function () {