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 15pt 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 15pt 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;
204 var filter = new tizen.AttributeFilter("type", "EXACTLY", filterType);
205 manager.find(callback, onError, null, filter);
208 function showMediaMenu()
210 console.log("MediaPlayer in showMediaMenu");
211 $(".navButton").show();
213 switch(currentPlayer.type)
216 $("#mediaName").show();
217 $("#trackTime").show();
218 $(".sortButton").show();
219 currentPlayer.show();
221 if (screenOrientation === "landscape" )
222 $("#audioMediaList").addClass("landscape");
224 $("#audioMediaList").removeClass("landscape");
226 $("#audioMediaList").show();
231 currentPlayer.show();
232 //setTimeout(function(){currentPlayer.show()}, 800); //The video element can't be faded, so wait a moment before showing
237 currentPlayer.show();
241 console.log("Invalid player type");
246 function showMediaList()
248 console.log("MediaPlayer in showMediaList");
250 if (currentMediaList.is(":visible"))
251 currentMediaList.hide();
254 currentMediaList.show();
258 function changeMenu(menuButtonId)
260 console.log("MediaPlayer in changeMenu");
261 var clickedButton = $("#" + menuButtonId);
262 var buttonWidth = clickedButton.width();
263 var buttonHeight = clickedButton.height();
264 var buttonBottom = clickedButton.css("bottom");
265 var buttonRight = clickedButton.css("right");
268 //Animate the clicked button slightly
269 clickedButton.animate({
270 bottom: screenOrientation === "portrait" ? "+=0" : "+=50",
271 right: screenOrientation === "portrait" ? "+=50" : "+=0",
275 //Reset the size once done
277 clickedButton.width(buttonWidth);
278 clickedButton.height(buttonHeight);
280 if (screenOrientation === "portrait")
281 clickedButton.css({"right": buttonRight});
283 clickedButton.css({"bottom": buttonBottom});
287 $(".mainButton").hide();
291 case ("mainMusicButton"):
292 speechObj.vocalizeString("Music player");
293 currentMenu = "audio";
294 currentPlayer = audioPlayer;
295 currentMediaList = $("#audioMediaList");
296 localStorage.prevMenu = "mainMusicButton";
298 if (audioPlayer.currentAudioContent && audioPlayer.currentAudioContent.contentURI)
300 localStorage.prevAudioTrack = audioPlayer.currentAudioContent.contentURI
301 localStorage.prevAudioTime = audioPlayer.playerControls.currentTime;
304 localStorage.prevVideo = undefined;
305 localStorage.prevVideoTime = undefined;
307 if (!audioMediaListLoaded)
308 audioPlayer.fillMediaList();
313 case ("mainVideoButton"):
314 speechObj.vocalizeString("Video player");
315 currentMenu = "video";
316 currentPlayer = videoPlayer;
317 currentMediaList = $("#videoMediaList");
318 localStorage.prevMenu = "mainVideoButton";
320 if (videoPlayer.currentVideoContent && videoPlayer.currentVideoContent.contentURI)
322 localStorage.prevVideo = videoPlayer.currentVideoContent.contentURI
323 localStorage.prevVideoTime = videoPlayer.playerControls.currentTime;
326 localStorage.prevAudioTime = undefined;
327 localStorage.prevAudioTrack = undefined;
329 if (!videoMediaListLoaded)
330 videoPlayer.fillMediaList();
335 case ("mainImageButton"):
336 speechObj.vocalizeString("Picture viewer");
337 currentMenu = "image";
338 currentPlayer = imagePlayer;
339 currentMediaList = $("#imageMediaList");
340 localStorage.prevMenu = "mainImageButton";
342 if (!imageMediaListLoaded)
343 imagePlayer.fillMediaList();
348 console.log("Error: No menu by that name");
353 function showMainMenu()
355 console.log("MediaPlayer in showMainMenu, clearing all localStorage...");
356 currentMenu = "main";
357 localStorage.prevMenu = "MAIN";
358 localStorage.prevAudioTime = undefined;
359 localStorage.prevAudioTrack = undefined;
360 localStorage.prevVideo = undefined;
361 localStorage.prevVideoTime = undefined;
362 localStorage.prevImage = undefined;
364 currentPlayer.pause();
366 //If the media list is showing, hide it. Remove the mediaListAudioList class if it exists so that it will resize properly
367 if (currentMediaList.is(":visible"))
368 currentMediaList.hide();
370 $(".navButton").hide();
371 $(".sortButton").hide();
372 $("#mediaName").hide();
373 $("#trackTime").hide();
375 $(".mainButton").css({"opacity": "100"});
376 $(".mainButton").show();
379 function sortByAlpha(contentToSort)
381 currentPlayer.sortByAlpha();
384 function sortByArtist(contentToSort)
386 currentPlayer.sortByArtist();
389 function sortByAlbum(contentToSort)
391 currentPlayer.sortByAlbum();
394 /**************************************** NAVIGATION FUNCTIONS *******************************************/
396 // This function is called once a file being loaded is ready to play
397 function playLoadedMedia()
399 audioPlayer.playLoadedMedia();
402 function videoLoaded()
404 videoPlayer.videoLoaded();
407 function playButtonClick()
409 console.log("MediaPlayer in playButtonClick");
410 if (!currentPlayer.playing())
411 currentPlayer.play();
413 currentPlayer.pause();
416 function pauseButtonClick()
418 console.log("MediaPlayer in pauseButtonClick");
419 if (currentPlayer.playing())
421 currentPlayer.pause();
425 function backButtonClick()
427 console.log("MediaPlayer in backButtonClick");
428 currentPlayer.previous();
432 function nextButtonClick()
434 console.log("MediaPlayer in nextButtonClick");
435 currentPlayer.next();
438 /**************************************** END NAVIGATION FUNCTIONS *******************************************/
440 function resizeMainMenu()
442 console.log("MediaPlayer in resizeMainMenu");
444 currentMediaList.hide();
445 screenWidth = window.innerWidth;
446 screenHeight = window.innerHeight;
447 screenOrientation = screenWidth < screenHeight ? "portrait" : "landscape";
448 iconWidth = screenOrientation === "portrait" ? screenHeight / 4 : screenWidth / 4;
451 $(".mainButton").width(iconWidth + "px");
452 $(".mainButton").height(iconWidth + "px");
454 var iconsTop = screenOrientation === "portrait" ? ((screenHeight - (iconWidth * 3)) / 2) - (padding * 3) : (screenHeight - iconWidth) / 2;
456 if (screenOrientation === "portrait")
457 $("#mainMenuButtons").css({"top": iconsTop + "px", "left" : (screenWidth / 2) - (iconWidth /2) - padding + "px", "width" : "50%"});
460 $("#mainMenuButtons").css({"top": iconsTop + "px", "left" : ((iconWidth / 2) - (padding * 3)) + "px", "width" : "100%"});
461 $("#sortButtons").addClass("landscape");
465 function resizePlayerPage()
467 console.log("MediaPlayer in resizePlayerPage");
469 screenWidth = window.innerWidth;
470 screenHeight = window.innerHeight;
473 var buttonWidth = screenOrientation === "portrait" ? screenHeight * 0.05 : screenWidth * 0.05;
475 $("#backButton").css({"width": buttonWidth + "px", "height": buttonWidth + "px", "top": padding + "px", "left": ((screenWidth / 2) - (buttonWidth *3)) + "px"});
476 $("#nextButton").css({"width": buttonWidth + "px", "height": buttonWidth + "px", "top": padding + "px", "left": ((screenWidth / 2) + (buttonWidth *2)) + "px"});
477 $("#returnButton").css({"width": buttonWidth + "px", "height": buttonWidth + "px", "top": padding + "px", "left": padding + "px"});
478 $("#listButton").css({"width": buttonWidth + "px", "height": buttonWidth + "px", "top": padding + "px", "left": (screenWidth - buttonWidth - padding * 2) + "px"});
479 $("#playButton").css({"width": buttonWidth * 1.15 + "px", "height": buttonWidth * 1.15 + "px", "top": padding * 0.3 + "px", "left": (screenWidth / 2) - (buttonWidth / 2) + "px"});
481 trackTimeCanvas.width = mediaNameCanvas.width = (screenWidth);
482 trackTimeCanvas.height = mediaNameCanvas.height = (screenHeight * 0.34) - (buttonWidth + (2 * padding));
483 trackTimeCanvas.style.top = mediaNameCanvas.style.top = (buttonWidth + (2 * padding) ) + "px";
484 trackTimeCanvas.style.left = mediaNameCanvas.style.left = "0px";
486 var sortButtonTop = (buttonWidth + (2 * padding) ) + mediaNameCanvas.height - (buttonWidth * 1.3);
487 var sortButtonWidth = buttonWidth * 2.5;
488 var buttonSpacing = screenWidth / 5;
490 mediaListItemW = $("#videoMediaList").width() * 0.92;
491 mediaListItemH = $("#videoMediaList").height() / 10;
496 console.log("MediaPlayer in resizeAll");
502 * swipe - Handles swipe events. Currently it just acts as another way to hit the next / back buttons, but
503 * it could be expanded to other things in the future.
506 function swipe(direction, object)
508 console.log("MediaPlayer in swipe");
512 if (direction === "right")
514 else if (direction === "left")
523 function toggleNightMode(nightModeValue)
525 if (nightMode !== nightModeValue)
527 Array.prototype.forEach.call (document.querySelectorAll ('*'), function (el) {el.classList.toggle('night');});
528 nightMode = nightModeValue;
534 console.log("MediaPlayer in init");
536 musicIcon.src = "images/musicIcon.png";
537 vidIcon.src = "images/videoIcon.png";
538 imgIcon.src = "images/imageIcon.png";
539 mediaNameCanvas = document.getElementById("mediaName");
540 mediaNameCTX = mediaNameCanvas.getContext("2d");
541 trackTimeCanvas = document.getElementById("trackTime");
542 trackTimeCTX = trackTimeCanvas.getContext("2d");
543 playBarHeight = mediaNameCanvas.height;
544 boxWidth = playBarHeight * 0.75;
545 textStartX = boxWidth + 50;
547 var vehicle = tizen.vehicle;
550 /* Subscribe to AMB NightMode signal, and switch colors
551 * upon receipt of the signal
554 if (vehicle && vehicle !== undefined)
556 var getVal = vehicle.get("NightMode");
558 //Check that NightMode returned a value before trying to hook up to it
561 toggleNightMode(getVal.nightMode);
564 /* Subscribe to AMB NightMode signal, and switch colors
565 * upon receipt of the signal
568 vehicle.subscribe("NightMode",function(value) {
569 console.log("MediaPlayer: Day / Night mode changed to " + value.nightMode);
570 toggleNightMode(value.nightMode);
574 /* Subscribe to AMB DrivingMode signal, and pause video
575 * upon receipt of the signal
579 vehicle.subscribe("DrivingMode",function(value) {
580 console.log("MediaPlayer: DrivingMode changed to " + value.drivingMode);
582 if (value.drivingMode > 0 && currentPlayer.type === "video" && currentPlayer.playing())
584 console.log("MediaPlayer: pausing video due to vehicle motion");
585 currentPlayer.pause();
586 waitingToResumeVideo = true;
588 else if (value.drivingMode === 0 && currentPlayer.type === "video" && waitingToResumeVideo)
590 console.log("MediaPlayer: vehicle has stopped, resuming video");
591 currentPlayer.play();
592 waitingToResumeVideo = false;
597 //Setup voice control
601 console.log("MediaPlayer: Speech Recognition not running, voice control will be unavailable");
603 audioPlayer = new MediaPlayer("audio");
604 videoPlayer = new MediaPlayer("video");
605 imagePlayer = new MediaPlayer("image");
606 currentPlayer = audioPlayer;
608 //Resize all items and search for local media
611 if (localStorage.prevMenu && localStorage.prevMenu !== "MAIN")
612 changeMenu(localStorage.prevMenu)
616 getMedia(onAudioContentLoaded, "AUDIO");
617 getMedia(onVideoContentLoaded, "VIDEO");
618 getMedia(onImageContentLoaded, "IMAGE");
620 //Check if DLNA plugin is installed. If so, scan for media.
621 if (tizen.mediaserver)
623 //Currently no success signal, so continue trying until a server is found. Once that
624 //happens, clear the stopServerSearch interval
626 stopServerSearch = setInterval(function(){console.log("MediaPlayer searching for remote media..."); tizen.mediaserver.scanNetwork(foundMediaServer);}, 5000);
629 console.log("MediaPlayer: No DLNA server running, using local media only...");
631 //Prevent highlighting
632 window.ondragstart = function() { return false; }
634 $(window).bind('resize', resizeAll);
636 //Simple swipe detection
637 $("#mediaName").mousedown(function(e){mouseDownEvent = e;});
638 $("#mediaName").mouseup(function(e){
639 if (Math.abs(mouseDownEvent.clientY - e.clientY) < 100)
641 if (Math.abs(mouseDownEvent.clientX - e.clientX) > 100)
643 if (mouseDownEvent.clientX > e.clientX)
644 swipe("left", "mediaName");
646 swipe("right", "mediaName");
651 document.getElementById('videoPlayer').addEventListener("playing", function() {
652 $("#playButton").toggleClass('playing', true);
653 $("#navigationButtons").hide();
655 document.getElementById('videoPlayer').addEventListener("pause", function() {
656 $("#playButton").toggleClass('playing', false);
657 $("#navigationButtons").show();
659 document.getElementById('videoPlayer').addEventListener("ended", function() {
660 $("#playButton").toggleClass('playing', false);
661 $("#navigationButtons").show();
663 document.getElementById('audioPlayer').addEventListener("playing", function() {
664 $("#playButton").toggleClass('playing', true);
666 document.getElementById('audioPlayer').addEventListener("pause", function() {
667 $("#playButton").toggleClass('playing', false);
669 document.getElementById('audioPlayer').addEventListener("ended", function() {
670 $("#playButton").toggleClass('playing', false);
672 document.getElementById('imagePlayer').addEventListener("click", function() {
673 if (!imagePlayer.playing)
680 // pause the slideshow and fade in the controls
682 $("#navigationButtons").show();
687 $(document).ready(function () {