├── .clang-format ├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.yaml │ ├── config.yaml │ └── feature_request.yaml └── workflows │ ├── build.yaml │ ├── debbuild.yaml │ ├── macos-dylib.yaml │ ├── mingw-packages.yaml │ ├── pages.yml │ ├── switch-portlibs.yaml │ └── vita-packages.yaml ├── .gitignore ├── .gitmodules ├── .vscode └── c_cpp_properties.json ├── CHANGELOG.md ├── CMakeLists.txt ├── LICENSE ├── README.md ├── app ├── include │ ├── activity │ │ ├── gallery_activity.hpp │ │ ├── hint_activity.hpp │ │ ├── main_activity.hpp │ │ ├── player_view.hpp │ │ └── server_list.hpp │ ├── api │ │ ├── analytics.hpp │ │ ├── http.hpp │ │ ├── jellyfin.hpp │ │ ├── jellyfin │ │ │ ├── device.hpp │ │ │ ├── media.hpp │ │ │ └── system.hpp │ │ └── websocket.hpp │ ├── client │ │ ├── apache.hpp │ │ ├── avio.hpp │ │ ├── client.hpp │ │ ├── local.hpp │ │ └── webdav.hpp │ ├── tab │ │ ├── home_tab.hpp │ │ ├── live_tv.hpp │ │ ├── media_collection.hpp │ │ ├── media_folder.hpp │ │ ├── media_movie.hpp │ │ ├── media_series.hpp │ │ ├── music_album.hpp │ │ ├── playlist.hpp │ │ ├── remote_tab.hpp │ │ ├── remote_view.hpp │ │ ├── search_result.hpp │ │ ├── search_tab.hpp │ │ ├── server_add.hpp │ │ ├── server_login.hpp │ │ ├── setting_tab.hpp │ │ ├── suggest_movie.hpp │ │ └── suggest_show.hpp │ ├── utils │ │ ├── config.hpp │ │ ├── dialog.hpp │ │ ├── event.hpp │ │ ├── gesture.hpp │ │ ├── image.hpp │ │ ├── misc.hpp │ │ ├── overclock.hpp │ │ ├── thread.hpp │ │ └── ums.hpp │ └── view │ │ ├── auto_tab_frame.hpp │ │ ├── button_close.hpp │ │ ├── custom_button.hpp │ │ ├── danmaku_core.hpp │ │ ├── danmaku_setting.hpp │ │ ├── gallery_view.hpp │ │ ├── h_recycling.hpp │ │ ├── media_filter.hpp │ │ ├── mpv_core.hpp │ │ ├── music_view.hpp │ │ ├── people_source.hpp │ │ ├── player_setting.hpp │ │ ├── presenter.hpp │ │ ├── recycling_grid.hpp │ │ ├── recyling_video.hpp │ │ ├── search_list.hpp │ │ ├── selector_cell.hpp │ │ ├── svg_image.hpp │ │ ├── text_box.hpp │ │ ├── video_card.hpp │ │ ├── video_profile.hpp │ │ ├── video_progress_slider.hpp │ │ ├── video_source.hpp │ │ └── video_view.hpp ├── platform │ ├── osx │ │ └── app.icns │ ├── ps4 │ │ └── sce_sys │ │ │ ├── icon0.png │ │ │ └── pic0.png │ ├── vita │ │ ├── sce_sys │ │ │ ├── bg.png │ │ │ ├── icon0.png │ │ │ ├── pic0.png │ │ │ └── startup.png │ │ └── template.xml.in │ └── win32 │ │ ├── app.ico │ │ ├── app.manifest │ │ └── app.rc.in └── src │ ├── activity │ ├── gallery_activity.cpp │ ├── hint_activity.cpp │ ├── main_activity.cpp │ ├── player_view.cpp │ └── server_list.cpp │ ├── api │ ├── analytics.cpp │ ├── http.cpp │ └── websocket.cpp │ ├── client │ ├── apache.cpp │ ├── avio.cpp │ ├── client.cpp │ ├── local.cpp │ └── webdav.cpp │ ├── main.cpp │ ├── tab │ ├── home_tab.cpp │ ├── live_tv.cpp │ ├── media_collection.cpp │ ├── media_folder.cpp │ ├── media_movie.cpp │ ├── media_series.cpp │ ├── music_album.cpp │ ├── playlist.cpp │ ├── remote_tab.cpp │ ├── remote_view.cpp │ ├── search_result.cpp │ ├── search_tab.cpp │ ├── server_add.cpp │ ├── server_login.cpp │ ├── setting_tab.cpp │ ├── suggest_movie.cpp │ └── suggest_show.cpp │ ├── utils │ ├── config.cpp │ ├── dialog.cpp │ ├── gesture.cpp │ ├── image.cpp │ ├── misc.cpp │ ├── overclock.cpp │ ├── thread.cpp │ ├── ums.cpp │ └── version.cpp │ └── view │ ├── auto_tab_frame.cpp │ ├── button_close.cpp │ ├── custom_button.cpp │ ├── danmaku_core.cpp │ ├── danmaku_setting.cpp │ ├── gallery_view.cpp │ ├── h_recycling.cpp │ ├── media_filter.cpp │ ├── mpv_core.cpp │ ├── music_view.cpp │ ├── people_source.cpp │ ├── player_setting.cpp │ ├── presenter.cpp │ ├── recycling_grid.cpp │ ├── recyling_video.cpp │ ├── search_list.cpp │ ├── selector_cell.cpp │ ├── svg_image.cpp │ ├── text_box.cpp │ ├── video_profile.cpp │ ├── video_progress_slider.cpp │ ├── video_source.cpp │ └── video_view.cpp ├── cmake ├── FindMPV.cmake └── FindWebP.cmake ├── debian ├── Dockerfile ├── Dockerfile.bookworm ├── Dockerfile.focal ├── changelog ├── compat ├── control └── rules ├── images ├── episode.jpg ├── home.jpg ├── library.jpg ├── music.jpg ├── search.jpg ├── series.jpg └── ums.jpg ├── library ├── CMakeLists.txt └── packages │ ├── b │ └── borealis │ │ └── xmake.lua │ ├── c │ └── cppwinrt │ │ └── xmake.lua │ ├── m │ └── mpv │ │ └── xmake.lua │ ├── n │ └── nanovg │ │ └── xmake.lua │ └── x │ └── xfangfang_glfw │ └── xmake.lua ├── resources ├── font │ ├── emoji.ttf │ ├── keymap_keyboard.ttf │ ├── keymap_keyboard_swap.ttf │ ├── keymap_ps.ttf │ ├── keymap_xbox.ttf │ └── switch_font.ttf ├── i18n │ ├── cs │ │ ├── hints.json │ │ └── main.json │ ├── de │ │ ├── hints.json │ │ └── main.json │ ├── en-US │ │ ├── hints.json │ │ └── main.json │ ├── ja │ │ ├── hints.json │ │ └── main.json │ ├── ko │ │ ├── hints.json │ │ └── main.json │ ├── pt-BR │ │ ├── hints.json │ │ └── main.json │ ├── uk-UA │ │ ├── hints.json │ │ └── main.json │ ├── vi_VN │ │ ├── hints.json │ │ └── main.json │ ├── zh-Hans │ │ ├── hints.json │ │ └── main.json │ └── zh-Hant │ │ ├── hints.json │ │ └── main.json ├── icon │ ├── ico-backward.svg │ ├── ico-cast.svg │ ├── ico-checkmark.svg │ ├── ico-circle.svg │ ├── ico-cloud-activate.svg │ ├── ico-cloud.svg │ ├── ico-danmu-setting.svg │ ├── ico-danmu-switch-off.svg │ ├── ico-danmu-switch-on.svg │ ├── ico-file-audio.svg │ ├── ico-file-image.svg │ ├── ico-file-text.svg │ ├── ico-file-video.svg │ ├── ico-file.svg │ ├── ico-folder-up.svg │ ├── ico-folder.svg │ ├── ico-forward.svg │ ├── ico-heart.svg │ ├── ico-home-activate.svg │ ├── ico-home.svg │ ├── ico-list.svg │ ├── ico-media-activate.svg │ ├── ico-media.svg │ ├── ico-pause.svg │ ├── ico-play.svg │ ├── ico-player-setting.svg │ ├── ico-playlist.svg │ ├── ico-repeat-list.svg │ ├── ico-repeat-song.svg │ ├── ico-search-activate.svg │ ├── ico-search.svg │ ├── ico-seeking.svg │ ├── ico-server-activate.svg │ ├── ico-server.svg │ ├── ico-setting-activate.svg │ ├── ico-setting.svg │ ├── ico-shuffle.svg │ ├── ico-star.svg │ ├── ico-sun-fill.svg │ ├── ico-volume-off.svg │ ├── ico-volume.svg │ ├── icon.jpg │ ├── icon.png │ ├── player-lock.svg │ ├── player-unlock.svg │ ├── widget-people-grey.svg │ └── widget-people.svg ├── img │ ├── empty.png │ ├── header-search-dark.svg │ ├── header-search.svg │ ├── hint_app.png │ ├── hint_game_1.png │ ├── hint_game_2.png │ ├── hint_hbmenu.png │ ├── net_error.png │ ├── sys │ │ ├── battery_back_dark.png │ │ ├── battery_back_light.png │ │ ├── cursor.png │ │ ├── ethernet_dark.png │ │ ├── ethernet_light.png │ │ ├── wifi_0_dark.png │ │ ├── wifi_0_light.png │ │ ├── wifi_1_dark.png │ │ ├── wifi_1_light.png │ │ ├── wifi_2_dark.png │ │ ├── wifi_2_light.png │ │ ├── wifi_3_dark.png │ │ └── wifi_3_light.png │ └── video-card-bg.png ├── material │ ├── LICENSE.txt │ └── MaterialIcons-Regular.ttf └── xml │ ├── activity │ ├── gallery.xml │ ├── hint.xml │ ├── main.xml │ └── server_list.xml │ ├── tabs │ ├── collection.xml │ ├── home.xml │ ├── media.xml │ ├── media_folder.xml │ ├── movie.xml │ ├── music_album.xml │ ├── remote.xml │ ├── search_result.xml │ ├── search_tv.xml │ ├── seasons.xml │ ├── series.xml │ ├── server_add.xml │ ├── server_login.xml │ ├── settings.xml │ └── suggest_show.xml │ └── view │ ├── button_close.xml │ ├── danmaku_setting.xml │ ├── dir_entry.xml │ ├── episode_card.xml │ ├── media_filter.xml │ ├── music_track.xml │ ├── music_view.xml │ ├── people.xml │ ├── player_setting.xml │ ├── playlist_item.xml │ ├── quick_connect.xml │ ├── recycler_list.xml │ ├── search_card.xml │ ├── server_item.xml │ ├── setting_about.xml │ ├── tutorial_error.xml │ ├── tutorial_font.xml │ ├── user_item.xml │ ├── video_card.xml │ ├── video_profile.xml │ └── video_view.xml ├── scripts ├── README.md ├── aur │ ├── PKGBUILD │ └── entrypoint.sh ├── flatpak.yaml ├── forwarder │ ├── CMakeLists.txt │ ├── README.md │ ├── config.json │ ├── icon │ │ ├── logo.gif │ │ └── logo.png │ └── source │ │ ├── main.c │ │ └── trampoline.s ├── icons │ ├── 128x128 │ │ └── org.player.switchfin.png │ ├── 256x256 │ │ └── org.player.switchfin.png │ ├── 32x32 │ │ └── org.player.switchfin.png │ ├── 48x48 │ │ └── org.player.switchfin.png │ └── 64x64 │ │ └── org.player.switchfin.png ├── macos │ ├── Makefile │ ├── arm64.meson │ ├── dmg.icns │ ├── lavfi.patch │ ├── mpv.patch │ └── x86_64.meson ├── mingw64 │ ├── curl │ │ ├── PKGBUILD │ │ └── static-libs.patch │ ├── dav1d │ │ └── PKGBUILD │ ├── ffmpeg │ │ ├── PKGBUILD │ │ └── avio.patch │ ├── freetype │ │ └── PKGBUILD │ ├── glfw │ │ └── PKGBUILD │ ├── glslang │ │ └── PKGBUILD │ ├── harfbuzz │ │ └── PKGBUILD │ ├── libass │ │ └── PKGBUILD │ ├── libplacebo │ │ └── PKGBUILD │ ├── libwebp │ │ ├── 0001-mingw-cmake-output.patch │ │ └── PKGBUILD │ ├── mpv │ │ ├── 0001-d3d11-render.patch │ │ └── PKGBUILD │ ├── shaderc │ │ ├── 0001-fix-glslang-hlsl-linking-order.patch │ │ └── PKGBUILD │ ├── spirv-cross │ │ ├── 0001-static-linking-hacks.patch │ │ └── PKGBUILD │ ├── spirv-headers │ │ └── PKGBUILD │ └── spirv-tools │ │ └── PKGBUILD ├── org.player.switchfin.appdata.xml ├── org.player.switchfin.desktop ├── org.player.switchfin.svg ├── snap │ └── snapcraft.yaml ├── switch │ ├── Dockerfile │ ├── curl │ │ ├── PKGBUILD │ │ └── switch-curl.patch │ ├── ffmpeg │ │ ├── PKGBUILD │ │ ├── avio.patch │ │ ├── ffmpeg-7.1.1.patch │ │ └── tls.patch │ ├── hacbrewpack │ │ ├── PKGBUILD │ │ └── nostartupuser.patch │ ├── harfbuzz │ │ └── PKGBUILD │ ├── libnx │ │ └── PKGBUILD │ ├── libssh2 │ │ └── PKGBUILD │ ├── libuam │ │ └── PKGBUILD │ ├── mbedtls │ │ ├── PKGBUILD │ │ └── mbedtls-2.28.10.patch │ ├── mpv │ │ ├── PKGBUILD │ │ └── deko3d.patch │ └── nspmini │ │ └── PKGBUILD └── vita │ ├── curl │ └── VITABUILD │ ├── ffmpeg │ ├── VITABUILD │ └── ffmpeg.patch │ ├── mbedtls │ ├── VITABUILD │ └── mbedtls.patch │ └── mpv │ ├── VITABUILD │ └── gxm.patch └── xmake.lua /.clang-format: -------------------------------------------------------------------------------- 1 | --- 2 | BasedOnStyle: Google 3 | ColumnLimit: 120 4 | AccessModifierOffset: -4 5 | AlignAfterOpenBracket: false 6 | IndentWidth: 4 7 | BreakBeforeBraces: Attach 8 | CommentPragmas: '^[^ ]' 9 | IncludeBlocks: Regroup 10 | PointerAlignment: Left 11 | SortIncludes: Never 12 | IndentCaseLabels : false 13 | Standard: Cpp11 14 | ... 15 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.yaml: -------------------------------------------------------------------------------- 1 | name: Bug report 2 | description: Create a report to help us improve 3 | labels: [ bug ] 4 | body: 5 | - type: textarea 6 | attributes: 7 | label: Describe the bug 8 | description: A clear and concise description of what the bug is. 9 | - type: textarea 10 | attributes: 11 | label: To reproduce 12 | description: Steps to reproduce the behavior. 13 | value: | 14 | 1. Go to '...' 15 | 2. Tap on '....' 16 | 3. Scroll down to '....' 17 | 4. See error 18 | - type: textarea 19 | attributes: 20 | label: Screenshots 21 | description: If applicable, add screenshots to help explain your problem. 22 | - type: input 23 | attributes: 24 | label: Operating system 25 | description: e.g. 16.0.3|AMS 1.5.4|S 26 | - type: input 27 | attributes: 28 | label: Jellyfin Server 29 | description: e.g. 10.8.10 Linux 30 | - type: textarea 31 | attributes: 32 | label: Additional context 33 | description: Add any other context about the problem here. -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yaml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: false -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.yaml: -------------------------------------------------------------------------------- 1 | name: Feature request 2 | description: Suggest an idea for this project 3 | labels: [ feature ] 4 | body: 5 | - type: textarea 6 | attributes: 7 | label: Is your feature request related to a problem? Please describe. 8 | description: A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 9 | - type: textarea 10 | attributes: 11 | label: Describe the solution you'd like 12 | description: A clear and concise description of what you want to happen. 13 | - type: textarea 14 | attributes: 15 | label: Describe alternatives you've considered 16 | description: A clear and concise description of any alternative solutions or features you've considered. 17 | - type: textarea 18 | attributes: 19 | label: Additional context 20 | description: Add any other context or screenshots about the feature request here. -------------------------------------------------------------------------------- /.github/workflows/debbuild.yaml: -------------------------------------------------------------------------------- 1 | name: build-docker 2 | 3 | on: 4 | workflow_dispatch: 5 | 6 | permissions: 7 | packages: write 8 | 9 | jobs: 10 | build-docker: 11 | strategy: 12 | fail-fast: false 13 | matrix: 14 | include: 15 | - { img: ubuntu, tag: focal, file: debian/Dockerfile.focal } 16 | - { img: ubuntu, tag: noble } 17 | - { img: debian, tag: bookworm, file: debian/Dockerfile.bookworm } 18 | tag: [ focal, noble, bookworm ] 19 | runs-on: ubuntu-latest 20 | steps: 21 | - uses: actions/checkout@v4 22 | with: 23 | sparse-checkout: debian 24 | - uses: docker/login-action@v3 25 | with: 26 | registry: ghcr.io 27 | username: ${{ github.actor }} 28 | password: ${{ secrets.GITHUB_TOKEN }} 29 | - name: Set up QEMU 30 | uses: docker/setup-qemu-action@v3 31 | - name: Set up Docker Buildx 32 | uses: docker/setup-buildx-action@v3 33 | - name: Build Docker image 34 | uses: docker/build-push-action@v6 35 | with: 36 | context: debian 37 | file: ${{ matrix.file }} 38 | push: true 39 | provenance: false 40 | platforms: linux/amd64,linux/arm64 41 | tags: ghcr.io/${{ github.repository_owner }}/build:${{ matrix.img }}-${{ matrix.tag }} 42 | build-args: | 43 | IMG=${{ matrix.img }} 44 | TAG=${{ matrix.tag }} -------------------------------------------------------------------------------- /.github/workflows/macos-dylib.yaml: -------------------------------------------------------------------------------- 1 | name: macos-dylib 2 | 3 | on: 4 | push: 5 | tags: [ macos-dylib ] 6 | paths: [ scripts/macos/* ] 7 | 8 | permissions: 9 | contents: write 10 | 11 | jobs: 12 | build: 13 | strategy: 14 | fail-fast: false 15 | matrix: 16 | include: 17 | - { tag: Silicon, arch: arm64 } 18 | - { tag: Intel, arch: x86_64 } 19 | tag: [ Silicon, Intel ] 20 | runs-on: macos-latest 21 | steps: 22 | - uses: actions/checkout@v4 23 | with: 24 | sparse-checkout: scripts 25 | - name: Remove stray upstream python binary symlinks under /usr/local 26 | run: | 27 | find /usr/local/bin -lname '*/Library/Frameworks/Python.framework/*' -delete -print 28 | brew unlink python && brew link --overwrite python 29 | - name: Install dependency 30 | run: brew reinstall ninja nasm meson 31 | - name: Build dylib 32 | run: make -C scripts/macos ARCH=${{ matrix.arch }} TMPDIR=${{ runner.temp }} PREFIX=${{ runner.temp }} 33 | - name: Build packages 34 | run: | 35 | tar zcf dylib-ffmpeg71-mpv36-${{ matrix.tag }}.tar.gz --exclude=lib/*.a \ 36 | -C ${{ runner.temp }} include lib 37 | - name: Archive Build Logs 38 | if: ${{ failure() }} 39 | uses: actions/upload-artifact@v4 40 | with: 41 | name: logs-${{ matrix.tag }} 42 | path: | 43 | build-ffmpeg/ffbuild 44 | build-*/meson-logs 45 | - name: Upload packages 46 | uses: softprops/action-gh-release@v2 47 | with: 48 | name: macos-dylib 49 | tag_name: macos-dylib 50 | prerelease: true 51 | files: dylib-*.tar.gz 52 | body: | 53 | ![download](https://img.shields.io/github/downloads/${{ github.repository }}/macos-dylib/total?label=Downloads) -------------------------------------------------------------------------------- /.github/workflows/pages.yml: -------------------------------------------------------------------------------- 1 | # Sample workflow for building and deploying a Jekyll site to GitHub Pages 2 | name: GitHub Pages 3 | 4 | on: 5 | # Runs on pushes targeting the default branch 6 | push: 7 | paths: 8 | - images/* 9 | - README.md 10 | branches: [ dev ] 11 | 12 | # Allows you to run this workflow manually from the Actions tab 13 | workflow_dispatch: 14 | 15 | # Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages 16 | permissions: 17 | contents: read 18 | pages: write 19 | id-token: write 20 | 21 | # Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued. 22 | # However, do NOT cancel in-progress runs as we want to allow these production deployments to complete. 23 | concurrency: 24 | group: "pages" 25 | cancel-in-progress: false 26 | 27 | jobs: 28 | # Build job 29 | build: 30 | runs-on: ubuntu-latest 31 | steps: 32 | - name: Checkout 33 | uses: actions/checkout@v4 34 | with: 35 | sparse-checkout: | 36 | scripts/org.player.switchfin.svg 37 | README.md 38 | images 39 | - name: Setup Pages 40 | uses: actions/configure-pages@v5 41 | - name: Build with Jekyll 42 | uses: actions/jekyll-build-pages@v1 43 | with: 44 | source: ./ 45 | destination: ./_site 46 | - name: Upload artifact 47 | uses: actions/upload-pages-artifact@v3 48 | 49 | # Deployment job 50 | deploy: 51 | environment: 52 | name: github-pages 53 | url: ${{ steps.deployment.outputs.page_url }} 54 | runs-on: ubuntu-latest 55 | needs: build 56 | steps: 57 | - name: Deploy to GitHub Pages 58 | id: deployment 59 | uses: actions/deploy-pages@v4 60 | -------------------------------------------------------------------------------- /.github/workflows/switch-portlibs.yaml: -------------------------------------------------------------------------------- 1 | name: switch-portlibs 2 | 3 | on: 4 | push: 5 | tags: [ switch-portlibs ] 6 | paths: [ scripts/switch/** ] 7 | 8 | permissions: 9 | contents: write 10 | 11 | jobs: 12 | build-portlibs: 13 | runs-on: ubuntu-latest 14 | container: 15 | image: devkitpro/devkita64:20241023 16 | steps: 17 | - name: Disable autocrlf 18 | run: git config --global core.autocrlf false 19 | - uses: actions/checkout@v4 20 | with: 21 | sparse-checkout: scripts/switch 22 | - name: Install dependency 23 | run: | 24 | apt-get update 25 | apt-get install -y fakeroot zstd bison flex libtool python3-pip manpages- 26 | pip3 install meson mako 27 | - name: Build portlibs 28 | run: | 29 | adduser --gecos '' --home ${GITHUB_WORKSPACE}/scripts/switch --disabled-password builder 30 | echo 'builder ALL=(ALL) NOPASSWD:ALL' > /etc/sudoers.d/builder 31 | 32 | chown -R builder:builder scripts/switch 33 | for pkg in libnx ffmpeg libuam; do 34 | echo building $pkg 35 | su - builder -c "cd $pkg && dkp-makepkg -siCf --noconfirm" 36 | done 37 | for pkg in mpv curl nspmini hacbrewpack; do 38 | echo building $pkg 39 | su - builder -c "cd $pkg && dkp-makepkg -sCf --noconfirm" 40 | done 41 | 42 | - name: Upload portlibs 43 | uses: softprops/action-gh-release@v2 44 | with: 45 | name: switch-portlibs 46 | tag_name: switch-portlibs 47 | prerelease: true 48 | files: scripts/switch/*/*.pkg.tar.zst 49 | body: | 50 | ![download](https://img.shields.io/github/downloads/${{ github.repository }}/switch-portlibs/total?label=Downloads) -------------------------------------------------------------------------------- /.github/workflows/vita-packages.yaml: -------------------------------------------------------------------------------- 1 | name: vita-packages 2 | 3 | on: 4 | push: 5 | tags: [ vita-packages ] 6 | paths: [ scripts/vita/** ] 7 | 8 | permissions: 9 | contents: write 10 | 11 | jobs: 12 | build-packages: 13 | runs-on: ubuntu-latest 14 | container: 15 | image: vitasdk/vitasdk:latest 16 | steps: 17 | - uses: actions/checkout@v4 18 | with: 19 | sparse-checkout: scripts/vita 20 | - name: Install dependency 21 | run: | 22 | apk update 23 | apk add cmake ninja meson pkgconf bash git zstd tar patch 24 | vdpm libass harfbuzz fribidi freetype libpng libwebp 25 | - name: Build packages 26 | run: | 27 | adduser --gecos '' --home ${GITHUB_WORKSPACE}/scripts/vita --disabled-password builder 28 | echo 'builder ALL=(ALL) NOPASSWD:ALL' > /etc/sudoers.d/builder 29 | chown -R builder:builder scripts/vita 30 | 31 | su - builder -c "cd mbedtls && vita-makepkg" 32 | vdpm $PWD/scripts/vita/mbedtls/*-arm.tar.xz 33 | touch /tmp/vdpm_install_mbedtls 34 | 35 | su - builder -c "cd curl && vita-makepkg" 36 | su - builder -c "cd ffmpeg && vita-makepkg" 37 | 38 | vdpm $PWD/scripts/vita/ffmpeg/*-arm.tar.xz 39 | touch /tmp/vdpm_install_ffmpeg 40 | 41 | su - builder -c "cd mpv && vita-makepkg" 42 | 43 | - name: Upload packages 44 | uses: softprops/action-gh-release@v2 45 | with: 46 | name: vita-packages 47 | tag_name: vita-packages 48 | prerelease: true 49 | files: scripts/vita/*/*-arm.tar.xz 50 | body: | 51 | ![download](https://img.shields.io/github/downloads/${{ github.repository }}/vita-packages/total?label=Downloads) -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | build*/ 2 | /.idea/ 3 | /cmake-*/ 4 | /.xmake/ 5 | /.vscode/ 6 | .gdbinit 7 | *.exe 8 | *.dmp 9 | /resources/forwarder.nsp 10 | /resources/shaders/*.dksh 11 | /scripts/*/*/*.tar.* 12 | /scripts/aur/*.tar.* 13 | /scripts/*/*/src 14 | /switchfin 15 | .DS_Store 16 | debian/debhelper-build-stamp 17 | debian/files 18 | debian/switchfin* 19 | debian/.debhelper 20 | .wget-hsts -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "library/borealis"] 2 | path = library/borealis 3 | url = https://github.com/dragonflylee/borealis 4 | branch = wiliwili 5 | [submodule "library/lunasvg"] 6 | path = library/lunasvg 7 | url = https://github.com/sammycage/lunasvg 8 | -------------------------------------------------------------------------------- /app/include/activity/gallery_activity.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by fang on 2023/4/26. 3 | // 4 | 5 | #pragma once 6 | 7 | #include 8 | #include 9 | 10 | class GalleryView; 11 | class NetImageGalleryItem; 12 | 13 | class GalleryActivity : public brls::Activity { 14 | public: 15 | // Declare that the content of this activity is the given XML file 16 | CONTENT_FROM_XML_RES("activity/gallery.xml"); 17 | 18 | explicit GalleryActivity(const std::string& url); 19 | 20 | bool isTranslucent() override; 21 | 22 | void onContentAvailable() override; 23 | 24 | ~GalleryActivity() override; 25 | 26 | private: 27 | BRLS_BIND(GalleryView, gallery, "hint/gallery"); 28 | 29 | NetImageGalleryItem* view; 30 | }; -------------------------------------------------------------------------------- /app/include/activity/hint_activity.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by fang on 2022/8/21. 3 | // 4 | 5 | #pragma once 6 | 7 | #include 8 | 9 | class GalleryView; 10 | 11 | class HintActivity : public brls::Activity { 12 | public: 13 | // Declare that the content of this activity is the given XML file 14 | CONTENT_FROM_XML_RES("activity/hint.xml"); 15 | 16 | HintActivity(); 17 | 18 | void onContentAvailable() override; 19 | 20 | ~HintActivity(); 21 | 22 | private: 23 | BRLS_BIND(GalleryView, gallery, "hint/gallery"); 24 | }; -------------------------------------------------------------------------------- /app/include/activity/main_activity.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2020-2021 natinusala 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | #pragma once 18 | 19 | #include 20 | #include 21 | 22 | class MainActivity : public brls::Activity { 23 | public: 24 | // Declare that the content of this activity is the given XML file 25 | CONTENT_FROM_XML_RES("activity/main.xml"); 26 | 27 | MainActivity(); 28 | 29 | private: 30 | std::unique_ptr ws; 31 | }; 32 | -------------------------------------------------------------------------------- /app/include/activity/player_view.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2024 dragonflylee 3 | */ 4 | 5 | #pragma once 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | class VideoView; 12 | 13 | class PlayerView : public brls::Box { 14 | public: 15 | PlayerView(const jellyfin::Item& item, const uint64_t seekTicks = 0); 16 | ~PlayerView(); 17 | 18 | void setSeries(const std::string& seriesId); 19 | void setTitie(const std::string& title); 20 | 21 | private: 22 | void setChapters(const std::vector& chaps, uint64_t duration); 23 | /// @brief get video url 24 | void playMedia(const uint64_t seekTicks); 25 | bool playIndex(int index); 26 | void reportStart(); 27 | void reportStop(); 28 | void reportPlay(bool isPaused = false); 29 | void requestDanmaku(); 30 | bool toggleQuality(); 31 | 32 | // Playinfo 33 | std::string itemId; 34 | /// @brief DirectPlay, Transcode 35 | std::string playMethod; 36 | std::string playSessionId; 37 | jellyfin::Source stream; 38 | std::vector episodes; 39 | 40 | MPVEvent::Subscription eventSubscribeID; 41 | brls::VoidEvent::Subscription exitSubscribeID; 42 | brls::Event::Subscription playSubscribeID; 43 | brls::VoidEvent::Subscription settingSubscribeID; 44 | MPVCustomEvent::Subscription customEventSubscribeID; 45 | VideoView* view = nullptr; 46 | }; -------------------------------------------------------------------------------- /app/include/activity/server_list.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2023 dragonflylee 3 | */ 4 | 5 | #pragma once 6 | 7 | #include 8 | #include "utils/config.hpp" 9 | 10 | class RecyclingGrid; 11 | class AutoTabFrame; 12 | class ServerCell; 13 | 14 | class ServerList : public brls::Activity { 15 | public: 16 | CONTENT_FROM_XML_RES("activity/server_list.xml"); 17 | 18 | ServerList(); 19 | ~ServerList(); 20 | 21 | void onContentAvailable() override; 22 | std::string getUrl(); 23 | void onUser(const std::string& id); 24 | void willAppear(bool resetState = false) override; 25 | 26 | private: 27 | BRLS_BIND(brls::Button, btnServerAdd, "btn/server/add"); 28 | BRLS_BIND(brls::Box, sidebarServers, "server/sidebar"); 29 | BRLS_BIND(brls::Box, serverDetail, "server/detail"); 30 | BRLS_BIND(RecyclingGrid, recyclerUsers, "user/recycler"); 31 | BRLS_BIND(brls::DetailCell, serverVersion, "server/version"); 32 | BRLS_BIND(brls::DetailCell, inputUrl, "selector/server/urls"); 33 | BRLS_BIND(brls::Button, btnSignin, "btn/server/signin"); 34 | BRLS_BIND(AutoTabFrame, tabFrame, "server/tabFrame"); 35 | 36 | void onServer(const AppServer &s); 37 | void setActive(brls::View *active); 38 | void getActive(); 39 | }; -------------------------------------------------------------------------------- /app/include/api/analytics.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | namespace analytics { 10 | 11 | class Event; 12 | 13 | const size_t REPORT_MAX_NUM = 25; 14 | 15 | #ifdef NO_GA 16 | #define GA(a) void(a); 17 | #else 18 | #define GA(a, ...) analytics::Analytics::instance().report(a, ##__VA_ARGS__); 19 | #endif /* NO_GA */ 20 | 21 | class Event { 22 | public: 23 | std::string name; 24 | nlohmann::json params; 25 | }; 26 | NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(Event, name, params); 27 | 28 | class Analytics : public brls::Singleton { 29 | public: 30 | Analytics(); 31 | ~Analytics(); 32 | 33 | void report(const std::string& event, nlohmann::json params = {}); 34 | 35 | private: 36 | void send(); 37 | 38 | std::string url; 39 | std::string client_id; 40 | std::mutex events_mutex; 41 | std::list events; 42 | brls::RepeatingTimer ticker; 43 | }; 44 | 45 | } -------------------------------------------------------------------------------- /app/include/api/jellyfin/device.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace jellyfin { 6 | 7 | struct DirectPlayProfile { 8 | std::string Container; 9 | std::string Type; 10 | std::string VideoCodec; 11 | }; 12 | NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT(DirectPlayProfile, Container, Type, VideoCodec); 13 | 14 | struct TranscodingProfile { 15 | std::string Container; 16 | std::string Type; 17 | std::string VideoCodec; 18 | std::string Context; 19 | std::string Protocol; 20 | }; 21 | NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT(TranscodingProfile, Container, Type, VideoCodec, Context, Protocol); 22 | 23 | struct SubtitleProfile { 24 | std::string Format; 25 | std::string Method; 26 | }; 27 | NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT(SubtitleProfile, Format, Method); 28 | 29 | struct DeviceProfile { 30 | int64_t MaxStreamingBitrate; 31 | int64_t MaxStaticBitrate; 32 | std::vector DirectPlayProfiles; 33 | std::vector TranscodingProfiles; 34 | std::vector SubtitleProfiles; 35 | }; 36 | NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT( 37 | DeviceProfile, MaxStreamingBitrate, MaxStaticBitrate, DirectPlayProfiles, TranscodingProfiles, SubtitleProfiles); 38 | 39 | } // namespace jellyfin -------------------------------------------------------------------------------- /app/include/api/websocket.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2024 dragonflylee 3 | */ 4 | 5 | #pragma once 6 | 7 | #include 8 | #include 9 | #ifdef BOREALIS_USE_STD_THREAD 10 | #include 11 | #else 12 | #include 13 | #endif 14 | #include 15 | #include 16 | 17 | class websocket { 18 | public: 19 | websocket(const std::string& url); 20 | ~websocket(); 21 | 22 | private: 23 | static void* wsRecv(void*); 24 | static size_t onMsg(char *b, size_t size, size_t nitems, void *p); 25 | static void onPlayNow(const std::string& itemId, uint64_t seekTicks); 26 | 27 | #ifdef BOREALIS_USE_STD_THREAD 28 | std::shared_ptr th; 29 | #else 30 | pthread_t th; 31 | #endif 32 | brls::RepeatingTimer hb; 33 | void *easy; 34 | }; -------------------------------------------------------------------------------- /app/include/client/apache.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "client.hpp" 4 | #include 5 | 6 | namespace remote { 7 | 8 | class Apache : public Client { 9 | public: 10 | Apache(const AppRemote &conf); 11 | std::vector list(const std::string &path) override; 12 | 13 | private: 14 | HTTP c; 15 | std::string host; 16 | }; 17 | 18 | } // namespace remote -------------------------------------------------------------------------------- /app/include/client/avio.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "client.hpp" 4 | 5 | namespace remote { 6 | 7 | class AVIO : public Client { 8 | public: 9 | AVIO(const std::string& path); 10 | std::vector list(const std::string &path) override; 11 | }; 12 | 13 | } // namespace remote -------------------------------------------------------------------------------- /app/include/client/client.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | namespace remote { 7 | 8 | class remote_error : public std::exception { 9 | public: 10 | explicit remote_error(const std::string& arg) : m(arg) {} 11 | const char* what() const noexcept override { return m.c_str(); } 12 | private: 13 | std::string m; 14 | }; 15 | 16 | enum class EntryType { 17 | FILE, 18 | DIR, 19 | VIDEO, 20 | AUDIO, 21 | IMAGE, 22 | PLAYLIST, 23 | SUBTITLE, 24 | TEXT, 25 | UP, 26 | }; 27 | 28 | struct DirEntry { 29 | std::string name; 30 | std::string path; 31 | uint64_t fileSize; 32 | EntryType type; 33 | std::tm modified; 34 | 35 | const std::string& url() const { return this->path; } 36 | }; 37 | 38 | class Client { 39 | public: 40 | virtual ~Client() = default; 41 | virtual std::vector list(const std::string& path) = 0; 42 | virtual void auth(const std::string& user, const std::string& passwd) {} 43 | const std::string& extraOption() { return this->extra; } 44 | 45 | protected: 46 | std::string extra; 47 | 48 | void init(const AppRemote& conf, HTTP& cilent); 49 | }; 50 | 51 | std::shared_ptr create(const AppRemote& c); 52 | 53 | } // namespace remote -------------------------------------------------------------------------------- /app/include/client/local.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "client.hpp" 4 | 5 | namespace remote { 6 | 7 | class Local : public Client { 8 | public: 9 | Local() = default; 10 | std::vector list(const std::string &path) override; 11 | }; 12 | 13 | } // namespace remote -------------------------------------------------------------------------------- /app/include/client/webdav.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "client.hpp" 4 | #include 5 | 6 | namespace remote { 7 | 8 | class Webdav : public Client { 9 | public: 10 | Webdav(const std::string& url, const AppRemote &conf); 11 | std::vector list(const std::string &path) override; 12 | 13 | private: 14 | HTTP c; 15 | std::string host; 16 | }; 17 | 18 | } // namespace remote -------------------------------------------------------------------------------- /app/include/tab/home_tab.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2023 dragonflylee 3 | */ 4 | 5 | #pragma once 6 | 7 | #include 8 | #include 9 | 10 | class RecylingVideo; 11 | 12 | class HomeTab : public AttachedView, public Presenter { 13 | public: 14 | HomeTab(); 15 | ~HomeTab() override; 16 | 17 | void onCreate() override; 18 | 19 | void doRequest() override; 20 | 21 | static brls::View* create(); 22 | 23 | private: 24 | BRLS_BIND(RecylingVideo, userResume, "home/user/resume"); 25 | BRLS_BIND(RecylingVideo, showNextup, "home/show/nextup"); 26 | BRLS_BIND(RecylingVideo, movieLatest, "home/movie/latest"); 27 | BRLS_BIND(RecylingVideo, seriesLatest, "home/series/latest"); 28 | BRLS_BIND(RecylingVideo, musicLatest, "home/music/latest"); 29 | }; 30 | -------------------------------------------------------------------------------- /app/include/tab/live_tv.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2023 dragonflylee 3 | */ 4 | 5 | #pragma once 6 | 7 | #include 8 | 9 | class RecyclingGrid; 10 | 11 | class LiveTV : public brls::Box { 12 | public: 13 | LiveTV(const std::string& itemId); 14 | 15 | brls::View* getDefaultFocus() override; 16 | 17 | private: 18 | BRLS_BIND(RecyclingGrid, recycler, "media/series"); 19 | 20 | void doRequest(); 21 | }; -------------------------------------------------------------------------------- /app/include/tab/media_collection.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2023 dragonflylee 3 | */ 4 | 5 | #pragma once 6 | 7 | #include 8 | 9 | class RecyclingGrid; 10 | class AutoTabFrame; 11 | class MediaFilter; 12 | 13 | class MediaCollection : public brls::Box { 14 | public: 15 | explicit MediaCollection( 16 | const std::string& itemId, const std::string& itemType = "", const std::string& genresId = ""); 17 | 18 | brls::View* getDefaultFocus() override; 19 | 20 | static void clearPref() { customPrefs.clear(); } 21 | 22 | private: 23 | BRLS_BIND(RecyclingGrid, recycler, "media/series"); 24 | BRLS_BIND(AutoTabFrame, tabFrame, "media/tabFrame"); 25 | 26 | /// @brief 获取显示配置 27 | void doPreferences(); 28 | void doRequest(); 29 | 30 | void loadFilter(); 31 | void saveFilter(); 32 | 33 | std::string itemId; 34 | std::string genresId; 35 | std::string itemType; 36 | size_t pageSize; 37 | size_t startIndex; 38 | 39 | std::string prefId; 40 | std::string prefKey; 41 | static std::map customPrefs; 42 | }; -------------------------------------------------------------------------------- /app/include/tab/media_folder.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2023 dragonflylee 3 | */ 4 | 5 | #pragma once 6 | 7 | #include 8 | 9 | class RecyclingGrid; 10 | 11 | class MediaFolders : public AttachedView { 12 | public: 13 | MediaFolders(); 14 | ~MediaFolders(); 15 | 16 | void onCreate() override; 17 | 18 | static brls::View* create(); 19 | 20 | private: 21 | BRLS_BIND(RecyclingGrid, recycler, "media/folders"); 22 | 23 | void doRequest(); 24 | }; 25 | -------------------------------------------------------------------------------- /app/include/tab/media_movie.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2025 dragonflylee 3 | */ 4 | 5 | #pragma once 6 | 7 | #include 8 | #include 9 | 10 | class HRecyclerFrame; 11 | class TextBox; 12 | 13 | class MediaMovie : public brls::Box { 14 | public: 15 | MediaMovie(const jellyfin::Item& item); 16 | ~MediaMovie() override; 17 | 18 | private: 19 | BRLS_BIND(brls::Image, imageLogo, "movie/image/logo"); 20 | BRLS_BIND(brls::Header, headerTitle, "movie/header/title"); 21 | BRLS_BIND(brls::Label, labelYear, "movie/label/year"); 22 | BRLS_BIND(brls::Label, parentalRating, "movie/parental/rating"); 23 | BRLS_BIND(brls::Label, labelRating, "movie/label/rating"); 24 | BRLS_BIND(TextBox, labelOverview, "movie/label/overview"); 25 | BRLS_BIND(brls::Label, labelGenres, "movie/label/genres"); 26 | BRLS_BIND(brls::Header, labelSimilar, "movie/label/similar"); 27 | BRLS_BIND(brls::Button, btnPlay, "movie/play"); 28 | BRLS_BIND(HRecyclerFrame, people, "movie/people"); 29 | BRLS_BIND(HRecyclerFrame, similar, "movie/similar"); 30 | 31 | void doMovie(const std::string& itemId); 32 | void doSimilar(const std::string& itemId); 33 | }; 34 | -------------------------------------------------------------------------------- /app/include/tab/media_series.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2023 dragonflylee 3 | */ 4 | 5 | #pragma once 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | class AutoTabFrame; 12 | class HRecyclerFrame; 13 | class TextBox; 14 | 15 | class MediaSeries : public brls::Box, public Presenter { 16 | public: 17 | MediaSeries(const jellyfin::Item& item); 18 | ~MediaSeries() override; 19 | 20 | void doRequest() override; 21 | 22 | private: 23 | BRLS_BIND(brls::Image, imageLogo, "series/image/logo"); 24 | BRLS_BIND(brls::Header, headerTitle, "series/header/title"); 25 | BRLS_BIND(brls::Label, labelYear, "series/label/year"); 26 | BRLS_BIND(brls::Label, parentalRating, "series/parental/rating"); 27 | BRLS_BIND(brls::Label, labelRating, "series/label/rating"); 28 | BRLS_BIND(TextBox, labelOverview, "series/label/overview"); 29 | BRLS_BIND(brls::Label, labelGenres, "series/label/genres"); 30 | BRLS_BIND(brls::Header, labelNextup, "series/label/nextup"); 31 | BRLS_BIND(brls::Header, labelSimilar, "series/label/similar"); 32 | BRLS_BIND(HRecyclerFrame, people, "series/people"); 33 | BRLS_BIND(HRecyclerFrame, similar, "series/similar"); 34 | BRLS_BIND(HRecyclerFrame, nextUp, "series/nextup"); 35 | BRLS_BIND(AutoTabFrame, tabFrame, "series/tabFrame"); 36 | 37 | void doSeries(); 38 | void doSeason(); 39 | void doSimilar(); 40 | void doNextup(); 41 | 42 | std::string seriesId; 43 | }; 44 | -------------------------------------------------------------------------------- /app/include/tab/music_album.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | class RecyclingGrid; 8 | 9 | class MusicAlbum : public brls::Box { 10 | public: 11 | MusicAlbum(const jellyfin::Item& item); 12 | ~MusicAlbum() override; 13 | 14 | private: 15 | BRLS_BIND(brls::Label, albumTitle, "album/label/title"); 16 | BRLS_BIND(brls::Label, albumAritst, "album/label/artist"); 17 | BRLS_BIND(brls::Label, albumYear, "album/label/year"); 18 | BRLS_BIND(brls::Image, imageCover, "album/image/cover"); 19 | BRLS_BIND(RecyclingGrid, albumTracks, "album/tracks"); 20 | BRLS_BIND(brls::Box, albumStats, "album/stats"); 21 | 22 | void doAlbum(); 23 | void doTracks(); 24 | 25 | std::string itemId; 26 | MPVCustomEvent::Subscription customEventSubscribeID; 27 | }; -------------------------------------------------------------------------------- /app/include/tab/playlist.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | class RecyclingGrid; 7 | 8 | class Playlist : public brls::Box { 9 | public: 10 | Playlist(const jellyfin::Item& item); 11 | ~Playlist() override; 12 | 13 | brls::View* getDefaultFocus() override; 14 | 15 | private: 16 | BRLS_BIND(brls::Label, title, "album/label/title"); 17 | BRLS_BIND(brls::Label, subtitle, "album/label/artist"); 18 | BRLS_BIND(brls::Label, misc, "album/label/year"); 19 | BRLS_BIND(brls::Image, cover, "album/image/cover"); 20 | BRLS_BIND(RecyclingGrid, playlist, "album/tracks"); 21 | BRLS_BIND(brls::Box, stats, "album/stats"); 22 | 23 | void doList(); 24 | 25 | std::string itemId; 26 | }; -------------------------------------------------------------------------------- /app/include/tab/remote_tab.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2023 dragonflylee 3 | */ 4 | 5 | #pragma once 6 | 7 | #include 8 | 9 | class RemoteTab : public AttachedView { 10 | public: 11 | RemoteTab(); 12 | ~RemoteTab() override; 13 | 14 | static brls::View* create(); 15 | 16 | void onCreate() override; 17 | 18 | private: 19 | BRLS_BIND(AutoTabFrame, tabFrame, "remote/tabFrame"); 20 | }; -------------------------------------------------------------------------------- /app/include/tab/remote_view.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2023 dragonflylee 3 | */ 4 | 5 | #pragma once 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | class RecyclingGrid; 12 | 13 | using DirList = std::vector; 14 | 15 | class RemoteView : public AttachedView { 16 | public: 17 | using Client = std::shared_ptr; 18 | 19 | RemoteView(Client c); 20 | ~RemoteView() override; 21 | 22 | brls::View* getDefaultFocus() override; 23 | 24 | void push(const std::string& path); 25 | 26 | void dismiss(std::function cb = [] {}) override; 27 | 28 | protected: 29 | void setContent(RecyclingGrid* view); 30 | RecyclingGrid* newRecycler(); 31 | 32 | std::vector stack; 33 | RecyclingGrid* recycler; 34 | Client client; 35 | }; 36 | 37 | class UmsView : public RemoteView { 38 | public: 39 | UmsView(); 40 | ~UmsView() override; 41 | 42 | private: 43 | Ums::DeviceEvent::Subscription deviceSubscribeID; 44 | }; -------------------------------------------------------------------------------- /app/include/tab/search_result.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2023 dragonflylee 3 | */ 4 | 5 | #pragma once 6 | 7 | #include 8 | 9 | class SearchList; 10 | 11 | class SearchResult : public brls::Box { 12 | public: 13 | SearchResult(const std::string& searchTerm); 14 | ~SearchResult() override; 15 | 16 | static brls::View* create(); 17 | 18 | private: 19 | BRLS_BIND(SearchList, searchMovie, "search/movie"); 20 | BRLS_BIND(SearchList, searchSeries, "search/series"); 21 | BRLS_BIND(SearchList, searchEpisode, "search/episode"); 22 | BRLS_BIND(SearchList, searchMusic, "search/music"); 23 | }; -------------------------------------------------------------------------------- /app/include/tab/search_tab.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2023 dragonflylee 3 | */ 4 | 5 | #pragma once 6 | 7 | #include 8 | 9 | class RecyclingGrid; 10 | 11 | class SearchTab : public AttachedView { 12 | public: 13 | SearchTab(); 14 | ~SearchTab(); 15 | 16 | void onCreate() override; 17 | 18 | static brls::View* create(); 19 | 20 | private: 21 | BRLS_BIND(RecyclingGrid, recyclingKeyboard, "tv/search/keyboard"); 22 | BRLS_BIND(RecyclingGrid, searchSuggest, "tv/search/suggest"); 23 | BRLS_BIND(RecyclingGrid, searchHistory, "tv/search/history"); 24 | BRLS_BIND(brls::Box, historyBox, "tv/history/box"); 25 | BRLS_BIND(brls::Box, searchBox, "tv/search/box"); 26 | BRLS_BIND(brls::Label, inputLabel, "tv/search/input"); 27 | BRLS_BIND(brls::Label, clearLabel, "tv/search/clear"); 28 | BRLS_BIND(brls::Label, deleteLabel, "tv/search/delete"); 29 | BRLS_BIND(brls::Label, searchLabel, "tv/search/label"); 30 | BRLS_BIND(SVGImage, searchSVG, "tv/search/svg"); 31 | 32 | void doSuggest(); 33 | void doSearch(const std::string& searchTerm); 34 | void updateInput(); 35 | 36 | std::string currentSearch; 37 | size_t searchIndex = 0; 38 | size_t pageSize = 20; 39 | }; 40 | -------------------------------------------------------------------------------- /app/include/tab/server_add.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2023 dragonflylee 3 | */ 4 | 5 | #pragma once 6 | 7 | #include 8 | 9 | class ServerAdd : public brls::Box { 10 | public: 11 | ServerAdd(); 12 | ~ServerAdd() override; 13 | 14 | brls::View* getDefaultFocus() override; 15 | 16 | private: 17 | bool onConnect(); 18 | 19 | BRLS_BIND(brls::InputCell, inputUrl, "server/url"); 20 | BRLS_BIND(brls::DetailCell, btnConnect, "server/connect"); 21 | }; 22 | -------------------------------------------------------------------------------- /app/include/tab/server_login.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2023 dragonflylee 3 | */ 4 | 5 | #pragma once 6 | 7 | #include 8 | 9 | class ServerLogin : public brls::Box { 10 | public: 11 | ServerLogin(const std::string& name, const std::string& url, const std::string& user = ""); 12 | ~ServerLogin(); 13 | 14 | bool onSignin(); 15 | 16 | private: 17 | BRLS_BIND(brls::Header, hdrSigin, "server/sigin_to"); 18 | BRLS_BIND(brls::InputCell, inputUser, "server/user"); 19 | BRLS_BIND(brls::InputCell, inputPass, "server/pass"); 20 | BRLS_BIND(brls::Button, btnSignin, "server/signin"); 21 | BRLS_BIND(brls::Button, btnQuickConnect, "server/quick_connect"); 22 | BRLS_BIND(brls::Label, labelDisclaimer, "login/disclaimer"); 23 | 24 | std::string url; 25 | 26 | void Disclaimer(); 27 | }; -------------------------------------------------------------------------------- /app/include/tab/suggest_movie.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2025 dragonflylee 3 | */ 4 | 5 | #pragma once 6 | 7 | #include 8 | 9 | class RecyclingGrid; 10 | class RecommendCell; 11 | 12 | class SuggestMovie : public AttachedView { 13 | public: 14 | explicit SuggestMovie(const std::string itemId); 15 | 16 | void onCreate() override; 17 | 18 | private: 19 | RecyclingGrid *recycler = nullptr; 20 | RecommendCell *latest = nullptr; 21 | std::string itemId; 22 | 23 | void doLatest(); 24 | void doRecommend(); 25 | }; -------------------------------------------------------------------------------- /app/include/tab/suggest_show.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2025 dragonflylee 3 | */ 4 | 5 | #pragma once 6 | 7 | #include 8 | #include 9 | 10 | class RecylingVideo; 11 | 12 | class SuggestShow : public AttachedView, public Presenter { 13 | public: 14 | explicit SuggestShow(const std::string& itemId); 15 | ~SuggestShow() override; 16 | 17 | void onCreate() override; 18 | 19 | void doRequest() override; 20 | 21 | private: 22 | BRLS_BIND(RecylingVideo, resume, "suggest/show/resume"); 23 | BRLS_BIND(RecylingVideo, latest, "suggest/show/latest"); 24 | BRLS_BIND(RecylingVideo, nextUp, "suggest/show/nextup"); 25 | 26 | std::string itemId; 27 | }; -------------------------------------------------------------------------------- /app/include/utils/dialog.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | class Dialog { 7 | public: 8 | using Callback = brls::VoidEvent::Callback; 9 | 10 | /// 展示普通对话框 11 | static void show(const std::string& msg, Callback cb = []() {}); 12 | 13 | /// 展示带有取消按钮的对话框 14 | static void cancelable(const std::string& msg, Callback cb); 15 | 16 | /// 退出应用提示 17 | static void quitApp(bool restart = true); 18 | }; -------------------------------------------------------------------------------- /app/include/utils/event.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | typedef enum MpvEventEnum { 8 | MPV_LOADED, 9 | MPV_PAUSE, 10 | MPV_RESUME, 11 | MPV_STOP, 12 | LOADING_START, 13 | LOADING_END, 14 | UPDATE_DURATION, 15 | UPDATE_PROGRESS, 16 | START_FILE, 17 | END_OF_FILE, 18 | CACHE_SPEED_CHANGE, 19 | VIDEO_SPEED_CHANGE, 20 | VIDEO_VOLUME_CHANGE, 21 | VIDEO_MUTE, 22 | VIDEO_UNMUTE, 23 | MPV_FILE_ERROR, 24 | RESET, 25 | } MpvEventEnum; 26 | 27 | typedef brls::Event MPVEvent; 28 | typedef brls::Event MPVCustomEvent; 29 | typedef brls::Event MPVCommandReply; 30 | 31 | // 用于 VideoView 可以接收的自定义事件 32 | const std::string VIDEO_CLOSE = "VIDEO_CLOSE"; 33 | // 用于 PlayerView 可以接收的自定义事件 34 | const std::string QUALITY_CHANGE = "QUALITY_CHANGE"; 35 | const std::string SYNC_STOP = "SYNC_STOP"; 36 | 37 | const std::string TRACK_START = "TRACK_START"; 38 | -------------------------------------------------------------------------------- /app/include/utils/gesture.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by fang on 2024/1/8. 3 | // 4 | 5 | #pragma once 6 | 7 | #include 8 | 9 | enum class OsdGestureType { 10 | TAP, 11 | DOUBLE_TAP_START, 12 | DOUBLE_TAP_END, 13 | LONG_PRESS_START, 14 | LONG_PRESS_END, 15 | LONG_PRESS_CANCEL, 16 | HORIZONTAL_PAN_START, 17 | HORIZONTAL_PAN_UPDATE, 18 | HORIZONTAL_PAN_END, 19 | HORIZONTAL_PAN_CANCEL, 20 | LEFT_VERTICAL_PAN_START, 21 | LEFT_VERTICAL_PAN_UPDATE, 22 | LEFT_VERTICAL_PAN_END, 23 | LEFT_VERTICAL_PAN_CANCEL, 24 | RIGHT_VERTICAL_PAN_START, 25 | RIGHT_VERTICAL_PAN_UPDATE, 26 | RIGHT_VERTICAL_PAN_END, 27 | RIGHT_VERTICAL_PAN_CANCEL, 28 | NONE, 29 | }; 30 | 31 | struct OsdGestureStatus { 32 | OsdGestureType osdGestureType; // Gesture type 33 | brls::GestureState state; // Gesture state 34 | brls::Point position; // Current position 35 | float deltaX, deltaY; 36 | }; 37 | typedef brls::Event OsdGestureEvent; 38 | 39 | class OsdGestureRecognizer : public brls::GestureRecognizer { 40 | public: 41 | explicit OsdGestureRecognizer(const OsdGestureEvent::Callback& respond); 42 | 43 | brls::GestureState recognitionLoop( 44 | brls::TouchState touch, brls::MouseState mouse, brls::View* view, brls::Sound* soundToPlay) override; 45 | 46 | // Get current state of recognizer 47 | OsdGestureStatus getCurrentStatus(); 48 | 49 | // Get tap gesture event 50 | [[nodiscard]] OsdGestureEvent getTapGestureEvent() const { return tapEvent; } 51 | 52 | private: 53 | OsdGestureEvent tapEvent; 54 | brls::Point position{}; 55 | brls::Point delta{}; 56 | float deltaX{}, deltaY{}; 57 | int64_t startTime{}; 58 | int64_t endTime{}; 59 | size_t iter{}; 60 | OsdGestureType osdGestureType{OsdGestureType::NONE}; 61 | brls::GestureState lastState{brls::GestureState::END}; 62 | }; -------------------------------------------------------------------------------- /app/include/utils/image.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include "api/http.hpp" 5 | #include "config.hpp" 6 | 7 | class Image { 8 | using Ref = std::shared_ptr; 9 | 10 | public: 11 | Image(); 12 | Image(const Image&) = delete; 13 | 14 | virtual ~Image(); 15 | 16 | template 17 | static void load(brls::Image* view, const fmt::string_view fmt, Args&&... args) { 18 | std::string path = fmt::format(fmt::runtime(fmt), std::forward(args)...); 19 | return with(view, AppConfig::instance().getUrl() + path); 20 | } 21 | 22 | /// @brief 设置要加载内容的图片组件。此函数需要工作在主线程。 23 | static void with(brls::Image* view, const std::string& url); 24 | 25 | /// @brief 取消请求,并清空图片。此函数需要工作在主线程。 26 | static void cancel(brls::Image* view); 27 | 28 | private: 29 | void doRequest(HTTP& s); 30 | 31 | static void clear(brls::Image* view); 32 | 33 | private: 34 | std::string url; 35 | brls::Image* image; 36 | HTTP::Cancel isCancel; 37 | 38 | /// 对象池 39 | inline static std::list pool; 40 | inline static std::mutex requestMutex; 41 | inline static std::unordered_map requests; 42 | }; -------------------------------------------------------------------------------- /app/include/utils/misc.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | namespace misc { 8 | 9 | std::string sec2Time(int64_t t); 10 | 11 | std::string formatSize(uint64_t s); 12 | 13 | std::string randHex(const int len); 14 | 15 | std::string hexEncode(const unsigned char* data, size_t len); 16 | 17 | std::vector split(const std::string& data, char seq); 18 | 19 | bool sendIPC(const std::string& sock, const std::string& payload); 20 | 21 | void initCrashDump(); 22 | 23 | } // namespace misc 24 | 25 | namespace base64 { 26 | 27 | std::string encode(const std::string& input); 28 | 29 | } -------------------------------------------------------------------------------- /app/include/utils/overclock.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifdef __SWITCH__ 4 | 5 | #include 6 | 7 | class SwitchSys { 8 | public: 9 | static void setClock(bool overclock); 10 | 11 | private: 12 | enum class CPUClock { 13 | Stock = 0, // default clock when application is launched 14 | Min = 1020000000, // minimal clock 15 | Med = 1224000000, // medium clock 16 | Max = 1785000000 // maximal clock 17 | }; 18 | 19 | enum class GPUClock { 20 | Stock = 0, // default clock when application is launched 21 | Min = 307200000, // minimal clock 22 | Med = 460000000, // medium clock 23 | Max = 921000000 // maximal clock 24 | }; 25 | 26 | enum class EMCClock { 27 | Stock = 0, // default clock when application is launched 28 | Min = 1331200000, // minimal clock 29 | Med = 1331200000, // medium clock 30 | Max = 1600000000 // maximal clock 31 | }; 32 | 33 | enum class Module { Cpu = PcvModule_CpuBus, Gpu = PcvModule_GPU, Emc = PcvModule_EMC }; 34 | 35 | static int getClock(const Module &module, bool stockClocks = false); 36 | 37 | static bool setClock(const Module &module, int hz); 38 | 39 | static int stock_cpu_clock; 40 | static int stock_gpu_clock; 41 | static int stock_emc_clock; 42 | }; 43 | 44 | #endif -------------------------------------------------------------------------------- /app/include/utils/thread.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #ifdef BOREALIS_USE_STD_THREAD 10 | #include 11 | #else 12 | #include 13 | #endif 14 | #include 15 | #include "api/http.hpp" 16 | 17 | class ThreadPool : public brls::Singleton { 18 | public: 19 | using Task = std::function; 20 | 21 | explicit ThreadPool(); 22 | virtual ~ThreadPool(); 23 | 24 | void submit(Task fn) { 25 | { 26 | std::lock_guard locker(this->taskMutex); 27 | this->tasks.push_back(fn); 28 | } 29 | this->taskCond.notify_one(); 30 | } 31 | 32 | /// @brief 创建线程 33 | void start(size_t num); 34 | 35 | size_t size() const { return this->threads.size(); } 36 | 37 | /// @brief 停止所有线程 38 | void stop(); 39 | 40 | static size_t max_thread_num; 41 | 42 | private: 43 | static void* task_loop(void*); 44 | 45 | #ifdef BOREALIS_USE_STD_THREAD 46 | typedef std::shared_ptr Thread; 47 | #else 48 | typedef pthread_t Thread; 49 | #endif 50 | 51 | std::list threads; 52 | std::mutex threadMutex; 53 | std::list tasks; 54 | std::mutex taskMutex; 55 | std::condition_variable taskCond; 56 | std::atomic_bool isStop; 57 | }; -------------------------------------------------------------------------------- /app/include/utils/ums.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | class Ums : public brls::Singleton { 7 | public: 8 | struct Device { 9 | int32_t intf_id; 10 | std::string name, mount_name; 11 | }; 12 | 13 | using DeviceList = std::unordered_map; 14 | using DeviceEvent = brls::Event; 15 | 16 | public: 17 | int init(); 18 | bool unmount(const Device &dev); 19 | DeviceEvent *getEvent() { return &this->event; } 20 | inline const DeviceList &getDevice() const { return this->devices; } 21 | 22 | private: 23 | DeviceList devices; 24 | DeviceEvent event; 25 | }; -------------------------------------------------------------------------------- /app/include/view/button_close.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by fang on 2022/12/27. 3 | // 4 | 5 | // register this view in main.cpp 6 | //#include "view/button_close.hpp" 7 | // brls::Application::registerXMLView("ButtonClose", ButtonClose::create); 8 | // 13 | 14 | class ButtonClose : public brls::Box { 15 | public: 16 | ButtonClose(); 17 | 18 | void setTextColor(NVGcolor color); 19 | 20 | ~ButtonClose(); 21 | 22 | static View* create(); 23 | 24 | private: 25 | BRLS_BIND(brls::Label, label, "close/button/text"); 26 | }; -------------------------------------------------------------------------------- /app/include/view/custom_button.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by fang on 2022/8/22. 3 | // 4 | 5 | // register this view in main.cpp 6 | //#include "view/custom_button.hpp" 7 | // brls::Application::registerXMLView("CustomButton", CustomButton::create); 8 | 9 | #pragma once 10 | 11 | #include 12 | 13 | class SVGImage; 14 | 15 | class CustomButton : public brls::Box { 16 | public: 17 | CustomButton(); 18 | 19 | ~CustomButton(); 20 | 21 | static View *create(); 22 | 23 | void onFocusGained() override; 24 | 25 | void onFocusLost() override; 26 | 27 | brls::Event *getFocusEvent(); 28 | 29 | View *getNextFocus(brls::FocusDirection direction, View *currentView) override; 30 | 31 | void setCustomNavigation(std::function navigation); 32 | 33 | private: 34 | std::string iconDefault, iconActivate; 35 | SVGImage *icon = nullptr; 36 | brls::Event focusEvent; 37 | std::function customNavigation = nullptr; 38 | }; -------------------------------------------------------------------------------- /app/include/view/danmaku_setting.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by fang on 2023/1/10. 3 | // 4 | 5 | // register this fragment in main.cpp 6 | //#include "fragment/player_danmaku_setting.hpp" 7 | // brls::Application::registerXMLView("DanmakuSetting", DanmakuSetting::create); 8 | // 13 | 14 | class ButtonClose; 15 | 16 | class DanmakuSetting : public brls::Box { 17 | public: 18 | DanmakuSetting(); 19 | 20 | bool isTranslucent() override; 21 | 22 | View* getDefaultFocus() override; 23 | 24 | ~DanmakuSetting() override; 25 | 26 | static View* create(); 27 | 28 | private: 29 | BRLS_BIND(brls::SelectorCell, cellArea, "player/danmaku/style/area"); 30 | BRLS_BIND(brls::SelectorCell, cellAlpha, "player/danmaku/style/alpha"); 31 | BRLS_BIND(brls::SelectorCell, cellSpeed, "player/danmaku/style/speed"); 32 | BRLS_BIND(brls::SelectorCell, cellFontsize, "player/danmaku/style/fontsize"); 33 | BRLS_BIND(brls::SelectorCell, cellLineHeight, "player/danmaku/style/lineHeight"); 34 | BRLS_BIND(brls::SelectorCell, cellBackground, "player/danmaku/style/background"); 35 | 36 | BRLS_BIND(brls::SelectorCell, cellRenderPerf, "player/danmaku/performance/render"); 37 | 38 | BRLS_BIND(ButtonClose, closebtn, "button/close"); 39 | BRLS_BIND(brls::ScrollingFrame, settings, "danmaku/settings"); 40 | BRLS_BIND(brls::Box, cancel, "player/cancel"); 41 | }; -------------------------------------------------------------------------------- /app/include/view/gallery_view.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by fang on 2022/8/21. 3 | // 4 | 5 | // register this view in main.cpp 6 | //#include "view/gallery_view.hpp" 7 | // brls::Application::registerXMLView("GalleryView", GalleryView::create); 8 | 9 | #pragma once 10 | 11 | #include 12 | 13 | typedef std::pair GalleryItemData; 14 | typedef std::vector GalleryData; 15 | 16 | enum class GalleryAnimation { ENTER_LEFT, ENTER_RIGHT, EXIT_LEFT, EXIT_RIGHT }; 17 | 18 | class GalleryItem : public brls::Box { 19 | public: 20 | GalleryItem(); 21 | 22 | ~GalleryItem() override = default; 23 | 24 | void animate(GalleryAnimation animation); 25 | 26 | void startScrolling(float newScroll); 27 | 28 | private: 29 | brls::Animatable contentOffsetX = 0.0f; 30 | }; 31 | 32 | class ImageGalleryItem : public GalleryItem { 33 | public: 34 | ImageGalleryItem(); 35 | 36 | virtual void setData(GalleryItemData value); 37 | 38 | private: 39 | BRLS_BIND(brls::Image, image, "gallery/image"); 40 | BRLS_BIND(brls::Label, label, "gallery/label"); 41 | GalleryItemData data; 42 | }; 43 | 44 | class GalleryView : public brls::Box { 45 | public: 46 | GalleryView(); 47 | 48 | ~GalleryView() override; 49 | 50 | static View *create(); 51 | 52 | void setData(GalleryData value); 53 | 54 | void addCustomView(GalleryItem *view); 55 | 56 | void prev(); 57 | 58 | void next(); 59 | 60 | void setIndicatorPosition(float height); 61 | 62 | void draw(NVGcontext *vg, float x, float y, float width, float height, brls::Style style, 63 | brls::FrameContext *ctx) override; 64 | 65 | private: 66 | GalleryData data; 67 | unsigned int index = 0; 68 | float indicatorPosition = 0.98; 69 | }; -------------------------------------------------------------------------------- /app/include/view/media_filter.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2023 dragonflylee 3 | // 4 | 5 | #pragma once 6 | 7 | #include 8 | 9 | class MediaFilter : public brls::Box { 10 | public: 11 | MediaFilter(); 12 | ~MediaFilter() override; 13 | 14 | bool isTranslucent() override { return true; } 15 | 16 | brls::VoidEvent* getEvent() { return &this->event; } 17 | 18 | inline static int selectedSort = 1; 19 | inline static int selectedOrder = 1; 20 | inline static bool selectedPlayed = false; 21 | inline static bool selectedUnplayed = false; 22 | 23 | inline static std::string sortList[] = { 24 | "SortName", 25 | "DateCreated", 26 | "DatePlayed", 27 | "PremiereDate", 28 | "PlayCount", 29 | "CommunityRating", 30 | "Random", 31 | }; 32 | 33 | private: 34 | BRLS_BIND(brls::Box, cancel, "filter/cancel"); 35 | BRLS_BIND(brls::SelectorCell, sortBy, "media/sort/by"); 36 | BRLS_BIND(brls::SelectorCell, sortOrder, "media/sort/order"); 37 | BRLS_BIND(brls::BooleanCell, filterPlayed, "media/filter/played"); 38 | BRLS_BIND(brls::BooleanCell, filterUnplayed, "media/filter/unplayed"); 39 | 40 | brls::VoidEvent event; 41 | }; -------------------------------------------------------------------------------- /app/include/view/people_source.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | class PeopleDataSource : public RecyclingGridDataSource { 7 | public: 8 | using MediaList = std::vector; 9 | 10 | explicit PeopleDataSource(const MediaList& r); 11 | 12 | size_t getItemCount() override; 13 | 14 | RecyclingGridItem* cellForRow(RecyclingView* recycler, size_t index) override; 15 | 16 | void onItemSelected(brls::Box* recycler, size_t index) override; 17 | 18 | void clearData() override; 19 | 20 | protected: 21 | MediaList list; 22 | }; 23 | -------------------------------------------------------------------------------- /app/include/view/presenter.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | class Presenter { 6 | public: 7 | Presenter(); 8 | virtual ~Presenter(); 9 | 10 | virtual void doRequest() = 0; 11 | 12 | protected: 13 | MPVCustomEvent::Subscription customEventSubscribeID; 14 | }; -------------------------------------------------------------------------------- /app/include/view/recyling_video.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2025 dragonflylee 3 | */ 4 | 5 | #pragma once 6 | 7 | #include 8 | 9 | class HRecyclerFrame; 10 | 11 | class RecylingVideo : public brls::Box { 12 | public: 13 | RecylingVideo(); 14 | ~RecylingVideo() override; 15 | 16 | static brls::View* create(); 17 | 18 | using Callback = std::function; 19 | 20 | void reset() { this->start = 0; } 21 | void setTitle(const std::string& text); 22 | void onQuery(const Callback& callback = nullptr); 23 | void doRequest(bool refresh = false); 24 | void doLatest(bool refresh = false); 25 | 26 | private: 27 | BRLS_BIND(brls::Header, title, "recycler/title"); 28 | BRLS_BIND(HRecyclerFrame, recycler, "recycler/videos"); 29 | 30 | Callback queryCallback = nullptr; 31 | size_t start = 0; 32 | size_t pageSize = 10; 33 | }; -------------------------------------------------------------------------------- /app/include/view/search_list.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2023 dragonflylee 3 | */ 4 | 5 | #pragma once 6 | 7 | #include 8 | 9 | class HRecyclerFrame; 10 | 11 | class SearchList : public brls::Box { 12 | public: 13 | SearchList(); 14 | ~SearchList() override; 15 | 16 | void doRequest(const std::string& searchTerm); 17 | 18 | static brls::View* create(); 19 | 20 | private: 21 | BRLS_BIND(brls::Header, title, "recycler/title"); 22 | BRLS_BIND(HRecyclerFrame, recycler, "recycler/videos"); 23 | 24 | std::string itemType; 25 | size_t pageSize = 10; 26 | }; -------------------------------------------------------------------------------- /app/include/view/selector_cell.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2023 dragonflylee 3 | */ 4 | 5 | #pragma once 6 | 7 | #include 8 | 9 | class SelectorCell : public brls::SelectorCell { 10 | public: 11 | SelectorCell(); 12 | 13 | static View* create(); 14 | 15 | private: 16 | brls::Event dismissEvent; 17 | }; -------------------------------------------------------------------------------- /app/include/view/svg_image.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by fang on 2022/6/5. 3 | // 4 | 5 | #pragma once 6 | 7 | #include 8 | #include 9 | 10 | class SVGImage : public brls::Image { 11 | public: 12 | SVGImage(); 13 | 14 | ~SVGImage() override; 15 | 16 | void draw(NVGcontext* vg, float x, float y, float width, float height, brls::Style style, brls::FrameContext* ctx) override; 17 | 18 | void setImageFromSVGRes(const std::string& value); 19 | 20 | void setImageFromSVGFile(const std::string& value); 21 | 22 | void setImageFromSVGString(const std::string& value); 23 | 24 | void rotate(float value); 25 | 26 | void updateBitmap(); 27 | 28 | static View* create(); 29 | 30 | private: 31 | std::unique_ptr document = nullptr; 32 | brls::VoidEvent::Subscription subscription; 33 | std::string filePath; 34 | float angle = 0; 35 | }; -------------------------------------------------------------------------------- /app/include/view/text_box.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by fang on 2022/5/30. 3 | // 4 | 5 | #pragma once 6 | 7 | #include 8 | 9 | class TextBox : public brls::Label { 10 | public: 11 | TextBox(); 12 | ~TextBox() override; 13 | 14 | void draw(NVGcontext* vg, float x, float y, float width, float height, brls::Style style, 15 | brls::FrameContext* ctx) override; 16 | void onLayout() override; 17 | void setText(const std::string& text) override; 18 | 19 | static brls::View* create(); 20 | 21 | float cutText(float width); 22 | 23 | void setParsedDone(bool value) { this->parsedDone = value; } 24 | 25 | private: 26 | // 最大的行数 27 | size_t maxRows = 20; 28 | 29 | bool parsedDone = false; 30 | std::string cuttedText; 31 | }; -------------------------------------------------------------------------------- /app/include/view/video_card.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | class SVGImage; 8 | 9 | class BaseCardCell : public RecyclingGridItem { 10 | public: 11 | ~BaseCardCell() { Image::cancel(this->picture); } 12 | 13 | void prepareForReuse() override { this->picture->setImageFromRes("img/video-card-bg.png"); } 14 | 15 | void cacheForReuse() override { Image::cancel(this->picture); } 16 | 17 | BRLS_BIND(brls::Image, picture, "video/card/picture"); 18 | BRLS_BIND(brls::Label, labelTitle, "video/card/label/title"); 19 | BRLS_BIND(brls::Label, labelExt, "video/card/label/ext"); 20 | }; 21 | 22 | class MediaCardCell : public BaseCardCell { 23 | public: 24 | MediaCardCell() { this->inflateFromXMLRes("xml/view/video_card.xml"); } 25 | 26 | static MediaCardCell* create() { return new MediaCardCell(); } 27 | }; 28 | 29 | class VideoCardCell : public BaseCardCell { 30 | public: 31 | VideoCardCell() { this->inflateFromXMLRes("xml/view/video_card.xml"); } 32 | 33 | static VideoCardCell* create() { return new VideoCardCell(); } 34 | 35 | BRLS_BIND(SVGImage, badgeTopRight, "video/card/badge/top"); 36 | BRLS_BIND(brls::Label, labelRating, "video/card/label/rating"); 37 | BRLS_BIND(brls::Rectangle, rectProgress, "video/card/progress"); 38 | }; -------------------------------------------------------------------------------- /app/include/view/video_progress_slider.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by fang on 2022/8/15. 3 | // 4 | 5 | // register this view in main.cpp 6 | //#include "view/video_progress_slider.hpp" 7 | // brls::Application::registerXMLView("VideoProgressSlider", VideoProgressSlider::create); 8 | 9 | #pragma once 10 | 11 | #include 12 | 13 | class SVGImage; 14 | 15 | class VideoProgressSlider : public brls::Box { 16 | public: 17 | VideoProgressSlider(); 18 | 19 | ~VideoProgressSlider() override; 20 | 21 | static brls::View* create(); 22 | 23 | void onLayout() override; 24 | 25 | brls::View* getDefaultFocus() override; 26 | 27 | void draw(NVGcontext* vg, float x, float y, float width, float height, brls::Style style, 28 | brls::FrameContext* ctx) override; 29 | 30 | void setProgress(float progress); 31 | 32 | [[nodiscard]] float getProgress() const { return this->progress; } 33 | 34 | // Progress is manually dragged 35 | brls::Event& getProgressEvent() { return this->progressEvent; } 36 | 37 | // Manual dragging is over 38 | brls::Event& getProgressSetEvent() { return this->progressSetEvent; } 39 | 40 | // Clear all the points 41 | void clearClipPoint(); 42 | 43 | void setClipPoint(const std::vector& data); 44 | 45 | private: 46 | brls::InputManager* input; 47 | brls::Rectangle* line; 48 | brls::Rectangle* lineEmpty; 49 | SVGImage* pointerIcon; 50 | brls::Box* pointer; 51 | 52 | brls::Event progressEvent; 53 | brls::Event progressSetEvent; 54 | std::vector clipPointList; 55 | 56 | float progress = 1; 57 | 58 | void updateUI(); 59 | }; -------------------------------------------------------------------------------- /app/include/view/video_source.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | class VideoDataSource : public RecyclingGridDataSource { 7 | public: 8 | using MediaList = std::vector; 9 | 10 | explicit VideoDataSource(const MediaList& r); 11 | 12 | size_t getItemCount() override; 13 | 14 | RecyclingGridItem* cellForRow(RecyclingView* recycler, size_t index) override; 15 | 16 | void onItemSelected(brls::Box* recycler, size_t index) override; 17 | 18 | void clearData() override; 19 | 20 | void appendData(const MediaList& data); 21 | 22 | protected: 23 | MediaList list; 24 | }; 25 | -------------------------------------------------------------------------------- /app/platform/osx/app.icns: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dragonflylee/switchfin/be742882e06e48943632d0255ac597c8955446df/app/platform/osx/app.icns -------------------------------------------------------------------------------- /app/platform/ps4/sce_sys/icon0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dragonflylee/switchfin/be742882e06e48943632d0255ac597c8955446df/app/platform/ps4/sce_sys/icon0.png -------------------------------------------------------------------------------- /app/platform/ps4/sce_sys/pic0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dragonflylee/switchfin/be742882e06e48943632d0255ac597c8955446df/app/platform/ps4/sce_sys/pic0.png -------------------------------------------------------------------------------- /app/platform/vita/sce_sys/bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dragonflylee/switchfin/be742882e06e48943632d0255ac597c8955446df/app/platform/vita/sce_sys/bg.png -------------------------------------------------------------------------------- /app/platform/vita/sce_sys/icon0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dragonflylee/switchfin/be742882e06e48943632d0255ac597c8955446df/app/platform/vita/sce_sys/icon0.png -------------------------------------------------------------------------------- /app/platform/vita/sce_sys/pic0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dragonflylee/switchfin/be742882e06e48943632d0255ac597c8955446df/app/platform/vita/sce_sys/pic0.png -------------------------------------------------------------------------------- /app/platform/vita/sce_sys/startup.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dragonflylee/switchfin/be742882e06e48943632d0255ac597c8955446df/app/platform/vita/sce_sys/startup.png -------------------------------------------------------------------------------- /app/platform/vita/template.xml.in: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | bg.png 6 | 7 | 8 | 9 | startup.png 10 | 11 | 12 | 13 | 14 | 15 | ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_ALTER} 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /app/platform/win32/app.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dragonflylee/switchfin/be742882e06e48943632d0255ac597c8955446df/app/platform/win32/app.ico -------------------------------------------------------------------------------- /app/platform/win32/app.manifest: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | UTF-8 6 | 7 | 8 | 9 | 10 | true/pm 11 | PerMonitorV2 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /app/platform/win32/app.rc.in: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | 1 VERSIONINFO 4 | FILEVERSION ${VERSION_MAJOR}, ${VERSION_MINOR}, ${VERSION_ALTER}, ${VERSION_BUILD} 5 | FILEFLAGSMASK VS_FFI_FILEFLAGSMASK 6 | #ifdef _DEBUG 7 | FILEFLAGS VS_FF_DEBUG 8 | #else 9 | FILEFLAGS 0 10 | #endif 11 | FILEOS VOS__WINDOWS32 12 | FILETYPE VFT_APP 13 | FILESUBTYPE VFT2_UNKNOWN 14 | BEGIN 15 | BLOCK "StringFileInfo" 16 | BEGIN 17 | BLOCK "040904B0" 18 | BEGIN 19 | VALUE "FileDescription", "Switchfin for Windows" 20 | VALUE "LegalCopyright", "dragonflyee (C) Copyright 2025" 21 | VALUE "OriginalFilename", "Switchfin.exe" 22 | VALUE "ProductVersion", "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_ALTER}.${VERSION_BUILD}" 23 | END 24 | END 25 | BLOCK "VarFileInfo" 26 | BEGIN 27 | VALUE "Translation", 0x409, 1200 28 | END 29 | END 30 | 31 | IDI_ICON ICON "${CMAKE_SOURCE_DIR}/app/platform/win32/app.ico" -------------------------------------------------------------------------------- /app/src/activity/gallery_activity.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by fang on 2023/4/26. 3 | // 4 | 5 | #include 6 | 7 | #include "activity/gallery_activity.hpp" 8 | #include "view/gallery_view.hpp" 9 | #include "utils/image.hpp" 10 | 11 | const std::string ImageGalleryItemXML = R"xml( 12 | 19 | 20 | 23 | 24 | )xml"; 25 | 26 | class NetImageGalleryItem : public GalleryItem { 27 | public: 28 | explicit NetImageGalleryItem(const std::string& url) { 29 | this->inflateFromXMLString(ImageGalleryItemXML); 30 | this->image->setImageFromRes("img/video-card-bg.png"); 31 | Image::with(this->image, url); 32 | } 33 | 34 | ~NetImageGalleryItem() override { Image::cancel(this->image); } 35 | 36 | BRLS_BIND(brls::Image, image, "gallery/image"); 37 | }; 38 | 39 | GalleryActivity::GalleryActivity(const std::string& url) { 40 | brls::Logger::debug("GalleryActivity: create"); 41 | 42 | this->view = new NetImageGalleryItem(url); 43 | } 44 | 45 | void GalleryActivity::onContentAvailable() { 46 | brls::Logger::debug("GalleryActivity: onContentAvailable"); 47 | gallery->setIndicatorPosition(0.97); 48 | gallery->addCustomView(this->view); 49 | } 50 | 51 | GalleryActivity::~GalleryActivity() { brls::Logger::debug("GalleryActivity: delete"); } 52 | 53 | bool GalleryActivity::isTranslucent() { return true; } 54 | -------------------------------------------------------------------------------- /app/src/activity/main_activity.cpp: -------------------------------------------------------------------------------- 1 | #include "activity/main_activity.hpp" 2 | #include "utils/config.hpp" 3 | #include "api/http.hpp" 4 | 5 | MainActivity::MainActivity() { 6 | brls::Logger::debug("MainActivity: create"); 7 | 8 | auto& conf = AppConfig::instance(); 9 | conf.checkDanmuku(); 10 | 11 | std::string query = HTTP::encode_form({ 12 | {"api_key", conf.getToken()}, 13 | {"deviceId", conf.getDeviceId()}, 14 | }); 15 | 16 | std::string url = fmt::format("{}/socket?{}", "ws" + conf.getUrl().substr(4), query); 17 | this->ws = std::make_unique(url); 18 | } -------------------------------------------------------------------------------- /app/src/client/avio.cpp: -------------------------------------------------------------------------------- 1 | #include "client/avio.hpp" 2 | 3 | namespace remote { 4 | 5 | #if __has_include() 6 | 7 | extern "C" { 8 | #include 9 | } 10 | 11 | AVIO::AVIO(const std::string& path) { 12 | if (!avio_find_protocol_name(path.c_str())) { 13 | throw remote_error("unsupport protocol"); 14 | } 15 | } 16 | 17 | std::vector AVIO::list(const std::string& path) { 18 | AVIODirContext* ctx = nullptr; 19 | AVIODirEntry* next = nullptr; 20 | int ret = avio_open_dir(&ctx, path.c_str(), nullptr); 21 | if (ret < 0) throw remote_error(fmt::format("avio_open_dir {:#x}", ret)); 22 | 23 | std::vector s = {{.type = EntryType::UP}}; 24 | while (avio_read_dir(ctx, &next) >= 0) { 25 | if (!next) break; 26 | 27 | DirEntry item; 28 | item.name = next->name; 29 | item.path = path + "/" + item.name; 30 | if (next->type == AVIO_ENTRY_DIRECTORY) { 31 | item.type = EntryType::DIR; 32 | } else { 33 | item.type = EntryType::FILE; 34 | item.fileSize = next->size; 35 | } 36 | s.push_back(item); 37 | avio_free_directory_entry(&next); 38 | } 39 | 40 | avio_close_dir(&ctx); 41 | return s; 42 | } 43 | 44 | #else 45 | 46 | AVIO::AVIO(const std::string& path) { throw remote_error("unsupport protocol"); } 47 | 48 | std::vector AVIO::list(const std::string& path) { return {}; } 49 | 50 | #endif 51 | 52 | } // namespace remote 53 | -------------------------------------------------------------------------------- /app/src/client/client.cpp: -------------------------------------------------------------------------------- 1 | #include "client/local.hpp" 2 | #include "client/webdav.hpp" 3 | #include "client/apache.hpp" 4 | #include "client/avio.hpp" 5 | #include 6 | 7 | namespace remote { 8 | 9 | std::shared_ptr create(const AppRemote& c) { 10 | auto pos = c.url.find_first_of("://"); 11 | if (pos == std::string::npos) { 12 | throw remote_error("invalid url"); 13 | } 14 | std::string scheme = c.url.substr(0, pos); 15 | if (scheme == "webdav" || scheme == "webdavs") { 16 | std::string url = "http" + c.url.substr(6); 17 | return std::make_shared(url, c); 18 | } 19 | if (scheme == "file") { 20 | return std::make_shared(); 21 | } 22 | if (scheme == "http" || scheme == "https") { 23 | return std::make_shared(c); 24 | } 25 | return std::make_shared(c.url); 26 | } 27 | 28 | void Client::init(const AppRemote& conf, HTTP& cilent) { 29 | std::stringstream ssextra; 30 | ssextra << fmt::format("network-timeout={}", HTTP::TIMEOUT / 100); 31 | if (HTTP::PROXY_STATUS) ssextra << ",http-proxy=\"" << HTTP::PROXY << "\""; 32 | 33 | if (conf.user.size() > 0 || conf.passwd.size() > 0) { 34 | std::string auth = base64::encode(fmt::format("{}:{}", conf.user, conf.passwd)); 35 | ssextra << fmt::format(",http-header-fields=\"Authorization: Basic {}\"", auth); 36 | cilent.set_basic_auth(conf.user, conf.passwd); 37 | } 38 | if (conf.user_agent.size() > 0) { 39 | ssextra << fmt::format(",user_agent=\"{}\"", conf.user_agent); 40 | cilent.set_user_agent(conf.user_agent); 41 | } 42 | this->extra = ssextra.str(); 43 | } 44 | 45 | } // namespace remote -------------------------------------------------------------------------------- /app/src/client/local.cpp: -------------------------------------------------------------------------------- 1 | #include "client/local.hpp" 2 | 3 | #ifdef USE_BOOST_FILESYSTEM 4 | #include 5 | namespace fs = boost::filesystem; 6 | #elif __has_include() 7 | #include 8 | namespace fs = std::filesystem; 9 | #elif __has_include("experimental/filesystem") 10 | #include 11 | namespace fs = std::experimental::filesystem; 12 | #else 13 | #error "Failed to include header!" 14 | #endif 15 | 16 | namespace remote { 17 | 18 | std::vector Local::list(const std::string& path) { 19 | std::vector s = {{.type = EntryType::UP}}; 20 | std::string p = path.rfind("file://") == 0 ? path.substr(7) : path; 21 | auto it = fs::directory_iterator(p); 22 | for (const auto& fp : it) { 23 | DirEntry item; 24 | auto& p = fp.path(); 25 | item.name = p.filename().string(); 26 | item.path = p.string(); 27 | if (fp.is_directory()) { 28 | item.type = EntryType::DIR; 29 | } else { 30 | item.type = EntryType::FILE; 31 | item.fileSize = fs::file_size(p); 32 | } 33 | s.push_back(item); 34 | } 35 | return s; 36 | } 37 | 38 | } // namespace remote -------------------------------------------------------------------------------- /app/src/tab/search_result.cpp: -------------------------------------------------------------------------------- 1 | #include "tab/search_result.hpp" 2 | #include "view/search_list.hpp" 3 | 4 | SearchResult::SearchResult(const std::string& searchTerm) { 5 | brls::Logger::debug("Tab SearchResult: create"); 6 | // Inflate the tab from the XML file 7 | this->inflateFromXMLRes("xml/tabs/search_result.xml"); 8 | 9 | this->searchMovie->doRequest(searchTerm); 10 | this->searchSeries->doRequest(searchTerm); 11 | this->searchEpisode->doRequest(searchTerm); 12 | this->searchMusic->doRequest(searchTerm); 13 | } 14 | 15 | SearchResult::~SearchResult() { brls::Logger::debug("Tab SearchResult: delete"); } -------------------------------------------------------------------------------- /app/src/utils/dialog.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by fang on 2023/1/6. 3 | // 4 | 5 | #include 6 | #include "utils/dialog.hpp" 7 | #include "utils/config.hpp" 8 | 9 | using namespace brls::literals; 10 | 11 | void Dialog::show(const std::string& msg, Callback cb) { 12 | auto dialog = new brls::Dialog(msg); 13 | dialog->addButton("hints/ok"_i18n, cb); 14 | dialog->open(); 15 | } 16 | 17 | void Dialog::cancelable(const std::string& msg, Callback cb) { 18 | auto dialog = new brls::Dialog(msg); 19 | dialog->addButton("hints/cancel"_i18n, []() {}); 20 | dialog->addButton("hints/ok"_i18n, cb); 21 | dialog->open(); 22 | } 23 | 24 | /// 退出应用提示 25 | void Dialog::quitApp(bool restart) { 26 | auto dialog = new brls::Dialog("main/setting/quit_hint"_i18n); 27 | dialog->addButton("hints/ok"_i18n, [restart]() { 28 | brls::Box* container = new brls::Box(); 29 | container->setJustifyContent(brls::JustifyContent::CENTER); 30 | container->setAlignItems(brls::AlignItems::CENTER); 31 | brls::Label* hint = new brls::Label(); 32 | hint->setFocusable(true); 33 | hint->setHideHighlight(true); 34 | hint->setFontSize(32); 35 | hint->setText("hints/quit"_i18n); 36 | container->addView(hint); 37 | container->setBackgroundColor(brls::Application::getTheme().getColor("brls/background")); 38 | brls::Application::pushActivity(new brls::Activity(container), brls::TransitionAnimation::NONE); 39 | brls::Application::getPlatform()->exitToHomeMode(!restart); 40 | brls::Application::quit(); 41 | }); 42 | dialog->setCancelable(false); 43 | dialog->open(); 44 | } -------------------------------------------------------------------------------- /app/src/view/button_close.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by fang on 2022/12/27. 3 | // 4 | 5 | #include "view/button_close.hpp" 6 | 7 | ButtonClose::ButtonClose() { 8 | this->inflateFromXMLRes("xml/view/button_close.xml"); 9 | brls::Logger::debug("View ButtonClose: create"); 10 | 11 | this->registerColorXMLAttribute("textColor", [this](NVGcolor value) { this->setTextColor(value); }); 12 | 13 | this->registerClickAction([this](...) { 14 | this->dismiss(); 15 | return true; 16 | }); 17 | this->addGestureRecognizer(new brls::TapGestureRecognizer(this)); 18 | } 19 | 20 | void ButtonClose::setTextColor(NVGcolor color) { this->label->setTextColor(color); } 21 | 22 | ButtonClose::~ButtonClose() { brls::Logger::debug("View ButtonClose: delete"); } 23 | 24 | brls::View* ButtonClose::create() { return new ButtonClose(); } -------------------------------------------------------------------------------- /app/src/view/media_filter.cpp: -------------------------------------------------------------------------------- 1 | #include "view/media_filter.hpp" 2 | #include "api/jellyfin.hpp" 3 | 4 | using namespace brls::literals; 5 | 6 | MediaFilter::MediaFilter() { 7 | this->inflateFromXMLRes("xml/view/media_filter.xml"); 8 | brls::Logger::debug("MediaFilter: create"); 9 | 10 | this->registerAction("hints/cancel"_i18n, brls::BUTTON_B, [this](...) { 11 | brls::Application::popActivity(brls::TransitionAnimation::NONE, [this]() { this->event.fire(); }); 12 | return true; 13 | }); 14 | 15 | this->cancel->registerClickAction([this](...) { 16 | brls::Application::popActivity(brls::TransitionAnimation::NONE, [this]() { this->event.fire(); }); 17 | return true; 18 | }); 19 | this->cancel->addGestureRecognizer(new brls::TapGestureRecognizer(this->cancel)); 20 | 21 | this->sortBy->init("main/media/sort_by"_i18n, 22 | { 23 | "main/media/name"_i18n, 24 | "main/media/date_add"_i18n, 25 | "main/media/date_played"_i18n, 26 | "main/media/premiere_date"_i18n, 27 | "main/media/play_count"_i18n, 28 | "main/media/rating"_i18n, 29 | "main/media/random"_i18n, 30 | }, 31 | selectedSort, [](int selected) { selectedSort = selected; }); 32 | 33 | this->sortOrder->init("main/media/order"_i18n, 34 | { 35 | "main/media/ascending"_i18n, 36 | "main/media/descending"_i18n, 37 | }, 38 | selectedOrder, [](int selected) { selectedOrder = selected; }); 39 | 40 | this->filterPlayed->init("main/media/played"_i18n, selectedPlayed, [](bool value) { selectedPlayed = value; }); 41 | this->filterUnplayed->init( 42 | "main/media/unplayed"_i18n, selectedUnplayed, [](bool value) { selectedUnplayed = value; }); 43 | } 44 | 45 | MediaFilter::~MediaFilter() { brls::Logger::debug("MediaFilter: delete"); } -------------------------------------------------------------------------------- /app/src/view/presenter.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | Presenter::Presenter() { 5 | auto mpvce = MPVCore::instance().getCustomEvent(); 6 | this->customEventSubscribeID = mpvce->subscribe([this](const std::string& event, void* data) { 7 | if (event == VIDEO_CLOSE) { 8 | this->doRequest(); 9 | } 10 | }); 11 | } 12 | 13 | Presenter::~Presenter() { 14 | auto mpvce = MPVCore::instance().getCustomEvent(); 15 | mpvce->unsubscribe(this->customEventSubscribeID); 16 | } -------------------------------------------------------------------------------- /app/src/view/selector_cell.cpp: -------------------------------------------------------------------------------- 1 | #include "view/selector_cell.hpp" 2 | #include "utils/dialog.hpp" 3 | 4 | SelectorCell::SelectorCell() { 5 | this->registerClickAction([this](View* view) { 6 | brls::Dropdown* dropdown = new brls::Dropdown( 7 | this->title->getFullText(), data, [this](int selected) { this->setSelection(selected, false); }, selection, 8 | [this](int selected) { this->dismissEvent.fire(selected); }); 9 | brls::Application::pushActivity(new brls::Activity(dropdown)); 10 | return true; 11 | }); 12 | 13 | this->registerBoolXMLAttribute("quitApp", [this](bool value) { 14 | if (value) this->dismissEvent.subscribe([](int selected) { Dialog::quitApp(); }); 15 | }); 16 | } 17 | 18 | brls::View* SelectorCell::create() { return new SelectorCell(); } -------------------------------------------------------------------------------- /debian/Dockerfile: -------------------------------------------------------------------------------- 1 | ARG IMG=ubuntu 2 | ARG TAG=noble 3 | FROM $IMG:$TAG 4 | ENV DEBIAN_FRONTEND=noninteractive 5 | RUN apt-get update && apt-get install -y --no-install-recommends wget xz-utils \ 6 | ca-certificates debhelper cmake build-essential nasm meson git fakeroot lzip \ 7 | && rm -rf /var/lib/apt/lists/* /usr/share/man/* 8 | 9 | RUN apt-get update && apt-get install -y --no-install-recommends xorg-dev libdbus-1-dev libxpresent-dev \ 10 | libwayland-dev libxkbcommon-dev wayland-protocols libpulse-dev libwebp-dev libass-dev libv4l-dev \ 11 | libuchardet-dev libva-dev libvdpau-dev libjpeg-dev libdrm-dev libegl-dev libdisplay-info-dev \ 12 | && rm -rf /var/lib/apt/lists/* /usr/share/man/* -------------------------------------------------------------------------------- /debian/Dockerfile.bookworm: -------------------------------------------------------------------------------- 1 | # docker build --network host -t build:debian-bookworm -f Dockerfile.bookworm . 2 | # docker run --rm --network host -v $PWD:/build -w /build -it build:debian-bookworm dpkg-buildpackage -b -nc 3 | 4 | FROM debian:bookworm-backports 5 | ENV DEBIAN_FRONTEND=noninteractive 6 | RUN apt-get update && apt-get install -y -t bookworm-backports --no-install-recommends git \ 7 | wget xz-utils ca-certificates debhelper cmake build-essential nasm meson fakeroot lzip \ 8 | && rm -rf /var/lib/apt/lists/* /usr/share/man/* 9 | 10 | RUN apt-get update && apt-get install -y --no-install-recommends xorg-dev libdbus-1-dev libxpresent-dev \ 11 | libwayland-dev libxkbcommon-dev wayland-protocols libpulse-dev libwebp-dev libass-dev libv4l-dev \ 12 | libuchardet-dev libva-dev libvdpau-dev libjpeg-dev libdrm-dev libegl-dev libdisplay-info-dev \ 13 | && rm -rf /var/lib/apt/lists/* /usr/share/man/* -------------------------------------------------------------------------------- /debian/Dockerfile.focal: -------------------------------------------------------------------------------- 1 | # docker build --network host -t build:ubuntu-focal -f Dockerfile.focal . 2 | # docker run --rm --network host -v $PWD:/build -w /build -it build:ubuntu-focal dpkg-buildpackage -b -nc 3 | 4 | ARG TAG=focal 5 | FROM ubuntu:$TAG 6 | ENV DEBIAN_FRONTEND=noninteractive 7 | RUN apt-get update && apt-get install -y --no-install-recommends wget ca-certificates \ 8 | && wget -qO /etc/apt/trusted.gpg.d/kitware.asc https://apt.kitware.com/keys/kitware-archive-latest.asc \ 9 | && echo > /etc/apt/sources.list.d/kitware.list "deb https://apt.kitware.com/ubuntu/ focal main" \ 10 | && apt-get update && apt-get install -y --no-install-recommends debhelper cmake build-essential \ 11 | nasm git fakeroot xz-utils lzip ninja-build python3-pip && pip3 install meson \ 12 | && rm -rf /var/lib/apt/lists/* /usr/share/man/* 13 | 14 | RUN apt-get update && apt-get install -y --no-install-recommends xorg-dev libdbus-1-dev \ 15 | libpulse-dev libwebp-dev libass-dev libv4l-dev libuchardet-dev libva-dev libvdpau-dev \ 16 | libjpeg-dev libdrm-dev libegl-dev libxpresent-dev \ 17 | && rm -rf /var/lib/apt/lists/* /usr/share/man/* -------------------------------------------------------------------------------- /debian/compat: -------------------------------------------------------------------------------- 1 | 10 -------------------------------------------------------------------------------- /debian/control: -------------------------------------------------------------------------------- 1 | Source: switchfin 2 | Section: video 3 | Priority: optional 4 | Maintainer: dragonflylee 5 | Build-Depends: debhelper (>= 10), 6 | cmake, 7 | g++, 8 | xorg-dev, 9 | libdbus-1-dev, 10 | libwebp-dev, 11 | libass-dev, 12 | libuchardet-dev, 13 | libxpresent-dev, 14 | libpulse-dev 15 | Standards-Version: 0.7.1 16 | Vcs-Git: https://github.com/dragonflylee/switchfin.git 17 | 18 | Package: switchfin 19 | Depends: ${shlibs:Depends}, ${misc:Depends} 20 | Architecture: any 21 | Recommends: va-driver-all, vdpau-driver-all 22 | Description: Third-party native Jellyfin client for Nintendo Switch 23 | -------------------------------------------------------------------------------- /images/episode.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dragonflylee/switchfin/be742882e06e48943632d0255ac597c8955446df/images/episode.jpg -------------------------------------------------------------------------------- /images/home.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dragonflylee/switchfin/be742882e06e48943632d0255ac597c8955446df/images/home.jpg -------------------------------------------------------------------------------- /images/library.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dragonflylee/switchfin/be742882e06e48943632d0255ac597c8955446df/images/library.jpg -------------------------------------------------------------------------------- /images/music.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dragonflylee/switchfin/be742882e06e48943632d0255ac597c8955446df/images/music.jpg -------------------------------------------------------------------------------- /images/search.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dragonflylee/switchfin/be742882e06e48943632d0255ac597c8955446df/images/search.jpg -------------------------------------------------------------------------------- /images/series.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dragonflylee/switchfin/be742882e06e48943632d0255ac597c8955446df/images/series.jpg -------------------------------------------------------------------------------- /images/ums.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dragonflylee/switchfin/be742882e06e48943632d0255ac597c8955446df/images/ums.jpg -------------------------------------------------------------------------------- /library/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.15) 2 | 3 | # add lunasvg 4 | set(BUILD_SHARED_LIBS OFF) 5 | set(CMAKE_POLICY_DEFAULT_CMP0077 NEW) 6 | add_subdirectory(lunasvg EXCLUDE_FROM_ALL) 7 | 8 | # add borealis 9 | add_subdirectory(borealis/library) 10 | 11 | if (PLATFORM_PS4) 12 | list(APPEND APP_PLATFORM_LIB SceNet mbedcrypto mbedtls mbedx509) 13 | set(APP_PLATFORM_LIB ${APP_PLATFORM_LIB} PARENT_SCOPE) 14 | elseif (PLATFORM_PSV) 15 | list(APPEND APP_PLATFORM_LIB SceVshBridge_stub) 16 | set(APP_PLATFORM_LIB ${APP_PLATFORM_LIB} PARENT_SCOPE) 17 | endif () -------------------------------------------------------------------------------- /library/packages/c/cppwinrt/xmake.lua: -------------------------------------------------------------------------------- 1 | package("cppwinrt") 2 | set_homepage("https://github.com/microsoft/cppwinrt") 3 | set_description("C++/WinRT is an entirely standard C++ language projection for Windows Runtime (WinRT) APIs") 4 | set_license("MIT") 5 | set_urls("https://github.com/microsoft/cppwinrt/releases/download/2.0.$(version)/Microsoft.Windows.CppWinRT.2.0.$(version).nupkg") 6 | add_versions("230706.1", "e4a827fee480291d4598ea3bb751cb5696a42ded0b795c16f52da729502e07e8") 7 | 8 | on_install("windows", "mingw", function (package) 9 | import("lib.detect.find_tool") 10 | local p7z = find_tool("7z") 11 | os.execv(p7z.program, {"x", package:originfile()}) 12 | 13 | local findvs = function () 14 | local find_vstudio = import("detect.sdks.find_vstudio") 15 | for _, vsinfo in pairs(find_vstudio()) do 16 | if vsinfo.vcvarsall then 17 | return vsinfo.vcvarsall[os.arch()] 18 | end 19 | end 20 | end 21 | 22 | local winmds = {"-in"} 23 | for _, p in ipairs(findvs()["WindowsLibPath"]:split(";")) do 24 | for _, winmd in ipairs(os.filedirs(path.join(p, "*.winmd"))) do 25 | table.insert(winmds, winmd) 26 | end 27 | end 28 | os.execv("bin/cppwinrt", {"-in", "local", "-out", package:installdir("include")}) 29 | os.execv("bin/cppwinrt", table.join(winmds, {"-out", package:installdir("include")})) 30 | end) -------------------------------------------------------------------------------- /library/packages/m/mpv/xmake.lua: -------------------------------------------------------------------------------- 1 | package("mpv") 2 | if is_arch("x64") then 3 | set_urls("https://github.com/dragonflylee/switchfin/releases/download/mingw-packages/mpv-dev-x86_64.7z") 4 | add_versions("0.36.0", "5fe9ae3cda785f2154f7bcb10d9ed4f90a2d32bac09069cad77c21b892fb0685") 5 | elseif is_arch("arm64") then 6 | set_urls("https://github.com/dragonflylee/switchfin/releases/download/mingw-packages/mpv-dev-aarch64.7z") 7 | add_versions("0.36.0", "d508aecfaae5e58b7b5a10f535d6163244215a95afafd62a27125005fdb3a461") 8 | end 9 | add_links("mpv") 10 | on_install("windows", "mingw", function (package) 11 | os.cp("include/*", package:installdir("include")) 12 | os.cp("*.a", package:installdir("lib")) 13 | os.cp("*.dll", package:installdir("bin")) 14 | 15 | import("detect.sdks.find_vstudio") 16 | for _, vsinfo in pairs(find_vstudio()) do 17 | if vsinfo.vcvarsall then 18 | os.setenv("PATH", vsinfo.vcvarsall[os.arch()]["PATH"]) 19 | end 20 | end 21 | 22 | os.execv("lib.exe", { 23 | "/name:libmpv-2.dll", 24 | "/def:mpv.def", 25 | "/out:"..package:installdir("lib").."/mpv.lib", 26 | "/MACHINE:"..package:arch(), 27 | }) 28 | end) -------------------------------------------------------------------------------- /library/packages/n/nanovg/xmake.lua: -------------------------------------------------------------------------------- 1 | package("nanovg") 2 | set_homepage("https://github.com/memononen/nanovg/") 3 | set_description("Antialiased 2D vector drawing library on top of OpenGL for UI and visualizations.") 4 | set_license("zlib") 5 | 6 | add_urls("https://github.com/zeromake/nanovg.git") 7 | add_versions("2023.12.25", "f45d73db67eaadc3df98971872add86f660a3ee5") 8 | 9 | on_install("windows", "macosx", "linux", function (package) 10 | local configs = {} 11 | if package:config("shared") then 12 | configs.kind = "shared" 13 | end 14 | import("package.tools.xmake").install(package, configs) 15 | end) -------------------------------------------------------------------------------- /library/packages/x/xfangfang_glfw/xmake.lua: -------------------------------------------------------------------------------- 1 | package("xfangfang_glfw") 2 | set_homepage("https://www.glfw.org/") 3 | set_description("GLFW is an Open Source, multi-platform library for OpenGL, OpenGL ES and Vulkan application development.") 4 | set_license("zlib") 5 | 6 | set_urls("https://github.com/xfangfang/glfw.git") 7 | add_versions("latest", "288235ec228582bf2bc9cf7765261e4d12426cfb") 8 | 9 | add_deps("cmake") 10 | add_deps("opengl", {optional = true}) 11 | if is_plat("macosx") then 12 | add_frameworks("Cocoa", "IOKit") 13 | elseif is_plat("windows") then 14 | add_syslinks("user32", "shell32", "gdi32") 15 | elseif is_plat("mingw") then 16 | add_syslinks("gdi32") 17 | elseif is_plat("linux") then 18 | -- TODO: add wayland support 19 | add_deps("libx11", "libxrandr", "libxrender", "libxinerama", "libxfixes", "libxcursor", "libxi", "libxext") 20 | add_syslinks("dl", "pthread") 21 | add_defines("_GLFW_X11") 22 | end 23 | on_install(function (package) 24 | local configs = {"-DGLFW_BUILD_DOCS=OFF", "-DGLFW_BUILD_TESTS=OFF", "-DGLFW_BUILD_EXAMPLES=OFF"} 25 | table.insert(configs, "-DCMAKE_BUILD_TYPE=" .. (package:debug() and "Debug" or "Release")) 26 | table.insert(configs, "-DBUILD_SHARED_LIBS=" .. (package:config("shared") and "ON" or "OFF")) 27 | if package:is_plat("windows") then 28 | table.insert(configs, "-DUSE_MSVC_RUNTIME_LIBRARY_DLL=" .. (package:config("vs_runtime"):startswith("MT") and "OFF" or "ON")) 29 | end 30 | if package:is_plat("linux") then 31 | import("package.tools.cmake").install(package, configs, {packagedeps = {"libxrender", "libxfixes", "libxext", "libx11"}}) 32 | else 33 | import("package.tools.cmake").install(package, configs) 34 | end 35 | end) 36 | -------------------------------------------------------------------------------- /resources/font/emoji.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dragonflylee/switchfin/be742882e06e48943632d0255ac597c8955446df/resources/font/emoji.ttf -------------------------------------------------------------------------------- /resources/font/keymap_keyboard.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dragonflylee/switchfin/be742882e06e48943632d0255ac597c8955446df/resources/font/keymap_keyboard.ttf -------------------------------------------------------------------------------- /resources/font/keymap_keyboard_swap.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dragonflylee/switchfin/be742882e06e48943632d0255ac597c8955446df/resources/font/keymap_keyboard_swap.ttf -------------------------------------------------------------------------------- /resources/font/keymap_ps.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dragonflylee/switchfin/be742882e06e48943632d0255ac597c8955446df/resources/font/keymap_ps.ttf -------------------------------------------------------------------------------- /resources/font/keymap_xbox.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dragonflylee/switchfin/be742882e06e48943632d0255ac597c8955446df/resources/font/keymap_xbox.ttf -------------------------------------------------------------------------------- /resources/font/switch_font.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dragonflylee/switchfin/be742882e06e48943632d0255ac597c8955446df/resources/font/switch_font.ttf -------------------------------------------------------------------------------- /resources/i18n/cs/hints.json: -------------------------------------------------------------------------------- 1 | { 2 | "ok": "OK", 3 | "back": "Zpět", 4 | "cancel": "Zrušit", 5 | "exit": "Ukončit", 6 | "on": "Zapnuto", 7 | "off": "Vypnuto", 8 | "delete": "Smazat", 9 | "save": "Uložit", 10 | "submit": "Potvrdit", 11 | "input": "Prosím zadejte...", 12 | "preset": "Předvolba", 13 | "default": "Výchozí", 14 | "current": "Aktuální", 15 | "success": "Povedlo se", 16 | "password": "Zobrazit/Skrýt", 17 | "failed": "Nepovedlo se", 18 | "exit_hint": "Chystáte se ukončit aplikaci?", 19 | "loading": "Načítání", 20 | "refresh": "Obnovit", 21 | "quit": "Ukončuji aplikaci..." 22 | } -------------------------------------------------------------------------------- /resources/i18n/de/hints.json: -------------------------------------------------------------------------------- 1 | { 2 | "ok": "OK", 3 | "back": "Zurück", 4 | "cancel": "Abbrechen", 5 | "exit": "Verlassen", 6 | "on": "An", 7 | "off": "Aus", 8 | "delete": "Löschen", 9 | "save": "Sichern", 10 | "submit": "Absenden", 11 | "input": "Bitte Eingeben...", 12 | "preset": "Preset", 13 | "default": "Voreinstellung", 14 | "current": "Momentanig", 15 | "success": "Erfolg", 16 | "failed": "Fehlgeschlagen", 17 | "exit_hint": "Die Applikation verlassen?", 18 | "loading": "Laden", 19 | "refresh": "Neu Laden", 20 | "quit": "Verlasse die App..." 21 | } 22 | -------------------------------------------------------------------------------- /resources/i18n/en-US/hints.json: -------------------------------------------------------------------------------- 1 | { 2 | "ok": "OK", 3 | "back": "Back", 4 | "cancel": "Cancel", 5 | "exit": "Exit", 6 | "on": "On", 7 | "off": "Off", 8 | "delete": "Delete", 9 | "save": "Save", 10 | "submit": "Submit", 11 | "input": "Please input...", 12 | "preset": "Preset", 13 | "default": "Default", 14 | "current": "Current", 15 | "success": "Success", 16 | "password": "Show/Hide", 17 | "retry": "Retry", 18 | "exit_hint": "Are you going to exit the application?", 19 | "loading": "Loading", 20 | "refresh": "Refresh", 21 | "quit": "Exiting app..." 22 | } -------------------------------------------------------------------------------- /resources/i18n/ja/hints.json: -------------------------------------------------------------------------------- 1 | { 2 | "ok": "OK", 3 | "back": "戻る", 4 | "cancel": "キャンセル", 5 | "exit": "閉じる", 6 | "on": "オン", 7 | "off": "オフ", 8 | "delete": "削除", 9 | "save": "セーブ", 10 | "submit": "投稿", 11 | "input": "入力してください...", 12 | "preset": "プリセット", 13 | "default": "初期設定", 14 | "current": "現在", 15 | "success": "成功", 16 | "password": "表示/非表示", 17 | "failed": "失敗しました", 18 | "exit_hint": "アプリケーションを終了しますか?", 19 | "loading": "読み込み中", 20 | "refresh": "更新", 21 | "quit": "アプリを終了中..." 22 | } -------------------------------------------------------------------------------- /resources/i18n/ko/hints.json: -------------------------------------------------------------------------------- 1 | { 2 | "ok": "확인", 3 | "back": "뒤로 가기", 4 | "cancel": "취소", 5 | "exit": "종료", 6 | "on": "켬", 7 | "off": "끔", 8 | "delete": "삭제", 9 | "save": "저장", 10 | "submit": "제출", 11 | "input": "입력하세요...", 12 | "preset": "사전 설정", 13 | "default": "기본", 14 | "current": "현재", 15 | "success": "성공", 16 | "password": "보이기/숨기기", 17 | "retry": "재시도", 18 | "exit_hint": "응용 프로그램을 종료하겠습니까?", 19 | "loading": "불러오기 중", 20 | "refresh": "새로고침", 21 | "quit": "앱 종료 중..." 22 | } -------------------------------------------------------------------------------- /resources/i18n/pt-BR/hints.json: -------------------------------------------------------------------------------- 1 | { 2 | "ok": "OK", 3 | "back": "Voltar", 4 | "cancel": "Cancelar", 5 | "exit": "Sair", 6 | "on": "Ligado", 7 | "off": "Desligado", 8 | "delete": "Excluir", 9 | "save": "Salvar", 10 | "submit": "Enviar", 11 | "input": "Por favor, insira...", 12 | "preset": "Predefinição", 13 | "default": "Padrão", 14 | "current": "Atual", 15 | "success": "Sucesso", 16 | "password": "Mostrar/Ocultar", 17 | "retry": "Tentar novamente", 18 | "exit_hint": "Você deseja sair do aplicativo?", 19 | "loading": "Carregando", 20 | "refresh": "Atualizar", 21 | "quit": "Saindo do aplicativo..." 22 | } 23 | -------------------------------------------------------------------------------- /resources/i18n/uk-UA/hints.json: -------------------------------------------------------------------------------- 1 | { 2 | "ok": "ОК", 3 | "back": "Назад", 4 | "cancel": "Відмінити", 5 | "exit": "Вихід", 6 | "on": "Вкл", 7 | "off": "Вимк", 8 | "delete": "Видалити", 9 | "save": "Зберегти", 10 | "submit": "Надіслати", 11 | "input": "Будь ласка введіть...", 12 | "preset": "Попереднє налаштування", 13 | "default": "За замовчуванням", 14 | "current": "Поточний", 15 | "success": "Успіх", 16 | "password": "Показати/Приховати", 17 | "failed": "Не вдалося", 18 | "exit_hint": "Ви збираєтеся вийти з програми?", 19 | "loading": "Завантаження", 20 | "refresh": "Оновити", 21 | "quit": "Завершення роботи програми..." 22 | } -------------------------------------------------------------------------------- /resources/i18n/vi_VN/hints.json: -------------------------------------------------------------------------------- 1 | { 2 | "ok": "OK", 3 | "back": "Trờ về", 4 | "cancel": "Huỷ", 5 | "exit": "Thoát", 6 | "on": "Bật", 7 | "off": "Tắt", 8 | "delete": "Xoá", 9 | "save": "Lưu", 10 | "submit": "Gửi", 11 | "input": "Vui lòng nhập...", 12 | "preset": "Cài đặt sẵn", 13 | "default": "Mặc định", 14 | "current": "Hiện tại", 15 | "success": "Thành công", 16 | "password": "Hiện/Ẩn", 17 | "failed": "Thất bại", 18 | "exit_hint": "Bạn có muốn thoát khỏi chương trình?", 19 | "loading": "Đang tải", 20 | "refresh": "Làm mới", 21 | "quit": "Đang thoát ứng dụng..." 22 | } -------------------------------------------------------------------------------- /resources/i18n/zh-Hans/hints.json: -------------------------------------------------------------------------------- 1 | { 2 | "ok": "确定", 3 | "back": "返回", 4 | "cancel": "取消", 5 | "exit": "退出", 6 | "on": "开", 7 | "off": "关", 8 | "delete": "删除", 9 | "save": "保存", 10 | "submit": "提交", 11 | "input": "请输入...", 12 | "preset": "预设", 13 | "default": "默认", 14 | "current": "当前", 15 | "success": "成功", 16 | "password": "显示/隐藏", 17 | "retry": "重试", 18 | "exit_hint": "退出应用?", 19 | "loading": "加载中", 20 | "refresh": "刷新", 21 | "quit": "正在退出应用..." 22 | } -------------------------------------------------------------------------------- /resources/i18n/zh-Hant/hints.json: -------------------------------------------------------------------------------- 1 | { 2 | "ok": "確定", 3 | "back": "返回", 4 | "cancel": "取消", 5 | "exit": "退出", 6 | "on": "開", 7 | "off": "關", 8 | "delete": "刪除", 9 | "save": "保存", 10 | "submit": "送出", 11 | "input": "請輸入...", 12 | "preset": "預設參數", 13 | "default": "預設", 14 | "current": "目前", 15 | "success": "成功", 16 | "password": "顯示/隱藏", 17 | "retry": "重試", 18 | "exit_hint": "離開本程式?", 19 | "loading": "載入中", 20 | "refresh": "重新整理", 21 | "quit": "正在退出..." 22 | } -------------------------------------------------------------------------------- /resources/icon/ico-backward.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /resources/icon/ico-cast.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /resources/icon/ico-checkmark.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /resources/icon/ico-circle.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /resources/icon/ico-cloud-activate.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /resources/icon/ico-cloud.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /resources/icon/ico-danmu-switch-off.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /resources/icon/ico-danmu-switch-on.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /resources/icon/ico-file-audio.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /resources/icon/ico-file-image.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /resources/icon/ico-file-text.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /resources/icon/ico-file-video.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /resources/icon/ico-file.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /resources/icon/ico-folder-up.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /resources/icon/ico-folder.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /resources/icon/ico-forward.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /resources/icon/ico-heart.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /resources/icon/ico-home-activate.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /resources/icon/ico-home.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /resources/icon/ico-list.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /resources/icon/ico-media-activate.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /resources/icon/ico-media.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /resources/icon/ico-pause.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /resources/icon/ico-play.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /resources/icon/ico-player-setting.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /resources/icon/ico-playlist.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /resources/icon/ico-repeat-list.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /resources/icon/ico-repeat-song.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /resources/icon/ico-search-activate.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /resources/icon/ico-search.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /resources/icon/ico-seeking.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /resources/icon/ico-server-activate.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /resources/icon/ico-server.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /resources/icon/ico-setting-activate.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /resources/icon/ico-setting.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /resources/icon/ico-shuffle.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /resources/icon/ico-star.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /resources/icon/ico-sun-fill.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /resources/icon/ico-volume-off.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /resources/icon/ico-volume.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /resources/icon/icon.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dragonflylee/switchfin/be742882e06e48943632d0255ac597c8955446df/resources/icon/icon.jpg -------------------------------------------------------------------------------- /resources/icon/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dragonflylee/switchfin/be742882e06e48943632d0255ac597c8955446df/resources/icon/icon.png -------------------------------------------------------------------------------- /resources/icon/player-lock.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /resources/icon/player-unlock.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /resources/icon/widget-people-grey.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /resources/icon/widget-people.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /resources/img/empty.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dragonflylee/switchfin/be742882e06e48943632d0255ac597c8955446df/resources/img/empty.png -------------------------------------------------------------------------------- /resources/img/header-search-dark.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /resources/img/header-search.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /resources/img/hint_app.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dragonflylee/switchfin/be742882e06e48943632d0255ac597c8955446df/resources/img/hint_app.png -------------------------------------------------------------------------------- /resources/img/hint_game_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dragonflylee/switchfin/be742882e06e48943632d0255ac597c8955446df/resources/img/hint_game_1.png -------------------------------------------------------------------------------- /resources/img/hint_game_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dragonflylee/switchfin/be742882e06e48943632d0255ac597c8955446df/resources/img/hint_game_2.png -------------------------------------------------------------------------------- /resources/img/hint_hbmenu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dragonflylee/switchfin/be742882e06e48943632d0255ac597c8955446df/resources/img/hint_hbmenu.png -------------------------------------------------------------------------------- /resources/img/net_error.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dragonflylee/switchfin/be742882e06e48943632d0255ac597c8955446df/resources/img/net_error.png -------------------------------------------------------------------------------- /resources/img/sys/battery_back_dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dragonflylee/switchfin/be742882e06e48943632d0255ac597c8955446df/resources/img/sys/battery_back_dark.png -------------------------------------------------------------------------------- /resources/img/sys/battery_back_light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dragonflylee/switchfin/be742882e06e48943632d0255ac597c8955446df/resources/img/sys/battery_back_light.png -------------------------------------------------------------------------------- /resources/img/sys/cursor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dragonflylee/switchfin/be742882e06e48943632d0255ac597c8955446df/resources/img/sys/cursor.png -------------------------------------------------------------------------------- /resources/img/sys/ethernet_dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dragonflylee/switchfin/be742882e06e48943632d0255ac597c8955446df/resources/img/sys/ethernet_dark.png -------------------------------------------------------------------------------- /resources/img/sys/ethernet_light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dragonflylee/switchfin/be742882e06e48943632d0255ac597c8955446df/resources/img/sys/ethernet_light.png -------------------------------------------------------------------------------- /resources/img/sys/wifi_0_dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dragonflylee/switchfin/be742882e06e48943632d0255ac597c8955446df/resources/img/sys/wifi_0_dark.png -------------------------------------------------------------------------------- /resources/img/sys/wifi_0_light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dragonflylee/switchfin/be742882e06e48943632d0255ac597c8955446df/resources/img/sys/wifi_0_light.png -------------------------------------------------------------------------------- /resources/img/sys/wifi_1_dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dragonflylee/switchfin/be742882e06e48943632d0255ac597c8955446df/resources/img/sys/wifi_1_dark.png -------------------------------------------------------------------------------- /resources/img/sys/wifi_1_light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dragonflylee/switchfin/be742882e06e48943632d0255ac597c8955446df/resources/img/sys/wifi_1_light.png -------------------------------------------------------------------------------- /resources/img/sys/wifi_2_dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dragonflylee/switchfin/be742882e06e48943632d0255ac597c8955446df/resources/img/sys/wifi_2_dark.png -------------------------------------------------------------------------------- /resources/img/sys/wifi_2_light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dragonflylee/switchfin/be742882e06e48943632d0255ac597c8955446df/resources/img/sys/wifi_2_light.png -------------------------------------------------------------------------------- /resources/img/sys/wifi_3_dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dragonflylee/switchfin/be742882e06e48943632d0255ac597c8955446df/resources/img/sys/wifi_3_dark.png -------------------------------------------------------------------------------- /resources/img/sys/wifi_3_light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dragonflylee/switchfin/be742882e06e48943632d0255ac597c8955446df/resources/img/sys/wifi_3_light.png -------------------------------------------------------------------------------- /resources/img/video-card-bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dragonflylee/switchfin/be742882e06e48943632d0255ac597c8955446df/resources/img/video-card-bg.png -------------------------------------------------------------------------------- /resources/material/MaterialIcons-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dragonflylee/switchfin/be742882e06e48943632d0255ac597c8955446df/resources/material/MaterialIcons-Regular.ttf -------------------------------------------------------------------------------- /resources/xml/activity/gallery.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 15 | 20 | 21 | -------------------------------------------------------------------------------- /resources/xml/activity/hint.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 17 | 24 | 25 | -------------------------------------------------------------------------------- /resources/xml/activity/main.xml: -------------------------------------------------------------------------------- 1 | 6 | 10 | 17 | 18 | 22 | 23 | 24 | 25 | 29 | 30 | 31 | 32 | 36 | 37 | 38 | 39 | 44 | 45 | 46 | 47 | 51 | 52 | 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /resources/xml/tabs/collection.xml: -------------------------------------------------------------------------------- 1 | 7 | 8 | 15 | 16 | 18 | 24 | 25 | 26 | 27 | 31 | 32 | -------------------------------------------------------------------------------- /resources/xml/tabs/home.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 9 | 10 | 16 | 17 | 24 | 25 | 32 | 33 | 39 | 40 | 46 | 47 | 53 | 54 | 55 | 56 | 57 | 58 | -------------------------------------------------------------------------------- /resources/xml/tabs/media.xml: -------------------------------------------------------------------------------- 1 | 8 | 9 | 15 | 16 | 20 | 21 | -------------------------------------------------------------------------------- /resources/xml/tabs/media_folder.xml: -------------------------------------------------------------------------------- 1 | 8 | 9 | 15 | 16 | -------------------------------------------------------------------------------- /resources/xml/tabs/music_album.xml: -------------------------------------------------------------------------------- 1 | 8 | 9 | 14 | 15 | 22 | 23 | 31 | 32 | 37 | 40 | 44 | 45 | 46 | 47 | 48 | 50 | 51 | 52 | 62 | 63 | -------------------------------------------------------------------------------- /resources/xml/tabs/remote.xml: -------------------------------------------------------------------------------- 1 | 6 | 7 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /resources/xml/tabs/search_result.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 9 | 10 | 17 | 18 | 24 | 25 | 31 | 32 | 38 | 39 | 45 | 46 | 47 | 48 | 49 | 53 | 54 | -------------------------------------------------------------------------------- /resources/xml/tabs/seasons.xml: -------------------------------------------------------------------------------- 1 | 8 | 9 | 17 | 18 | -------------------------------------------------------------------------------- /resources/xml/tabs/server_add.xml: -------------------------------------------------------------------------------- 1 | 6 | 7 | 16 | 17 | 22 | 27 | 28 | 30 | 31 | 34 | 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /resources/xml/tabs/server_login.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 9 | 10 | 12 | 13 | 15 | 16 | 19 | 20 | 26 | 27 | 33 | 34 | 40 | 42 | 43 | 44 | 45 | 49 | -------------------------------------------------------------------------------- /resources/xml/tabs/suggest_show.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 9 | 10 | 12 | 13 | 20 | 21 | 27 | 28 | 35 | 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /resources/xml/view/button_close.xml: -------------------------------------------------------------------------------- 1 | 9 | 18 | -------------------------------------------------------------------------------- /resources/xml/view/dir_entry.xml: -------------------------------------------------------------------------------- 1 | 6 | 7 | 13 | 14 | 16 | 17 | 18 | 19 | 24 | 25 | -------------------------------------------------------------------------------- /resources/xml/view/episode_card.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 9 | 10 | 16 | 17 | 23 | 24 | 32 | 37 | 38 | 39 | 40 | 41 | 44 | 49 | 50 | 56 | 57 | 58 | -------------------------------------------------------------------------------- /resources/xml/view/music_track.xml: -------------------------------------------------------------------------------- 1 | 5 | 6 | 11 | 12 | 14 | 17 | 18 | 22 | 23 | 24 | 29 | 30 | 36 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /resources/xml/view/quick_connect.xml: -------------------------------------------------------------------------------- 1 | 7 | 8 | 11 | 12 | 14 | 15 | 18 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /resources/xml/view/recycler_list.xml: -------------------------------------------------------------------------------- 1 | 5 | 6 | 10 | 11 | 16 | -------------------------------------------------------------------------------- /resources/xml/view/search_card.xml: -------------------------------------------------------------------------------- 1 | 7 | 8 | 16 | 17 | 23 | -------------------------------------------------------------------------------- /resources/xml/view/server_item.xml: -------------------------------------------------------------------------------- 1 | 6 | 7 | 17 | 18 | 22 | 23 | 26 | 27 | 30 | 31 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /resources/xml/view/setting_about.xml: -------------------------------------------------------------------------------- 1 | 7 | 8 | 12 | 17 | 23 | 24 | 25 | 28 | 31 | 32 | 35 | 39 | 42 | 43 | 44 | 48 | 49 | 53 | 54 | -------------------------------------------------------------------------------- /resources/xml/view/tutorial_error.xml: -------------------------------------------------------------------------------- 1 | 4 | 7 | 11 | 14 | 18 | -------------------------------------------------------------------------------- /resources/xml/view/tutorial_font.xml: -------------------------------------------------------------------------------- 1 | 7 | 8 | 11 | 14 | 15 | 18 | 21 | 22 | 25 | 27 | 28 | -------------------------------------------------------------------------------- /resources/xml/view/user_item.xml: -------------------------------------------------------------------------------- 1 | 6 | 11 | 18 | 19 | 20 | 24 | 28 | 29 | -------------------------------------------------------------------------------- /scripts/README.md: -------------------------------------------------------------------------------- 1 | # Build Depency 2 | 3 | ### build for macOS 4 | 5 | ```shell 6 | # https://pkg-config.freedesktop.org/releases/pkg-config-0.29.2.tar.gz 7 | LDFLAGS="-framework CoreFoundation -framework Carbon" ./configure --with-internal-glib 8 | 9 | # https://github.com/ninja-build/ninja/releases/download/v1.12.0/ninja-mac.zip 10 | # https://www.nasm.us/pub/nasm/releasebuilds/2.16.01/macosx/nasm-2.16.01-macosx.zip 11 | ``` 12 | 13 | ### generate icons 14 | 15 | ```shell 16 | sudo apt-get install -y librsvg2-bin 17 | for size in 32 48 64 128 256; do 18 | icon_path="icons/${size}x${size}" 19 | mkdir -p ${icon_path} 20 | rsvg-convert -w ${size} -h ${size} -o ${icon_path}/org.player.switchfin.png org.player.switchfin.svg 21 | done 22 | ``` -------------------------------------------------------------------------------- /scripts/aur/PKGBUILD: -------------------------------------------------------------------------------- 1 | pkgname=switchfin 2 | pkgver=0.7.1 3 | pkgrel=1 4 | pkgdesc='Third-party native Jellyfin client' 5 | arch=('x86_64' 'aarch64') 6 | url='https://github.com/dragonflylee/switchfin' 7 | license=('GPL-3.0-or-later') 8 | depends=('curl' 'dbus' 'gcc-libs' 'glibc' 'hicolor-icon-theme' 'libwebp' 'mpv' 'libxcb' 'tinyxml2' 'libpng') 9 | makedepends=('cmake' 'git' 'libxi' 'libxinerama' 'ninja' 'python' 'wayland-protocols') 10 | options=(strip !debug) 11 | #source=("${pkgname}::git+$url.git") 12 | #sha256sums=('SKIP') 13 | 14 | build() { 15 | cmake -B "${srcdir}/build" -G Ninja \ 16 | -D CMAKE_BUILD_TYPE=Release \ 17 | -D CMAKE_INSTALL_PREFIX='/usr' \ 18 | -D CMAKE_INSTALL=ON \ 19 | -D PLATFORM_DESKTOP=ON \ 20 | -D USE_SYSTEM_CURL=ON \ 21 | -D USE_SYSTEM_TINYXML2=ON \ 22 | -D GLFW_BUILD_WAYLAND=ON \ 23 | -D GLFW_BUILD_X11=ON \ 24 | -S "../../.." 25 | cmake --build "${srcdir}/build" 26 | } 27 | 28 | package() { 29 | DESTDIR="${pkgdir}" cmake --install "${srcdir}/build" 30 | } 31 | -------------------------------------------------------------------------------- /scripts/aur/entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -euo pipefail 3 | 4 | FILE="$(basename "$0")" 5 | 6 | # Enable the multilib repository 7 | cat << EOM >> /etc/pacman.conf 8 | [multilib] 9 | Include = /etc/pacman.d/mirrorlist 10 | EOM 11 | 12 | pacman -Syu --noconfirm --needed base-devel 13 | 14 | # Makepkg does not allow running as root 15 | # Create a new user `builder` 16 | # `builder` needs to have a home directory because some PKGBUILDs will try to 17 | # write to it (e.g. for cache) 18 | useradd builder -m -u $PUID 19 | # When installing dependencies, makepkg will use sudo 20 | # Give user `builder` passwordless sudo access 21 | echo "builder ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers 22 | 23 | sudo -H -u builder makepkg -scCf --noconfirm -------------------------------------------------------------------------------- /scripts/forwarder/README.md: -------------------------------------------------------------------------------- 1 | # 构建 NSP forwarder (桌面图标) 2 | 3 | bash 4 | ```shell 5 | make -C scripts/forwarder Switchfin.nacp 6 | 7 | hacbrewpack -k prod.keys --titleid 010FF000FFFF0003 --titlename Switchfin --noromfs --nologo 8 | ``` 9 | 10 | # Thanks to 11 | 12 | https://github.com/The-4n/hacBrewPack 13 | https://github.com/switchbrew/nx-hbloader 14 | -------------------------------------------------------------------------------- /scripts/forwarder/icon/logo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dragonflylee/switchfin/be742882e06e48943632d0255ac597c8955446df/scripts/forwarder/icon/logo.gif -------------------------------------------------------------------------------- /scripts/forwarder/icon/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dragonflylee/switchfin/be742882e06e48943632d0255ac597c8955446df/scripts/forwarder/icon/logo.png -------------------------------------------------------------------------------- /scripts/forwarder/source/trampoline.s: -------------------------------------------------------------------------------- 1 | .section .text.nroEntrypointTrampoline, "ax", %progbits 2 | .align 2 3 | .global nroEntrypointTrampoline 4 | .type nroEntrypointTrampoline, %function 5 | .cfi_startproc 6 | nroEntrypointTrampoline: 7 | 8 | // Reset stack pointer. 9 | adrp x8, __stack_top //Defined in libnx. 10 | ldr x8, [x8, #:lo12:__stack_top] 11 | mov sp, x8 12 | 13 | // Call NRO. 14 | blr x2 15 | 16 | // Save retval 17 | adrp x1, g_lastRet 18 | str w0, [x1, #:lo12:g_lastRet] 19 | 20 | // Reset stack pointer and load next NRO. 21 | adrp x8, __stack_top 22 | ldr x8, [x8, #:lo12:__stack_top] 23 | mov sp, x8 24 | 25 | b loadNro 26 | 27 | .cfi_endproc 28 | 29 | .section .text.__libnx_exception_entry, "ax", %progbits 30 | .align 2 31 | .global __libnx_exception_entry 32 | .type __libnx_exception_entry, %function 33 | .cfi_startproc 34 | __libnx_exception_entry: 35 | 36 | // Divert execution to the NRO entrypoint (if a NRO is actually loaded). 37 | adrp x7, g_nroAddr 38 | ldr x7, [x7, #:lo12:g_nroAddr] 39 | cbz x7, .Lfail 40 | br x7 41 | 42 | .Lfail: 43 | // Otherwise, pass this unhandled exception right back to the kernel. 44 | mov w0, #0xf801 // KERNELRESULT(UnhandledUserInterrupt) 45 | svc 0x28 // svcReturnFromException 46 | 47 | .cfi_endproc 48 | -------------------------------------------------------------------------------- /scripts/icons/128x128/org.player.switchfin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dragonflylee/switchfin/be742882e06e48943632d0255ac597c8955446df/scripts/icons/128x128/org.player.switchfin.png -------------------------------------------------------------------------------- /scripts/icons/256x256/org.player.switchfin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dragonflylee/switchfin/be742882e06e48943632d0255ac597c8955446df/scripts/icons/256x256/org.player.switchfin.png -------------------------------------------------------------------------------- /scripts/icons/32x32/org.player.switchfin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dragonflylee/switchfin/be742882e06e48943632d0255ac597c8955446df/scripts/icons/32x32/org.player.switchfin.png -------------------------------------------------------------------------------- /scripts/icons/48x48/org.player.switchfin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dragonflylee/switchfin/be742882e06e48943632d0255ac597c8955446df/scripts/icons/48x48/org.player.switchfin.png -------------------------------------------------------------------------------- /scripts/icons/64x64/org.player.switchfin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dragonflylee/switchfin/be742882e06e48943632d0255ac597c8955446df/scripts/icons/64x64/org.player.switchfin.png -------------------------------------------------------------------------------- /scripts/macos/arm64.meson: -------------------------------------------------------------------------------- 1 | [host_machine] 2 | system = 'darwin' 3 | cpu_family = 'aarch64' 4 | cpu = 'arm64' 5 | endian = 'little' 6 | 7 | [binaries] 8 | c = ['clang'] 9 | cpp = ['clang++'] 10 | objc = ['clang'] 11 | objcpp = ['clang++'] 12 | ar = ['ar'] 13 | strip = ['strip'] 14 | pkg-config = ['pkg-config'] 15 | 16 | [built-in options] 17 | buildtype = 'release' 18 | default_library = 'shared' 19 | wrap_mode = 'nodownload' 20 | c_args = ['-arch', 'arm64', '-mmacosx-version-min=11.0'] 21 | cpp_args = ['-arch', 'arm64', '-mmacosx-version-min=11.0'] 22 | objc_args = ['-arch', 'arm64', '-mmacosx-version-min=11.0'] 23 | objcpp_args = ['-arch', 'arm64', '-mmacosx-version-min=11.0'] 24 | c_link_args = ['-arch', 'arm64', '-mmacosx-version-min=11.0'] 25 | cpp_link_args = ['-arch', 'arm64', '-mmacosx-version-min=11.0'] 26 | objc_link_args = ['-arch', 'arm64', '-mmacosx-version-min=11.0'] 27 | objcpp_link_args = ['-arch', 'arm64', '-mmacosx-version-min=11.0'] -------------------------------------------------------------------------------- /scripts/macos/dmg.icns: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dragonflylee/switchfin/be742882e06e48943632d0255ac597c8955446df/scripts/macos/dmg.icns -------------------------------------------------------------------------------- /scripts/macos/x86_64.meson: -------------------------------------------------------------------------------- 1 | [host_machine] 2 | system = 'darwin' 3 | cpu_family = 'x86_64' 4 | cpu = 'x86_64' 5 | endian = 'little' 6 | 7 | [binaries] 8 | c = ['clang'] 9 | cpp = ['clang++'] 10 | objc = ['clang'] 11 | objcpp = ['clang++'] 12 | ar = ['ar'] 13 | strip = ['strip'] 14 | pkg-config = ['pkg-config'] 15 | 16 | [built-in options] 17 | buildtype = 'release' 18 | default_library = 'shared' 19 | wrap_mode = 'nodownload' 20 | c_args = ['-arch', 'x86_64', '-mmacosx-version-min=10.15'] 21 | cpp_args = ['-arch', 'x86_64', '-mmacosx-version-min=10.15'] 22 | objc_args = ['-arch', 'x86_64', '-mmacosx-version-min=10.15'] 23 | objcpp_args = ['-arch', 'x86_64', '-mmacosx-version-min=10.15'] 24 | c_link_args = ['-arch', 'x86_64', '-mmacosx-version-min=10.15'] 25 | cpp_link_args = ['-arch', 'x86_64', '-mmacosx-version-min=10.15'] 26 | objc_link_args = ['-arch', 'x86_64', '-mmacosx-version-min=10.15'] 27 | objcpp_link_args = ['-arch', 'x86_64', '-mmacosx-version-min=10.15'] -------------------------------------------------------------------------------- /scripts/mingw64/curl/static-libs.patch: -------------------------------------------------------------------------------- 1 | diff --git a/CMakeLists.txt b/CMakeLists.txt 2 | index c4ba74d9fb..03cc9ea0e3 100644 3 | --- a/CMakeLists.txt 4 | +++ b/CMakeLists.txt 5 | @@ -246,11 +246,7 @@ else() 6 | endif() 7 | 8 | # Lib flavour selected for example and test programs. 9 | -if(BUILD_SHARED_LIBS) 10 | - set(LIB_SELECTED ${LIB_SHARED}) 11 | -else() 12 | - set(LIB_SELECTED ${LIB_STATIC}) 13 | -endif() 14 | +set(LIB_SELECTED ${LIB_STATIC}) 15 | 16 | # Override to force-disable or force-enable the use of pkg-config. 17 | if(UNIX OR VCPKG_TOOLCHAIN OR (MINGW AND NOT CMAKE_CROSSCOMPILING)) # Keep in sync with CMake/curl-config.cmake.in 18 | -------------------------------------------------------------------------------- /scripts/mingw64/dav1d/PKGBUILD: -------------------------------------------------------------------------------- 1 | # Maintainer: Christopher Degawa 2 | 3 | _realname=dav1d 4 | pkgbase=mingw-w64-${_realname} 5 | pkgname=("${MINGW_PACKAGE_PREFIX}-${_realname}") 6 | pkgver=1.5.1 7 | pkgrel=1 8 | pkgdesc="AV1 cross-platform decoder focused on speed and correctness (mingw-w64)" 9 | arch=('any') 10 | mingw_arch=('mingw32' 'mingw64' 'clangarm64') 11 | url='https://code.videolan.org/videolan/dav1d' 12 | license=('spdx:BSD-2-Clause') 13 | makedepends=( 14 | "${MINGW_PACKAGE_PREFIX}-pkgconf" 15 | "${MINGW_PACKAGE_PREFIX}-cc" 16 | "${MINGW_PACKAGE_PREFIX}-meson" 17 | "${MINGW_PACKAGE_PREFIX}-ninja" 18 | "${MINGW_PACKAGE_PREFIX}-xxhash" 19 | $([[ ${MINGW_PACKAGE_PREFIX} == *-clang-aarch64* ]] || echo "${MINGW_PACKAGE_PREFIX}-nasm") 20 | ) 21 | source=("https://downloads.videolan.org/pub/videolan/dav1d/${pkgver}/dav1d-${pkgver}.tar.xz") 22 | sha256sums=('401813f1f89fa8fd4295805aa5284d9aed9bc7fc1fdbe554af4292f64cbabe21') 23 | 24 | build() { 25 | MSYS2_ARG_CONV_EXCL="--prefix=" \ 26 | ${MINGW_PREFIX}/bin/meson setup \ 27 | --prefix=${MINGW_PREFIX} \ 28 | --default-library=static \ 29 | --buildtype=release \ 30 | -Denable_tests=false \ 31 | -Denable_docs=false \ 32 | -Denable_tools=false \ 33 | -Denable_examples=false \ 34 | "build-${MSYSTEM}" \ 35 | "${srcdir}/${_realname}-${pkgver}" 36 | 37 | ${MINGW_PREFIX}/bin/meson compile -C "build-${MSYSTEM}" 38 | } 39 | 40 | package() { 41 | ${MINGW_PREFIX}/bin/meson install -C "build-${MSYSTEM}" --destdir "${pkgdir}" 42 | } 43 | -------------------------------------------------------------------------------- /scripts/mingw64/freetype/PKGBUILD: -------------------------------------------------------------------------------- 1 | # Maintainer: Alexey Pavlov 2 | # Contributor: Renato Silva 3 | 4 | _realname=freetype 5 | pkgbase=mingw-w64-${_realname} 6 | pkgname="${MINGW_PACKAGE_PREFIX}-${_realname}" 7 | pkgver=2.13.3 8 | pkgrel=1 9 | pkgdesc="TrueType font rendering library (mingw-w64)" 10 | arch=('any') 11 | mingw_arch=('mingw32' 'mingw64' 'clangarm64') 12 | msys2_references=( 13 | 'archlinux: freetype2' 14 | ) 15 | url="https://www.freetype.org/" 16 | license=('spdx:GPL-2.0-or-later OR FTL') 17 | depends=( 18 | "${MINGW_PACKAGE_PREFIX}-bzip2" 19 | "${MINGW_PACKAGE_PREFIX}-libpng" 20 | "${MINGW_PACKAGE_PREFIX}-zlib" 21 | ) 22 | makedepends=( 23 | "${MINGW_PACKAGE_PREFIX}-meson" 24 | "${MINGW_PACKAGE_PREFIX}-ninja" 25 | "${MINGW_PACKAGE_PREFIX}-cc" 26 | ) 27 | options=('staticlibs' '!strip') 28 | source=("https://downloads.sourceforge.net/project/freetype/freetype2/${pkgver}/freetype-${pkgver}.tar.xz") 29 | sha256sums=('0550350666d427c74daeb85d5ac7bb353acba5f76956395995311a9c6f063289') 30 | 31 | build() { 32 | MSYS2_ARG_CONV_EXCL="--prefix=" \ 33 | meson setup \ 34 | --prefix="${MINGW_PREFIX}" \ 35 | --buildtype=release \ 36 | --default-library=static \ 37 | -Dharfbuzz=disabled \ 38 | -Dtests=disabled \ 39 | -Dbrotli=disabled \ 40 | "build-${MSYSTEM}" \ 41 | "${srcdir}/${_realname}-${pkgver}" 42 | 43 | meson compile -C "build-${MSYSTEM}" 44 | } 45 | 46 | package () { 47 | meson install -C "build-${MSYSTEM}" --destdir "${pkgdir}" 48 | } -------------------------------------------------------------------------------- /scripts/mingw64/glfw/PKGBUILD: -------------------------------------------------------------------------------- 1 | # Maintainer: Martell Malone 2 | 3 | _realname=glfw 4 | pkgbase=mingw-w64-${_realname} 5 | pkgname=("${MINGW_PACKAGE_PREFIX}-${_realname}") 6 | pkgver=3.5.0 7 | pkgrel=1 8 | pkgref=switchfin 9 | pkgdesc="A free, open source, portable framework for OpenGL application development (mingw-w64)" 10 | arch=('any') 11 | mingw_arch=('mingw32' 'mingw64' 'clangarm64') 12 | url='https://www.glfw.org/' 13 | license=('spdx:Zlib') 14 | makedepends=( 15 | "${MINGW_PACKAGE_PREFIX}-cc" 16 | "${MINGW_PACKAGE_PREFIX}-cmake" 17 | "${MINGW_PACKAGE_PREFIX}-ninja" 18 | ) 19 | source=("${_realname}-${pkgref}.tar.gz"::"https://github.com/dragonflylee/glfw/archive/${pkgref}.tar.gz") 20 | sha256sums=('SKIP') 21 | 22 | prepare() { 23 | cd "${srcdir}/${_realname}-${pkgref}" 24 | ${MINGW_PREFIX}/bin/cmake.exe -P CMake/GenerateMappings.cmake \ 25 | src/mappings.h.in src/mappings.h 26 | } 27 | 28 | build() { 29 | MSYS2_ARG_CONV_EXCL="-DCMAKE_INSTALL_PREFIX=" \ 30 | ${MINGW_PREFIX}/bin/cmake.exe -B "build-${MSYSTEM}" -G Ninja \ 31 | -DCMAKE_INSTALL_PREFIX="${MINGW_PREFIX}" \ 32 | -DCMAKE_BUILD_TYPE=Release \ 33 | -DBUILD_SHARED_LIBS=OFF \ 34 | -DGLFW_BUILD_EXAMPLES=OFF \ 35 | -DGLFW_BUILD_TESTS=OFF \ 36 | -DGLFW_BUILD_DOCS=OFF \ 37 | "${srcdir}/${_realname}-${pkgref}" 38 | ${MINGW_PREFIX}/bin/cmake.exe --build "build-${MSYSTEM}" 39 | } 40 | 41 | package() { 42 | DESTDIR="${pkgdir}" ${MINGW_PREFIX}/bin/cmake.exe --install "build-${MSYSTEM}" 43 | } 44 | -------------------------------------------------------------------------------- /scripts/mingw64/glslang/PKGBUILD: -------------------------------------------------------------------------------- 1 | # Maintainer: J. Peter Mugaas 2 | # Contributor: wirx6 3 | 4 | _realname=glslang 5 | pkgbase=mingw-w64-${_realname} 6 | pkgname=("${MINGW_PACKAGE_PREFIX}-${_realname}") 7 | pkgver=15.3.0 8 | pkgrel=1 9 | pkgdesc='An OpenGL and OpenGL ES shader front end and validator (mingw-w64)' 10 | arch=('any') 11 | mingw_arch=('mingw32' 'mingw64' 'clangarm64') 12 | url='https://github.com/KhronosGroup/glslang' 13 | msys2_references=( 14 | 'archlinux: glslang' 15 | ) 16 | license=('spdx:BSD-3-Clause') 17 | depends=("${MINGW_PACKAGE_PREFIX}-gcc-libs" 18 | "${MINGW_PACKAGE_PREFIX}-spirv-tools") 19 | makedepends=("${MINGW_PACKAGE_PREFIX}-cc" 20 | "${MINGW_PACKAGE_PREFIX}-cmake" 21 | "${MINGW_PACKAGE_PREFIX}-ninja" 22 | "${MINGW_PACKAGE_PREFIX}-python") 23 | source=("https://github.com/KhronosGroup/glslang/archive/${pkgver}/${_realname}-${pkgver}.tar.gz") 24 | sha256sums=('c6c21fe1873c37e639a6a9ac72d857ab63a5be6893a589f34e09a6c757174201') 25 | 26 | build() { 27 | MSYS2_ARG_CONV_EXCL="-DCMAKE_INSTALL_PREFIX=" \ 28 | ${MINGW_PREFIX}/bin/cmake.exe \ 29 | -B "build-${MSYSTEM}" -G Ninja -G Ninja \ 30 | -DCMAKE_INSTALL_PREFIX=${MINGW_PREFIX} \ 31 | -DCMAKE_BUILD_TYPE=Release \ 32 | -DBUILD_SHARED_LIBS=OFF \ 33 | -DENABLE_GLSLANG_BINARIES=OFF \ 34 | -DGLSLANG_TESTS=OFF \ 35 | -DBUILD_EXTERNAL=OFF \ 36 | -DALLOW_EXTERNAL_SPIRV_TOOLS=ON \ 37 | "${srcdir}/${_realname}-${pkgver}" 38 | ${MINGW_PREFIX}/bin/cmake.exe --build "build-${MSYSTEM}" 39 | } 40 | 41 | package() { 42 | DESTDIR="${pkgdir}" cmake --install "build-${MSYSTEM}" 43 | } 44 | -------------------------------------------------------------------------------- /scripts/mingw64/harfbuzz/PKGBUILD: -------------------------------------------------------------------------------- 1 | # Maintainer: Alexey Pavlov 2 | # Contributor: Renato Silva 3 | 4 | _realname=harfbuzz 5 | pkgbase=mingw-w64-${_realname} 6 | pkgname=("${MINGW_PACKAGE_PREFIX}-${_realname}") 7 | pkgver=11.2.1 8 | pkgrel=1 9 | pkgdesc="OpenType text shaping engine (mingw-w64)" 10 | arch=('any') 11 | mingw_arch=('mingw32' 'mingw64' 'clangarm64') 12 | url="https://github.com/harfbuzz/harfbuzz" 13 | license=('spdx:MIT') 14 | makedepends=( 15 | "${MINGW_PACKAGE_PREFIX}-cc" 16 | "${MINGW_PACKAGE_PREFIX}-meson" 17 | "${MINGW_PACKAGE_PREFIX}-ninja" 18 | ) 19 | depends=( 20 | "${MINGW_PACKAGE_PREFIX}-freetype" 21 | "${MINGW_PACKAGE_PREFIX}-libpng" 22 | ) 23 | options=('staticlibs' '!strip') 24 | source=("https://github.com/harfbuzz/harfbuzz/releases/download/${pkgver}/harfbuzz-${pkgver}.tar.xz") 25 | sha256sums=('093714c8548a285094685f0bdc999e202d666b59eeb3df2ff921ab68b8336a49') 26 | noextract=("harfbuzz-${pkgver}.tar.xz") 27 | 28 | prepare() { 29 | echo "Extracting harfbuzz-${pkgver}.tar.xz..." 30 | tar -xJf harfbuzz-${pkgver}.tar.xz || true 31 | } 32 | 33 | build() { 34 | MSYS2_ARG_CONV_EXCL="--prefix=" \ 35 | ${MINGW_PREFIX}/bin/meson setup \ 36 | --prefix="${MINGW_PREFIX}" \ 37 | --buildtype=release \ 38 | --default-library=static \ 39 | -Dicu=disabled \ 40 | -Dglib=disabled \ 41 | -Dcairo=disabled \ 42 | -Dgobject=disabled \ 43 | -Dtests=disabled \ 44 | -Ddocs=disabled \ 45 | -Dbenchmark=disabled \ 46 | -Dutilities=disabled \ 47 | "build-${MSYSTEM}" \ 48 | "${srcdir}/${_realname}-${pkgver}" 49 | 50 | ${MINGW_PREFIX}/bin/meson compile -C "build-${MSYSTEM}" 51 | } 52 | 53 | package() { 54 | ${MINGW_PREFIX}/bin/meson install -C "build-${MSYSTEM}" --destdir "${pkgdir}" 55 | } 56 | -------------------------------------------------------------------------------- /scripts/mingw64/libass/PKGBUILD: -------------------------------------------------------------------------------- 1 | # Maintainer: Alexey Pavlov 2 | 3 | _realname=libass 4 | pkgbase=mingw-w64-${_realname} 5 | pkgname="${MINGW_PACKAGE_PREFIX}-${_realname}" 6 | pkgver=0.17.3 7 | pkgrel=1 8 | pkgdesc="A portable library for SSA/ASS subtitles rendering (mingw-w64)" 9 | arch=('any') 10 | mingw_arch=('mingw32' 'mingw64' 'clangarm64') 11 | url='https://github.com/libass/libass' 12 | license=('spdx:ISC') 13 | makedepends=( 14 | "${MINGW_PACKAGE_PREFIX}-cc" 15 | "${MINGW_PACKAGE_PREFIX}-meson" 16 | "${MINGW_PACKAGE_PREFIX}-ninja" 17 | ) 18 | depends=( 19 | "${MINGW_PACKAGE_PREFIX}-fribidi" 20 | "${MINGW_PACKAGE_PREFIX}-freetype" 21 | "${MINGW_PACKAGE_PREFIX}-libunibreak" 22 | "${MINGW_PACKAGE_PREFIX}-harfbuzz" 23 | ) 24 | options=('staticlibs' '!strip') 25 | source=(https://github.com/libass/${_realname}/releases/download/${pkgver}/${_realname}-${pkgver}.tar.xz) 26 | sha256sums=('eae425da50f0015c21f7b3a9c7262a910f0218af469e22e2931462fed3c50959') 27 | 28 | build() { 29 | MSYS2_ARG_CONV_EXCL="--prefix=" \ 30 | ${MINGW_PREFIX}/bin/meson setup \ 31 | --prefix="${MINGW_PREFIX}" \ 32 | --buildtype=release \ 33 | --default-library=static \ 34 | -Dasm=enabled \ 35 | "build-${MSYSTEM}" \ 36 | "${srcdir}/${_realname}-${pkgver}" 37 | 38 | ${MINGW_PREFIX}/bin/meson compile -C "build-${MSYSTEM}" 39 | } 40 | 41 | package() { 42 | ${MINGW_PREFIX}/bin/meson install -C "build-${MSYSTEM}" --destdir "${pkgdir}" 43 | } -------------------------------------------------------------------------------- /scripts/mingw64/libplacebo/PKGBUILD: -------------------------------------------------------------------------------- 1 | # Maintainer: Alexey Pavlov 2 | 3 | _realname=libplacebo 4 | pkgbase=mingw-w64-${_realname} 5 | pkgname=("${MINGW_PACKAGE_PREFIX}-libplacebo") 6 | pkgver=7.351.0 7 | pkgrel=1 8 | pkgdesc="Reusable library for GPU-accelerated video/image rendering primitives (mingw-w64)" 9 | arch=('any') 10 | mingw_arch=('mingw32' 'mingw64' 'clangarm64') 11 | url="https://code.videolan.org/videolan/libplacebo" 12 | depends=( 13 | "${MINGW_PACKAGE_PREFIX}-shaderc" 14 | "${MINGW_PACKAGE_PREFIX}-spirv-cross" 15 | ) 16 | makedepends=( 17 | "${MINGW_PACKAGE_PREFIX}-cc" 18 | "${MINGW_PACKAGE_PREFIX}-meson" 19 | "${MINGW_PACKAGE_PREFIX}-pkgconf" 20 | "${MINGW_PACKAGE_PREFIX}-python-jinja" 21 | "${MINGW_PACKAGE_PREFIX}-fast_float" 22 | "${MINGW_PACKAGE_PREFIX}-vulkan-headers" 23 | ) 24 | license=('LGPL2.1') 25 | source=("${_realname}-v${pkgver}.tar.gz::https://github.com/haasn/libplacebo/archive/v${pkgver}.tar.gz") 26 | sha256sums=('716954501d9b76e6906fddda66febc5886493d0673dd265ec1e6e52f4e5cd7c6') 27 | 28 | build() { 29 | MSYS2_ARG_CONV_EXCL="--prefix=" \ 30 | meson setup \ 31 | --prefix="${MINGW_PREFIX}" \ 32 | --buildtype=release \ 33 | --default-library=static \ 34 | -Ddemos=false \ 35 | -Dtests=false \ 36 | -Dopengl=disabled \ 37 | -Dgl-proc-addr=disabled \ 38 | -Dlcms=disabled \ 39 | -Ddovi=enabled \ 40 | -Dshaderc=enabled \ 41 | -Dvulkan=disabled \ 42 | "build-${MSYSTEM}" \ 43 | "${srcdir}/${_realname}-${pkgver}" 44 | 45 | meson compile -C "build-${MSYSTEM}" 46 | } 47 | 48 | package() { 49 | cd "${srcdir}/build-${MSYSTEM}" 50 | meson install --destdir "${pkgdir}" 51 | 52 | sed -s "s|$(cygpath -am ${MINGW_PREFIX})|${MINGW_PREFIX}|g" -i ${pkgdir}${MINGW_PREFIX}/lib/pkgconfig/libplacebo.pc 53 | } -------------------------------------------------------------------------------- /scripts/mingw64/libwebp/0001-mingw-cmake-output.patch: -------------------------------------------------------------------------------- 1 | --- libwebp-1.3.0/CMakeLists.txt.orig 2023-01-13 12:49:52.571844700 +0100 2 | +++ libwebp-1.3.0/CMakeLists.txt 2023-01-13 12:52:53.077790900 +0100 3 | @@ -713,7 +713,7 @@ 4 | ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} 5 | LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} 6 | RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) 7 | -set(ConfigPackageLocation ${CMAKE_INSTALL_DATADIR}/${PROJECT_NAME}/cmake/) 8 | +set(ConfigPackageLocation ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}/) 9 | install(EXPORT ${PROJECT_NAME}Targets NAMESPACE ${PROJECT_NAME}:: 10 | DESTINATION ${ConfigPackageLocation}) 11 | 12 | -------------------------------------------------------------------------------- /scripts/mingw64/libwebp/PKGBUILD: -------------------------------------------------------------------------------- 1 | # Maintainer: Alexey Pavlov 2 | # Contributor: Andrew Sun 3 | 4 | _realname=libwebp 5 | pkgbase=mingw-w64-${_realname} 6 | pkgname=("${MINGW_PACKAGE_PREFIX}-${_realname}") 7 | pkgver=1.5.0 8 | pkgrel=1 9 | pkgdesc="A library to encode and decode images in WebP format (mingw-w64)" 10 | arch=('any') 11 | mingw_arch=('mingw32' 'mingw64' 'clangarm64') 12 | url='https://developers.google.com/speed/webp/' 13 | license=('spdx:BSD-3-Clause') 14 | makedepends=( 15 | "${MINGW_PACKAGE_PREFIX}-cc" 16 | "${MINGW_PACKAGE_PREFIX}-cmake" 17 | "${MINGW_PACKAGE_PREFIX}-ninja" 18 | ) 19 | provides=("${MINGW_PACKAGE_PREFIX}-libsharpyuv") 20 | source=( 21 | ${_realname}-${pkgver}.tar.gz::https://github.com/webmproject/libwebp/archive/v${pkgver}.tar.gz 22 | 0001-mingw-cmake-output.patch 23 | ) 24 | sha256sums=('668c9aba45565e24c27e17f7aaf7060a399f7f31dba6c97a044e1feacb930f37' 'SKIP') 25 | 26 | prepare() { 27 | cd "${srcdir}/${_realname}-${pkgver}" 28 | 29 | patch -Np1 -i "${srcdir}"/0001-mingw-cmake-output.patch 30 | } 31 | 32 | build() { 33 | MSYS2_ARG_CONV_EXCL="-DCMAKE_INSTALL_PREFIX=" \ 34 | ${MINGW_PREFIX}/bin/cmake.exe -B "build-${MSYSTEM}" -G Ninja \ 35 | -DCMAKE_INSTALL_PREFIX="${MINGW_PREFIX}" \ 36 | -DCMAKE_BUILD_TYPE=Release \ 37 | -DBUILD_SHARED_LIBS=OFF \ 38 | -DWEBP_ENABLE_SWAP_16BIT_CSP=ON \ 39 | -DWEBP_BUILD_ANIM_UTILS=OFF \ 40 | -DWEBP_BUILD_CWEBP=OFF \ 41 | -DWEBP_BUILD_DWEBP=OFF \ 42 | -DWEBP_BUILD_GIF2WEBP=OFF \ 43 | -DWEBP_BUILD_IMG2WEBP=OFF \ 44 | -DWEBP_BUILD_VWEBP=OFF \ 45 | -DWEBP_BUILD_WEBPINFO=OFF \ 46 | -DWEBP_BUILD_WEBPMUX=OFF \ 47 | -DWEBP_BUILD_EXTRAS=OFF \ 48 | "${srcdir}/${_realname}-${pkgver}" 49 | ${MINGW_PREFIX}/bin/cmake.exe --build "build-${MSYSTEM}" 50 | } 51 | 52 | package() { 53 | DESTDIR="${pkgdir}" ${MINGW_PREFIX}/bin/cmake.exe --install "build-${MSYSTEM}" 54 | } -------------------------------------------------------------------------------- /scripts/mingw64/shaderc/0001-fix-glslang-hlsl-linking-order.patch: -------------------------------------------------------------------------------- 1 | diff --git a/CMakeLists.txt b/CMakeLists.txt 2 | index ffcb54b98f..1451cb6503 100644 3 | --- a/CMakeLists.txt 4 | +++ b/CMakeLists.txt 5 | @@ -157,6 +157,6 @@ function(define_pkg_config_file NAME LIBS) 6 | endif() 7 | endfunction() 8 | 9 | -define_pkg_config_file(shaderc -lshaderc_shared) 10 | +define_pkg_config_file(shaderc -lshaderc_combined) 11 | define_pkg_config_file(shaderc_static "-lshaderc ${EXTRA_STATIC_PKGCONFIG_LIBS} -lshaderc_util") 12 | define_pkg_config_file(shaderc_combined -lshaderc_combined) 13 | diff --git a/cmake/shaderc_combined.pc.in b/cmake/shaderc_combined.pc.in 14 | index 6d217bfcde..e5f500bd1b 100644 15 | --- a/cmake/shaderc_combined.pc.in 16 | +++ b/cmake/shaderc_combined.pc.in 17 | @@ -8,5 +8,7 @@ Description: Tools and libraries for Vulkan shader compilation 18 | Version: @CURRENT_VERSION@ 19 | URL: https://github.com/google/shaderc 20 | 21 | +Requires.private: SPIRV-Tools 22 | +Libs.private: -lGenericCodeGen -lMachineIndependent -lglslang -lOSDependent -lSPIRV 23 | Libs: -L${libdir} @LIBS@ 24 | Cflags: -I${includedir} 25 | diff --git a/libshaderc_util/CMakeLists.txt b/libshaderc_util/CMakeLists.txt 26 | index 69ba519..964b7e2 100644 27 | --- a/libshaderc_util/CMakeLists.txt 28 | +++ b/libshaderc_util/CMakeLists.txt 29 | @@ -46,8 +46,8 @@ add_definitions(-DENABLE_HLSL) 30 | 31 | find_package(Threads) 32 | target_link_libraries(shaderc_util PRIVATE 33 | - glslang SPIRV 34 | - SPIRV-Tools-opt ${CMAKE_THREAD_LIBS_INIT}) 35 | + MachineIndependent GenericCodeGen glslang OSDependent SPIRV 36 | + SPIRV-Tools-opt SPIRV-Tools ${CMAKE_THREAD_LIBS_INIT}) 37 | 38 | shaderc_add_tests( 39 | TEST_PREFIX shaderc_util 40 | -------------------------------------------------------------------------------- /scripts/mingw64/spirv-cross/0001-static-linking-hacks.patch: -------------------------------------------------------------------------------- 1 | From cc84968aed97d321774609f0f154413246aa8df4 Mon Sep 17 00:00:00 2001 2 | From: shinchiro 3 | Date: Mon, 4 Oct 2021 11:08:44 +0800 4 | Subject: [PATCH] static linking hacks 5 | 6 | --- 7 | CMakeLists.txt | 7 +------ 8 | 1 file changed, 1 insertion(+), 6 deletions(-) 9 | 10 | diff --git a/CMakeLists.txt b/CMakeLists.txt 11 | index 6860c5b..3ef7718 100644 12 | --- a/CMakeLists.txt 13 | +++ b/CMakeLists.txt 14 | @@ -345,7 +345,7 @@ if (SPIRV_CROSS_SHARED) 15 | install(FILES ${CMAKE_CURRENT_BINARY_DIR}/spirv-cross-c-shared.pc DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig) 16 | endif() 17 | 18 | - spirv_cross_add_library(spirv-cross-c-shared spirv_cross_c_shared SHARED 19 | + spirv_cross_add_library(spirv-cross-c-shared spirv_cross_c_shared STATIC 20 | ${spirv-cross-core-sources} 21 | ${spirv-cross-c-sources}) 22 | 23 | @@ -401,11 +401,6 @@ if (SPIRV_CROSS_SHARED) 24 | endif() 25 | endif() 26 | 27 | - target_compile_definitions(spirv-cross-c-shared PRIVATE SPVC_EXPORT_SYMBOLS) 28 | - 29 | - set_target_properties(spirv-cross-c-shared PROPERTIES 30 | - VERSION ${SPIRV_CROSS_VERSION} 31 | - SOVERSION ${spirv-cross-abi-major}) 32 | endif() 33 | 34 | if (SPIRV_CROSS_CLI) 35 | -- 36 | 2.33.0 37 | 38 | -------------------------------------------------------------------------------- /scripts/mingw64/spirv-headers/PKGBUILD: -------------------------------------------------------------------------------- 1 | # Maintainer: Christoph Reiter 2 | # Contributor: Biswapriyo Nath 3 | 4 | _realname=spirv-headers 5 | pkgbase=mingw-w64-${_realname} 6 | pkgname="${MINGW_PACKAGE_PREFIX}-${_realname}" 7 | epoch=2 8 | pkgver=1.4.313.0 9 | pkgrel=1 10 | pkgdesc='Machine-readable files for the SPIR-V Registry (mingw-w64)' 11 | arch=('any') 12 | mingw_arch=('mingw32' 'mingw64' 'clangarm64') 13 | url='https://www.khronos.org/registry/spir-v/' 14 | msys2_repository_url="https://github.com/KhronosGroup/SPIRV-Headers" 15 | license=('spdx:MIT') 16 | groups=("${MINGW_PACKAGE_PREFIX}-vulkan-devel") 17 | makedepends=( 18 | "${MINGW_PACKAGE_PREFIX}-cc" 19 | "${MINGW_PACKAGE_PREFIX}-cmake" 20 | "${MINGW_PACKAGE_PREFIX}-ninja" 21 | ) 22 | source=("https://github.com/KhronosGroup/SPIRV-Headers/archive/vulkan-sdk-${pkgver}/${_realname}-${pkgver}.tar.gz") 23 | sha256sums=('f68be549d74afb61600a1e3a7d1da1e6b7437758c8e77d664909f88f302c5ac1') 24 | 25 | build() { 26 | MSYS2_ARG_CONV_EXCL="-DCMAKE_INSTALL_PREFIX=" \ 27 | ${MINGW_PREFIX}/bin/cmake.exe -B "build-${MSYSTEM}" -G Ninja \ 28 | -DCMAKE_INSTALL_PREFIX=${MINGW_PREFIX} \ 29 | "${srcdir}/SPIRV-Headers-vulkan-sdk-${pkgver}" 30 | 31 | ${MINGW_PREFIX}/bin/cmake.exe --build "build-${MSYSTEM}" 32 | } 33 | 34 | package() { 35 | DESTDIR="${pkgdir}" ${MINGW_PREFIX}/bin/cmake.exe --install "build-${MSYSTEM}" 36 | } 37 | -------------------------------------------------------------------------------- /scripts/mingw64/spirv-tools/PKGBUILD: -------------------------------------------------------------------------------- 1 | # Maintainer: J. Peter Mugaas 2 | # Contributor: Biswapriyo Nath 3 | 4 | _realname=spirv-tools 5 | pkgbase=mingw-w64-${_realname} 6 | pkgname=("${MINGW_PACKAGE_PREFIX}-${_realname}") 7 | epoch=3 8 | pkgver=1.4.313.0 9 | pkgrel=1 10 | pkgdesc="API and commands for processing SPIR-V modules (mingw-w64)" 11 | arch=('any') 12 | mingw_arch=('mingw32' 'mingw64' 'clangarm64') 13 | url="https://www.khronos.org/vulkan/" 14 | msys2_repository_url="https://github.com/KhronosGroup/SPIRV-Tools" 15 | license=('spdx:Apache-2.0') 16 | groups=("${MINGW_PACKAGE_PREFIX}-vulkan-devel") 17 | depends=("${MINGW_PACKAGE_PREFIX}-gcc-libs") 18 | makedepends=( 19 | "${MINGW_PACKAGE_PREFIX}-cc" 20 | "${MINGW_PACKAGE_PREFIX}-cmake" 21 | "${MINGW_PACKAGE_PREFIX}-ninja" 22 | "${MINGW_PACKAGE_PREFIX}-python" 23 | "${MINGW_PACKAGE_PREFIX}-spirv-headers" 24 | ) 25 | source=("https://github.com/KhronosGroup/SPIRV-Tools/archive/vulkan-sdk-${pkgver}/${_realname}-${pkgver}.tar.gz") 26 | sha256sums=('6b60f723345ceed5291cceebbcfacf7fea9361a69332261fa08ae57e2a562005') 27 | 28 | build() { 29 | MSYS2_ARG_CONV_EXCL="-DCMAKE_INSTALL_PREFIX=" \ 30 | ${MINGW_PREFIX}/bin/cmake.exe -B "build-${MSYSTEM}" -G Ninja \ 31 | -DCMAKE_INSTALL_PREFIX=${MINGW_PREFIX} \ 32 | -DCMAKE_BUILD_TYPE=Release \ 33 | -DSPIRV_WERROR=OFF \ 34 | -DBUILD_SHARED_LIBS=OFF \ 35 | -DSPIRV_TOOLS_BUILD_STATIC=ON \ 36 | -DSPIRV_SKIP_EXECUTABLES=ON \ 37 | -DSPIRV_SKIP_TESTS=ON \ 38 | -DSPIRV-Headers_SOURCE_DIR=${MINGW_PREFIX} \ 39 | -DPython3_EXECUTABLE=${MINGW_PREFIX}/bin/python.exe \ 40 | "${srcdir}/SPIRV-Tools-vulkan-sdk-${pkgver}" 41 | ${MINGW_PREFIX}/bin/cmake.exe --build "build-${MSYSTEM}" 42 | } 43 | 44 | package() { 45 | DESTDIR="${pkgdir}" ${MINGW_PREFIX}/bin/cmake.exe --install "build-${MSYSTEM}" 46 | } 47 | -------------------------------------------------------------------------------- /scripts/org.player.switchfin.appdata.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | org.player.switchfin 4 | CC0-1.0 5 | Switchfin 6 | 7 | dragonflylee 8 | 9 | Third-party native Jellyfin client designed specifically for controller users 10 | org.player.switchfin.desktop 11 | 12 |

Switchfin is third-party PC player for Jellyfin that provides a native user interface to browse and play movies and series.

13 |

Features:

14 |
    15 |
  • Completely native interface
  • 16 |
  • Supported media items: movies, series, seasons, episodes
  • 17 |
  • Base on MPV Player
  • 18 |
  • Filter: Quickly find the movie and bangumi
  • 19 |
  • Search: TV style, Videos and Movie...
  • 20 |
21 |
22 | 23 | 24 | 25 |

26 | Please See Official Changelog at github.com/dragonflylee/switchfin/releases 27 |

28 |
29 |
30 |
31 | 32 | 33 | https://github.com/dragonflylee/switchfin/raw/dev/images/home.jpg 34 | Home 35 | 36 | 37 | https://github.com/dragonflylee/switchfin 38 | https://github.com/dragonflylee/switchfin/issues 39 |
40 | -------------------------------------------------------------------------------- /scripts/org.player.switchfin.desktop: -------------------------------------------------------------------------------- 1 | [Desktop Entry] 2 | Name=Switchfin 3 | Comment=A 3rd party jellyfin client 4 | Exec=${CMAKE_INSTALL_PREFIX}/bin/${PROJECT_NAME} 5 | Icon=${PACKAGE_NAME} 6 | Terminal=false 7 | Type=Application 8 | Categories=AudioVideo;Audio;Video; 9 | -------------------------------------------------------------------------------- /scripts/org.player.switchfin.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | icon-transparent 10 | 11 | 12 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /scripts/switch/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM devkitpro/devkita64:20241023 2 | RUN sed -i 's/deb.debian.org/mirrors.aliyun.com/g' /etc/apt/sources.list && apt-get update \ 3 | && apt-get install -y --no-install-recommends fakeroot zstd bison flex file libtool python3-pip \ 4 | && pip install meson && rm -rf /var/lib/apt/lists/* /usr/share/man/* 5 | RUN useradd --home-dir /build --create-home builder \ 6 | && echo 'builder ALL=(ALL) NOPASSWD:ALL' > /etc/sudoers.d/builder 7 | USER builder 8 | WORKDIR /build 9 | -------------------------------------------------------------------------------- /scripts/switch/curl/PKGBUILD: -------------------------------------------------------------------------------- 1 | 2 | # Maintainer: WinterMute 3 | pkgname=switch-curl 4 | pkgver=8.13.0 5 | pkgrel=1 6 | pkgdesc='An URL retrieval utility and library' 7 | arch=('any') 8 | url="https://curl.se/" 9 | license=('zlib') 10 | options=(!strip libtool staticlibs) 11 | depends=('switch-zlib' 'libnx') 12 | makedepends=('switch-pkg-config' 'dkp-toolchain-vars') 13 | source=("https://curl.haxx.se/download/curl-${pkgver}.tar.xz" 'switch-curl.patch') 14 | groups=('switch-portlibs') 15 | 16 | sha256sums=('4a093979a3c2d02de2fbc00549a32771007f2e78032c6faa5ecd2f7a9e152025' 'SKIP') 17 | 18 | build() { 19 | cd curl-$pkgver 20 | patch -Np1 -i $srcdir/switch-curl.patch 21 | 22 | source ${DEVKITPRO}/switchvars.sh 23 | LDFLAGS="-specs=${DEVKITPRO}/libnx/switch.specs ${LDFLAGS}" 24 | 25 | autoreconf -fi 26 | 27 | ./configure --prefix=$PORTLIBS_PREFIX --host=aarch64-none-elf \ 28 | --disable-shared --enable-static --disable-ipv6 --disable-unix-sockets \ 29 | --disable-manual --disable-threaded-resolver --disable-progress-meter \ 30 | --without-zstd --without-brotli --without-libpsl --enable-websockets \ 31 | --with-libnx --with-default-ssl-backend=libnx 32 | sed -i '/HAVE_SOCKETPAIR/d' lib/curl_config.h 33 | make -C lib -j$(nproc) 34 | } 35 | 36 | package() { 37 | cd curl-$pkgver 38 | 39 | source /opt/devkitpro/switchvars.sh 40 | 41 | make DESTDIR="$pkgdir" -C lib install 42 | make DESTDIR="$pkgdir" -C include install 43 | make DESTDIR="$pkgdir" install-binSCRIPTS install-pkgconfigDATA 44 | } -------------------------------------------------------------------------------- /scripts/switch/hacbrewpack/PKGBUILD: -------------------------------------------------------------------------------- 1 | # Maintainer: fincs 2 | 3 | pkgname=('hacBrewPack') 4 | pkgver=3.05 5 | pkgrel=1 6 | pkgdesc="Make NCAs/NSPs from Nintendo Switch homebrews" 7 | arch=('x86_64') 8 | license=('custom') 9 | url="http://github.com/dragonflylee/${pkgname}" 10 | options=(!strip) 11 | source=("${pkgname}-${pkgver}.tar.gz::${url}/archive/v${pkgver}.tar.gz" "nostartupuser.patch") 12 | sha256sums=('9b5cb51e8e8a53d20d0e7d4518d82c99012eb40545d45b4f8edaa9786670e0ec' 'SKIP') 13 | 14 | groups=('switch-dev') 15 | 16 | build() { 17 | cd $srcdir/$pkgname-$pkgver 18 | patch -Np1 -i "$srcdir/nostartupuser.patch" 19 | mv config.mk.template config.mk 20 | make 21 | } 22 | 23 | package() { 24 | cd $srcdir/$pkgname-$pkgver 25 | install -D hacbrewpack $pkgdir/opt/devkitpro/tools/bin/hacbrewpack 26 | } 27 | -------------------------------------------------------------------------------- /scripts/switch/harfbuzz/PKGBUILD: -------------------------------------------------------------------------------- 1 | # Maintainer: Mary Strodl 2 | 3 | pkgname=switch-harfbuzz 4 | pkgver=11.2.1 5 | pkgrel=1 6 | pkgdesc='HarfBuzz is a text shaping library. Using the HarfBuzz library allows programs to convert a sequence of Unicode input into properly formatted and positioned glyph output—for any writing system and language.' 7 | arch=('any') 8 | url='https://harfbuzz.github.io/' 9 | license=(LGPL) 10 | options=(!strip libtool staticlibs) 11 | source=("https://github.com/harfbuzz/harfbuzz/releases/download/${pkgver}/harfbuzz-${pkgver}.tar.xz") 12 | sha256sums=('093714c8548a285094685f0bdc999e202d666b59eeb3df2ff921ab68b8336a49') 13 | makedepends=('dkp-toolchain-vars' 'dkp-meson-scripts') 14 | depends=('switch-freetype') 15 | 16 | groups=('switch-portlibs') 17 | 18 | build() { 19 | cd harfbuzz-${pkgver} 20 | /opt/devkitpro/meson-cross.sh switch ../crossfile.txt build -Dc_std=gnu11 -Db_ndebug=true \ 21 | -Dicu=disabled -Dglib=disabled -Dcairo=disabled -Dgobject=disabled -Dtests=disabled \ 22 | -Ddocs=disabled -Dbenchmark=disabled 23 | meson compile -C build 24 | } 25 | 26 | package() { 27 | 28 | cd harfbuzz-${pkgver} 29 | DESTDIR="${pkgdir}" meson install -C build 30 | 31 | } -------------------------------------------------------------------------------- /scripts/switch/libnx/PKGBUILD: -------------------------------------------------------------------------------- 1 | 2 | # Maintainer: Dave Murphy 3 | 4 | pkgname=libnx 5 | pkgver=4.9.0 6 | pkgrel=1 7 | pkgdesc="Nintendo Switch AArch64-only userland library." 8 | arch=('any') 9 | license=('custom') 10 | url="http://github.com/switchbrew" 11 | options=(!strip libtool staticlibs) 12 | source=("${pkgname}-${pkgver}.tar.gz::${url}/${pkgname}/archive/v${pkgver}.tar.gz") 13 | sha256sums=('5abffc13708cbc2af870e4c630e7b2b30ce8f5d873975fb0ce89b4bfbf73e788') 14 | makedepends=('devkitA64') 15 | groups=('switch-dev') 16 | 17 | build() { 18 | 19 | cd ${srcdir}/${pkgname}-${pkgver}/nx 20 | make -j$(nproc) 21 | 22 | } 23 | 24 | package() { 25 | 26 | cd ${srcdir}/${pkgname}-${pkgver}/nx 27 | make DESTDIR=$pkgdir install 28 | 29 | } 30 | -------------------------------------------------------------------------------- /scripts/switch/libssh2/PKGBUILD: -------------------------------------------------------------------------------- 1 | # Maintainer: WinterMute 2 | pkgname=switch-libssh2 3 | pkgver=1.11.1 4 | pkgrel=1 5 | pkgdesc="A library implementing the SSH2 protocol as defined by Internet Drafts" 6 | url="https://github.com/libssh2/libssh2" 7 | license=('BSD') 8 | arch=('any') 9 | options=(!strip libtool staticlibs) 10 | depends=('switch-mbedtls' 'switch-zlib') 11 | makedepends=('switch-pkg-config' 'dkp-toolchain-vars') 12 | groups=('switch-portlibs') 13 | source=("https://libssh2.org/download/libssh2-${pkgver}.tar.xz") 14 | sha256sums=('9954cb54c4f548198a7cbebad248bdc87dd64bd26185708a294b2b50771e3769') 15 | 16 | prepare() { 17 | cd "libssh2-${pkgver}" 18 | autoreconf -fi 19 | } 20 | 21 | build() { 22 | cd "libssh2-${pkgver}" 23 | 24 | source ${DEVKITPRO}/switchvars.sh 25 | 26 | ./configure --prefix=${PORTLIBS_PREFIX} \ 27 | --disable-shared --enable-static \ 28 | --host=aarch64-none-elf \ 29 | --with-crypto=mbedtls \ 30 | --disable-examples-build \ 31 | --disable-tests-build \ 32 | --disable-docker-tests \ 33 | --disable-sshd-tests 34 | 35 | make -j$(nproc) 36 | } 37 | 38 | package() { 39 | cd "libssh2-${pkgver}" 40 | make DESTDIR="${pkgdir}" install 41 | install -Dm644 COPYING "${pkgdir}/opt/devkitpro/portlibs/switch/licenses/${pkgname}/LICENSE" 42 | } -------------------------------------------------------------------------------- /scripts/switch/libuam/PKGBUILD: -------------------------------------------------------------------------------- 1 | # Maintainer: fincs 2 | # Contributor: averne 3 | 4 | pkgname=('libuam') 5 | pkgver=master 6 | pkgrel=1 7 | pkgdesc="Shader compiler for Nintendo Switch, targeting the deko3d API" 8 | arch=('any') 9 | license=('custom') 10 | url="https://github.com/averne/${pkgname}" 11 | options=(!strip libtool staticlibs) 12 | source=(${pkgname}-${pkgver}.tar.gz::${url}/archive/${pkgver}.tar.gz) 13 | sha256sums=('SKIP') 14 | makedepends=("dkp-toolchain-vars" "dkp-meson-scripts") 15 | 16 | groups=('switch-dev') 17 | 18 | build() { 19 | cd ${pkgname}-${pkgver} 20 | 21 | /opt/devkitpro/meson-cross.sh switch ../crossfile.txt build 22 | meson compile -C build 23 | } 24 | 25 | package() { 26 | cd ${pkgname}-${pkgver} 27 | 28 | DESTDIR="$pkgdir" meson install -C build 29 | } 30 | -------------------------------------------------------------------------------- /scripts/switch/mbedtls/PKGBUILD: -------------------------------------------------------------------------------- 1 | _realname=mbedtls 2 | pkgname=switch-${_realname} 3 | pkgver=2.28.10 4 | pkgrel=3 5 | pkgdesc='An open source, portable, easy to use, readable and flexible SSL library' 6 | arch=('any') 7 | url='https://tls.mbed.org' 8 | license=('apache') 9 | options=(!strip libtool staticlibs) 10 | depends=(switch-zlib) 11 | makedepends=('switch-pkg-config' 'dkp-toolchain-vars') 12 | source=( "https://github.com/Mbed-TLS/mbedtls/releases/download/mbedtls-${pkgver}/mbedtls-${pkgver}.tar.bz2" 13 | "mbedtls-${pkgver}.patch" ) 14 | groups=('switch-portlibs') 15 | sha256sums=('19e5b81fdac0fe22009b9e2bdcd52d7dcafbf62bc67fc59cf0a76b5b5540d149' 'SKIP') 16 | 17 | build() { 18 | cd mbedtls-$pkgver 19 | 20 | patch -Np1 -i $srcdir/mbedtls-${pkgver}.patch 21 | 22 | ./scripts/config.pl set MBEDTLS_ENTROPY_HARDWARE_ALT 23 | ./scripts/config.pl set MBEDTLS_NO_PLATFORM_ENTROPY 24 | 25 | source ${DEVKITPRO}/switchvars.sh 26 | 27 | aarch64-none-elf-cmake \ 28 | -DCMAKE_INSTALL_PREFIX=$PORTLIBS_PREFIX \ 29 | -DCMAKE_C_FLAGS="$CFLAGS $CPPFLAGS" \ 30 | -DENABLE_ZLIB_SUPPORT=ON \ 31 | -DENABLE_TESTING=OFF \ 32 | -DENABLE_PROGRAMS=OFF \ 33 | . 34 | 35 | make -j$(nproc) 36 | 37 | } 38 | 39 | package() { 40 | 41 | cd mbedtls-$pkgver 42 | make install DESTDIR="$pkgdir" 43 | 44 | } 45 | -------------------------------------------------------------------------------- /scripts/switch/nspmini/PKGBUILD: -------------------------------------------------------------------------------- 1 | pkgbasename=nspmini 2 | pkgname=switch-${pkgbasename} 3 | pkgver=main 4 | pkgrel=1 5 | pkgdesc='easy install nsp lib' 6 | arch=('any') 7 | license=('GPL') 8 | options=(!strip libtool staticlibs) 9 | source=("${pkgbasename}-${pkgver}.tar.gz::https://github.com/StarDustCFW/nspmini/archive/${pkgver}.tar.gz") 10 | sha256sums=('SKIP') 11 | makedepends=('switch-pkg-config' 'dkp-toolchain-vars') 12 | groups=('switch-portlibs') 13 | 14 | build() { 15 | cd nspmini-main 16 | 17 | source /opt/devkitpro/switchvars.sh 18 | 19 | make -j$(nproc) 20 | } 21 | 22 | package() { 23 | cd nspmini-main 24 | 25 | mkdir -p $pkgdir/${PORTLIBS_PREFIX} 26 | 27 | cp -r lib $pkgdir/${PORTLIBS_PREFIX}/lib 28 | cp -r include $pkgdir/${PORTLIBS_PREFIX}/include 29 | } -------------------------------------------------------------------------------- /scripts/vita/curl/VITABUILD: -------------------------------------------------------------------------------- 1 | pkgname=curl 2 | pkgver=8.13.0 3 | pkgrel=2 4 | url="https://curl.se/" 5 | source=("https://curl.haxx.se/download/curl-${pkgver}.tar.xz") 6 | sha256sums=('4a093979a3c2d02de2fbc00549a32771007f2e78032c6faa5ecd2f7a9e152025') 7 | depends=('mbedtls' 'zlib') 8 | 9 | build() { 10 | cd curl-${pkgver} 11 | 12 | cmake -B build -DCMAKE_TOOLCHAIN_FILE=$VITASDK/share/vita.toolchain.cmake \ 13 | -DCMAKE_INSTALL_PREFIX=$prefix \ 14 | -DCMAKE_BUILD_TYPE=Release \ 15 | -DBUILD_CURL_EXE=OFF \ 16 | -DBUILD_SHARED_LIBS=OFF \ 17 | -DBUILD_TESTING=OFF \ 18 | -DBUILD_EXAMPLES=OFF \ 19 | -DBUILD_LIBCURL_DOCS=OFF \ 20 | -DBUILD_MISC_DOCS=OFF \ 21 | -DENABLE_CURL_MANUAL=OFF \ 22 | -DHTTP_ONLY=ON \ 23 | -DCURL_USE_MBEDTLS=ON \ 24 | -DCURL_DISABLE_PROGRESS_METER=ON \ 25 | -DENABLE_IPV6=OFF \ 26 | -DENABLE_THREADED_RESOLVER=OFF \ 27 | -DUSE_NGHTTP2=OFF \ 28 | -DUSE_LIBIDN2=OFF \ 29 | -DCURL_BROTLI=OFF \ 30 | -DCURL_ZSTD=OFF \ 31 | -DCURL_USE_LIBSSH2=OFF \ 32 | -DCURL_USE_LIBPSL=OFF 33 | cmake --build build -j$(nproc) 34 | } 35 | 36 | package () { 37 | cd curl-${pkgver} 38 | DESTDIR=$pkgdir cmake --install build 39 | } -------------------------------------------------------------------------------- /scripts/vita/mbedtls/VITABUILD: -------------------------------------------------------------------------------- 1 | pkgname=mbedtls 2 | pkgver=3.4.1 3 | pkgrel=1 4 | url="https://www.trustedfirmware.org/projects/mbed-tls/" 5 | source=("https://github.com/Mbed-TLS/mbedtls/archive/refs/tags/v$pkgver.tar.gz" "mbedtls.patch") 6 | sha256sums=('SKIP' 'SKIP') 7 | 8 | prepare() { 9 | cd $pkgname-$pkgver 10 | patch --strip=1 --input=${srcdir}/mbedtls.patch 11 | } 12 | 13 | build() { 14 | cd $pkgname-$pkgver 15 | mkdir build && cd build 16 | cmake .. \ 17 | -DCMAKE_TOOLCHAIN_FILE=$VITASDK/share/vita.toolchain.cmake \ 18 | -DCMAKE_INSTALL_PREFIX=$prefix \ 19 | -DCMAKE_BUILD_TYPE=Release \ 20 | -DENABLE_PROGRAMS=OFF \ 21 | -DENABLE_TESTING=OFF \ 22 | -DMBEDTLS_FATAL_WARNINGS=OFF 23 | make -j$(nproc) mbedtls 24 | } 25 | 26 | package () { 27 | cd $pkgname-$pkgver/build 28 | make DESTDIR=$pkgdir install 29 | } 30 | -------------------------------------------------------------------------------- /scripts/vita/mpv/VITABUILD: -------------------------------------------------------------------------------- 1 | pkgname=mpv 2 | pkgver=0.36.0 3 | pkgrel=3 4 | url="https://mpv.io/" 5 | source=("${pkgname}-${pkgver}.tar.gz::https://github.com/mpv-player/mpv/archive/v${pkgver}.tar.gz" "gxm.patch") 6 | sha256sums=('SKIP' 'SKIP') 7 | depends=('libass' 'ffmpeg') 8 | 9 | prepare() { 10 | cd $pkgname-$pkgver 11 | patch --strip=1 --input=${srcdir}/gxm.patch 12 | } 13 | 14 | build() { 15 | cd $pkgname-$pkgver 16 | meson setup build --prefix=$prefix --cross-file crossfile.txt \ 17 | --default-library static \ 18 | -Diconv=disabled \ 19 | -Dlua=disabled \ 20 | -Djpeg=disabled \ 21 | -Dopensles=disabled \ 22 | -Dlibavdevice=disabled \ 23 | -Dmanpage-build=disabled \ 24 | -Dhtml-build=disabled \ 25 | -Dsdl2=disabled \ 26 | -Dlibmpv=true \ 27 | -Dgxm=enabled \ 28 | -Dvitashark=disabled \ 29 | -Dcplayer=false 30 | 31 | meson compile -C build 32 | } 33 | 34 | package () { 35 | cd $pkgname-$pkgver 36 | DESTDIR=$pkgdir meson install -C build 37 | } --------------------------------------------------------------------------------