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;
37 var nightMode = false;
38 var waitingToResumeVideo = false; //Media has been paused by exterior forces. If set to true, resume previous media when given the signal.
41 var mainMenuTitleTemplateLandscape = {"font" : "oblique bolder 30pt arial", "lineWidth" : 9.5, "fillStyle" : "black", "strokeStyle" : "white", "textAlign" : "left",
42 "largeShadow" : 8, "shadowOffsetX" : 0, "shadowOffsetY" : 0, "shadowBlur" : 45, "shadowColor" : "rgba(255, 187, 0, 0.4)"};
44 var mainMenuTitleTemplate = {"font" : "oblique bolder 40pt 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 mainTrackTemplateLandscape = {"font" : "bold 20pt Arial", "lineWidth" : 7.5, "fillStyle" : "black", "strokeStyle" : "white", "textAlign" : "left",
48 "largeShadow" : 8, "shadowOffsetX" : 0, "shadowOffsetY" : 0, "shadowBlur" : 45, "shadowColor" : "rgba(255, 187, 0, 0.5))"};
50 var mainTrackTemplate = {"font" : "bold 30pt 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 mediaTextTemplate2 = {"font" : "bold 20pt Arial", "lineWidth" : 10.0, "fillStyle" : "white", "strokeStyle" : "rgba(0, 0, 0, 1.0)", "textAlign" : "left",
54 "shadowOffsetX" : 0, "shadowOffsetY" : 0, "shadowBlur" : 0, "shadowColor" : "rgba(0, 0, 0, 1.0)"};
56 var mediaTextTemplate3 = {"font" : "bold 20pt Arial", "lineWidth" : 3.0, "fillStyle" : "white", "strokeStyle" : "rgba(100, 0, 0, 1.0)", "textAlign" : "left"};
58 var trackTextTemplate = {"font" : "bold 16pt Arial", "lineWidth" : 3.0, "fillStyle" : "white", "strokeStyle" : "black", "textAlign" : "left"};
60 var mediaTextTemplate2Landscape = {"font" : "bold 15pt Arial", "lineWidth" : 10.0, "fillStyle" : "white", "strokeStyle" : "rgba(0, 0, 0, 1.0)", "textAlign" : "left",
61 "shadowOffsetX" : 0, "shadowOffsetY" : 0, "shadowBlur" : 0, "shadowColor" : "rgba(0, 0, 0, 1.0)"};
63 var mediaTextTemplate3Landscape = {"font" : "bold 15pt Arial", "lineWidth" : 3.0, "fillStyle" : "white", "strokeStyle" : "rgba(100, 0, 0, 1.0)", "textAlign" : "left"};
65 var trackTextTemplateLandscape = {"font" : "bold 11pt Arial", "lineWidth" : 3.0, "fillStyle" : "white", "strokeStyle" : "black", "textAlign" : "left"};
68 var mediaTextTemplate = {"font" : "bold 20pt Arial", "fillStyle" : "", "textAlign" : "left",
69 "shadowOffsetX" : 0, "shadowOffsetY" : 0, "shadowBlur" : 12, "shadowColor" : "red"};
73 console.log("Content discovery failed");
76 function setupSpeech()
78 console.log("MediaPlayer in setupSpeech");
80 speechObj = tizen.speech;
81 speechObj.vocalizeString(" ");
85 var speechEventListener = {
86 onaudiostart: function(){console.log("MediaPlayer: onaudiostart received");},
87 onsoundstart: function(){console.log("MediaPlayer: onsoundstart received");},
88 onspeechstart: function(){console.log("MediaPlayer: onspeechstart received");},
89 onspeechend: function(){console.log("MediaPlayer: onspeechend received");},
90 onsoundend: function(){console.log("MediaPlayer: onsoundend received");},
91 onaudioend: function(){console.log("MediaPlayer: onaudioend received");},
92 onresult: function(result){
94 console.log("MediaPlayer: onresult received");
96 for (var i = 0; i < result.length; i++)
98 console.log("MediaPlayer: forloop, command = " + result[i]);
99 var commandFound = false;
128 onnomatch: function(result){console.log("MediaPlayer: onnomatch received ");},
129 onerror: function(error){console.log("MediaPlayer: onerror received");},
130 onstart: function(){console.log("MediaPlayer: onstart received");},
131 onend: function(){console.log("MediaPlayer: onend received");}
134 speechObj.setCBListener(speechEventListener);
139 console.log("MediaPlayer setupSpeech FAILED + " + err.message);
144 function onAudioContentLoaded(newContent)
146 if (!newContent || newContent.length === 0)
148 console.log("MediaPlayer: some content failed to load, trying again for " + audioPlayer.type);
149 audioPlayer.clearContent();
150 setTimeout(function(){getMedia(onAudioContentLoaded, "AUDIO");}, 3000);
155 audioPlayer.updateContent(newContent, true);
156 audioPlayer.onContentLoaded();
160 function onVideoContentLoaded(newContent)
162 if (!newContent || newContent.length === 0)
164 console.log("MediaPlayer: some content failed to load, trying again for " + videoPlayer.type);
165 videoPlayer.clearContent();
166 setTimeout(function(){getMedia(onVideoContentLoaded, "VIDEO");}, 3000);
171 videoPlayer.updateContent(newContent, true);
172 videoPlayer.onContentLoaded();
176 function onImageContentLoaded(newContent)
178 if (!newContent || newContent.length === 0)
180 console.log("MediaPlayer: some content failed to load, trying again for " + imagePlayer.type);
181 imagePlayer.clearContent();
182 setTimeout(function(){getMedia(onImageContentLoaded, "IMAGE");}, 3000);
187 imagePlayer.updateContent(newContent, true);
188 imagePlayer.onContentLoaded();
192 function getMedia(callback, filterType)
194 console.log("MediaPlayer in getMedia");
195 var manager = tizen.content;
196 var filter = new tizen.AttributeFilter("type", "EXACTLY", filterType);
197 manager.find(callback, onError, null, filter);
200 function showMediaMenu()
202 console.log("MediaPlayer in showMediaMenu");
203 $(".navButton").show();
205 switch(currentPlayer.type)
208 $("#mediaName").show();
209 $(".sortButton").show();
210 currentPlayer.show();
212 if (screenOrientation === "landscape" )
213 $("#audioMediaList").addClass("landscape");
215 $("#audioMediaList").removeClass("landscape");
217 $("#audioMediaList").show();
222 currentPlayer.show();
223 //setTimeout(function(){currentPlayer.show()}, 800); //The video element can't be faded, so wait a moment before showing
228 currentPlayer.show();
232 console.log("Invalid player type");
237 function showMediaList()
239 console.log("MediaPlayer in showMediaList");
241 if (currentMediaList.is(":visible"))
242 currentMediaList.hide();
245 currentMediaList.show();
249 function changeMenu(menuButtonId)
251 console.log("MediaPlayer in changeMenu");
252 var clickedButton = $("#" + menuButtonId);
253 var buttonWidth = clickedButton.width();
254 var buttonHeight = clickedButton.height();
255 var buttonBottom = clickedButton.css("bottom");
256 var buttonRight = clickedButton.css("right");
259 //Animate the clicked button slightly
260 clickedButton.animate({
261 bottom: screenOrientation === "portrait" ? "+=0" : "+=50",
262 right: screenOrientation === "portrait" ? "+=50" : "+=0",
266 //Reset the size once done
268 clickedButton.width(buttonWidth);
269 clickedButton.height(buttonHeight);
271 if (screenOrientation === "portrait")
272 clickedButton.css({"right": buttonRight});
274 clickedButton.css({"bottom": buttonBottom});
278 $(".mainButton").hide();
282 case ("mainMusicButton"):
283 speechObj.vocalizeString("Music player");
284 currentMenu = "audio";
285 currentPlayer = audioPlayer;
286 currentMediaList = $("#audioMediaList");
287 localStorage.prevMenu = "mainMusicButton";
289 if (audioPlayer.currentAudioContent)
291 localStorage.prevAudioTrack = audioPlayer.currentAudioContent.contentURI
292 localStorage.prevAudioTime = audioPlayer.playerControls.currentTime;
295 localStorage.prevVideo = undefined;
296 localStorage.prevVideoTime = undefined;
298 if (!audioMediaListLoaded)
299 audioPlayer.fillMediaList();
304 case ("mainVideoButton"):
305 speechObj.vocalizeString("Video player");
306 currentMenu = "video";
307 currentPlayer = videoPlayer;
308 currentMediaList = $("#videoMediaList");
309 localStorage.prevMenu = "mainVideoButton";
310 localStorage.prevAudioTime = undefined;
311 localStorage.prevAudioTrack = undefined;
313 if (!videoMediaListLoaded)
314 videoPlayer.fillMediaList();
319 case ("mainImageButton"):
320 speechObj.vocalizeString("Picture viewer");
321 currentMenu = "image";
322 currentPlayer = imagePlayer;
323 currentMediaList = $("#imageMediaList");
324 localStorage.prevMenu = "mainImageButton";
326 if (!imageMediaListLoaded)
327 imagePlayer.fillMediaList();
332 console.log("Error: No menu by that name");
337 function showMainMenu()
339 console.log("MediaPlayer in showMainMenu");
340 currentMenu = "main";
341 localStorage.prevMenu = "MAIN";
342 localStorage.prevAudioTime = undefined;
343 localStorage.prevAudioTrack = undefined;
344 localStorage.prevVideo = undefined;
345 localStorage.prevVideoTime = undefined;
346 currentPlayer.pause();
348 //If the media list is showing, hide it. Remove the mediaListAudioList class if it exists so that it will resize properly
349 if (currentMediaList.is(":visible"))
350 currentMediaList.hide();
352 $(".navButton").hide();
353 $(".sortButton").hide();
354 $("#mediaName").hide();
356 $(".mainButton").css({"opacity": "100"});
357 $(".mainButton").show();
360 function sortByAlpha(contentToSort)
362 currentPlayer.sortByAlpha();
365 function sortByArtist(contentToSort)
367 currentPlayer.sortByArtist();
370 function sortByAlbum(contentToSort)
372 currentPlayer.sortByAlbum();
375 /**************************************** NAVIGATION FUNCTIONS *******************************************/
377 // This function is called once a file being loaded is ready to play
378 function playLoadedMedia()
380 audioPlayer.playLoadedMedia();
383 function videoLoaded()
385 videoPlayer.videoLoaded();
388 function playButtonClick()
390 console.log("MediaPlayer in playButtonClick");
391 if (!currentPlayer.playing())
392 currentPlayer.play();
394 currentPlayer.pause();
397 function pauseButtonClick()
399 console.log("MediaPlayer in pauseButtonClick");
400 if (currentPlayer.playing())
402 currentPlayer.pause();
406 function backButtonClick()
408 console.log("MediaPlayer in backButtonClick");
409 currentPlayer.previous();
413 function nextButtonClick()
415 console.log("MediaPlayer in nextButtonClick");
416 currentPlayer.next();
419 /**************************************** END NAVIGATION FUNCTIONS *******************************************/
421 function resizeMainMenu()
423 console.log("MediaPlayer in resizeMainMenu");
425 currentMediaList.hide();
426 screenWidth = window.innerWidth;
427 screenHeight = window.innerHeight;
428 screenOrientation = screenWidth < screenHeight ? "portrait" : "landscape";
429 iconWidth = screenOrientation === "portrait" ? screenHeight / 4 : screenWidth / 4;
432 $(".mainButton").width(iconWidth + "px");
433 $(".mainButton").height(iconWidth + "px");
435 var iconsTop = screenOrientation === "portrait" ? ((screenHeight - (iconWidth * 3)) / 2) - (padding * 3) : (screenHeight - iconWidth) / 2;
437 if (screenOrientation === "portrait")
438 $("#mainMenuButtons").css({"top": iconsTop + "px", "left" : (screenWidth / 2) - (iconWidth /2) - padding + "px", "width" : "50%"});
441 $("#mainMenuButtons").css({"top": iconsTop + "px", "left" : ((iconWidth / 2) - (padding * 3)) + "px", "width" : "100%"});
442 $("#sortButtons").addClass("landscape");
446 function resizePlayerPage()
448 console.log("MediaPlayer in resizePlayerPage");
450 screenWidth = window.innerWidth;
451 screenHeight = window.innerHeight;
454 var buttonWidth = screenOrientation === "portrait" ? screenHeight * 0.05 : screenWidth * 0.05;
456 $("#backButton").css({"width": buttonWidth + "px", "height": buttonWidth + "px", "top": padding + "px", "left": ((screenWidth / 2) - (buttonWidth *3)) + "px"});
457 $("#nextButton").css({"width": buttonWidth + "px", "height": buttonWidth + "px", "top": padding + "px", "left": ((screenWidth / 2) + (buttonWidth *2)) + "px"});
458 $("#returnButton").css({"width": buttonWidth + "px", "height": buttonWidth + "px", "top": padding + "px", "left": padding + "px"});
459 $("#listButton").css({"width": buttonWidth + "px", "height": buttonWidth + "px", "top": padding + "px", "left": (screenWidth - buttonWidth - padding * 2) + "px"});
460 $("#playButton").css({"width": buttonWidth * 1.15 + "px", "height": buttonWidth * 1.15 + "px", "top": padding * 0.3 + "px", "left": (screenWidth / 2) - (buttonWidth / 2) + "px"});
462 mediaNameCanvas.width = (screenWidth);
463 mediaNameCanvas.height = (screenHeight * 0.34) - (buttonWidth + (2 * padding));
464 mediaNameCanvas.style.top = (buttonWidth + (2 * padding) ) + "px";
465 mediaNameCanvas.style.left = "0px";
467 var sortButtonTop = (buttonWidth + (2 * padding) ) + mediaNameCanvas.height - (buttonWidth * 1.3);
468 var sortButtonWidth = buttonWidth * 2.5;
469 var buttonSpacing = screenWidth / 5;
471 mediaListItemW = $("#videoMediaList").width() * 0.92;
472 mediaListItemH = $("#videoMediaList").height() / 10;
477 console.log("MediaPlayer in resizeAll");
483 * swipe - Handles swipe events. Currently it just acts as another way to hit the next / back buttons, but
484 * it could be expanded to other things in the future.
487 function swipe(direction, object)
489 console.log("MediaPlayer in swipe");
493 if (direction === "right")
495 else if (direction === "left")
504 function toggleNightMode(nightModeValue)
506 if (nightMode !== nightModeValue)
508 Array.prototype.forEach.call (document.querySelectorAll ('*'), function (el) {el.classList.toggle('night');});
509 nightMode = nightModeValue;
515 console.log("MediaPlayer in init");
517 musicIcon.src = "images/musicIcon.png";
518 vidIcon.src = "images/videoIcon.png";
519 imgIcon.src = "images/imageIcon.png";
520 mediaNameCanvas = document.getElementById("mediaName");
521 mediaNameCTX = mediaNameCanvas.getContext("2d");
523 var vehicle = tizen.vehicle;
526 /* Subscribe to AMB NightMode signal, and switch colors
527 * upon receipt of the signal
530 if (vehicle && vehicle !== undefined)
532 var getVal = vehicle.get("NightMode");
534 //Check that NightMode returned a value before trying to hook up to it
537 toggleNightMode(getVal.nightMode);
540 /* Subscribe to AMB NightMode signal, and switch colors
541 * upon receipt of the signal
544 vehicle.subscribe("NightMode",function(value) {
545 console.log("MediaPlayer: Day / Night mode changed to " + value.nightMode);
546 toggleNightMode(value.nightMode);
550 /* Subscribe to AMB DrivingMode signal, and pause video
551 * upon receipt of the signal
555 vehicle.subscribe("DrivingMode",function(value) {
556 console.log("MediaPlayer: DrivingMode changed to " + value.drivingMode);
558 if (value.drivingMode > 0 && currentPlayer.type === "video" && currentPlayer.playing())
560 console.log("MediaPlayer: pausing video due to vehicle motion");
561 currentPlayer.pause();
562 waitingToResumeVideo = true;
564 else if (value.drivingMode === 0 && currentPlayer.type === "video" && waitingToResumeVideo)
566 console.log("MediaPlayer: vehicle has stopped, resuming video");
567 currentPlayer.play();
568 waitingToResumeVideo = false;
573 //Setup voice control
577 console.log("MediaPlayer: Speech Recognition not running, voice control will be unavailable");
579 audioPlayer = new MediaPlayer("audio");
580 videoPlayer = new MediaPlayer("video");
581 imagePlayer = new MediaPlayer("image");
582 currentPlayer = audioPlayer;
584 //Resize all items and search for local media
587 if (localStorage.prevMenu && localStorage.prevMenu !== "MAIN")
588 changeMenu(localStorage.prevMenu)
592 getMedia(onAudioContentLoaded, "AUDIO");
593 getMedia(onVideoContentLoaded, "VIDEO");
594 getMedia(onImageContentLoaded, "IMAGE");
596 //Check if DLNA plugin is installed. If so, scan for media.
597 if (tizen.mediaserver)
599 //Currently no success signal, so continue trying until a server is found. Once that
600 //happens, clear the stopServerSearch interval
602 stopServerSearch = setInterval(function(){console.log("MediaPlayer searching for remote media..."); tizen.mediaserver.scanNetwork(foundMediaServer);}, 5000);
605 console.log("MediaPlayer: No DLNA server running, using local media only...");
607 //Prevent highlighting
608 window.ondragstart = function() { return false; }
610 $(window).bind('resize', resizeAll);
612 //Simple swipe detection
613 $("#mediaName").mousedown(function(e){mouseDownEvent = e;});
614 $("#mediaName").mouseup(function(e){
615 if (Math.abs(mouseDownEvent.clientY - e.clientY) < 100)
617 if (Math.abs(mouseDownEvent.clientX - e.clientX) > 100)
619 if (mouseDownEvent.clientX > e.clientX)
620 swipe("left", "mediaName");
622 swipe("right", "mediaName");
627 document.getElementById('videoPlayer').addEventListener("playing", function() {
628 $("#playButton").toggleClass('playing', true);
629 $("#navigationButtons").hide();
631 document.getElementById('videoPlayer').addEventListener("pause", function() {
632 $("#playButton").toggleClass('playing', false);
633 $("#navigationButtons").show();
635 document.getElementById('videoPlayer').addEventListener("ended", function() {
636 $("#playButton").toggleClass('playing', false);
637 $("#navigationButtons").show();
639 document.getElementById('audioPlayer').addEventListener("playing", function() {
640 $("#playButton").toggleClass('playing', true);
642 document.getElementById('audioPlayer').addEventListener("pause", function() {
643 $("#playButton").toggleClass('playing', false);
645 document.getElementById('audioPlayer').addEventListener("ended", function() {
646 $("#playButton").toggleClass('playing', false);
648 document.getElementById('imagePlayer').addEventListener("click", function() {
649 if (!imagePlayer.playing)
656 // pause the slideshow and fade in the controls
658 $("#navigationButtons").show();
663 $(document).ready(function () {