Show/Hide config options based on platform and added vaapi config options to UI

This commit is contained in:
loki
2021-06-09 20:40:17 +02:00
parent 17d3fcf0d0
commit 33fbd5f431
2 changed files with 145 additions and 85 deletions
+2 -1
View File
@@ -103,7 +103,8 @@
# #
# You can find the name of the audio sink using the following command: # You can find the name of the audio sink using the following command:
# !! Linux only !! # !! Linux only !!
# pacmd list-sinks | grep "name:" # pacmd list-sinks | grep "name:" if running vanilla pulseaudio
# pactl info | grep Source` if running pipewire
# audio_sink = alsa_output.pci-0000_09_00.3.analog-stereo # audio_sink = alsa_output.pci-0000_09_00.3.analog-stereo
# #
# !! Windows only !! # !! Windows only !!
+141 -82
View File
@@ -13,14 +13,15 @@
<!--Sunshine Name--> <!--Sunshine Name-->
<div class="mb-3"> <div class="mb-3">
<label for="sunshine_name" class="form-label">Sunshine Name</label> <label for="sunshine_name" class="form-label">Sunshine Name</label>
<input type="text" class="form-control" id="sunshine_name" placeholder="Sunshine" v-model="config.sunshine_name"> <input type="text" class="form-control" id="sunshine_name" placeholder="Sunshine"
v-model="config.sunshine_name">
<div class="form-text">The name displayed by Moonlight. If not specified, the PC's hostname is used <div class="form-text">The name displayed by Moonlight. If not specified, the PC's hostname is used
</div> </div>
</div> </div>
<!--Log Level--> <!--Log Level-->
<div class="mb-3"> <div class="mb-3">
<label for="min_log_level" class="form-label">Log Level</label> <label for="min_log_level" class="form-label">Log Level</label>
<select id="min_log_level" class="form-select" v-model="config.min_log_level"> <select id="min_log_level" class="form-select" v-model="config.min_log_level">
<option :value="0">Verbose</option> <option :value="0">Verbose</option>
<option :value="1">Debug</option> <option :value="1">Debug</option>
<option :value="2">Info</option> <option :value="2">Info</option>
@@ -45,13 +46,15 @@
<!--External IP--> <!--External IP-->
<div class="mb-3"> <div class="mb-3">
<label for="external_ip" class="form-label">External IP</label> <label for="external_ip" class="form-label">External IP</label>
<input type="text" class="form-control" id="external_ip" placeholder="123.456.789.12" v-model="config.external_ip"> <input type="text" class="form-control" id="external_ip" placeholder="123.456.789.12"
v-model="config.external_ip">
<div class="form-text">If no external IP address is given, the local IP address is used</div> <div class="form-text">If no external IP address is given, the local IP address is used</div>
</div> </div>
<!--Ping Timeout--> <!--Ping Timeout-->
<div class="mb-3"> <div class="mb-3">
<label for="ping_timeout" class="form-label">Ping Timeout</label> <label for="ping_timeout" class="form-label">Ping Timeout</label>
<input type="text" class="form-control" id="ping_timeout" placeholder="2000" v-model="config.ping_timeout"> <input type="text" class="form-control" id="ping_timeout" placeholder="2000"
v-model="config.ping_timeout">
<div class="form-text">How long to wait in milliseconds for data from moonlight before shutting down the <div class="form-text">How long to wait in milliseconds for data from moonlight before shutting down the
stream</div> stream</div>
</div> </div>
@@ -61,13 +64,16 @@
<div class="resolutions-container"> <div class="resolutions-container">
<label>Resolutions</label> <label>Resolutions</label>
<div class="resolutions d-flex flex-wrap"> <div class="resolutions d-flex flex-wrap">
<div class="p-2 ms-item m-2 d-flex justify-content-between" v-for="(r,i) in resolutions" :key="r"> <div class="p-2 ms-item m-2 d-flex justify-content-between" v-for="(r,i) in resolutions"
:key="r">
<span class="px-2">{{r}}</span> <span class="px-2">{{r}}</span>
<span style="cursor: pointer;" @click="resolutions.splice(i,1)">&times;</span> <span style="cursor: pointer;" @click="resolutions.splice(i,1)">&times;</span>
</div> </div>
<form @submit.prevent="resolutions.push(resIn);resIn = '';" class="d-flex align-items-center"> <form @submit.prevent="resolutions.push(resIn);resIn = '';" class="d-flex align-items-center">
<input type="text" v-model="resIn" required pattern="[0-9]+x[0-9]+" style="border-top-right-radius: 0;border-bottom-right-radius: 0;" class="form-control"> <input type="text" v-model="resIn" required pattern="[0-9]+x[0-9]+"
<button style="border-top-left-radius: 0;border-bottom-left-radius: 0;" class="btn btn-success">+</button> style="border-top-right-radius: 0;border-bottom-right-radius: 0;" class="form-control">
<button style="border-top-left-radius: 0;border-bottom-left-radius: 0;"
class="btn btn-success">+</button>
</form> </form>
</div> </div>
</div> </div>
@@ -80,8 +86,10 @@
</div> </div>
<form @submit.prevent="fps.push(fpsIn);fpsIn = '';" class="d-flex align-items-center"> <form @submit.prevent="fps.push(fpsIn);fpsIn = '';" class="d-flex align-items-center">
<input type="text" v-model="fpsIn" required pattern="[0-9]+" <input type="text" v-model="fpsIn" required pattern="[0-9]+"
style="width: 6ch;border-top-right-radius: 0;border-bottom-right-radius: 0;" class="form-control"> style="width: 6ch;border-top-right-radius: 0;border-bottom-right-radius: 0;"
<button style="border-top-left-radius: 0;border-bottom-left-radius: 0;" class="btn btn-success">+</button> class="form-control">
<button style="border-top-left-radius: 0;border-bottom-left-radius: 0;"
class="btn btn-success">+</button>
</form> </form>
</div> </div>
</div> </div>
@@ -111,13 +119,15 @@
<!--State File--> <!--State File-->
<div class="mb-3"> <div class="mb-3">
<label for="file_state" class="form-label">State File</label> <label for="file_state" class="form-label">State File</label>
<input type="text" class="form-control" id="file_state" placeholder="sunshine_state.json" v-model="config.file_state"> <input type="text" class="form-control" id="file_state" placeholder="sunshine_state.json"
v-model="config.file_state">
<div class="form-text">The file where current state of Sunshine is stored</div> <div class="form-text">The file where current state of Sunshine is stored</div>
</div> </div>
<!--Apps File--> <!--Apps File-->
<div class="mb-3"> <div class="mb-3">
<label for="file_apps" class="form-label">Apps File</label> <label for="file_apps" class="form-label">Apps File</label>
<input type="text" class="form-control" id="file_apps" placeholder="apps.json" v-model="config.file_apps"> <input type="text" class="form-control" id="file_apps" placeholder="apps.json"
v-model="config.file_apps">
<div class="form-text">The file where current apps of Sunshine are stored</div> <div class="form-text">The file where current apps of Sunshine are stored</div>
</div> </div>
</div> </div>
@@ -125,7 +135,8 @@
<!--Back Button Timeout--> <!--Back Button Timeout-->
<div class="mb-3"> <div class="mb-3">
<label for="back_button_timeout" class="form-label">Back Button Timeout</label> <label for="back_button_timeout" class="form-label">Back Button Timeout</label>
<input type="text" class="form-control" id="back_button_timeout" placeholder="2000" v-model="config.back_button_timeout"> <input type="text" class="form-control" id="back_button_timeout" placeholder="2000"
v-model="config.back_button_timeout">
<div class="form-text"> <div class="form-text">
The back/select button on the controller.<br> The back/select button on the controller.<br>
On the Shield, the home and powerbutton are not passed to Moonlight.<br> On the Shield, the home and powerbutton are not passed to Moonlight.<br>
@@ -137,7 +148,8 @@
<!-- Key Repeat Delay--> <!-- Key Repeat Delay-->
<div class="mb-3" v-if="platform === 'windows'"> <div class="mb-3" v-if="platform === 'windows'">
<label for="key_repeat_delay" class="form-label">Key Repeat Delay</label> <label for="key_repeat_delay" class="form-label">Key Repeat Delay</label>
<input type="text" class="form-control" id="key_repeat_delay" placeholder="500" v-model="config.key_repeat_delay"> <input type="text" class="form-control" id="key_repeat_delay" placeholder="500"
v-model="config.key_repeat_delay">
<div class="form-text"> <div class="form-text">
Control how fast keys will repeat themselves<br> Control how fast keys will repeat themselves<br>
The initial delay in milliseconds before repeating keys The initial delay in milliseconds before repeating keys
@@ -146,7 +158,8 @@
<!-- Key Repeat Frequency--> <!-- Key Repeat Frequency-->
<div class="mb-3" v-if="platform === 'windows'"> <div class="mb-3" v-if="platform === 'windows'">
<label for="key_repeat_frequency" class="form-label">Key Repeat Frequency</label> <label for="key_repeat_frequency" class="form-label">Key Repeat Frequency</label>
<input type="text" class="form-control" id="key_repeat_frequency" placeholder="24.9" v-model="config.key_repeat_frequency"> <input type="text" class="form-control" id="key_repeat_frequency" placeholder="24.9"
v-model="config.key_repeat_frequency">
<div class="form-text"> <div class="form-text">
How often keys repeat every second<br> How often keys repeat every second<br>
This configurable option supports decimals This configurable option supports decimals
@@ -156,51 +169,69 @@
<!--Files Tab--> <!--Files Tab-->
<div v-if="currentTab === 'av'" class="config-page"> <div v-if="currentTab === 'av'" class="config-page">
<!--Audio Sink--> <!--Audio Sink-->
<div class="mb-3"> <div class="mb-3" v-if="platform === 'windows'">
<label for="audio_sink" class="form-label">Audio Sink</label> <label for="audio_sink" class="form-label">Audio Sink</label>
<input type="text" class="form-control" id="audio_sink" placeholder="" v-model="config.audio_sink"> <input type="text" class="form-control" id="audio_sink"
<div class="form-text" v-if="platform === 'windows'"> placeholder="{0.0.0.00000000}.{FD47D9CC-4218-4135-9CE2-0C195C87405B}" v-model="config.audio_sink">
<div class="form-text">
The name of the audio sink used for Audio Loopback<br> The name of the audio sink used for Audio Loopback<br>
You can find the name of the audio sink using the following command:<br> You can find the name of the audio sink using the following command:<br>
<pre>tools\audio-info.exe</pre> <pre>tools\audio-info.exe</pre>
</div> </div>
<div class="form-text" v-if="platform === 'linux'"> </div>
<div class="mb-3" v-if="platform === 'linux'">
<label for="audio_sink" class="form-label">Audio Sink</label>
<input type="text" class="form-control" id="audio_sink"
placeholder="alsa_output.pci-0000_09_00.3.analog-stereo" v-model="config.audio_sink">
<div class="form-text">
The name of the audio sink used for Audio Loopback<br> The name of the audio sink used for Audio Loopback<br>
If you do not specify this variable, pulseaudio will select the default monitor device.<br> If you do not specify this variable, pulseaudio will select the default monitor device.<br>
<br> <br>
You can find the name of the audio sink using the following command:<br> You can find the name of the audio sink using either command:<br>
<pre>pacmd list-sinks | grep "name:"</pre><br> <pre>pacmd list-sinks | grep "name:"</pre>
<pre>pactl info | grep Source</pre><br>
</div> </div>
</div> </div>
<!--Virtual Sink--> <!--Virtual Sink-->
<div class="mb-3" v-if="platform === 'windows'"> <div class="mb-3" v-if="platform === 'windows'">
<label for="virtual_sink" class="form-label">Virtual Sink</label> <label for="virtual_sink" class="form-label">Virtual Sink</label>
<input type="text" class="form-control" id="virtual_sink" placeholder="{0.0.0.00000000}.{8edba70c-1125-467c-b89c-15da389bc1d4}" v-model="config.virtual_sink"> <input type="text" class="form-control" id="virtual_sink"
placeholder="{0.0.0.00000000}.{8edba70c-1125-467c-b89c-15da389bc1d4}" v-model="config.virtual_sink">
<div class="form-text"> <div class="form-text">
The virtual sink, is the audio device that's virtual (Like Steam Streaming Speakers), it allows Sunshine The virtual sink, is the audio device that's virtual (Like Steam Streaming Speakers), it allows
Sunshine
to stream audio, while muting the speakers. to stream audio, while muting the speakers.
</div> </div>
</div> </div>
<!--Adapter Name --> <!--Adapter Name -->
<div class="mb-3" v-if="platform === 'windows'"> <div class="mb-3" v-if="platform === 'windows'">
<label for="adapter_name" class="form-label">Adapter Name</label> <label for="adapter_name" class="form-label">Adapter Name</label>
<input type="text" class="form-control" id="adapter_name" placeholder="Radeon RX 580 Series" v-model="config.adapter_name"> <input type="text" class="form-control" id="adapter_name" placeholder="Radeon RX 580 Series"
<div class="form-text"> v-model="config.adapter_name">
<div class="form-text" v-if="platform === 'windows'">
You can select the video card you want to stream:<br> You can select the video card you want to stream:<br>
The appropriate values can be found using the following command:<br> The appropriate values can be found using the following command:<br>
<pre>tools\dxgi-info.exe</pre> <pre>tools\dxgi-info.exe</pre>
</div> </div>
</div> </div>
<!--Output Name --> <!--Output Name -->
<div class="mb-3" class="config-page"> <div class="mb-3" class="config-page" v-if="platform === 'windows'">
<label for="output_name" class="form-label">Output Name</label> <label for="output_name" class="form-label">Output Name</label>
<input type="text" class="form-control" id="output_name" placeholder="\\.\DISPLAY1" v-model="config.output_name"> <input type="text" class="form-control" id="output_name" placeholder="\\.\DISPLAY1"
v-model="config.output_name">
<div class="form-text"> <div class="form-text">
You can select the video card you want to stream:<br> You can select the video card you want to stream:<br>
The appropriate values can be found using the following command:<br> The appropriate values can be found using the following command:<br>
tools\dxgi-info.exe<br> tools\dxgi-info.exe<br><br>
!! Linux only !!<br> </div>
Set the display number to stream. I have no idea how they are numbered. They start from 0, usually.<br> </div>
<div class="mb-3" class="config-page" v-if="platform === 'linux'">
<label for="output_name" class="form-label">Monitor number</label>
<input type="text" class="form-control" id="output_name" placeholder="0" v-model="config.output_name">
<div class="form-text">
xrandr --listmonitors<br>
Example output:
<pre> 0: +HDMI-1 1920/518x1200/324+0+0 HDMI-1</pre>
</div> </div>
</div> </div>
</div> </div>
@@ -208,7 +239,8 @@
<!--Constant Rate Factor--> <!--Constant Rate Factor-->
<div class="mb-3"> <div class="mb-3">
<label for="crf" class="form-label">Constant Rate Factor</label> <label for="crf" class="form-label">Constant Rate Factor</label>
<input type="number" min="0" max="52" class="form-control" id="crf" placeholder="0" v-model="config.crf"> <input type="number" min="0" max="52" class="form-control" id="crf" placeholder="0"
v-model="config.crf">
<div class="form-text"> <div class="form-text">
Constant Rate Factor. Between 1 and 52. It allows QP to go up during motion and down with still Constant Rate Factor. Between 1 and 52. It allows QP to go up during motion and down with still
image, image,
@@ -231,7 +263,8 @@
<div class="mb-3"> <div class="mb-3">
<label for="min_threads" class="form-label">Minimum number of threads used by ffmpeg to encode the <label for="min_threads" class="form-label">Minimum number of threads used by ffmpeg to encode the
video.</label> video.</label>
<input type="number" min="1" class="form-control" id="min_threads" placeholder="1" v-model="config.min_threads"> <input type="number" min="1" class="form-control" id="min_threads" placeholder="1"
v-model="config.min_threads">
<div class="form-text"> <div class="form-text">
Minimum number of threads used by ffmpeg to encode the video.<br> Minimum number of threads used by ffmpeg to encode the video.<br>
Increasing the value slightly reduces encoding efficiency, but the tradeoff is usually<br> Increasing the value slightly reduces encoding efficiency, but the tradeoff is usually<br>
@@ -246,11 +279,13 @@
<option value="0">Sunshine will specify support for HEVC based on encoder</option> <option value="0">Sunshine will specify support for HEVC based on encoder</option>
<option value="1">Sunshine will not advertise support for HEVC</option> <option value="1">Sunshine will not advertise support for HEVC</option>
<option value="2">Sunshine will advertise support for HEVC Main profile</option> <option value="2">Sunshine will advertise support for HEVC Main profile</option>
<option value="3">Sunshine will advertise support for HEVC Main and Main10 (HDR) profiles</option> <option value="3">Sunshine will advertise support for HEVC Main and Main10 (HDR) profiles
</option>
</select> </select>
<div class="form-text"> <div class="form-text">
Allows the client to request HEVC Main or HEVC Main10 video streams.<br> Allows the client to request HEVC Main or HEVC Main10 video streams.<br>
HEVC is more CPU-intensive to encode, so enabling this may reduce performance when using software HEVC is more CPU-intensive to encode, so enabling this may reduce performance when using
software
encoding. encoding.
</div> </div>
</div> </div>
@@ -261,6 +296,7 @@
<option :value="''">Autodetect</option> <option :value="''">Autodetect</option>
<option value="nvenc">nVidia NVENC</option> <option value="nvenc">nVidia NVENC</option>
<option value="amdvce">AMD AMF/VCE</option> <option value="amdvce">AMD AMF/VCE</option>
<option value="vaapi">VA-API</option>
<option value="software">Software</option> <option value="software">Software</option>
</select> </select>
<div class="form-text"> <div class="form-text">
@@ -270,7 +306,8 @@
<!--FEC Percentage--> <!--FEC Percentage-->
<div class="mb-3"> <div class="mb-3">
<label for="fec_percentage" class="form-label">FEC Percentage</label> <label for="fec_percentage" class="form-label">FEC Percentage</label>
<input type="text" class="form-control" id="fec_percentage" placeholder="10" v-model="config.fec_percentage"> <input type="text" class="form-control" id="fec_percentage" placeholder="10"
v-model="config.fec_percentage">
<div class="form-text"> <div class="form-text">
How much error correcting packets must be send for every video.<br> How much error correcting packets must be send for every video.<br>
This is just some random number, don't know the optimal value.<br> This is just some random number, don't know the optimal value.<br>
@@ -280,9 +317,10 @@
<!--Channels--> <!--Channels-->
<div class="mb-3"> <div class="mb-3">
<label for="channels" class="form-label">Channels</label> <label for="channels" class="form-label">Channels</label>
<input type="text" class="form-control" id="channels" placeholder="1" v-model="config.channels"> <input type="text" class="form-control" id="channels" placeholder="1" v-model="config.channels">
<div class="form-text"> <div class="form-text">
When multicasting, it could be useful to have different configurations for each connected Client. When multicasting, it could be useful to have different configurations for each connected
Client.
For example: For example:
<ul> <ul>
<li>Clients connected through WAN and LAN have different bitrate contstraints.</li> <li>Clients connected through WAN and LAN have different bitrate contstraints.</li>
@@ -296,7 +334,7 @@
<!--Software Settings--> <!--Software Settings-->
<div v-if="currentTab === 'sw'" class="config-page"> <div v-if="currentTab === 'sw'" class="config-page">
<div class="mb-3"> <div class="mb-3">
<label for="sw_preset" class="form-label" >SW Presets</label> <label for="sw_preset" class="form-label">SW Presets</label>
<input class="form-control" id="sw_preset" placeholder="superfast" v-model="config.sw_preset"> <input class="form-control" id="sw_preset" placeholder="superfast" v-model="config.sw_preset">
</div> </div>
<div class="mb-3"> <div class="mb-3">
@@ -375,6 +413,10 @@
</select> </select>
</div> </div>
</div> </div>
<div v-if="currentTab === 'va-api'" class="config-page">
<input class="form-control" id="adapter_name" placeholder="/dev/dri/renderD128"
v-model="config.adapter_name">
</div>
</div> </div>
<div class="alert alert-success my-4" v-if="success"><b>Success!</b> Restart Sunshine to apply changes</div> <div class="alert alert-success my-4" v-if="success"><b>Success!</b> Restart Sunshine to apply changes</div>
<div class="mb-3 buttons"> <div class="mb-3 buttons">
@@ -396,61 +438,78 @@
resIn: '', resIn: '',
fpsIn: '', fpsIn: '',
tabs: [{ tabs: [{
id: 'general', id: 'general',
name: "General" name: "General"
}, },
{ {
id: 'files', id: 'files',
name: "Files" name: "Files"
}, },
{ {
id: 'input', id: 'input',
name: "Input" name: "Input"
}, },
{ {
id: 'av', id: 'av',
name: "Audio/Video" name: "Audio/Video"
}, },
{ {
id: 'advanced', id: 'advanced',
name: "Advanced" name: "Advanced"
}, },
{ {
id: "sw", id: "sw",
name: "Software Encoder" name: "Software Encoder"
}, },
{ {
id: "nv", id: "nv",
name: "NVENC Encoder" name: "NVENC Encoder"
}, },
{ {
id: "amd", id: "amd",
name: "AMF Encoder" name: "AMF Encoder"
} },
{
id: "va-api",
name: "VA-API encoder"
}
] ]
} }
}, },
created() { created() {
fetch("/api/config").then(r => r.json()).then((r) => { fetch("/api/config").then(r => r.json()).then((r) => {
this.config = r; this.config = r;
this.platform = this.config.platform; this.platform = this.config.platform;
var app = document.getElementById("app");
if (this.platform == "windows") {
this.tabs = this.tabs.filter(el => {
return el.id !== "va-api";
});
}
if (this.platform == "linux") {
this.tabs = this.tabs.filter(el => {
return el.id !== "nv" && el.id !== "amd";
});
}
delete this.config.status; delete this.config.status;
delete this.config.platform; delete this.config.platform;
//Populate default values if not present in config //Populate default values if not present in config
this.config.min_log_level = this.config.min_log_level || 2; this.config.min_log_level = this.config.min_log_level || 2;
this.config.origin_pin_allowed = this.config.origin_pin_allowed || "lan"; this.config.origin_pin_allowed = this.config.origin_pin_allowed || "lan";
this.config.hevc_mode = this.config.hevc_mode || 0; this.config.hevc_mode = this.config.hevc_mode || 0;
this.config.encoder = this.config.encoder || ''; this.config.encoder = this.config.encoder || '';
this.config.nv_preset = this.config.nv_preset || 'default'; this.config.nv_preset = this.config.nv_preset || 'default';
this.config.nv_rc = this.config.nv_rc || 'auto'; this.config.nv_rc = this.config.nv_rc || 'auto';
this.config.nv_coder = this.config.nv_coder || 'auto'; this.config.nv_coder = this.config.nv_coder || 'auto';
this.config.amd_quality = this.config.amd_quality || 'default'; this.config.amd_quality = this.config.amd_quality || 'default';
this.config.amd_rc = this.config.amd_rc || 'auto'; this.config.amd_rc = this.config.amd_rc || 'auto';
this.config.fps = this.config.fps || '[10, 30, 60, 90, 120]'; this.config.fps = this.config.fps || '[10, 30, 60, 90, 120]';
this.config.resolutions = this.config.resolutions || '[352x240,480x360,858x480,1280x720,1920x1080,2560x1080,3440x1440,1920x1200,3860x2160,3840x1600]'; this.config.resolutions = this.config.resolutions || '[352x240,480x360,858x480,1280x720,1920x1080,2560x1080,3440x1440,1920x1200,3860x2160,3840x1600]';
this.fps = JSON.parse(this.config.fps); this.fps = JSON.parse(this.config.fps);
//Resolutions should be fixed because are not valid JSON //Resolutions should be fixed because are not valid JSON
let res = this.config.resolutions.substring(1,this.config.resolutions.length-1); let res = this.config.resolutions.substring(1, this.config.resolutions.length - 1);
let resolutions = []; let resolutions = [];
res.split(",").forEach(r => resolutions.push(r.trim())); res.split(",").forEach(r => resolutions.push(r.trim()));
this.resolutions = resolutions; this.resolutions = resolutions;
@@ -466,7 +525,7 @@
method: "POST", method: "POST",
body: JSON.stringify(this.config) body: JSON.stringify(this.config)
}).then((r) => { }).then((r) => {
if (r.status == 200)this.success = true; if (r.status == 200) this.success = true;
}); });
} }
} }