';
html += '
' + current.Code + '
';
@@ -57,7 +57,7 @@ define(['require', 'apphost', 'layoutManager', 'focusManager', 'globalize', 'loa
};
QuickConnectSettings.prototype.activate = function() {
- var url = ApiClient.getUrl("/QuickConnect/Activate");
+ let url = ApiClient.getUrl("/QuickConnect/Activate");
ApiClient.ajax({
type: "POST",
url: url,
diff --git a/src/controllers/auth/login.js b/src/controllers/auth/login.js
index 86e8874e7e..8b0bcdd28d 100644
--- a/src/controllers/auth/login.js
+++ b/src/controllers/auth/login.js
@@ -151,10 +151,10 @@ define(["apphost", "appSettings", "dom", "connectionManager", "loading", "layout
}
function loginQuickConnect() {
- var apiClient = getApiClient();
- var friendlyName = navigator.userAgent;
+ let apiClient = getApiClient();
+ let friendlyName = navigator.userAgent;
- var url = apiClient.getUrl("/QuickConnect/Initiate?FriendlyName=" + friendlyName);
+ let url = apiClient.getUrl("/QuickConnect/Initiate?FriendlyName=" + friendlyName);
apiClient.getJSON(url)
.then(json => {
if (!json.Secret || !json.Code) {
@@ -173,15 +173,15 @@ define(["apphost", "appSettings", "dom", "connectionManager", "loading", "layout
loading.show();
- var interval = setInterval(async function() {
+ let interval = setInterval(async function() {
try {
let connectUrl = apiClient.getUrl('/QuickConnect/Connect?Secret=' + json.Secret);
let data = await apiClient.getJSON(connectUrl);
if (data.Authenticated) {
let result = await apiClient.quickConnect(data.Authentication);
- var user = result.User;
- var serverId = getParameterByName("serverid");
- var newUrl = "home.html";
+ let user = result.User;
+ let serverId = getParameterByName("serverid");
+ let newUrl = "home.html";
if (user.Policy.IsAdministrator && !serverId) {
newUrl = "dashboard.html";
diff --git a/src/controllers/quickconnect.js b/src/controllers/quickconnect.js
index 3432e79231..93b74a1b52 100644
--- a/src/controllers/quickconnect.js
+++ b/src/controllers/quickconnect.js
@@ -1,9 +1,9 @@
define(["jQuery", "loading", "fnchecked"], function ($, loading) {
"use strict";
- var page;
+ let page;
function loadPage(status) {
- var available = status === "Available" || status === "Active";
+ let available = status === "Available" || status === "Active";
page.querySelector("#quickConnectStatus").textContent = status.toLocaleLowerCase();
page.querySelector("#chkQuickConnectAvailable").checked = available;
@@ -14,9 +14,9 @@ define(["jQuery", "loading", "fnchecked"], function ($, loading) {
function onSubmit() {
loading.show();
- var newStatus = page.querySelector("#chkQuickConnectAvailable").checked ? "Available" : "Unavailable";
+ let newStatus = page.querySelector("#chkQuickConnectAvailable").checked ? "Available" : "Unavailable";
- var url = ApiClient.getUrl("/QuickConnect/Available");
+ let url = ApiClient.getUrl("/QuickConnect/Available");
ApiClient.ajax({
type: "POST",
@@ -41,7 +41,7 @@ define(["jQuery", "loading", "fnchecked"], function ($, loading) {
}
function updatePage() {
- var promise1 = ApiClient.getQuickConnect("Status");
+ let promise1 = ApiClient.getQuickConnect("Status");
Promise.all([promise1]).then((responses) => {
loadPage(responses[0]);
return true;
diff --git a/src/controllers/user/quickconnect.js b/src/controllers/user/quickconnect.js
index 035aef8f2f..bee0c1b817 100644
--- a/src/controllers/user/quickconnect.js
+++ b/src/controllers/user/quickconnect.js
@@ -2,7 +2,7 @@ define(["quickConnectSettings", "dom", "globalize", "loading", "userSettings", "
"use strict";
return function (view) {
- var quickConnectSettingsInstance = null;
+ let quickConnectSettingsInstance = null;
view.addEventListener("viewshow", function () {
quickConnectSettingsInstance = new QuickConnectSettings({
From 8655de4469c3aade0e1f949169c8f536a43e210b Mon Sep 17 00:00:00 2001
From: Matt Montgomery <33811686+ConfusedPolarBear@users.noreply.github.com>
Date: Fri, 1 May 2020 13:49:06 -0500
Subject: [PATCH 009/340] Rename to camel case
---
.../quickConnectSettings.js} | 0
src/controllers/{quickconnect.js => quickConnect.js} | 0
src/controllers/user/{quickconnect.js => quickConnect.js} | 0
...referencesquickconnect.html => myPreferencesQuickConnect.html} | 0
src/{quickconnect.html => quickConnect.html} | 0
5 files changed, 0 insertions(+), 0 deletions(-)
rename src/components/{quickconnectsettings/quickconnectsettings.js => quickConnectSettings/quickConnectSettings.js} (100%)
rename src/controllers/{quickconnect.js => quickConnect.js} (100%)
rename src/controllers/user/{quickconnect.js => quickConnect.js} (100%)
rename src/{mypreferencesquickconnect.html => myPreferencesQuickConnect.html} (100%)
rename src/{quickconnect.html => quickConnect.html} (100%)
diff --git a/src/components/quickconnectsettings/quickconnectsettings.js b/src/components/quickConnectSettings/quickConnectSettings.js
similarity index 100%
rename from src/components/quickconnectsettings/quickconnectsettings.js
rename to src/components/quickConnectSettings/quickConnectSettings.js
diff --git a/src/controllers/quickconnect.js b/src/controllers/quickConnect.js
similarity index 100%
rename from src/controllers/quickconnect.js
rename to src/controllers/quickConnect.js
diff --git a/src/controllers/user/quickconnect.js b/src/controllers/user/quickConnect.js
similarity index 100%
rename from src/controllers/user/quickconnect.js
rename to src/controllers/user/quickConnect.js
diff --git a/src/mypreferencesquickconnect.html b/src/myPreferencesQuickConnect.html
similarity index 100%
rename from src/mypreferencesquickconnect.html
rename to src/myPreferencesQuickConnect.html
diff --git a/src/quickconnect.html b/src/quickConnect.html
similarity index 100%
rename from src/quickconnect.html
rename to src/quickConnect.html
From d8cfe064e60379033fdf61a963efbc27296130af Mon Sep 17 00:00:00 2001
From: Matt Montgomery <33811686+ConfusedPolarBear@users.noreply.github.com>
Date: Fri, 1 May 2020 14:18:04 -0500
Subject: [PATCH 010/340] Changed code to camel case
---
src/controllers/user/menu.js | 2 +-
src/scripts/librarymenu.js | 2 +-
src/scripts/routes.js | 8 ++++----
src/scripts/site.js | 2 +-
4 files changed, 7 insertions(+), 7 deletions(-)
diff --git a/src/controllers/user/menu.js b/src/controllers/user/menu.js
index f5d05c5be3..9482b26cb5 100644
--- a/src/controllers/user/menu.js
+++ b/src/controllers/user/menu.js
@@ -24,7 +24,7 @@ define(["apphost", "connectionManager", "layoutManager", "listViewStyle", "emby-
page.querySelector(".lnkHomePreferences").setAttribute("href", "mypreferenceshome.html?userId=" + userId);
page.querySelector(".lnkPlaybackPreferences").setAttribute("href", "mypreferencesplayback.html?userId=" + userId);
page.querySelector(".lnkSubtitlePreferences").setAttribute("href", "mypreferencessubtitles.html?userId=" + userId);
- page.querySelector(".lnkQuickConnectPreferences").setAttribute("href", "mypreferencesquickconnect.html?userId=" + userId);
+ page.querySelector(".lnkQuickConnectPreferences").setAttribute("href", "myPreferencesQuickConnect.html?userId=" + userId);
if (window.NativeShell && window.NativeShell.AppHost.supports("clientsettings")) {
page.querySelector(".clientSettings").classList.remove("hide");
diff --git a/src/scripts/librarymenu.js b/src/scripts/librarymenu.js
index e3ef65f22f..d123395ca0 100644
--- a/src/scripts/librarymenu.js
+++ b/src/scripts/librarymenu.js
@@ -352,7 +352,7 @@ define(["dom", "layoutManager", "inputManager", "connectionManager", "events", "
});
links.push({
name: globalize.translate("QuickConnect"),
- href: "quickconnect.html",
+ href: "quickConnect.html",
pageIds: ["quickConnectPage", "quickConnectPage"],
icon: "tap_and_play"
});
diff --git a/src/scripts/routes.js b/src/scripts/routes.js
index 1520e96632..f0806f56e0 100644
--- a/src/scripts/routes.js
+++ b/src/scripts/routes.js
@@ -73,10 +73,10 @@ define([
controller: "user/subtitles"
});
defineRoute({
- path: "/mypreferencesquickconnect.html",
+ path: "/myPreferencesQuickConnect.html",
autoFocus: false,
transition: "fade",
- controller: "user/quickconnect"
+ controller: "user/quickConnect"
});
defineRoute({
@@ -110,10 +110,10 @@ define([
controller: "device"
});
defineRoute({
- path: "/quickconnect.html",
+ path: "/quickConnect.html",
autoFocus: false,
roles: "admin",
- controller: "quickconnect"
+ controller: "quickConnect"
});
defineRoute({
path: "/dlnaprofile.html",
diff --git a/src/scripts/site.js b/src/scripts/site.js
index 3b8abf2bfe..ca8a828b0b 100644
--- a/src/scripts/site.js
+++ b/src/scripts/site.js
@@ -829,7 +829,7 @@ var AppInfo = {};
define("displaySettings", [componentsPath + "/displaysettings/displaysettings"], returnFirstDependency);
define("playbackSettings", [componentsPath + "/playbacksettings/playbacksettings"], returnFirstDependency);
define("homescreenSettings", [componentsPath + "/homescreensettings/homescreensettings"], returnFirstDependency);
- define("quickConnectSettings", [componentsPath + "/quickconnectsettings/quickconnectsettings"], returnFirstDependency);
+ define("quickConnectSettings", [componentsPath + "/quickConnectSettings/quickConnectSettings"], returnFirstDependency);
define("playbackManager", [componentsPath + "/playback/playbackmanager"], getPlaybackManager);
define("layoutManager", [componentsPath + "/layoutManager", "apphost"], getLayoutManager);
define("homeSections", [componentsPath + "/homesections/homesections"], returnFirstDependency);
From 2655b4dca3da200f9dc720f37b4d6e7f32b4d839 Mon Sep 17 00:00:00 2001
From: Matt Montgomery <33811686+ConfusedPolarBear@users.noreply.github.com>
Date: Mon, 4 May 2020 17:23:57 -0500
Subject: [PATCH 011/340] Migrate API changes to apiclient repo
---
src/libraries/apiclient/apiclientcore.js | 25 ------------------------
1 file changed, 25 deletions(-)
diff --git a/src/libraries/apiclient/apiclientcore.js b/src/libraries/apiclient/apiclientcore.js
index e1892505fc..557a4e1033 100644
--- a/src/libraries/apiclient/apiclientcore.js
+++ b/src/libraries/apiclient/apiclientcore.js
@@ -356,31 +356,6 @@ define(["events", "appStorage"], function(events, appStorage) {
instance.onAuthenticated ? instance.onAuthenticated(instance, result).then(afterOnAuthenticated) : afterOnAuthenticated()
}, reject)
})
- }, ApiClient.prototype.quickConnect = function (token) {
- if (!token) return Promise.reject();
- var url = this.getUrl("Users/AuthenticateWithQuickConnect");
- var instance = this;
- return new Promise(function(resolve, reject) {
- var postData = {
- Token: token
- };
- instance.ajax({
- type: "POST",
- url: url,
- data: JSON.stringify(postData),
- dataType: "json",
- contentType: "application/json"
- }).then(function(result) {
- var afterOnAuthenticated = function() {
- redetectBitrate(instance);
- return resolve(result);
- };
- instance.onAuthenticated ? instance.onAuthenticated(instance, result).then(afterOnAuthenticated) : afterOnAuthenticated()
- }, reject)
- })
- }, ApiClient.prototype.getQuickConnect = function(verb) {
- var url = this.getUrl("/QuickConnect/" + verb);
- return this.getJSON(url);
}, ApiClient.prototype.ensureWebSocket = function() {
if (!this.isWebSocketOpenOrConnecting() && this.isWebSocketSupported()) try {
this.openWebSocket()
From 2ea2132740238f79136e7e398d78a9d25329c9fa Mon Sep 17 00:00:00 2001
From: MrTimscampi
Date: Fri, 29 May 2020 23:32:45 +0200
Subject: [PATCH 012/340] Add barebones comic book reader
---
package.json | 2 +
src/bundle.js | 6 +
src/components/comicsPlayer/plugin.js | 215 +++++++++++++++++++++
src/components/playback/playbackmanager.js | 6 +-
src/components/pluginManager.js | 2 +-
src/scripts/site.js | 4 +-
webpack.common.js | 18 +-
yarn.lock | 5 +
8 files changed, 252 insertions(+), 6 deletions(-)
create mode 100644 src/components/comicsPlayer/plugin.js
diff --git a/package.json b/package.json
index 749c62d39c..aefec20d7a 100644
--- a/package.json
+++ b/package.json
@@ -69,6 +69,7 @@
"jellyfin-noto": "https://github.com/jellyfin/jellyfin-noto",
"jquery": "^3.5.1",
"jstree": "^3.3.7",
+ "libarchive.js": "^1.3.0",
"libass-wasm": "https://github.com/jellyfin/JavascriptSubtitlesOctopus#4.0.0-jf-smarttv",
"material-design-icons-iconfont": "^5.0.1",
"native-promise-only": "^0.8.0-a",
@@ -92,6 +93,7 @@
"src/components/autoFocuser.js",
"src/components/cardbuilder/cardBuilder.js",
"src/scripts/fileDownloader.js",
+ "src/components/comicsPlayer/plugin.js",
"src/components/images/imageLoader.js",
"src/components/lazyLoader/lazyLoaderIntersectionObserver.js",
"src/components/playback/mediasession.js",
diff --git a/src/bundle.js b/src/bundle.js
index d7ba6c6a51..fd9099aaf3 100644
--- a/src/bundle.js
+++ b/src/bundle.js
@@ -176,3 +176,9 @@ _define('connectionManagerFactory', function () {
_define('appStorage', function () {
return apiclient.AppStorage;
});
+
+// libarchive.js
+var libarchive = require('libarchive.js');
+_define('libarchive', function () {
+ return libarchive;
+});
diff --git a/src/components/comicsPlayer/plugin.js b/src/components/comicsPlayer/plugin.js
new file mode 100644
index 0000000000..43469bfed4
--- /dev/null
+++ b/src/components/comicsPlayer/plugin.js
@@ -0,0 +1,215 @@
+import connectionManager from 'connectionManager';
+import loading from 'loading';
+import dialogHelper from 'dialogHelper';
+import keyboardnavigation from 'keyboardnavigation';
+import appRouter from 'appRouter';
+import 'css!../slideshow/style';
+import * as libarchive from 'libarchive';
+
+export class ComicsPlayer {
+ constructor() {
+ this.name = 'Comics Player';
+ this.type = 'mediaplayer';
+ this.id = 'comicsplayer';
+ this.priority = 1;
+ this.imageMap = new Map();
+
+ this.onDialogClosed = this.onDialogClosed.bind(this);
+ this.onWindowKeyUp = this.onWindowKeyUp.bind(this);
+ }
+
+ play(options) {
+ this._progress = 0;
+
+ let elem = this.createMediaElement();
+ return this.setCurrentSrc(elem, options);
+ }
+
+ stop() {
+ this.unbindEvents();
+
+ let elem = this._mediaElement;
+
+ if (elem) {
+ dialogHelper.close(elem);
+ this._mediaElement = null;
+ }
+
+ // Hide loader in case player was not fully loaded yet
+ loading.hide();
+ }
+
+ onDialogClosed() {
+ this.stop();
+ }
+
+ onWindowKeyUp(e) {
+ let key = keyboardnavigation.getKeyName(e);
+ switch (key) {
+ case 'Escape':
+ this.stop();
+ break;
+ }
+ }
+
+ bindEvents() {
+ document.addEventListener('keyup', this.onWindowKeyUp);
+ }
+
+ unbindEvents() {
+ document.removeEventListener('keyup', this.onWindowKeyUp);
+ }
+
+ createMediaElement() {
+ let elem = this._mediaElement;
+
+ if (elem) {
+ return elem;
+ }
+
+ elem = document.getElementById('comicsPlayer');
+ if (!elem) {
+ elem = dialogHelper.createDialog({
+ exitAnimationDuration: 400,
+ size: 'fullscreen',
+ autoFocus: false,
+ scrollY: false,
+ exitAnimation: 'fadeout',
+ removeOnClose: true
+ });
+ elem.id = 'bookPlayer';
+
+ elem.classList.add('slideshowDialog');
+
+ elem.innerHTML = '';
+
+ this.bindEvents();
+
+ dialogHelper.open(elem);
+ }
+
+ this._mediaElement = elem;
+
+ return elem;
+ }
+
+ setCurrentSrc(elem, options) {
+ let item = options.items[0];
+ this._currentItem = item;
+
+ loading.show();
+
+ let serverId = item.ServerId;
+ let apiClient = connectionManager.getApiClient(serverId);
+
+ libarchive.Archive.init({
+ workerUrl: appRouter.baseUrl() + '/libraries/worker-bundle.js'
+ });
+
+ return new Promise((resolve, reject) => {
+ let downloadUrl = apiClient.getItemDownloadUrl(item.Id);
+ const archiveSource = new ArchiveSource(downloadUrl);
+ var instance = this;
+ import('swiper').then(({default: Swiper}) => {
+ archiveSource.load().then(() => {
+ loading.hide();
+ this.swiperInstance = new Swiper(elem.querySelector('.slideshowSwiperContainer'), {
+ direction: 'horizontal',
+ // Loop is disabled due to the virtual slides option not supporting it.
+ loop: false,
+ zoom: {
+ minRatio: 1,
+ toggle: true,
+ containerClass: 'slider-zoom-container'
+ },
+ autoplay: false,
+ keyboard: {
+ enabled: true
+ },
+ preloadImages: true,
+ slidesPerView: 1,
+ slidesPerColumn: 1,
+ initialSlide: 0,
+ // Virtual slides reduce memory consumption for large libraries while allowing preloading of images;
+ virtual: {
+ slides: archiveSource.urls,
+ cache: true,
+ renderSlide: instance.getImgFromUrl,
+ addSlidesBefore: 1,
+ addSlidesAfter: 1
+ }
+ });
+ });
+ });
+ });
+ }
+
+ getImgFromUrl(url) {
+ return `
+
+

+
+
`;
+ }
+
+ canPlayMediaType(mediaType) {
+ return (mediaType || '').toLowerCase() === 'book';
+ }
+
+ canPlayItem(item) {
+ if (item.Path && (item.Path.endsWith('cbz') || item.Path.endsWith('cbr'))) {
+ return true;
+ }
+ return false;
+ }
+}
+
+class ArchiveSource {
+ constructor(url) {
+ this.url = url;
+ this.files = [];
+ this.urls = [];
+ this.loadPromise = this.load();
+ this.itemsLoaded = 0;
+ }
+
+ async load() {
+ let res = await fetch(this.url);
+ if (!res.ok) {
+ return;
+ }
+ let blob = await res.blob();
+ this.archive = await libarchive.Archive.open(blob);
+ this.raw = await this.archive.getFilesArray();
+ this.numberOfFiles = this.raw.length;
+ await this.archive.extractFiles();
+
+ let files = await this.archive.getFilesArray();
+ files.sort((a, b) => {
+ if (a.file.name < b.file.name)
+ return -1;
+ else
+ return 1;
+ });
+
+ for (let file of files) {
+ let url = URL.createObjectURL(file.file);
+ this.urls.push(url);
+ }
+ }
+
+ getLength() {
+ return this.raw.length;
+ }
+
+ async item(index) {
+ if (this.urls[index]) {
+ return this.urls[index];
+ }
+
+ await this.loadPromise;
+ return this.urls[index];
+ }
+}
+
+export default ComicsPlayer;
diff --git a/src/components/playback/playbackmanager.js b/src/components/playback/playbackmanager.js
index 59108cf72e..053088ef2f 100644
--- a/src/components/playback/playbackmanager.js
+++ b/src/components/playback/playbackmanager.js
@@ -2187,7 +2187,7 @@ define(['events', 'datetime', 'appSettings', 'itemHelper', 'pluginManager', 'pla
// Only used internally
self.getCurrentTicks = getCurrentTicks;
- function playPhotos(items, options, user) {
+ function playOther(items, options, user) {
var playStartIndex = options.startIndex || 0;
var player = getPlayer(items[playStartIndex], options);
@@ -2216,9 +2216,9 @@ define(['events', 'datetime', 'appSettings', 'itemHelper', 'pluginManager', 'pla
return Promise.reject();
}
- if (firstItem.MediaType === 'Photo') {
+ if (firstItem.MediaType === 'Photo' || firstItem.MediaType === 'Book') {
- return playPhotos(items, options, user);
+ return playOther(items, options, user);
}
var apiClient = connectionManager.getApiClient(firstItem.ServerId);
diff --git a/src/components/pluginManager.js b/src/components/pluginManager.js
index 6cb56d767b..fd35d344bf 100644
--- a/src/components/pluginManager.js
+++ b/src/components/pluginManager.js
@@ -58,7 +58,7 @@ define(['events', 'globalize'], function (events, globalize) {
return new Promise(function (resolve, reject) {
require([pluginSpec], (pluginFactory) => {
- var plugin = new pluginFactory();
+ var plugin = pluginFactory.default ? new pluginFactory.default() : new pluginFactory();
// See if it's already installed
var existing = instance.pluginsList.filter(function (p) {
diff --git a/src/scripts/site.js b/src/scripts/site.js
index aeb651d888..2e83928f97 100644
--- a/src/scripts/site.js
+++ b/src/scripts/site.js
@@ -490,6 +490,7 @@ var AppInfo = {};
'components/playback/experimentalwarnings',
'components/htmlAudioPlayer/plugin',
'components/htmlVideoPlayer/plugin',
+ 'components/comicsPlayer/plugin',
'components/photoPlayer/plugin',
'components/youtubeplayer/plugin',
'components/backdropScreensaver/plugin',
@@ -701,7 +702,8 @@ var AppInfo = {};
'events',
'credentialprovider',
'connectionManagerFactory',
- 'appStorage'
+ 'appStorage',
+ 'comicReader'
]
},
urlArgs: urlArgs,
diff --git a/webpack.common.js b/webpack.common.js
index 03beb63a73..2cc8478d86 100644
--- a/webpack.common.js
+++ b/webpack.common.js
@@ -1,10 +1,12 @@
const path = require('path');
const CopyPlugin = require('copy-webpack-plugin');
+const WorkerPlugin = require('worker-plugin');
const Assets = [
'alameda/alameda.js',
'native-promise-only/npo.js',
+ 'libarchive.js/dist/worker-bundle.js',
'libass-wasm/dist/js/subtitles-octopus-worker.js',
'libass-wasm/dist/js/subtitles-octopus-worker.data',
'libass-wasm/dist/js/subtitles-octopus-worker.wasm',
@@ -13,6 +15,11 @@ const Assets = [
'libass-wasm/dist/js/subtitles-octopus-worker-legacy.js.mem'
];
+const LibarchiveWasm = [
+ 'libarchive.js/dist/wasm-gen/libarchive.js',
+ 'libarchive.js/dist/wasm-gen/libarchive.wasm'
+];
+
module.exports = {
context: path.resolve(__dirname, 'src'),
entry: './bundle.js',
@@ -34,6 +41,15 @@ module.exports = {
to: path.resolve(__dirname, './dist/libraries')
};
})
- )
+ ),
+ new CopyPlugin(
+ LibarchiveWasm.map(asset => {
+ return {
+ from: path.resolve(__dirname, `./node_modules/${asset}`),
+ to: path.resolve(__dirname, './dist/libraries/wasm-gen/')
+ };
+ })
+ ),
+ new WorkerPlugin()
]
};
diff --git a/yarn.lock b/yarn.lock
index 20fdef5de1..5b8df85f45 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -6783,6 +6783,11 @@ levn@^0.3.0, levn@~0.3.0:
prelude-ls "~1.1.2"
type-check "~0.3.2"
+libarchive.js@^1.3.0:
+ version "1.3.0"
+ resolved "https://registry.yarnpkg.com/libarchive.js/-/libarchive.js-1.3.0.tgz#18c42c6b4ce727a02359c90769e4e454cf3743cd"
+ integrity sha512-EkQfRXt9DhWwj6BnEA2TNpOf4jTnzSTUPGgE+iFxcdNqjktY8GitbDeHnx8qZA0/IukNyyBUR3oQKRdYkO+HFg==
+
"libass-wasm@https://github.com/jellyfin/JavascriptSubtitlesOctopus#4.0.0-jf-smarttv":
version "4.0.0"
resolved "https://github.com/jellyfin/JavascriptSubtitlesOctopus#58e9a3f1a7f7883556ee002545f445a430120639"
From 429c47f414851bf95f24736ce2e08e370c397eac Mon Sep 17 00:00:00 2001
From: nyanmisaka
Date: Thu, 25 Jun 2020 16:53:45 +0800
Subject: [PATCH 013/340] add tonemapping settings
---
src/components/itemMediaInfo/itemMediaInfo.js | 12 +++++
src/components/playerstats/playerstats.js | 28 ++++++++++
src/controllers/dashboard/encodingsettings.js | 26 +++++++++
src/encodingsettings.html | 53 +++++++++++++++++++
src/strings/en-us.json | 26 ++++++++-
src/strings/zh-cn.json | 26 ++++++++-
6 files changed, 169 insertions(+), 2 deletions(-)
diff --git a/src/components/itemMediaInfo/itemMediaInfo.js b/src/components/itemMediaInfo/itemMediaInfo.js
index 81c84b6a23..ad5f261ec6 100644
--- a/src/components/itemMediaInfo/itemMediaInfo.js
+++ b/src/components/itemMediaInfo/itemMediaInfo.js
@@ -90,6 +90,18 @@ define(['dialogHelper', 'require', 'layoutManager', 'globalize', 'userSettings',
if (stream.BitDepth) {
attributes.push(createAttribute(globalize.translate('MediaInfoBitDepth'), stream.BitDepth + ' bit'));
}
+ if (stream.VideoRange) {
+ attributes.push(createAttribute(globalize.translate('MediaInfoVideoRange'), stream.VideoRange));
+ }
+ if (stream.ColorSpace) {
+ attributes.push(createAttribute(globalize.translate('MediaInfoColorSpace'), stream.ColorSpace));
+ }
+ if (stream.ColorTransfer) {
+ attributes.push(createAttribute(globalize.translate('MediaInfoColorTransfer'), stream.ColorTransfer));
+ }
+ if (stream.ColorPrimaries) {
+ attributes.push(createAttribute(globalize.translate('MediaInfoColorPrimaries'), stream.ColorPrimaries));
+ }
if (stream.PixelFormat) {
attributes.push(createAttribute(globalize.translate('MediaInfoPixelFormat'), stream.PixelFormat));
}
diff --git a/src/components/playerstats/playerstats.js b/src/components/playerstats/playerstats.js
index a65baf3553..e3fe6452f8 100644
--- a/src/components/playerstats/playerstats.js
+++ b/src/components/playerstats/playerstats.js
@@ -279,6 +279,34 @@ define(['events', 'globalize', 'playbackManager', 'connectionManager', 'syncPlay
});
}
+ if (videoStream.VideoRange) {
+ sessionStats.push({
+ label: globalize.translate('LabelVideoRange'),
+ value: videoStream.VideoRange
+ });
+ }
+
+ if (videoStream.ColorSpace) {
+ sessionStats.push({
+ label: globalize.translate('LabelColorSpace'),
+ value: videoStream.ColorSpace
+ });
+ }
+
+ if (videoStream.ColorTransfer) {
+ sessionStats.push({
+ label: globalize.translate('LabelColorTransfer'),
+ value: videoStream.ColorTransfer
+ });
+ }
+
+ if (videoStream.ColorPrimaries) {
+ sessionStats.push({
+ label: globalize.translate('LabelColorPrimaries'),
+ value: videoStream.ColorPrimaries
+ });
+ }
+
var audioInfos = [];
if (audioCodec) {
diff --git a/src/controllers/dashboard/encodingsettings.js b/src/controllers/dashboard/encodingsettings.js
index 0f54f9d70f..d728321284 100644
--- a/src/controllers/dashboard/encodingsettings.js
+++ b/src/controllers/dashboard/encodingsettings.js
@@ -8,12 +8,20 @@ define(['jQuery', 'loading', 'globalize', 'dom', 'libraryMenu'], function ($, lo
page.querySelector('#chkDecodingColorDepth10Hevc').checked = config.EnableDecodingColorDepth10Hevc;
page.querySelector('#chkDecodingColorDepth10Vp9').checked = config.EnableDecodingColorDepth10Vp9;
page.querySelector('#chkHardwareEncoding').checked = config.EnableHardwareEncoding;
+ page.querySelector('#chkTonemapping').checked = config.EnableTonemapping;
$('#selectVideoDecoder', page).val(config.HardwareAccelerationType);
$('#selectThreadCount', page).val(config.EncodingThreadCount);
$('#txtDownMixAudioBoost', page).val(config.DownMixAudioBoost);
page.querySelector('.txtEncoderPath').value = config.EncoderAppPathDisplay || '';
$('#txtTranscodingTempPath', page).val(systemInfo.TranscodingTempPath || '');
$('#txtVaapiDevice', page).val(config.VaapiDevice || '');
+ $('#txtOpenclDevice', page).val(config.OpenclDevice || '');
+ $('#selectTonemappingAlgorithm', page).val(config.TonemappingAlgorithm);
+ $('#selectTonemappingRange', page).val(config.TonemappingRange);
+ $('#txtTonemappingDesat', page).val(config.TonemappingDesat);
+ $('#txtTonemappingThreshold', page).val(config.TonemappingThreshold);
+ $('#txtTonemappingPeak', page).val(config.TonemappingPeak);
+ $('#txtTonemappingParam', page).val(config.TonemappingParam || '');
page.querySelector('#selectEncoderPreset').value = config.EncoderPreset || '';
page.querySelector('#txtH264Crf').value = config.H264Crf || '';
page.querySelector('#selectDeinterlaceMethod').value = config.DeinterlaceMethod || '';
@@ -59,6 +67,14 @@ define(['jQuery', 'loading', 'globalize', 'dom', 'libraryMenu'], function ($, lo
config.EncodingThreadCount = $('#selectThreadCount', form).val();
config.HardwareAccelerationType = $('#selectVideoDecoder', form).val();
config.VaapiDevice = $('#txtVaapiDevice', form).val();
+ config.OpenclDevice = $('#txtOpenclDevice', form).val();
+ config.EnableTonemapping = form.querySelector('#chkTonemapping').checked;
+ config.TonemappingAlgorithm = form.querySelector('#selectTonemappingAlgorithm').value;
+ config.TonemappingRange = form.querySelector('#selectTonemappingRange').value;
+ config.TonemappingDesat = $('#txtTonemappingDesat', form).val();
+ config.TonemappingThreshold = $('#txtTonemappingThreshold', form).val();
+ config.TonemappingPeak = $('#txtTonemappingPeak', form).val();
+ config.TonemappingParam = $('#txtTonemappingParam', form).val();
config.EncoderPreset = form.querySelector('#selectEncoderPreset').value;
config.H264Crf = parseInt(form.querySelector('#txtH264Crf').value || '0');
config.DeinterlaceMethod = form.querySelector('#selectDeinterlaceMethod').value;
@@ -141,6 +157,16 @@ define(['jQuery', 'loading', 'globalize', 'dom', 'libraryMenu'], function ($, lo
page.querySelector('#txtVaapiDevice').removeAttribute('required');
}
+ if ('nvenc' == this.value) {
+ page.querySelector('.fldOpenclDevice').classList.remove('hide');
+ page.querySelector('#txtOpenclDevice').setAttribute('required', 'required');
+ page.querySelector('.tonemappingOptions').classList.remove('hide');
+ } else {
+ page.querySelector('.fldOpenclDevice').classList.add('hide');
+ page.querySelector('#txtOpenclDevice').removeAttribute('required');
+ page.querySelector('.tonemappingOptions').classList.add('hide');
+ }
+
if (this.value) {
page.querySelector('.hardwareAccelerationOptions').classList.remove('hide');
} else {
diff --git a/src/encodingsettings.html b/src/encodingsettings.html
index 858375b145..c020df9121 100644
--- a/src/encodingsettings.html
+++ b/src/encodingsettings.html
@@ -31,6 +31,11 @@
${LabelVaapiDeviceHelp}