diff --git a/.gitignore b/.gitignore index f30be11f9..793927f8c 100644 --- a/.gitignore +++ b/.gitignore @@ -40,7 +40,8 @@ # build directories build/ cmake-*/ -docs/doxyconfig* +/.dockle/ +/_site/ # npm node_modules/ diff --git a/.gitmodules b/.gitmodules index 88f8e617f..413520198 100644 --- a/.gitmodules +++ b/.gitmodules @@ -6,9 +6,9 @@ path = third-party/build-deps url = https://github.com/LizardByte/build-deps.git branch = master -[submodule "third-party/doxyconfig"] - path = third-party/doxyconfig - url = https://github.com/LizardByte/doxyconfig.git +[submodule "third-party/dockle"] + path = third-party/dockle + url = https://github.com/LizardByte/dockle.git branch = master [submodule "third-party/glad"] path = third-party/glad diff --git a/.readthedocs.yaml b/.readthedocs.yaml index ee2f3bb2e..5011c0674 100644 --- a/.readthedocs.yaml +++ b/.readthedocs.yaml @@ -8,22 +8,23 @@ version: 2 build: os: ubuntu-24.04 tools: + nodejs: "24" python: "miniconda-latest" - commands: - - | - if [ -f readthedocs_build.sh ]; then - doxyconfig_dir="." - else - doxyconfig_dir="./third-party/doxyconfig" - fi - chmod +x "${doxyconfig_dir}/readthedocs_build.sh" - export DOXYCONFIG_DIR="${doxyconfig_dir}" - "${doxyconfig_dir}/readthedocs_build.sh" + jobs: + build: + html: + - | + if [ -f readthedocs_build.sh ]; then + dockle_dir="." + else + dockle_dir="./third-party/dockle" + fi + chmod +x "${dockle_dir}/readthedocs_build.sh" + export DOCKLE_DIR="${dockle_dir}" + "${dockle_dir}/readthedocs_build.sh" -# using conda, we can get newer doxygen and graphviz than ubuntu provide -# https://github.com/readthedocs/readthedocs.org/issues/8151#issuecomment-890359661 conda: - environment: third-party/doxyconfig/environment.yml + environment: third-party/dockle/environment.yml submodules: include: all diff --git a/DOCKER_README.md b/DOCKER_README.md index c5298035b..a7d8610e6 100644 --- a/DOCKER_README.md +++ b/DOCKER_README.md @@ -155,16 +155,3 @@ The architectures supported by these images are shown in the table below. | debian-bookworm | ✅ | ✅ | | ubuntu-22.04 | ✅ | ✅ | | ubuntu-24.04 | ✅ | ✅ | - -
- -| Previous | Next | -|:-------------------------------|-----------------------------------------------------:| -| [Changelog](docs/changelog.md) | [Third-Party Packages](docs/third_party_packages.md) | - -
- -
- - [TOC] -
diff --git a/README.md b/README.md index ccb5c3b37..bc9a6f464 100644 --- a/README.md +++ b/README.md @@ -521,16 +521,3 @@ Thank you to all the contributors who have helped make Sunshine better!

CrowdIn contributors

- -
- -| Previous | Next | -|:---------|-------------------------------------------:| -| | [Getting Started](docs/getting_started.md) | - -
- -
- - [TOC] -
diff --git a/cmake/targets/common.cmake b/cmake/targets/common.cmake index 5e7e9262f..0bdbea5a2 100644 --- a/cmake/targets/common.cmake +++ b/cmake/targets/common.cmake @@ -97,7 +97,8 @@ add_custom_target(web-ui ALL # docs if(BUILD_DOCS) - add_subdirectory(third-party/doxyconfig docs) + include(third-party/dockle/cmake/Dockle.cmake) + dockle_add_docs(docs TARGETS docs) endif() # tests diff --git a/dockle.toml b/dockle.toml new file mode 100644 index 000000000..7dee29f28 --- /dev/null +++ b/dockle.toml @@ -0,0 +1,64 @@ +[project] +name = "Sunshine" +version = "0.0.0" +description = "Self-hosted game stream host for Moonlight." +repository = "https://github.com/LizardByte/Sunshine" +logo = "sunshine.svg" +favicon = "sunshine.ico" + +[build] +output = "_site" +work = ".dockle" +strict = true +clean = true + +[[targets]] +name = "docs" +title = "Sunshine documentation" +framework = "doxygen" +source = "." +home = true + +[targets.doxygen] +inputs = [ + "README.md", + "docs/getting_started.md", + "docs/changelog.md", + "DOCKER_README.md", + "docs/third_party_packages.md", + "docs/gamestream_migration.md", + "docs/legal.md", + "docs/configuration.md", + "docs/app_examples.md", + "docs/awesome_sunshine.md", + "docs/guides.md", + "docs/performance_tuning.md", + "docs/api.md", + "docs/troubleshooting.md", + "docs/building.md", + "docs/contributing.md", + "src", +] +image_paths = ["docs/images"] +predefined = [ + "__APPLE__", + "linux", + "__linux", + "__linux__", + "__MACH__", + "_WIN32", + "SUNSHINE_BUILD_WAYLAND", + "SUNSHINE_TRAY=1", +] +extra_stylesheets = [ + "docs/doc-styles.css", + "https://cdn.jsdelivr.net/npm/@lizardbyte/shared-web@2026.920.12131/dist/crowdin-dockle-css.css", +] +extra_javascript = [ + "https://cdn.jsdelivr.net/npm/@lizardbyte/shared-web@2026.920.12131/dist/crowdin.js", + "docs/crowdin.js", +] +extra_files = ["docs/api.js", "docs/configuration.js"] +aliases = ["api_examples{3|:|}=@htmlonly@endhtmlonly"] +main_page = "README.md" +dot_graph_max_nodes = 60 diff --git a/docs/Doxyfile b/docs/Doxyfile deleted file mode 100644 index 74b3f3815..000000000 --- a/docs/Doxyfile +++ /dev/null @@ -1,67 +0,0 @@ -# This file describes the settings to be used by the documentation system -# doxygen (www.doxygen.org) for a project. -# -# All text after a double hash (##) is considered a comment and is placed in -# front of the TAG it is preceding. -# -# All text after a single hash (#) is considered a comment and will be ignored. -# The format is: -# TAG = value [value, ...] -# For lists, items can also be appended using: -# TAG += value [value, ...] -# Values that contain spaces should be placed between quotes (\" \"). -# -# Note: -# -# Use doxygen to compare the used configuration file with the template -# configuration file: -# doxygen -x [configFile] -# Use doxygen to compare the used configuration file with the template -# configuration file without replacing the environment variables or CMake type -# replacement variables: -# doxygen -x_noenv [configFile] - -# project metadata -DOCSET_BUNDLE_ID = dev.lizardbyte.Sunshine -DOCSET_PUBLISHER_ID = dev.lizardbyte.Sunshine.documentation -PROJECT_BRIEF = "Self-hosted game stream host for Moonlight." -PROJECT_ICON = ../sunshine.ico -PROJECT_LOGO = ../sunshine.svg -PROJECT_NAME = Sunshine - -# project specific settings -DOT_GRAPH_MAX_NODES = 60 -IMAGE_PATH = ../docs/images -PREDEFINED += SUNSHINE_BUILD_WAYLAND -PREDEFINED += SUNSHINE_TRAY=1 - -# files and directories to process -USE_MDFILE_AS_MAINPAGE = ../README.md -INPUT = ../README.md \ - getting_started.md \ - changelog.md \ - ../DOCKER_README.md \ - third_party_packages.md \ - gamestream_migration.md \ - legal.md \ - configuration.md \ - app_examples.md \ - awesome_sunshine.md \ - guides.md \ - performance_tuning.md \ - api.md \ - troubleshooting.md \ - building.md \ - contributing.md \ - ../third-party/doxyconfig/docs/source_code.md \ - ../src - -# extra css -HTML_EXTRA_STYLESHEET += doc-styles.css - -# extra js -HTML_EXTRA_FILES += api.js -HTML_EXTRA_FILES += configuration.js - -# custom aliases -ALIASES += api_examples{3|}="@htmlonly@endhtmlonly" diff --git a/docs/api.js b/docs/api.js index 90f035c50..4b8512476 100644 --- a/docs/api.js +++ b/docs/api.js @@ -43,102 +43,27 @@ requests.${method.trim().toLowerCase()}( }; } -/** - * @brief Create a stable signed 32-bit hash for a string. - * - * @param {string} str String to hash. - * @return {number} Signed 32-bit hash value. - */ -function hashString(str) { - let hash = 0; - const signedHash = new Int32Array(1); - for (const character of str) { - const codePoint = character.codePointAt(0); - hash = hash * 31 + codePoint; - signedHash[0] = hash; - hash = signedHash[0]; - } - return hash; +function escapeHtml(value) { + return value + .replaceAll('&', '&') + .replaceAll('<', '<') + .replaceAll('>', '>') + .replaceAll('"', '"') + .replaceAll("'", '''); } function createTabs(examples) { - const languages = Object.keys(examples); - let tabs = '
'; - let content = '
'; + const languages = { + cURL: 'bash', + Python: 'python', + JavaScript: 'javascript', + PowerShell: 'powershell' + }; + const tabs = Object.entries(examples).map(([label, example]) => ` +
  • + ${escapeHtml(label)} +
    ${escapeHtml(example)}
    +
  • `).join(''); - languages.forEach((lang, index) => { - const hash = hashString(examples[lang]); - tabs += ``; - content += `
    -
    -
    - ${examples[lang].split('\n').map(line => `
    ${line}
    `).join('')} -
    - - - - - - -
    -
    `; - }); - - tabs += '
    '; - content += '
    '; - - setTimeout(() => { - languages.forEach((lang, index) => { - const hash = hashString(examples[lang]); - const copyButton = document.getElementById(`copy-button-${lang}-${hash}`); - copyButton.addEventListener('click', copyContent); - }); - }, 0); - - return tabs + content; -} - -function copyContent() { - const content = this.previousElementSibling.cloneNode(true); - if (content instanceof Element) { - // filter out line number from file listings - content.querySelectorAll(".lineno, .ttc").forEach((node) => { - node.remove(); - }); - let textContent = Array.from(content.querySelectorAll('.line')) - .map(line => line.innerText) - .join('\n') - .trim(); // Join lines with newline characters and trim leading/trailing whitespace - navigator.clipboard.writeText(textContent); - this.classList.add("success"); - this.innerHTML = ``; - window.setTimeout(() => { - this.classList.remove("success"); - this.innerHTML = ``; - }, 980); - } else { - console.error('Failed to copy: content is not a DOM element'); - } -} - -function openTab(evt, lang) { - const tabcontent = document.getElementsByClassName("tabcontent"); - for (const content of tabcontent) { - content.style.display = "none"; - } - - const tablinks = document.getElementsByClassName("tab-button"); - for (const link of tablinks) { - link.className = link.className.replace(" active", ""); - } - - const selectedTabs = document.querySelectorAll(`#${lang}`); - for (const tab of selectedTabs) { - tab.style.display = "block"; - } - - const selectedButtons = document.querySelectorAll(`.tab-button[onclick*="${lang}"]`); - for (const button of selectedButtons) { - button.className += " active"; - } + return `
    `; } diff --git a/docs/api.md b/docs/api.md index 143827de7..9ba232415 100644 --- a/docs/api.md +++ b/docs/api.md @@ -99,16 +99,3 @@ curl -u user:pass -H "X-CSRF-Token: your_token_here" \ ## GET /api/virtual-input/status @copydoc confighttp::getVirtualInputStatus() - -
    - -| Previous | Next | -|:--------------------------------------------|--------------------------------------:| -| [Performance Tuning](performance_tuning.md) | [Troubleshooting](troubleshooting.md) | - -
    - -
    - - [TOC] -
    diff --git a/docs/app_examples.md b/docs/app_examples.md index 2769ea413..cd86bf360 100644 --- a/docs/app_examples.md +++ b/docs/app_examples.md @@ -25,36 +25,36 @@ and applications to Sunshine. > Steam is launched as a detached command because Steam starts with a process that self updates itself and the original > process is killed. -@tabs{ - @tab{FreeBSD | +@tabs_grouped{platform|:| + @tab{FreeBSD |:| \| Field \| Value \| \|------------------------------\|------------------------------------------------------\| \| Application Name \| @code{}Steam Big Picture@endcode \| - \| Command Preporations -> Undo \| @code{}setsid steam steam://close/bigpicture@endcode \| + \| Command Preparations -> Undo \| @code{}setsid steam steam://close/bigpicture@endcode \| \| Detached Commands \| @code{}setsid steam steam://open/bigpicture@endcode \| \| Image \| @code{}steam.png@endcode \| } - @tab{Linux | + @tab{Linux |:| \| Field \| Value \| \|------------------------------\|------------------------------------------------------\| \| Application Name \| @code{}Steam Big Picture@endcode \| - \| Command Preporations -> Undo \| @code{}setsid steam steam://close/bigpicture@endcode \| + \| Command Preparations -> Undo \| @code{}setsid steam steam://close/bigpicture@endcode \| \| Detached Commands \| @code{}setsid steam steam://open/bigpicture@endcode \| \| Image \| @code{}steam.png@endcode \| } - @tab{macOS | + @tab{macOS |:| \| Field \| Value \| \|------------------------------\|------------------------------------------------\| \| Application Name \| @code{}Steam Big Picture@endcode \| - \| Command Preporations -> Undo \| @code{}open steam://close/bigpicture@endcode \| + \| Command Preparations -> Undo \| @code{}open steam://close/bigpicture@endcode \| \| Detached Commands \| @code{}open steam://open/bigpicture@endcode \| \| Image \| @code{}steam.png@endcode \| } - @tab{Windows | + @tab{Windows |:| \| Field \| Value \| \|------------------------------\|-------------------------------------------\| \| Application Name \| @code{}Steam Big Picture@endcode \| - \| Command Preporations -> Undo \| @code{}steam://close/bigpicture@endcode \| + \| Command Preparations -> Undo \| @code{}steam://close/bigpicture@endcode \| \| Detached Commands \| @code{}steam://open/bigpicture@endcode \| \| Image \| @code{}steam.png@endcode \| } @@ -67,8 +67,8 @@ and applications to Sunshine. #### URI -@tabs{ - @tab{Windows | +@tabs_grouped{platform|:| + @tab{Windows |:| \| Field \| Value \| \|------------------\|-------------------------------------------------------------------------------------------------------------------------------------------------------\| \| Application Name \| @code{}Surviving Mars@endcode \| @@ -77,8 +77,8 @@ and applications to Sunshine. } #### Binary (w/ working directory -@tabs{ - @tab{Windows | +@tabs_grouped{platform|:| + @tab{Windows |:| \| Field \| Value \| \|-------------------\|------------------------------------------------------------\| \| Application Name \| @code{}Surviving Mars@endcode \| @@ -88,8 +88,8 @@ and applications to Sunshine. } #### Binary (w/o working directory) -@tabs{ - @tab{Windows | +@tabs_grouped{platform|:| + @tab{Windows |:| \| Field \| Value \| \|-------------------\|-------------------------------------------------------------------------\| \| Application Name \| @code{}Surviving Mars@endcode \| @@ -104,26 +104,26 @@ and applications to Sunshine. #### URI -@tabs{ - @tab{FreeBSD | +@tabs_grouped{platform|:| + @tab{FreeBSD |:| \| Field \| Value \| \|-------------------\|------------------------------------------------------\| \| Application Name \| @code{}Surviving Mars@endcode \| \| Detached Commands \| @code{}setsid steam steam://rungameid/464920@endcode \| } - @tab{Linux | + @tab{Linux |:| \| Field \| Value \| \|-------------------\|------------------------------------------------------\| \| Application Name \| @code{}Surviving Mars@endcode \| \| Detached Commands \| @code{}setsid steam steam://rungameid/464920@endcode \| } - @tab{macOS | + @tab{macOS |:| \| Field \| Value \| \|-------------------\|----------------------------------------------\| \| Application Name \| @code{}Surviving Mars@endcode \| \| Detached Commands \| @code{}open steam://rungameid/464920@endcode \| } - @tab{Windows | + @tab{Windows |:| \| Field \| Value \| \|-------------------\|-----------------------------------------\| \| Application Name \| @code{}Surviving Mars@endcode \| @@ -132,29 +132,29 @@ and applications to Sunshine. } #### Binary (w/ working directory -@tabs{ - @tab{FreeBSD | +@tabs_grouped{platform|:| + @tab{FreeBSD |:| \| Field \| Value \| \|-------------------\|--------------------------------------------------------------\| \| Application Name \| @code{}Surviving Mars@endcode \| \| Command \| @code{}MarsSteam@endcode \| \| Working Directory \| @code{}$(HOME)/.steam/steam/SteamApps/common/Survivng Mars@endcode \| } - @tab{Linux | + @tab{Linux |:| \| Field \| Value \| \|-------------------\|--------------------------------------------------------------\| \| Application Name \| @code{}Surviving Mars@endcode \| \| Command \| @code{}MarsSteam@endcode \| \| Working Directory \| @code{}$(HOME)/.steam/steam/SteamApps/common/Survivng Mars@endcode \| } - @tab{macOS | + @tab{macOS |:| \| Field \| Value \| \|-------------------\|--------------------------------------------------------------\| \| Application Name \| @code{}Surviving Mars@endcode \| \| Command \| @code{}MarsSteam@endcode \| \| Working Directory \| @code{}$(HOME)/.steam/steam/SteamApps/common/Survivng Mars@endcode \| } - @tab{Windows | + @tab{Windows |:| \| Field \| Value \| \|-------------------\|-------------------------------------------------------------------------------\| \| Application Name \| @code{}Surviving Mars@endcode \| @@ -164,26 +164,26 @@ and applications to Sunshine. } #### Binary (w/o working directory) -@tabs{ - @tab{FreeBSD | +@tabs_grouped{platform|:| + @tab{FreeBSD |:| \| Field \| Value \| \|-------------------\|------------------------------------------------------------------------\| \| Application Name \| @code{}Surviving Mars@endcode \| \| Command \| @code{}$(HOME)/.steam/steam/SteamApps/common/Survivng Mars/MarsSteam@endcode \| } - @tab{Linux | + @tab{Linux |:| \| Field \| Value \| \|-------------------\|------------------------------------------------------------------------\| \| Application Name \| @code{}Surviving Mars@endcode \| \| Command \| @code{}$(HOME)/.steam/steam/SteamApps/common/Survivng Mars/MarsSteam@endcode \| } - @tab{macOS | + @tab{macOS |:| \| Field \| Value \| \|-------------------\|------------------------------------------------------------------------\| \| Application Name \| @code{}Surviving Mars@endcode \| \| Command \| @code{}$(HOME)/.steam/steam/SteamApps/common/Survivng Mars/MarsSteam@endcode \| } - @tab{Windows | + @tab{Windows |:| \| Field \| Value \| \|-------------------\|---------------------------------------------------------------------------------------------\| \| Application Name \| @code{}Surviving Mars@endcode \| @@ -371,16 +371,3 @@ UAC prompt. "image-path": "" } ``` - -
    - -| Previous | Next | -|:----------------------------------|----------------------------------------:| -| [Configuration](configuration.md) | [Awesome-Sunshine](awesome_sunshine.md) | - -
    - -
    - - [TOC] -
    diff --git a/docs/awesome_sunshine.md b/docs/awesome_sunshine.md index 554c8113e..34c4b0e91 100644 --- a/docs/awesome_sunshine.md +++ b/docs/awesome_sunshine.md @@ -8,16 +8,3 @@ src="https://raw.githubusercontent.com/LizardByte/awesome-sunshine/master/README.md"> @endhtmlonly - -
    - -| Previous | Next | -|:--------------------------------|--------------------:| -| [App Examples](app_examples.md) | [Guides](guides.md) | - -
    - -
    - - [TOC] -
    diff --git a/docs/building.md b/docs/building.md index 6069a38d2..726ba52a5 100644 --- a/docs/building.md +++ b/docs/building.md @@ -135,11 +135,11 @@ brew install "${dependencies[@]}" If there are issues with an SSL header that is not found: -@tabs{ - @tab{ Intel | ```bash +@tabs_grouped{mac-architecture|:| + @tab{ Intel |:| ```bash ln -s /usr/local/opt/openssl/include/openssl /usr/local/include/openssl ```} - @tab{ Apple Silicon | ```bash + @tab{ Apple Silicon |:| ```bash ln -s /opt/homebrew/opt/openssl/include/openssl /opt/homebrew/include/openssl ``` } @@ -249,33 +249,33 @@ ninja -C build ### Package -@tabs{ - @tab{FreeBSD | @tabs{ - @tab{pkg | ```bash +@tabs_grouped{platform|:| + @tab{FreeBSD |:| @tabs{ + @tab{pkg |:| ```bash cpack -G FREEBSD --config ./build/CPackConfig.cmake ```} }} - @tab{Linux | @tabs{ - @tab{deb | ```bash + @tab{Linux |:| @tabs{ + @tab{deb |:| ```bash cpack -G DEB --config ./build/CPackConfig.cmake ```} - @tab{rpm | ```bash + @tab{rpm |:| ```bash cpack -G RPM --config ./build/CPackConfig.cmake ```} }} - @tab{macOS | @tabs{ - @tab{DragNDrop | ```bash + @tab{macOS |:| @tabs{ + @tab{DragNDrop |:| ```bash cpack -G DragNDrop --config ./build/CPackConfig.cmake ```} }} - @tab{Windows | @tabs{ - @tab{NSIS Installer | ```bash + @tab{Windows |:| @tabs{ + @tab{NSIS Installer |:| ```bash cpack -G NSIS --config ./build/CPackConfig.cmake ```} - @tab{WiX Installer | ```bash + @tab{WiX Installer |:| ```bash cpack -G WIX --config ./build/CPackConfig.cmake ```} - @tab{Portable | ```bash + @tab{Portable |:| ```bash cpack -G ZIP --config ./build/CPackConfig.cmake ```} }} @@ -288,16 +288,3 @@ It may be beneficial to build remotely in some cases. This will enable easier bu 2. Activate workflows 3. Trigger the *CI* workflow manually 4. Download the artifacts/binaries from the workflow run summary - -
    - -| Previous | Next | -|:--------------------------------------|--------------------------------:| -| [Troubleshooting](troubleshooting.md) | [Contributing](contributing.md) | - -
    - -
    - - [TOC] -
    diff --git a/docs/changelog.md b/docs/changelog.md index 9cf35f269..9a5069a50 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -7,16 +7,3 @@ src="https://raw.githubusercontent.com/LizardByte/Sunshine/changelog/CHANGELOG.md"> @endhtmlonly - -
    - -| Previous | Next | -|:--------------------------------------|------------------------------:| -| [Getting Started](getting_started.md) | [Docker](../DOCKER_README.md) | - -
    - -
    - - [TOC] -
    diff --git a/docs/configuration.js b/docs/configuration.js index 8adb78d0d..ecccabbef 100644 --- a/docs/configuration.js +++ b/docs/configuration.js @@ -19,12 +19,16 @@ document.addEventListener("DOMContentLoaded", function() { const newCell = document.createElement("td"); newCell.setAttribute("colspan", "3"); - const newCode = document.createElement("code"); - newCode.className = "open-button"; - newCode.setAttribute("onclick", `window.open('https://${document.getElementById('host-authority').value}/config/#${sectionId}', '_blank')`); - newCode.textContent = "Open"; + const openButton = document.createElement("button"); + openButton.className = "open-button"; + openButton.type = "button"; + openButton.textContent = "Open configuration"; + openButton.addEventListener("click", () => { + const authority = document.getElementById("host-authority").value; + window.open(`https://${authority}/config/#${sectionId}`, "_blank", "noopener"); + }); - newCell.appendChild(newCode); + newCell.appendChild(openButton); newRow.appendChild(newCell); // get the table body diff --git a/docs/configuration.md b/docs/configuration.md index 7b0ff4da6..d1b12b3c1 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -1,6 +1,6 @@ # Configuration -@admonition{ Host authority | @htmlonly +@admonition{ Host authority |:| @htmlonly By providing the host authority (URI + port), you can easily open each configuration option in the config UI.
    @@ -3455,16 +3455,3 @@ supported on the current platform. good for fast encoding and low-latency streaming - -
    - -| Previous | Next | -|:------------------|--------------------------------:| -| [Legal](legal.md) | [App Examples](app_examples.md) | - -
    - -
    - - [TOC] -
    diff --git a/docs/contributing.md b/docs/contributing.md index 977423aa6..7197def4f 100644 --- a/docs/contributing.md +++ b/docs/contributing.md @@ -23,11 +23,11 @@ Read our contribution guide in our organization level #### Building @tabs{ - @tab{CMake | ```bash + @tab{CMake |:| ```bash cmake -B build -G Ninja -S . --target web-ui ninja -C build web-ui ```} - @tab{Manual | ```bash + @tab{Manual |:| ```bash npm run dev ```} } @@ -46,7 +46,7 @@ The default language is `en` (English). ![](https://app.lizardbyte.dev/dashboard/crowdin/LizardByte_graph.svg) -@admonition{Community | We are looking for language coordinators to help approve translations. +@admonition{Community |:| We are looking for language coordinators to help approve translations. The goal is to have the bars above filled with green! If you are interested, please reach out to us on our Discord server.} @@ -210,16 +210,3 @@ Even if your changes cannot be covered in the CI, we still encourage you to writ maintainers to run the tests locally. [crowdin-url]: https://translate.lizardbyte.dev - -
    - -| Previous | Next | -|:------------------------|-------------------------------------------------------------:| -| [Building](building.md) | [Source Code](../third-party/doxyconfig/docs/source_code.md) | - -
    - -
    - - [TOC] -
    diff --git a/docs/crowdin.js b/docs/crowdin.js new file mode 100644 index 000000000..8160fd180 --- /dev/null +++ b/docs/crowdin.js @@ -0,0 +1 @@ +globalThis.initCrowdIn('LizardByte-docs', 'dockle') diff --git a/docs/doc-styles.css b/docs/doc-styles.css index 1505e851e..339811791 100644 --- a/docs/doc-styles.css +++ b/docs/doc-styles.css @@ -1,6 +1,21 @@ -/* A fake button as doxygen doesn't allow button elements */ +/* Link generated configuration actions to Sunshine's web UI. */ .open-button { - background: var(--primary-color); - color: white; - cursor: pointer; + background: var(--dockle-primary); + border: 1px solid color-mix(in srgb, var(--dockle-primary) 75%, black); + border-radius: var(--dockle-radius); + color: white; + cursor: pointer; + font: inherit; + font-weight: 650; + padding: 0.5rem 0.8rem; +} + +.open-button:hover, +.open-button:focus-visible { + filter: brightness(1.1); +} + +.open-button:focus-visible { + outline: 2px solid color-mix(in srgb, var(--dockle-primary) 40%, transparent); + outline-offset: 2px; } diff --git a/docs/gamestream_migration.md b/docs/gamestream_migration.md index 5018ba585..f281927fe 100644 --- a/docs/gamestream_migration.md +++ b/docs/gamestream_migration.md @@ -22,16 +22,3 @@ Sunshine does have some limitations, as compared to Nvidia GameStream. * Automatic game/application list. * Changing game settings automatically to optimize streaming. - -
    - -| Previous | Next | -|:------------------------------------------------|------------------:| -| [Third-party Packages](third_party_packages.md) | [Legal](legal.md) | - -
    - -
    - - [TOC] -
    diff --git a/docs/getting_started.md b/docs/getting_started.md index 07dfd991c..2a3eb1214 100644 --- a/docs/getting_started.md +++ b/docs/getting_started.md @@ -195,11 +195,11 @@ pacman -R sunshine Configure the `stable` repository for releases or the `beta` repository for prereleases. The setup script automatically selects the appropriate Debian or Ubuntu release. -@tabs{ - @tab_with_pipe{ Stable |:| ```bash +@tabs_grouped{release-channel|:| + @tab{ Stable |:| ```bash curl -1sLf 'https://dl.cloudsmith.io/public/lizardbyte/stable/cfg/setup/bash.deb.sh' | sudo -E bash ```} - @tab_with_pipe{ Beta |:| ```bash + @tab{ Beta |:| ```bash curl -1sLf 'https://dl.cloudsmith.io/public/lizardbyte/beta/cfg/setup/bash.deb.sh' | sudo -E bash ```} } @@ -240,22 +240,22 @@ sudo apt remove sunshine Configure the `stable` repository for releases or the `beta` repository for prereleases. Cloudsmith's setup script automatically selects Fedora or openSUSE and the appropriate release. -@tabs{ - @tab_with_pipe{ Stable |:| ```bash +@tabs_grouped{release-channel|:| + @tab{ Stable |:| ```bash curl -1sLf 'https://dl.cloudsmith.io/public/lizardbyte/stable/cfg/setup/bash.rpm.sh' | sudo -E bash ```} - @tab_with_pipe{ Beta |:| ```bash + @tab{ Beta |:| ```bash curl -1sLf 'https://dl.cloudsmith.io/public/lizardbyte/beta/cfg/setup/bash.rpm.sh' | sudo -E bash ```} } Install Sunshine with your distribution's package manager. -@tabs{ - @tab{ Fedora | ```bash +@tabs_grouped{distribution|:| + @tab{ Fedora |:| ```bash sudo dnf install Sunshine ```} - @tab{ openSUSE | ```bash + @tab{ openSUSE |:| ```bash sudo zypper install Sunshine ```} } @@ -264,11 +264,11 @@ Install Sunshine with your distribution's package manager. Download `Sunshine-{version}-1.{distro+version}.{arch}.rpm` and run the following command. -@tabs{ - @tab{ Fedora | ```bash +@tabs_grouped{distribution|:| + @tab{ Fedora |:| ```bash sudo dnf install ./Sunshine-{version}-1.{distro+version}.{arch}.rpm ```} - @tab{ openSUSE | ```bash + @tab{ openSUSE |:| ```bash sudo zypper install ./Sunshine-{version}-1.{distro+version}.{arch}.rpm ```} } @@ -282,11 +282,11 @@ Download `Sunshine-{version}-1.{distro+version}.{arch}.rpm` and run the followin ##### Uninstall -@tabs{ - @tab{ Fedora | ```bash +@tabs_grouped{distribution|:| + @tab{ Fedora |:| ```bash sudo dnf remove Sunshine ```} - @tab{ openSUSE | ```bash + @tab{ openSUSE |:| ```bash sudo zypper remove Sunshine ```} } @@ -678,19 +678,20 @@ by default. You may replace *localhost* with your internal ip address. 7. If you run into issues, logs are available in the `Troubleshooting` tab. You can navigate through each warning/error message for clues to the issue. + ![Logs](images/troubleshooting-logs.png) ### Arguments To get a list of available arguments, run the following command. -@tabs{ - @tab{ General | ```bash +@tabs_grouped{linux-package|:| + @tab{ General |:| ```bash sunshine --help ```} - @tab{ AppImage | ```bash + @tab{ AppImage |:| ```bash ./Sunshine_{version}_{arch}.AppImage --help ```} - @tab{ Flatpak | ```bash + @tab{ Flatpak |:| ```bash flatpak run --command=sunshine dev.lizardbyte.app.Sunshine --help ```} } @@ -755,14 +756,14 @@ Streaming HDR content is officially supported on Windows hosts and experimentall Additional information: -@tabs{ - @tab{ Windows | +@tabs_grouped{platform|:| + @tab{ Windows |:| - HDR streaming is supported for Intel, AMD, and NVIDIA GPUs that support encoding HEVC Main 10 or AV1 10-bit profiles. - We recommend calibrating the display by streaming the Windows HDR Calibration app to your client device and saving an HDR calibration profile to use while streaming. - Older games that use NVIDIA-specific NVAPI HDR rather than native Windows HDR support may not display properly in HDR. } -@tab{ Linux | +@tab{ Linux |:| - HDR streaming is supported for Intel and AMD GPUs that support encoding HEVC Main 10 or AV1 10-bit profiles using VAAPI. - The KMS capture backend is required for HDR capture. Other capture methods, like NvFBC or X11, do not support HDR. - You will need a desktop environment with a compositor that supports HDR rendering, such as Gamescope or KDE Plasma 6. @@ -777,20 +778,8 @@ Tutorial videos are available [here](https://www.youtube.com/playlist?list=PLMYr Guides are available [here](guides.md). -@admonition{Community! | +@admonition{Community! |:| Tutorials and Guides are community generated. Want to contribute? Reach out to us on our discord server.} -
    - -| Previous | Next | -|:-------------------------|--------------------------:| -| [Overview](../README.md) | [Changelog](changelog.md) | - -
    - -
    - - [TOC] -
    [latest-release]: https://github.com/LizardByte/Sunshine/releases/latest diff --git a/docs/guides.md b/docs/guides.md index 8f3d056dc..5d22d159a 100644 --- a/docs/guides.md +++ b/docs/guides.md @@ -1,19 +1,6 @@ # Guides -@admonition{Community | A collection of guides written by the community is available on our +@admonition{Community |:| A collection of guides written by the community is available on our [blog](https://app.lizardbyte.dev/blog). Feel free to contribute your own tips and trips by making a PR to [LizardByte.github.io](https://github.com/LizardByte/LizardByte.github.io).} - -
    - -| Previous | Next | -|:----------------------------------------|--------------------------------------------:| -| [Awesome-Sunshine](awesome_sunshine.md) | [Performance Tuning](performance_tuning.md) | - -
    - -
    - - [TOC] -
    diff --git a/docs/legal.md b/docs/legal.md index d171389fc..deb0b111c 100644 --- a/docs/legal.md +++ b/docs/legal.md @@ -19,16 +19,3 @@ Motion Picture Experts Group (MPEG-LA) and/or any other necessary licensing requ In summary, while Sunshine is free to use, it is the user's responsibility to ensure compliance with all applicable licensing requirements when redistributing the software as part of a commercial offering. If you have any questions or concerns about using Sunshine in a commercial setting, we recommend consulting with a lawyer. - -
    - -| Previous | Next | -|:------------------------------------------------|----------------------------------:| -| [Gamestream Migration](gamestream_migration.md) | [Configuration](configuration.md) | - -
    - -
    - - [TOC] -
    diff --git a/docs/performance_tuning.md b/docs/performance_tuning.md index b4418f6d7..7c375a97c 100644 --- a/docs/performance_tuning.md +++ b/docs/performance_tuning.md @@ -10,16 +10,3 @@ applies to `amfenc` and `libx264`. ## NVIDIA Enabling *Fast Sync* in Nvidia settings may help reduce latency. - -
    - -| Previous | Next | -|:--------------------|--------------:| -| [Guides](guides.md) | [API](api.md) | - -
    - -
    - - [TOC] -
    diff --git a/docs/third_party_packages.md b/docs/third_party_packages.md index 33b18e14d..0d00422cb 100644 --- a/docs/third_party_packages.md +++ b/docs/third_party_packages.md @@ -14,16 +14,3 @@ ## Solus [![Solus](https://img.shields.io/badge/dynamic/xml.svg?color=orange&label=Solus&style=for-the-badge&prefix=v&query=%2F%2Ftr%5B%40id%3D%27solus%27%5D%2Ftd%5B3%5D%2Fspan%2Fa&url=https%3A%2F%2Frepology.org%2Fproject%2Fsunshine%2Fversions&logo=solus)](https://dev.getsol.us/source/sunshine) - -
    - -| Previous | Next | -|:------------------------------|------------------------------------------------:| -| [Docker](../DOCKER_README.md) | [Gamestream Migration](gamestream_migration.md) | - -
    - -
    - - [TOC] -
    diff --git a/docs/troubleshooting.md b/docs/troubleshooting.md index 6fa16fcc6..3a40f3993 100644 --- a/docs/troubleshooting.md +++ b/docs/troubleshooting.md @@ -5,16 +5,16 @@ ### Forgotten Credentials If you forgot your credentials to the web UI, try this. -@tabs{ - @tab{General | ```bash +@tabs_grouped{linux-package|:| + @tab{General |:| ```bash sunshine --creds {new-username} {new-password} ``` } - @tab{AppImage | ```bash + @tab{AppImage |:| ```bash ./sunshine.AppImage --creds {new-username} {new-password} ``` } - @tab{Flatpak | ```bash + @tab{Flatpak |:| ```bash flatpak run --command=sunshine dev.lizardbyte.app.Sunshine --creds {new-username} {new-password} ``` } @@ -193,11 +193,11 @@ restarts. Approve the Remote Desktop prompt and select the display to capture wh If the Web UI is inaccessible, stop Sunshine and delete the token manually: @tabs{ - @tab{Linux / FreeBSD | ```bash + @tab{Linux / FreeBSD |:| ```bash rm "${XDG_CONFIG_HOME:-$HOME/.config}/sunshine/portal_token" ``` } - @tab{Flatpak | ```bash + @tab{Flatpak |:| ```bash rm "$HOME/.var/app/dev.lizardbyte.app.Sunshine/config/sunshine/portal_token" ``` } @@ -385,16 +385,3 @@ permissions on the disk. ### Stuttering If you experience stuttering using NVIDIA, try disabling `vsync:fast` in the NVIDIA Control Panel. - -
    - -| Previous | Next | -|:--------------|------------------------:| -| [API](api.md) | [Building](building.md) | - -
    - -
    - - [TOC] -
    diff --git a/src/confighttp.cpp b/src/confighttp.cpp index 56608e122..5bfcf1f20 100644 --- a/src/confighttp.cpp +++ b/src/confighttp.cpp @@ -1004,7 +1004,7 @@ namespace confighttp { * @param response The HTTP response object. * @param request The HTTP request object. * - * @api_examples{/api/csrf-token| GET| null} + * @api_examples{/api/csrf-token|:| GET|:| null} */ void getCSRFToken(const resp_https_t &response, const req_https_t &request) { if (!authenticate(response, request)) { @@ -1026,7 +1026,7 @@ namespace confighttp { * @param response The HTTP response object. * @param request The HTTP request object. * - * @api_examples{/api/apps| GET| null} + * @api_examples{/api/apps|:| GET|:| null} */ void getApps(const resp_https_t &response, const req_https_t &request) { if (!authenticate(response, request)) { @@ -1111,7 +1111,7 @@ namespace confighttp { * } * @endcode * - * @api_examples{/api/apps| POST| {"name":"Hello, World!","index":-1}} + * @api_examples{/api/apps|:| POST|:| {"name":"Hello, World!","index":-1}} */ void saveApp(const resp_https_t &response, const req_https_t &request) { if (!check_content_type(response, request, "application/json")) { @@ -1186,7 +1186,7 @@ namespace confighttp { * @param response The HTTP response object. * @param request The HTTP request object. * - * @api_examples{/api/apps/close| POST| null} + * @api_examples{/api/apps/close|:| POST|:| null} */ void closeApp(const resp_https_t &response, const req_https_t &request) { if (!authenticate(response, request)) { @@ -1212,7 +1212,7 @@ namespace confighttp { * @param response The HTTP response object. * @param request The HTTP request object. * - * @api_examples{/api/apps/9999| DELETE| null} + * @api_examples{/api/apps/9999|:| DELETE|:| null} */ void deleteApp(const resp_https_t &response, const req_https_t &request) { if (!authenticate(response, request)) { @@ -1263,7 +1263,7 @@ namespace confighttp { * @param response The HTTP response object. * @param request The HTTP request object. * - * @api_examples{/api/clients/list| GET| null} + * @api_examples{/api/clients/list|:| GET|:| null} */ void getClients(const resp_https_t &response, const req_https_t &request) { if (!authenticate(response, request)) { @@ -1292,7 +1292,7 @@ namespace confighttp { * } * @endcode * - * @api_examples{/api/clients/update| POST| {"uuid":"","enabled":true}} + * @api_examples{/api/clients/update|:| POST|:| {"uuid":"","enabled":true}} */ void updateClient(resp_https_t response, req_https_t request) { if (!check_content_type(response, request, "application/json")) { @@ -1346,7 +1346,7 @@ namespace confighttp { * } * @endcode * - * @api_examples{/api/unpair| POST| {"uuid":"1234"}} + * @api_examples{/api/unpair|:| POST|:| {"uuid":"1234"}} */ void unpair(const resp_https_t &response, const req_https_t &request) { if (!check_content_type(response, request, "application/json")) { @@ -1390,7 +1390,7 @@ namespace confighttp { * @param response The HTTP response object. * @param request The HTTP request object. * - * @api_examples{/api/clients/unpair-all| POST| null} + * @api_examples{/api/clients/unpair-all|:| POST|:| null} */ void unpairAll(const resp_https_t &response, const req_https_t &request) { if (!authenticate(response, request)) { @@ -1417,7 +1417,7 @@ namespace confighttp { * @param response The HTTP response object. * @param request The HTTP request object. * - * @api_examples{/api/config| GET| null} + * @api_examples{/api/config|:| GET|:| null} */ void getConfig(const resp_https_t &response, const req_https_t &request) { if (!authenticate(response, request)) { @@ -1445,7 +1445,7 @@ namespace confighttp { * @param response The HTTP response object. * @param request The HTTP request object. * - * @api_examples{/api/configLocale| GET| null} + * @api_examples{/api/configLocale|:| GET|:| null} */ void getLocale(const resp_https_t &response, const req_https_t &request) { // we need to return the locale whether authenticated or not @@ -1471,7 +1471,7 @@ namespace confighttp { * * @attention{It is recommended to ONLY save the config settings that differ from the default behavior.} * - * @api_examples{/api/config| POST| {"key":"value"}} + * @api_examples{/api/config|:| POST|:| {"key":"value"}} */ void saveConfig(const resp_https_t &response, const req_https_t &request) { if (!check_content_type(response, request, "application/json")) { @@ -1520,7 +1520,7 @@ namespace confighttp { * * @note{The index in the url path is the application index.} * - * @api_examples{/api/covers/9999 | GET| null} + * @api_examples{/api/covers/9999 |:| GET|:| null} */ void getCover(const resp_https_t &response, const req_https_t &request) { if (!authenticate(response, request)) { @@ -1590,7 +1590,7 @@ namespace confighttp { * } * @endcode * - * @api_examples{/api/covers/upload| POST| {"key":"igdb_1234","url":"https://images.igdb.com/igdb/image/upload/t_cover_big_2x/abc123.png"}} + * @api_examples{/api/covers/upload|:| POST|:| {"key":"igdb_1234","url":"https://images.igdb.com/igdb/image/upload/t_cover_big_2x/abc123.png"}} */ void uploadCover(const resp_https_t &response, const req_https_t &request) { if (!check_content_type(response, request, "application/json")) { @@ -1646,7 +1646,7 @@ namespace confighttp { * @param response The HTTP response object. * @param request The HTTP request object. * - * @api_examples{/api/logs| GET| null} + * @api_examples{/api/logs|:| GET|:| null} */ void getLogs(const resp_https_t &response, const req_https_t &request) { if (!authenticate(response, request)) { @@ -1678,7 +1678,7 @@ namespace confighttp { * } * @endcode * - * @api_examples{/api/password| POST| {"currentUsername":"admin","currentPassword":"admin","newUsername":"admin","newPassword":"admin","confirmNewPassword":"admin"}} + * @api_examples{/api/password|:| POST|:| {"currentUsername":"admin","currentPassword":"admin","newUsername":"admin","newPassword":"admin","confirmNewPassword":"admin"}} */ void savePassword(const resp_https_t &response, const req_https_t &request) { if (!check_content_type(response, request, "application/json")) { @@ -1747,7 +1747,7 @@ namespace confighttp { /** * @brief List client pairing requests that are waiting for PIN approval. * - * @api_examples{/api/pin| GET| null} + * @api_examples{/api/pin|:| GET|:| null} */ void getPendingPairings(const resp_https_t &response, const req_https_t &request) { if (!authenticate(response, request)) { @@ -1777,7 +1777,7 @@ namespace confighttp { * } * @endcode * - * @api_examples{/api/pin| DELETE| {"pairing_id":"0123456789abcdef0123456789abcdef"}} + * @api_examples{/api/pin|:| DELETE|:| {"pairing_id":"0123456789abcdef0123456789abcdef"}} */ void cancelPairing(const resp_https_t &response, const req_https_t &request) { if (!check_content_type(response, request, "application/json")) { @@ -1828,7 +1828,7 @@ namespace confighttp { * } * @endcode * - * @api_examples{/api/pin| POST| {"pairing_id":"0123456789abcdef0123456789abcdef","pin":"1234","name":"My PC"}} + * @api_examples{/api/pin|:| POST|:| {"pairing_id":"0123456789abcdef0123456789abcdef","pin":"1234","name":"My PC"}} */ void savePin(const resp_https_t &response, const req_https_t &request) { if (!check_content_type(response, request, "application/json")) { @@ -1879,7 +1879,7 @@ namespace confighttp { * @param response The HTTP response object. * @param request The HTTP request object. * - * @api_examples{/api/reset-display-device-persistence| POST| null} + * @api_examples{/api/reset-display-device-persistence|:| POST|:| null} */ void resetDisplayDevicePersistence(const resp_https_t &response, const req_https_t &request) { if (!authenticate(response, request)) { @@ -1905,7 +1905,7 @@ namespace confighttp { * @param response HTTP response used for authentication, CSRF, and status output. * @param request HTTP request carrying the client identity and CSRF token. * - * @api_examples{/api/reset-portal-token| POST| null} + * @api_examples{/api/reset-portal-token|:| POST|:| null} */ void resetPortalToken(const resp_https_t &response, const req_https_t &request) { if (!authenticate(response, request)) { @@ -1940,7 +1940,7 @@ namespace confighttp { * @param response HTTP response used for authentication or CSRF failures. * @param request HTTP request carrying the client identity and CSRF token. * - * @api_examples{/api/restart| POST| null} + * @api_examples{/api/restart|:| POST|:| null} */ void restart(const resp_https_t &response, const req_https_t &request) { if (!authenticate(response, request)) { @@ -2033,7 +2033,7 @@ namespace confighttp { * @param response The HTTP response object. * @param request The HTTP request object. * - * @api_examples{/api/virtual-input/status| GET| null} + * @api_examples{/api/virtual-input/status|:| GET|:| null} */ void getVirtualInputStatus(const resp_https_t &response, const req_https_t &request) { if (!authenticate(response, request)) { @@ -2054,7 +2054,7 @@ namespace confighttp { * @param response HTTP response object. * @param request Authenticated HTTP request. * - * @api_examples{/api/virtual-input/license| GET| null} + * @api_examples{/api/virtual-input/license|:| GET|:| null} */ void getVirtualInputLicense(const resp_https_t &response, const req_https_t &request) { get_virtual_input_license(response, request); @@ -2070,7 +2070,7 @@ namespace confighttp { * @param response HTTP response object. * @param request Authenticated HTTP request with a JSON action. * - * @api_examples{/api/virtual-input/license| POST| {"action":"validate"}} + * @api_examples{/api/virtual-input/license|:| POST|:| {"action":"validate"}} */ void updateVirtualInputLicense(const resp_https_t &response, const req_https_t &request) { if (!authenticate(response, request)) { @@ -2235,7 +2235,7 @@ namespace confighttp { * @note On Windows, an empty or root path returns the list of available drive letters. * @note On non-Windows, an empty path defaults to the filesystem root ("/"). * - * @api_examples{/api/browse?path=/home/user&type=directory| GET| null} + * @api_examples{/api/browse?path=/home/user&type=directory|:| GET|:| null} */ void browseDirectory(const resp_https_t &response, const req_https_t &request) { if (!authenticate(response, request)) { diff --git a/third-party/dockle b/third-party/dockle new file mode 160000 index 000000000..c1bca827d --- /dev/null +++ b/third-party/dockle @@ -0,0 +1 @@ +Subproject commit c1bca827d905e3e64cc6663488f5f741e17e681a diff --git a/third-party/doxyconfig b/third-party/doxyconfig deleted file mode 160000 index 419127bad..000000000 --- a/third-party/doxyconfig +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 419127bad87f49b2d45fa957ea7302abbb49c01f