(function (window, document, $, setTimeout, clearTimeout) { var currentPlayer; var currentTimeElement; var nowPlayingImageElement; var nowPlayingTextElement; var nowPlayingUserData; var unmuteButton; var muteButton; var volumeSlider; var unpauseButton; var pauseButton; var positionSlider; var toggleRepeatButton; var lastPlayerState; function getNowPlayingBarHtml() { var html = ''; html += '
'; return html; } var height; function getHeight(elem) { if (!height) { height = elem.offsetHeight; } return height + 'px'; } function slideDown(elem) { if (elem.classList.contains('hide')) { return; } var onfinish = function () { elem.classList.add('hide'); }; if (!browserInfo.animate || browserInfo.mobile) { onfinish(); return; } requestAnimationFrame(function () { var keyframes = [ { height: getHeight(elem), offset: 0 }, { height: '0', display: 'none', offset: 1 }]; var timing = { duration: 200, iterations: 1, fill: 'both', easing: 'ease-out' }; elem.animate(keyframes, timing).onfinish = onfinish; }); } function slideUp(elem) { if (!elem.classList.contains('hide')) { return; } elem.classList.remove('hide'); if (!browserInfo.animate || browserInfo.mobile) { return; } requestAnimationFrame(function () { var keyframes = [ { height: '0', offset: 0 }, { height: getHeight(elem), offset: 1 }]; var timing = { duration: 200, iterations: 1, fill: 'both', easing: 'ease-out' }; elem.animate(keyframes, timing); }); } function bindEvents(elem) { currentTimeElement = $('.nowPlayingBarCurrentTime', elem); nowPlayingImageElement = $('.nowPlayingImage', elem); nowPlayingTextElement = $('.nowPlayingBarText', elem); nowPlayingUserData = $('.nowPlayingBarUserDataButtons', elem); unmuteButton = $('.unmuteButton', elem).on('click', function () { if (currentPlayer) { currentPlayer.unMute(); } }); muteButton = $('.muteButton', elem).on('click', function () { if (currentPlayer) { currentPlayer.mute(); } }); $('.stopButton', elem).on('click', function () { if (currentPlayer) { currentPlayer.stop(); } }); pauseButton = $('.pauseButton', elem).on('click', function () { if (currentPlayer) { currentPlayer.pause(); } }); unpauseButton = $('.unpauseButton', elem).on('click', function () { if (currentPlayer) { currentPlayer.unpause(); } }); $('.nextTrackButton', elem).on('click', function () { if (currentPlayer) { currentPlayer.nextTrack(); } }); $('.previousTrackButton', elem).on('click', function () { if (currentPlayer) { currentPlayer.previousTrack(); } }); $('.playlistButton', elem).on('click', function () { $.mobile.changePage('nowplaying.html', { dataUrl: 'nowplaying.html#playlist' }); }); toggleRepeatButton = $('.toggleRepeatButton', elem).on('click', function () { if (currentPlayer) { var state = lastPlayerState || {}; switch ((state.PlayState || {}).RepeatMode) { case 'RepeatAll': currentPlayer.setRepeatMode('RepeatOne'); break; case 'RepeatOne': currentPlayer.setRepeatMode('RepeatNone'); break; default: currentPlayer.setRepeatMode('RepeatAll'); break; } } })[0]; // Unfortunately this is necessary because the polymer elements might not be ready immediately and there doesn't seem to be an event-driven way to find out when setTimeout(function () { volumeSlider = $('.nowPlayingBarVolumeSlider', elem).on('change', function () { if (currentPlayer) { currentPlayer.setVolume(this.value); } })[0]; positionSlider = $('.nowPlayingBarPositionSlider', elem).on('change', function () { if (currentPlayer && lastPlayerState) { var newPercent = parseFloat(this.value); var newPositionTicks = (newPercent / 100) * lastPlayerState.NowPlayingItem.RunTimeTicks; currentPlayer.seek(Math.floor(newPositionTicks)); } })[0]; positionSlider._setPinValue = function (value) { var state = lastPlayerState; if (!state || !state.NowPlayingItem || !state.NowPlayingItem.RunTimeTicks) { this.pinValue = '--:--'; return; } var ticks = state.NowPlayingItem.RunTimeTicks; ticks /= 100; ticks *= value; this.pinValue = Dashboard.getDisplayTime(ticks); }; }, 300); } var nowPlayingBarElement; function getNowPlayingBar() { return new Promise(function (resolve, reject) { if (nowPlayingBarElement) { resolve(nowPlayingBarElement); return; } require(['css!css/nowplayingbar.css', 'paper-slider'], function () { nowPlayingBarElement = document.querySelector('.nowPlayingBar'); if (nowPlayingBarElement) { resolve(nowPlayingBarElement); return; } nowPlayingBarElement = $(getNowPlayingBarHtml()).appendTo(document.body)[0]; if ((browserInfo.safari || !AppInfo.isNativeApp) && browserInfo.mobile) { // Not handled well here. The wrong elements receive events, bar doesn't update quickly enough, etc. nowPlayingBarElement.classList.add('noMediaProgress'); } bindEvents(nowPlayingBarElement); resolve(nowPlayingBarElement); }); }); } function showButton(button) { button.removeClass('hide'); } function hideButton(button) { button.addClass('hide'); } var lastUpdateTime = 0; function updatePlayerState(event, state) { if (!state.NowPlayingItem) { hideNowPlayingBar(); return; } if (nowPlayingBarElement) { updatePlayerStateInternal(event, state); return; } getNowPlayingBar().then(function () { updatePlayerStateInternal(event, state); }); } function updatePlayerStateInternal(event, state) { showNowPlayingBar(); if (event.type == 'positionchange') { // Try to avoid hammering the document with changes var now = new Date().getTime(); if ((now - lastUpdateTime) < 700) { return; } lastUpdateTime = now; } lastPlayerState = state; var playerInfo = MediaController.getPlayerInfo(); var playState = state.PlayState || {}; if (playState.IsPaused) { hideButton(pauseButton); showButton(unpauseButton); } else { showButton(pauseButton); hideButton(unpauseButton); } updatePlayerVolumeState(state, playerInfo); var nowPlayingItem = state.NowPlayingItem || {}; // See bindEvents for why this is necessary if (positionSlider) { if (!positionSlider.dragging) { if (nowPlayingItem.RunTimeTicks) { var pct = playState.PositionTicks / nowPlayingItem.RunTimeTicks; pct *= 100; positionSlider.value = pct; } else { positionSlider.value = 0; } positionSlider.disabled = !playState.CanSeek; } } var timeText = Dashboard.getDisplayTime(playState.PositionTicks); if (nowPlayingItem.RunTimeTicks) { timeText += " / " + Dashboard.getDisplayTime(nowPlayingItem.RunTimeTicks); } currentTimeElement.html(timeText); updateNowPlayingInfo(state); } function updatePlayerVolumeState(state, playerInfo) { playerInfo = playerInfo || MediaController.getPlayerInfo(); var playState = state.PlayState || {}; var supportedCommands = playerInfo.supportedCommands; var showMuteButton = true; var showUnmuteButton = true; var showVolumeSlider = true; if (supportedCommands.indexOf('Mute') == -1) { showMuteButton = false; } if (supportedCommands.indexOf('Unmute') == -1) { showUnmuteButton = false; } if (playState.IsMuted) { showMuteButton = false; } else { showUnmuteButton = false; } if (supportedCommands.indexOf('SetRepeatMode') == -1) { toggleRepeatButton.classList.add('hide'); } else { toggleRepeatButton.classList.remove('hide'); } if (playState.RepeatMode == 'RepeatAll') { toggleRepeatButton.icon = "repeat"; toggleRepeatButton.classList.add('repeatActive'); } else if (playState.RepeatMode == 'RepeatOne') { toggleRepeatButton.icon = "repeat-one"; toggleRepeatButton.classList.add('repeatActive'); } else { toggleRepeatButton.icon = "repeat"; toggleRepeatButton.classList.remove('repeatActive'); } if (supportedCommands.indexOf('SetVolume') == -1) { showVolumeSlider = false; } if (playerInfo.isLocalPlayer && AppInfo.hasPhysicalVolumeButtons) { showMuteButton = false; showUnmuteButton = false; showVolumeSlider = false; } if (showMuteButton) { showButton(muteButton); } else { hideButton(muteButton); } if (showUnmuteButton) { showButton(unmuteButton); } else { hideButton(unmuteButton); } // See bindEvents for why this is necessary if (volumeSlider) { if (showVolumeSlider) { volumeSlider.classList.remove('hide'); } else { volumeSlider.classList.add('hide'); } if (!volumeSlider.dragging) { volumeSlider.value = playState.VolumeLevel || 0; } } } var currentImgUrl; function updateNowPlayingInfo(state) { var nameHtml = MediaController.getNowPlayingNameHtml(state.NowPlayingItem) || ''; if (nameHtml.indexOf('