mirror of
https://github.com/jellyfin/jellyfin-media-player.git
synced 2024-11-23 05:59:43 +00:00
Cleaned up settings modal and added an extra configuration input.
This commit is contained in:
parent
5bc944cb60
commit
23d7c36aa0
7
BuildAndInstall.sh
Executable file
7
BuildAndInstall.sh
Executable file
@ -0,0 +1,7 @@
|
||||
#!/bin/bash
|
||||
./download_webclient.sh
|
||||
cd build
|
||||
cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_INSTALL_PREFIX=/usr/local/ ..
|
||||
make -j4
|
||||
sudo make
|
||||
sudo make install
|
@ -197,24 +197,25 @@ Current Settings:
|
||||
- `aspect: string enum`: Allows control of aspect ratio. The default is `normal`.
|
||||
- Options: `normal`, `zoom`, `force_4_3`, `force_16_9`, `force_16_9_if_4_3`, `stretch`, `noscaling`, `custom`
|
||||
- Subtitle Section (`subtitles`):
|
||||
- `ass_scale_border_and_shadow`: Controls whether or not ASS subtitles scale their border and shadow with the video resolution. Default `true`
|
||||
- `ass_style_override: string enum`: Controls whether user style override should be applied to ASS subtitles. Default: ``
|
||||
- Provided options: [see enum](https://github.com/jellyfin/jellyfin-media-player/blob/7d5943becc1ca672d599887cac9107836c38d337/resources/settings/settings_description.json#L408-L415)
|
||||
- Provided options: [see enum](https://github.com/jellyfin/jellyfin-media-player/blob/7d5943becc1ca672d599887cac9107836c38d337/resources/settings/settings_description.json#L412-L419)
|
||||
- `placement: string enum`: Controls where subtitles are displayed on the screen. Default: ``
|
||||
- Provided options: [see enum](https://github.com/jellyfin/jellyfin-media-player/blob/7d5943becc1ca672d599887cac9107836c38d337/resources/settings/settings_description.json#L420-L428)
|
||||
- Provided options: [see enum](https://github.com/jellyfin/jellyfin-media-player/blob/7d5943becc1ca672d599887cac9107836c38d337/resources/settings/settings_description.json#L424-L432)
|
||||
- `color: string enum`: Controls colors of subtitles. Default: ``
|
||||
- Provided options: [see enum](https://github.com/jellyfin/jellyfin-media-player/blob/master/resources/settings/settings_description.json#L433-L442)
|
||||
- Provided options: [see enum](https://github.com/jellyfin/jellyfin-media-player/blob/master/resources/settings/settings_description.json#L437-L446)
|
||||
- `border_color: string enum`: Controls font border colors of subtitles. Default: ``
|
||||
- Provided options: [see enum](https://github.com/jellyfin/jellyfin-media-player/blob/master/resources/settings/settings_description.json#L447-L456)
|
||||
- Provided options: [see enum](https://github.com/jellyfin/jellyfin-media-player/blob/master/resources/settings/settings_description.json#L451-L460)
|
||||
- `border_size: int`: Controls subtitle border size. Default is `-1`.
|
||||
- Provided options: [see enum](https://github.com/jellyfin/jellyfin-media-player/blob/7d5943becc1ca672d599887cac9107836c38d337/resources/settings/settings_description.json#L461-L469)
|
||||
- Provided options: [see enum](https://github.com/jellyfin/jellyfin-media-player/blob/7d5943becc1ca672d599887cac9107836c38d337/resources/settings/settings_description.json#L465-L473)
|
||||
- `background_color: string enum`: Controls backgroud colors of subtitles. Default: ``
|
||||
- Provided options: [see enum](https://github.com/jellyfin/jellyfin-media-player/blob/master/resources/settings/settings_description.json#L474-L483)
|
||||
- Provided options: [see enum](https://github.com/jellyfin/jellyfin-media-player/blob/master/resources/settings/settings_description.json#L478-L487)
|
||||
- `background_transparency: string enum`: Controls backgroud transparency (in hex) of subtitles. Default: ``
|
||||
- Provided options: [see enum](https://github.com/jellyfin/jellyfin-media-player/blob/master/resources/settings/settings_description.json#L488-L495)
|
||||
- Provided options: [see enum](https://github.com/jellyfin/jellyfin-media-player/blob/master/resources/settings/settings_description.json#L492-L499)
|
||||
- `size: int`: Controls subtitle size. Default is `-1`.
|
||||
- Provided options: [see enum](https://github.com/jellyfin/jellyfin-media-player/blob/7d5943becc1ca672d599887cac9107836c38d337/resources/settings/settings_description.json#L500-L507)
|
||||
- Provided options: [see enum](https://github.com/jellyfin/jellyfin-media-player/blob/7d5943becc1ca672d599887cac9107836c38d337/resources/settings/settings_description.json#L504-L511)
|
||||
- `font: string enum`: Specify font to use for subtitles that do not themselves specify a particular font. Default: ``
|
||||
- Provided options: [see enum](https://github.com/jellyfin/jellyfin-media-player/blob/master/resources/settings/settings_description.json#L512-L521)
|
||||
- Provided options: [see enum](https://github.com/jellyfin/jellyfin-media-player/blob/master/resources/settings/settings_description.json#L515-L525)
|
||||
|
||||
The global `window.jmpInfo` object contains settings for the application in the form of `window.jmpInfo.settings.[section][key] = value`.
|
||||
Settings descriptions are stored in the form `window.jmpInfo.settingsDescriptions.[section] = [{ key, options }]`
|
||||
|
@ -245,6 +245,11 @@ async function createApi() {
|
||||
return channel.objects;
|
||||
}
|
||||
|
||||
const sectionsFromStorage = window.sessionStorage.getItem('sections');
|
||||
if (sectionsFromStorage) {
|
||||
jmpInfo.sections = JSON.parse(sectionsFromStorage);
|
||||
}
|
||||
|
||||
let rawSettings = {};
|
||||
Object.assign(rawSettings, jmpInfo.settings);
|
||||
const settingsFromStorage = window.sessionStorage.getItem('settings');
|
||||
@ -342,6 +347,40 @@ window.NativeShell.AppHost = {
|
||||
async function showSettingsModal() {
|
||||
await initCompleted;
|
||||
|
||||
const tooltipCSS = `
|
||||
.tooltip {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
margin-left: 0.5rem;
|
||||
font-size: 18px;
|
||||
vertical-align: sub;
|
||||
}
|
||||
|
||||
.tooltip .tooltip-text {
|
||||
visibility: hidden;
|
||||
width: max-content;
|
||||
max-width: 40em;
|
||||
background-color: black;
|
||||
color: white;
|
||||
text-align: left;
|
||||
position: absolute;
|
||||
z-index: 1;
|
||||
border-radius: 6px;
|
||||
padding: 5px;
|
||||
top: -4px;
|
||||
left: 25px;
|
||||
border: solid 1px grey;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.tooltip:hover .tooltip-text {
|
||||
visibility: visible;
|
||||
}`;
|
||||
|
||||
var style = document.createElement('style')
|
||||
style.innerText = tooltipCSS
|
||||
document.head.appendChild(style)
|
||||
|
||||
const modalContainer = document.createElement("div");
|
||||
modalContainer.className = "dialogContainer";
|
||||
modalContainer.style.backgroundColor = "rgba(0,0,0,0.5)";
|
||||
@ -372,7 +411,8 @@ async function showSettingsModal() {
|
||||
modalContainer2.appendChild(modalContents);
|
||||
|
||||
const settingUpdateHandlers = {};
|
||||
for (const section of Object.keys(jmpInfo.settingsDescriptions)) {
|
||||
for (const sectionOrder of jmpInfo.sections.sort((a, b) => a.order - b.order)) {
|
||||
const section = sectionOrder.key;
|
||||
const group = document.createElement("fieldset");
|
||||
group.className = "editItemMetadataForm editMetadataForm dialog-content-centered";
|
||||
group.style.border = 0;
|
||||
@ -396,6 +436,10 @@ async function showSettingsModal() {
|
||||
const legendSubHeader = document.createElement("h4");
|
||||
legendSubHeader.textContent = "Plugins are UNOFFICIAL and require a restart to take effect.";
|
||||
legend.appendChild(legendSubHeader);
|
||||
} else if (section == "other") {
|
||||
const legendSubHeader = document.createElement("h4");
|
||||
legendSubHeader.textContent = "Use this section to input custom MPV configuration. These will override the above settings.";
|
||||
legend.appendChild(legendSubHeader);
|
||||
}
|
||||
group.appendChild(legend);
|
||||
|
||||
@ -404,7 +448,21 @@ async function showSettingsModal() {
|
||||
label.className = "inputContainer";
|
||||
label.style.marginBottom = "1.8em";
|
||||
label.style.display = "block";
|
||||
label.style.textTransform = "capitalize";
|
||||
|
||||
let helpElement;
|
||||
if (setting.help) {
|
||||
helpElement = document.createElement("div");
|
||||
helpElement.className = "tooltip";
|
||||
const helpIcon = document.createElement("span");
|
||||
helpIcon.style.fontSize = "18px"
|
||||
helpIcon.className = "material-icons help_outline";
|
||||
helpElement.appendChild(helpIcon);
|
||||
const tooltipElement = document.createElement("span");
|
||||
tooltipElement.className = "tooltip-text";
|
||||
tooltipElement.innerText = setting.help;
|
||||
helpElement.appendChild(tooltipElement);
|
||||
}
|
||||
|
||||
if (setting.options) {
|
||||
const safeValues = {};
|
||||
const control = document.createElement("select");
|
||||
@ -430,8 +488,25 @@ async function showSettingsModal() {
|
||||
});
|
||||
const labelText = document.createElement('label');
|
||||
labelText.className = "inputLabel";
|
||||
labelText.textContent = setting.key + ": ";
|
||||
labelText.textContent = (setting.displayName ? setting.displayName : setting.key) + ": ";
|
||||
label.appendChild(labelText);
|
||||
if (helpElement) label.appendChild(helpElement);
|
||||
label.appendChild(control);
|
||||
} else if (setting.inputType === "textarea") {
|
||||
const control = document.createElement("textarea");
|
||||
control.className = "emby-select-withcolor emby-select";
|
||||
control.style = "resize: none;"
|
||||
control.value = values[setting.key];
|
||||
control.rows = 5;
|
||||
control.addEventListener("change", e =>
|
||||
{
|
||||
jmpInfo.settings[section][setting.key] = e.target.value;
|
||||
});
|
||||
const labelText = document.createElement('label');
|
||||
labelText.className = "inputLabel";
|
||||
labelText.textContent = (setting.displayName ? setting.displayName : setting.key) + ": ";
|
||||
label.appendChild(labelText);
|
||||
if (helpElement) label.appendChild(helpElement);
|
||||
label.appendChild(control);
|
||||
} else {
|
||||
const control = document.createElement("input");
|
||||
@ -441,8 +516,10 @@ async function showSettingsModal() {
|
||||
jmpInfo.settings[section][setting.key] = e.target.checked;
|
||||
});
|
||||
label.appendChild(control);
|
||||
label.appendChild(document.createTextNode(" " + setting.key));
|
||||
label.appendChild(document.createTextNode(" " + (setting.displayName ? setting.displayName : setting.key)));
|
||||
if (helpElement) label.appendChild(helpElement);
|
||||
}
|
||||
|
||||
group.appendChild(label);
|
||||
}
|
||||
};
|
||||
|
@ -17,6 +17,7 @@
|
||||
},
|
||||
{
|
||||
"section": "main",
|
||||
"order": 1,
|
||||
"values": [
|
||||
{
|
||||
"value": "webMode",
|
||||
@ -38,6 +39,8 @@
|
||||
},
|
||||
{
|
||||
"value": "fullscreen",
|
||||
"display_name": "Full Screen",
|
||||
"help": "Forces the application into fullscreen mode.\nNote: Regular HTML5 fullscreen does still work.",
|
||||
"default": false,
|
||||
"platforms_excluded": "oe"
|
||||
},
|
||||
@ -49,6 +52,8 @@
|
||||
},
|
||||
{
|
||||
"value": "alwaysOnTop",
|
||||
"display_name": "Always on Top",
|
||||
"help": "Keeps Jellyfin Media Player on top of other windows.",
|
||||
"default": false
|
||||
},
|
||||
{
|
||||
@ -78,7 +83,8 @@
|
||||
},
|
||||
{
|
||||
"value": "useOpenGL",
|
||||
// Warning: the default must be the same as the one in preinitQt().
|
||||
"display_name": "Use OpenGL",
|
||||
"help": "Controls display method.",
|
||||
"default": false,
|
||||
"platforms": [ "windows" ]
|
||||
},
|
||||
@ -92,7 +98,6 @@
|
||||
"default": [
|
||||
{
|
||||
"value": true,
|
||||
// MMAL works just fine
|
||||
"platforms": [ "oe" ]
|
||||
},
|
||||
{
|
||||
@ -103,6 +108,8 @@
|
||||
},
|
||||
{
|
||||
"value": "forceFSScreen",
|
||||
"display_name": "Force Full Screen Display",
|
||||
"help": "Forces fullscreen to use a specific display.",
|
||||
"platforms_excluded": [ "oe" ],
|
||||
"default": ""
|
||||
},
|
||||
@ -118,10 +125,14 @@
|
||||
},
|
||||
{
|
||||
"value": "checkForUpdates",
|
||||
"display_name": "Check For Updates",
|
||||
"help": "Allows user to disable update check plugin script.",
|
||||
"default": true
|
||||
},
|
||||
{
|
||||
"value": "enableInputRepeat",
|
||||
"display_name": "Enable Input Repeat",
|
||||
"help": "Allows disabling repeating of control inputs.",
|
||||
"default": true
|
||||
},
|
||||
{
|
||||
@ -131,11 +142,15 @@
|
||||
},
|
||||
{
|
||||
"value": "autodetectCertBundle",
|
||||
"display_name": "Auto-Detect Certificate Bundle",
|
||||
"help": "Allows use of system certificates for TLS.",
|
||||
"default": false,
|
||||
"platforms": [ "linux" ]
|
||||
},
|
||||
{
|
||||
"value": "forceExternalWebclient",
|
||||
"display_name": "Force External Web Client",
|
||||
"help": "Allows the user to connect to external webclients even if the bundled one is available.\nThis has not landed in a released version yet.",
|
||||
"default": false
|
||||
},
|
||||
{
|
||||
@ -145,11 +160,13 @@
|
||||
},
|
||||
{
|
||||
"value": "enableWindowsMediaIntegration",
|
||||
"display_name": "Enable Windows Media Integration",
|
||||
"default": true,
|
||||
"platforms": [ "windows" ]
|
||||
},
|
||||
{
|
||||
"value": "enableWindowsTaskbarIntegration",
|
||||
"display_name": "Enable Windows Taskbar Integration",
|
||||
"default": true,
|
||||
"platforms": [ "windows" ]
|
||||
}
|
||||
@ -157,31 +174,41 @@
|
||||
},
|
||||
{
|
||||
"section": "plugins",
|
||||
"order": 5,
|
||||
"values": [
|
||||
{
|
||||
"value": "skipintro",
|
||||
"display_name": "Skip Intro",
|
||||
"help": "Enables a built-in skip intro plugin based off of ConfusedPolarBear's Intro-Skipper plugin (https://github.com/ConfusedPolarBear/intro-skipper).",
|
||||
"default": false
|
||||
},
|
||||
{
|
||||
"value": "jellyscrub",
|
||||
"display_name": "Jellyscrub",
|
||||
"help": "Enables a built-in thumbnail scrubber plugin based off of nicksny's Jellyscrub (https://github.com/nicknsy/jellyscrub).",
|
||||
"default": false
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"section": "audio",
|
||||
"order": 2,
|
||||
"values": [
|
||||
{
|
||||
"value": "devicetype",
|
||||
"display_name": "Device Type",
|
||||
"help": "Sets the device type. Can be \"Basic\", \"S/PDIF\", or \"HDMI\".\n\n- Basic: disables passthrough.\n- S/PDIF: transcodes surround sound to specific formats.\n- HDMI: supports additional passthrough options.",
|
||||
"default": "basic",
|
||||
"possible_values": [
|
||||
[ "basic", "audio.basic" ],
|
||||
[ "spdif", "audio.spdif" ],
|
||||
[ "hdmi", "audio.hdmi" ]
|
||||
[ "basic", "Basic" ],
|
||||
[ "spdif", "S/PDIF" ],
|
||||
[ "hdmi", "HDMI" ]
|
||||
]
|
||||
},
|
||||
{
|
||||
"value": "channels",
|
||||
"display_name": "Channels",
|
||||
"help": "Sets how many audio channels are allowed. The default is \"Stereo\" except on MacOS where it is \"Auto\".\n\n- Auto: automatically set.\n- Stereo: 2 channel stereo.\n- 5.1 Surround Sound: up to 5.1 surround sound.\n- 7.1 Surround Sound: up to 7.1 surround sound.",
|
||||
"default": [
|
||||
{
|
||||
"value": "auto",
|
||||
@ -192,45 +219,61 @@
|
||||
}
|
||||
],
|
||||
"possible_values": [
|
||||
[ "auto", "audio.auto" ],
|
||||
[ "2.0", "audio.stereo" ],
|
||||
[ "5.1,2.0", "audio.51" ],
|
||||
[ "7.1,5.1,2.0", "audio.71" ]
|
||||
[ "auto", "Auto" ],
|
||||
[ "2.0", "Stereo" ],
|
||||
[ "5.1,2.0", "5.1 Surround Sound" ],
|
||||
[ "7.1,5.1,2.0", "7.1 Surround Sound" ]
|
||||
]
|
||||
},
|
||||
{
|
||||
"value": "device",
|
||||
"display_name": "Device",
|
||||
"help": "Allows forcing media output to a specific device. The default is \"Auto\".",
|
||||
"default": "auto"
|
||||
},
|
||||
{
|
||||
"value": "normalize",
|
||||
"display_name": "Normalize",
|
||||
"help": "Enable audio volume normalization.",
|
||||
"default": true
|
||||
},
|
||||
{
|
||||
"value": "exclusive",
|
||||
"display_name": "Exclusive",
|
||||
"help": "Takes exclusive control of audio device. The default is disabled.",
|
||||
"default": false,
|
||||
"platforms": [ "osx", "windows" ]
|
||||
},
|
||||
{
|
||||
"value": "passthrough.ac3",
|
||||
"display_name": "AC3 Passthrough",
|
||||
"help": "Enables AC3 passthrough. Requires \"S/PDIF\", or \"HDMI\" device type. The default is disabled.",
|
||||
"default": false
|
||||
},
|
||||
{
|
||||
"value": "passthrough.dts",
|
||||
"display_name": "DTS Passthrough",
|
||||
"help": "Enables DTS passthrough. Requires \"S/PDIF\", or \"HDMI\" device type. The default is disabled.",
|
||||
"default": false
|
||||
},
|
||||
{
|
||||
"value": "passthrough.eac3",
|
||||
"display_name": "E-AC3 Passthrough",
|
||||
"help": "Enables E-AC3 passthrough. Requires \"HDMI\" device type. The default is disabled.",
|
||||
"default": false,
|
||||
"platforms_excluded": [ "osx", "oe_rpi" ]
|
||||
},
|
||||
{
|
||||
"value": "passthrough.dts-hd",
|
||||
"display_name": "DTS-HD Passthrough",
|
||||
"help": "Enables DTS-HD passthrough. Requires \"HDMI\" device type. The default is disabled.",
|
||||
"default": false,
|
||||
"platforms_excluded": [ "osx", "oe_rpi" ]
|
||||
},
|
||||
{
|
||||
"value": "passthrough.truehd",
|
||||
"display_name": "TrueHD Passthrough",
|
||||
"help": "Enables TrueHD passthrough. Requires \"HDMI\" device type. The default is disabled.",
|
||||
"default": false,
|
||||
"platforms_excluded": [ "osx", "oe_rpi" ]
|
||||
}
|
||||
@ -238,6 +281,7 @@
|
||||
},
|
||||
{
|
||||
"section": "video",
|
||||
"order": 3,
|
||||
"values": [
|
||||
{
|
||||
"value": "debug.force_vo",
|
||||
@ -246,6 +290,8 @@
|
||||
},
|
||||
{
|
||||
"value": "refreshrate.auto_switch",
|
||||
"display_name": "Display Refresh Rate Sync",
|
||||
"help": "Sets the display refresh rate to the media refresh rate. The default is disabled.",
|
||||
"default": false
|
||||
},
|
||||
{
|
||||
@ -260,64 +306,81 @@
|
||||
},
|
||||
{
|
||||
"value": "hardwareDecoding",
|
||||
"display_name": "Hardware Decoding",
|
||||
"help": "Sets the hardware decoding method. The default is \"copy\"\n\n- Enabled: full hardware acceleration. Removes MPV shader pipelines. Can cause issues more often.\n- Copy: uses hardware decoding but copies the video through MPV's shader pipelines.\n- Disabled: completely disable hardware decoding. Use this if video is glitchy.",
|
||||
"default": "copy",
|
||||
"possible_values": [
|
||||
[ "enabled", "video.decode.enabled", { "platforms_excluded": "osx" } ],
|
||||
[ "enabled", "video.decode.enabled.modern", { "platforms": "osx" } ],
|
||||
[ "osx_compat", "video.decode.enabled.old", { "platforms": "osx" } ],
|
||||
[ "copy", "video.decode.copy" ],
|
||||
[ "disabled", "video.decode.disabled" ]
|
||||
[ "enabled", "Enabled", { "platforms_excluded": "osx" } ],
|
||||
[ "enabled", "Enabled (Modern)", { "platforms": "osx" } ],
|
||||
[ "osx_compat", "Enabled (Old)", { "platforms": "osx" } ],
|
||||
[ "copy", "Copy" ],
|
||||
[ "disabled", "Disabled" ]
|
||||
],
|
||||
"platforms_excluded": "oe_rpi"
|
||||
},
|
||||
{
|
||||
"value": "deinterlace",
|
||||
"display_name": "Deinterlace",
|
||||
"help": "Enables deinterlacing. The default is disabled.",
|
||||
"default": false,
|
||||
"platforms_excluded": "oe_rpi"
|
||||
},
|
||||
{
|
||||
"value": "allow_transcode_to_hevc",
|
||||
"default": false
|
||||
},
|
||||
{
|
||||
"value": "force_transcode_hdr",
|
||||
"default": false
|
||||
},
|
||||
{
|
||||
"value": "prefer_transcode_to_h265",
|
||||
"display_name": "Prefer Transcode to H.265",
|
||||
"default": false
|
||||
},
|
||||
{
|
||||
"value": "force_transcode_hi10p",
|
||||
"value": "allow_transcode_to_hevc",
|
||||
"display_name": "Allow Transcode to HEVC",
|
||||
"help": "If set, it allows transcoding to \"HEVC\" in the video profile. The default is false.\n\nThis is mostly added as a workaround for Dolby Vision content direct playing when it shouldn't.",
|
||||
"default": false
|
||||
},
|
||||
{
|
||||
"value": "force_transcode_hevc",
|
||||
"default": false
|
||||
},
|
||||
{
|
||||
"value": "force_transcode_av1",
|
||||
"display_name": "Force Transcode HEVC",
|
||||
"default": false
|
||||
},
|
||||
{
|
||||
"value": "force_transcode_4k",
|
||||
"display_name": "Force Transcode 4K",
|
||||
"default": false
|
||||
},
|
||||
{
|
||||
"value": "always_force_transcode",
|
||||
"value": "force_transcode_av1",
|
||||
"display_name": "Force Transcode AV1",
|
||||
"default": false
|
||||
},
|
||||
{
|
||||
"value": "force_transcode_hdr",
|
||||
"display_name": "Force Transcode HDR",
|
||||
"help": "If set, HDR media support is dropped from the video profile. The default is false.",
|
||||
"default": false
|
||||
},
|
||||
{
|
||||
"value": "force_transcode_hi10p",
|
||||
"display_name": "Force Transcode Hi10P",
|
||||
"default": false
|
||||
},
|
||||
{
|
||||
"value": "force_transcode_dovi",
|
||||
"display_name": "Force Transcode Dolby Vision",
|
||||
"default": true
|
||||
},
|
||||
{
|
||||
"value": "always_force_transcode",
|
||||
"display_name": "Always Force Transcode",
|
||||
"default": false
|
||||
},
|
||||
{
|
||||
"value": "sync_mode",
|
||||
"display_name": "AV Sync Mode",
|
||||
"help": "How the player synchronizes audio and video.\n\nIf you use this option, you usually want to set it to display-resample to enable a timing mode that tries to not skip or repeat frames when for example playing 24fps video on a 24Hz screen.\n\n- Audio: time video frames to audio. This is the most robust mode, because the player doesn't have to assume anything about how the display behaves. The disadvantage is that it can lead to occasional frame drops or repeats. If audio is disabled, this uses the system clock. This is the default mode.\n\n- Resample: resample audio to match the video. This mode will also try to adjust audio speed to compensate for other drift. (This means it will play the audio at a different speed every once in a while to reduce the A/V difference.)\n\n- Audio Drop: drop or repeat audio data to compensate desyncing video. This mode will cause severe audio artifacts if the real monitor refresh rate is too different from the reported or forced rate. Since mpv 0.33.0, this acts on entire audio frames, instead of single samples.",
|
||||
"default": "audio",
|
||||
"possible_values": [
|
||||
[ "audio", "video.sync.audio" ],
|
||||
[ "display-resample", "video.sync.resample" ],
|
||||
[ "display-adrop", "video.sync.adrop" ]
|
||||
[ "audio", "Audio" ],
|
||||
[ "display-resample", "Resample" ],
|
||||
[ "display-adrop", "Audio Drop" ]
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -362,30 +425,34 @@
|
||||
},
|
||||
{
|
||||
"value": "cache",
|
||||
"display_name": "Cache Size",
|
||||
"help": "Controls cache size in MB for video streaming. The default is 75 MB",
|
||||
"default": 75,
|
||||
"possible_values": [
|
||||
[ 10, "video.cache.tiny" ],
|
||||
[ 75, "video.cache.default" ],
|
||||
[ 150, "video.cache.large", { "platforms_excluded": "oe_rpi" } ],
|
||||
[ 500, "video.cache.vlarge", { "platforms_excluded": "oe_rpi" } ]
|
||||
[ 10, "Tiny (10 MB)" ],
|
||||
[ 75, "Default (75 MB)" ],
|
||||
[ 150, "Large (150 MB)", { "platforms_excluded": "oe_rpi" } ],
|
||||
[ 500, "Very Large (500 MB)", { "platforms_excluded": "oe_rpi" } ]
|
||||
]
|
||||
},
|
||||
{
|
||||
"value": "aspect",
|
||||
"display_name": "Aspect Ratio",
|
||||
"default": "normal",
|
||||
"possible_values": [
|
||||
[ "normal", "video.aspect.normal" ],
|
||||
[ "zoom", "video.aspect.zoom" ],
|
||||
[ "force_4_3", "video.aspect.force43" ],
|
||||
[ "force_16_9", "video.aspect.force169" ],
|
||||
[ "force_16_9_if_4_3", "video.aspect.force169if43" ],
|
||||
[ "stretch", "video.aspect.stretch" ],
|
||||
[ "noscaling", "video.aspect.noscale" ],
|
||||
[ "custom", "video.aspect.custom" ]
|
||||
[ "custom", "Default" ],
|
||||
[ "normal", "Normal" ],
|
||||
[ "zoom", "Zoom" ],
|
||||
[ "force_4_3", "Force 4:3" ],
|
||||
[ "force_16_9", "Force 16:9" ],
|
||||
[ "force_16_9_if_4_3", "Force 16:9 if 4:3" ],
|
||||
[ "stretch", "Stretch" ],
|
||||
[ "noscaling", "No Scale" ]
|
||||
]
|
||||
},
|
||||
{
|
||||
"value": "default_playback_speed",
|
||||
"display_name": "Default Playback Speed",
|
||||
"default": 1.0,
|
||||
"possible_values": [
|
||||
[ 0.5, "0.5x" ],
|
||||
@ -401,123 +468,140 @@
|
||||
},
|
||||
{
|
||||
"section": "subtitles",
|
||||
"order": 4,
|
||||
"values": [
|
||||
{
|
||||
"value": "ass_scale_border_and_shadow",
|
||||
"display_name": "ASS Scale Border and Shadow",
|
||||
"help": "For ASS format subtitles, ensures that the text borders and shadows scale proportionally with the resolution.",
|
||||
"default": true
|
||||
},
|
||||
{
|
||||
"value": "ass_style_override",
|
||||
"display_name": "ASS Style Override",
|
||||
"help": "Control whether user style overrides should be applied. Note that all of these overrides try to be somewhat smart about figuring out whether or not a subtitle is considered a \"sign\".\n\nNo: Render subtitles as specified by the subtitle scripts, without overrides.\nYes: Apply all the --sub-ass-* style override options. Changing the default for any of these options can lead to incorrect subtitle rendering (default).\nForce: Like yes, but also force all --sub-* options. Can break rendering easily.\nScale: Like yes, but also apply --sub-scale.\nStrip: Radically strip all ASS tags and styles from the subtitle. This is equivalent to the old --no-ass / --no-sub-ass options.\n\nThis also controls some bitmap subtitle overrides, as well as HTML tags in formats like SRT, despite the name of the option.",
|
||||
"default": "",
|
||||
"possible_values": [
|
||||
[ "", "subtitles.default" ],
|
||||
[ "yes", "subtitles.yes" ],
|
||||
[ "no", "subtitles.no" ],
|
||||
[ "force", "subtitles.force" ],
|
||||
[ "scale", "subtitles.scale" ],
|
||||
[ "strip", "subtitles.strip" ]
|
||||
[ "", "Default" ],
|
||||
[ "yes", "Yes" ],
|
||||
[ "no", "No" ],
|
||||
[ "force", "Force" ],
|
||||
[ "scale", "Scale" ],
|
||||
[ "strip", "Strip" ]
|
||||
]
|
||||
},
|
||||
{
|
||||
"value": "placement",
|
||||
"display_name": "Placement",
|
||||
"default": "",
|
||||
"possible_values": [
|
||||
[ "", "subtitles.default" ],
|
||||
[ "left,bottom", "subtitles.leftBottom" ],
|
||||
[ "right,bottom", "subtitles.rightBottom" ],
|
||||
[ "center,bottom", "subtitles.centerBottom" ],
|
||||
[ "left,top", "subtitles.leftTop" ],
|
||||
[ "right,top", "subtitles.rightTop" ],
|
||||
[ "center,top", "subtitles.centerTop" ]
|
||||
[ "", "Default" ],
|
||||
[ "left,bottom", "Left, Bottom" ],
|
||||
[ "right,bottom", "Right, Bottom" ],
|
||||
[ "center,bottom", "Center, Bottom" ],
|
||||
[ "left,top", "Left, Top" ],
|
||||
[ "right,top", "Right, Top" ],
|
||||
[ "center,top", "Center, Top" ]
|
||||
]
|
||||
},
|
||||
{
|
||||
"value": "color",
|
||||
"display_name": "Color",
|
||||
"default": "",
|
||||
"possible_values": [
|
||||
[ "", "subtitles.default" ],
|
||||
[ "#000000", "subtitles.black" ],
|
||||
[ "#FFFFFF", "subtitles.white" ],
|
||||
[ "#EEEEEE", "subtitles.lightGrey" ],
|
||||
[ "#CCCCCC", "subtitles.blendedLightGrey" ],
|
||||
[ "#FBF93E", "subtitles.yellow" ],
|
||||
[ "#FFFFCC", "subtitles.lightYellow" ],
|
||||
[ "#EEEDB8", "subtitles.blendedLightYellow" ]
|
||||
[ "", "Default" ],
|
||||
[ "#000000", "Black" ],
|
||||
[ "#FFFFFF", "White" ],
|
||||
[ "#EEEEEE", "Light Grey" ],
|
||||
[ "#CCCCCC", "Blended Light Grey" ],
|
||||
[ "#FBF93E", "Yellow" ],
|
||||
[ "#FFFFCC", "Light Yellow" ],
|
||||
[ "#EEEDB8", "Blended Light Yellow" ]
|
||||
]
|
||||
},
|
||||
{
|
||||
"value": "border_color",
|
||||
"display_name": "Border Color",
|
||||
"default": "",
|
||||
"possible_values": [
|
||||
[ "", "subtitles.default" ],
|
||||
[ "#000000", "subtitles.black" ],
|
||||
[ "#FFFFFF", "subtitles.white" ],
|
||||
[ "#EEEEEE", "subtitles.lightGrey" ],
|
||||
[ "#CCCCCC", "subtitles.blendedLightGrey" ],
|
||||
[ "#FBF93E", "subtitles.yellow" ],
|
||||
[ "#FFFFCC", "subtitles.lightYellow" ],
|
||||
[ "#EEEDB8", "subtitles.blendedLightYellow" ]
|
||||
[ "", "Default" ],
|
||||
[ "#000000", "Black" ],
|
||||
[ "#FFFFFF", "White" ],
|
||||
[ "#EEEEEE", "Light Grey" ],
|
||||
[ "#CCCCCC", "Blended Light Grey" ],
|
||||
[ "#FBF93E", "Yellow" ],
|
||||
[ "#FFFFCC", "Light Yellow" ],
|
||||
[ "#EEEDB8", "Blended Light Yellow" ]
|
||||
]
|
||||
},
|
||||
{
|
||||
"value": "border_size",
|
||||
"display_name": "Border Size",
|
||||
"default": -1,
|
||||
"possible_values": [
|
||||
[ -1, "subtitles.default" ],
|
||||
[ 0, "subtitles.none" ],
|
||||
[ 1, "subtitles.tiny" ],
|
||||
[ 2, "subtitles.small" ],
|
||||
[ 3, "subtitles.normal" ],
|
||||
[ 4, "subtitles.large" ],
|
||||
[ 5, "subtitles.huge" ]
|
||||
[ -1, "Default" ],
|
||||
[ 0, "None" ],
|
||||
[ 1, "Tiny" ],
|
||||
[ 2, "Small" ],
|
||||
[ 3, "Normal" ],
|
||||
[ 4, "Large" ],
|
||||
[ 5, "Huge" ]
|
||||
]
|
||||
},
|
||||
{
|
||||
"value": "background_color",
|
||||
"display_name": "Background Color",
|
||||
"default": "",
|
||||
"possible_values": [
|
||||
[ "", "subtitles.default" ],
|
||||
[ "#000000", "subtitles.black" ],
|
||||
[ "#FFFFFF", "subtitles.white" ],
|
||||
[ "#EEEEEE", "subtitles.lightGrey" ],
|
||||
[ "#CCCCCC", "subtitles.blendedLightGrey" ],
|
||||
[ "#FBF93E", "subtitles.yellow" ],
|
||||
[ "#FFFFCC", "subtitles.lightYellow" ],
|
||||
[ "#EEEDB8", "subtitles.blendedLightYellow" ]
|
||||
[ "", "Default" ],
|
||||
[ "#000000", "Black" ],
|
||||
[ "#FFFFFF", "White" ],
|
||||
[ "#EEEEEE", "Light Grey" ],
|
||||
[ "#CCCCCC", "Blended Light Grey" ],
|
||||
[ "#FBF93E", "Yellow" ],
|
||||
[ "#FFFFCC", "Light Yellow" ],
|
||||
[ "#EEEDB8", "Blended Light Yellow" ]
|
||||
]
|
||||
},
|
||||
{
|
||||
"value": "background_transparency",
|
||||
"display_name": "Background Transparency",
|
||||
"default": "",
|
||||
"possible_values": [
|
||||
[ "", "subtitles.default" ],
|
||||
[ "FF", "subtitles.0%" ],
|
||||
[ "C0", "subtitles.25%" ],
|
||||
[ "80", "subtitles.50%" ],
|
||||
[ "40", "subtitles.75%" ],
|
||||
[ "00", "subtitles.100%" ]
|
||||
[ "", "Default" ],
|
||||
[ "FF", "0%" ],
|
||||
[ "C0", "25%" ],
|
||||
[ "80", "50%" ],
|
||||
[ "40", "75%" ],
|
||||
[ "00", "100%" ]
|
||||
]
|
||||
},
|
||||
{
|
||||
"value": "size",
|
||||
"display_name": "Size",
|
||||
"default": -1,
|
||||
"possible_values": [
|
||||
[ -1, "subtitles.default" ],
|
||||
[ 18, "subtitles.tiny" ],
|
||||
[ 24, "subtitles.small" ],
|
||||
[ 32, "subtitles.normal" ],
|
||||
[ 42, "subtitles.large" ],
|
||||
[ 60, "subtitles.huge" ]
|
||||
[ -1, "Default" ],
|
||||
[ 18, "Tiny" ],
|
||||
[ 24, "Small" ],
|
||||
[ 32, "Normal" ],
|
||||
[ 42, "Large" ],
|
||||
[ 60, "Huge" ]
|
||||
]
|
||||
},
|
||||
{
|
||||
"value": "font",
|
||||
"display_name": "Font",
|
||||
"default": "sans-serif",
|
||||
"possible_values": [
|
||||
[ "", "subtitles.default" ],
|
||||
[ "serif", "serif" ],
|
||||
[ "sans-serif", "sans-serif" ],
|
||||
[ "script", "script" ],
|
||||
[ "monospace", "monospace" ],
|
||||
[ "display", "display" ],
|
||||
[ "cursive", "cursive" ],
|
||||
[ "fantasy", "fantasy" ]
|
||||
[ "", "Default" ],
|
||||
[ "serif", "Serif" ],
|
||||
[ "sans-serif", "Sans-Serif" ],
|
||||
[ "script", "Script" ],
|
||||
[ "monospace", "Monospace" ],
|
||||
[ "display", "Display" ],
|
||||
[ "cursive", "Cursive" ],
|
||||
[ "fantasy", "Fantasy" ]
|
||||
]
|
||||
}
|
||||
]
|
||||
@ -606,5 +690,18 @@
|
||||
"platforms": [ "oe" ]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"section": "other",
|
||||
"order": 6,
|
||||
"values": [
|
||||
{
|
||||
"value": "other_conf",
|
||||
"display_name": "Manual MPV Configuration",
|
||||
"help": "Configuration must be supplied in the same format as mpv.conf, with each configuration on a new line. i.e. \"sub-border-size=5\". Removing all set values of a configuration, from both here and the settings above, will only restore it to default once Jellyfin Media Player has restarted.",
|
||||
"input_type": "textarea",
|
||||
"default": ""
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
|
@ -213,17 +213,21 @@ bool PlayerComponent::componentInitialize()
|
||||
|
||||
updateAudioDeviceList();
|
||||
setAudioConfiguration();
|
||||
updateSubtitleSettings();
|
||||
updateVideoSettings();
|
||||
|
||||
connect(SettingsComponent::Get().getSection(SETTINGS_SECTION_VIDEO), &SettingsSection::valuesUpdated,
|
||||
this, &PlayerComponent::updateVideoSettings);
|
||||
|
||||
connect(SettingsComponent::Get().getSection(SETTINGS_SECTION_SUBTITLES), &SettingsSection::valuesUpdated,
|
||||
this, &PlayerComponent::updateSubtitleSettings);
|
||||
setVideoConfiguration();
|
||||
setSubtitleConfiguration();
|
||||
setOtherConfiguration();
|
||||
|
||||
connect(SettingsComponent::Get().getSection(SETTINGS_SECTION_AUDIO), &SettingsSection::valuesUpdated,
|
||||
this, &PlayerComponent::setAudioConfiguration);
|
||||
this, &PlayerComponent::updateAudioConfiguration);
|
||||
|
||||
connect(SettingsComponent::Get().getSection(SETTINGS_SECTION_VIDEO), &SettingsSection::valuesUpdated,
|
||||
this, &PlayerComponent::updateVideoConfiguration);
|
||||
|
||||
connect(SettingsComponent::Get().getSection(SETTINGS_SECTION_SUBTITLES), &SettingsSection::valuesUpdated,
|
||||
this, &PlayerComponent::updateSubtitleConfiguration);
|
||||
|
||||
connect(SettingsComponent::Get().getSection(SETTINGS_SECTION_OTHER), &SettingsSection::valuesUpdated,
|
||||
this, &PlayerComponent::updateConfiguration);
|
||||
|
||||
initializeCodecSupport();
|
||||
Codecs::initCodecs();
|
||||
@ -309,7 +313,7 @@ void PlayerComponent::queueMedia(const QString& url, const QVariantMap& options,
|
||||
m_mediaFrameRate = metadata["frameRate"].toFloat(); // returns 0 on failure
|
||||
m_serverMediaInfo = metadata["media"].toMap();
|
||||
|
||||
updateVideoSettings();
|
||||
updateVideoConfiguration();
|
||||
|
||||
QUrl qurl = url;
|
||||
QString host = qurl.host();
|
||||
@ -396,7 +400,7 @@ bool PlayerComponent::switchDisplayFrameRate()
|
||||
}
|
||||
|
||||
// Make sure settings dependent on the display refresh rate are updated properly.
|
||||
updateVideoSettings();
|
||||
updateVideoConfiguration();
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -412,7 +416,7 @@ void PlayerComponent::onRestoreDisplay()
|
||||
void PlayerComponent::onRefreshRateChange()
|
||||
{
|
||||
// Make sure settings dependent on the display refresh rate are updated properly.
|
||||
updateVideoSettings();
|
||||
updateVideoConfiguration();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
@ -1053,6 +1057,13 @@ void PlayerComponent::updateAudioDevice()
|
||||
mpv::qt::set_property(m_mpv, "audio-device", device);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
void PlayerComponent::updateAudioConfiguration()
|
||||
{
|
||||
setAudioConfiguration();
|
||||
setOtherConfiguration();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
void PlayerComponent::setAudioConfiguration()
|
||||
{
|
||||
@ -1137,8 +1148,18 @@ void PlayerComponent::setAudioConfiguration()
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
void PlayerComponent::updateSubtitleSettings()
|
||||
void PlayerComponent::updateSubtitleConfiguration()
|
||||
{
|
||||
setSubtitleConfiguration();
|
||||
setOtherConfiguration();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
void PlayerComponent::setSubtitleConfiguration()
|
||||
{
|
||||
bool assScaleBorderAndShadow = SettingsComponent::Get().value(SETTINGS_SECTION_SUBTITLES, "ass_scale_border_and_shadow").toBool();
|
||||
mpv::qt::set_property(m_mpv, "sub-ass-style-overrides", assScaleBorderAndShadow ? "ScaledBorderAndShadow=yes" : "ScaledBorderAndShadow=no");
|
||||
|
||||
QString assStyleOverride = SettingsComponent::Get().value(SETTINGS_SECTION_SUBTITLES, "ass_style_override").toString();
|
||||
if (!assStyleOverride.isEmpty())
|
||||
{
|
||||
@ -1169,10 +1190,10 @@ void PlayerComponent::updateSubtitleSettings()
|
||||
mpv::qt::set_property(m_mpv, "sub-border-color", borderColor);
|
||||
}
|
||||
|
||||
QString borderSize = SettingsComponent::Get().value(SETTINGS_SECTION_SUBTITLES, "border_size").toString();
|
||||
QVariant borderSize = SettingsComponent::Get().value(SETTINGS_SECTION_SUBTITLES, "border_size");
|
||||
if (borderSize != -1)
|
||||
{
|
||||
mpv::qt::set_property(m_mpv, "sub-border-size", borderSize);
|
||||
mpv::qt::set_property(m_mpv, "sub-border-size", borderSize.toInt());
|
||||
}
|
||||
|
||||
QString backgroundColor = SettingsComponent::Get().value(SETTINGS_SECTION_SUBTITLES, "background_color").toString();
|
||||
@ -1241,7 +1262,14 @@ void PlayerComponent::updateVideoAspectSettings()
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
void PlayerComponent::updateVideoSettings()
|
||||
void PlayerComponent::updateVideoConfiguration()
|
||||
{
|
||||
setVideoConfiguration();
|
||||
setOtherConfiguration();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
void PlayerComponent::setVideoConfiguration()
|
||||
{
|
||||
if (!m_mpv)
|
||||
return;
|
||||
@ -1280,6 +1308,37 @@ void PlayerComponent::updateVideoSettings()
|
||||
mpv::qt::set_property(m_mpv, "cache", cache.toInt() * 1024);
|
||||
|
||||
updateVideoAspectSettings();
|
||||
setOtherConfiguration();
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
void PlayerComponent::setOtherConfiguration()
|
||||
{
|
||||
QString otherConfiguration = SettingsComponent::Get().value(SETTINGS_SECTION_OTHER, "other_conf").toString();
|
||||
qDebug() << "Parsing other configuration: "+otherConfiguration;
|
||||
QStringList configurationList = otherConfiguration.split(QRegExp("[\r\n]"), Qt::SkipEmptyParts);
|
||||
|
||||
for(const QString& configuration : configurationList)
|
||||
{
|
||||
int splitIndex = configuration.indexOf("=");
|
||||
int configurationLength = configuration.length();
|
||||
if (splitIndex > 0 && splitIndex < configurationLength - 1)
|
||||
{
|
||||
QString configurationKey = configuration.left(splitIndex).remove(QRegExp("^([\"]+)")).remove(QRegExp("([\"]+)$"));
|
||||
QString configurationValue = configuration.right(configurationLength - splitIndex - 1).remove(QRegExp("^([\"]+)")).remove(QRegExp("([\"]+)$"));
|
||||
mpv::qt::set_property(m_mpv, configurationKey, configurationValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
void PlayerComponent::updateConfiguration()
|
||||
{
|
||||
setAudioConfiguration();
|
||||
setVideoConfiguration();
|
||||
setSubtitleConfiguration();
|
||||
setOtherConfiguration();
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -148,10 +148,15 @@ public:
|
||||
};
|
||||
|
||||
public Q_SLOTS:
|
||||
void setAudioConfiguration();
|
||||
void updateAudioDeviceList();
|
||||
void updateSubtitleSettings();
|
||||
void updateVideoSettings();
|
||||
void setAudioConfiguration();
|
||||
void setSubtitleConfiguration();
|
||||
void setVideoConfiguration();
|
||||
void setOtherConfiguration();
|
||||
void updateAudioConfiguration();
|
||||
void updateSubtitleConfiguration();
|
||||
void updateVideoConfiguration();
|
||||
void updateConfiguration();
|
||||
|
||||
private Q_SLOTS:
|
||||
void handleMpvEvents();
|
||||
|
@ -163,6 +163,20 @@ QVariant SettingsComponent::allValues(const QString& section)
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
QVariant SettingsComponent::orderedSections()
|
||||
{
|
||||
QJsonArray desc;
|
||||
|
||||
for(SettingsSection* section : m_sections.values())
|
||||
{
|
||||
if (!section->isHidden())
|
||||
desc.push_back(QJsonValue::fromVariant(section->sectionOrder()));
|
||||
}
|
||||
|
||||
return desc.toVariantList();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
static void writeFile(const QString& filename, const QByteArray& data)
|
||||
{
|
||||
@ -486,8 +500,6 @@ bool SettingsComponent::loadDescription()
|
||||
return false;
|
||||
}
|
||||
|
||||
m_sectionIndex = 0;
|
||||
|
||||
for(auto val : doc.array())
|
||||
{
|
||||
if (!val.isObject())
|
||||
@ -523,8 +535,9 @@ void SettingsComponent::parseSection(const QJsonObject& sectionObject)
|
||||
}
|
||||
|
||||
int platformMask = platformMaskFromObject(sectionObject);
|
||||
int sectionOrder = sectionObject.value("order").toInt(-1);
|
||||
|
||||
auto section = new SettingsSection(sectionName, (quint8)platformMask, m_sectionIndex ++, this);
|
||||
auto section = new SettingsSection(sectionName, (quint8)platformMask, sectionOrder, this);
|
||||
section->setHidden(sectionObject.value("hidden").toBool(false));
|
||||
section->setStorage(sectionObject.value("storage").toBool(false));
|
||||
|
||||
@ -559,6 +572,13 @@ void SettingsComponent::parseSection(const QJsonObject& sectionObject)
|
||||
|
||||
int vPlatformMask = platformMaskFromObject(valobj);
|
||||
SettingsValue* setting = new SettingsValue(valobj.value("value").toString(), defaultval, (quint8)vPlatformMask, this);
|
||||
|
||||
if (valobj.contains("display_name"))
|
||||
setting->setDisplayName(valobj.value("display_name").toString());
|
||||
|
||||
if (valobj.contains("help"))
|
||||
setting->setHelp(valobj.value("help").toString());
|
||||
|
||||
setting->setHasDescription(true);
|
||||
setting->setHidden(valobj.value("hidden").toBool(false));
|
||||
setting->setIndexOrder(order ++);
|
||||
|
@ -17,6 +17,7 @@
|
||||
#define SETTINGS_SECTION_OVERRIDES "overrides"
|
||||
#define SETTINGS_SECTION_CEC "cec"
|
||||
#define SETTINGS_SECTION_APPLEREMOTE "appleremote"
|
||||
#define SETTINGS_SECTION_OTHER "other"
|
||||
|
||||
#define AUDIO_DEVICE_TYPE_BASIC "basic"
|
||||
#define AUDIO_DEVICE_TYPE_SPDIF "spdif"
|
||||
@ -49,6 +50,7 @@ public:
|
||||
Q_INVOKABLE void setValue(const QString& sectionID, const QString& key, const QVariant& value);
|
||||
Q_INVOKABLE void setValues(const QVariantMap& options);
|
||||
Q_INVOKABLE QVariant value(const QString& sectionID, const QString& key);
|
||||
Q_INVOKABLE QVariant orderedSections();
|
||||
Q_INVOKABLE QVariant allValues(const QString& section = "");
|
||||
// Note: the naming "remove" is a lie - it will remove the affected keys only if they are not
|
||||
// declared in settings_descriptions.json. Also, sections are never removed, even if they
|
||||
|
@ -201,6 +201,17 @@ const QVariantMap SettingsSection::descriptions() const
|
||||
return map;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
const QVariantMap SettingsSection::sectionOrder() const
|
||||
{
|
||||
QVariantMap map;
|
||||
|
||||
map.insert("key", m_sectionID);
|
||||
map.insert("order", m_orderIndex);
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
bool SettingsSection::isHidden() const
|
||||
{
|
||||
|
@ -31,6 +31,7 @@ public:
|
||||
|
||||
const QVariantMap allValues() const;
|
||||
const QVariantMap descriptions() const;
|
||||
const QVariantMap sectionOrder() const;
|
||||
|
||||
bool isValueHidden(const QString& key) const { return m_values[key]->isHidden(); }
|
||||
int orderIndex() const { return m_orderIndex; }
|
||||
|
@ -34,6 +34,20 @@ public:
|
||||
|
||||
const QString& key() const { return m_key; }
|
||||
|
||||
const QString& displayName() const { return m_displayName; }
|
||||
|
||||
void setDisplayName(const QString& displayName)
|
||||
{
|
||||
m_displayName = displayName;
|
||||
}
|
||||
|
||||
const QString& help() const { return m_help; }
|
||||
|
||||
void setHelp(const QString& help)
|
||||
{
|
||||
m_help = help;
|
||||
}
|
||||
|
||||
const QVariant& value() const
|
||||
{
|
||||
if (!m_value.isValid())
|
||||
@ -104,12 +118,14 @@ public:
|
||||
{
|
||||
QVariantMap ret;
|
||||
ret.insert("key", m_key);
|
||||
ret.insert("displayName", m_displayName);
|
||||
ret.insert("help", m_help);
|
||||
|
||||
if (!m_possibleValues.isEmpty())
|
||||
ret.insert("options", m_possibleValues);
|
||||
|
||||
if (m_inputType.size())
|
||||
ret.insert("input_type", m_inputType);
|
||||
ret.insert("inputType", m_inputType);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@ -130,6 +146,8 @@ public:
|
||||
|
||||
private:
|
||||
QString m_key;
|
||||
QString m_displayName;
|
||||
QString m_help;
|
||||
QVariant m_value;
|
||||
QVariant m_defaultValue;
|
||||
QVariantList m_possibleValues;
|
||||
|
@ -350,6 +350,7 @@ QString SystemComponent::getNativeShellScript()
|
||||
QVariantMap settingMap = setting.toMap();
|
||||
settingsDescriptions.insert(settingMap["key"].toString(), settingMap["settings"]);
|
||||
}
|
||||
clientData.insert("sections", QJsonValue::fromVariant(SettingsComponent::Get().orderedSections()));
|
||||
clientData.insert("settingsDescriptions", QJsonValue::fromVariant(settingsDescriptions));
|
||||
clientData.insert("settings", QJsonValue::fromVariant(SettingsComponent::Get().allValues()));
|
||||
nativeshellString.replace("@@data@@", QJsonDocument(clientData).toJson(QJsonDocument::Compact).toBase64());
|
||||
|
Loading…
Reference in New Issue
Block a user