Add CRT shader toggle to player settings menu
Some checks failed
Push & Release 🌍 / Automation 🎛️ (push) Has been cancelled
Push & Release 🌍 / Unstable release 🚀⚠️ (push) Has been cancelled
Push & Release 🌍 / Quality checks 👌🧪 (push) Has been cancelled
Push & Release 🌍 / GitHub CodeQL 🔬 (push) Has been cancelled
Push & Release 🌍 / Deploy 🚀 (push) Has been cancelled
Some checks failed
Push & Release 🌍 / Automation 🎛️ (push) Has been cancelled
Push & Release 🌍 / Unstable release 🚀⚠️ (push) Has been cancelled
Push & Release 🌍 / Quality checks 👌🧪 (push) Has been cancelled
Push & Release 🌍 / GitHub CodeQL 🔬 (push) Has been cancelled
Push & Release 🌍 / Deploy 🚀 (push) Has been cancelled
Adds a per-session CRT-Lottes shader toggle in the video player settings menu (shown when transcoding is available). Toggling restarts the stream with streamOptions[crtShader]=true appended to the TranscodingUrl, which the server picks up to apply the OpenCL CRT post-processing filter. - playersettingsmenu: showCrtMenu() (On/Off actionsheet), menu entry with current state as aside text, handleSelectedOption case - playbackmanager: isCrtShaderEnabled(), setCrtShader(enabled, shadowMask) methods; createStreamInfo appends CRT stream options to TranscodingUrl Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1422,6 +1422,21 @@ export class PlaybackManager {
|
||||
});
|
||||
};
|
||||
|
||||
self.isCrtShaderEnabled = function (player) {
|
||||
player = player || self._currentPlayer;
|
||||
return !!(getPlayerData(player).enableCrtShader);
|
||||
};
|
||||
|
||||
self.setCrtShader = function (enabled, shadowMask, player) {
|
||||
player = player || self._currentPlayer;
|
||||
const pd = getPlayerData(player);
|
||||
pd.enableCrtShader = !!enabled;
|
||||
if (shadowMask !== undefined && shadowMask !== null) {
|
||||
pd.crtShadowMask = shadowMask;
|
||||
}
|
||||
changeStream(player, getCurrentTicks(player), {});
|
||||
};
|
||||
|
||||
self.isFullscreen = function (player) {
|
||||
player = player || self._currentPlayer;
|
||||
if (!player.isLocalPlayer || player.isFullscreen) {
|
||||
@@ -2856,7 +2871,19 @@ export class PlaybackManager {
|
||||
|
||||
playMethod = mediaSource.SupportsDirectPlay ? 'DirectPlay' : 'DirectStream';
|
||||
} else if (mediaSource.SupportsTranscoding) {
|
||||
mediaUrl = apiClient.getUrl(mediaSource.TranscodingUrl);
|
||||
let transcodingUrl = mediaSource.TranscodingUrl;
|
||||
|
||||
// Append CRT-Lottes shader option when enabled for this session.
|
||||
if (getPlayerData(player).enableCrtShader) {
|
||||
const sep = transcodingUrl.includes('?') ? '&' : '?';
|
||||
transcodingUrl += sep + 'streamOptions%5BcrtShader%5D=true';
|
||||
const maskVal = getPlayerData(player).crtShadowMask;
|
||||
if (maskVal !== undefined && maskVal !== null) {
|
||||
transcodingUrl += '&streamOptions%5BcrtShadowMask%5D=' + maskVal;
|
||||
}
|
||||
}
|
||||
|
||||
mediaUrl = apiClient.getUrl(transcodingUrl);
|
||||
|
||||
if (mediaSource.TranscodingSubProtocol === 'hls') {
|
||||
contentType = 'application/x-mpegURL';
|
||||
|
||||
@@ -4,6 +4,34 @@ import globalize from 'lib/globalize';
|
||||
import { ServerConnections } from 'lib/jellyfin-apiclient';
|
||||
import qualityoptions from '../qualityOptions';
|
||||
|
||||
function showCrtMenu(player, btn) {
|
||||
const isEnabled = playbackManager.isCrtShaderEnabled(player);
|
||||
|
||||
const menuItems = [
|
||||
{
|
||||
name: globalize.translate('On'),
|
||||
id: 'crt_on',
|
||||
selected: isEnabled
|
||||
},
|
||||
{
|
||||
name: globalize.translate('Off'),
|
||||
id: 'crt_off',
|
||||
selected: !isEnabled
|
||||
}
|
||||
];
|
||||
|
||||
return actionsheet.show({
|
||||
items: menuItems,
|
||||
positionTo: btn
|
||||
}).then(function (id) {
|
||||
if (id === 'crt_on' && !isEnabled) {
|
||||
playbackManager.setCrtShader(true, null, player);
|
||||
} else if (id === 'crt_off' && isEnabled) {
|
||||
playbackManager.setCrtShader(false, null, player);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function showQualityMenu(player, btn) {
|
||||
const videoStream = playbackManager.currentMediaSource(player).MediaStreams.filter(function (stream) {
|
||||
return stream.Type === 'Video';
|
||||
@@ -214,6 +242,16 @@ function showWithUser(options, player, user) {
|
||||
});
|
||||
}
|
||||
|
||||
if (options.quality && user?.Policy?.EnableVideoPlaybackTranscoding) {
|
||||
menuItems.push({
|
||||
name: 'CRT Shader',
|
||||
id: 'crtshader',
|
||||
asideText: playbackManager.isCrtShaderEnabled(player)
|
||||
? globalize.translate('On')
|
||||
: globalize.translate('Off')
|
||||
});
|
||||
}
|
||||
|
||||
const repeatMode = playbackManager.getRepeatMode(player);
|
||||
|
||||
if (supportedCommands.indexOf('SetRepeatMode') !== -1 && playbackManager.currentMediaSource(player).RunTimeTicks) {
|
||||
@@ -272,6 +310,8 @@ function handleSelectedOption(id, options, player) {
|
||||
return showPlaybackRateMenu(player, options.positionTo);
|
||||
case 'repeatmode':
|
||||
return showRepeatModeMenu(player, options.positionTo);
|
||||
case 'crtshader':
|
||||
return showCrtMenu(player, options.positionTo);
|
||||
case 'stats':
|
||||
if (options.onOption) {
|
||||
options.onOption('stats');
|
||||
|
||||
Reference in New Issue
Block a user