mirror of
https://github.com/LizardByte/Sunshine.git
synced 2025-08-10 00:52:16 +00:00
Compare commits
17 Commits
feat/api/a
...
dependabot
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fad21cf671 | ||
|
|
849ad1c176 | ||
|
|
782b3827d7 | ||
|
|
e45b0b95fe | ||
|
|
ffccc1af9b | ||
|
|
41d9a58560 | ||
|
|
4f62944a7c | ||
|
|
3a88ddc639 | ||
|
|
ff0ed25e47 | ||
|
|
ac2fc48288 | ||
|
|
d777b72421 | ||
|
|
f99d3af0a1 | ||
|
|
265a00793c | ||
|
|
dbba364ed7 | ||
|
|
997093986d | ||
|
|
6efc687036 | ||
|
|
a995e578fa |
12
.github/ISSUE_TEMPLATE/config.yml
vendored
12
.github/ISSUE_TEMPLATE/config.yml
vendored
@@ -5,9 +5,15 @@
|
|||||||
|
|
||||||
blank_issues_enabled: false
|
blank_issues_enabled: false
|
||||||
contact_links:
|
contact_links:
|
||||||
|
- name: Discussions
|
||||||
|
url: https://github.com/orgs/LizardByte/discussions
|
||||||
|
about: Community discussions
|
||||||
|
- name: Questions
|
||||||
|
url: https://github.com/orgs/LizardByte/discussions
|
||||||
|
about: Ask questions
|
||||||
|
- name: Feature Requests
|
||||||
|
url: https://github.com/orgs/LizardByte/discussions
|
||||||
|
about: Request new features
|
||||||
- name: Support Center
|
- name: Support Center
|
||||||
url: https://app.lizardbyte.dev/support
|
url: https://app.lizardbyte.dev/support
|
||||||
about: Official LizardByte support
|
about: Official LizardByte support
|
||||||
- name: Discussions
|
|
||||||
url: https://github.com/orgs/LizardByte/discussions
|
|
||||||
about: Community discussions, questions, and feature requests
|
|
||||||
|
|||||||
6
.github/workflows/CI.yml
vendored
6
.github/workflows/CI.yml
vendored
@@ -554,12 +554,16 @@ jobs:
|
|||||||
rm '/usr/local/bin/2to3-3.12'
|
rm '/usr/local/bin/2to3-3.12'
|
||||||
rm '/usr/local/bin/idle3'
|
rm '/usr/local/bin/idle3'
|
||||||
rm '/usr/local/bin/idle3.12'
|
rm '/usr/local/bin/idle3.12'
|
||||||
|
rm '/usr/local/bin/idle3.13'
|
||||||
rm '/usr/local/bin/pydoc3'
|
rm '/usr/local/bin/pydoc3'
|
||||||
rm '/usr/local/bin/pydoc3.12'
|
rm '/usr/local/bin/pydoc3.12'
|
||||||
|
rm '/usr/local/bin/pydoc3.13'
|
||||||
rm '/usr/local/bin/python3'
|
rm '/usr/local/bin/python3'
|
||||||
rm '/usr/local/bin/python3-config'
|
|
||||||
rm '/usr/local/bin/python3.12'
|
rm '/usr/local/bin/python3.12'
|
||||||
|
rm '/usr/local/bin/python3.13'
|
||||||
|
rm '/usr/local/bin/python3-config'
|
||||||
rm '/usr/local/bin/python3.12-config'
|
rm '/usr/local/bin/python3.12-config'
|
||||||
|
rm '/usr/local/bin/python3.13-config'
|
||||||
brew install python
|
brew install python
|
||||||
|
|
||||||
- name: Setup python
|
- name: Setup python
|
||||||
|
|||||||
2
.github/workflows/ci-docker.yml
vendored
2
.github/workflows/ci-docker.yml
vendored
@@ -123,7 +123,7 @@ jobs:
|
|||||||
docker:
|
docker:
|
||||||
needs: [check_dockerfiles, setup_release]
|
needs: [check_dockerfiles, setup_release]
|
||||||
if: ${{ needs.check_dockerfiles.outputs.dockerfiles }}
|
if: ${{ needs.check_dockerfiles.outputs.dockerfiles }}
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-22.04
|
||||||
permissions:
|
permissions:
|
||||||
packages: write
|
packages: write
|
||||||
contents: write
|
contents: write
|
||||||
|
|||||||
@@ -1,17 +0,0 @@
|
|||||||
---
|
|
||||||
description: Bad Request - A parameter was not specified, or was specified incorrectly.
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema:
|
|
||||||
type: object
|
|
||||||
properties:
|
|
||||||
status_code:
|
|
||||||
type: string
|
|
||||||
status:
|
|
||||||
type: string
|
|
||||||
error:
|
|
||||||
type: string
|
|
||||||
example:
|
|
||||||
status_code: 400
|
|
||||||
status: false
|
|
||||||
error: "Bad Request"
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
---
|
|
||||||
description: Unauthorized - The request requires user authentication.
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema:
|
|
||||||
type: object
|
|
||||||
properties:
|
|
||||||
status_code:
|
|
||||||
type: string
|
|
||||||
status:
|
|
||||||
type: string
|
|
||||||
error:
|
|
||||||
type: string
|
|
||||||
example:
|
|
||||||
status_code: 401
|
|
||||||
status: false
|
|
||||||
error: "Unauthorized"
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
---
|
|
||||||
description: Forbidden - The server understood the request, but is refusing to fulfill it.
|
|
||||||
content:
|
|
||||||
# TODO: return JSON response.
|
|
||||||
text/plain:
|
|
||||||
schema:
|
|
||||||
type: string
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
---
|
|
||||||
description: Not Found - The requested resource could not be found.
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema:
|
|
||||||
type: object
|
|
||||||
properties:
|
|
||||||
status_code:
|
|
||||||
type: integer
|
|
||||||
format: int32
|
|
||||||
error:
|
|
||||||
type: string
|
|
||||||
example:
|
|
||||||
status_code: 404
|
|
||||||
error: "Not Found"
|
|
||||||
@@ -1,48 +0,0 @@
|
|||||||
---
|
|
||||||
type: object
|
|
||||||
required:
|
|
||||||
- name
|
|
||||||
properties:
|
|
||||||
name:
|
|
||||||
type: string
|
|
||||||
description: Application Name, as shown on Moonlight
|
|
||||||
output:
|
|
||||||
type: string
|
|
||||||
description: The file where the output of the command is stored, if it is not specified, the output is ignored
|
|
||||||
cmd:
|
|
||||||
$ref: "./cmd.yml"
|
|
||||||
description: The main application to start. If blank, no application will be started.
|
|
||||||
exclude-global-prep-cmd:
|
|
||||||
type: boolean
|
|
||||||
description: Enable/Disable the execution of Global Prep Commands for this application.
|
|
||||||
elevated:
|
|
||||||
type: boolean
|
|
||||||
description: Run the application as an elevated process.
|
|
||||||
auto-detach:
|
|
||||||
type: boolean
|
|
||||||
description: Continue streaming if the application exits quickly
|
|
||||||
wait-all:
|
|
||||||
type: boolean
|
|
||||||
description: Continue streaming until all app processes exit
|
|
||||||
exit-timeout:
|
|
||||||
type: integer
|
|
||||||
description: Number of seconds to wait for all app processes to gracefully exit when requested to quit.
|
|
||||||
image-path:
|
|
||||||
type: string
|
|
||||||
description: |
|
|
||||||
Application icon/picture/image path that will be sent to client. Image must be a PNG file.
|
|
||||||
If not set, Sunshine will send default box image.
|
|
||||||
working-dir:
|
|
||||||
type: string
|
|
||||||
description: |
|
|
||||||
The working directory that should be passed to the process.
|
|
||||||
For example, some applications use the working directory to search for configuration files.
|
|
||||||
If not set, Sunshine will default to the parent directory of the command
|
|
||||||
prep-cmd:
|
|
||||||
type: array
|
|
||||||
items:
|
|
||||||
$ref: "./prep-cmd.yml"
|
|
||||||
detached:
|
|
||||||
type: array
|
|
||||||
items:
|
|
||||||
$ref: "./cmd.yml"
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
---
|
|
||||||
type: string
|
|
||||||
description: Command to execute
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
---
|
|
||||||
type: object
|
|
||||||
required:
|
|
||||||
- do
|
|
||||||
- undo
|
|
||||||
- elevated
|
|
||||||
properties:
|
|
||||||
do:
|
|
||||||
$ref: "./cmd.yml"
|
|
||||||
description: Command to run before the application starts.
|
|
||||||
undo:
|
|
||||||
$ref: "./cmd.yml"
|
|
||||||
description: Command to run after the application exits.
|
|
||||||
elevated:
|
|
||||||
type: boolean
|
|
||||||
description: Run the command as an elevated process.
|
|
||||||
@@ -1,44 +0,0 @@
|
|||||||
---
|
|
||||||
# https://openapi.tools
|
|
||||||
|
|
||||||
openapi: 3.1.0
|
|
||||||
|
|
||||||
info:
|
|
||||||
title: Sunshine
|
|
||||||
summary: Self-hosted game stream host for Moonlight.
|
|
||||||
version: 0.0.0
|
|
||||||
contact:
|
|
||||||
name: LizardByte
|
|
||||||
url: https://app.lizardbyte.dev/support
|
|
||||||
license:
|
|
||||||
name: GNU General Public License v3.0 only
|
|
||||||
url: https://github.com/LizardByte/Sunshine/blob/master/LICENSE
|
|
||||||
|
|
||||||
servers:
|
|
||||||
- url: "https://{host}:{ui-port}"
|
|
||||||
description: Sunshine server
|
|
||||||
variables:
|
|
||||||
host:
|
|
||||||
default: "localhost"
|
|
||||||
ui-port:
|
|
||||||
default: 47990
|
|
||||||
|
|
||||||
security:
|
|
||||||
- basicAuth: []
|
|
||||||
|
|
||||||
components:
|
|
||||||
securitySchemes:
|
|
||||||
# TODO: update when JWT is implemented (https://github.com/LizardByte/Sunshine/pull/2995)
|
|
||||||
# https://swagger.io/specification/#security-scheme-object-examples
|
|
||||||
basicAuth:
|
|
||||||
description: HTTP Basic authentication
|
|
||||||
type: http
|
|
||||||
scheme: basic
|
|
||||||
|
|
||||||
paths:
|
|
||||||
/api/apps:
|
|
||||||
$ref: "./paths/confighttp/apps/apps.yml"
|
|
||||||
/api/apps/{index}:
|
|
||||||
$ref: "./paths/confighttp/apps/apps-by-index.yml"
|
|
||||||
/api/logs:
|
|
||||||
$ref: "./paths/confighttp/logs/logs.yml"
|
|
||||||
@@ -1,37 +0,0 @@
|
|||||||
---
|
|
||||||
delete:
|
|
||||||
summary: Delete an application.
|
|
||||||
description: |
|
|
||||||
Delete an application.
|
|
||||||
operationId: deleteApps
|
|
||||||
tags:
|
|
||||||
- Apps
|
|
||||||
parameters:
|
|
||||||
- name: index
|
|
||||||
in: path
|
|
||||||
description: The index of the application to delete.
|
|
||||||
required: true
|
|
||||||
schema:
|
|
||||||
type: integer
|
|
||||||
format: int32
|
|
||||||
responses:
|
|
||||||
'200':
|
|
||||||
description: The application was deleted successfully.
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema:
|
|
||||||
type: object
|
|
||||||
properties:
|
|
||||||
status:
|
|
||||||
type: string
|
|
||||||
result:
|
|
||||||
type: string
|
|
||||||
example:
|
|
||||||
status: true
|
|
||||||
result: "application 9999 deleted"
|
|
||||||
'400':
|
|
||||||
$ref: "../../../components/responses/400.yml"
|
|
||||||
'401':
|
|
||||||
$ref: "../../../components/responses/401.yml"
|
|
||||||
'403':
|
|
||||||
$ref: "../../../components/responses/403.yml"
|
|
||||||
@@ -1,151 +0,0 @@
|
|||||||
---
|
|
||||||
get:
|
|
||||||
summary: Get the list of available applications.
|
|
||||||
description: |
|
|
||||||
Get the list of available applications.
|
|
||||||
operationId: getApps
|
|
||||||
tags:
|
|
||||||
- Apps
|
|
||||||
responses:
|
|
||||||
'200':
|
|
||||||
description: A list of available applications.
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema:
|
|
||||||
type: array
|
|
||||||
items:
|
|
||||||
$ref: "../../../components/schemas/app.yml"
|
|
||||||
example:
|
|
||||||
- name: "Example App"
|
|
||||||
output: "/path/to/output.log"
|
|
||||||
cmd: "example-command"
|
|
||||||
exclude-global-prep-cmd: false
|
|
||||||
elevated: false
|
|
||||||
auto-detach: true
|
|
||||||
wait-all: false
|
|
||||||
exit-timeout: 30
|
|
||||||
image-path: "/path/to/image.png"
|
|
||||||
working-dir: "/path/to/working-dir"
|
|
||||||
prep-cmd:
|
|
||||||
- do: "prep-command-1"
|
|
||||||
undo: "undo-command-1"
|
|
||||||
elevated: false
|
|
||||||
detached:
|
|
||||||
- "detached-command-1"
|
|
||||||
'401':
|
|
||||||
$ref: "../../../components/responses/401.yml"
|
|
||||||
'403':
|
|
||||||
$ref: "../../../components/responses/403.yml"
|
|
||||||
|
|
||||||
post:
|
|
||||||
summary: Save an application.
|
|
||||||
description: |
|
|
||||||
Save an application.
|
|
||||||
To save a new application the index must be `-1`.
|
|
||||||
To update an existing application, you must provide the current index of the application.
|
|
||||||
operationId: postApps
|
|
||||||
tags:
|
|
||||||
- Apps
|
|
||||||
parameters:
|
|
||||||
- name: index
|
|
||||||
in: query
|
|
||||||
description: The index of the application to update. If the index is -1, a new application will be created.
|
|
||||||
required: true
|
|
||||||
schema:
|
|
||||||
type: integer
|
|
||||||
format: int32
|
|
||||||
- name: name
|
|
||||||
in: query
|
|
||||||
description: Application Name
|
|
||||||
required: false
|
|
||||||
schema:
|
|
||||||
type: string
|
|
||||||
- name: output
|
|
||||||
in: query
|
|
||||||
description: Log Output Path
|
|
||||||
required: false
|
|
||||||
schema:
|
|
||||||
type: string
|
|
||||||
- name: cmd
|
|
||||||
in: query
|
|
||||||
description: Command to run the application
|
|
||||||
required: false
|
|
||||||
schema:
|
|
||||||
$ref: "../../../components/schemas/cmd.yml"
|
|
||||||
- name: exclude-global-prep-cmd
|
|
||||||
in: query
|
|
||||||
description: Enable/Disable the execution of Global Prep Commands for this application.
|
|
||||||
required: false
|
|
||||||
schema:
|
|
||||||
type: boolean
|
|
||||||
- name: elevated
|
|
||||||
in: query
|
|
||||||
description: Run the application as an elevated process.
|
|
||||||
required: false
|
|
||||||
schema:
|
|
||||||
type: boolean
|
|
||||||
- name: auto-detach
|
|
||||||
in: query
|
|
||||||
description: Continue streaming if the application exits quickly
|
|
||||||
required: false
|
|
||||||
schema:
|
|
||||||
type: boolean
|
|
||||||
- name: wait-all
|
|
||||||
in: query
|
|
||||||
description: Continue streaming until all app processes exit
|
|
||||||
required: false
|
|
||||||
schema:
|
|
||||||
type: boolean
|
|
||||||
- name: exit-timeout
|
|
||||||
in: query
|
|
||||||
description: Number of seconds to wait for all app processes to gracefully exit when requested to quit.
|
|
||||||
required: false
|
|
||||||
schema:
|
|
||||||
type: integer
|
|
||||||
format: int32
|
|
||||||
- name: prep-cmd
|
|
||||||
in: query
|
|
||||||
description: Commands to run before the main application
|
|
||||||
required: false
|
|
||||||
schema:
|
|
||||||
type: array
|
|
||||||
items:
|
|
||||||
$ref: "../../../components/schemas/prep-cmd.yml"
|
|
||||||
- name: detached
|
|
||||||
in: query
|
|
||||||
description: Commands to run in detached processes
|
|
||||||
required: false
|
|
||||||
schema:
|
|
||||||
type: array
|
|
||||||
items:
|
|
||||||
$ref: "../../../components/schemas/cmd.yml"
|
|
||||||
- name: image-path
|
|
||||||
in: query
|
|
||||||
description: Full path to the application image. Must be a png file.
|
|
||||||
required: false
|
|
||||||
schema:
|
|
||||||
type: string
|
|
||||||
- name: working-dir
|
|
||||||
in: query
|
|
||||||
description: The working directory that should be passed to the process.
|
|
||||||
required: false
|
|
||||||
schema:
|
|
||||||
type: string
|
|
||||||
responses:
|
|
||||||
'200':
|
|
||||||
description: The application was saved successfully.
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema:
|
|
||||||
type: object
|
|
||||||
properties:
|
|
||||||
status:
|
|
||||||
type: string
|
|
||||||
example:
|
|
||||||
status: true
|
|
||||||
'400':
|
|
||||||
$ref: "../../../components/responses/400.yml"
|
|
||||||
'401':
|
|
||||||
$ref: "../../../components/responses/401.yml"
|
|
||||||
'403':
|
|
||||||
$ref: "../../../components/responses/403.yml"
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
---
|
|
||||||
get:
|
|
||||||
summary: Get the logs from the log file.
|
|
||||||
description: |
|
|
||||||
Get the logs from the log file.
|
|
||||||
operationId: getLogs
|
|
||||||
tags:
|
|
||||||
- Logs
|
|
||||||
responses:
|
|
||||||
'200':
|
|
||||||
description: The contents of the log file.
|
|
||||||
content:
|
|
||||||
text/plain:
|
|
||||||
schema:
|
|
||||||
type: string
|
|
||||||
example: '[2025-01-15 17:07:58.131]: Info: Sunshine version: v...'
|
|
||||||
'401':
|
|
||||||
$ref: "../../../components/responses/401.yml"
|
|
||||||
'403':
|
|
||||||
$ref: "../../../components/responses/403.yml"
|
|
||||||
@@ -974,7 +974,9 @@ editing the `conf` file in a text editor. Use the examples as reference.
|
|||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Default</td>
|
<td>Default</td>
|
||||||
<td colspan="2">@code{}verify_only@endcode</td>
|
<td colspan="2">@code{}
|
||||||
|
disabled
|
||||||
|
@endcode</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Example</td>
|
<td>Example</td>
|
||||||
@@ -1314,6 +1316,29 @@ editing the `conf` file in a text editor. Use the examples as reference.
|
|||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
|
### max_bitrate
|
||||||
|
|
||||||
|
<table>
|
||||||
|
<tr>
|
||||||
|
<td>Description</td>
|
||||||
|
<td colspan="2">
|
||||||
|
The maximum bitrate (in Kbps) that Sunshine will encode the stream at. If set to 0, it will always use the bitrate requested by Moonlight.
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Default</td>
|
||||||
|
<td colspan="2">@code{}
|
||||||
|
0
|
||||||
|
@endcode</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Example</td>
|
||||||
|
<td colspan="2">@code{}
|
||||||
|
max_bitrate = 5000
|
||||||
|
@endcode</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
### min_fps_factor
|
### min_fps_factor
|
||||||
|
|
||||||
<table>
|
<table>
|
||||||
|
|||||||
@@ -10,12 +10,12 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@lizardbyte/shared-web": "2024.921.191855",
|
"@lizardbyte/shared-web": "2024.921.191855",
|
||||||
"vue": "3.5.13",
|
"vue": "3.5.13",
|
||||||
"vue-i18n": "11.0.1"
|
"vue-i18n": "11.1.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@vitejs/plugin-vue": "4.6.2",
|
"@vitejs/plugin-vue": "4.6.2",
|
||||||
"serve": "14.2.3",
|
"serve": "14.2.3",
|
||||||
"vite": "4.5.2",
|
"vite": "4.5.9",
|
||||||
"vite-plugin-ejs": "1.6.4"
|
"vite-plugin-ejs": "1.6.4"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Submodule packaging/linux/flatpak/deps/flatpak-builder-tools updated: a1eb29c5f3...aac65cf44c
Submodule packaging/linux/flatpak/deps/shared-modules updated: 26def5f1d2...802d804161
@@ -3,6 +3,7 @@ set -e
|
|||||||
|
|
||||||
# Default value for arguments
|
# Default value for arguments
|
||||||
appimage_build=0
|
appimage_build=0
|
||||||
|
num_processors=$(nproc)
|
||||||
publisher_name="Third Party Publisher"
|
publisher_name="Third Party Publisher"
|
||||||
publisher_website=""
|
publisher_website=""
|
||||||
publisher_issue_url="https://app.lizardbyte.dev/support"
|
publisher_issue_url="https://app.lizardbyte.dev/support"
|
||||||
@@ -27,6 +28,7 @@ Options:
|
|||||||
-h, --help Display this help message.
|
-h, --help Display this help message.
|
||||||
-s, --sudo-off Disable sudo command.
|
-s, --sudo-off Disable sudo command.
|
||||||
--appimage-build Compile for AppImage, this will not create the AppImage, just the executable.
|
--appimage-build Compile for AppImage, this will not create the AppImage, just the executable.
|
||||||
|
--num-processors The number of processors to use for compilation. Default is the value of 'nproc'.
|
||||||
--publisher-name The name of the publisher (not developer) of the application.
|
--publisher-name The name of the publisher (not developer) of the application.
|
||||||
--publisher-website The URL of the publisher's website.
|
--publisher-website The URL of the publisher's website.
|
||||||
--publisher-issue-url The URL of the publisher's support site or issue tracker.
|
--publisher-issue-url The URL of the publisher's support site or issue tracker.
|
||||||
@@ -53,6 +55,9 @@ while getopts ":hs-:" opt; do
|
|||||||
appimage_build=1
|
appimage_build=1
|
||||||
skip_libva=1
|
skip_libva=1
|
||||||
;;
|
;;
|
||||||
|
num-processors=*)
|
||||||
|
num_processors="${OPTARG#*=}"
|
||||||
|
;;
|
||||||
publisher-name=*)
|
publisher-name=*)
|
||||||
publisher_name="${OPTARG#*=}"
|
publisher_name="${OPTARG#*=}"
|
||||||
;;
|
;;
|
||||||
@@ -367,7 +372,7 @@ function run_install() {
|
|||||||
tar -xzf "${build_dir}/doxygen.tar.gz"
|
tar -xzf "${build_dir}/doxygen.tar.gz"
|
||||||
cd "doxygen-${doxygen_min}"
|
cd "doxygen-${doxygen_min}"
|
||||||
cmake -DCMAKE_BUILD_TYPE=Release -G="Ninja" -B="build" -S="."
|
cmake -DCMAKE_BUILD_TYPE=Release -G="Ninja" -B="build" -S="."
|
||||||
ninja -C "build"
|
ninja -C "build" -j"${num_processors}"
|
||||||
ninja -C "build" install
|
ninja -C "build" install
|
||||||
else
|
else
|
||||||
echo "Doxygen version too low, skipping docs"
|
echo "Doxygen version too low, skipping docs"
|
||||||
|
|||||||
@@ -1,2 +1,2 @@
|
|||||||
Babel==2.16.0
|
Babel==2.17.0
|
||||||
clang-format
|
clang-format
|
||||||
|
|||||||
@@ -497,7 +497,7 @@ namespace config {
|
|||||||
{}, // output_name
|
{}, // output_name
|
||||||
|
|
||||||
{
|
{
|
||||||
video_t::dd_t::config_option_e::verify_only, // configuration_option
|
video_t::dd_t::config_option_e::disabled, // configuration_option
|
||||||
video_t::dd_t::resolution_option_e::automatic, // resolution_option
|
video_t::dd_t::resolution_option_e::automatic, // resolution_option
|
||||||
{}, // manual_resolution
|
{}, // manual_resolution
|
||||||
video_t::dd_t::refresh_rate_option_e::automatic, // refresh_rate_option
|
video_t::dd_t::refresh_rate_option_e::automatic, // refresh_rate_option
|
||||||
@@ -509,7 +509,8 @@ namespace config {
|
|||||||
{} // wa
|
{} // wa
|
||||||
}, // display_device
|
}, // display_device
|
||||||
|
|
||||||
1 // min_fps_factor
|
1, // min_fps_factor
|
||||||
|
0 // max_bitrate
|
||||||
};
|
};
|
||||||
|
|
||||||
audio_t audio {
|
audio_t audio {
|
||||||
@@ -1138,6 +1139,7 @@ namespace config {
|
|||||||
bool_f(vars, "dd_wa_hdr_toggle", video.dd.wa.hdr_toggle);
|
bool_f(vars, "dd_wa_hdr_toggle", video.dd.wa.hdr_toggle);
|
||||||
|
|
||||||
int_between_f(vars, "min_fps_factor", video.min_fps_factor, {1, 3});
|
int_between_f(vars, "min_fps_factor", video.min_fps_factor, {1, 3});
|
||||||
|
int_f(vars, "max_bitrate", video.max_bitrate);
|
||||||
|
|
||||||
path_f(vars, "pkey", nvhttp.pkey);
|
path_f(vars, "pkey", nvhttp.pkey);
|
||||||
path_f(vars, "cert", nvhttp.cert);
|
path_f(vars, "cert", nvhttp.cert);
|
||||||
|
|||||||
@@ -138,6 +138,7 @@ namespace config {
|
|||||||
} dd;
|
} dd;
|
||||||
|
|
||||||
int min_fps_factor; // Minimum fps target, determines minimum frame time
|
int min_fps_factor; // Minimum fps target, determines minimum frame time
|
||||||
|
int max_bitrate; // Maximum bitrate, sets ceiling in kbps for bitrate requested from client
|
||||||
};
|
};
|
||||||
|
|
||||||
struct audio_t {
|
struct audio_t {
|
||||||
|
|||||||
@@ -528,7 +528,7 @@ namespace nvenc {
|
|||||||
|
|
||||||
NV_ENC_LOCK_BITSTREAM lock_bitstream = {min_struct_version(NV_ENC_LOCK_BITSTREAM_VER, 1, 2)};
|
NV_ENC_LOCK_BITSTREAM lock_bitstream = {min_struct_version(NV_ENC_LOCK_BITSTREAM_VER, 1, 2)};
|
||||||
lock_bitstream.outputBitstream = output_bitstream;
|
lock_bitstream.outputBitstream = output_bitstream;
|
||||||
lock_bitstream.doNotWait = 0;
|
lock_bitstream.doNotWait = async_event_handle ? 1 : 0;
|
||||||
|
|
||||||
if (async_event_handle && !wait_for_async_event(100)) {
|
if (async_event_handle && !wait_for_async_event(100)) {
|
||||||
BOOST_LOG(error) << "NvEnc: frame " << frame_index << " encode wait timeout";
|
BOOST_LOG(error) << "NvEnc: frame " << frame_index << " encode wait timeout";
|
||||||
|
|||||||
@@ -10,11 +10,19 @@
|
|||||||
|
|
||||||
namespace nvenc {
|
namespace nvenc {
|
||||||
|
|
||||||
|
nvenc_d3d11::nvenc_d3d11(NV_ENC_DEVICE_TYPE device_type):
|
||||||
|
nvenc_base(device_type) {
|
||||||
|
async_event_handle = CreateEvent(NULL, FALSE, FALSE, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
nvenc_d3d11::~nvenc_d3d11() {
|
nvenc_d3d11::~nvenc_d3d11() {
|
||||||
if (dll) {
|
if (dll) {
|
||||||
FreeLibrary(dll);
|
FreeLibrary(dll);
|
||||||
dll = NULL;
|
dll = NULL;
|
||||||
}
|
}
|
||||||
|
if (async_event_handle) {
|
||||||
|
CloseHandle(async_event_handle);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool nvenc_d3d11::init_library() {
|
bool nvenc_d3d11::init_library() {
|
||||||
@@ -53,5 +61,9 @@ namespace nvenc {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool nvenc_d3d11::wait_for_async_event(uint32_t timeout_ms) {
|
||||||
|
return WaitForSingleObject(async_event_handle, timeout_ms) == WAIT_OBJECT_0;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace nvenc
|
} // namespace nvenc
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -25,10 +25,7 @@ namespace nvenc {
|
|||||||
*/
|
*/
|
||||||
class nvenc_d3d11: public nvenc_base {
|
class nvenc_d3d11: public nvenc_base {
|
||||||
public:
|
public:
|
||||||
explicit nvenc_d3d11(NV_ENC_DEVICE_TYPE device_type):
|
explicit nvenc_d3d11(NV_ENC_DEVICE_TYPE device_type);
|
||||||
nvenc_base(device_type) {
|
|
||||||
}
|
|
||||||
|
|
||||||
~nvenc_d3d11();
|
~nvenc_d3d11();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -39,6 +36,7 @@ namespace nvenc {
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool init_library() override;
|
bool init_library() override;
|
||||||
|
bool wait_for_async_event(uint32_t timeout_ms) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
HMODULE dll = NULL;
|
HMODULE dll = NULL;
|
||||||
|
|||||||
@@ -299,6 +299,7 @@ namespace video {
|
|||||||
REF_FRAMES_INVALIDATION = 1 << 8, ///< Support reference frames invalidation
|
REF_FRAMES_INVALIDATION = 1 << 8, ///< Support reference frames invalidation
|
||||||
ALWAYS_REPROBE = 1 << 9, ///< This is an encoder of last resort and we want to aggressively probe for a better one
|
ALWAYS_REPROBE = 1 << 9, ///< This is an encoder of last resort and we want to aggressively probe for a better one
|
||||||
YUV444_SUPPORT = 1 << 10, ///< Encoder may support 4:4:4 chroma sampling depending on hardware
|
YUV444_SUPPORT = 1 << 10, ///< Encoder may support 4:4:4 chroma sampling depending on hardware
|
||||||
|
ASYNC_TEARDOWN = 1 << 11, ///< Encoder supports async teardown on a different thread
|
||||||
};
|
};
|
||||||
|
|
||||||
class avcodec_encode_session_t: public encode_session_t {
|
class avcodec_encode_session_t: public encode_session_t {
|
||||||
@@ -503,7 +504,7 @@ namespace video {
|
|||||||
{}, // Fallback options
|
{}, // Fallback options
|
||||||
"h264_nvenc"s,
|
"h264_nvenc"s,
|
||||||
},
|
},
|
||||||
PARALLEL_ENCODING | REF_FRAMES_INVALIDATION | YUV444_SUPPORT // flags
|
PARALLEL_ENCODING | REF_FRAMES_INVALIDATION | YUV444_SUPPORT | ASYNC_TEARDOWN // flags
|
||||||
};
|
};
|
||||||
#elif !defined(__APPLE__)
|
#elif !defined(__APPLE__)
|
||||||
encoder_t nvenc {
|
encoder_t nvenc {
|
||||||
@@ -1686,7 +1687,8 @@ namespace video {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto bitrate = config.bitrate * 1000;
|
auto bitrate = ((config::video.max_bitrate > 0) ? std::min(config.bitrate, config::video.max_bitrate) : config.bitrate) * 1000;
|
||||||
|
BOOST_LOG(info) << "Streaming bitrate is " << bitrate;
|
||||||
ctx->rc_max_rate = bitrate;
|
ctx->rc_max_rate = bitrate;
|
||||||
ctx->bit_rate = bitrate;
|
ctx->bit_rate = bitrate;
|
||||||
|
|
||||||
@@ -1856,6 +1858,23 @@ namespace video {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// As a workaround for NVENC hangs and to generally speed up encoder reinit,
|
||||||
|
// we will complete the encoder teardown in a separate thread if supported.
|
||||||
|
// This will move expensive processing off the encoder thread to allow us
|
||||||
|
// to restart encoding as soon as possible. For cases where the NVENC driver
|
||||||
|
// hang occurs, this thread may probably never exit, but it will allow
|
||||||
|
// streaming to continue without requiring a full restart of Sunshine.
|
||||||
|
auto fail_guard = util::fail_guard([&encoder, &session] {
|
||||||
|
if (encoder.flags & ASYNC_TEARDOWN) {
|
||||||
|
std::thread encoder_teardown_thread {[session = std::move(session)]() mutable {
|
||||||
|
BOOST_LOG(info) << "Starting async encoder teardown";
|
||||||
|
session.reset();
|
||||||
|
BOOST_LOG(info) << "Async encoder teardown complete";
|
||||||
|
}};
|
||||||
|
encoder_teardown_thread.detach();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// set minimum frame time, avoiding violation of client-requested target framerate
|
// set minimum frame time, avoiding violation of client-requested target framerate
|
||||||
auto minimum_frame_time = std::chrono::milliseconds(1000 / std::min(config.framerate, (config::video.min_fps_factor * 10)));
|
auto minimum_frame_time = std::chrono::milliseconds(1000 / std::min(config.framerate, (config::video.min_fps_factor * 10)));
|
||||||
BOOST_LOG(debug) << "Minimum frame time set to "sv << minimum_frame_time.count() << "ms, based on min fps factor of "sv << config::video.min_fps_factor << "."sv;
|
BOOST_LOG(debug) << "Minimum frame time set to "sv << minimum_frame_time.count() << "ms, based on min fps factor of "sv << config::video.min_fps_factor << "."sv;
|
||||||
|
|||||||
@@ -441,7 +441,7 @@
|
|||||||
);
|
);
|
||||||
if (resp) {
|
if (resp) {
|
||||||
fetch("./api/apps/" + id, { method: "DELETE" }).then((r) => {
|
fetch("./api/apps/" + id, { method: "DELETE" }).then((r) => {
|
||||||
if (r.status == 200) document.location.reload();
|
if (r.status === 200) document.location.reload();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -557,7 +557,7 @@
|
|||||||
method: "POST",
|
method: "POST",
|
||||||
body: JSON.stringify(this.editForm),
|
body: JSON.stringify(this.editForm),
|
||||||
}).then((r) => {
|
}).then((r) => {
|
||||||
if (r.status == 200) document.location.reload();
|
if (r.status === 200) document.location.reload();
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -168,7 +168,7 @@
|
|||||||
"install_steam_audio_drivers": "enabled",
|
"install_steam_audio_drivers": "enabled",
|
||||||
"adapter_name": "",
|
"adapter_name": "",
|
||||||
"output_name": "",
|
"output_name": "",
|
||||||
"dd_configuration_option": "verify_only",
|
"dd_configuration_option": "disabled",
|
||||||
"dd_resolution_option": "auto",
|
"dd_resolution_option": "auto",
|
||||||
"dd_manual_resolution": "",
|
"dd_manual_resolution": "",
|
||||||
"dd_refresh_rate_option": "auto",
|
"dd_refresh_rate_option": "auto",
|
||||||
@@ -179,6 +179,7 @@
|
|||||||
"dd_mode_remapping": {"mixed": [], "resolution_only": [], "refresh_rate_only": []},
|
"dd_mode_remapping": {"mixed": [], "resolution_only": [], "refresh_rate_only": []},
|
||||||
"dd_wa_hdr_toggle": "disabled",
|
"dd_wa_hdr_toggle": "disabled",
|
||||||
"min_fps_factor": 1,
|
"min_fps_factor": 1,
|
||||||
|
"max_bitrate": 0,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ function addRemappingEntry() {
|
|||||||
{{ $t('config.dd_config_label') }}
|
{{ $t('config.dd_config_label') }}
|
||||||
</label>
|
</label>
|
||||||
<select id="dd_configuration_option" class="form-select" v-model="config.dd_configuration_option">
|
<select id="dd_configuration_option" class="form-select" v-model="config.dd_configuration_option">
|
||||||
<option value="disabled">{{ $t('_common.disabled') }}</option>
|
<option value="disabled">{{ $t('_common.disabled_def') }}</option>
|
||||||
<option value="verify_only">{{ $t('config.dd_config_verify_only') }}</option>
|
<option value="verify_only">{{ $t('config.dd_config_verify_only') }}</option>
|
||||||
<option value="ensure_active">{{ $t('config.dd_config_ensure_active') }}</option>
|
<option value="ensure_active">{{ $t('config.dd_config_ensure_active') }}</option>
|
||||||
<option value="ensure_primary">{{ $t('config.dd_config_ensure_primary') }}</option>
|
<option value="ensure_primary">{{ $t('config.dd_config_ensure_primary') }}</option>
|
||||||
|
|||||||
@@ -17,6 +17,13 @@ const config = ref(props.config)
|
|||||||
<input type="number" min="1" max="3" class="form-control" id="min_fps_factor" placeholder="1" v-model="config.min_fps_factor" />
|
<input type="number" min="1" max="3" class="form-control" id="min_fps_factor" placeholder="1" v-model="config.min_fps_factor" />
|
||||||
<div class="form-text">{{ $t('config.min_fps_factor_desc') }}</div>
|
<div class="form-text">{{ $t('config.min_fps_factor_desc') }}</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!--max_bitrate-->
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="max_bitrate" class="form-label">{{ $t("config.max_bitrate") }}</label>
|
||||||
|
<input type="number" class="form-control" id="max_bitrate" placeholder="0" v-model="config.max_bitrate" />
|
||||||
|
<div class="form-text">{{ $t("config.max_bitrate_desc") }}</div>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
|||||||
@@ -94,10 +94,10 @@
|
|||||||
method: "POST",
|
method: "POST",
|
||||||
body: JSON.stringify(this.passwordData),
|
body: JSON.stringify(this.passwordData),
|
||||||
}).then((r) => {
|
}).then((r) => {
|
||||||
if (r.status == 200) {
|
if (r.status === 200) {
|
||||||
r.json().then((rj) => {
|
r.json().then((rj) => {
|
||||||
if (rj.status.toString() === "true") {
|
this.success = rj.status;
|
||||||
this.success = true;
|
if (this.success === true) {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
document.location.reload();
|
document.location.reload();
|
||||||
}, 5000);
|
}, 5000);
|
||||||
|
|||||||
@@ -42,7 +42,7 @@
|
|||||||
fetch("./api/pin", {method: "POST", body: b})
|
fetch("./api/pin", {method: "POST", body: b})
|
||||||
.then((response) => response.json())
|
.then((response) => response.json())
|
||||||
.then((response) => {
|
.then((response) => {
|
||||||
if (response.status.toString().toLowerCase() === "true") {
|
if (response.status === true) {
|
||||||
document.querySelector(
|
document.querySelector(
|
||||||
"#status"
|
"#status"
|
||||||
).innerHTML = `<div class="alert alert-success" role="alert">${this.i18n.t('pin.pair_success')}</div>`;
|
).innerHTML = `<div class="alert alert-success" role="alert">${this.i18n.t('pin.pair_success')}</div>`;
|
||||||
|
|||||||
@@ -160,7 +160,7 @@
|
|||||||
"dd_config_revert_delay_desc": "Additional delay in milliseconds to wait before reverting configuration when the app has been closed or the last session terminated. Main purpose is to provide a smoother transition when quickly switching between apps.",
|
"dd_config_revert_delay_desc": "Additional delay in milliseconds to wait before reverting configuration when the app has been closed or the last session terminated. Main purpose is to provide a smoother transition when quickly switching between apps.",
|
||||||
"dd_config_revert_on_disconnect": "Config revert on disconnect",
|
"dd_config_revert_on_disconnect": "Config revert on disconnect",
|
||||||
"dd_config_revert_on_disconnect_desc": "Revert configuration upon disconnect of all clients instead of app close or last session termination.",
|
"dd_config_revert_on_disconnect_desc": "Revert configuration upon disconnect of all clients instead of app close or last session termination.",
|
||||||
"dd_config_verify_only": "Verify that the display is enabled (default)",
|
"dd_config_verify_only": "Verify that the display is enabled",
|
||||||
"dd_hdr_option": "HDR",
|
"dd_hdr_option": "HDR",
|
||||||
"dd_hdr_option_auto": "Switch on/off the HDR mode as requested by the client (default)",
|
"dd_hdr_option_auto": "Switch on/off the HDR mode as requested by the client (default)",
|
||||||
"dd_hdr_option_disabled": "Do not change HDR settings",
|
"dd_hdr_option_disabled": "Do not change HDR settings",
|
||||||
@@ -252,6 +252,8 @@
|
|||||||
"log_level_desc": "The minimum log level printed to standard out",
|
"log_level_desc": "The minimum log level printed to standard out",
|
||||||
"log_path": "Logfile Path",
|
"log_path": "Logfile Path",
|
||||||
"log_path_desc": "The file where the current logs of Sunshine are stored.",
|
"log_path_desc": "The file where the current logs of Sunshine are stored.",
|
||||||
|
"max_bitrate": "Maximum Bitrate",
|
||||||
|
"max_bitrate_desc": "The maximum bitrate (in Kbps) that Sunshine will encode the stream at. If set to 0, it will always use the bitrate requested by Moonlight.",
|
||||||
"min_fps_factor": "Minimum FPS Factor",
|
"min_fps_factor": "Minimum FPS Factor",
|
||||||
"min_fps_factor_desc": "Sunshine will use this factor to calculate the minimum time between frames. Increasing this value slightly may help when streaming mostly static content. Higher values will consume more bandwidth.",
|
"min_fps_factor_desc": "Sunshine will use this factor to calculate the minimum time between frames. Increasing this value slightly may help when streaming mostly static content. Higher values will consume more bandwidth.",
|
||||||
"min_threads": "Minimum CPU Thread Count",
|
"min_threads": "Minimum CPU Thread Count",
|
||||||
|
|||||||
@@ -120,13 +120,14 @@
|
|||||||
</div>
|
</div>
|
||||||
<ul id="client-list" class="list-group list-group-flush list-group-item-light" v-if="clients && clients.length > 0">
|
<ul id="client-list" class="list-group list-group-flush list-group-item-light" v-if="clients && clients.length > 0">
|
||||||
<div v-for="client in clients" class="list-group-item d-flex">
|
<div v-for="client in clients" class="list-group-item d-flex">
|
||||||
<div class="p-2 flex-grow-1">{{client.name != "" ? client.name : $t('troubleshooting.unpair_single_unknown')}}</div><div class="me-2 ms-auto btn btn-danger" @click="unpairSingle(client.uuid)"><i class="fas fa-trash"></i></div>
|
<div class="p-2 flex-grow-1">{{ client.name !== "" ? client.name : $t('troubleshooting.unpair_single_unknown') }}</div>
|
||||||
|
<div class="me-2 ms-auto btn btn-danger" @click="unpairSingle(client.uuid)"><i class="fas fa-trash"></i></div>
|
||||||
</div>
|
</div>
|
||||||
</ul>
|
</ul>
|
||||||
<ul v-else class="list-group list-group-flush list-group-item-light">
|
<ul v-else class="list-group list-group-flush list-group-item-light">
|
||||||
<div class="list-group-item p-3 text-center"><em>{{ $t('troubleshooting.unpair_single_no_devices') }}</em></div>
|
<div class="list-group-item p-3 text-center"><em>{{ $t('troubleshooting.unpair_single_no_devices') }}</em></div>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<!-- Logs -->
|
<!-- Logs -->
|
||||||
<div class="card p-2 my-4">
|
<div class="card p-2 my-4">
|
||||||
@@ -176,7 +177,7 @@
|
|||||||
actualLogs() {
|
actualLogs() {
|
||||||
if (!this.logFilter) return this.logs;
|
if (!this.logFilter) return this.logs;
|
||||||
let lines = this.logs.split("\n");
|
let lines = this.logs.split("\n");
|
||||||
lines = lines.filter(x => x.indexOf(this.logFilter) != -1);
|
lines = lines.filter(x => x.indexOf(this.logFilter) !== -1);
|
||||||
return lines.join("\n");
|
return lines.join("\n");
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -210,7 +211,7 @@
|
|||||||
.then((r) => r.json())
|
.then((r) => r.json())
|
||||||
.then((r) => {
|
.then((r) => {
|
||||||
this.closeAppPressed = false;
|
this.closeAppPressed = false;
|
||||||
this.closeAppStatus = r.status.toString() === "true";
|
this.closeAppStatus = r.status;
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
this.closeAppStatus = null;
|
this.closeAppStatus = null;
|
||||||
}, 5000);
|
}, 5000);
|
||||||
@@ -222,7 +223,7 @@
|
|||||||
.then((r) => r.json())
|
.then((r) => r.json())
|
||||||
.then((r) => {
|
.then((r) => {
|
||||||
this.unpairAllPressed = false;
|
this.unpairAllPressed = false;
|
||||||
this.unpairAllStatus = r.status.toString() === "true";
|
this.unpairAllStatus = r.status;
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
this.unpairAllStatus = null;
|
this.unpairAllStatus = null;
|
||||||
}, 5000);
|
}, 5000);
|
||||||
@@ -240,9 +241,9 @@
|
|||||||
.then((response) => response.json())
|
.then((response) => response.json())
|
||||||
.then((response) => {
|
.then((response) => {
|
||||||
const clientList = document.querySelector("#client-list");
|
const clientList = document.querySelector("#client-list");
|
||||||
if (response.status === 'true' && response.named_certs && response.named_certs.length) {
|
if (response.status === true && response.named_certs && response.named_certs.length) {
|
||||||
this.clients = response.named_certs.sort((a, b) => {
|
this.clients = response.named_certs.sort((a, b) => {
|
||||||
return (a.name.toLowerCase() > b.name.toLowerCase() || a.name == "" ? 1 : -1)
|
return (a.name.toLowerCase() > b.name.toLowerCase() || a.name === "" ? 1 : -1)
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
this.clients = [];
|
this.clients = [];
|
||||||
@@ -270,7 +271,7 @@
|
|||||||
.then((r) => r.json())
|
.then((r) => r.json())
|
||||||
.then((r) => {
|
.then((r) => {
|
||||||
this.ddResetPressed = false;
|
this.ddResetPressed = false;
|
||||||
this.ddResetStatus = r.status.toString() === "true";
|
this.ddResetStatus = r.status;
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
this.ddResetStatus = null;
|
this.ddResetStatus = null;
|
||||||
}, 5000);
|
}, 5000);
|
||||||
|
|||||||
@@ -81,10 +81,10 @@
|
|||||||
body: JSON.stringify(this.passwordData),
|
body: JSON.stringify(this.passwordData),
|
||||||
}).then((r) => {
|
}).then((r) => {
|
||||||
this.loading = false;
|
this.loading = false;
|
||||||
if (r.status == 200) {
|
if (r.status === 200) {
|
||||||
r.json().then((rj) => {
|
r.json().then((rj) => {
|
||||||
if (rj.status.toString() === "true") {
|
this.success = rj.status;
|
||||||
this.success = true;
|
if (this.success === true) {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
document.location.reload();
|
document.location.reload();
|
||||||
}, 5000);
|
}, 5000);
|
||||||
|
|||||||
2
third-party/googletest
vendored
2
third-party/googletest
vendored
Submodule third-party/googletest updated: b514bdc898...6910c9d916
2
third-party/inputtino
vendored
2
third-party/inputtino
vendored
Submodule third-party/inputtino updated: 8065aeb46e...311fd2deea
2
third-party/libdisplaydevice
vendored
2
third-party/libdisplaydevice
vendored
Submodule third-party/libdisplaydevice updated: 53a0ea5317...591387c584
2
third-party/nvapi-open-source-sdk
vendored
2
third-party/nvapi-open-source-sdk
vendored
Submodule third-party/nvapi-open-source-sdk updated: cce4e90b62...c873858214
Reference in New Issue
Block a user