diff --git a/.github/actions/install-dependencies/action.yml b/.github/actions/install-dependencies/action.yml new file mode 100644 index 0000000..83de601 --- /dev/null +++ b/.github/actions/install-dependencies/action.yml @@ -0,0 +1,113 @@ +name: 'Install Dependencies' +description: 'Install vcpkg libraries and qt environment' +inputs: + os_name: + description: 'os name' + required: true + type: string + vcpkg_libs: + description: 'vcpkg libraries' + required: false + default: 'breakpad crashpad' + type: string + vcpkg_ffmpeg_features: + description: 'vcpkg ffmpeg features' + required: false + default: 'opengl,ass,bzip2,freetype,fribidi,zlib,gpl,ffmpeg,ffplay,ffprobe' + type: string + qt_modules: + description: 'qt modules' + required: false + default: 'qt5compat qtnetworkauth qtmultimedia qtimageformats' + type: string + qt_ver: + description: 'qt version' + required: false + default: '6.7.0' + type: string + +runs: + using: 'composite' + + steps: + - name: Install Custom VCPKG + uses: RealChuan/install-vcpkg@main + with: + repo: 'https://github.com/RealChuan/vcpkg.git' + branch: 'dev' + + - name: Delete vcpkg.json + shell: bash + run: | + rm vcpkg.json + + - name: Cache windows vcpkg + if: startsWith(runner.os, 'Windows') + uses: actions/cache@v4 + with: + path: C:\vcpkg\installed + key: ${{ inputs.os_name }}-vcpkg-installed-${{ runner.os }}-${{ github.sha }} + restore-keys: | + ${{ inputs.os_name }}-vcpkg-installed-${{ runner.os_name }}- + ${{ inputs.os_name }}-vcpkg-installed- + ${{ inputs.os_name }}- + save-always: true + + - name: Cache macos or linux vcpkg + if: startsWith(runner.os, 'macOS') || startsWith(runner.os, 'Linux') + uses: actions/cache@v4 + with: + path: /usr/local/share/vcpkg/installed + key: ${{ inputs.os_name }}-vcpkg-installed-${{ runner.os }}-${{ github.sha }} + restore-keys: | + ${{ inputs.os_name }}-vcpkg-installed-${{ runner.os_name }}- + ${{ inputs.os_name }}-vcpkg-installed- + ${{ inputs.os_name }}- + save-always: true + + - name: Install dependencies on windows + if: startsWith(runner.os, 'Windows') + shell: bash + run: | + choco install ninja + ninja --version + cmake --version + vcpkg install ${{ inputs.vcpkg_libs }} \ + ffmpeg[${{ inputs.vcpkg_ffmpeg_features }},amf,nvcodec,qsv] --triplet x64-windows \ + || (cat C:/vcpkg/installed/vcpkg/issue_body.md && exit 1) + + - name: Install dependencies on macos + if: startsWith(runner.os, 'macOS') + shell: bash + run: | + brew install ninja nasm pkg-config python-setuptools + ninja --version + cmake --version + clang --version + vcpkg install ${{ inputs.vcpkg_libs }} \ + ffmpeg[${{ inputs.vcpkg_ffmpeg_features }}] --triplet x64-osx \ + || (cat /usr/local/share/vcpkg/installed/vcpkg/issue_body.md && exit 1) + vcpkg install ${{ inputs.vcpkg_libs }} \ + ffmpeg[${{ inputs.vcpkg_ffmpeg_features }}] --triplet arm64-osx \ + || (cat /usr/local/share/vcpkg/installed/vcpkg/issue_body.md && exit 1) + + - name: Install dependencies on linux + if: startsWith(runner.os, 'Linux') + shell: bash + run: | + sudo apt-get update + sudo apt-get install ninja-build nasm autopoint gperf libgl1-mesa-dev \ + libxinerama-dev libxcursor-dev xorg-dev libglu1-mesa-dev + ninja --version + cmake --version + gcc --version + vcpkg install ${{ inputs.vcpkg_libs }} \ + ffmpeg[${{ inputs.vcpkg_ffmpeg_features }},amf,nvcodec] --triplet x64-linux \ + || (cat /usr/local/share/vcpkg/installed/vcpkg/issue_body.md && exit 1) + + - name: Install Qt + uses: jurplel/install-qt-action@v4 + with: + version: ${{ inputs.qt_ver }} + modules: ${{ inputs.qt_modules }} + cache: 'true' diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index a6c01ed..4c7d375 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -1,33 +1,23 @@ name: CMake build on: - # push代码时触发workflow push: - paths-ignore: # 下列文件的变更不触发部署,可以自行添加 - - '.github/workflows/clean_cache.yml' - - '.github/workflows/delete_workflow.yml' - - '.github/workflows/qmake.yml' - - '.github/workflows/readme.yml' - - '.github/workflows/toolchain.yml' + paths-ignore: - 'doc/**' - '.clang*' - '.gitignore' - 'LICENSE' - 'README*' - - 'vcpkg.json' pull_request: - paths-ignore: # 下列文件的变更不触发部署,可以自行添加 - - '.github/workflows/clean_cache.yml' - - '.github/workflows/delete_workflow.yml' - - '.github/workflows/qmake.yml' - - '.github/workflows/readme.yml' - - '.github/workflows/toolchain.yml' + paths-ignore: - 'doc/**' - '.clang*' - '.gitignore' - 'LICENSE' - 'README*' - - 'vcpkg.json' + +env: + MACOSX_DEPLOYMENT_TARGET: 11.0 jobs: build: @@ -40,108 +30,39 @@ jobs: - windows-latest - macos-latest - ubuntu-latest - qt_ver: - - 6.6.2 build_type: - "RelWithDebInfo" generators: - "Ninja" - vcpkg_libs: - - breakpad - vcpkg_ffmpeg_features: - - opengl,ass,bzip2,freetype,fribidi,zlib,gpl,ffmpeg,ffplay,ffprobe steps: - - name: Restore windows vcpkg - if: startsWith(matrix.os, 'windows') - uses: actions/cache/restore@v4 - with: - path: C:\vcpkg\installed - key: ${{ runner.os }}-vcpkg-installed-${{ matrix.os }} - - name: Restore macos or ubuntu vcpkg - if: startsWith(matrix.os, 'macos') || startsWith(matrix.os, 'ubuntu') - uses: actions/cache/restore@v4 - with: - path: /usr/local/share/vcpkg/installed - key: ${{ runner.os }}-vcpkg-installed-${{ matrix.os }} - - - name: Install dependencies on windows - if: startsWith(matrix.os, 'windows') - shell: bash - run: | - choco install ninja - ninja --version - cmake --version - vcpkg install ${{ matrix.vcpkg_libs }} ffmpeg[${{ matrix.vcpkg_ffmpeg_features }},amf,nvcodec,qsv] --triplet x64-windows - - name: Install dependencies on macos - if: startsWith(matrix.os, 'macos') - shell: bash - run: | - brew install ninja nasm pkg-config - ninja --version - cmake --version - clang --version - vcpkg install ${{ matrix.vcpkg_libs }} ffmpeg[${{ matrix.vcpkg_ffmpeg_features }}] --triplet x64-osx - - name: Install dependencies on ubuntu - if: startsWith(matrix.os, 'ubuntu') - shell: bash - run: | - sudo apt-get update - sudo apt-get install ninja-build nasm autopoint gperf libgl1-mesa-dev \ - libxinerama-dev libxcursor-dev xorg-dev libglu1-mesa-dev - ninja --version - cmake --version - gcc --version - vcpkg install ${{ matrix.vcpkg_libs }} ffmpeg[${{ matrix.vcpkg_ffmpeg_features }},amf,nvcodec] --triplet x64-linux - - - name: Install Qt - uses: jurplel/install-qt-action@v3 - with: - version: ${{ matrix.qt_ver }} - install-deps: 'true' - modules: 'qt5compat qtnetworkauth qtmultimedia qtimageformats' - cache: 'true' - - uses: actions/checkout@v4 - with: + with: fetch-depth: 1 - - # jurplel/install-qt-action@v3, 这个action会修改默认的python版本, - # 会导致部分使用vcpkg的库编译失败,比如libsystemd,所以需要删除vcpkg.json - - name: Delete vcpkg.json - shell: bash - run: | - rm vcpkg.json - - - name: Enable Developer Command Prompt - if: startsWith(matrix.os, 'windows') - uses: ilammy/msvc-dev-cmd@v1.12.1 + + - uses: ./.github/actions/install-dependencies with: - arch: amd64 - - name: Configure windows + os_name: ${{ matrix.os }} + + - name: Configure and build windows if: startsWith(matrix.os, 'windows') - shell: bash + shell: pwsh run: | - cmake \ - -S . \ - -B ./build \ - -DCMAKE_C_COMPILER=cl \ - -DCMAKE_CXX_COMPILER=cl \ - -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} \ - -G "${{ matrix.generators }}" \ - -DCMAKE_INSTALL_PREFIX:PATH=instdir - - name: Configure macos or ubuntu - if: startsWith(matrix.os, 'macos') || startsWith(matrix.os, 'ubuntu') + .\scripts\windows\setVsDev.ps1 + cmake ` + -S . ` + -B ./build ` + -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} ` + -G "${{ matrix.generators }}" + cmake --build ./build --config ${{ matrix.build_type }} + - name: Configure and build on ubuntu or macos + if: startsWith(matrix.os, 'ubuntu') || startsWith(matrix.os, 'macos') shell: bash run: | cmake \ -S . \ -B ./build \ -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} \ - -G "${{ matrix.generators }}" \ - -DCMAKE_INSTALL_PREFIX:PATH=instdir - - name: Build - shell: bash - run: | + -G "${{ matrix.generators }}" cmake --build ./build --config ${{ matrix.build_type }} \ No newline at end of file diff --git a/.github/workflows/delete_workflow.yml b/.github/workflows/delete_workflow.yml index ae96aae..9c96ce6 100644 --- a/.github/workflows/delete_workflow.yml +++ b/.github/workflows/delete_workflow.yml @@ -27,7 +27,7 @@ on: delete_run_by_conclusion_pattern: description: 'Remove runs based on conclusion: action_required, cancelled, failure, skipped, success' required: true - default: "failure" + default: "Unsuccessful: action_required,cancelled,failure,skipped" type: choice options: - "ALL" diff --git a/.github/workflows/qmake.yml b/.github/workflows/qmake.yml index be27b3d..43f364f 100644 --- a/.github/workflows/qmake.yml +++ b/.github/workflows/qmake.yml @@ -1,14 +1,8 @@ name: QMake build on: - # push代码时触发workflow push: - paths-ignore: # 下列文件的变更不触发部署,可以自行添加 - - '.github/workflows/clean_cache.yml' - - '.github/workflows/delete_workflow.yml' - - '.github/workflows/cmake.yml' - - '.github/workflows/readme.yml' - - '.github/workflows/toolchain.yml' + paths-ignore: - 'doc/**' - '.clang*' - '.gitignore' @@ -16,12 +10,7 @@ on: - 'README*' - 'vcpkg.json' pull_request: - paths-ignore: # 下列文件的变更不触发部署,可以自行添加 - - '.github/workflows/clean_cache.yml' - - '.github/workflows/delete_workflow.yml' - - '.github/workflows/cmake.yml' - - '.github/workflows/readme.yml' - - '.github/workflows/toolchain.yml' + paths-ignore: - 'doc/**' - '.clang*' - '.gitignore' @@ -29,6 +18,9 @@ on: - 'README*' - 'vcpkg.json' +env: + MACOSX_DEPLOYMENT_TARGET: 11.0 + jobs: build: name: Build @@ -40,78 +32,42 @@ jobs: - windows-2019 - macos-latest - ubuntu-latest - qt_ver: - - 6.6.2 - vcpkg_libs: - - breakpad - vcpkg_ffmpeg_features: - - opengl,ass,bzip2,freetype,fribidi,zlib,gpl,ffmpeg,ffplay,ffprobe steps: - - name: Restore windows vcpkg - if: startsWith(matrix.os, 'windows') - uses: actions/cache/restore@v4 - with: - path: C:\vcpkg\installed - key: ${{ runner.os }}-vcpkg-installed-${{ matrix.os }} - - name: Restore macos or ubuntu vcpkg - if: startsWith(matrix.os, 'macos') || startsWith(matrix.os, 'ubuntu') - uses: actions/cache/restore@v4 + - uses: actions/checkout@v4 with: - path: /usr/local/share/vcpkg/installed - key: ${{ runner.os }}-vcpkg-installed-${{ matrix.os }} - - - name: Install dependencies on windows - if: startsWith(matrix.os, 'windows') - shell: bash - run: | - choco install ninja - ninja --version - cmake --version - vcpkg install ${{ matrix.vcpkg_libs }} ffmpeg[${{ matrix.vcpkg_ffmpeg_features }},amf,nvcodec,qsv] --triplet x64-windows - - name: Install dependencies on macos - if: startsWith(matrix.os, 'macos') - shell: bash - run: | - brew install ninja nasm pkg-config - ninja --version - cmake --version - clang --version - vcpkg install ${{ matrix.vcpkg_libs }} ffmpeg[${{ matrix.vcpkg_ffmpeg_features }}] --triplet x64-osx - - name: Install dependencies on ubuntu - if: startsWith(matrix.os, 'ubuntu') - shell: bash - run: | - sudo apt-get update - sudo apt-get install ninja-build nasm autopoint gperf libgl1-mesa-dev \ - libxinerama-dev libxcursor-dev xorg-dev libglu1-mesa-dev - ninja --version - cmake --version - gcc --version - vcpkg install ${{ matrix.vcpkg_libs }} ffmpeg[${{ matrix.vcpkg_ffmpeg_features }},amf,nvcodec] --triplet x64-linux - - - name: Install Qt - uses: jurplel/install-qt-action@v3 + fetch-depth: 1 + + - uses: ./.github/actions/install-dependencies with: - version: ${{ matrix.qt_ver }} - install-deps: 'true' - modules: 'qt5compat qtnetworkauth qtmultimedia qtimageformats' - cache: 'true' + os_name: ${{ matrix.os }} - - uses: actions/checkout@v4 - with: - fetch-depth: 1 + - uses: RealChuan/install-jom@main + + - name: mkdir build + shell: bash + run: | + mkdir build - name: msvc-build if: startsWith(matrix.os, 'windows') - shell: cmd + shell: pwsh + run: | + ..\scripts\windows\setVsDev.ps1 -VersionRange "[16.0,17.0)" -Arch "x64" + & qmake ./../. + & jom + working-directory: build + - name: ubuntu-build + if: startsWith(matrix.os, 'ubuntu') + shell: bash run: | - call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - qmake - nmake - - name: build macos or ubuntu - if: startsWith(matrix.os, 'macos') || startsWith(matrix.os, 'ubuntu') + qmake ./../. + make -j $(nproc) + working-directory: build + - name: macos-build + if: startsWith(matrix.os, 'macos') shell: bash run: | - qmake - make -j4 + qmake ./../. + make -j $(sysctl -n hw.ncpu) + working-directory: build diff --git a/.github/workflows/readme.yml b/.github/workflows/readme.yml index 7079ea6..ebe25e0 100644 --- a/.github/workflows/readme.yml +++ b/.github/workflows/readme.yml @@ -15,8 +15,6 @@ jobs: - uses: actions/checkout@v4 - name: Setup Node.js uses: actions/setup-node@v4 - with: - node-version: 20.x # ISO Langusge Codes: https://cloud.google.com/translate/docs/languages - name: Adding README - English uses: dephraiim/translate-readme@main diff --git a/.github/workflows/toolchain.yml b/.github/workflows/toolchain.yml index 693634a..39dd345 100644 --- a/.github/workflows/toolchain.yml +++ b/.github/workflows/toolchain.yml @@ -8,6 +8,9 @@ on: # 手动触发 workflow_dispatch: +env: + MACOSX_DEPLOYMENT_TARGET: 11.0 + jobs: build: name: Build @@ -20,60 +23,12 @@ jobs: - windows-2019 - macos-latest - ubuntu-latest - qt_ver: - - 6.6.2 - vcpkg_libs: - - breakpad - vcpkg_ffmpeg_features: - - opengl,ass,bzip2,freetype,fribidi,zlib,gpl,ffmpeg,ffplay,ffprobe steps: - - name: Install dependencies on windows - if: startsWith(matrix.os, 'windows') - shell: bash - run: | - choco install ninja - ninja --version - cmake --version - vcpkg install ${{ matrix.vcpkg_libs }} ffmpeg[${{ matrix.vcpkg_ffmpeg_features }},amf,nvcodec,qsv] --triplet x64-windows - - name: Install dependencies on macos - if: startsWith(matrix.os, 'macos') - shell: bash - run: | - brew install ninja nasm pkg-config - ninja --version - cmake --version - clang --version - vcpkg install ${{ matrix.vcpkg_libs }} ffmpeg[${{ matrix.vcpkg_ffmpeg_features }}] --triplet x64-osx - - name: Install dependencies on ubuntu - if: startsWith(matrix.os, 'ubuntu') - shell: bash - run: | - sudo apt-get update - sudo apt-get install ninja-build nasm autopoint gperf libgl1-mesa-dev \ - libxinerama-dev libxcursor-dev xorg-dev libglu1-mesa-dev - ninja --version - cmake --version - gcc --version - vcpkg install ${{ matrix.vcpkg_libs }} ffmpeg[${{ matrix.vcpkg_ffmpeg_features }},amf,nvcodec] --triplet x64-linux - - - name: cache windows vcpkg - if: startsWith(matrix.os, 'windows') - uses: actions/cache/save@v4 - with: - path: C:\vcpkg\installed - key: ${{ runner.os }}-vcpkg-installed-${{ matrix.os }} - - name: cache macos or ubuntu vcpkg - if: startsWith(matrix.os, 'macos') || startsWith(matrix.os, 'ubuntu') - uses: actions/cache/save@v4 + - uses: actions/checkout@v4 with: - path: /usr/local/share/vcpkg/installed - key: ${{ runner.os }}-vcpkg-installed-${{ matrix.os }} + fetch-depth: 1 - - name: Install Qt - uses: jurplel/install-qt-action@v3 + - uses: ./.github/actions/install-dependencies with: - version: ${{ matrix.qt_ver }} - install-deps: 'true' - modules: 'qt5compat qtnetworkauth qtmultimedia qtimageformats' - cache: 'true' + os_name: ${{ matrix.os }} diff --git a/3rdparty/3rdparty.pri b/3rdparty/3rdparty.pri deleted file mode 100644 index 2b868bc..0000000 --- a/3rdparty/3rdparty.pri +++ /dev/null @@ -1,80 +0,0 @@ -win32{ - contains(QT_ARCH, i386) { - vcpkg_path = C:/vcpkg/installed/x86-windows - }else{ - vcpkg_path = C:/vcpkg/installed/x64-windows - } -} - -macx{ - contains(QMAKE_APPLE_DEVICE_ARCHS, arm64) { - vcpkg_path = /usr/local/share/vcpkg/installed/arm64-osx - } else { - vcpkg_path = /usr/local/share/vcpkg/installed/x64-osx - } -} - -unix:!macx{ - vcpkg_path = /usr/local/share/vcpkg/installed/x64-linux -} - -CONFIG(debug, debug|release) { - LIBS += -L$$vcpkg_path/debug/lib \ - -llibbreakpad_clientd -llibbreakpadd -}else{ - LIBS += -L$$vcpkg_path/lib \ - -llibbreakpad_client -llibbreakpad -} - -LIBS += -lavdevice -lavfilter -lavformat -lavcodec -lswresample -lswscale -lavutil \ - -lass -lharfbuzz -lfribidi - -win32{ - -CONFIG(debug, debug|release) { - LIBS += -lfreetyped -llibpng16d -lzlibd -lbz2d -lbrotlidec -lbrotlienc -lbrotlicommon -}else{ - LIBS += -lfreetype -llibpng16 -lzlib -lbz2 -lbrotlidec -lbrotlienc -lbrotlicommon -} - -} - -unix:!macx{ - LIBS += -lfontconfig -lexpat -} - -unix{ - -CONFIG(debug, debug|release) { - LIBS += -lfreetyped -lpng -lz -lbz2d -}else{ - LIBS += -lfreetype -lpng -lz -lbz2 -} - -LIBS += -lbrotlidec -lbrotlicommon - -} - -INCLUDEPATH += $$vcpkg_path/include - -macx{ -LIBS += \ - -framework Foundation \ - -framework CoreAudio \ - -framework AVFoundation \ - -framework CoreGraphics \ - -framework OpenGL \ - -framework CoreText \ - -framework CoreImage \ - -framework AppKit \ - -framework Security \ - -framework AudioToolBox \ - -framework VideoToolBox \ - -framework CoreFoundation \ - -framework CoreMedia \ - -framework CoreVideo \ - -framework CoreServices -# -framework QuartzCore \ -# -framework Cocoa \ -# -framework VideoDecodeAcceleration -} diff --git a/CMakeLists.txt b/CMakeLists.txt index 677f76a..b443bd7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,85 +1,37 @@ -cmake_minimum_required(VERSION 3.16) +cmake_minimum_required(VERSION 3.25.1) -if(CMAKE_HOST_WIN32) - set(CMAKE_TOOLCHAIN_FILE - "C:/vcpkg/scripts/buildsystems/vcpkg.cmake" - CACHE STRING "Vcpkg toolchain file") -elseif(CMAKE_HOST_APPLE) - set(CMAKE_TOOLCHAIN_FILE - "/usr/local/share/vcpkg/scripts/buildsystems/vcpkg.cmake" - CACHE STRING "Vcpkg toolchain file") -elseif(CMAKE_HOST_UNIX) - set(CMAKE_TOOLCHAIN_FILE - "/usr/local/share/vcpkg/scripts/buildsystems/vcpkg.cmake" - CACHE STRING "Vcpkg toolchain file") -endif() +include(cmake/vcpkg.cmake) +include(cmake/qt.cmake) list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") include(utils) - -if(CMAKE_HOST_WIN32) - list(APPEND CMAKE_PREFIX_PATH "C:\\Qt\\6.6.2\\msvc2019_64") -elseif(CMAKE_HOST_APPLE) - -elseif(CMAKE_HOST_UNIX) - list(APPEND CMAKE_PREFIX_PATH "/opt/Qt/6.6.2/gcc_64") -endif() +include(qt_utils) project( Qt-Ffmpeg - VERSION 0.1 + VERSION 0.0.1 + DESCRIPTION "This is a Qt project for Ffmpeg" + HOMEPAGE_URL "https://github.com/RealChuan/Qt-Ffmpeg" LANGUAGES CXX) -set(CMAKE_AUTOUIC ON) -set(CMAKE_AUTOMOC ON) -set(CMAKE_AUTORCC ON) -# qt_standard_project_setup() 这个识别不了 - -set(CMAKE_EXPORT_COMPILE_COMMANDS ON) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) -set(CMAKE_CURRENT_SOURCE_DIR ON) - -set(CMAKE_CXX_STANDARD 17) -set(CMAKE_CXX_STANDARD_REQUIRED ON) - -set(CMAKE_DEBUG_POSTFIX d) - -if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) - message("Setting build type to 'RelWithDebInfo' as none was specified.") - set(CMAKE_BUILD_TYPE - RelWithDebInfo - CACHE STRING "Choose the type of build." FORCE) - # Set the possible values of build type for cmake-gui - set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release" - "MinSizeRel" "RelWithDebInfo") -endif() - -if(CMAKE_SIZEOF_VOID_P EQUAL 8) - set(CURRENT_PLATFORM "-64") -else() - set(CURRENT_PLATFORM "-32") -endif() - -message(STATUS "Current Platform is ${CURRENT_PLATFORM}") - -# 设定可执行二进制文件的目录 -set(EXECUTABLE_OUTPUT_PATH - ${PROJECT_SOURCE_DIR}/bin${CURRENT_PLATFORM}/${CMAKE_BUILD_TYPE}) # 源文件目录 -# 设定存放编译出来的库文件的目录 -set(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin${CURRENT_PLATFORM}/libs) -# 并且把该目录设为连接目录 -link_directories(${LIBRARY_OUTPUT_PATH}) - -include_directories(${PROJECT_SOURCE_DIR}) +include(cmake/common.cmake) find_package(Qt6 REQUIRED COMPONENTS Widgets Network Core5Compat Concurrent Multimedia OpenGLWidgets) +qt_standard_project_setup() +# qt_standard_project_setup will set CMAKE_RUNTIME_OUTPUT_DIRECTORY, we need to +# set it back, and use EXECUTABLE_OUTPUT_PATH +unset(CMAKE_RUNTIME_OUTPUT_DIRECTORY) + find_package(unofficial-breakpad CONFIG REQUIRED) if(unofficial-breakpad_FOUND) message(STATUS "found unofficial-breakpad") endif() +find_package(crashpad CONFIG REQUIRED) +if(crashpad_FOUND) + message(STATUS "found crashpad") +endif() find_package(PkgConfig REQUIRED) if(PkgConfig_FOUND) @@ -100,7 +52,7 @@ pkg_check_modules( libavutil) pkg_check_modules(ass REQUIRED IMPORTED_TARGET libass) -if(CMAKE_HOST_SYSTEM_NAME MATCHES "Linux") +if(CMAKE_HOST_LINUX) pkg_check_modules(fontconfig REQUIRED IMPORTED_TARGET fontconfig) find_package(expat CONFIG REQUIRED) if(expat_FOUND) @@ -152,8 +104,7 @@ if(CMAKE_HOST_APPLE) find_library(CoreServices_LIBRARY CoreServices) endif() -add_subdirectory(utils) -add_subdirectory(3rdparty) -add_subdirectory(ffmpeg) +include_directories(src) +add_subdirectory(src) add_subdirectory(tests) add_subdirectory(examples) diff --git a/Qt-Ffmpeg.pro b/Qt-Ffmpeg.pro index 7abb7f5..3358706 100644 --- a/Qt-Ffmpeg.pro +++ b/Qt-Ffmpeg.pro @@ -2,17 +2,12 @@ TEMPLATE = subdirs CONFIG += ordered SUBDIRS += \ - utils \ - 3rdparty \ - ffmpeg \ + src \ tests \ examples -TRANSLATIONS += \ - translations/language.zh_cn.ts \ - translations/language.zh_en.ts - DISTFILES += \ - $$files(docs/*.png)\ + doc/** \ + .clang* \ LICENSE \ - README.md + README* diff --git a/cmake/build_info.cmake b/cmake/build_info.cmake new file mode 100644 index 0000000..917befe --- /dev/null +++ b/cmake/build_info.cmake @@ -0,0 +1,22 @@ +# 输出 CMake 版本和构建系统类型 +message("CMake Version: ${CMAKE_VERSION}") +message("Generator: ${CMAKE_GENERATOR}") + +# 输出编译器信息 +message("C Compiler ID: ${CMAKE_C_COMPILER_ID}") +message("C++ Compiler ID: ${CMAKE_CXX_COMPILER_ID}") +message("C++ Compiler Version: ${CMAKE_CXX_COMPILER_VERSION}") + +# 输出构建类型和编译选项 +message("Build Type: ${CMAKE_BUILD_TYPE}") +message("C++ Compiler Flags: ${CMAKE_CXX_FLAGS}") + +# 输出链接选项 +message("Executable Linker Flags: ${CMAKE_EXE_LINKER_FLAGS}") + +# 输出构建和源代码目录 +message("Build Directory: ${CMAKE_BINARY_DIR}") +message("Source Directory: ${CMAKE_SOURCE_DIR}") + +# 输出目标架构 +message("Target Processor: ${CMAKE_SYSTEM_PROCESSOR}") diff --git a/cmake/common.cmake b/cmake/common.cmake new file mode 100644 index 0000000..ccfb15a --- /dev/null +++ b/cmake/common.cmake @@ -0,0 +1,37 @@ +if(CMAKE_HOST_APPLE) + set(CMAKE_OSX_DEPLOYMENT_TARGET + "11.0" + CACHE STRING "Minimum OS X version") +endif() + +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_EXPORT_COMPILE_COMMANDS ON) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) +set(CMAKE_DEBUG_POSTFIX d) + +if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) + message("Setting build type to 'RelWithDebInfo' as none was specified.") + set(CMAKE_BUILD_TYPE + RelWithDebInfo + CACHE STRING "Choose the type of build." FORCE) + # Set the possible values of build type for cmake-gui + set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release" + "MinSizeRel" "RelWithDebInfo") +endif() + +if(CMAKE_SIZEOF_VOID_P EQUAL 8) + set(BITS "64") +else() + set(BITS "32") +endif() + +message(STATUS "Current Platform is ${BITS} bits.") + +set(EXECUTABLE_OUTPUT_PATH + ${PROJECT_SOURCE_DIR}/bin-${BITS}/${CMAKE_BUILD_TYPE}) +set(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin-${BITS}/libs) +link_directories(${LIBRARY_OUTPUT_PATH}) + +include_directories(${PROJECT_SOURCE_DIR}) diff --git a/cmake/qt.cmake b/cmake/qt.cmake new file mode 100644 index 0000000..5a7f536 --- /dev/null +++ b/cmake/qt.cmake @@ -0,0 +1,7 @@ +if(CMAKE_HOST_WIN32) + list(APPEND CMAKE_PREFIX_PATH "C:\\Qt\\6.7.0\\msvc2019_64") +elseif(CMAKE_HOST_APPLE) + +elseif(CMAKE_HOST_LINUX) + list(APPEND CMAKE_PREFIX_PATH "/opt/Qt/6.7.0/gcc_64") +endif() diff --git a/cmake/qt_utils.cmake b/cmake/qt_utils.cmake new file mode 100644 index 0000000..ed9adf4 --- /dev/null +++ b/cmake/qt_utils.cmake @@ -0,0 +1,33 @@ +function(add_translations OUTPUT_NAME) + # 转换输出名称为小写 + string(TOLOWER ${OUTPUT_NAME} Lower_Output_Name) + + # 添加翻译文件 + qt_add_translations( + ${OUTPUT_NAME} + TS_FILE_BASE + ${Lower_Output_Name} + TS_FILE_DIR + translations + INCLUDE_DIRECTORIES + directory + ${PROJECT_SOURCE_DIR}/src) + + # 确定翻译文件的输出位置 + if(CMAKE_HOST_APPLE) + set(output_location + "${EXECUTABLE_OUTPUT_PATH}/${OUTPUT_NAME}.app/Contents/Resources/translations" + ) + else() + set(output_location "${EXECUTABLE_OUTPUT_PATH}/translations") + endif() + + # 查找所有的翻译文件(.ts) + file(GLOB_RECURSE TS_FILES "${PROJECT_SOURCE_DIR}/translations/*.ts") + + # 设置翻译文件的输出位置 + foreach(ts_file ${TS_FILES}) + set_source_files_properties("${ts_file}" PROPERTIES OUTPUT_LOCATION + "${output_location}") + endforeach() +endfunction() diff --git a/cmake/utils.cmake b/cmake/utils.cmake index d4f8bc3..01357ef 100644 --- a/cmake/utils.cmake +++ b/cmake/utils.cmake @@ -11,3 +11,35 @@ function(add_custom_library target_name) add_library(${target_name} ${ARGN}) endif() endfunction(add_custom_library) + +function(add_custom_plugin target_name) + add_library(${target_name} SHARED ${ARGN}) + add_custom_command( + TARGET ${target_name} + POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_if_different $ + ${EXECUTABLE_OUTPUT_PATH}/plugins/$ + ) + add_rpath(${target_name}) +endfunction(add_custom_plugin) + +function(add_share_library target_name) + add_library(${target_name} SHARED ${ARGN}) + add_custom_command( + TARGET ${target_name} + POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_if_different $ + ${EXECUTABLE_OUTPUT_PATH}/$) + add_rpath(${target_name}) +endfunction(add_share_library) + +function(add_rpath target_name) + if(CMAKE_HOST_APPLE) + set_target_properties( + ${target_name} + PROPERTIES LINK_FLAGS "-Wl,-rpath,./:./../Frameworks:./../../Frameworks") + elseif(CMAKE_HOST_LINUX) + set_target_properties(${target_name} + PROPERTIES LINK_FLAGS "-Wl,-rpath,./:./lib:./../lib") + endif() +endfunction() diff --git a/cmake/vcpkg.cmake b/cmake/vcpkg.cmake new file mode 100644 index 0000000..328f00f --- /dev/null +++ b/cmake/vcpkg.cmake @@ -0,0 +1,13 @@ +if(CMAKE_HOST_WIN32) + set(CMAKE_TOOLCHAIN_FILE + "C:/vcpkg/scripts/buildsystems/vcpkg.cmake" + CACHE STRING "Vcpkg toolchain file") +elseif(CMAKE_HOST_APPLE) + set(CMAKE_TOOLCHAIN_FILE + "/usr/local/share/vcpkg/scripts/buildsystems/vcpkg.cmake" + CACHE STRING "Vcpkg toolchain file") +elseif(CMAKE_HOST_LINUX) + set(CMAKE_TOOLCHAIN_FILE + "/usr/local/share/vcpkg/scripts/buildsystems/vcpkg.cmake" + CACHE STRING "Vcpkg toolchain file") +endif() diff --git a/Common.pri b/common.pri similarity index 54% rename from Common.pri rename to common.pri index 0514e8c..58deca2 100644 --- a/Common.pri +++ b/common.pri @@ -2,6 +2,14 @@ CONFIG += c++17 DEFINES += QT_DEPRECATED_WARNINGS +# add debug info +QMAKE_CXXFLAGS_RELEASE += $$QMAKE_CFLAGS_RELEASE_WITH_DEBUGINFO +QMAKE_LFLAGS_RELEASE += $$QMAKE_LFLAGS_RELEASE_WITH_DEBUGINFO + +# unix add rpath +macx:QMAKE_LFLAGS += "-Wl,-rpath,@executable_path:@executable_path/../Frameworks:@executable_path/../../Frameworks" +unix:!macx:QMAKE_LFLAGS += "-Wl,-rpath,\'\$$ORIGIN\':\'\$$ORIGIN/lib\':'\$$ORIGIN/../lib'" + contains(QT_ARCH, i386) { BIN = bin-32 }else{ @@ -14,31 +22,38 @@ CONFIG(debug, debug|release) { APP_OUTPUT_PATH = $$PWD/$$BIN/Release } -INCLUDEPATH += $$PWD/ -DEPENDPATH += $$PWD/ +INCLUDEPATH += \ + $$PWD \ + $$PWD/src/ +DEPENDPATH += \ + $$PWD \ + $$PWD/src/ + +LIBS += \ + -L$$APP_OUTPUT_PATH \ + -L$$APP_OUTPUT_PATH/../libs + +isEmpty(RC_LANG): RC_LANG = 0x0004 +isEmpty(VERSION): VERSION = 0.0.1.0 +CONFIG += skip_target_version_ext + +isEmpty(QMAKE_TARGET_COMPANY): QMAKE_TARGET_COMPANY = The Youth. +isEmpty(QMAKE_TARGET_DESCRIPTION): QMAKE_TARGET_DESCRIPTION = Qt-App +isEmpty(QMAKE_TARGET_COPYRIGHT): QMAKE_TARGET_COPYRIGHT = Copyright (C) 2017-2024 Youth. +isEmpty(QMAKE_TARGET_PRODUCT): QMAKE_TARGET_PRODUCT = Qt-App +isEmpty(QMAKE_TARGET_ORIGINAL_FILENAME): QMAKE_TARGET_ORIGINAL_FILENAME = Qt-App +isEmpty(QMAKE_TARGET_INTERNALNAME): QMAKE_TARGET_INTERNALNAME = Qt-App +isEmpty(QMAKE_TARGET_COMMENTS): QMAKE_TARGET_COMMENTS = Qt-App +isEmpty(QMAKE_TARGET_TRADEMARKS): QMAKE_TARGET_TRADEMARKS = Youth defineReplace(replaceLibName) { unset(LIBRARY_NAME) LIBRARY_NAME = $$1 CONFIG(debug, debug|release) { !debug_and_release|build_pass { - mac:RET = $$member(LIBRARY_NAME, 0)_debug - else:win32:RET = $$member(LIBRARY_NAME, 0)d + RET = $$member(LIBRARY_NAME, 0)d } } isEmpty(RET):RET = $$LIBRARY_NAME return($$RET) } - -isEmpty(RC_LANG): RC_LANG = 0x0004 -isEmpty(VERSION): VERSION = 0.0.0.1 -CONFIG += skip_target_version_ext - -isEmpty(QMAKE_TARGET_COMPANY): QMAKE_TARGET_COMPANY = The Youth. -isEmpty(QMAKE_TARGET_DESCRIPTION): QMAKE_TARGET_DESCRIPTION = Qt-Ffmpeg -isEmpty(QMAKE_TARGET_COPYRIGHT): QMAKE_TARGET_COPYRIGHT = Copyright (C) 2021 Youth. -isEmpty(QMAKE_TARGET_PRODUCT): QMAKE_TARGET_PRODUCT = Qt-Ffmpeg -isEmpty(QMAKE_TARGET_ORIGINAL_FILENAME): QMAKE_TARGET_ORIGINAL_FILENAME = Qt-Ffmpeg -isEmpty(QMAKE_TARGET_INTERNALNAME): QMAKE_TARGET_INTERNALNAME = Qt-Ffmpeg -isEmpty(QMAKE_TARGET_COMMENTS): QMAKE_TARGET_COMMENTS = Qt-Ffmpeg -isEmpty(QMAKE_TARGET_TRADEMARKS): QMAKE_TARGET_TRADEMARKS = Youth diff --git a/examples/appinfo.hpp b/examples/appinfo.hpp new file mode 100644 index 0000000..dc019b0 --- /dev/null +++ b/examples/appinfo.hpp @@ -0,0 +1,12 @@ +#pragma once + +#include + +namespace AppInfo { + +static const QVersionNumber version = QVersionNumber(0, 1, 1); +static const QString organzationName = "Youth"; +static const QString organizationDomain = "Youth"; +static const QString copyright = "Copyright 2017-2024 Youth. All rights reserved."; + +} // namespace AppInfo diff --git a/examples/player/CMakeLists.txt b/examples/player/CMakeLists.txt index c875166..223e9b9 100644 --- a/examples/player/CMakeLists.txt +++ b/examples/player/CMakeLists.txt @@ -23,8 +23,15 @@ set(PROJECT_SOURCES titlewidget.hpp) qt_add_executable(Player MANUAL_FINALIZATION ${PROJECT_SOURCES}) -target_link_libraries(Player PRIVATE ffmpeg thirdparty utils Qt6::Widgets - Qt6::Multimedia Qt6::OpenGLWidgets) +target_link_libraries( + Player + PRIVATE ffmpeg + thirdparty + dump + utils + Qt6::Widgets + Qt6::Multimedia + Qt6::OpenGLWidgets) target_link_libraries(Player PRIVATE PkgConfig::ffmpeg) if(CMAKE_HOST_APPLE) target_link_libraries( diff --git a/examples/player/main.cpp b/examples/player/main.cpp index acc1480..9ce9466 100644 --- a/examples/player/main.cpp +++ b/examples/player/main.cpp @@ -1,7 +1,8 @@ #include "mainwindow.h" -#include <3rdparty/breakpad.hpp> #include <3rdparty/qtsingleapplication/qtsingleapplication.h> +#include +#include #include #include #include @@ -15,12 +16,12 @@ void setAppInfo() { - qApp->setApplicationVersion("0.0.1"); + qApp->setApplicationVersion(AppInfo::version.toString()); qApp->setApplicationDisplayName(AppName); qApp->setApplicationName(AppName); qApp->setDesktopFileName(AppName); - qApp->setOrganizationDomain("Youth"); - qApp->setOrganizationName("Youth"); + qApp->setOrganizationDomain(AppInfo::organizationDomain); + qApp->setOrganizationName(AppInfo::organzationName); qApp->setWindowIcon(qApp->style()->standardIcon(QStyle::SP_MediaPlay)); } @@ -45,11 +46,13 @@ auto main(int argc, char *argv[]) -> int return EXIT_SUCCESS; } } + #ifndef Q_OS_WIN Q_INIT_RESOURCE(shaders); #endif + #ifdef Q_OS_WIN - if (!qFuzzyCompare(qApp->devicePixelRatio(), 1.0) + if (!qFuzzyCompare(app.devicePixelRatio(), 1.0) && QApplication::style()->objectName().startsWith(QLatin1String("windows"), Qt::CaseInsensitive)) { QApplication::setStyle(QLatin1String("fusion")); @@ -59,21 +62,19 @@ auto main(int argc, char *argv[]) -> int app.setAttribute(Qt::AA_UseHighDpiPixmaps); app.setAttribute(Qt::AA_DisableWindowContextHelpButton); #endif - - Utils::BreakPad::instance(); + setAppInfo(); + Dump::BreakPad::instance()->setDumpPath(Utils::crashPath()); QDir::setCurrent(app.applicationDirPath()); // 异步日志 - Utils::LogAsync *log = Utils::LogAsync::instance(); + auto *log = Utils::LogAsync::instance(); + log->setLogPath(Utils::logPath()); + log->setAutoDelFile(true); + log->setAutoDelFileDays(7); log->setOrientation(Utils::LogAsync::Orientation::StdAndFile); log->setLogLevel(QtDebugMsg); log->startWork(); - Utils::printBuildInfo(); - Utils::setGlobalThreadPoolMaxSize(); - - setAppInfo(); - // Make sure we honor the system's proxy settings QNetworkProxyFactory::setUseSystemConfiguration(true); diff --git a/examples/player/player.pro b/examples/player/player.pro index a923210..2ba417b 100644 --- a/examples/player/player.pro +++ b/examples/player/player.pro @@ -1,4 +1,4 @@ -include(../../Common.pri) +include(../../common.pri) QT += core gui widgets network multimedia openglwidgets core5compat @@ -7,12 +7,12 @@ TEMPLATE = app TARGET = Player LIBS += \ - -L$$APP_OUTPUT_PATH/../libs \ -l$$replaceLibName(ffmpeg) \ -l$$replaceLibName(thirdparty) \ + -l$$replaceLibName(dump) \ -l$$replaceLibName(utils) -include(../../3rdparty/3rdparty.pri) +include(../../src/3rdparty/3rdparty.pri) SOURCES += \ colorspacedialog.cc \ diff --git a/examples/transcoder/CMakeLists.txt b/examples/transcoder/CMakeLists.txt index ab58140..2e2b869 100644 --- a/examples/transcoder/CMakeLists.txt +++ b/examples/transcoder/CMakeLists.txt @@ -30,8 +30,15 @@ set(PROJECT_SOURCES videoencoderwidget.hpp) qt_add_executable(Transcoder MANUAL_FINALIZATION ${PROJECT_SOURCES}) -target_link_libraries(Transcoder PRIVATE ffmpeg thirdparty utils Qt6::Widgets - Qt6::Multimedia Qt6::OpenGLWidgets) +target_link_libraries( + Transcoder + PRIVATE ffmpeg + thirdparty + dump + utils + Qt6::Widgets + Qt6::Multimedia + Qt6::OpenGLWidgets) target_link_libraries(Transcoder PRIVATE PkgConfig::ffmpeg) if(CMAKE_HOST_APPLE) diff --git a/examples/transcoder/main.cc b/examples/transcoder/main.cc index ad22f24..fdde155 100644 --- a/examples/transcoder/main.cc +++ b/examples/transcoder/main.cc @@ -1,7 +1,8 @@ #include "mainwindow.hpp" -#include <3rdparty/breakpad.hpp> #include <3rdparty/qtsingleapplication/qtsingleapplication.h> +#include +#include #include #include @@ -10,16 +11,16 @@ #include #include -#define AppnName "Transcoder" +#define AppName "Transcoder" void setAppInfo() { - qApp->setApplicationVersion("0.0.1"); - qApp->setApplicationDisplayName(AppnName); - qApp->setApplicationName(AppnName); - qApp->setDesktopFileName(AppnName); - qApp->setOrganizationDomain("Youth"); - qApp->setOrganizationName("Youth"); + qApp->setApplicationVersion(AppInfo::version.toString()); + qApp->setApplicationDisplayName(AppName); + qApp->setApplicationName(AppName); + qApp->setDesktopFileName(AppName); + qApp->setOrganizationDomain(AppInfo::organizationDomain); + qApp->setOrganizationName(AppInfo::organzationName); qApp->setWindowIcon(qApp->style()->standardIcon(QStyle::SP_DriveDVDIcon)); } @@ -34,7 +35,7 @@ auto main(int argc, char *argv[]) -> int #endif Utils::setHighDpiEnvironmentVariable(); SharedTools::QtSingleApplication::setAttribute(Qt::AA_ShareOpenGLContexts); - SharedTools::QtSingleApplication app(AppnName, argc, argv); + SharedTools::QtSingleApplication app(AppName, argc, argv); if (app.isRunning()) { qWarning() << "This is already running"; if (app.sendMessage("raise_window_noop", 5000)) { @@ -45,7 +46,7 @@ auto main(int argc, char *argv[]) -> int Q_INIT_RESOURCE(shaders); #endif #ifdef Q_OS_WIN - if (!qFuzzyCompare(qApp->devicePixelRatio(), 1.0) + if (!qFuzzyCompare(app.devicePixelRatio(), 1.0) && QApplication::style()->objectName().startsWith(QLatin1String("windows"), Qt::CaseInsensitive)) { QApplication::setStyle(QLatin1String("fusion")); @@ -56,20 +57,19 @@ auto main(int argc, char *argv[]) -> int app.setAttribute(Qt::AA_DisableWindowContextHelpButton); #endif - Utils::BreakPad::instance(); + setAppInfo(); + Dump::BreakPad::instance()->setDumpPath(Utils::crashPath()); QDir::setCurrent(app.applicationDirPath()); // 异步日志 - Utils::LogAsync *log = Utils::LogAsync::instance(); + auto *log = Utils::LogAsync::instance(); + log->setLogPath(Utils::logPath()); + log->setAutoDelFile(true); + log->setAutoDelFileDays(7); log->setOrientation(Utils::LogAsync::Orientation::StdAndFile); log->setLogLevel(QtDebugMsg); log->startWork(); - Utils::printBuildInfo(); - Utils::setGlobalThreadPoolMaxSize(); - - setAppInfo(); - // Make sure we honor the system's proxy settings QNetworkProxyFactory::setUseSystemConfiguration(true); diff --git a/examples/transcoder/transcoder.pro b/examples/transcoder/transcoder.pro index e45d6d7..a5666a5 100644 --- a/examples/transcoder/transcoder.pro +++ b/examples/transcoder/transcoder.pro @@ -1,4 +1,4 @@ -include(../../Common.pri) +include(../../common.pri) QT += core gui widgets network multimedia openglwidgets core5compat @@ -7,12 +7,12 @@ TEMPLATE = app TARGET = Transcoder LIBS += \ - -L$$APP_OUTPUT_PATH/../libs \ -l$$replaceLibName(ffmpeg) \ -l$$replaceLibName(thirdparty) \ + -l$$replaceLibName(dump) \ -l$$replaceLibName(utils) -include(../../3rdparty/3rdparty.pri) +include(../../src/3rdparty/3rdparty.pri) SOURCES += \ audioencodermodel.cc \ diff --git a/scripts/windows/setVsDev.ps1 b/scripts/windows/setVsDev.ps1 new file mode 100644 index 0000000..c7928f7 --- /dev/null +++ b/scripts/windows/setVsDev.ps1 @@ -0,0 +1,62 @@ +param( + [Parameter(Mandatory = $false)] + [string]$VersionRange, + [Parameter(Mandatory = $false)] + [string]$Arch +) + + +$vswhereArgs = @() + +if ($VersionRange) { + $vswhereArgs += "-version" + $vswhereArgs += $VersionRange +} +else { + $vswhereArgs += "-latest" +} + + +$vswhereArgs += "-property" +$vswhereArgs += "installationPath" + +if ([string]::IsNullOrEmpty($Arch)) { + $Arch = "x64" +} + +Write-Host "Architecture: $Arch" +Write-Host "VSWhere Args: $vswhereArgs" + +# 使用 vswhere 获取 Visual Studio 的安装路径 +$vswherePath = "C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe" +$vsInstallPath = & $vswherePath $vswhereArgs | ForEach-Object { $_ } +# Output the results +Write-Host "Visual Studio installation paths:" +$vsInstallPath + +if ($null -ne $vsInstallPath) { + $vsDevShell = Join-Path $vsInstallPath "Common7\Tools\Microsoft.VisualStudio.DevShell.dll" + if (-not (Test-Path $vsDevShell)) { + Write-Host "Failed to find Visual Studio DevShell DLL: $vsDevShell" + exit 1 + } + Import-Module $vsDevShell + Enter-VsDevShell -VsInstallPath $vsInstallPath -DevCmdArguments "-arch=$Arch -host_arch=$Arch" -SkipAutomaticLocation + + if ($LASTEXITCODE -eq 0) { + Write-Host "Development environment set up successfully." + } + else { + Write-Host "Failed to set up the development environment." + } +} +else { + Write-Host "Using Custom Visual Studio installation path." + $vsInstallPath = "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise" + if (-not (Test-Path $vsInstallPath)) { + $vsInstallPath = "C:\Program Files (x86)\Microsoft Visual Studio\2022\Enterprise" + } + $vsDevShell = Join-Path $vsInstallPath "Common7\Tools\Microsoft.VisualStudio.DevShell.dll" + Import-Module $vsDevShell + Enter-VsDevShell -VsInstallPath $vsInstallPath -DevCmdArguments "-arch=x64 -host_arch=x64" -SkipAutomaticLocation +} \ No newline at end of file diff --git a/src/3rdparty/3rdparty.pri b/src/3rdparty/3rdparty.pri new file mode 100644 index 0000000..b0fcc8f --- /dev/null +++ b/src/3rdparty/3rdparty.pri @@ -0,0 +1,96 @@ +win32{ + contains(QT_ARCH, i386) { + vcpkg_path = C:/vcpkg/installed/x86-windows + } else:contains(QT_ARCH, arm64) { + vcpkg_path = C:/vcpkg/installed/arm64-windows + } else { + vcpkg_path = C:/vcpkg/installed/x64-windows + } +} + +macx{ + contains(QMAKE_APPLE_DEVICE_ARCHS, arm64) { + vcpkg_path = /usr/local/share/vcpkg/installed/arm64-osx + } else { + vcpkg_path = /usr/local/share/vcpkg/installed/x64-osx + } +} + +unix:!macx{ + contains(QT_ARCH, arm64) { + vcpkg_path = /usr/local/share/vcpkg/installed/arm64-linux + }else{ + vcpkg_path = /usr/local/share/vcpkg/installed/x64-linux + } +} + +message("QT_ARCH: "$$QT_ARCH) +message("vcpkg_path: "$$vcpkg_path) + +CONFIG(debug, debug|release) { + LIBS += -L$$vcpkg_path/debug/lib \ + -llibbreakpad_clientd -llibbreakpadd +}else{ + LIBS += -L$$vcpkg_path/lib \ + -llibbreakpad_client -llibbreakpad +} + +LIBS += -lcommon -lclient -lutil -lbase + +LIBS += -lavdevice -lavfilter -lavformat -lavcodec -lswresample -lswscale -lavutil \ + -lass -lharfbuzz -lfribidi + +win32{ + CONFIG(debug, debug|release) { + LIBS += -lfreetyped -llibpng16d -lzlibd -lbz2d -lbrotlidec -lbrotlienc -lbrotlicommon + }else{ + LIBS += -lfreetype -llibpng16 -lzlib -lbz2 -lbrotlidec -lbrotlienc -lbrotlicommon + } + + DEFINES += NOMINMAX + LIBS += -lAdvapi32 +} + +unix:!macx{ + LIBS += -lfontconfig -lexpat +} + +unix{ + CONFIG(debug, debug|release) { + LIBS += -lfreetyped -lpng -lz -lbz2d + }else{ + LIBS += -lfreetype -lpng -lz -lbz2 + } + + LIBS += -lbrotlidec -lbrotlicommon +} + +INCLUDEPATH += \ + $$vcpkg_path/include \ + $$vcpkg_path/include/crashpad + +macx{ + LIBS += \ + -lbsm \ + -lmig_output + + LIBS += \ + -framework Foundation \ + -framework CoreAudio \ + -framework AVFoundation \ + -framework CoreGraphics \ + -framework OpenGL \ + -framework CoreText \ + -framework CoreImage \ + -framework AppKit \ + -framework Security \ + -framework AudioToolBox \ + -framework VideoToolBox \ + -framework CoreFoundation \ + -framework CoreMedia \ + -framework CoreVideo \ + -framework CoreServices + # -framework QuartzCore \ + # -framework Cocoa \ + # -framework VideoDecodeAcceleration +} diff --git a/3rdparty/3rdparty.pro b/src/3rdparty/3rdparty.pro similarity index 62% rename from 3rdparty/3rdparty.pro rename to src/3rdparty/3rdparty.pro index 8c747cc..36de8bc 100644 --- a/3rdparty/3rdparty.pro +++ b/src/3rdparty/3rdparty.pro @@ -1,5 +1,5 @@ include(3rdparty.pri) -include(../libs.pri) +include(../slib.pri) include(qtsingleapplication/qtsingleapplication.pri) DEFINES += THRIDPARTY_LIBRARY @@ -7,9 +7,4 @@ TARGET = $$replaceLibName(thirdparty) LIBS += -l$$replaceLibName(utils) -HEADERS += \ - breakpad.hpp \ - thirdparty_global.hpp - -SOURCES += \ - breakpad.cc +HEADERS += thirdparty_global.hpp diff --git a/3rdparty/CMakeLists.txt b/src/3rdparty/CMakeLists.txt similarity index 63% rename from 3rdparty/CMakeLists.txt rename to src/3rdparty/CMakeLists.txt index f5bd6d7..b315c08 100644 --- a/3rdparty/CMakeLists.txt +++ b/src/3rdparty/CMakeLists.txt @@ -5,16 +5,11 @@ set(PROJECT_SOURCES qtsingleapplication/qtsingleapplication.h qtsingleapplication/qtlocalpeer.cpp qtsingleapplication/qtlocalpeer.h - breakpad.cc - breakpad.hpp thirdparty_global.hpp) add_custom_library(thirdparty ${PROJECT_SOURCES}) -target_link_libraries( - thirdparty - PRIVATE shared_qtlockedfile utils Qt6::Network Qt6::Widgets - unofficial::breakpad::libbreakpad - unofficial::breakpad::libbreakpad_client) +target_link_libraries(thirdparty PRIVATE shared_qtlockedfile Qt6::Network + Qt6::Widgets) if(CMAKE_HOST_WIN32) target_compile_definitions(thirdparty PRIVATE "THRIDPARTY_LIBRARY") diff --git a/3rdparty/qtlockedfile/CMakeLists.txt b/src/3rdparty/qtlockedfile/CMakeLists.txt similarity index 100% rename from 3rdparty/qtlockedfile/CMakeLists.txt rename to src/3rdparty/qtlockedfile/CMakeLists.txt diff --git a/3rdparty/qtlockedfile/README.txt b/src/3rdparty/qtlockedfile/README.txt similarity index 100% rename from 3rdparty/qtlockedfile/README.txt rename to src/3rdparty/qtlockedfile/README.txt diff --git a/3rdparty/qtlockedfile/namespace.patch b/src/3rdparty/qtlockedfile/namespace.patch similarity index 100% rename from 3rdparty/qtlockedfile/namespace.patch rename to src/3rdparty/qtlockedfile/namespace.patch diff --git a/3rdparty/qtlockedfile/qtlockedfile.cpp b/src/3rdparty/qtlockedfile/qtlockedfile.cpp similarity index 97% rename from 3rdparty/qtlockedfile/qtlockedfile.cpp rename to src/3rdparty/qtlockedfile/qtlockedfile.cpp index bf181a9..87e79e4 100644 --- a/3rdparty/qtlockedfile/qtlockedfile.cpp +++ b/src/3rdparty/qtlockedfile/qtlockedfile.cpp @@ -98,7 +98,7 @@ QtLockedFile::QtLockedFile(const QString &name) \sa lockMode() */ -bool QtLockedFile::isLocked() const +auto QtLockedFile::isLocked() const -> bool { return m_lock_mode != NoLock; } @@ -108,7 +108,7 @@ bool QtLockedFile::isLocked() const \sa isLocked() */ -QtLockedFile::LockMode QtLockedFile::lockMode() const +auto QtLockedFile::lockMode() const -> QtLockedFile::LockMode { return m_lock_mode; } diff --git a/3rdparty/qtlockedfile/qtlockedfile.h b/src/3rdparty/qtlockedfile/qtlockedfile.h similarity index 88% rename from 3rdparty/qtlockedfile/qtlockedfile.h rename to src/3rdparty/qtlockedfile/qtlockedfile.h index 52dfef6..9f0e0f0 100644 --- a/3rdparty/qtlockedfile/qtlockedfile.h +++ b/src/3rdparty/qtlockedfile/qtlockedfile.h @@ -51,13 +51,13 @@ class QT_QTLOCKEDFILE_EXPORT QtLockedFile : public QFile enum LockMode { NoLock = 0, ReadLock, WriteLock }; QtLockedFile(); - QtLockedFile(const QString &name); - ~QtLockedFile(); + explicit QtLockedFile(const QString &name); + ~QtLockedFile() override; - bool lock(LockMode mode, bool block = true); - bool unlock(); - bool isLocked() const; - LockMode lockMode() const; + auto lock(LockMode mode, bool block = true) -> bool; + auto unlock() -> bool; + [[nodiscard]] auto isLocked() const -> bool; + [[nodiscard]] auto lockMode() const -> LockMode; private: #ifdef Q_OS_WIN diff --git a/3rdparty/qtlockedfile/qtlockedfile.pri b/src/3rdparty/qtlockedfile/qtlockedfile.pri similarity index 100% rename from 3rdparty/qtlockedfile/qtlockedfile.pri rename to src/3rdparty/qtlockedfile/qtlockedfile.pri diff --git a/3rdparty/qtlockedfile/qtlockedfile_unix.cpp b/src/3rdparty/qtlockedfile/qtlockedfile_unix.cpp similarity index 100% rename from 3rdparty/qtlockedfile/qtlockedfile_unix.cpp rename to src/3rdparty/qtlockedfile/qtlockedfile_unix.cpp diff --git a/3rdparty/qtlockedfile/qtlockedfile_win.cpp b/src/3rdparty/qtlockedfile/qtlockedfile_win.cpp similarity index 97% rename from 3rdparty/qtlockedfile/qtlockedfile_win.cpp rename to src/3rdparty/qtlockedfile/qtlockedfile_win.cpp index 0ad8f71..ef9198b 100644 --- a/3rdparty/qtlockedfile/qtlockedfile_win.cpp +++ b/src/3rdparty/qtlockedfile/qtlockedfile_win.cpp @@ -34,7 +34,7 @@ namespace SharedTools { #define MUTEX_PREFIX "QtLockedFile mutex " #define SEMAPHORE_MAX 100 -static QString errorCodeToString(DWORD errorCode) +static auto errorCodeToString(DWORD errorCode) -> QString { QString result; char *data = 0; @@ -51,7 +51,7 @@ static QString errorCodeToString(DWORD errorCode) return result; } -bool QtLockedFile::lock(LockMode mode, bool block) +auto QtLockedFile::lock(LockMode mode, bool block) -> bool { if (!isOpen()) { qWarning("QtLockedFile::lock(): file is not opened"); @@ -112,7 +112,7 @@ bool QtLockedFile::lock(LockMode mode, bool block) for (int i = 0; i < decrement; ++i) { DWORD res = WaitForSingleObject(m_semaphore_hnd, block ? INFINITE : 0); if (res == WAIT_TIMEOUT) { - if (i) { + if (i != 0) { // A failed nonblocking rw locking. Undo changes to semaphore. if (ReleaseSemaphore(m_semaphore_hnd, i, NULL) == 0) { qWarning("QtLockedFile::unlock(): ReleaseSemaphore: %s", @@ -139,7 +139,7 @@ bool QtLockedFile::lock(LockMode mode, bool block) return true; } -bool QtLockedFile::unlock() +auto QtLockedFile::unlock() -> bool { if (!isOpen()) { qWarning("QtLockedFile::unlock(): file is not opened"); diff --git a/3rdparty/qtsingleapplication/CMakeLists.txt b/src/3rdparty/qtsingleapplication/CMakeLists.txt similarity index 100% rename from 3rdparty/qtsingleapplication/CMakeLists.txt rename to src/3rdparty/qtsingleapplication/CMakeLists.txt diff --git a/3rdparty/qtsingleapplication/README.txt b/src/3rdparty/qtsingleapplication/README.txt similarity index 100% rename from 3rdparty/qtsingleapplication/README.txt rename to src/3rdparty/qtsingleapplication/README.txt diff --git a/3rdparty/qtsingleapplication/namespace.patch b/src/3rdparty/qtsingleapplication/namespace.patch similarity index 100% rename from 3rdparty/qtsingleapplication/namespace.patch rename to src/3rdparty/qtsingleapplication/namespace.patch diff --git a/3rdparty/qtsingleapplication/qtlocalpeer.cpp b/src/3rdparty/qtsingleapplication/qtlocalpeer.cpp similarity index 93% rename from 3rdparty/qtsingleapplication/qtlocalpeer.cpp rename to src/3rdparty/qtsingleapplication/qtlocalpeer.cpp index df66d5d..6210f75 100644 --- a/3rdparty/qtsingleapplication/qtlocalpeer.cpp +++ b/src/3rdparty/qtsingleapplication/qtlocalpeer.cpp @@ -45,7 +45,7 @@ namespace SharedTools { static const char ack[] = "ack"; -QString QtLocalPeer::appSessionId(const QString &appId) +auto QtLocalPeer::appSessionId(const QString &appId) -> QString { QByteArray idc = appId.toUtf8(); #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) @@ -59,11 +59,11 @@ QString QtLocalPeer::appSessionId(const QString &appId) QString res = QLatin1String("qtsingleapplication-") + QString::number(idNum, 16); #if defined(Q_OS_WIN) - if (!pProcessIdToSessionId) { + if (pProcessIdToSessionId == nullptr) { QLibrary lib(QLatin1String("kernel32")); pProcessIdToSessionId = (PProcessIdToSessionId)lib.resolve("ProcessIdToSessionId"); } - if (pProcessIdToSessionId) { + if (pProcessIdToSessionId != nullptr) { DWORD sessionId = 0; pProcessIdToSessionId(GetCurrentProcessId(), &sessionId); res += QLatin1Char('-') + QString::number(sessionId, 16); @@ -89,7 +89,7 @@ QtLocalPeer::QtLocalPeer(QObject *parent, const QString &appId) lockFile.open(QIODevice::ReadWrite); } -bool QtLocalPeer::isClient() +auto QtLocalPeer::isClient() -> bool { if (lockFile.isLocked()) return false; @@ -106,7 +106,7 @@ bool QtLocalPeer::isClient() return false; } -bool QtLocalPeer::sendMessage(const QString &message, int timeout, bool block) +auto QtLocalPeer::sendMessage(const QString &message, int timeout, bool block) -> bool { if (!isClient()) return false; @@ -117,7 +117,7 @@ bool QtLocalPeer::sendMessage(const QString &message, int timeout, bool block) // Try twice, in case the other instance is just starting up socket.connectToServer(socketName); connOk = socket.waitForConnected(timeout/2); - if (connOk || i) + if (connOk || (i != 0)) break; int ms = 250; #if defined(Q_OS_WIN) @@ -144,7 +144,7 @@ bool QtLocalPeer::sendMessage(const QString &message, int timeout, bool block) void QtLocalPeer::receiveConnection() { QLocalSocket* socket = server->nextPendingConnection(); - if (!socket) + if (socket == nullptr) return; // Why doesn't Qt have a blocking stream that takes care of this shait??? @@ -166,7 +166,7 @@ void QtLocalPeer::receiveConnection() remaining -= got; uMsgBuf += got; //qDebug() << "RCV: got" << got << "remaining" << remaining; - } while (remaining && got >= 0 && socket->waitForReadyRead(2000)); + } while ((remaining != 0u) && got >= 0 && socket->waitForReadyRead(2000)); //### error check: got<0 if (got < 0) { qWarning() << "QtLocalPeer: Message reception failed" << socket->errorString(); diff --git a/3rdparty/qtsingleapplication/qtlocalpeer.h b/src/3rdparty/qtsingleapplication/qtlocalpeer.h similarity index 88% rename from 3rdparty/qtsingleapplication/qtlocalpeer.h rename to src/3rdparty/qtsingleapplication/qtlocalpeer.h index fa57241..03ba950 100644 --- a/3rdparty/qtsingleapplication/qtlocalpeer.h +++ b/src/3rdparty/qtsingleapplication/qtlocalpeer.h @@ -37,11 +37,11 @@ class QtLocalPeer : public QObject public: explicit QtLocalPeer(QObject *parent = 0, const QString &appId = QString()); - bool isClient(); - bool sendMessage(const QString &message, int timeout, bool block); - QString applicationId() const + auto isClient() -> bool; + auto sendMessage(const QString &message, int timeout, bool block) -> bool; + [[nodiscard]] auto applicationId() const -> QString { return id; } - static QString appSessionId(const QString &appId); + static auto appSessionId(const QString &appId) -> QString; Q_SIGNALS: void messageReceived(const QString &message, QObject *socket); diff --git a/3rdparty/qtsingleapplication/qtsingleapplication.cpp b/src/3rdparty/qtsingleapplication/qtsingleapplication.cpp similarity index 90% rename from 3rdparty/qtsingleapplication/qtsingleapplication.cpp rename to src/3rdparty/qtsingleapplication/qtsingleapplication.cpp index 2d90ea1..d486b91 100644 --- a/3rdparty/qtsingleapplication/qtsingleapplication.cpp +++ b/src/3rdparty/qtsingleapplication/qtsingleapplication.cpp @@ -37,7 +37,7 @@ namespace SharedTools { static const int instancesSize = 1024; -static QString instancesLockFilename(const QString &appSessionId) +static auto instancesLockFilename(const QString &appSessionId) -> QString { const QChar slash(QLatin1Char('/')); QString res = QDir::tempPath(); @@ -81,7 +81,7 @@ QtSingleApplication::QtSingleApplication(const QString &appId, int &argc, char * if (!created) { // Find the first instance that it still running // The whole list needs to be iterated in order to append to it - for (; *pids; ++pids) { + for (; *pids != 0; ++pids) { if (firstPeer == -1 && isRunning(*pids)) firstPeer = *pids; } @@ -98,7 +98,7 @@ QtSingleApplication::QtSingleApplication(const QString &appId, int &argc, char * QtSingleApplication::~QtSingleApplication() { - if (!instances) + if (instances == nullptr) return; const qint64 appPid = QCoreApplication::applicationPid(); QtLockedFile lockfile(instancesLockFilename(QtLocalPeer::appSessionId(appId))); @@ -107,7 +107,7 @@ QtSingleApplication::~QtSingleApplication() // Rewrite array, removing current pid and previously crashed ones qint64 *pids = static_cast(instances->data()); qint64 *newpids = pids; - for (; *pids; ++pids) { + for (; *pids != 0; ++pids) { if (*pids != appPid && isRunning(*pids)) *newpids++ = *pids; } @@ -115,7 +115,7 @@ QtSingleApplication::~QtSingleApplication() lockfile.unlock(); } -bool QtSingleApplication::event(QEvent *event) +auto QtSingleApplication::event(QEvent *event) -> bool { if (event->type() == QEvent::FileOpen) { QFileOpenEvent *foe = static_cast(event); @@ -125,7 +125,7 @@ bool QtSingleApplication::event(QEvent *event) return QApplication::event(event); } -bool QtSingleApplication::isRunning(qint64 pid) +auto QtSingleApplication::isRunning(qint64 pid) -> bool { if (pid == -1) { pid = firstPeer; @@ -137,7 +137,7 @@ bool QtSingleApplication::isRunning(qint64 pid) return peer.isClient(); } -bool QtSingleApplication::sendMessage(const QString &message, int timeout, qint64 pid) +auto QtSingleApplication::sendMessage(const QString &message, int timeout, qint64 pid) -> bool { if (pid == -1) { pid = firstPeer; @@ -149,7 +149,7 @@ bool QtSingleApplication::sendMessage(const QString &message, int timeout, qint6 return peer.sendMessage(message, timeout, block); } -QString QtSingleApplication::applicationId() const +auto QtSingleApplication::applicationId() const -> QString { return appId; } @@ -162,7 +162,7 @@ void QtSingleApplication::setBlock(bool value) void QtSingleApplication::setActivationWindow(QWidget *aw, bool activateOnMessage) { actWin = aw; - if (!pidPeer) + if (pidPeer == nullptr) return; if (activateOnMessage) connect(pidPeer, &QtLocalPeer::messageReceived, this, &QtSingleApplication::activateWindow); @@ -171,7 +171,7 @@ void QtSingleApplication::setActivationWindow(QWidget *aw, bool activateOnMessag } -QWidget* QtSingleApplication::activationWindow() const +auto QtSingleApplication::activationWindow() const -> QWidget* { return actWin; } @@ -179,7 +179,7 @@ QWidget* QtSingleApplication::activationWindow() const void QtSingleApplication::activateWindow() { - if (actWin) { + if (actWin != nullptr) { actWin->setWindowState(actWin->windowState() & ~Qt::WindowMinimized); actWin->raise(); actWin->activateWindow(); diff --git a/3rdparty/qtsingleapplication/qtsingleapplication.h b/src/3rdparty/qtsingleapplication/qtsingleapplication.h similarity index 100% rename from 3rdparty/qtsingleapplication/qtsingleapplication.h rename to src/3rdparty/qtsingleapplication/qtsingleapplication.h diff --git a/3rdparty/qtsingleapplication/qtsingleapplication.pri b/src/3rdparty/qtsingleapplication/qtsingleapplication.pri similarity index 100% rename from 3rdparty/qtsingleapplication/qtsingleapplication.pri rename to src/3rdparty/qtsingleapplication/qtsingleapplication.pri diff --git a/3rdparty/thirdparty_global.hpp b/src/3rdparty/thirdparty_global.hpp similarity index 100% rename from 3rdparty/thirdparty_global.hpp rename to src/3rdparty/thirdparty_global.hpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt new file mode 100644 index 0000000..467ab46 --- /dev/null +++ b/src/CMakeLists.txt @@ -0,0 +1,4 @@ +add_subdirectory(utils) +add_subdirectory(dump) +add_subdirectory(3rdparty) +add_subdirectory(ffmpeg) diff --git a/src/dump/CMakeLists.txt b/src/dump/CMakeLists.txt new file mode 100644 index 0000000..ee32b6f --- /dev/null +++ b/src/dump/CMakeLists.txt @@ -0,0 +1,10 @@ +set(PROJECT_SOURCES breakpad.hpp breakpad.cc crashpad.hpp crashpad.cc + dump_global.hpp) +add_custom_library(dump ${PROJECT_SOURCES}) +target_link_libraries( + dump PRIVATE utils Qt6::Widgets unofficial::breakpad::libbreakpad + unofficial::breakpad::libbreakpad_client crashpad::crashpad) + +if(CMAKE_HOST_WIN32) + target_compile_definitions(dump PRIVATE "DUMP_LIBRARY") +endif() diff --git a/3rdparty/breakpad.cc b/src/dump/breakpad.cc similarity index 65% rename from 3rdparty/breakpad.cc rename to src/dump/breakpad.cc index e463e92..36537c3 100644 --- a/3rdparty/breakpad.cc +++ b/src/dump/breakpad.cc @@ -19,45 +19,16 @@ #define CrashReportName "CrashReport" #endif -namespace Utils { - -QString getCrashPath() -{ - const QString path = Utils::getConfigPath() + "/crashes"; - Utils::generateDirectorys(path); - return QDir::toNativeSeparators(path); -} - -void createEnvironment() -{ - const auto strTime = QDateTime::currentDateTime().toString("yyyy-MM-dd-HH-mm-ss-zzz"); - const auto path = QString("%1/crashes/%2-System Environment.txt") - .arg(Utils::getConfigPath(), strTime); - - QFile file(path); - if (file.open(QIODevice::WriteOnly | QIODevice::Text)) { - auto systemEnviroment = QProcess::systemEnvironment(); - QString str; - for (const QString &info : std::as_const(systemEnviroment)) { - str += info; - str += '\n'; - } - file.write(str.toUtf8()); - file.flush(); - file.close(); - } else { - qWarning() << file.errorString(); - } -} +namespace Dump { // 程序崩溃回调函数; #if defined(Q_OS_WIN) -bool callback(const wchar_t *dump_path, +auto callback(const wchar_t *dump_path, const wchar_t *id, - void *, - EXCEPTION_POINTERS *, - MDRawAssertionInfo *, - bool succeeded) + void * /*unused*/, + EXCEPTION_POINTERS * /*unused*/, + MDRawAssertionInfo * /*unused*/, + bool succeeded) -> bool { if (succeeded) { qInfo() << "Create dump file success:" << QString::fromWCharArray(dump_path) @@ -93,19 +64,24 @@ bool callback(const google_breakpad::MinidumpDescriptor &descriptor, void *conte } #endif -struct BreakPad::BreakPadPrivate +class BreakPad::BreakPadPrivate { - BreakPadPrivate() +public: + explicit BreakPadPrivate(BreakPad *q) + : q_ptr(q) + {} + + void setDumpPath(const QString &path) { #if defined(Q_OS_WIN) exceptionHandlerPtr.reset( - new google_breakpad::ExceptionHandler(getCrashPath().toStdWString(), + new google_breakpad::ExceptionHandler(path.toStdWString(), nullptr, callback, nullptr, google_breakpad::ExceptionHandler::HANDLER_ALL)); #elif defined(Q_OS_MAC) - exceptionHandlerPtr.reset(new google_breakpad::ExceptionHandler(getCrashPath().toStdString(), + exceptionHandlerPtr.reset(new google_breakpad::ExceptionHandler(path.toStdString(), nullptr, callback, nullptr, @@ -114,7 +90,7 @@ struct BreakPad::BreakPadPrivate #elif defined(Q_OS_LINUX) exceptionHandlerPtr.reset( new google_breakpad::ExceptionHandler(google_breakpad::MinidumpDescriptor( - getCrashPath().toStdString()), + path.toStdString()), nullptr, callback, nullptr, @@ -122,40 +98,32 @@ struct BreakPad::BreakPadPrivate -1)); #endif } - ~BreakPadPrivate() {} + + ~BreakPadPrivate() = default; + + BreakPad *q_ptr; QScopedPointer exceptionHandlerPtr; }; -BreakPad *BreakPad::instance() +void BreakPad::setDumpPath(const QString &path) { - static BreakPad breakPad; - return &breakPad; + d_ptr->setDumpPath(path); } BreakPad::BreakPad(QObject *parent) : QObject{parent} - , d_ptr(new BreakPadPrivate) + , d_ptr(new BreakPadPrivate(this)) {} -BreakPad::~BreakPad() {} +BreakPad::~BreakPad() = default; void openCrashReporter() { - createEnvironment(); - const auto reporterPath = qApp->applicationDirPath() + "/" + CrashReportName; - QStringList args{Utils::getConfigPath() + "/crashes", - Utils::getConfigPath() + "/log", - qApp->applicationFilePath()}; + QStringList args{Utils::crashPath(), Utils::logPath(), qApp->applicationFilePath()}; args.append(qApp->arguments()); QProcess process; process.startDetached(reporterPath, args); } -void crash() -{ - int *p; - *p = 10; -} - -} // namespace Utils +} // namespace Dump diff --git a/3rdparty/breakpad.hpp b/src/dump/breakpad.hpp similarity index 50% rename from 3rdparty/breakpad.hpp rename to src/dump/breakpad.hpp index 297f5c8..76f59b7 100644 --- a/3rdparty/breakpad.hpp +++ b/src/dump/breakpad.hpp @@ -1,17 +1,19 @@ #ifndef BREAKPAD_HPP #define BREAKPAD_HPP -#include "thirdparty_global.hpp" +#include "dump_global.hpp" + +#include #include -namespace Utils { +namespace Dump { -class THRIDPARTY_EXPORT BreakPad : public QObject +class DUMP_EXPORT BreakPad : public QObject { Q_OBJECT public: - static auto instance() -> BreakPad *; + void setDumpPath(const QString &path); signals: void crash(); @@ -20,14 +22,14 @@ class THRIDPARTY_EXPORT BreakPad : public QObject explicit BreakPad(QObject *parent = nullptr); ~BreakPad() override; - struct BreakPadPrivate; + class BreakPadPrivate; QScopedPointer d_ptr; -}; -THRIDPARTY_EXPORT void openCrashReporter(); + SINGLETON(BreakPad) +}; -void crash(); +DUMP_EXPORT void openCrashReporter(); -} // namespace Utils +} // namespace Dump #endif // BREAKPAD_HPP diff --git a/src/dump/crashpad.cc b/src/dump/crashpad.cc new file mode 100644 index 0000000..45843f1 --- /dev/null +++ b/src/dump/crashpad.cc @@ -0,0 +1,63 @@ +#include "crashpad.hpp" + +#include +#include +#include + +namespace Dump { + +class CrashPad::CrashPadPrivate +{ +public: + explicit CrashPadPrivate(CrashPad *q) + : q_ptr(q) + , crashpadClientPtr(new crashpad::CrashpadClient) + {} + ~CrashPadPrivate() {} + + CrashPad *q_ptr = nullptr; + + QScopedPointer crashpadClientPtr; +}; + +CrashPad::CrashPad(const QString &dumpPath, + const QString &libexecPath, + const QString &reportUrl, + bool crashReportingEnabled, + QObject *parent) + : QObject(parent) + , d_ptr(new CrashPadPrivate(this)) +{ + auto handlerPath = libexecPath + "/crashpad_handler"; +#ifdef Q_OS_WIN + handlerPath += ".exe"; + base::FilePath database(dumpPath.toStdWString()); + base::FilePath handler(handlerPath.toStdWString()); +#else + base::FilePath database(dumpPath.toStdString()); + base::FilePath handler(handlerPath.toStdString()); +#endif +#ifdef Q_OS_LINUX + bool asynchronous_start = false; +#else + bool asynchronous_start = true; +#endif + + auto dbPtr = crashpad::CrashReportDatabase::Initialize(database); + if (dbPtr && (dbPtr->GetSettings() != nullptr)) { + dbPtr->GetSettings()->SetUploadsEnabled(crashReportingEnabled); + } + + d_ptr->crashpadClientPtr->StartHandler(handler, + database, + database, + reportUrl.toStdString(), + {}, + {"--no-rate-limit"}, + true, + asynchronous_start); +} + +CrashPad::~CrashPad() {} + +} // namespace Dump diff --git a/src/dump/crashpad.hpp b/src/dump/crashpad.hpp new file mode 100644 index 0000000..4df170c --- /dev/null +++ b/src/dump/crashpad.hpp @@ -0,0 +1,28 @@ +#ifndef CRASHPAD_HPP +#define CRASHPAD_HPP + +#include "dump_global.hpp" + +#include + +namespace Dump { + +class DUMP_EXPORT CrashPad : public QObject +{ + Q_OBJECT +public: + explicit CrashPad(const QString &dumpPath, + const QString &libexecPath, + const QString &reportUrl, + bool crashReportingEnabled, + QObject *parent = nullptr); + ~CrashPad() override; + +private: + class CrashPadPrivate; + QScopedPointer d_ptr; +}; + +} // namespace Dump + +#endif // CRASHPAD_HPP diff --git a/src/dump/dump.pro b/src/dump/dump.pro new file mode 100644 index 0000000..d3c9831 --- /dev/null +++ b/src/dump/dump.pro @@ -0,0 +1,17 @@ +include(../3rdparty/3rdparty.pri) +include(../slib.pri) + +DEFINES += DUMP_LIBRARY +TARGET = $$replaceLibName(dump) + +LIBS += \ + -l$$replaceLibName(utils) + +SOURCES += \ + breakpad.cc \ + crashpad.cc + +HEADERS += \ + breakpad.hpp \ + crashpad.hpp \ + dump_global.hpp diff --git a/src/dump/dump_global.hpp b/src/dump/dump_global.hpp new file mode 100644 index 0000000..5f4fb9b --- /dev/null +++ b/src/dump/dump_global.hpp @@ -0,0 +1,12 @@ +#ifndef DUMP_GLOBAL_HPP +#define DUMP_GLOBAL_HPP + +#include + +#if defined(DUMP_LIBRARY) +#define DUMP_EXPORT Q_DECL_EXPORT +#else +#define DUMP_EXPORT Q_DECL_IMPORT +#endif + +#endif // DUMP_GLOBAL_HPP diff --git a/ffmpeg/CMakeLists.txt b/src/ffmpeg/CMakeLists.txt similarity index 100% rename from ffmpeg/CMakeLists.txt rename to src/ffmpeg/CMakeLists.txt diff --git a/ffmpeg/audiodecoder.cpp b/src/ffmpeg/audiodecoder.cpp similarity index 100% rename from ffmpeg/audiodecoder.cpp rename to src/ffmpeg/audiodecoder.cpp diff --git a/ffmpeg/audiodecoder.h b/src/ffmpeg/audiodecoder.h similarity index 100% rename from ffmpeg/audiodecoder.h rename to src/ffmpeg/audiodecoder.h diff --git a/ffmpeg/audiodisplay.cc b/src/ffmpeg/audiodisplay.cc similarity index 100% rename from ffmpeg/audiodisplay.cc rename to src/ffmpeg/audiodisplay.cc diff --git a/ffmpeg/audiodisplay.hpp b/src/ffmpeg/audiodisplay.hpp similarity index 100% rename from ffmpeg/audiodisplay.hpp rename to src/ffmpeg/audiodisplay.hpp diff --git a/ffmpeg/audiofifo.cc b/src/ffmpeg/audiofifo.cc similarity index 100% rename from ffmpeg/audiofifo.cc rename to src/ffmpeg/audiofifo.cc diff --git a/ffmpeg/audiofifo.hpp b/src/ffmpeg/audiofifo.hpp similarity index 100% rename from ffmpeg/audiofifo.hpp rename to src/ffmpeg/audiofifo.hpp diff --git a/ffmpeg/audioframeconverter.cpp b/src/ffmpeg/audioframeconverter.cpp similarity index 100% rename from ffmpeg/audioframeconverter.cpp rename to src/ffmpeg/audioframeconverter.cpp diff --git a/ffmpeg/audioframeconverter.h b/src/ffmpeg/audioframeconverter.h similarity index 100% rename from ffmpeg/audioframeconverter.h rename to src/ffmpeg/audioframeconverter.h diff --git a/ffmpeg/audiorender/audiooutput.cc b/src/ffmpeg/audiorender/audiooutput.cc similarity index 100% rename from ffmpeg/audiorender/audiooutput.cc rename to src/ffmpeg/audiorender/audiooutput.cc diff --git a/ffmpeg/audiorender/audiooutput.hpp b/src/ffmpeg/audiorender/audiooutput.hpp similarity index 100% rename from ffmpeg/audiorender/audiooutput.hpp rename to src/ffmpeg/audiorender/audiooutput.hpp diff --git a/ffmpeg/audiorender/audiooutputthread.cc b/src/ffmpeg/audiorender/audiooutputthread.cc similarity index 100% rename from ffmpeg/audiorender/audiooutputthread.cc rename to src/ffmpeg/audiorender/audiooutputthread.cc diff --git a/ffmpeg/audiorender/audiooutputthread.hpp b/src/ffmpeg/audiorender/audiooutputthread.hpp similarity index 100% rename from ffmpeg/audiorender/audiooutputthread.hpp rename to src/ffmpeg/audiorender/audiooutputthread.hpp diff --git a/ffmpeg/audiorender/audiorender.pri b/src/ffmpeg/audiorender/audiorender.pri similarity index 100% rename from ffmpeg/audiorender/audiorender.pri rename to src/ffmpeg/audiorender/audiorender.pri diff --git a/ffmpeg/avcontextinfo.cpp b/src/ffmpeg/avcontextinfo.cpp similarity index 100% rename from ffmpeg/avcontextinfo.cpp rename to src/ffmpeg/avcontextinfo.cpp diff --git a/ffmpeg/avcontextinfo.h b/src/ffmpeg/avcontextinfo.h similarity index 100% rename from ffmpeg/avcontextinfo.h rename to src/ffmpeg/avcontextinfo.h diff --git a/ffmpeg/averror.cpp b/src/ffmpeg/averror.cpp similarity index 100% rename from ffmpeg/averror.cpp rename to src/ffmpeg/averror.cpp diff --git a/ffmpeg/averror.h b/src/ffmpeg/averror.h similarity index 100% rename from ffmpeg/averror.h rename to src/ffmpeg/averror.h diff --git a/ffmpeg/averrormanager.cc b/src/ffmpeg/averrormanager.cc similarity index 100% rename from ffmpeg/averrormanager.cc rename to src/ffmpeg/averrormanager.cc diff --git a/ffmpeg/averrormanager.hpp b/src/ffmpeg/averrormanager.hpp similarity index 100% rename from ffmpeg/averrormanager.hpp rename to src/ffmpeg/averrormanager.hpp diff --git a/ffmpeg/clock.cc b/src/ffmpeg/clock.cc similarity index 100% rename from ffmpeg/clock.cc rename to src/ffmpeg/clock.cc diff --git a/ffmpeg/clock.hpp b/src/ffmpeg/clock.hpp similarity index 100% rename from ffmpeg/clock.hpp rename to src/ffmpeg/clock.hpp diff --git a/ffmpeg/codeccontext.cpp b/src/ffmpeg/codeccontext.cpp similarity index 100% rename from ffmpeg/codeccontext.cpp rename to src/ffmpeg/codeccontext.cpp diff --git a/ffmpeg/codeccontext.h b/src/ffmpeg/codeccontext.h similarity index 100% rename from ffmpeg/codeccontext.h rename to src/ffmpeg/codeccontext.h diff --git a/ffmpeg/colorutils.cc b/src/ffmpeg/colorutils.cc similarity index 100% rename from ffmpeg/colorutils.cc rename to src/ffmpeg/colorutils.cc diff --git a/ffmpeg/colorutils.hpp b/src/ffmpeg/colorutils.hpp similarity index 100% rename from ffmpeg/colorutils.hpp rename to src/ffmpeg/colorutils.hpp diff --git a/ffmpeg/decoder.cc b/src/ffmpeg/decoder.cc similarity index 100% rename from ffmpeg/decoder.cc rename to src/ffmpeg/decoder.cc diff --git a/ffmpeg/decoder.h b/src/ffmpeg/decoder.h similarity index 100% rename from ffmpeg/decoder.h rename to src/ffmpeg/decoder.h diff --git a/ffmpeg/encodecontext.cc b/src/ffmpeg/encodecontext.cc similarity index 100% rename from ffmpeg/encodecontext.cc rename to src/ffmpeg/encodecontext.cc diff --git a/ffmpeg/encodecontext.hpp b/src/ffmpeg/encodecontext.hpp similarity index 100% rename from ffmpeg/encodecontext.hpp rename to src/ffmpeg/encodecontext.hpp diff --git a/ffmpeg/event/errorevent.hpp b/src/ffmpeg/event/errorevent.hpp similarity index 100% rename from ffmpeg/event/errorevent.hpp rename to src/ffmpeg/event/errorevent.hpp diff --git a/ffmpeg/event/event.hpp b/src/ffmpeg/event/event.hpp similarity index 100% rename from ffmpeg/event/event.hpp rename to src/ffmpeg/event/event.hpp diff --git a/ffmpeg/event/event.pri b/src/ffmpeg/event/event.pri similarity index 100% rename from ffmpeg/event/event.pri rename to src/ffmpeg/event/event.pri diff --git a/ffmpeg/event/seekevent.hpp b/src/ffmpeg/event/seekevent.hpp similarity index 100% rename from ffmpeg/event/seekevent.hpp rename to src/ffmpeg/event/seekevent.hpp diff --git a/ffmpeg/event/trackevent.hpp b/src/ffmpeg/event/trackevent.hpp similarity index 100% rename from ffmpeg/event/trackevent.hpp rename to src/ffmpeg/event/trackevent.hpp diff --git a/ffmpeg/event/valueevent.hpp b/src/ffmpeg/event/valueevent.hpp similarity index 100% rename from ffmpeg/event/valueevent.hpp rename to src/ffmpeg/event/valueevent.hpp diff --git a/ffmpeg/ffmepg_global.h b/src/ffmpeg/ffmepg_global.h similarity index 100% rename from ffmpeg/ffmepg_global.h rename to src/ffmpeg/ffmepg_global.h diff --git a/ffmpeg/ffmpeg.pro b/src/ffmpeg/ffmpeg.pro similarity index 98% rename from ffmpeg/ffmpeg.pro rename to src/ffmpeg/ffmpeg.pro index 1bbc9bc..d058b35 100644 --- a/ffmpeg/ffmpeg.pro +++ b/src/ffmpeg/ffmpeg.pro @@ -1,4 +1,4 @@ -include(../libs.pri) +include(../slib.pri) include(../3rdparty/3rdparty.pri) include(subtitle/subtitle.pri) include(filter/filter.pri) diff --git a/ffmpeg/ffmpegutils.cc b/src/ffmpeg/ffmpegutils.cc similarity index 100% rename from ffmpeg/ffmpegutils.cc rename to src/ffmpeg/ffmpegutils.cc diff --git a/ffmpeg/ffmpegutils.hpp b/src/ffmpeg/ffmpegutils.hpp similarity index 100% rename from ffmpeg/ffmpegutils.hpp rename to src/ffmpeg/ffmpegutils.hpp diff --git a/ffmpeg/filter/filter.cc b/src/ffmpeg/filter/filter.cc similarity index 100% rename from ffmpeg/filter/filter.cc rename to src/ffmpeg/filter/filter.cc diff --git a/ffmpeg/filter/filter.hpp b/src/ffmpeg/filter/filter.hpp similarity index 100% rename from ffmpeg/filter/filter.hpp rename to src/ffmpeg/filter/filter.hpp diff --git a/ffmpeg/filter/filter.pri b/src/ffmpeg/filter/filter.pri similarity index 100% rename from ffmpeg/filter/filter.pri rename to src/ffmpeg/filter/filter.pri diff --git a/ffmpeg/filter/filtercontext.cc b/src/ffmpeg/filter/filtercontext.cc similarity index 100% rename from ffmpeg/filter/filtercontext.cc rename to src/ffmpeg/filter/filtercontext.cc diff --git a/ffmpeg/filter/filtercontext.hpp b/src/ffmpeg/filter/filtercontext.hpp similarity index 100% rename from ffmpeg/filter/filtercontext.hpp rename to src/ffmpeg/filter/filtercontext.hpp diff --git a/ffmpeg/filter/filtergraph.cc b/src/ffmpeg/filter/filtergraph.cc similarity index 100% rename from ffmpeg/filter/filtergraph.cc rename to src/ffmpeg/filter/filtergraph.cc diff --git a/ffmpeg/filter/filtergraph.hpp b/src/ffmpeg/filter/filtergraph.hpp similarity index 100% rename from ffmpeg/filter/filtergraph.hpp rename to src/ffmpeg/filter/filtergraph.hpp diff --git a/ffmpeg/filter/filterinout.cc b/src/ffmpeg/filter/filterinout.cc similarity index 100% rename from ffmpeg/filter/filterinout.cc rename to src/ffmpeg/filter/filterinout.cc diff --git a/ffmpeg/filter/filterinout.hpp b/src/ffmpeg/filter/filterinout.hpp similarity index 100% rename from ffmpeg/filter/filterinout.hpp rename to src/ffmpeg/filter/filterinout.hpp diff --git a/ffmpeg/formatcontext.cpp b/src/ffmpeg/formatcontext.cpp similarity index 100% rename from ffmpeg/formatcontext.cpp rename to src/ffmpeg/formatcontext.cpp diff --git a/ffmpeg/formatcontext.h b/src/ffmpeg/formatcontext.h similarity index 100% rename from ffmpeg/formatcontext.h rename to src/ffmpeg/formatcontext.h diff --git a/ffmpeg/frame.cc b/src/ffmpeg/frame.cc similarity index 100% rename from ffmpeg/frame.cc rename to src/ffmpeg/frame.cc diff --git a/ffmpeg/frame.hpp b/src/ffmpeg/frame.hpp similarity index 100% rename from ffmpeg/frame.hpp rename to src/ffmpeg/frame.hpp diff --git a/ffmpeg/gpu/bufferref.cc b/src/ffmpeg/gpu/bufferref.cc similarity index 100% rename from ffmpeg/gpu/bufferref.cc rename to src/ffmpeg/gpu/bufferref.cc diff --git a/ffmpeg/gpu/bufferref.hpp b/src/ffmpeg/gpu/bufferref.hpp similarity index 100% rename from ffmpeg/gpu/bufferref.hpp rename to src/ffmpeg/gpu/bufferref.hpp diff --git a/ffmpeg/gpu/gpu.pri b/src/ffmpeg/gpu/gpu.pri similarity index 100% rename from ffmpeg/gpu/gpu.pri rename to src/ffmpeg/gpu/gpu.pri diff --git a/ffmpeg/gpu/hardwaredecode.cc b/src/ffmpeg/gpu/hardwaredecode.cc similarity index 100% rename from ffmpeg/gpu/hardwaredecode.cc rename to src/ffmpeg/gpu/hardwaredecode.cc diff --git a/ffmpeg/gpu/hardwaredecode.hpp b/src/ffmpeg/gpu/hardwaredecode.hpp similarity index 100% rename from ffmpeg/gpu/hardwaredecode.hpp rename to src/ffmpeg/gpu/hardwaredecode.hpp diff --git a/ffmpeg/gpu/hardwareencode.cc b/src/ffmpeg/gpu/hardwareencode.cc similarity index 100% rename from ffmpeg/gpu/hardwareencode.cc rename to src/ffmpeg/gpu/hardwareencode.cc diff --git a/ffmpeg/gpu/hardwareencode.hpp b/src/ffmpeg/gpu/hardwareencode.hpp similarity index 100% rename from ffmpeg/gpu/hardwareencode.hpp rename to src/ffmpeg/gpu/hardwareencode.hpp diff --git a/ffmpeg/hdrmetadata.cc b/src/ffmpeg/hdrmetadata.cc similarity index 100% rename from ffmpeg/hdrmetadata.cc rename to src/ffmpeg/hdrmetadata.cc diff --git a/ffmpeg/hdrmetadata.hpp b/src/ffmpeg/hdrmetadata.hpp similarity index 100% rename from ffmpeg/hdrmetadata.hpp rename to src/ffmpeg/hdrmetadata.hpp diff --git a/ffmpeg/mediainfo.cc b/src/ffmpeg/mediainfo.cc similarity index 100% rename from ffmpeg/mediainfo.cc rename to src/ffmpeg/mediainfo.cc diff --git a/ffmpeg/mediainfo.hpp b/src/ffmpeg/mediainfo.hpp similarity index 100% rename from ffmpeg/mediainfo.hpp rename to src/ffmpeg/mediainfo.hpp diff --git a/ffmpeg/packet.cpp b/src/ffmpeg/packet.cpp similarity index 100% rename from ffmpeg/packet.cpp rename to src/ffmpeg/packet.cpp diff --git a/ffmpeg/packet.h b/src/ffmpeg/packet.h similarity index 100% rename from ffmpeg/packet.h rename to src/ffmpeg/packet.h diff --git a/ffmpeg/player.cpp b/src/ffmpeg/player.cpp similarity index 100% rename from ffmpeg/player.cpp rename to src/ffmpeg/player.cpp diff --git a/ffmpeg/player.h b/src/ffmpeg/player.h similarity index 100% rename from ffmpeg/player.h rename to src/ffmpeg/player.h diff --git a/ffmpeg/previewtask.cc b/src/ffmpeg/previewtask.cc similarity index 100% rename from ffmpeg/previewtask.cc rename to src/ffmpeg/previewtask.cc diff --git a/ffmpeg/previewtask.hpp b/src/ffmpeg/previewtask.hpp similarity index 100% rename from ffmpeg/previewtask.hpp rename to src/ffmpeg/previewtask.hpp diff --git a/ffmpeg/subtitle.cpp b/src/ffmpeg/subtitle.cpp similarity index 100% rename from ffmpeg/subtitle.cpp rename to src/ffmpeg/subtitle.cpp diff --git a/ffmpeg/subtitle.h b/src/ffmpeg/subtitle.h similarity index 100% rename from ffmpeg/subtitle.h rename to src/ffmpeg/subtitle.h diff --git a/ffmpeg/subtitle/ass.cc b/src/ffmpeg/subtitle/ass.cc similarity index 100% rename from ffmpeg/subtitle/ass.cc rename to src/ffmpeg/subtitle/ass.cc diff --git a/ffmpeg/subtitle/ass.hpp b/src/ffmpeg/subtitle/ass.hpp similarity index 100% rename from ffmpeg/subtitle/ass.hpp rename to src/ffmpeg/subtitle/ass.hpp diff --git a/ffmpeg/subtitle/assdata.cc b/src/ffmpeg/subtitle/assdata.cc similarity index 100% rename from ffmpeg/subtitle/assdata.cc rename to src/ffmpeg/subtitle/assdata.cc diff --git a/ffmpeg/subtitle/assdata.hpp b/src/ffmpeg/subtitle/assdata.hpp similarity index 100% rename from ffmpeg/subtitle/assdata.hpp rename to src/ffmpeg/subtitle/assdata.hpp diff --git a/ffmpeg/subtitle/subtitle.pri b/src/ffmpeg/subtitle/subtitle.pri similarity index 100% rename from ffmpeg/subtitle/subtitle.pri rename to src/ffmpeg/subtitle/subtitle.pri diff --git a/ffmpeg/subtitledecoder.cpp b/src/ffmpeg/subtitledecoder.cpp similarity index 100% rename from ffmpeg/subtitledecoder.cpp rename to src/ffmpeg/subtitledecoder.cpp diff --git a/ffmpeg/subtitledecoder.h b/src/ffmpeg/subtitledecoder.h similarity index 100% rename from ffmpeg/subtitledecoder.h rename to src/ffmpeg/subtitledecoder.h diff --git a/ffmpeg/subtitledisplay.cc b/src/ffmpeg/subtitledisplay.cc similarity index 100% rename from ffmpeg/subtitledisplay.cc rename to src/ffmpeg/subtitledisplay.cc diff --git a/ffmpeg/subtitledisplay.hpp b/src/ffmpeg/subtitledisplay.hpp similarity index 100% rename from ffmpeg/subtitledisplay.hpp rename to src/ffmpeg/subtitledisplay.hpp diff --git a/ffmpeg/transcoder.cc b/src/ffmpeg/transcoder.cc similarity index 100% rename from ffmpeg/transcoder.cc rename to src/ffmpeg/transcoder.cc diff --git a/ffmpeg/transcoder.hpp b/src/ffmpeg/transcoder.hpp similarity index 100% rename from ffmpeg/transcoder.hpp rename to src/ffmpeg/transcoder.hpp diff --git a/ffmpeg/transcodercontext.cc b/src/ffmpeg/transcodercontext.cc similarity index 100% rename from ffmpeg/transcodercontext.cc rename to src/ffmpeg/transcodercontext.cc diff --git a/ffmpeg/transcodercontext.hpp b/src/ffmpeg/transcodercontext.hpp similarity index 100% rename from ffmpeg/transcodercontext.hpp rename to src/ffmpeg/transcodercontext.hpp diff --git a/ffmpeg/videodecoder.cpp b/src/ffmpeg/videodecoder.cpp similarity index 100% rename from ffmpeg/videodecoder.cpp rename to src/ffmpeg/videodecoder.cpp diff --git a/ffmpeg/videodecoder.h b/src/ffmpeg/videodecoder.h similarity index 100% rename from ffmpeg/videodecoder.h rename to src/ffmpeg/videodecoder.h diff --git a/ffmpeg/videodisplay.cc b/src/ffmpeg/videodisplay.cc similarity index 100% rename from ffmpeg/videodisplay.cc rename to src/ffmpeg/videodisplay.cc diff --git a/ffmpeg/videodisplay.hpp b/src/ffmpeg/videodisplay.hpp similarity index 100% rename from ffmpeg/videodisplay.hpp rename to src/ffmpeg/videodisplay.hpp diff --git a/ffmpeg/videoformat.cc b/src/ffmpeg/videoformat.cc similarity index 100% rename from ffmpeg/videoformat.cc rename to src/ffmpeg/videoformat.cc diff --git a/ffmpeg/videoformat.hpp b/src/ffmpeg/videoformat.hpp similarity index 100% rename from ffmpeg/videoformat.hpp rename to src/ffmpeg/videoformat.hpp diff --git a/ffmpeg/videoframeconverter.cc b/src/ffmpeg/videoframeconverter.cc similarity index 100% rename from ffmpeg/videoframeconverter.cc rename to src/ffmpeg/videoframeconverter.cc diff --git a/ffmpeg/videoframeconverter.hpp b/src/ffmpeg/videoframeconverter.hpp similarity index 100% rename from ffmpeg/videoframeconverter.hpp rename to src/ffmpeg/videoframeconverter.hpp diff --git a/ffmpeg/videorender/openglrender.cc b/src/ffmpeg/videorender/openglrender.cc similarity index 100% rename from ffmpeg/videorender/openglrender.cc rename to src/ffmpeg/videorender/openglrender.cc diff --git a/ffmpeg/videorender/openglrender.hpp b/src/ffmpeg/videorender/openglrender.hpp similarity index 100% rename from ffmpeg/videorender/openglrender.hpp rename to src/ffmpeg/videorender/openglrender.hpp diff --git a/ffmpeg/videorender/openglshader.cc b/src/ffmpeg/videorender/openglshader.cc similarity index 100% rename from ffmpeg/videorender/openglshader.cc rename to src/ffmpeg/videorender/openglshader.cc diff --git a/ffmpeg/videorender/openglshader.hpp b/src/ffmpeg/videorender/openglshader.hpp similarity index 100% rename from ffmpeg/videorender/openglshader.hpp rename to src/ffmpeg/videorender/openglshader.hpp diff --git a/ffmpeg/videorender/openglshaderprogram.cc b/src/ffmpeg/videorender/openglshaderprogram.cc similarity index 100% rename from ffmpeg/videorender/openglshaderprogram.cc rename to src/ffmpeg/videorender/openglshaderprogram.cc diff --git a/ffmpeg/videorender/openglshaderprogram.hpp b/src/ffmpeg/videorender/openglshaderprogram.hpp similarity index 100% rename from ffmpeg/videorender/openglshaderprogram.hpp rename to src/ffmpeg/videorender/openglshaderprogram.hpp diff --git a/ffmpeg/videorender/shader/sub.frag b/src/ffmpeg/videorender/shader/sub.frag similarity index 100% rename from ffmpeg/videorender/shader/sub.frag rename to src/ffmpeg/videorender/shader/sub.frag diff --git a/ffmpeg/videorender/shader/tonemap.frag b/src/ffmpeg/videorender/shader/tonemap.frag similarity index 100% rename from ffmpeg/videorender/shader/tonemap.frag rename to src/ffmpeg/videorender/shader/tonemap.frag diff --git a/ffmpeg/videorender/shader/video.frag b/src/ffmpeg/videorender/shader/video.frag similarity index 100% rename from ffmpeg/videorender/shader/video.frag rename to src/ffmpeg/videorender/shader/video.frag diff --git a/ffmpeg/videorender/shader/video.vert b/src/ffmpeg/videorender/shader/video.vert similarity index 100% rename from ffmpeg/videorender/shader/video.vert rename to src/ffmpeg/videorender/shader/video.vert diff --git a/ffmpeg/videorender/shader/video_color.frag b/src/ffmpeg/videorender/shader/video_color.frag similarity index 100% rename from ffmpeg/videorender/shader/video_color.frag rename to src/ffmpeg/videorender/shader/video_color.frag diff --git a/ffmpeg/videorender/shader/video_header.frag b/src/ffmpeg/videorender/shader/video_header.frag similarity index 100% rename from ffmpeg/videorender/shader/video_header.frag rename to src/ffmpeg/videorender/shader/video_header.frag diff --git a/ffmpeg/videorender/shader/video_nv12.frag b/src/ffmpeg/videorender/shader/video_nv12.frag similarity index 100% rename from ffmpeg/videorender/shader/video_nv12.frag rename to src/ffmpeg/videorender/shader/video_nv12.frag diff --git a/ffmpeg/videorender/shader/video_nv21.frag b/src/ffmpeg/videorender/shader/video_nv21.frag similarity index 100% rename from ffmpeg/videorender/shader/video_nv21.frag rename to src/ffmpeg/videorender/shader/video_nv21.frag diff --git a/ffmpeg/videorender/shader/video_p010le.frag b/src/ffmpeg/videorender/shader/video_p010le.frag similarity index 100% rename from ffmpeg/videorender/shader/video_p010le.frag rename to src/ffmpeg/videorender/shader/video_p010le.frag diff --git a/ffmpeg/videorender/shader/video_uyvy422.frag b/src/ffmpeg/videorender/shader/video_uyvy422.frag similarity index 100% rename from ffmpeg/videorender/shader/video_uyvy422.frag rename to src/ffmpeg/videorender/shader/video_uyvy422.frag diff --git a/ffmpeg/videorender/shader/video_vulkan.frag b/src/ffmpeg/videorender/shader/video_vulkan.frag similarity index 100% rename from ffmpeg/videorender/shader/video_vulkan.frag rename to src/ffmpeg/videorender/shader/video_vulkan.frag diff --git a/ffmpeg/videorender/shader/video_vulkan.vert b/src/ffmpeg/videorender/shader/video_vulkan.vert similarity index 100% rename from ffmpeg/videorender/shader/video_vulkan.vert rename to src/ffmpeg/videorender/shader/video_vulkan.vert diff --git a/ffmpeg/videorender/shader/video_yuv420p.frag b/src/ffmpeg/videorender/shader/video_yuv420p.frag similarity index 100% rename from ffmpeg/videorender/shader/video_yuv420p.frag rename to src/ffmpeg/videorender/shader/video_yuv420p.frag diff --git a/ffmpeg/videorender/shader/video_yuyv422.frag b/src/ffmpeg/videorender/shader/video_yuyv422.frag similarity index 100% rename from ffmpeg/videorender/shader/video_yuyv422.frag rename to src/ffmpeg/videorender/shader/video_yuyv422.frag diff --git a/ffmpeg/videorender/shaders.qrc b/src/ffmpeg/videorender/shaders.qrc similarity index 100% rename from ffmpeg/videorender/shaders.qrc rename to src/ffmpeg/videorender/shaders.qrc diff --git a/ffmpeg/videorender/shaderutils.cc b/src/ffmpeg/videorender/shaderutils.cc similarity index 100% rename from ffmpeg/videorender/shaderutils.cc rename to src/ffmpeg/videorender/shaderutils.cc diff --git a/ffmpeg/videorender/shaderutils.hpp b/src/ffmpeg/videorender/shaderutils.hpp similarity index 100% rename from ffmpeg/videorender/shaderutils.hpp rename to src/ffmpeg/videorender/shaderutils.hpp diff --git a/ffmpeg/videorender/tonemap.cc b/src/ffmpeg/videorender/tonemap.cc similarity index 100% rename from ffmpeg/videorender/tonemap.cc rename to src/ffmpeg/videorender/tonemap.cc diff --git a/ffmpeg/videorender/tonemap.hpp b/src/ffmpeg/videorender/tonemap.hpp similarity index 100% rename from ffmpeg/videorender/tonemap.hpp rename to src/ffmpeg/videorender/tonemap.hpp diff --git a/ffmpeg/videorender/videopreviewwidget.cc b/src/ffmpeg/videorender/videopreviewwidget.cc similarity index 100% rename from ffmpeg/videorender/videopreviewwidget.cc rename to src/ffmpeg/videorender/videopreviewwidget.cc diff --git a/ffmpeg/videorender/videopreviewwidget.hpp b/src/ffmpeg/videorender/videopreviewwidget.hpp similarity index 100% rename from ffmpeg/videorender/videopreviewwidget.hpp rename to src/ffmpeg/videorender/videopreviewwidget.hpp diff --git a/ffmpeg/videorender/videorender.cc b/src/ffmpeg/videorender/videorender.cc similarity index 100% rename from ffmpeg/videorender/videorender.cc rename to src/ffmpeg/videorender/videorender.cc diff --git a/ffmpeg/videorender/videorender.hpp b/src/ffmpeg/videorender/videorender.hpp similarity index 100% rename from ffmpeg/videorender/videorender.hpp rename to src/ffmpeg/videorender/videorender.hpp diff --git a/ffmpeg/videorender/videorender.pri b/src/ffmpeg/videorender/videorender.pri similarity index 100% rename from ffmpeg/videorender/videorender.pri rename to src/ffmpeg/videorender/videorender.pri diff --git a/ffmpeg/videorender/videorendercreate.cc b/src/ffmpeg/videorender/videorendercreate.cc similarity index 100% rename from ffmpeg/videorender/videorendercreate.cc rename to src/ffmpeg/videorender/videorendercreate.cc diff --git a/ffmpeg/videorender/videorendercreate.hpp b/src/ffmpeg/videorender/videorendercreate.hpp similarity index 100% rename from ffmpeg/videorender/videorendercreate.hpp rename to src/ffmpeg/videorender/videorendercreate.hpp diff --git a/ffmpeg/videorender/widgetrender.cc b/src/ffmpeg/videorender/widgetrender.cc similarity index 100% rename from ffmpeg/videorender/widgetrender.cc rename to src/ffmpeg/videorender/widgetrender.cc diff --git a/ffmpeg/videorender/widgetrender.hpp b/src/ffmpeg/videorender/widgetrender.hpp similarity index 100% rename from ffmpeg/videorender/widgetrender.hpp rename to src/ffmpeg/videorender/widgetrender.hpp diff --git a/ffmpeg/widgets/mediainfodialog.cc b/src/ffmpeg/widgets/mediainfodialog.cc similarity index 100% rename from ffmpeg/widgets/mediainfodialog.cc rename to src/ffmpeg/widgets/mediainfodialog.cc diff --git a/ffmpeg/widgets/mediainfodialog.hpp b/src/ffmpeg/widgets/mediainfodialog.hpp similarity index 100% rename from ffmpeg/widgets/mediainfodialog.hpp rename to src/ffmpeg/widgets/mediainfodialog.hpp diff --git a/ffmpeg/widgets/widgets.pri b/src/ffmpeg/widgets/widgets.pri similarity index 100% rename from ffmpeg/widgets/widgets.pri rename to src/ffmpeg/widgets/widgets.pri diff --git a/libs.pri b/src/slib.pri similarity index 79% rename from libs.pri rename to src/slib.pri index f74a391..0842f1a 100644 --- a/libs.pri +++ b/src/slib.pri @@ -1,4 +1,4 @@ -include(Common.pri) +include(../common.pri) TEMPLATE = lib @@ -11,5 +11,3 @@ unix{ CONFIG += staticlib DESTDIR = $$APP_OUTPUT_PATH/../libs } - -LIBS += -L$$DESTDIR diff --git a/src/src.pro b/src/src.pro new file mode 100644 index 0000000..9673fc5 --- /dev/null +++ b/src/src.pro @@ -0,0 +1,8 @@ +TEMPLATE = subdirs +CONFIG += ordered + +SUBDIRS += \ + utils \ + dump \ + 3rdparty \ + ffmpeg diff --git a/utils/CMakeLists.txt b/src/utils/CMakeLists.txt similarity index 95% rename from utils/CMakeLists.txt rename to src/utils/CMakeLists.txt index dd0cf2b..3291132 100644 --- a/utils/CMakeLists.txt +++ b/src/utils/CMakeLists.txt @@ -15,7 +15,8 @@ set(PROJECT_SOURCES threadsafequeue.hpp utils_global.h utils.cpp - utils.h) + utils.h + utilstr.h) add_custom_library(utils ${PROJECT_SOURCES} ${SOURCES}) target_link_libraries(utils PRIVATE Qt6::Widgets Qt6::Core5Compat) diff --git a/utils/boundedblockingqueue.hpp b/src/utils/boundedblockingqueue.hpp similarity index 100% rename from utils/boundedblockingqueue.hpp rename to src/utils/boundedblockingqueue.hpp diff --git a/utils/countdownlatch.cc b/src/utils/countdownlatch.cc similarity index 94% rename from utils/countdownlatch.cc rename to src/utils/countdownlatch.cc index 191ea87..9ac06a6 100644 --- a/utils/countdownlatch.cc +++ b/src/utils/countdownlatch.cc @@ -1,53 +1,53 @@ -#include "countdownlatch.hpp" - -#include -#include -#include - -namespace Utils { - -struct CountDownLatch::CountDownLatchPrivate -{ - mutable QMutex mutex; - QWaitCondition waintCondition; - int count; -}; - -CountDownLatch::CountDownLatch(int count) - : d_ptr(new CountDownLatchPrivate) -{ - d_ptr->count = count; -} - -CountDownLatch::~CountDownLatch() = default; - -void CountDownLatch::wait() -{ - QMutexLocker locker(&d_ptr->mutex); - while (d_ptr->count > 0) { - d_ptr->waintCondition.wait(&d_ptr->mutex); - } -} - -void CountDownLatch::countDown() -{ - QMutexLocker locker(&d_ptr->mutex); - d_ptr->count--; - if (d_ptr->count == 0) { - d_ptr->waintCondition.wakeAll(); - } -} - -void CountDownLatch::setCount(int count) -{ - QMutexLocker locker(&d_ptr->mutex); - d_ptr->count = count; -} - -int CountDownLatch::getCount() const -{ - QMutexLocker locker(&d_ptr->mutex); - return d_ptr->count; -} - -} // namespace Utils +#include "countdownlatch.hpp" + +#include +#include +#include + +namespace Utils { + +struct CountDownLatch::CountDownLatchPrivate +{ + mutable QMutex mutex; + QWaitCondition waintCondition; + int count; +}; + +CountDownLatch::CountDownLatch(int count) + : d_ptr(new CountDownLatchPrivate) +{ + d_ptr->count = count; +} + +CountDownLatch::~CountDownLatch() = default; + +void CountDownLatch::wait() +{ + QMutexLocker locker(&d_ptr->mutex); + while (d_ptr->count > 0) { + d_ptr->waintCondition.wait(&d_ptr->mutex); + } +} + +void CountDownLatch::countDown() +{ + QMutexLocker locker(&d_ptr->mutex); + d_ptr->count--; + if (d_ptr->count == 0) { + d_ptr->waintCondition.wakeAll(); + } +} + +void CountDownLatch::setCount(int count) +{ + QMutexLocker locker(&d_ptr->mutex); + d_ptr->count = count; +} + +int CountDownLatch::getCount() const +{ + QMutexLocker locker(&d_ptr->mutex); + return d_ptr->count; +} + +} // namespace Utils diff --git a/utils/countdownlatch.hpp b/src/utils/countdownlatch.hpp similarity index 94% rename from utils/countdownlatch.hpp rename to src/utils/countdownlatch.hpp index f3d03f3..d0cbe34 100644 --- a/utils/countdownlatch.hpp +++ b/src/utils/countdownlatch.hpp @@ -1,30 +1,30 @@ -#ifndef COUNTDOWNLATCH_HPP -#define COUNTDOWNLATCH_HPP - -#include "utils_global.h" - -#include - -namespace Utils { - -class UTILS_EXPORT CountDownLatch -{ - Q_DISABLE_COPY_MOVE(CountDownLatch) -public: - explicit CountDownLatch(int count); - ~CountDownLatch(); - - void wait(); - void countDown(); - - void setCount(int count); - [[nodiscard]] auto getCount() const -> int; - -private: - struct CountDownLatchPrivate; - QScopedPointer d_ptr; -}; - -} // namespace Utils - -#endif // COUNTDOWNLATCH_HPP +#ifndef COUNTDOWNLATCH_HPP +#define COUNTDOWNLATCH_HPP + +#include "utils_global.h" + +#include + +namespace Utils { + +class UTILS_EXPORT CountDownLatch +{ + Q_DISABLE_COPY_MOVE(CountDownLatch) +public: + explicit CountDownLatch(int count); + ~CountDownLatch(); + + void wait(); + void countDown(); + + void setCount(int count); + [[nodiscard]] auto getCount() const -> int; + +private: + struct CountDownLatchPrivate; + QScopedPointer d_ptr; +}; + +} // namespace Utils + +#endif // COUNTDOWNLATCH_HPP diff --git a/utils/fps.cc b/src/utils/fps.cc similarity index 100% rename from utils/fps.cc rename to src/utils/fps.cc diff --git a/utils/fps.hpp b/src/utils/fps.hpp similarity index 100% rename from utils/fps.hpp rename to src/utils/fps.hpp diff --git a/src/utils/hostosinfo.cpp b/src/utils/hostosinfo.cpp new file mode 100644 index 0000000..20b3a6b --- /dev/null +++ b/src/utils/hostosinfo.cpp @@ -0,0 +1,112 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +#include "hostosinfo.h" + +#include "utilstr.h" + +#if !defined(QT_NO_OPENGL) && defined(QT_GUI_LIB) +#include +#endif + +#ifdef Q_OS_LINUX +#include +#endif + +#ifdef Q_OS_WIN +#include +#endif + +#ifdef Q_OS_MACOS +#include +#endif + +using namespace Utils; + +Qt::CaseSensitivity HostOsInfo::m_overrideFileNameCaseSensitivity = Qt::CaseSensitive; +bool HostOsInfo::m_useOverrideFileNameCaseSensitivity = false; + +#ifdef Q_OS_WIN +static auto hostProcessorArchitecture() -> WORD +{ + SYSTEM_INFO info; + GetNativeSystemInfo(&info); + return info.wProcessorArchitecture; +} +#endif + +auto HostOsInfo::hostArchitecture() -> HostOsInfo::HostArchitecture +{ +#ifdef Q_OS_WIN + static const WORD processorArchitecture = hostProcessorArchitecture(); + switch (processorArchitecture) { + case PROCESSOR_ARCHITECTURE_AMD64: return HostOsInfo::HostArchitectureAMD64; + case PROCESSOR_ARCHITECTURE_INTEL: return HostOsInfo::HostArchitectureX86; + case PROCESSOR_ARCHITECTURE_IA64: return HostOsInfo::HostArchitectureItanium; + case PROCESSOR_ARCHITECTURE_ARM: return HostOsInfo::HostArchitectureArm; + case PROCESSOR_ARCHITECTURE_ARM64: return HostOsInfo::HostArchitectureArm64; + default: return HostOsInfo::HostArchitectureUnknown; + } +#else + return HostOsInfo::HostArchitectureUnknown; +#endif +} + +auto HostOsInfo::isRunningUnderRosetta() -> bool +{ +#ifdef Q_OS_MACOS + int translated = 0; + auto size = sizeof(translated); + if (sysctlbyname("sysctl.proc_translated", &translated, &size, nullptr, 0) == 0) + return translated; +#endif + return false; +} + +void HostOsInfo::setOverrideFileNameCaseSensitivity(Qt::CaseSensitivity sensitivity) +{ + m_useOverrideFileNameCaseSensitivity = true; + m_overrideFileNameCaseSensitivity = sensitivity; +} + +void HostOsInfo::unsetOverrideFileNameCaseSensitivity() +{ + m_useOverrideFileNameCaseSensitivity = false; +} + +auto HostOsInfo::canCreateOpenGLContext(QString *errorMessage) -> bool +{ +#if defined(QT_NO_OPENGL) || !defined(QT_GUI_LIB) + Q_UNUSED(errorMessage) + return false; +#else + static const bool canCreate = QOpenGLContext().create(); + if (!canCreate) + *errorMessage = Tr::tr("Cannot create OpenGL context."); + return canCreate; +#endif +} + +std::optional HostOsInfo::totalMemoryInstalledInBytes() +{ +#ifdef Q_OS_LINUX + struct sysinfo info; + if (sysinfo(&info) == -1) + return {}; + return info.totalram; +#elif defined(Q_OS_WIN) + MEMORYSTATUSEX statex; + statex.dwLength = sizeof statex; + if (GlobalMemoryStatusEx(&statex) == 0) + return {}; + return statex.ullTotalPhys; +#elif defined(Q_OS_MACOS) + int mib[] = {CTL_HW, HW_MEMSIZE}; + int64_t ram; + size_t length = sizeof(int64_t); + if (sysctl(mib, 2, &ram, &length, nullptr, 0) == -1) + return {}; + return ram; +#endif + return {}; +} diff --git a/utils/hostosinfo.h b/src/utils/hostosinfo.h similarity index 58% rename from utils/hostosinfo.h rename to src/utils/hostosinfo.h index 0340984..254e4fb 100644 --- a/utils/hostosinfo.h +++ b/src/utils/hostosinfo.h @@ -1,27 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of Qt Creator. -** -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 #pragma once @@ -29,7 +7,11 @@ #include "osspecificaspects.h" -#include +#include + +QT_BEGIN_NAMESPACE +class QString; +QT_END_NAMESPACE #ifdef Q_OS_WIN #define QTC_HOST_EXE_SUFFIX QTC_WIN_EXE_SUFFIX @@ -62,6 +44,7 @@ class UTILS_EXPORT HostOsInfo HostArchitectureAMD64, HostArchitectureItanium, HostArchitectureArm, + HostArchitectureArm64, HostArchitectureUnknown }; static auto hostArchitecture() -> HostArchitecture; @@ -78,6 +61,8 @@ class UTILS_EXPORT HostOsInfo #endif } + static auto isRunningUnderRosetta() -> bool; + static auto withExecutableSuffix(const QString &executable) -> QString { return OsSpecificAspects::withExecutableSuffix(hostOs(), executable); @@ -86,22 +71,27 @@ class UTILS_EXPORT HostOsInfo static void setOverrideFileNameCaseSensitivity(Qt::CaseSensitivity sensitivity); static void unsetOverrideFileNameCaseSensitivity(); - static Qt::CaseSensitivity fileNameCaseSensitivity() + static auto fileNameCaseSensitivity() -> Qt::CaseSensitivity { return m_useOverrideFileNameCaseSensitivity ? m_overrideFileNameCaseSensitivity : OsSpecificAspects::fileNameCaseSensitivity(hostOs()); } - static QChar pathListSeparator() { return OsSpecificAspects::pathListSeparator(hostOs()); } + static constexpr auto pathListSeparator() -> QChar + { + return OsSpecificAspects::pathListSeparator(hostOs()); + } - static Qt::KeyboardModifier controlModifier() + static constexpr auto controlModifier() -> Qt::KeyboardModifier { return OsSpecificAspects::controlModifier(hostOs()); } static auto canCreateOpenGLContext(QString *errorMessage) -> bool; + static auto totalMemoryInstalledInBytes() -> std::optional; + private: static Qt::CaseSensitivity m_overrideFileNameCaseSensitivity; static bool m_useOverrideFileNameCaseSensitivity; diff --git a/utils/logasync.cpp b/src/utils/logasync.cpp similarity index 65% rename from utils/logasync.cpp rename to src/utils/logasync.cpp index 4077b64..1c6fe27 100644 --- a/utils/logasync.cpp +++ b/src/utils/logasync.cpp @@ -11,27 +11,63 @@ namespace Utils { -#define ROLLSIZE 1000 * 1000 * 1000 +#define ROLLSIZE (1000 * 1000 * 1000) -const static int kRollPerSeconds_ = 60 * 60 * 24; +const static int g_kRollPerSeconds = 60 * 60 * 24; -struct FileUtilPrivate +static auto getFileName(qint64 seconds) -> QString { + auto data = QDateTime::fromSecsSinceEpoch(seconds).toString("yyyy-MM-dd-hh-mm-ss"); + auto filename = QString("%1/%2.%3.%4.%5.log") + .arg(LogAsync::instance()->logPath(), + qAppName(), + data, + QSysInfo::machineHostName(), + QString::number(qApp->applicationPid())); + return filename; +} + +static void autoDelFile() +{ + auto *instance = LogAsync::instance(); + const QString path(instance->logPath()); + QDir dir(path); + if (!dir.exists()) { + return; + } + + const QFileInfoList list = dir.entryInfoList(QDir::Files | QDir::NoDotAndDotDot, QDir::Time); + const QDateTime cur = QDateTime::currentDateTime(); + const QDateTime pre = cur.addDays(-instance->autoDelFileDays()); + + for (const QFileInfo &info : std::as_const(list)) { + if (info.lastModified() <= pre) { + dir.remove(info.fileName()); + } + } +} + +class FileUtil::FileUtilPrivate +{ +public: + explicit FileUtilPrivate(FileUtil *q) + : q_ptr(q) + {} + + FileUtil *q_ptr; + QFile file; //QTextStream 读写分离的,内部有缓冲区static const int QTEXTSTREAM_BUFFERSIZE = 16384; QTextStream stream; qint64 startTime = 0; qint64 lastRoll = 0; int count = 0; - qint64 autoDelFileDays = 30; }; -FileUtil::FileUtil(qint64 days, QObject *parent) +FileUtil::FileUtil(QObject *parent) : QObject(parent) - , d_ptr(new FileUtilPrivate) + , d_ptr(new FileUtilPrivate(this)) { - d_ptr->autoDelFileDays = days; - Utils::generateDirectorys(Utils::getConfigPath() + "/log"); rollFile(0); setTimer(); } @@ -47,7 +83,7 @@ void FileUtil::onWrite(const QString &msg) rollFile(++d_ptr->count); } else { qint64 now = QDateTime::currentSecsSinceEpoch(); - qint64 thisPeriod = now / kRollPerSeconds_ * kRollPerSeconds_; + qint64 thisPeriod = now / g_kRollPerSeconds * g_kRollPerSeconds; if (thisPeriod != d_ptr->startTime) { d_ptr->count = 0; rollFile(0); @@ -62,29 +98,16 @@ void FileUtil::onFlush() d_ptr->stream.flush(); } -QString FileUtil::getFileName(qint64 *now) const +auto FileUtil::rollFile(int count) -> bool { - *now = QDateTime::currentSecsSinceEpoch(); - QString data = QDateTime::fromSecsSinceEpoch(*now).toString("yyyy-MM-dd-hh-mm-ss"); - QString filename = QString("%1/log/%2.%3.%4.%5.log") - .arg(Utils::getConfigPath(), - qAppName(), - data, - QSysInfo::machineHostName(), - QString::number(qApp->applicationPid())); - return filename; -} - -bool FileUtil::rollFile(int count) -{ - qint64 now = 0; - QString filename = getFileName(&now); - if (count) { + qint64 now = QDateTime::currentSecsSinceEpoch(); + QString filename = getFileName(now); + if (count != 0) { filename += QString(".%1").arg(count); - } else { + } else if (LogAsync::instance()->autoDelFile()) { autoDelFile(); } - qint64 start = now / kRollPerSeconds_ * kRollPerSeconds_; + qint64 start = now / g_kRollPerSeconds * g_kRollPerSeconds; if (now > d_ptr->lastRoll) { d_ptr->startTime = start; d_ptr->lastRoll = now; @@ -101,26 +124,9 @@ bool FileUtil::rollFile(int count) return false; } -void FileUtil::autoDelFile() -{ - const QString path(Utils::getConfigPath() + "/log"); - Utils::generateDirectorys(path); - QDir dir(path); - - const QFileInfoList list = dir.entryInfoList(QDir::Files | QDir::NoDotAndDotDot, QDir::Time); - const QDateTime cur = QDateTime::currentDateTime(); - const QDateTime pre = cur.addDays(-d_ptr->autoDelFileDays); - - for (const QFileInfo &info : std::as_const(list)) { - if (info.lastModified() <= pre) { - dir.remove(info.fileName()); - } - } -} - void FileUtil::setTimer() { - QTimer *timer = new QTimer(this); + auto *timer = new QTimer(this); connect(timer, &QTimer::timeout, this, &FileUtil::onFlush); timer->start(5000); // 5秒刷新一次 } @@ -128,8 +134,10 @@ void FileUtil::setTimer() // 消息处理函数 void messageHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg) { - if (type < LogAsync::instance()->logLevel()) + auto *instance = LogAsync::instance(); + if (type < instance->logLevel()) { return; + } FILE *stdPrint = stdout; QString level; @@ -158,7 +166,7 @@ void messageHandler(QtMsgType type, const QMessageLogContext &context, const QSt } const QString dataTimeString(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss.zzz")); - const QString threadId = QString("%1").arg(qulonglong(QThread::currentThreadId()), + const QString threadId = QString("%1").arg(reinterpret_cast(QThread::currentThreadId()), 5, 10, QLatin1Char('0')); @@ -168,19 +176,19 @@ void messageHandler(QtMsgType type, const QMessageLogContext &context, const QSt #ifndef QT_NO_DEBUG contexInfo = QString("File:(%1) Line:(%2)").arg(context.file).arg(context.line); #endif - const QString message = QString("%1 %2 [%3] %4 - %5\n") - .arg(dataTimeString, threadId, level, msg, contexInfo); + const auto message = QString("%1 %2 [%3] %4 - %5\n") + .arg(dataTimeString, threadId, level, msg, contexInfo); - switch (LogAsync::instance()->orientation()) { + switch (instance->orientation()) { case LogAsync::Orientation::Std: fprintf(stdPrint, "%s", message.toLocal8Bit().constData()); ::fflush(stdPrint); break; - case LogAsync::Orientation::File: emit LogAsync::instance()->appendBuf(message); break; + case LogAsync::Orientation::File: emit instance->appendBuf(message); break; case LogAsync::Orientation::StdAndFile: fprintf(stdPrint, "%s", message.toLocal8Bit().constData()); ::fflush(stdPrint); - emit LogAsync::instance()->appendBuf(message); + emit instance->appendBuf(message); break; default: fprintf(stdPrint, "%s", message.toLocal8Bit().constData()); @@ -189,20 +197,60 @@ void messageHandler(QtMsgType type, const QMessageLogContext &context, const QSt } } -struct LogAsyncPrivate +class LogAsync::LogAsyncPrivate { +public: + explicit LogAsyncPrivate(LogAsync *q) + : q_ptr(q) + {} + + LogAsync *q_ptr; + + QString logPath; + bool autoDelFile = false; + qint64 autoDelFileDays = 7; QtMsgType msgType = QtWarningMsg; LogAsync::Orientation orientation = LogAsync::Orientation::Std; QWaitCondition waitCondition; QMutex mutex; }; +void LogAsync::setLogPath(const QString &path) +{ + d_ptr->logPath = path; +} + +auto LogAsync::logPath() -> QString +{ + return d_ptr->logPath; +} + +void LogAsync::setAutoDelFile(bool on) +{ + d_ptr->autoDelFile = on; +} + +auto LogAsync::autoDelFile() -> bool +{ + return d_ptr->autoDelFile; +} + +void LogAsync::setAutoDelFileDays(qint64 days) +{ + d_ptr->autoDelFileDays = days; +} + +auto LogAsync::autoDelFileDays() -> qint64 +{ + return d_ptr->autoDelFileDays; +} + void LogAsync::setOrientation(LogAsync::Orientation orientation) { d_ptr->orientation = orientation; } -LogAsync::Orientation LogAsync::orientation() +auto LogAsync::orientation() -> LogAsync::Orientation { return d_ptr->orientation; } @@ -212,7 +260,7 @@ void LogAsync::setLogLevel(QtMsgType type) d_ptr->msgType = type; } -QtMsgType LogAsync::logLevel() +auto LogAsync::logLevel() -> QtMsgType { return d_ptr->msgType; } @@ -243,7 +291,7 @@ void LogAsync::run() LogAsync::LogAsync(QObject *parent) : QThread(parent) - , d_ptr(new LogAsyncPrivate) + , d_ptr(new LogAsyncPrivate(this)) { qInstallMessageHandler(messageHandler); } diff --git a/utils/logasync.h b/src/utils/logasync.h similarity index 62% rename from utils/logasync.h rename to src/utils/logasync.h index c804deb..8f7820f 100644 --- a/utils/logasync.h +++ b/src/utils/logasync.h @@ -8,40 +8,46 @@ namespace Utils { -struct FileUtilPrivate; class FileUtil : public QObject { Q_OBJECT public: - explicit FileUtil(qint64 days = 7, QObject *parent = nullptr); + explicit FileUtil(QObject *parent = nullptr); ~FileUtil() override; public slots: - void onWrite(const QString &); + void onWrite(const QString & /*msg*/); private slots: void onFlush(); private: - auto getFileName(qint64 *now) const -> QString; - auto rollFile(int) -> bool; - void autoDelFile(); + auto rollFile(int /*count*/) -> bool; void setTimer(); + class FileUtilPrivate; QScopedPointer d_ptr; }; -struct LogAsyncPrivate; class UTILS_EXPORT LogAsync : public QThread { Q_OBJECT public: enum Orientation { Std = 1, File, StdAndFile }; - void setOrientation(Orientation); + void setLogPath(const QString &path); + auto logPath() -> QString; + + void setAutoDelFile(bool on); + auto autoDelFile() -> bool; + + void setAutoDelFileDays(qint64 days); + auto autoDelFileDays() -> qint64; + + void setOrientation(Orientation /*orientation*/); auto orientation() -> Orientation; - void setLogLevel(QtMsgType); + void setLogLevel(QtMsgType /*type*/); auto logLevel() -> QtMsgType; void startWork(); @@ -57,6 +63,7 @@ class UTILS_EXPORT LogAsync : public QThread explicit LogAsync(QObject *parent = nullptr); ~LogAsync() override; + class LogAsyncPrivate; QScopedPointer d_ptr; SINGLETON(LogAsync) diff --git a/src/utils/osspecificaspects.h b/src/utils/osspecificaspects.h new file mode 100644 index 0000000..dabcde8 --- /dev/null +++ b/src/utils/osspecificaspects.h @@ -0,0 +1,69 @@ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +#pragma once + +#include + +#include + +#define QTC_WIN_EXE_SUFFIX ".exe" + +namespace Utils { + +// Add more as needed. +enum OsType { OsTypeWindows, OsTypeLinux, OsTypeMac, OsTypeOtherUnix, OsTypeOther }; + +namespace OsSpecificAspects { + +inline auto withExecutableSuffix(OsType osType, const QString &executable) -> QString +{ + QString finalName = executable; + if (osType == OsTypeWindows && !finalName.endsWith(QTC_WIN_EXE_SUFFIX)) { + finalName += QLatin1String(QTC_WIN_EXE_SUFFIX); + } + return finalName; +} + +constexpr auto fileNameCaseSensitivity(OsType osType) -> Qt::CaseSensitivity +{ + return osType == OsTypeWindows || osType == OsTypeMac ? Qt::CaseInsensitive : Qt::CaseSensitive; +} + +constexpr auto envVarCaseSensitivity(OsType osType) -> Qt::CaseSensitivity +{ + return fileNameCaseSensitivity(osType); +} + +constexpr auto pathListSeparator(OsType osType) -> QChar +{ + return QLatin1Char(osType == OsTypeWindows ? ';' : ':'); +} + +constexpr auto controlModifier(OsType osType) -> Qt::KeyboardModifier +{ + return osType == OsTypeMac ? Qt::MetaModifier : Qt::ControlModifier; +} + +inline auto pathWithNativeSeparators(OsType osType, const QString &pathName) -> QString +{ + if (osType == OsTypeWindows) { + const int pos = pathName.indexOf('/'); + if (pos >= 0) { + QString n = pathName; + std::replace(std::begin(n) + pos, std::end(n), '/', '\\'); + return n; + } + } else { + const int pos = pathName.indexOf('\\'); + if (pos >= 0) { + QString n = pathName; + std::replace(std::begin(n) + pos, std::end(n), '\\', '/'); + return n; + } + } + return pathName; +} + +} // namespace OsSpecificAspects +} // namespace Utils diff --git a/utils/singleton.hpp b/src/utils/singleton.hpp similarity index 100% rename from utils/singleton.hpp rename to src/utils/singleton.hpp diff --git a/utils/speed.cc b/src/utils/speed.cc similarity index 100% rename from utils/speed.cc rename to src/utils/speed.cc diff --git a/utils/speed.hpp b/src/utils/speed.hpp similarity index 100% rename from utils/speed.hpp rename to src/utils/speed.hpp diff --git a/utils/threadsafequeue.hpp b/src/utils/threadsafequeue.hpp similarity index 100% rename from utils/threadsafequeue.hpp rename to src/utils/threadsafequeue.hpp diff --git a/src/utils/utils.cpp b/src/utils/utils.cpp new file mode 100644 index 0000000..9adc077 --- /dev/null +++ b/src/utils/utils.cpp @@ -0,0 +1,445 @@ +#include "utils.h" +#include "hostosinfo.h" + +#include +#include + +#ifdef Q_OS_WIN +#include + +#include +#endif + +QByteArray Utils::readAllFile(const QString &filePath) +{ + QFile file(filePath); + if (!file.open(QIODevice::ReadOnly)) { + qWarning() << QObject::tr("Cannot open the file: %1").arg(filePath); + return {}; + } + auto buf = file.readAll(); + file.close(); + return buf; +} + +float Utils::rangeMap(float value, float min, float max, float newMin, float newMax) +{ + Q_ASSERT(min <= max); + Q_ASSERT(newMin <= newMax); + Q_ASSERT(min <= value && value <= max); + return (value - min) * (newMax - newMin) / (max - min) + newMin; +} + +void Utils::setUTF8Code() +{ + QTextCodec::setCodecForLocale(QTextCodec::codecForName("UTF-8")); +} + +void Utils::setQSS(const QStringList &qssFilePaths) +{ + QString qss; + for (const auto &path : std::as_const(qssFilePaths)) { + qDebug() << QCoreApplication::translate("Utils", "Loading QSS file: %1.").arg(path); + QFile file(path); + if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { + qDebug() << QCoreApplication::translate("Utils", "Cannot open the file: %1!").arg(path) + << file.errorString(); + continue; + } + qss.append(QLatin1String(file.readAll())).append("\n"); + file.close(); + } + if (qss.isEmpty()) { + return; + } + qApp->setStyleSheet(qss); +} + +void Utils::loadFonts(const QString &fontPath) +{ + const QDir dir(fontPath); + if (!dir.exists()) { + return; + } + // QFontDatabase::removeAllApplicationFonts(); + const auto fonts = dir.entryInfoList(QStringList("*.ttf"), QDir::Files); + for (const auto &fileInfo : std::as_const(fonts)) { + int fontId = QFontDatabase::addApplicationFont(fileInfo.absoluteFilePath()); + if (fontId == -1) { + qWarning() << QString("Loading Fonts file: %1 Failed.").arg(fileInfo.fileName()); + } else { + qDebug() << QString("Loading Fonts file: %1.").arg(fileInfo.fileName()) + << QFontDatabase::applicationFontFamilies(fontId); + } + } +} + +void Utils::windowCenter(QWidget *child, QWidget *parent) +{ + const QSize size = parent->size() - child->size(); + int x = qMax(0, size.width() / 2); + int y = qMax(0, size.height() / 2); + child->move(x, y); +} + +void Utils::windowCenter(QWidget *window) +{ + const QRect rect = qApp->primaryScreen()->availableGeometry(); + int x = (rect.width() - window->width()) / 2 + rect.x(); + int y = (rect.height() - window->height()) / 2 + rect.y(); + x = qMax(0, x); + y = qMax(0, y); + window->move(x, y); +} + +auto compilerString() -> QString +{ +#if defined(__apple_build_version__) // Apple clang has other version numbers + QString isAppleString = QLatin1String(" (Apple)"); + return QLatin1String("Clang ") + QString::number(__clang_major__) + QLatin1Char('.') + + QString::number(__clang_minor__) + isAppleString; +#elif defined(Q_CC_GNU) + return QLatin1String("GCC ") + QLatin1String(__VERSION__); +#elif defined(Q_CC_MSVC) + return QString("MSVC Version: %1").arg(_MSC_VER); +#endif + return QLatin1String(""); +} + +auto Utils::systemInfo() -> QString +{ + auto text = QString("%1 (%2) on %3 (%4) with CPU Cores: %5") + .arg(QSysInfo::prettyProductName(), + QSysInfo::kernelVersion(), + QSysInfo::currentCpuArchitecture(), + QSysInfo::machineHostName(), + QString::number(QThread::idealThreadCount())) + + "\n" + + QString("Build with: Qt %1 (%2, %3)") + .arg(qVersion(), compilerString(), QSysInfo::buildAbi()); + return text; +} + +void Utils::setHighDpiEnvironmentVariable() +{ +#ifdef Q_OS_WIN + +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) + if (!qEnvironmentVariableIsSet("QT_DEVICE_PIXEL_RATIO") // legacy in 5.6, but still functional + && !qEnvironmentVariableIsSet("QT_AUTO_SCREEN_SCALE_FACTOR") + && !qEnvironmentVariableIsSet("QT_SCALE_FACTOR") + && !qEnvironmentVariableIsSet("QT_SCREEN_SCALE_FACTORS")) { + QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); + } +#endif + +#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0) + QGuiApplication::setHighDpiScaleFactorRoundingPolicy( + Qt::HighDpiScaleFactorRoundingPolicy::PassThrough); +#endif + +#endif // Q_OS_WIN +} + +void Utils::reboot() +{ + QProcess::startDetached(QApplication::applicationFilePath(), + QApplication::arguments(), + QDir::currentPath()); + QApplication::exit(); +} + +auto calculateDir(const QString &localPath) -> qint64 +{ + qint64 size = 0; + QDir dir(localPath); + if (!dir.exists()) { + return size; + } + QFileInfoList list = dir.entryInfoList(QDir::AllEntries | QDir::Hidden | QDir::NoDotAndDotDot); + for (int i = 0; i < list.count(); i++) { + const QFileInfo &info = list.at(i); + if (info.isDir()) { + size += calculateDir(info.filePath()); + } else { + size += info.size(); + } + } + return size; +} + +auto Utils::fileSize(const QString &localPath) -> qint64 +{ + QFileInfo info(localPath); + if (info.isDir()) { + return calculateDir(localPath); + } + return info.size(); +} + +auto Utils::generateDirectorys(const QString &directory) -> bool +{ + QDir sourceDir(directory); + if (sourceDir.exists()) { + return true; + } + + QString tempDir; + auto directorys = directory.split("/"); + for (int i = 0; i < directorys.count(); i++) { + auto path = directorys[i]; + tempDir += path + "/"; + + QDir dir(tempDir); + if (!dir.exists() && !dir.mkdir(tempDir)) { + return false; + } + } + + return true; +} + +void removeFiles(const QString &path) +{ + QDir dir(path); + if (!dir.exists()) { + return; + } + const QFileInfoList entries = dir.entryInfoList(QDir::AllEntries | QDir::Hidden); + for (const QFileInfo &fi : std::as_const(entries)) { + if (fi.isSymLink() || fi.isFile()) { + QFile f(fi.filePath()); + if (!f.remove()) { + const QString errorMessage + = QCoreApplication::translate("Utils", "Cannot remove file \"%1\": %2") + .arg(QDir::toNativeSeparators(f.fileName()), f.errorString()); + qWarning() << errorMessage; + } + } + } +} + +static auto errnoToQString(int error) -> QString +{ +#if defined(Q_OS_WIN) && !defined(Q_CC_MINGW) + char msg[128]; + if (strerror_s(msg, sizeof msg, error) != 0) { + return QString::fromLocal8Bit(msg); + } + return {}; +#else + return QString::fromLocal8Bit(strerror(error)); +#endif +} + +void Utils::removeDirectory(const QString &path) +{ + if (path.isEmpty()) { // QDir("") points to the working directory! We never want to remove that one. + return; + } + + QStringList dirs; + QDirIterator it(path, + QDir::NoDotAndDotDot | QDir::Dirs | QDir::NoSymLinks | QDir::Hidden, + QDirIterator::Subdirectories); + while (it.hasNext()) { + dirs.prepend(it.next()); + removeFiles(dirs.at(0)); + } + + QDir d; + dirs.append(path); + removeFiles(path); + for (const QString &dir : std::as_const(dirs)) { + errno = 0; + if (d.exists(path) && !d.rmdir(dir)) { + const QString errorMessage + = QCoreApplication::translate("Utils", "Cannot remove directory \"%1\": %2") + .arg(QDir::toNativeSeparators(dir), errnoToQString(errno)); + qWarning() << errorMessage; + } + } +} + +auto Utils::convertBytesToString(qint64 bytes) -> QString +{ + const QStringList list = {"B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"}; + const int unit = 1024; + int index = 0; + double size = bytes; + while (size >= unit) { + size /= unit; + index++; + } + return QString("%1 %2").arg(QString::number(size, 'f', 2)).arg(list.at(index)); +} + +auto Utils::jsonFromFile(const QString &filePath) -> QJsonObject +{ + QFile file(filePath); + if (!file.open(QIODevice::ReadOnly)) { + qWarning() << QCoreApplication::translate("Utils", "Cannot open the file: %1").arg(filePath); + return {}; + } + const QByteArray buf(file.readAll()); + file.close(); + return jsonFromBytes(buf); +} + +auto Utils::jsonFromBytes(const QByteArray &bytes) -> QJsonObject +{ + QJsonParseError jsonParseError; + auto jsonDocument = QJsonDocument::fromJson(bytes, &jsonParseError); + if (QJsonParseError::NoError != jsonParseError.error) { + qWarning() << QCoreApplication::translate("Utils", "%1\nOffset: %2") + .arg(jsonParseError.errorString(), jsonParseError.offset); + return {}; + } + return jsonDocument.object(); +} + +auto Utils::configLocation() -> QString +{ + static QString path; + if (path.isEmpty()) { + path = QStandardPaths::writableLocation(QStandardPaths::AppConfigLocation); + if (path.isEmpty()) { + path = QDir::homePath(); + } + } + //qInfo() << path; + Utils::generateDirectorys(path); + return path; +} + +auto Utils::execMenuAtWidget(QMenu *menu, QWidget *widget) -> QAction * +{ + QPoint p; + QRect screen = widget->screen()->availableGeometry(); + QSize sh = menu->sizeHint(); + QRect rect = widget->rect(); + if (widget->isRightToLeft()) { + if (widget->mapToGlobal(QPoint(0, rect.bottom())).y() + sh.height() <= screen.height()) { + p = widget->mapToGlobal(rect.bottomRight()); + } else { + p = widget->mapToGlobal(rect.topRight() - QPoint(0, sh.height())); + } + p.rx() -= sh.width(); + } else { + if (widget->mapToGlobal(QPoint(0, rect.bottom())).y() + sh.height() <= screen.height()) { + p = widget->mapToGlobal(rect.bottomLeft()); + } else { + p = widget->mapToGlobal(rect.topLeft() - QPoint(0, sh.height())); + } + } + p.rx() = qMax(screen.left(), qMin(p.x(), screen.right() - sh.width())); + p.ry() += 1; + + return menu->exec(p); +} + +auto Utils::getPidFromProcessName(const QString &processName) -> qint64 +{ +#if defined(Q_OS_WIN) + auto *hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); + if (hSnapshot == INVALID_HANDLE_VALUE) { + return -1; + } + PROCESSENTRY32 pe; + pe.dwSize = sizeof(PROCESSENTRY32); + if (!Process32First(hSnapshot, &pe)) { + CloseHandle(hSnapshot); + return -1; + } + do { + if (QString::fromWCharArray(pe.szExeFile) == processName) { + CloseHandle(hSnapshot); + return pe.th32ProcessID; + } + } while (Process32Next(hSnapshot, &pe)); + CloseHandle(hSnapshot); + return -1; +#else + // 创建一个QProcess对象 + QProcess process; + // 启动ps -A命令 + process.start("ps -A"); + // 等待命令执行完成 + process.waitForFinished(); + // 读取命令输出并转换为QString + auto output = QString::fromLocal8Bit(process.readAllStandardOutput()); + // 按行分割输出 + auto lines = output.split("\n"); + // 创建一个正则表达式对象,匹配以空格+processName结尾的字符串 + QRegularExpression re("\\s" + processName + "$"); + // 遍历输出的每一行 + for (const auto &line : lines) { + // 如果匹配成功 + if (re.match(line).hasMatch()) { + // 按空格分割字符串 + auto parts = line.split(" "); + // 返回pid + return parts.at(0).toLongLong(); + } + } + return -1; +#endif +} + +auto Utils::killProcess(qint64 pid) -> bool +{ + qWarning() << "kill process: " << pid; +#if defined(Q_OS_WIN) + auto *hProcess = OpenProcess(PROCESS_TERMINATE, FALSE, pid); + if (hProcess == nullptr) { + return false; + } + auto result = TerminateProcess(hProcess, 0); + CloseHandle(hProcess); + return result != 0; +#else + return QProcess::execute("kill", QStringList() << QString::number(pid)) == 0; +#endif +} + +void Utils::setMacComboBoxStyle(QWidget *parent) +{ +#ifndef Q_OS_MACOS + return; +#endif + auto comboBoxs = parent->findChildren(); + for (auto *const comboBox : comboBoxs) { + comboBox->setStyle(QStyleFactory::create("Fusion")); + } +} + +void Utils::quitApplication() +{ + QMetaObject::invokeMethod(qApp, &QApplication::quit, Qt::QueuedConnection); +} + +auto Utils::crashPath() -> QString +{ + const auto path = configLocation() + "/crash"; + generateDirectorys(path); + return path; +} + +auto Utils::logPath() -> QString +{ + const auto path = configLocation() + "/log"; + generateDirectorys(path); + return path; +} + +auto Utils::configPath() -> QString +{ + const auto path = configLocation() + "/config"; + generateDirectorys(path); + return path; +} + +auto Utils::configFilePath() -> QString +{ + return (configPath() + "/config.ini"); +} diff --git a/utils/utils.h b/src/utils/utils.h similarity index 57% rename from utils/utils.h rename to src/utils/utils.h index 3a82155..3951ad2 100644 --- a/utils/utils.h +++ b/src/utils/utils.h @@ -7,15 +7,26 @@ #include class QWidget; +class QAction; +class QMenu; namespace Utils { -UTILS_EXPORT void printBuildInfo(); +UTILS_EXPORT auto readAllFile(const QString &filePath) -> QByteArray; +UTILS_EXPORT auto rangeMap(float value, float min, float max, float newMin, float newMax) -> float; + +UTILS_EXPORT auto configLocation() -> QString; +UTILS_EXPORT auto configPath() -> QString; +UTILS_EXPORT auto configFilePath() -> QString; +UTILS_EXPORT auto crashPath() -> QString; +UTILS_EXPORT auto logPath() -> QString; + +UTILS_EXPORT auto systemInfo() -> QString; UTILS_EXPORT void setHighDpiEnvironmentVariable(); +UTILS_EXPORT void quitApplication(); UTILS_EXPORT void setUTF8Code(); -UTILS_EXPORT void setQSS(); -UTILS_EXPORT void loadFonts(); -UTILS_EXPORT void setGlobalThreadPoolMaxSize(int maxSize = -1); +UTILS_EXPORT void setQSS(const QStringList &qssFilePaths); +UTILS_EXPORT void loadFonts(const QString &fontPath); UTILS_EXPORT void windowCenter(QWidget *child, QWidget *parent); UTILS_EXPORT void windowCenter(QWidget *window); UTILS_EXPORT void reboot(); @@ -25,9 +36,10 @@ UTILS_EXPORT void removeDirectory(const QString &path); UTILS_EXPORT auto convertBytesToString(qint64 bytes) -> QString; UTILS_EXPORT auto jsonFromFile(const QString &filePath) -> QJsonObject; UTILS_EXPORT auto jsonFromBytes(const QByteArray &bytes) -> QJsonObject; -UTILS_EXPORT auto getConfigPath() -> QString; -UTILS_EXPORT auto readAllFile(const QString &filePath) -> QByteArray; -UTILS_EXPORT auto rangeMap(float value, float min, float max, float newMin, float newMax) -> float; +UTILS_EXPORT auto execMenuAtWidget(QMenu *menu, QWidget *widget) -> QAction *; +UTILS_EXPORT void setMacComboBoxStyle(QWidget *parent); +UTILS_EXPORT auto getPidFromProcessName(const QString &processName) -> qint64; +UTILS_EXPORT auto killProcess(qint64 pid) -> bool; } // namespace Utils diff --git a/utils/utils.pro b/src/utils/utils.pro similarity index 96% rename from utils/utils.pro rename to src/utils/utils.pro index a086d1d..073b28d 100644 --- a/utils/utils.pro +++ b/src/utils/utils.pro @@ -1,4 +1,4 @@ -include(../libs.pri) +include(../slib.pri) QT += widgets diff --git a/utils/utils_global.h b/src/utils/utils_global.h similarity index 100% rename from utils/utils_global.h rename to src/utils/utils_global.h diff --git a/src/utils/utilstr.h b/src/utils/utilstr.h new file mode 100644 index 0000000..5cfd23d --- /dev/null +++ b/src/utils/utilstr.h @@ -0,0 +1,15 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +#pragma once + +#include + +namespace Utils { + +struct Tr +{ + Q_DECLARE_TR_FUNCTIONS(QtC::Utils) +}; + +} // Utils diff --git a/tests/subtitle_unittest/subtitle_unittest.pro b/tests/subtitle_unittest/subtitle_unittest.pro index bb0bf66..d3e66e5 100644 --- a/tests/subtitle_unittest/subtitle_unittest.pro +++ b/tests/subtitle_unittest/subtitle_unittest.pro @@ -1,4 +1,4 @@ -include(../../Common.pri) +include(../../common.pri) QT += core gui network multimedia openglwidgets core5compat @@ -12,7 +12,7 @@ LIBS += -L$$APP_OUTPUT_PATH/../libs \ -l$$replaceLibName(ffmpeg) \ -l$$replaceLibName(utils) -include(../../3rdparty/3rdparty.pri) +include(../../src/3rdparty/3rdparty.pri) SOURCES += \ main.cc \ diff --git a/utils/hostosinfo.cpp b/utils/hostosinfo.cpp deleted file mode 100644 index 8a3c0e8..0000000 --- a/utils/hostosinfo.cpp +++ /dev/null @@ -1,98 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of Qt Creator. -** -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -****************************************************************************/ - -#include "hostosinfo.h" - -#include - -#if !defined(QT_NO_OPENGL) && defined(QT_GUI_LIB) -#include -#endif - -#ifdef Q_OS_WIN -#undef _WIN32_WINNT -#define _WIN32_WINNT 0x0501 /* WinXP, needed for GetNativeSystemInfo() */ -#include -#endif - -using namespace Utils; - -Qt::CaseSensitivity HostOsInfo::m_overrideFileNameCaseSensitivity = Qt::CaseSensitive; -bool HostOsInfo::m_useOverrideFileNameCaseSensitivity = false; - -#ifdef Q_OS_WIN -static WORD hostProcessorArchitecture() -{ - SYSTEM_INFO info; - GetNativeSystemInfo(&info); - return info.wProcessorArchitecture; -} -#endif - -HostOsInfo::HostArchitecture HostOsInfo::hostArchitecture() -{ -#ifdef Q_OS_WIN - static const WORD processorArchitecture = hostProcessorArchitecture(); - switch (processorArchitecture) { - case PROCESSOR_ARCHITECTURE_AMD64: - return HostOsInfo::HostArchitectureAMD64; - case PROCESSOR_ARCHITECTURE_INTEL: - return HostOsInfo::HostArchitectureX86; - case PROCESSOR_ARCHITECTURE_IA64: - return HostOsInfo::HostArchitectureItanium; - case PROCESSOR_ARCHITECTURE_ARM: - return HostOsInfo::HostArchitectureArm; - default: - return HostOsInfo::HostArchitectureUnknown; - } -#else - return HostOsInfo::HostArchitectureUnknown; -#endif -} - -void HostOsInfo::setOverrideFileNameCaseSensitivity(Qt::CaseSensitivity sensitivity) -{ - m_useOverrideFileNameCaseSensitivity = true; - m_overrideFileNameCaseSensitivity = sensitivity; -} - -void HostOsInfo::unsetOverrideFileNameCaseSensitivity() -{ - m_useOverrideFileNameCaseSensitivity = false; -} - -bool HostOsInfo::canCreateOpenGLContext(QString *errorMessage) -{ -#if defined(QT_NO_OPENGL) || !defined(QT_GUI_LIB) - Q_UNUSED(errorMessage) - return false; -#else - static const bool canCreate = QOpenGLContext().create(); - if (!canCreate) - *errorMessage = QCoreApplication::translate("Utils::HostOsInfo", - "Cannot create OpenGL context."); - return canCreate; -#endif -} diff --git a/utils/osspecificaspects.h b/utils/osspecificaspects.h deleted file mode 100644 index d60a584..0000000 --- a/utils/osspecificaspects.h +++ /dev/null @@ -1,83 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of Qt Creator. -** -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -****************************************************************************/ - -#pragma once - -#include - -#include - -#define QTC_WIN_EXE_SUFFIX ".exe" - -namespace Utils { - -// Add more as needed. -enum OsType { OsTypeWindows, OsTypeLinux, OsTypeMac, OsTypeOtherUnix, OsTypeOther }; - -namespace OsSpecificAspects { - -inline auto withExecutableSuffix(OsType osType, const QString &executable) -> QString -{ - QString finalName = executable; - if (osType == OsTypeWindows) - finalName += QLatin1String(QTC_WIN_EXE_SUFFIX); - return finalName; -} - -inline Qt::CaseSensitivity fileNameCaseSensitivity(OsType osType) -{ - return osType == OsTypeWindows || osType == OsTypeMac ? Qt::CaseInsensitive : Qt::CaseSensitive; -} - -inline Qt::CaseSensitivity envVarCaseSensitivity(OsType osType) -{ - return fileNameCaseSensitivity(osType); -} - -inline QChar pathListSeparator(OsType osType) -{ - return QLatin1Char(osType == OsTypeWindows ? ';' : ':'); -} - -inline Qt::KeyboardModifier controlModifier(OsType osType) -{ - return osType == OsTypeMac ? Qt::MetaModifier : Qt::ControlModifier; -} - -inline auto pathWithNativeSeparators(OsType osType, const QString &pathName) -> QString -{ - if (osType == OsTypeWindows) { - const int pos = pathName.indexOf('/'); - if (pos >= 0) { - QString n = pathName; - std::replace(std::begin(n) + pos, std::end(n), '/', '\\'); - return n; - } - } - return pathName; -} - -} // namespace OsSpecificAspects -} // namespace Utils diff --git a/utils/utils.cpp b/utils/utils.cpp deleted file mode 100644 index 8ea729b..0000000 --- a/utils/utils.cpp +++ /dev/null @@ -1,302 +0,0 @@ -#include "utils.h" -#include "hostosinfo.h" - -#include -#include - -void Utils::setUTF8Code() -{ - QTextCodec::setCodecForLocale(QTextCodec::codecForName("UTF-8")); -} - -void Utils::setQSS() -{ - const QJsonObject json(jsonFromFile(qApp->applicationDirPath() + "/config/config.json")); - const QStringList qssPath(json.value("qss_files").toVariant().toStringList()); - QString qss; - for (const QString &path : std::as_const(qssPath)) { - qDebug() << QObject::tr("Loading QSS file: %1.").arg(path); - QFile file(path); - if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { - qDebug() << QObject::tr("Cannot open the file: %1!").arg(path) << file.errorString(); - continue; - } - qss.append(QLatin1String(file.readAll())).append("\n"); - file.close(); - } - if (qss.isEmpty()) - return; - qApp->setStyleSheet(qss); -} - -void Utils::loadFonts() -{ - const QJsonObject json(jsonFromFile(qApp->applicationDirPath() + "/config/config.json")); - const QStringList fontFiles(json.value("font_files").toVariant().toStringList()); - - for (const QString &file : std::as_const(fontFiles)) { - qDebug() << QObject::tr("Loading Font file: %1").arg(file); - QFontDatabase::addApplicationFont(file); - } -} - -void Utils::windowCenter(QWidget *child, QWidget *parent) -{ - const QSize size = parent->size() - child->size(); - int x = qMax(0, size.width() / 2); - int y = qMax(0, size.height() / 2); - child->move(x, y); -} - -void Utils::windowCenter(QWidget *window) -{ - const QRect rect = qApp->primaryScreen()->availableGeometry(); - int x = (rect.width() - window->width()) / 2 + rect.x(); - int y = (rect.height() - window->height()) / 2 + rect.y(); - x = qMax(0, x); - y = qMax(0, y); - window->move(x, y); -} - -auto compilerString() -> QString -{ -#if defined(__apple_build_version__) // Apple clang has other version numbers - QString isAppleString = QLatin1String(" (Apple)"); - return QLatin1String("Clang ") + QString::number(__clang_major__) + QLatin1Char('.') - + QString::number(__clang_minor__) + isAppleString; -#elif defined(Q_CC_GNU) - return QLatin1String("GCC ") + QLatin1String(__VERSION__); -#elif defined(Q_CC_MSVC) - return QString("MSVC Version: %1").arg(_MSC_VER); -#endif - return QLatin1String(""); -} - -void Utils::printBuildInfo() -{ - // qInfo() << QSysInfo::buildAbi() << QSysInfo::machineUniqueId() - // << QOperatingSystemVersion::current(); - const QString info = QString("Qt %1 (%2, %3 bit)") - .arg(qVersion(), compilerString(), QString::number(QSysInfo::WordSize)); - qInfo() << QObject::tr("Build with: ") << info; -} - -void Utils::setHighDpiEnvironmentVariable() -{ - if (Utils::HostOsInfo::isMacHost()) { - return; - } - - if (Utils::HostOsInfo::isWindowsHost() - && !qEnvironmentVariableIsSet("QT_DEVICE_PIXEL_RATIO") // legacy in 5.6, but still functional - && !qEnvironmentVariableIsSet("QT_AUTO_SCREEN_SCALE_FACTOR") - && !qEnvironmentVariableIsSet("QT_SCALE_FACTOR") - && !qEnvironmentVariableIsSet("QT_SCREEN_SCALE_FACTORS")) { -#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) - QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); -#endif - } - -#if defined(Q_OS_WIN) && (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)) - QGuiApplication::setHighDpiScaleFactorRoundingPolicy( - Qt::HighDpiScaleFactorRoundingPolicy::PassThrough); -#endif -} - -void Utils::reboot() -{ - QProcess::startDetached(QApplication::applicationFilePath(), - QApplication::arguments(), - QDir::currentPath()); - QApplication::exit(); -} - -auto calculateDir(const QString &localPath) -> qint64 -{ - qint64 size = 0; - QDir dir(localPath); - if (!dir.exists()) { - return size; - } - QFileInfoList list = dir.entryInfoList(QDir::AllEntries | QDir::Hidden | QDir::NoDotAndDotDot); - for (int i = 0; i < list.count(); i++) { - QFileInfo info = list.at(i); - if (info.isDir()) { - size += calculateDir(info.filePath()); - } else { - size += info.size(); - } - } - return size; -} - -auto Utils::fileSize(const QString &localPath) -> qint64 -{ - QFileInfo info(localPath); - if (info.isDir()) { - return calculateDir(localPath); - } else { - return info.size(); - } -} - -auto Utils::generateDirectorys(const QString &directory) -> bool -{ - QDir sourceDir(directory); - if (sourceDir.exists()) { - return true; - } - - QString tempDir; - auto directorys = directory.split("/"); - for (int i = 0; i < directorys.count(); i++) { - auto path = directorys[i]; - tempDir += path + "/"; - - QDir dir(tempDir); - if (!dir.exists() && !dir.mkdir(tempDir)) { - return false; - } - } - - return true; -} - -void removeFiles(const QString &path) -{ - QDir dir(path); - if (!dir.exists()) { - return; - } - const QFileInfoList entries = dir.entryInfoList(QDir::AllEntries | QDir::Hidden); - for (const QFileInfo &fi : std::as_const(entries)) { - if (fi.isSymLink() || fi.isFile()) { - QFile f(fi.filePath()); - if (!f.remove()) { - const QString errorMessage = QObject::tr("Cannot remove file \"%1\": %2") - .arg(QDir::toNativeSeparators(f.fileName()), - f.errorString()); - qWarning() << errorMessage; - } - } - } -} - -static auto errnoToQString(int error) -> QString -{ -#if defined(Q_OS_WIN) && !defined(Q_CC_MINGW) - char msg[128]; - if (strerror_s(msg, sizeof msg, error) != 0) - return QString::fromLocal8Bit(msg); - return {}; -#else - return QString::fromLocal8Bit(strerror(error)); -#endif -} - -void Utils::removeDirectory(const QString &path) -{ - if (path.isEmpty()) { // QDir("") points to the working directory! We never want to remove that one. - return; - } - - QStringList dirs; - QDirIterator it(path, - QDir::NoDotAndDotDot | QDir::Dirs | QDir::NoSymLinks | QDir::Hidden, - QDirIterator::Subdirectories); - while (it.hasNext()) { - dirs.prepend(it.next()); - removeFiles(dirs.at(0)); - } - - QDir d; - dirs.append(path); - removeFiles(path); - for (const QString &dir : std::as_const(dirs)) { - errno = 0; - if (d.exists(path) && !d.rmdir(dir)) { - const QString errorMessage = QObject::tr("Cannot remove directory \"%1\": %2") - .arg(QDir::toNativeSeparators(dir), - errnoToQString(errno)); - qWarning() << errorMessage; - } - } -} - -auto Utils::convertBytesToString(qint64 bytes) -> QString -{ - const QStringList list = {"B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"}; - const int unit = 1024; - int index = 0; - double size = bytes; - while (size >= unit) { - size /= unit; - index++; - } - return QString("%1 %2").arg(QString::number(size, 'f', 2)).arg(list.at(index)); -} - -QJsonObject Utils::jsonFromFile(const QString &filePath) -{ - const QByteArray buf(readAllFile(filePath)); - return jsonFromBytes(buf); -} - -QJsonObject Utils::jsonFromBytes(const QByteArray &bytes) -{ - QJsonParseError jsonParseError; - auto jsonDocument = QJsonDocument::fromJson(bytes, &jsonParseError); - if (QJsonParseError::NoError != jsonParseError.error) { - qWarning() << QObject::tr("%1\nOffset: %2") - .arg(jsonParseError.errorString(), jsonParseError.offset); - return {}; - } - return jsonDocument.object(); -} - -void Utils::setGlobalThreadPoolMaxSize(int maxSize) -{ - auto *instance = QThreadPool::globalInstance(); - if (maxSize > 0) { - instance->setMaxThreadCount(maxSize); - return; - } - instance->setMaxThreadCount(qMax(4, 2 * instance->maxThreadCount())); -} - -auto Utils::getConfigPath() -> QString -{ - static QString path; - if (path.isEmpty()) { - path = QStandardPaths::writableLocation(QStandardPaths::AppConfigLocation); - if (path.isEmpty()) { - path = QDir::homePath(); - } - if (!path.endsWith(qAppName())) { - path = path + "/" + qAppName(); - } - } - //qInfo() << path; - Utils::generateDirectorys(path); - return path; -} - -QByteArray Utils::readAllFile(const QString &filePath) -{ - QFile file(filePath); - if (!file.open(QIODevice::ReadOnly)) { - qWarning() << QObject::tr("Cannot open the file: %1").arg(filePath); - return {}; - } - auto buf = file.readAll(); - file.close(); - return buf; -} - -float Utils::rangeMap(float value, float min, float max, float newMin, float newMax) -{ - Q_ASSERT(min <= max); - Q_ASSERT(newMin <= newMax); - Q_ASSERT(min <= value && value <= max); - return (value - min) * (newMax - newMin) / (max - min) + newMin; -} diff --git a/vcpkg.json b/vcpkg.json index cc21a93..3b0e9bb 100644 --- a/vcpkg.json +++ b/vcpkg.json @@ -5,6 +5,7 @@ "description": "manifest", "dependencies": [ "breakpad", + "crashpad", { "name": "ffmpeg", "features": [ @@ -33,5 +34,5 @@ ] } ], - "builtin-baseline": "3c76dc55f8bd2b7f4824bcd860055094bfbbb9ea" + "builtin-baseline": "dee924de74e81388140a53c32a919ecec57d20ab" } \ No newline at end of file