diff --git a/dashboard-ui/bower_components/emby-webcomponents/.bower.json b/dashboard-ui/bower_components/emby-webcomponents/.bower.json index b52f127f11..97107bed5f 100644 --- a/dashboard-ui/bower_components/emby-webcomponents/.bower.json +++ b/dashboard-ui/bower_components/emby-webcomponents/.bower.json @@ -14,12 +14,12 @@ }, "devDependencies": {}, "ignore": [], - "version": "1.4.409", - "_release": "1.4.409", + "version": "1.4.411", + "_release": "1.4.411", "_resolution": { "type": "version", - "tag": "1.4.409", - "commit": "6a6a35e136f70989be0a63846b02bff62bab6367" + "tag": "1.4.411", + "commit": "50fdd44728ec2a1faa1aaf44ccb16df821b8295f" }, "_source": "https://github.com/MediaBrowser/emby-webcomponents.git", "_target": "^1.2.1", diff --git a/dashboard-ui/bower_components/emby-webcomponents/htmlaudioplayer/blank.mp3 b/dashboard-ui/bower_components/emby-webcomponents/htmlaudioplayer/blank.mp3 new file mode 100644 index 0000000000..dbf05cbdd5 Binary files /dev/null and b/dashboard-ui/bower_components/emby-webcomponents/htmlaudioplayer/blank.mp3 differ diff --git a/dashboard-ui/bower_components/emby-webcomponents/htmlaudioplayer/plugin.js b/dashboard-ui/bower_components/emby-webcomponents/htmlaudioplayer/plugin.js new file mode 100644 index 0000000000..3f6c741b26 --- /dev/null +++ b/dashboard-ui/bower_components/emby-webcomponents/htmlaudioplayer/plugin.js @@ -0,0 +1,367 @@ +define(['events', 'browser', 'pluginManager', 'apphost'], function (events, browser, pluginManager, appHost) { + "use strict"; + + return function () { + + var self = this; + + self.name = 'Html Audio Player'; + self.type = 'mediaplayer'; + self.id = 'htmlaudioplayer'; + + // Let any players created by plugins take priority + self.priority = 1; + + var mediaElement; + var currentSrc; + + self.canPlayMediaType = function (mediaType) { + + return (mediaType || '').toLowerCase() === 'audio'; + }; + + self.getDeviceProfile = function () { + + return new Promise(function (resolve, reject) { + + require(['browserdeviceprofile'], function (profileBuilder) { + + var profile = profileBuilder({ + supportsCustomSeeking: true + }); + resolve(profile); + }); + }); + }; + + self.currentSrc = function () { + return currentSrc; + }; + + self.play = function (options) { + + var elem = createMediaElement(); + + var val = options.url; + + elem.crossOrigin = getCrossOriginValue(options.mediaSource); + elem.title = options.title; + + // Opera TV guidelines suggest using source elements, so let's do that if we have a valid mimeType + if (options.mimeType && browser.operaTv) { + + // Need to do this or we won't be able to restart a new stream + if (elem.currentSrc) { + elem.src = ''; + elem.removeAttribute('src'); + } + + elem.innerHTML = ''; + } else { + elem.src = val; + } + + currentSrc = val; + + // Chrome now returns a promise + var promise = elem.play(); + + if (promise && promise.then) { + return promise; + } + return Promise.resolve(); + }; + + function getCrossOriginValue(mediaSource) { + + return 'anonymous'; + } + + // Save this for when playback stops, because querying the time at that point might return 0 + self.currentTime = function (val) { + + if (mediaElement) { + if (val != null) { + mediaElement.currentTime = val / 1000; + return; + } + + return (mediaElement.currentTime || 0) * 1000; + } + }; + + self.duration = function (val) { + + if (mediaElement) { + return mediaElement.duration * 1000; + } + + return null; + }; + + function supportsFade() { + + if (browser.tv) { + // Not working on tizen. + // We could possibly enable on other tv's, but all smart tv browsers tend to be pretty primitive + return false; + } + + return true; + } + + self.stop = function (destroyPlayer, reportEnded) { + + cancelFadeTimeout(); + + var elem = mediaElement; + var src = currentSrc; + + if (elem && src) { + + if (!destroyPlayer || !supportsFade()) { + + if (!elem.paused) { + elem.pause(); + } + elem.src = ''; + elem.innerHTML = ''; + elem.removeAttribute("src"); + onEndedInternal(reportEnded); + return Promise.resolve(); + } + + var originalVolume = elem.volume; + + return fade(elem, function () { + + }).then(function () { + if (!elem.paused) { + elem.pause(); + } + elem.src = ''; + elem.innerHTML = ''; + elem.removeAttribute("src"); + + elem.volume = originalVolume; + onEndedInternal(reportEnded); + }); + } + return Promise.resolve(); + }; + + self.destroy = function () { + + }; + + var fadeTimeout; + + function fade(elem) { + + var newVolume = Math.max(0, elem.volume - 0.15); + console.log('fading volume to ' + newVolume); + elem.volume = newVolume; + + if (!elem.volume) { + return Promise.resolve(); + } + + return new Promise(function (resolve, reject) { + + cancelFadeTimeout(); + + fadeTimeout = setTimeout(function () { + fade(elem).then(resolve, reject); + }, 100); + }); + } + + function cancelFadeTimeout() { + var timeout = fadeTimeout; + if (timeout) { + clearTimeout(timeout); + fadeTimeout = null; + } + } + + self.pause = function () { + if (mediaElement) { + mediaElement.pause(); + } + }; + + // This is a retry after error + self.resume = function () { + if (mediaElement) { + mediaElement.play(); + } + }; + + self.unpause = function () { + if (mediaElement) { + mediaElement.play(); + } + }; + + self.paused = function () { + + if (mediaElement) { + return mediaElement.paused; + } + + return false; + }; + + self.volume = function (val) { + if (mediaElement) { + if (val != null) { + mediaElement.volume = val / 100; + return; + } + + return mediaElement.volume * 100; + } + }; + + self.volumeUp = function () { + self.volume(Math.min(self.volume() + 2, 100)); + }; + + self.volumeDown = function () { + self.volume(Math.max(self.volume() - 2, 0)); + }; + + self.setMute = function (mute) { + + if (mute) { + self.volume(0); + } else { + + if (self.isMuted()) { + self.volume(50); + } + } + }; + + self.isMuted = function () { + return self.volume() === 0; + }; + + function onEnded() { + + onEndedInternal(true); + } + + function onEndedInternal(triggerEnded) { + + if (triggerEnded) { + var stopInfo = { + src: currentSrc + }; + + events.trigger(self, 'stopped', [stopInfo]); + } + + currentSrc = null; + } + + function onTimeUpdate() { + + events.trigger(self, 'timeupdate'); + } + + function onVolumeChange() { + + if (!fadeTimeout) { + events.trigger(self, 'volumechange'); + } + } + + function onPlaying() { + + events.trigger(self, 'playing'); + } + + function onPause() { + events.trigger(self, 'pause'); + } + + function onError() { + + var errorCode = this.error ? this.error.code : ''; + errorCode = (errorCode || '').toString(); + console.log('Media element error code: ' + errorCode); + + var type; + + switch (errorCode) { + case 1: + // MEDIA_ERR_ABORTED + // This will trigger when changing media while something is playing + return; + case 2: + // MEDIA_ERR_NETWORK + type = 'network'; + break; + case 3: + // MEDIA_ERR_DECODE + break; + case 4: + // MEDIA_ERR_SRC_NOT_SUPPORTED + break; + } + + //events.trigger(self, 'error', [ + //{ + // type: type + //}]); + } + + function createMediaElement() { + + var elem = document.querySelector('.mediaPlayerAudio'); + + if (!elem) { + elem = document.createElement('audio'); + elem.classList.add('mediaPlayerAudio'); + elem.classList.add('hide'); + + document.body.appendChild(elem); + + elem.addEventListener('timeupdate', onTimeUpdate); + elem.addEventListener('ended', onEnded); + elem.addEventListener('volumechange', onVolumeChange); + elem.addEventListener('pause', onPause); + elem.addEventListener('playing', onPlaying); + elem.addEventListener('error', onError); + } + + mediaElement = elem; + + return elem; + } + + function onDocumentClick() { + document.removeEventListener('click', onDocumentClick); + + var elem = document.createElement('audio'); + elem.classList.add('mediaPlayerAudio'); + elem.classList.add('hide'); + + document.body.appendChild(elem); + + elem.src = pluginManager.mapPath(self, 'blank.mp3'); + elem.play(); + + setTimeout(function () { + elem.src = ''; + elem.removeAttribute("src"); + }, 1000); + } + + // Mobile browsers don't allow autoplay, so this is a nice workaround + if (!appHost.supports('htmlaudioautoplay')) { + document.addEventListener('click', onDocumentClick); + } + }; +}); \ No newline at end of file diff --git a/dashboard-ui/bower_components/emby-webcomponents/playbackmanager.js b/dashboard-ui/bower_components/emby-webcomponents/playbackmanager.js index bf885fcc3c..9026edc766 100644 --- a/dashboard-ui/bower_components/emby-webcomponents/playbackmanager.js +++ b/dashboard-ui/bower_components/emby-webcomponents/playbackmanager.js @@ -33,11 +33,32 @@ define(['events', 'datetime', 'appSettings', 'pluginManager', 'userSettings', 'g events.trigger(self, 'playerchange', [newPlayer, newTarget, previousPlayer]); } + self.getPlayerInfo = function () { + + var player = currentPlayer; + + if (!player) { + return null; + } + + var target = currentTargetInfo || {}; + + return { + + name: player.name, + isLocalPlayer: player.isLocalPlayer, + id: target.id, + deviceName: target.deviceName, + playableMediaTypes: target.playableMediaTypes, + supportedCommands: target.supportedCommands + }; + }; + self.setActivePlayer = function (player, targetInfo) { if (typeof (player) === 'string') { player = players.filter(function (p) { - return p.name == player; + return p.name === player; })[0]; } @@ -60,7 +81,7 @@ define(['events', 'datetime', 'appSettings', 'pluginManager', 'userSettings', 'g if (typeof (player) === 'string') { player = players.filter(function (p) { - return p.name == player; + return p.name === player; })[0]; } @@ -68,7 +89,7 @@ define(['events', 'datetime', 'appSettings', 'pluginManager', 'userSettings', 'g throw new Error('null player'); } - if (currentPairingId == targetInfo.id) { + if (currentPairingId === targetInfo.id) { return; } @@ -86,7 +107,7 @@ define(['events', 'datetime', 'appSettings', 'pluginManager', 'userSettings', 'g triggerPlayerChange(player, targetInfo, previousPlayer); }, function () { - if (currentPairingId == targetInfo.id) { + if (currentPairingId === targetInfo.id) { currentPairingId = null; } }); @@ -103,7 +124,7 @@ define(['events', 'datetime', 'appSettings', 'pluginManager', 'userSettings', 'g self.getTargets().then(function (result) { var target = result.filter(function (p) { - return normalizeName(p.name) == name; + return normalizeName(p.name) === name; })[0]; if (target) { @@ -125,7 +146,7 @@ define(['events', 'datetime', 'appSettings', 'pluginManager', 'userSettings', 'g self.removeActivePlayer = function (name) { - if (self.getPlayerInfo().name == name) { + if (self.getPlayerInfo().name === name) { self.setDefaultPlayerActive(); } @@ -133,7 +154,7 @@ define(['events', 'datetime', 'appSettings', 'pluginManager', 'userSettings', 'g self.removeActiveTarget = function (id) { - if (self.getPlayerInfo().id == id) { + if (self.getPlayerInfo().id === id) { self.setDefaultPlayerActive(); } }; @@ -142,7 +163,7 @@ define(['events', 'datetime', 'appSettings', 'pluginManager', 'userSettings', 'g var playerInfo = self.getPlayerInfo(); - if (playerInfo.supportedCommands.indexOf('EndSession') != -1) { + if (playerInfo.supportedCommands.indexOf('EndSession') !== -1) { require(['dialog'], function (dialog) { @@ -166,7 +187,7 @@ define(['events', 'datetime', 'appSettings', 'pluginManager', 'userSettings', 'g switch (id) { case 'yes': - MediaController.getCurrentPlayer().endSession(); + self.getCurrentPlayer().endSession(); self.setDefaultPlayerActive(); break; case 'no': @@ -261,7 +282,7 @@ define(['events', 'datetime', 'appSettings', 'pluginManager', 'userSettings', 'g return playlist.slice(0); }; - self.currentPlayer = function () { + self.getCurrentPlayer = function () { return currentPlayer; }; @@ -481,7 +502,7 @@ define(['events', 'datetime', 'appSettings', 'pluginManager', 'userSettings', 'g return; } - return (appSettings.get('displaymirror--' + Dashboard.getCurrentUserId()) || '') != '0'; + return (appSettings.get('displaymirror--' + Dashboard.getCurrentUserId()) || '') !== '0'; }; self.stop = function () { @@ -523,14 +544,14 @@ define(['events', 'datetime', 'appSettings', 'pluginManager', 'userSettings', 'g self.seek = function (ticks) { - var player = self.currentPlayer(); + var player = currentPlayer; changeStream(player, ticks); }; self.nextChapter = function () { - var player = self.currentPlayer(); + var player = currentPlayer; var item = self.currentItem(player); var ticks = getCurrentTicks(player); @@ -549,7 +570,8 @@ define(['events', 'datetime', 'appSettings', 'pluginManager', 'userSettings', 'g }; self.previousChapter = function () { - var player = self.currentPlayer(); + + var player = currentPlayer; var item = self.currentItem(player); var ticks = getCurrentTicks(player); @@ -571,7 +593,7 @@ define(['events', 'datetime', 'appSettings', 'pluginManager', 'userSettings', 'g self.fastForward = function () { - var player = self.currentPlayer(); + var player = currentPlayer; if (player.fastForward != null) { player.fastForward(userSettings.skipForwardLength()); @@ -597,7 +619,7 @@ define(['events', 'datetime', 'appSettings', 'pluginManager', 'userSettings', 'g self.rewind = function () { - var player = self.currentPlayer(); + var player = currentPlayer; if (player.rewind != null) { player.rewind(userSettings.skipBackLength());