This commit is contained in:
Megamouse 2021-05-22 10:42:05 +02:00 committed by Elad Ashkenazi
parent 9b3a878c18
commit d119cf6e96
54 changed files with 431 additions and 595 deletions

View file

@ -1,10 +1,5 @@
#!/bin/sh -ex
# Setup Qt variables
export QT_BASE_DIR=/opt/qt"${QTVERMIN}"
export PATH="$QT_BASE_DIR"/bin:"$PATH"
export LD_LIBRARY_PATH="$QT_BASE_DIR"/lib/x86_64-linux-gnu:"$QT_BASE_DIR"/lib
if [ -z "$CIRRUS_CI" ]; then
cd rpcs3 || exit 1
fi

View file

@ -28,23 +28,24 @@ export WORKDIR;
WORKDIR="$(pwd)"
# Get Qt
if [ ! -d "/tmp/Qt/5.15.2" ]; then
if [ ! -d "/tmp/Qt/$QT_VER" ]; then
mkdir -p "/tmp/Qt"
git clone https://github.com/engnr/qt-downloader.git
cd qt-downloader
git checkout f52efee0f18668c6d6de2dec0234b8c4bc54c597
cd "/tmp/Qt"
"/opt/homebrew/bin/pipenv" run pip3 install py7zr requests semantic_version lxml
"/opt/homebrew/bin/pipenv" run "$WORKDIR/qt-downloader/qt-downloader" macos desktop 5.15.2 clang_64 --opensource
mkdir -p "$QT_VER/macos" ; ln -s "macos" "$QT_VER/clang_64"
"/opt/homebrew/bin/pipenv" run "$WORKDIR/qt-downloader/qt-downloader" macos desktop "$QT_VER" clang_64 --opensource --addons qtmultimedia
fi
cd "$WORKDIR"
ditto "/tmp/Qt/5.15.2" "qt-downloader/5.15.2"
ditto "/tmp/Qt/$QT_VER" "qt-downloader/$QT_VER"
export Qt5_DIR="$WORKDIR/qt-downloader/5.15.2/clang_64/lib/cmake/Qt5"
export Qt6_DIR="$WORKDIR/qt-downloader/$QT_VER/clang_64/lib/cmake/Qt$QT_VER_MAIN"
export SDL2_DIR="$BREW_X64_PATH/opt/sdl2/lib/cmake/SDL2"
export PATH="$BREW_X64_PATH/opt/llvm@16/bin:$WORKDIR/qt-downloader/5.15.2/clang_64/bin:$BREW_BIN:$BREW_SBIN:/usr/bin:/bin:/usr/sbin:/sbin:/opt/X11/bin:/Library/Apple/usr/bin:$PATH"
export PATH="$BREW_X64_PATH/opt/llvm@16/bin:$WORKDIR/qt-downloader/$QT_VER/clang_64/bin:$BREW_BIN:$BREW_SBIN:/usr/bin:/bin:/usr/sbin:/sbin:/opt/X11/bin:/Library/Apple/usr/bin:$PATH"
export LDFLAGS="-L$BREW_X64_PATH/lib -Wl,-rpath,$BREW_X64_PATH/lib"
export CPPFLAGS="-I$BREW_X64_PATH/include -msse -msse2 -mcx16 -no-pie"
export LIBRARY_PATH="$BREW_X64_PATH/lib"
@ -67,16 +68,30 @@ sed -i '' "s/extern const double NSAppKitVersionNumber;/const double NSAppKitVer
mkdir build && cd build || exit 1
"$BREW_X64_PATH/bin/cmake" .. \
-DUSE_SDL=ON -DUSE_DISCORD_RPC=ON -DUSE_VULKAN=ON -DUSE_ALSA=OFF -DUSE_PULSE=OFF -DUSE_AUDIOUNIT=ON \
-DLLVM_CCACHE_BUILD=OFF -DLLVM_BUILD_RUNTIME=OFF -DLLVM_BUILD_TOOLS=OFF \
-DLLVM_INCLUDE_DOCS=OFF -DLLVM_INCLUDE_EXAMPLES=OFF -DLLVM_INCLUDE_TESTS=OFF -DLLVM_INCLUDE_TOOLS=OFF \
-DLLVM_INCLUDE_UTILS=OFF -DLLVM_USE_PERF=OFF -DLLVM_ENABLE_Z3_SOLVER=OFF \
-DUSE_SDL=ON \
-DUSE_DISCORD_RPC=ON \
-DUSE_VULKAN=ON \
-DUSE_ALSA=OFF \
-DUSE_PULSE=OFF \
-DUSE_AUDIOUNIT=ON \
-DLLVM_CCACHE_BUILD=OFF \
-DLLVM_BUILD_RUNTIME=OFF \
-DLLVM_BUILD_TOOLS=OFF \
-DLLVM_INCLUDE_DOCS=OFF \
-DLLVM_INCLUDE_EXAMPLES=OFF \
-DLLVM_INCLUDE_TESTS=OFF \
-DLLVM_INCLUDE_TOOLS=OFF \
-DLLVM_INCLUDE_UTILS=OFF \
-DLLVM_USE_PERF=OFF \
-DLLVM_ENABLE_Z3_SOLVER=OFF \
-DUSE_NATIVE_INSTRUCTIONS=OFF \
-DUSE_SYSTEM_MVK=ON \
-DUSE_SYSTEM_FAUDIO=ON \
-DUSE_SYSTEM_SDL=ON \
$CMAKE_EXTRA_OPTS \
-DLLVM_TARGET_ARCH=X86_64 -DCMAKE_OSX_ARCHITECTURES=x86_64 -DCMAKE_IGNORE_PATH="$BREW_PATH/lib" \
-DLLVM_TARGET_ARCH=X86_64 \
-DCMAKE_OSX_ARCHITECTURES=x86_64 \
-DCMAKE_IGNORE_PATH="$BREW_PATH/lib" \
-G Ninja
"$BREW_PATH/bin/ninja"; build_status=$?;

View file

@ -2,7 +2,7 @@
# NOTE: this script is run under root permissions
# shellcheck shell=sh disable=SC2096
# RPCS3 often needs recent Qt5 and Vulkan-Headers
# RPCS3 often needs recent Qt and Vulkan-Headers
sed -i '' 's/quarterly/latest/' /etc/pkg/FreeBSD.conf
export ASSUME_ALWAYS_YES=true
@ -11,8 +11,8 @@ pkg info # debug
# Prefer newer Clang than in base system (see also .ci/build-freebsd.sh)
pkg install llvm16
# Mandatory dependencies (qt5-dbus and qt5-gui are pulled via qt5-widgets)
pkg install git ccache cmake ninja qt5-qmake qt5-buildtools qt5-widgets qt5-concurrent qt5-multimedia qt5-svg glew openal-soft ffmpeg
# Mandatory dependencies (qt6-base and qt6-svg are pulled via qt6-multimedia)
pkg install git ccache cmake ninja qt6-multimedia glew openal-soft ffmpeg
# Optional dependencies (libevdev is pulled by qt5-gui)
# Optional dependencies (libevdev is pulled by qt6-base)
pkg install pkgconf alsa-lib pulseaudio sdl2 evdev-proto vulkan-headers vulkan-loader

View file

@ -11,25 +11,26 @@ PR_NUMBER="$SYSTEM_PULLREQUEST_PULLREQUESTID"
QT_HOST="http://qt.mirror.constant.com/"
QT_URL_VER=$(echo "$QT_VER" | sed "s/\.//g")
QT_VER_MSVC_UP=$(echo "${QT_VER_MSVC}" | tr '[:lower:]' '[:upper:]')
QT_PREFIX="online/qtsdkrepository/windows_x86/desktop/qt${QT_VER_MAIN}_${QT_URL_VER}/qt.qt${QT_VER_MAIN}.${QT_URL_VER}.win64_${QT_VER_MSVC}_64/${QT_VER}-0-${QT_DATE}"
QT_SUFFIX="-Windows-Windows_10-${QT_VER_MSVC_UP}-Windows-Windows_10-X86_64.7z"
QT_BASE_URL="${QT_HOST}${QT_PREFIX}qtbase${QT_SUFFIX}"
QT_WINE_URL="${QT_HOST}${QT_PREFIX}qtwinextras${QT_SUFFIX}"
QT_DECL_URL="${QT_HOST}${QT_PREFIX}qtdeclarative${QT_SUFFIX}"
QT_TOOL_URL="${QT_HOST}${QT_PREFIX}qttools${QT_SUFFIX}"
QT_MM_URL="${QT_HOST}${QT_PREFIX}qtmultimedia${QT_SUFFIX}"
QT_SVG_URL="${QT_HOST}${QT_PREFIX}qtsvg${QT_SUFFIX}"
QT_PREFIX="online/qtsdkrepository/windows_x86/desktop/qt${QT_VER_MAIN}_${QT_URL_VER}/qt.qt${QT_VER_MAIN}.${QT_URL_VER}."
QT_PREFIX_2="win64_${QT_VER_MSVC}_64/${QT_VER}-0-${QT_DATE}"
QT_SUFFIX="-Windows-Windows_10_22H2-${QT_VER_MSVC_UP}-Windows-Windows_10_22H2-X86_64.7z"
QT_BASE_URL="${QT_HOST}${QT_PREFIX}${QT_PREFIX_2}qtbase${QT_SUFFIX}"
QT_DECL_URL="${QT_HOST}${QT_PREFIX}${QT_PREFIX_2}qtdeclarative${QT_SUFFIX}"
QT_TOOL_URL="${QT_HOST}${QT_PREFIX}${QT_PREFIX_2}qttools${QT_SUFFIX}"
QT_MM_URL="${QT_HOST}${QT_PREFIX}addons.qtmultimedia.${QT_PREFIX_2}qtmultimedia${QT_SUFFIX}"
QT_SVG_URL="${QT_HOST}${QT_PREFIX}${QT_PREFIX_2}qtsvg${QT_SUFFIX}"
QT_5CMP_URL="${QT_HOST}${QT_PREFIX}qt5compat.${QT_PREFIX_2}qt5compat${QT_SUFFIX}"
LLVMLIBS_URL='https://github.com/RPCS3/llvm-mirror/releases/download/custom-build-win-16.0.1/llvmlibs_mt.7z'
GLSLANG_URL='https://github.com/RPCS3/glslang/releases/download/custom-build-win/glslanglibs_mt.7z'
VULKAN_SDK_URL="https://www.dropbox.com/s/cs77c3iv5mbo0bt/VulkanSDK-${VULKAN_VER}-Installer.exe"
DEP_URLS=" \
$QT_BASE_URL \
$QT_WINE_URL \
$QT_DECL_URL \
$QT_TOOL_URL \
$QT_MM_URL \
$QT_SVG_URL \
$QT_5CMP_URL \
$LLVMLIBS_URL \
$GLSLANG_URL \
$VULKAN_SDK_URL"

View file

@ -6,6 +6,8 @@ env:
BUILD_SOURCEVERSION: $CIRRUS_CHANGE_IN_REPO
BUILD_SOURCEBRANCHNAME: $CIRRUS_BRANCH
RPCS3_TOKEN: ENCRYPTED[!a4c3850e29ab150692286a74bec29819d25971a7ec431b86de2a35f7ed90c5b2ab3c93469f9298e30924d843599110e9!]
QT_VER_MAIN: '6'
QT_VER: '6.5.2'
windows_task:
matrix:
@ -17,11 +19,9 @@ windows_task:
env:
CIRRUS_SHELL: "bash"
COMPILER: msvc
QT_VER_MAIN: '5'
BUILD_ARTIFACTSTAGINGDIRECTORY: ${CIRRUS_WORKING_DIR}\artifacts\
QT_VER: '5.15.2'
QT_VER_MSVC: 'msvc2019'
QT_DATE: '202011130602'
QT_DATE: '202307080351'
QTDIR: C:\Qt\${QT_VER}\${QT_VER_MSVC}_64
VULKAN_VER: '1.3.224.1'
VULKAN_SDK_SHA: '2029e652e39ee6a6036cff3765da31e1e6c595fd2413d3cd111dfab7855621ea'
@ -61,7 +61,7 @@ windows_task:
linux_task:
container:
image: rpcs3/rpcs3-ci-bionic:1.8
image: rpcs3/rpcs3-ci-focal:1.0
cpu: 4
memory: 16G
env:

45
3rdparty/qt5.cmake vendored
View file

@ -1,45 +0,0 @@
add_library(3rdparty_qt5 INTERFACE)
set(QT_MIN_VER 5.15.2)
find_package(Qt5 ${QT_MIN_VER} CONFIG COMPONENTS Widgets Concurrent Multimedia MultimediaWidgets Svg)
if(WIN32)
find_package(Qt5 ${QT_MIN_VER} COMPONENTS WinExtras REQUIRED)
target_link_libraries(3rdparty_qt5 INTERFACE Qt5::Widgets Qt5::WinExtras Qt5::Concurrent Qt5::Multimedia Qt5::MultimediaWidgets Qt5::Svg)
else()
find_package(Qt5 ${QT_MIN_VER} COMPONENTS DBus Gui)
if(Qt5DBus_FOUND)
target_link_libraries(3rdparty_qt5 INTERFACE Qt5::Widgets Qt5::DBus Qt5::Concurrent Qt5::Multimedia Qt5::MultimediaWidgets Qt5::Svg)
target_compile_definitions(3rdparty_qt5 INTERFACE -DHAVE_QTDBUS)
else()
target_link_libraries(3rdparty_qt5 INTERFACE Qt5::Widgets Qt5::Concurrent Qt5::Multimedia Qt5::MultimediaWidgets Qt5::Svg)
endif()
target_include_directories(3rdparty_qt5 INTERFACE ${Qt5Gui_PRIVATE_INCLUDE_DIRS})
endif()
if(NOT Qt5Widgets_FOUND)
if(Qt5Widgets_VERSION VERSION_LESS ${QT_MIN_VER})
message("Minimum supported Qt5 version is ${QT_MIN_VER}! You have version ${Qt5Widgets_VERSION} installed, please upgrade!")
if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
message(FATAL_ERROR "Most distros do not provide an up-to-date version of Qt.
If you're on Ubuntu or Linux Mint, there are PPAs you can use to install one of the latest qt5 versions.
Find the correct ppa at https://launchpad.net/~beineri and follow the instructions.")
elseif(WIN32)
message(FATAL_ERROR "You can download the latest version of Qt5 here: https://www.qt.io/download-open-source/")
else()
message(FATAL_ERROR "Look online for instructions on installing an up-to-date Qt5 on ${CMAKE_SYSTEM}.")
endif()
endif()
message("CMake was unable to find Qt5!")
if(WIN32)
message(FATAL_ERROR "Make sure the QTDIR env variable has been set properly. (for example C:\\Qt\\${QT_MIN_VER}\\msvc2019_64\\)
You can also try setting the Qt5_DIR preprocessor definiton.")
elseif(CMAKE_SYSTEM_NAME STREQUAL "Linux")
message(FATAL_ERROR "Make sure to install your distro's qt5 package!")
else()
message(FATAL_ERROR "You need to have Qt5 installed, look online for instructions on installing Qt5 on ${CMAKE_SYSTEM}.")
endif()
endif()
add_library(3rdparty::qt5 ALIAS 3rdparty_qt5)

45
3rdparty/qt6.cmake vendored Normal file
View file

@ -0,0 +1,45 @@
add_library(3rdparty_qt6 INTERFACE)
set(QT_MIN_VER 6.4.0)
find_package(Qt6 ${QT_MIN_VER} CONFIG COMPONENTS Widgets Concurrent Multimedia MultimediaWidgets Svg SvgWidgets)
if(WIN32)
find_package(Qt6 ${QT_MIN_VER} COMPONENTS WinExtras REQUIRED)
target_link_libraries(3rdparty_qt6 INTERFACE Qt6::Widgets Qt6::WinExtras Qt6::Concurrent Qt6::Multimedia Qt6::MultimediaWidgets Qt6::Svg Qt6::SvgWidgets)
else()
find_package(Qt6 ${QT_MIN_VER} COMPONENTS DBus Gui)
if(Qt6DBus_FOUND)
target_link_libraries(3rdparty_qt6 INTERFACE Qt6::Widgets Qt6::DBus Qt6::Concurrent Qt6::Multimedia Qt6::MultimediaWidgets Qt6::Svg Qt6::SvgWidgets)
target_compile_definitions(3rdparty_qt6 INTERFACE -DHAVE_QTDBUS)
else()
target_link_libraries(3rdparty_qt6 INTERFACE Qt6::Widgets Qt6::Concurrent Qt6::Multimedia Qt6::MultimediaWidgets Qt6::Svg Qt6::SvgWidgets)
endif()
target_include_directories(3rdparty_qt6 INTERFACE ${Qt6Gui_PRIVATE_INCLUDE_DIRS})
endif()
if(Qt6Widgets_FOUND)
if(Qt6Widgets_VERSION VERSION_LESS ${QT_MIN_VER})
message("Minimum supported Qt version is ${QT_MIN_VER}! You have version ${Qt6Widgets_VERSION} installed, please upgrade!")
if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
message(FATAL_ERROR "Most distros do not provide an up-to-date version of Qt.
If you're on Ubuntu or Linux Mint, there are PPAs you can use to install one of the latest qt6 versions.
Find the correct ppa at https://launchpad.net/~beineri and follow the instructions.")
elseif(WIN32)
message(FATAL_ERROR "You can download the latest version of Qt6 here: https://www.qt.io/download-open-source/")
else()
message(FATAL_ERROR "Look online for instructions on installing an up-to-date Qt6 on ${CMAKE_SYSTEM}.")
endif()
endif()
else()
message("CMake was unable to find Qt6!")
if(WIN32)
message(FATAL_ERROR "Make sure the QTDIR env variable has been set properly. (for example C:\\Qt\\${QT_MIN_VER}\\msvc2019_64\\)
You can also try setting the Qt6_DIR preprocessor definiton.")
elseif(CMAKE_SYSTEM_NAME STREQUAL "Linux")
message(FATAL_ERROR "Make sure to install your distro's qt6 package!")
else()
message(FATAL_ERROR "You need to have Qt6 installed, look online for instructions on installing Qt6 on ${CMAKE_SYSTEM}.")
endif()
endif()
add_library(3rdparty::qt6 ALIAS 3rdparty_qt6)

View file

@ -9,11 +9,11 @@ Other instructions may be found [here](https://wiki.rpcs3.net/index.php?title=Bu
* [CMake 3.16.9+](https://www.cmake.org/download/) (add to PATH)
* [Python 3.6+](https://www.python.org/downloads/) (add to PATH)
* [Qt 5.15.2](https://www.qt.io/download-qt-installer)
* [Qt 6.5.2](https://www.qt.io/download-qt-installer)
* [Visual Studio 2019](https://visualstudio.microsoft.com/thank-you-downloading-visual-studio/?sku=Community)
* [Vulkan SDK 1.3.224+](https://vulkan.lunarg.com/sdk/home) (See "Install the SDK" [here](https://vulkan.lunarg.com/doc/sdk/latest/windows/getting_started.html))
**Either add the** `QTDIR` **environment variable, e.g.** `<QtInstallFolder>\5.15.2\msvc2019_64\` **, or use the [Visual Studio Qt Plugin](https://marketplace.visualstudio.com/items?itemName=TheQtCompany.QtVisualStudioTools2019)**
**Either add the** `QTDIR` **environment variable, e.g.** `<QtInstallFolder>\6.5.2\msvc2019_64\` **, or use the [Visual Studio Qt Plugin](https://marketplace.visualstudio.com/items?itemName=TheQtCompany.QtVisualStudioTools2019)**
### Linux
@ -21,7 +21,7 @@ These are the essentials tools to build RPCS3 on Linux. Some of them can be inst
* Clang 12+ or GCC 11+
* [CMake 3.16.9+](https://www.cmake.org/download/)
* [Qt 5.15.2](https://www.qt.io/download-qt-installer)
* [Qt 6.5.2](https://www.qt.io/download-qt-installer)
* [Vulkan SDK 1.3.224+](https://vulkan.lunarg.com/sdk/home) (See "Install the SDK" [here](https://vulkan.lunarg.com/doc/sdk/latest/linux/getting_started.html))
* [SDL2](https://github.com/libsdl-org/SDL/releases) (for the FAudio backend)
@ -29,7 +29,7 @@ These are the essentials tools to build RPCS3 on Linux. Some of them can be inst
#### Arch Linux
sudo pacman -S glew openal cmake vulkan-validation-layers qt5-base qt5-declarative qt5-multimedia sdl2 sndio jack2 base-devel
sudo pacman -S glew openal cmake vulkan-validation-layers qt6-base qt6-declarative qt6-multimedia sdl2 sndio jack2 base-devel
#### Debian & Ubuntu
@ -38,14 +38,7 @@ These are the essentials tools to build RPCS3 on Linux. Some of them can be inst
Ubuntu is usually horrendously out of date, and some packages need to be downloaded by hand. This part is for Qt, GCC, Vulkan, and CMake
##### Qt PPA
Ubuntu usually does not have a new enough Qt package to suit rpcs3's needs. There is a PPA available to work around this. Run the following:
```
. /etc/os-release
sudo add-apt-repository ppa:beineri/opt-qt-5.15.2-$UBUNTU_CODENAME
sudo apt-get update
sudo apt-get install qt515base qt515svg
. /opt/qt515/bin/qt515-env.sh >/dev/null 2>&1
```
Ubuntu usually does not have a new enough Qt package to suit rpcs3's needs. There is currently no PPA available to work around this.
##### GCC 11.x installation
@ -82,11 +75,11 @@ sudo apt-get install cmake
#### Fedora
sudo dnf install alsa-lib-devel cmake glew glew-devel libatomic libevdev-devel libudev-devel openal-devel qt5-qtbase-devel qt5-qtbase-private-devel vulkan-devel pipewire-jack-audio-connection-kit-devel qt5-qtmultimedia-devel qt5-qtsvg-devel
sudo dnf install alsa-lib-devel cmake glew glew-devel libatomic libevdev-devel libudev-devel openal-devel qt6-qtbase-devel qt6-qtbase-private-devel vulkan-devel pipewire-jack-audio-connection-kit-devel qt6-qtmultimedia-devel qt6-qtsvg-devel
#### OpenSUSE
sudo zypper install git cmake libasound2 libpulse-devel openal-soft-devel glew-devel zlib-devel libedit-devel vulkan-devel libudev-devel libqt5-qtbase-devel libqt5-qtmultimedia-devel libqt5-qtsvg-devel libQt5Gui-private-headers-devel libevdev-devel libsndio7_1 libjack-devel
sudo zypper install git cmake libasound2 libpulse-devel openal-soft-devel glew-devel zlib-devel libedit-devel vulkan-devel libudev-devel libqt6-qtbase-devel libqt6-qtmultimedia-devel libqt6-qtsvg-devel libQt6Gui-private-headers-devel libevdev-devel libsndio7_1 libjack-devel
## Setup the project
@ -103,7 +96,7 @@ git submodule update --init
#### Configuring the Qt plugin (if used)
1) Go to `Extensions->Qt VS Tools->Qt Versions`.
2) Add the path to your Qt installation with compiler e.g. `<QtInstallFolder>\5.15.2\msvc2019_64`, version will fill in automatically.
2) Add the path to your Qt installation with compiler e.g. `<QtInstallFolder>\6.5.2\msvc2019_64`, version will fill in automatically.
3) Go to `Extensions->Qt VS Tools->Options->Legacy Project Format`.
4) Set `Build: Run pre-build setup` to `true`.

View file

@ -726,7 +726,7 @@ bool patch_engine::add_patch_data(YAML::Node node, patch_info& info, u32 modifie
break;
default:
{
get_yaml_node_value<u32>(addr_node, error_message);
[[maybe_unused]] const u32 offset = get_yaml_node_value<u32>(addr_node, error_message);
if (!error_message.empty())
{
error_message = fmt::format("Skipping patch data entry: [ %s, 0x%.8x, %s ] (key: %s, location: %s) Invalid patch offset '%s' (not a valid u32 or overflow)",

View file

@ -65,10 +65,10 @@ jobs:
- job: Windows_Build
variables:
COMPILER: msvc
QT_VER_MAIN: '5'
QT_VER: '5.15.2'
QT_VER_MAIN: '6'
QT_VER: '6.5.2'
QT_VER_MSVC: 'msvc2019'
QT_DATE: '202011130602'
QT_DATE: '202307080351'
QTDIR: C:\Qt\$(QT_VER)\$(QT_VER_MSVC)_64
VULKAN_VER: '1.3.224.1'
VULKAN_SDK_SHA: '2029e652e39ee6a6036cff3765da31e1e6c595fd2413d3cd111dfab7855621ea'

View file

@ -29,11 +29,11 @@ if(UNIX AND NOT APPLE)
endif()
endif()
# Qt5
# Qt
# finds Qt libraries and setups custom commands for MOC and UIC
# Must be done here because generated MOC and UIC targets cant
# be found otherwise
include(${CMAKE_SOURCE_DIR}/3rdparty/qt5.cmake)
include(${CMAKE_SOURCE_DIR}/3rdparty/qt6.cmake)
# subdirectories
add_subdirectory(Emu)
@ -84,7 +84,7 @@ set_target_properties(rpcs3
AUTOUIC ON)
target_link_libraries(rpcs3 PRIVATE rpcs3_emu rpcs3_ui)
target_link_libraries(rpcs3 PRIVATE 3rdparty::discordRPC 3rdparty::qt5 3rdparty::hidapi 3rdparty::libusb 3rdparty::wolfssl 3rdparty::libcurl 3rdparty::zlib)
target_link_libraries(rpcs3 PRIVATE 3rdparty::discordRPC 3rdparty::qt6 3rdparty::hidapi 3rdparty::libusb 3rdparty::wolfssl 3rdparty::libcurl 3rdparty::zlib)
target_link_libraries(rpcs3 PRIVATE ${ADDITIONAL_LIBS})
# Unix display manager
@ -112,7 +112,7 @@ if(USE_PRECOMPILED_HEADERS)
target_precompile_headers(rpcs3 PRIVATE stdafx.h)
endif()
get_target_property(_qmake_executable Qt5::qmake IMPORTED_LOCATION)
get_target_property(_qmake_executable Qt6::qmake IMPORTED_LOCATION)
get_filename_component(_qt_bin_dir "${_qmake_executable}" DIRECTORY)
if(APPLE)
find_program(MACDEPLOYQT_EXECUTABLE macdeployqt HINTS "${_qt_bin_dir}")
@ -156,27 +156,27 @@ elseif(WIN32)
# Qt installed from Qt installer has following hierarchy:
# bin/ for release and debug dlls and windeployqt tools
# lib/cmake/Qt5/ for Qt5_Dir
# lib/cmake/Qt6/ for Qt6_Dir
# Qt installed from vcpkg has following hierarchy:
# bin/ for release dlls
# debug/bin/ for debug dlls
# tools/qt5/bin/ for tools including windeployqt
# tools/qt5/debug/bin/ for tools with debug build including windeployqt
# share/cmake/Qt5/ for Qt5_Dir
# tools/qt6/bin/ for tools including windeployqt
# tools/qt6/debug/bin/ for tools with debug build including windeployqt
# share/cmake/Qt6/ for Qt6_Dir
# If Qt5 is installed from official Qt installer
# list(APPEND _QT5_TOOLS_PATHS "${Qt5_DIR}/../../../bin/")
# If Qt is installed from official Qt installer
# list(APPEND _QT6_TOOLS_PATHS "${Qt6_DIR}/../../../bin/")
# If Qt5 is installed from vcpkg
# list(APPEND _QT5_TOOLS_PATHS "${Qt5_DIR}/../../../tools/qt5$<$<CONFIG:Debug>:/debug>/bin/")
# If Qt is installed from vcpkg
# list(APPEND _QT6_TOOLS_PATHS "${Qt6_DIR}/../../../tools/qt6$<$<CONFIG:Debug>:/debug>/bin/")
add_custom_command(TARGET rpcs3 POST_BUILD
# COMMAND set PATH=${_QT5_TOOLS_PATHS}$<SEMICOLON>%PATH%
# COMMAND set PATH=${_QT6_TOOLS_PATHS}$<SEMICOLON>%PATH%
COMMAND "${CMAKE_COMMAND}" -E copy_directory "${CMAKE_SOURCE_DIR}/bin" "$<TARGET_FILE_DIR:rpcs3>"
# If Qt5 is installed from vcpkg, add binary path to PATH
# If Qt is installed from vcpkg, add binary path to PATH
# otherwise windeployqt tool won't be able to locate necessary dlls
# COMMAND set PATH=${Qt5_DIR}/../../../$<$<CONFIG:Debug>:debug/>bin/$<SEMICOLON>%PATH%
COMMAND "${WINDEPLOYQT_EXECUTABLE}" --no-angle --no-compiler-runtime --no-opengl-sw --no-patchqt --no-translations --no-quick --plugindir "$<TARGET_FILE_DIR:rpcs3>/qt/plugins" --verbose 0 "$<TARGET_FILE:rpcs3>")
# COMMAND set PATH=${Qt6_DIR}/../../../$<$<CONFIG:Debug>:debug/>bin/$<SEMICOLON>%PATH%
COMMAND "${WINDEPLOYQT_EXECUTABLE}" --no-compiler-runtime --no-opengl-sw --no-patchqt --no-translations --no-quick --no-system-d3d-compiler --no-quick-import --plugindir "$<TARGET_FILE_DIR:rpcs3>/qt6/plugins" --verbose 0 "$<TARGET_FILE:rpcs3>")
endif()
# Unix installation

View file

@ -1891,7 +1891,6 @@ bool camera_context::on_handler_state(camera_handler_base::camera_handler_state
{
switch (state)
{
case camera_handler_base::camera_handler_state::not_available:
case camera_handler_base::camera_handler_state::closed:
{
if (is_attached)

View file

@ -67,7 +67,7 @@ void cfg_camera::set_camera_setting(const std::string& camera, const camera_sett
std::string cfg_camera::camera_setting::to_string() const
{
return fmt::format("%d,%d,%f,%f,%d,%d,%d", width, height, min_fps, max_fps, format, pixel_aspect_width, pixel_aspect_height);
return fmt::format("%d,%d,%f,%f,%d", width, height, min_fps, max_fps, format);
}
void cfg_camera::camera_setting::from_string(const std::string& text)
@ -112,16 +112,12 @@ void cfg_camera::camera_setting::from_string(const std::string& text)
!to_integer(::at32(list, 1), height) ||
!to_double(::at32(list, 2), min_fps) ||
!to_double(::at32(list, 3), max_fps) ||
!to_integer(::at32(list, 4), format) ||
!to_integer(::at32(list, 5), pixel_aspect_width) ||
!to_integer(::at32(list, 6), pixel_aspect_height))
!to_integer(::at32(list, 4), format))
{
width = 0;
height = 0;
min_fps = 0;
max_fps = 0;
format = 0;
pixel_aspect_width = 0;
pixel_aspect_height = 0;
}
}

View file

@ -15,8 +15,6 @@ struct cfg_camera final : cfg::node
double min_fps = 0;
double max_fps = 0;
int format = 0;
int pixel_aspect_width = 0;
int pixel_aspect_height = 0;
static const u32 member_count = 7;

View file

@ -8,7 +8,6 @@ class camera_handler_base
public:
enum class camera_handler_state
{
not_available,
closed,
open,
running
@ -33,7 +32,7 @@ public:
protected:
std::mutex m_mutex;
atomic_t<camera_handler_state> m_state = camera_handler_state::not_available;
atomic_t<camera_handler_state> m_state = camera_handler_state::closed;
bool m_mirrored = false;
s32 m_format = 2; // CELL_CAMERA_RAW8
u32 m_bytesize = 0;

View file

@ -5,7 +5,7 @@
#elif defined(__APPLE__)
// nothing
#elif defined(HAVE_X11)
// Cannot include Xlib.h before Qt5
// Cannot include Xlib.h before Qt
// and we don't need all of Xlib anyway
using Display = struct _XDisplay;
using Window = unsigned long;

View file

@ -128,6 +128,7 @@ void basic_mouse_handler::MouseMove(QMouseEvent* event)
{
// get the screen dimensions
const QSize screen = m_target->size();
const QPoint e_pos = event->pos();
if (m_target && m_target->isActive() && get_mouse_lock_state())
{
@ -144,7 +145,7 @@ void basic_mouse_handler::MouseMove(QMouseEvent* event)
static QPoint p_real(p_center);
// get the delta of the mouse position to the screen center
const QPoint p_delta = event->pos() - p_center;
const QPoint p_delta = e_pos - p_center;
// update the current position without leaving the screen borders
p_real.setX(std::clamp(p_real.x() + p_delta.x(), 0, screen.width()));
@ -155,7 +156,7 @@ void basic_mouse_handler::MouseMove(QMouseEvent* event)
}
else
{
MouseHandlerBase::Move(event->x(), event->y(), screen.width(), screen.height());
MouseHandlerBase::Move(e_pos.x(), e_pos.y(), screen.width(), screen.height());
}
}
}

View file

@ -505,12 +505,13 @@ void keyboard_pad_handler::mouseMoveEvent(QMouseEvent* event)
{
static int last_pos_x = 0;
static int last_pos_y = 0;
const QPoint e_pos = event->pos();
movement_x = event->x() - last_pos_x;
movement_y = event->y() - last_pos_y;
movement_x = e_pos.x() - last_pos_x;
movement_y = e_pos.y() - last_pos_y;
last_pos_x = event->x();
last_pos_y = event->y();
last_pos_x = e_pos.x();
last_pos_y = e_pos.y();
}
else if (m_target && m_target->isActive())
{
@ -807,8 +808,8 @@ u32 keyboard_pad_handler::GetKeyCode(const QString& keyName)
const QKeySequence seq(keyName);
u32 key_code = Qt::NoButton;
if (seq.count() == 1 && seq[0] != Qt::Key_unknown)
key_code = seq[0];
if (seq.count() == 1 && seq[0].key() != Qt::Key_unknown)
key_code = seq[0].key();
else
input_log.notice("GetKeyCode(%s): seq.count() = %d", keyName, seq.count());

View file

@ -1,4 +1,4 @@
// Qt5.10+ frontend implementation for rpcs3. Known to work on Windows, Linux, Mac
// Qt6 frontend implementation for rpcs3. Known to work on Windows, Linux, Mac
// by Sacha Refshauge, Megamouse and flash-fire
#include <iostream>
@ -349,9 +349,6 @@ QCoreApplication* create_application(int& argc, char* argv[])
use_high_dpi = "1" == qEnvironmentVariable("QT_ENABLE_HIGHDPI_SCALING", high_dpi_setting);
}
// AA_EnableHighDpiScaling has to be set before creating a QApplication
QApplication::setAttribute(use_high_dpi ? Qt::AA_EnableHighDpiScaling : Qt::AA_DisableHighDpiScaling);
if (use_high_dpi)
{
// Set QT_SCALE_FACTOR_ROUNDING_POLICY from environment. Defaults to cli argument, which defaults to PassThrough.
@ -974,8 +971,6 @@ int main(int argc, char** argv)
if (gui_application* gui_app = qobject_cast<gui_application*>(app.data()))
{
gui_app->setAttribute(Qt::AA_UseHighDpiPixmaps);
gui_app->setAttribute(Qt::AA_DisableWindowContextHelpButton);
gui_app->setAttribute(Qt::AA_DontCheckOpenGLContextThreadAffinity);
gui_app->SetShowGui(!s_no_gui);
@ -1057,7 +1052,7 @@ int main(int argc, char** argv)
bool got_timer_resolution = NtQueryTimerResolution(&min_res, &max_res, &orig_res) == 0;
// Set 0.5 msec timer resolution for best performance
// - As QT5 timers (QTimer) sets the timer resolution to 1 msec, override it here.
// - As QT timers (QTimer) sets the timer resolution to 1 msec, override it here.
if (parser.value(arg_timer).toStdString() == "1")
{
ULONG new_res;

View file

@ -315,7 +315,7 @@ EmuCallbacks main_application::CreateCallbacks()
image = image.convertToFormat(QImage::Format::Format_RGBA8888);
}
std::memcpy(dst, image.constBits(), std::min(4 * target_width * target_height, image.height() * image.bytesPerLine()));
std::memcpy(dst, image.constBits(), std::min(target_width * target_height * 4LL, image.height() * image.bytesPerLine()));
success = true;
sys_log.notice("get_scaled_image scaled image: path='%s', width=%d, height=%d", path, width, height);
}

View file

@ -1,4 +1,4 @@
[Paths]
Prefix = qt/
Prefix = qt6/
Plugins = plugins
Translations = translations

View file

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Release|x64">
@ -71,8 +71,8 @@
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<AdditionalIncludeDirectories>..\3rdparty\SoundTouch\soundtouch\include;..\3rdparty\cubeb\extra;..\3rdparty\cubeb\cubeb\include\;..\3rdparty\flatbuffers\include;..\3rdparty\wolfssl\wolfssl;..\3rdparty\curl\curl\include;..\3rdparty\rtmidi\rtmidi;..\3rdparty\libusb\libusb\libusb;$(VULKAN_SDK)\Include;..\3rdparty\libsdl-org\SDL\include;..\3rdparty\XAudio2Redist\include;$(QTDIR)\include;$(QTDIR)\include\QtWidgets;$(QTDIR)\include\QtGui;$(QTDIR)\include\QtANGLE;$(QTDIR)\include\QtCore;.\release;$(QTDIR)\mkspecs\win32-msvc2015;.\QTGeneratedFiles\$(ConfigurationName);.\QTGeneratedFiles;$(QTDIR)\include\QtWinExtras;$(QTDIR)\include\QtConcurrent;$(QTDIR)\include\QtMultimedia;$(QTDIR)\include\QtMultimediaWidgets;$(QTDIR)\include\QtSvg;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalOptions>-Zc:strictStrings -Zc:throwingNew- -w34100 -w34189 -w44996 -w44456 -w44457 -w44458 %(AdditionalOptions)</AdditionalOptions>
<AdditionalIncludeDirectories>..\3rdparty\SoundTouch\soundtouch\include;..\3rdparty\cubeb\extra;..\3rdparty\cubeb\cubeb\include\;..\3rdparty\flatbuffers\include;..\3rdparty\wolfssl\wolfssl;..\3rdparty\curl\curl\include;..\3rdparty\rtmidi\rtmidi;..\3rdparty\libusb\libusb\libusb;$(VULKAN_SDK)\Include;..\3rdparty\libsdl-org\SDL\include;..\3rdparty\XAudio2Redist\include;$(QTDIR)\include;$(QTDIR)\include\QtCore;$(QTDIR)\include\QtCore5Compat;$(QTDIR)\include\QtConcurrent;$(QTDIR)\include\QtGui;$(QTDIR)\include\QtSvg;$(QTDIR)\include\QtSvgWidgets;$(QTDIR)\include\QtWidgets;$(QTDIR)\include\QtMultimedia;$(QTDIR)\mkspecs\win32-msvc;.\release;.\QTGeneratedFiles\$(ConfigurationName);.\QTGeneratedFiles;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalOptions>/Zc:__cplusplus -Zc:strictStrings -Zc:throwingNew- -w34100 -w34189 -w44996 -w44456 -w44457 -w44458 %(AdditionalOptions)</AdditionalOptions>
<AssemblerListingLocation>release\</AssemblerListingLocation>
<BrowseInformation>false</BrowseInformation>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
@ -89,7 +89,7 @@
<ExternalWarningLevel>TurnOffAllWarnings</ExternalWarningLevel>
</ClCompile>
<Link>
<AdditionalDependencies>DbgHelp.lib;Ole32.lib;gdi32.lib;..\hidapi.lib;..\libusb-1.0.lib;winmm.lib;miniupnpc_static.lib;rtmidi.lib;imm32.lib;ksuser.lib;version.lib;OpenAL32.lib;XAudio.lib;GLGSRender.lib;shlwapi.lib;VKGSRender.lib;vulkan-1.lib;wolfssl.lib;libcurl.lib;Wldap32.lib;glslang.lib;OSDependent.lib;OGLCompiler.lib;SPIRV.lib;MachineIndependent.lib;GenericCodeGen.lib;Advapi32.lib;user32.lib;zlib.lib;..\libpng16.lib;asmjit.lib;yaml-cpp.lib;discord-rpc.lib;emucore.lib;dxgi.lib;$(QTDIR)\lib\qtmain.lib;shell32.lib;$(QTDIR)\lib\Qt5Widgets.lib;$(QTDIR)\lib\Qt5Gui.lib;$(QTDIR)\lib\Qt5Core.lib;Qt5Core.lib;Qt5Gui.lib;Qt5Widgets.lib;Qt5WinExtras.lib;Qt5Concurrent.lib;7zlib.lib;SPIRV-Tools.lib;SPIRV-Tools-opt.lib;Qt5Multimedia.lib;Qt5MultimediaWidgets.lib;Qt5Svg.lib;libcubeb.lib;cubeb.lib;soundtouch.lib;Avrt.lib;SDL.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>DbgHelp.lib;Ole32.lib;gdi32.lib;..\hidapi.lib;..\libusb-1.0.lib;winmm.lib;miniupnpc_static.lib;rtmidi.lib;imm32.lib;ksuser.lib;version.lib;OpenAL32.lib;XAudio.lib;GLGSRender.lib;shlwapi.lib;VKGSRender.lib;vulkan-1.lib;wolfssl.lib;libcurl.lib;Wldap32.lib;glslang.lib;OSDependent.lib;OGLCompiler.lib;SPIRV.lib;MachineIndependent.lib;GenericCodeGen.lib;Advapi32.lib;user32.lib;zlib.lib;..\libpng16.lib;asmjit.lib;yaml-cpp.lib;discord-rpc.lib;emucore.lib;dxgi.lib;shell32.lib;Qt6Core.lib;Qt6Gui.lib;Qt6Widgets.lib;Qt6Concurrent.lib;Qt6Core5Compat.lib;Qt6Multimedia.lib;Qt6MultimediaWidgets.lib;Qt6Svg.lib;Qt6SvgWidgets.lib;7zlib.lib;SPIRV-Tools.lib;SPIRV-Tools-opt.lib;libcubeb.lib;cubeb.lib;soundtouch.lib;Avrt.lib;SDL.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>..\3rdparty\OpenAL\libs\Win64;..\3rdparty\glslang\build\hlsl\Release;..\3rdparty\glslang\build\SPIRV\Release;..\3rdparty\glslang\build\OGLCompilersDLL\Release;..\3rdparty\glslang\build\glslang\OSDependent\Windows\Release;..\3rdparty\glslang\build\glslang\Release;..\3rdparty\SPIRV\build\source\Release;..\3rdparty\SPIRV\build\source\opt\Release;..\lib\$(CONFIGURATION)-$(PLATFORM);..\3rdparty\XAudio2Redist\libs;..\3rdparty\discord-rpc\lib;$(QTDIR)\lib;%(AdditionalLibraryDirectories);$(VULKAN_SDK)\Lib</AdditionalLibraryDirectories>
<AdditionalOptions>"/MANIFESTDEPENDENCY:type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' publicKeyToken='6595b64144ccf1df' language='*' processorArchitecture='*'" %(AdditionalOptions)</AdditionalOptions>
<DataExecutionPrevention>true</DataExecutionPrevention>
@ -102,6 +102,7 @@
<SuppressStartupBanner>true</SuppressStartupBanner>
<BaseAddress>0x10000</BaseAddress>
<DelayLoadDLLs>xaudio2_9redist.dll</DelayLoadDLLs>
<EntryPointSymbol>mainCRTStartup</EntryPointSymbol>
</Link>
<Midl>
<DefaultCharType>Unsigned</DefaultCharType>
@ -113,7 +114,7 @@
</ResourceCompile>
<PostBuildEvent>
<Command>
$(QTDIR)\bin\windeployqt --no-angle --no-opengl-sw --no-translations --no-quick --plugindir "$(TargetDir)qt\plugins" --release "$(TargetPath)"
$(QTDIR)\bin\windeployqt --no-compiler-runtime --no-opengl-sw --no-patchqt --no-translations --no-quick --no-system-d3d-compiler --no-quick-import --plugindir "$(TargetDir)qt6\plugins" --release "$(TargetPath)"
</Command>
</PostBuildEvent>
<PostBuildEvent>
@ -123,7 +124,7 @@
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<AdditionalIncludeDirectories>..\3rdparty\SoundTouch\soundtouch\include;..\3rdparty\cubeb\extra;..\3rdparty\cubeb\cubeb\include\;..\3rdparty\flatbuffers\include;..\3rdparty\wolfssl\wolfssl;..\3rdparty\curl\curl\include;..\3rdparty\rtmidi\rtmidi;..\3rdparty\libusb\libusb\libusb;$(VULKAN_SDK)\Include;..\3rdparty\XAudio2Redist\include;$(QTDIR)\include;$(QTDIR)\include\QtWidgets;$(QTDIR)\include\QtGui;$(QTDIR)\include\QtANGLE;$(QTDIR)\include\QtCore;.\debug;$(QTDIR)\mkspecs\win32-msvc2015;.\QTGeneratedFiles\$(ConfigurationName);.\QTGeneratedFiles;$(QTDIR)\include\QtWinExtras;$(QTDIR)\include\QtConcurrent;$(QTDIR)\include\QtMultimedia;$(QTDIR)\include\QtMultimediaWidgets;$(QTDIR)\include\QtSvg;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>..\3rdparty\SoundTouch\soundtouch\include;..\3rdparty\cubeb\extra;..\3rdparty\cubeb\cubeb\include\;..\3rdparty\flatbuffers\include;..\3rdparty\wolfssl\wolfssl;..\3rdparty\curl\curl\include;..\3rdparty\rtmidi\rtmidi;..\3rdparty\libusb\libusb\libusb;$(VULKAN_SDK)\Include;..\3rdparty\XAudio2Redist\include;$(QTDIR)\include;$(QTDIR)\include\QtCore;$(QTDIR)\include\QtCore5Compat;$(QTDIR)\include\QtConcurrent;$(QTDIR)\include\QtGui;$(QTDIR)\include\QtSvg;$(QTDIR)\include\QtSvgWidgets;$(QTDIR)\include\QtWidgets;$(QTDIR)\include\QtMultimedia;$(QTDIR)\mkspecs\win32-msvc;.\debug;.\QTGeneratedFiles\$(ConfigurationName);.\QTGeneratedFiles;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalOptions>-Zc:strictStrings -Zc:throwingNew- -w34100 -w34189 -w44996 -w44456 -w44457 -w44458 %(AdditionalOptions)</AdditionalOptions>
<AssemblerListingLocation>debug\</AssemblerListingLocation>
<BrowseInformation>false</BrowseInformation>
@ -140,7 +141,7 @@
<ProgramDataBaseFileName>$(IntDir)vc$(PlatformToolsetVersion).pdb</ProgramDataBaseFileName>
</ClCompile>
<Link>
<AdditionalDependencies>DbgHelp.lib;Ole32.lib;gdi32.lib;..\hidapi.lib;..\libusb-1.0.lib;winmm.lib;miniupnpc_static.lib;rtmidi.lib;ksuser.lib;OpenAL32.lib;XAudio.lib;GLGSRender.lib;shlwapi.lib;VKGSRender.lib;vulkan-1.lib;wolfssl.lib;libcurl.lib;Wldap32.lib;glslangd.lib;OSDependentd.lib;OGLCompilerd.lib;SPIRVd.lib;MachineIndependentd.lib;GenericCodeGend.lib;Advapi32.lib;user32.lib;zlib.lib;..\libpng16.lib;asmjit.lib;yaml-cpp.lib;discord-rpc.lib;emucore.lib;dxgi.lib;$(QTDIR)\lib\qtmaind.lib;shell32.lib;$(QTDIR)\lib\Qt5Widgetsd.lib;$(QTDIR)\lib\Qt5Guid.lib;$(QTDIR)\lib\Qt5Cored.lib;Qt5Cored.lib;Qt5Guid.lib;Qt5Widgetsd.lib;Qt5WinExtrasd.lib;Qt5Concurrentd.lib;7zlib.lib;SPIRV-Tools.lib;SPIRV-Tools-opt.lib;Qt5Multimediad.lib;Qt5MultimediaWidgetsd.lib;Qt5Svgd.lib;libcubeb.lib;cubeb.lib;soundtouch.lib;Avrt.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>DbgHelp.lib;Ole32.lib;gdi32.lib;..\hidapi.lib;..\libusb-1.0.lib;winmm.lib;miniupnpc_static.lib;rtmidi.lib;ksuser.lib;OpenAL32.lib;XAudio.lib;GLGSRender.lib;shlwapi.lib;VKGSRender.lib;vulkan-1.lib;wolfssl.lib;libcurl.lib;Wldap32.lib;glslangd.lib;OSDependentd.lib;OGLCompilerd.lib;SPIRVd.lib;MachineIndependentd.lib;GenericCodeGend.lib;Advapi32.lib;user32.lib;zlib.lib;..\libpng16.lib;asmjit.lib;yaml-cpp.lib;discord-rpc.lib;emucore.lib;dxgi.lib;shell32.lib;qtmaind.lib;Qt6Cored.lib;Qt6Guid.lib;Qt6Widgetsd.lib;Qt6Concurrentd.lib;Qt6Multimediad.lib;Qt6MultimediaWidgetsd.lib;Qt6Svgd.lib;Qt6SvgWidgetsd.lib;7zlib.lib;SPIRV-Tools.lib;SPIRV-Tools-opt.lib;libcubeb.lib;cubeb.lib;soundtouch.lib;Avrt.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>..\3rdparty\OpenAL\libs\Win64;..\3rdparty\glslang\build\hlsl\Debug;..\3rdparty\glslang\build\SPIRV\Debug;..\3rdparty\glslang\build\OGLCompilersDLL\Debug;..\3rdparty\glslang\build\glslang\OSDependent\Windows\Debug;..\3rdparty\glslang\build\glslang\Debug;..\3rdparty\SPIRV\build\source\opt\Debug;..\3rdparty\XAudio2Redist\libs;..\3rdparty\discord-rpc\lib;..\lib\$(CONFIGURATION)-$(PLATFORM);$(QTDIR)\lib;%(AdditionalLibraryDirectories);$(VULKAN_SDK)\Lib</AdditionalLibraryDirectories>
<AdditionalOptions>"/MANIFESTDEPENDENCY:type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' publicKeyToken='6595b64144ccf1df' language='*' processorArchitecture='*'" /VERBOSE %(AdditionalOptions)</AdditionalOptions>
<DataExecutionPrevention>true</DataExecutionPrevention>
@ -165,7 +166,7 @@
</ResourceCompile>
<PostBuildEvent>
<Command>
$(QTDIR)\bin\windeployqt --no-angle --no-opengl-sw --no-translations --no-quick --plugindir "$(TargetDir)qt\plugins" --debug "$(TargetPath)"
$(QTDIR)\bin\windeployqt --no-compiler-runtime --no-opengl-sw --no-patchqt --no-translations --no-quick --no-system-d3d-compiler --no-quick-import --plugindir "$(TargetDir)qt6\plugins" --debug "$(TargetPath)"
</Command>
</PostBuildEvent>
<PostBuildEvent>
@ -763,7 +764,7 @@
<ClCompile Include="rpcs3qt\table_item_delegate.cpp" />
<ClCompile Include="rpcs3qt\tooltips.cpp" />
<ClCompile Include="rpcs3qt\update_manager.cpp" />
<ClCompile Include="rpcs3qt\qt_camera_video_surface.cpp" />
<ClCompile Include="rpcs3qt\qt_camera_video_sink.cpp" />
<ClCompile Include="rpcs3qt\uuid.cpp" />
<ClCompile Include="rpcs3qt\vfs_dialog_path_widget.cpp" />
<ClCompile Include="rpcs3qt\vfs_dialog_usb_input.cpp" />
@ -1482,7 +1483,7 @@
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">.\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp</Outputs>
<Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">"$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -D_WINDOWS -DUNICODE -DWIN32 -DWIN64 -DWITH_DISCORD_RPC -DQT_NO_DEBUG -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CORE_LIB -DNDEBUG -DQT_WINEXTRAS_LIB -DQT_CONCURRENT_LIB -D%(PreprocessorDefinitions) "-I.\..\3rdparty\wolfssl\wolfssl" "-I.\..\3rdparty\curl\curl\include" "-I.\..\3rdparty\libusb\libusb\libusb" "-I$(VULKAN_SDK)\Include" "-I.\..\3rdparty\XAudio2Redist\include" "-I$(QTDIR)\include" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtANGLE" "-I$(QTDIR)\include\QtCore" "-I.\release" "-I$(QTDIR)\mkspecs\win32-msvc2015" "-I.\QTGeneratedFiles\$(ConfigurationName)" "-I.\QTGeneratedFiles" "-I$(QTDIR)\include\QtWinExtras" "-I$(QTDIR)\include\QtConcurrent"</Command>
</CustomBuild>
<ClInclude Include="rpcs3qt\qt_camera_video_surface.h" />
<ClInclude Include="rpcs3qt\qt_camera_video_sink.h" />
<CustomBuild Include="rpcs3qt\vfs_dialog_usb_tab.h">
<AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(QTDIR)\bin\moc.exe;%(FullPath)</AdditionalInputs>
<Message Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Moc%27ing %(Identity)...</Message>

View file

@ -807,7 +807,7 @@
<ClCompile Include="rpcs3qt\qt_camera_handler.cpp">
<Filter>Io\camera</Filter>
</ClCompile>
<ClCompile Include="rpcs3qt\qt_camera_video_surface.cpp">
<ClCompile Include="rpcs3qt\qt_camera_video_sink.cpp">
<Filter>Io\camera</Filter>
</ClCompile>
<ClCompile Include="rpcs3qt\qt_camera_error_handler.cpp">
@ -1166,7 +1166,7 @@
<ClInclude Include="QTGeneratedFiles\ui_patch_creator_dialog.h">
<Filter>Generated Files</Filter>
</ClInclude>
<ClInclude Include="rpcs3qt\qt_camera_video_surface.h">
<ClInclude Include="rpcs3qt\qt_camera_video_sink.h">
<Filter>Io\camera</Filter>
</ClInclude>
<ClInclude Include="rpcs3qt\qt_camera_handler.h">

View file

@ -65,7 +65,7 @@ add_library(rpcs3_ui STATIC
progress_indicator.cpp
qt_camera_error_handler.cpp
qt_camera_handler.cpp
qt_camera_video_surface.cpp
qt_camera_video_sink.cpp
qt_music_error_handler.cpp
qt_music_handler.cpp
qt_utils.cpp
@ -140,7 +140,7 @@ target_compile_definitions(rpcs3_ui PRIVATE WIN32_LEAN_AND_MEAN)
target_link_libraries(rpcs3_ui
PUBLIC
3rdparty::qt5 3rdparty::yaml-cpp
3rdparty::qt6 3rdparty::yaml-cpp
PRIVATE
rpcs3_emu

View file

@ -3,61 +3,56 @@
#include "ui_camera_settings_dialog.h"
#include "Emu/Io/camera_config.h"
#include <QCameraInfo>
#include <QCameraDevice>
#include <QMediaDevices>
#include <QMessageBox>
#include <QPushButton>
LOG_CHANNEL(camera_log, "Camera");
template <>
void fmt_class_string<QVideoFrame::PixelFormat>::format(std::string& out, u64 arg)
void fmt_class_string<QVideoFrameFormat::PixelFormat>::format(std::string& out, u64 arg)
{
format_enum(out, arg, [](QVideoFrame::PixelFormat value)
format_enum(out, arg, [](QVideoFrameFormat::PixelFormat value)
{
switch (value)
{
case QVideoFrame::Format_Invalid: return "Invalid";
case QVideoFrame::Format_ARGB32: return "ARGB32";
case QVideoFrame::Format_ARGB32_Premultiplied: return "ARGB32_Premultiplied";
case QVideoFrame::Format_RGB32: return "RGB32";
case QVideoFrame::Format_RGB24: return "RGB24";
case QVideoFrame::Format_RGB565: return "RGB565";
case QVideoFrame::Format_RGB555: return "RGB555";
case QVideoFrame::Format_ARGB8565_Premultiplied: return "ARGB8565_Premultiplied";
case QVideoFrame::Format_BGRA32: return "BGRA32";
case QVideoFrame::Format_BGRA32_Premultiplied: return "BGRA32_Premultiplied";
case QVideoFrame::Format_BGR32: return "BGR32";
case QVideoFrame::Format_BGR24: return "BGR24";
case QVideoFrame::Format_BGR565: return "BGR565";
case QVideoFrame::Format_BGR555: return "BGR555";
case QVideoFrame::Format_BGRA5658_Premultiplied: return "BGRA5658_Premultiplied";
case QVideoFrame::Format_AYUV444: return "AYUV444";
case QVideoFrame::Format_AYUV444_Premultiplied: return "AYUV444_Premultiplied";
case QVideoFrame::Format_YUV444: return "YUV444";
case QVideoFrame::Format_YUV420P: return "YUV420P";
case QVideoFrame::Format_YV12: return "YV12";
case QVideoFrame::Format_UYVY: return "UYVY";
case QVideoFrame::Format_YUYV: return "YUYV";
case QVideoFrame::Format_NV12: return "NV12";
case QVideoFrame::Format_NV21: return "NV21";
case QVideoFrame::Format_IMC1: return "IMC1";
case QVideoFrame::Format_IMC2: return "IMC2";
case QVideoFrame::Format_IMC3: return "IMC3";
case QVideoFrame::Format_IMC4: return "IMC4";
case QVideoFrame::Format_Y8: return "Y8";
case QVideoFrame::Format_Y16: return "Y16";
case QVideoFrame::Format_Jpeg: return "Jpeg";
case QVideoFrame::Format_CameraRaw: return "CameraRaw";
case QVideoFrame::Format_AdobeDng: return "AdobeDng";
case QVideoFrame::Format_ABGR32: return "ABGR32";
case QVideoFrame::Format_YUV422P: return "YUV422P";
case QVideoFrame::Format_User: return "User";
case QVideoFrameFormat::Format_ARGB8888: return "ARGB8888";
case QVideoFrameFormat::Format_ARGB8888_Premultiplied: return "ARGB8888_Premultiplied";
case QVideoFrameFormat::Format_XRGB8888: return "XRGB8888";
case QVideoFrameFormat::Format_BGRA8888: return "BGRA8888";
case QVideoFrameFormat::Format_BGRA8888_Premultiplied: return "BGRA8888_Premultiplied";
case QVideoFrameFormat::Format_BGRX8888: return "BGRX8888";
case QVideoFrameFormat::Format_ABGR8888: return "ABGR8888";
case QVideoFrameFormat::Format_XBGR8888: return "XBGR8888";
case QVideoFrameFormat::Format_RGBA8888: return "RGBA8888";
case QVideoFrameFormat::Format_RGBX8888: return "RGBX8888";
case QVideoFrameFormat::Format_AYUV: return "AYUV";
case QVideoFrameFormat::Format_AYUV_Premultiplied: return "AYUV_Premultiplied";
case QVideoFrameFormat::Format_YUV420P: return "YUV420P";
case QVideoFrameFormat::Format_YUV422P: return "YUV422P";
case QVideoFrameFormat::Format_YV12: return "YV12";
case QVideoFrameFormat::Format_UYVY: return "UYVY";
case QVideoFrameFormat::Format_YUYV: return "YUYV";
case QVideoFrameFormat::Format_NV12: return "NV12";
case QVideoFrameFormat::Format_NV21: return "NV21";
case QVideoFrameFormat::Format_IMC1: return "IMC1";
case QVideoFrameFormat::Format_IMC2: return "IMC2";
case QVideoFrameFormat::Format_IMC3: return "IMC3";
case QVideoFrameFormat::Format_IMC4: return "IMC4";
case QVideoFrameFormat::Format_Y8: return "Y8";
case QVideoFrameFormat::Format_Y16: return "Y16";
case QVideoFrameFormat::Format_P010: return "P010";
case QVideoFrameFormat::Format_P016: return "P016";
case QVideoFrameFormat::Format_SamplerExternalOES: return "SamplerExternalOES";
case QVideoFrameFormat::Format_Jpeg: return "Jpeg";
case QVideoFrameFormat::Format_SamplerRect: return "SamplerRect";
default: return unknown;
}
});
}
Q_DECLARE_METATYPE(QCameraInfo);
Q_DECLARE_METATYPE(QCameraDevice);
camera_settings_dialog::camera_settings_dialog(QWidget* parent)
: QDialog(parent)
@ -67,7 +62,7 @@ camera_settings_dialog::camera_settings_dialog(QWidget* parent)
load_config();
for (const QCameraInfo& camera_info : QCameraInfo::availableCameras())
for (const QCameraDevice& camera_info : QMediaDevices::videoInputs())
{
if (camera_info.isNull()) continue;
ui->combo_camera->addItem(camera_info.description(), QVariant::fromValue(camera_info));
@ -108,13 +103,13 @@ camera_settings_dialog::~camera_settings_dialog()
void camera_settings_dialog::handle_camera_change(int index)
{
if (index < 0 || !ui->combo_camera->itemData(index).canConvert<QCameraInfo>())
if (index < 0 || !ui->combo_camera->itemData(index).canConvert<QCameraDevice>())
{
ui->combo_settings->clear();
return;
}
const QCameraInfo camera_info = ui->combo_camera->itemData(index).value<QCameraInfo>();
const QCameraDevice camera_info = ui->combo_camera->itemData(index).value<QCameraDevice>();
if (camera_info.isNull())
{
@ -123,7 +118,9 @@ void camera_settings_dialog::handle_camera_change(int index)
}
m_camera.reset(new QCamera(camera_info));
m_camera->setViewfinder(ui->viewfinder);
m_media_capture_session.reset(new QMediaCaptureSession(nullptr));
m_media_capture_session->setCamera(m_camera.get());
m_media_capture_session->setVideoSink(ui->videoWidget->videoSink());
if (!m_camera->isAvailable())
{
@ -132,42 +129,34 @@ void camera_settings_dialog::handle_camera_change(int index)
return;
}
m_camera->load();
ui->combo_settings->blockSignals(true);
ui->combo_settings->clear();
QList<QCameraViewfinderSettings> settings = m_camera->supportedViewfinderSettings();
std::sort(settings.begin(), settings.end(), [](const QCameraViewfinderSettings& l, const QCameraViewfinderSettings& r) -> bool
QList<QCameraFormat> settings = camera_info.videoFormats();
std::sort(settings.begin(), settings.end(), [](const QCameraFormat& l, const QCameraFormat& r) -> bool
{
if (l.resolution().width() > r.resolution().width()) return true;
if (l.resolution().width() < r.resolution().width()) return false;
if (l.resolution().height() > r.resolution().height()) return true;
if (l.resolution().height() < r.resolution().height()) return false;
if (l.minimumFrameRate() > r.minimumFrameRate()) return true;
if (l.minimumFrameRate() < r.minimumFrameRate()) return false;
if (l.maximumFrameRate() > r.maximumFrameRate()) return true;
if (l.maximumFrameRate() < r.maximumFrameRate()) return false;
if (l.minFrameRate() > r.minFrameRate()) return true;
if (l.minFrameRate() < r.minFrameRate()) return false;
if (l.maxFrameRate() > r.maxFrameRate()) return true;
if (l.maxFrameRate() < r.maxFrameRate()) return false;
if (l.pixelFormat() > r.pixelFormat()) return true;
if (l.pixelFormat() < r.pixelFormat()) return false;
if (l.pixelAspectRatio().width() > r.pixelAspectRatio().width()) return true;
if (l.pixelAspectRatio().width() < r.pixelAspectRatio().width()) return false;
if (l.pixelAspectRatio().height() > r.pixelAspectRatio().height()) return true;
if (l.pixelAspectRatio().height() < r.pixelAspectRatio().height()) return false;
return false;
});
for (const QCameraViewfinderSettings& setting : settings)
for (const QCameraFormat& setting : settings)
{
if (setting.isNull()) continue;
const QString description = tr("%0x%1, %2-%3 FPS, Format=%4, PixelAspectRatio=%5x%6")
const QString description = tr("%0x%1, %2-%3 FPS, Format=%4")
.arg(setting.resolution().width())
.arg(setting.resolution().height())
.arg(setting.minimumFrameRate())
.arg(setting.maximumFrameRate())
.arg(QString::fromStdString(fmt::format("%s", setting.pixelFormat())))
.arg(setting.pixelAspectRatio().width())
.arg(setting.pixelAspectRatio().height());
.arg(setting.minFrameRate())
.arg(setting.maxFrameRate())
.arg(QString::fromStdString(fmt::format("%s", setting.pixelFormat())));
ui->combo_settings->addItem(description, QVariant::fromValue(setting));
}
ui->combo_settings->blockSignals(false);
@ -181,37 +170,27 @@ void camera_settings_dialog::handle_camera_change(int index)
// Load selected settings from config file
int index = 0;
bool success = false;
const std::string key = camera_info.deviceName().toStdString();
const std::string key = camera_info.id().toStdString();
cfg_camera::camera_setting cfg_setting = g_cfg_camera.get_camera_setting(key, success);
if (success)
{
camera_log.notice("Found config entry for camera \"%s\"", key);
// Convert to Qt data
QCameraViewfinderSettings setting;
setting.setResolution(cfg_setting.width, cfg_setting.height);
setting.setMinimumFrameRate(cfg_setting.min_fps);
setting.setMaximumFrameRate(cfg_setting.max_fps);
setting.setPixelFormat(static_cast<QVideoFrame::PixelFormat>(cfg_setting.format));
setting.setPixelAspectRatio(cfg_setting.pixel_aspect_width, cfg_setting.pixel_aspect_height);
// Select matching drowdown entry
const double epsilon = 0.001;
for (int i = 0; i < ui->combo_settings->count(); i++)
{
const QCameraViewfinderSettings tmp = ui->combo_settings->itemData(i).value<QCameraViewfinderSettings>();
const QCameraFormat tmp = ui->combo_settings->itemData(i).value<QCameraFormat>();
if (tmp.resolution().width() == setting.resolution().width() &&
tmp.resolution().height() == setting.resolution().height() &&
tmp.minimumFrameRate() >= (setting.minimumFrameRate() - epsilon) &&
tmp.minimumFrameRate() <= (setting.minimumFrameRate() + epsilon) &&
tmp.maximumFrameRate() >= (setting.maximumFrameRate() - epsilon) &&
tmp.maximumFrameRate() <= (setting.maximumFrameRate() + epsilon) &&
tmp.pixelFormat() == setting.pixelFormat() &&
tmp.pixelAspectRatio().width() == setting.pixelAspectRatio().width() &&
tmp.pixelAspectRatio().height() == setting.pixelAspectRatio().height())
if (tmp.resolution().width() == cfg_setting.width &&
tmp.resolution().height() == cfg_setting.height &&
tmp.minFrameRate() >= (cfg_setting.min_fps - epsilon) &&
tmp.minFrameRate() <= (cfg_setting.min_fps + epsilon) &&
tmp.maxFrameRate() >= (cfg_setting.max_fps - epsilon) &&
tmp.maxFrameRate() <= (cfg_setting.max_fps + epsilon) &&
tmp.pixelFormat() == static_cast<QVideoFrameFormat::PixelFormat>(cfg_setting.format))
{
index = i;
break;
@ -223,14 +202,12 @@ void camera_settings_dialog::handle_camera_change(int index)
ui->combo_settings->setEnabled(true);
// Update config to match user interface outcome
const QCameraViewfinderSettings setting = ui->combo_settings->currentData().value<QCameraViewfinderSettings>();
const QCameraFormat setting = ui->combo_settings->currentData().value<QCameraFormat>();
cfg_setting.width = setting.resolution().width();
cfg_setting.height = setting.resolution().height();
cfg_setting.min_fps = setting.minimumFrameRate();
cfg_setting.max_fps = setting.maximumFrameRate();
cfg_setting.min_fps = setting.minFrameRate();
cfg_setting.max_fps = setting.maxFrameRate();
cfg_setting.format = static_cast<int>(setting.pixelFormat());
cfg_setting.pixel_aspect_width = setting.pixelAspectRatio().width();
cfg_setting.pixel_aspect_height = setting.pixelAspectRatio().height();
g_cfg_camera.set_camera_setting(key, cfg_setting);
}
}
@ -248,23 +225,21 @@ void camera_settings_dialog::handle_settings_change(int index)
return;
}
if (index >= 0 && ui->combo_settings->itemData(index).canConvert<QCameraViewfinderSettings>() && ui->combo_camera->currentData().canConvert<QCameraInfo>())
if (index >= 0 && ui->combo_settings->itemData(index).canConvert<QCameraFormat>() && ui->combo_camera->currentData().canConvert<QCameraDevice>())
{
const QCameraViewfinderSettings setting = ui->combo_settings->itemData(index).value<QCameraViewfinderSettings>();
const QCameraFormat setting = ui->combo_settings->itemData(index).value<QCameraFormat>();
if (!setting.isNull())
{
m_camera->setViewfinderSettings(setting);
m_camera->setCameraFormat(setting);
}
cfg_camera::camera_setting cfg_setting;
cfg_setting.width = setting.resolution().width();
cfg_setting.height = setting.resolution().height();
cfg_setting.min_fps = setting.minimumFrameRate();
cfg_setting.max_fps = setting.maximumFrameRate();
cfg_setting.min_fps = setting.minFrameRate();
cfg_setting.max_fps = setting.maxFrameRate();
cfg_setting.format = static_cast<int>(setting.pixelFormat());
cfg_setting.pixel_aspect_width = setting.pixelAspectRatio().width();
cfg_setting.pixel_aspect_height = setting.pixelAspectRatio().height();
g_cfg_camera.set_camera_setting(ui->combo_camera->currentData().value<QCameraInfo>().deviceName().toStdString(), cfg_setting);
g_cfg_camera.set_camera_setting(ui->combo_camera->currentData().value<QCameraDevice>().id().toStdString(), cfg_setting);
}
m_camera->start();

View file

@ -2,6 +2,7 @@
#include <QCamera>
#include <QDialog>
#include <QMediaCaptureSession>
namespace Ui
{
@ -25,5 +26,6 @@ private:
void save_config();
std::unique_ptr<Ui::camera_settings_dialog> ui;
std::shared_ptr<QCamera> m_camera;
std::unique_ptr<QCamera> m_camera;
std::unique_ptr<QMediaCaptureSession> m_media_capture_session;
};

View file

@ -57,7 +57,7 @@
</property>
<layout class="QVBoxLayout" name="preview_layout">
<item>
<widget class="QCameraViewfinder" name="viewfinder" native="true">
<widget class="QVideoWidget" name="videoWidget" native="true">
<property name="minimumSize">
<size>
<width>64</width>
@ -86,9 +86,9 @@
</widget>
<customwidgets>
<customwidget>
<class>QCameraViewfinder</class>
<class>QVideoWidget</class>
<extends>QWidget</extends>
<header>qcameraviewfinder.h</header>
<header>qvideowidget.h</header>
<container>1</container>
</customwidget>
</customwidgets>

View file

@ -64,12 +64,12 @@ bool config_checker::check_config(QString content, QString& result, bool is_log)
const QString start_token = "SYS: Used configuration:\n";
const QString end_token = "\n·";
int start = content.indexOf(start_token);
int end = -1;
qsizetype start = content.indexOf(start_token);
qsizetype end = -1;
if (start >= 0)
{
start += start_token.count();
start += start_token.size();
end = content.indexOf(end_token, start);
}

View file

@ -30,35 +30,35 @@ bool custom_table_widget_item::operator<(const QTableWidgetItem& other) const
const QVariant data_l = data(m_sort_role);
const QVariant data_r = other.data(m_sort_role);
const QVariant::Type type_l = data_l.type();
const QVariant::Type type_r = data_r.type();
const int type_l = data_l.metaType().id();
const int type_r = data_r.metaType().id();
ensure(type_l == type_r);
switch (type_l)
{
case QVariant::Type::Bool:
case QVariant::Type::Int:
case QMetaType::Type::Bool:
case QMetaType::Type::Int:
return data_l.toInt() < data_r.toInt();
case QVariant::Type::UInt:
case QMetaType::Type::UInt:
return data_l.toUInt() < data_r.toUInt();
case QVariant::Type::LongLong:
case QMetaType::Type::LongLong:
return data_l.toLongLong() < data_r.toLongLong();
case QVariant::Type::ULongLong:
case QMetaType::Type::ULongLong:
return data_l.toULongLong() < data_r.toULongLong();
case QVariant::Type::Double:
case QMetaType::Type::Double:
return data_l.toDouble() < data_r.toDouble();
case QVariant::Type::Date:
case QMetaType::Type::QDate:
return data_l.toDate() < data_r.toDate();
case QVariant::Type::Time:
case QMetaType::Type::QTime:
return data_l.toTime() < data_r.toTime();
case QVariant::Type::DateTime:
case QMetaType::Type::QDateTime:
return data_l.toDateTime() < data_r.toDateTime();
case QVariant::Type::Char:
case QVariant::Type::String:
case QMetaType::Type::Char:
case QMetaType::Type::QString:
return data_l.toString() < data_r.toString();
default:
fmt::throw_exception("Unimplemented type %s", QVariant::typeToName(type_l));
fmt::throw_exception("Unimplemented type %s", QMetaType(type_l).name());
}
}

View file

@ -73,7 +73,7 @@ public:
void take_screenshot(std::vector<u8> data, const u32 sshot_width, const u32 sshot_height, bool is_bgra) override;
protected:
virtual void paintEvent(QPaintEvent *event);
void paintEvent(QPaintEvent *event) override;
void showEvent(QShowEvent *event) override;
void keyPressEvent(QKeyEvent *keyEvent) override;

View file

@ -34,7 +34,6 @@
#include <QLibraryInfo>
#include <QDirIterator>
#include <QFileInfo>
#include <QSound>
#include <QMessageBox>
#include <QTextDocument>
@ -173,7 +172,7 @@ void gui_application::SwitchTranslator(QTranslator& translator, const QString& f
// remove the old translator
removeTranslator(&translator);
const QString lang_path = QLibraryInfo::location(QLibraryInfo::TranslationsPath) + QStringLiteral("/");
const QString lang_path = QLibraryInfo::path(QLibraryInfo::TranslationsPath) + QStringLiteral("/");
const QString file_path = lang_path + filename;
if (QFileInfo(file_path).isFile())
@ -236,7 +235,7 @@ QStringList gui_application::GetAvailableLanguageCodes()
{
QStringList language_codes;
const QString language_path = QLibraryInfo::location(QLibraryInfo::TranslationsPath);
const QString language_path = QLibraryInfo::path(QLibraryInfo::TranslationsPath);
if (QFileInfo(language_path).isDir())
{
@ -546,13 +545,17 @@ void gui_application::InitializeCallbacks()
return localized_emu::get_u32string(id, args);
};
callbacks.play_sound = [](const std::string& path)
callbacks.play_sound = [this](const std::string& path)
{
Emu.CallFromMainThread([path]()
Emu.CallFromMainThread([this, path]()
{
if (fs::is_file(path))
{
QSound::play(qstr(path));
m_sound_effect.stop();
m_sound_effect.setSource(QUrl::fromLocalFile(qstr(path)));
m_sound_effect.setVolume(g_cfg.audio.volume * 0.01f);
m_sound_effect.setLoopCount(1);
m_sound_effect.play();
}
});
};

View file

@ -7,6 +7,7 @@
#include <QElapsedTimer>
#include <QTimer>
#include <QTranslator>
#include <QSoundEffect>
#include "main_application.h"
@ -87,6 +88,8 @@ private:
QTimer m_timer;
QElapsedTimer m_timer_playtime;
QSoundEffect m_sound_effect{};
std::shared_ptr<emu_settings> m_emu_settings;
std::shared_ptr<gui_settings> m_gui_settings;
std::shared_ptr<persistent_settings> m_persistent_settings;

View file

@ -235,8 +235,11 @@ void log_viewer::show_log()
{
m_gui_settings->SetValue(gui::fd_log_viewer, m_path_last);
QTextStream stream(&file);
m_full_log = stream.readAll();
// TODO: Due to a bug in Qt 6.5.2 QTextStream::readAll is ridiculously slow to the point where it gets stuck on large files.
// In Qt 5.15.2 this was much faster than QFile::readAll. Use QTextStream again once this bug is fixed upstream.
//QTextStream stream(&file);
//m_full_log = stream.readAll();
m_full_log = file.readAll();
m_full_log.replace('\0', '0');
file.close();
}

View file

@ -155,7 +155,7 @@ bool main_window::Init([[maybe_unused]] bool with_cli_boot)
ui->toolbar_start->setEnabled(enable_play_last);
// create tool buttons for the taskbar thumbnail
#ifdef _WIN32
#ifdef HAS_QT_WIN_STUFF
m_thumb_bar = new QWinThumbnailToolBar(this);
m_thumb_bar->setWindow(windowHandle());
@ -1700,7 +1700,7 @@ void main_window::RepaintThumbnailIcons()
return gui::utils::get_colorized_icon(QPixmap::fromImage(gui::utils::get_opaque_image_area(path)), Qt::black, new_color);
};
#ifdef _WIN32
#ifdef HAS_QT_WIN_STUFF
if (!m_thumb_bar) return;
m_icon_thumb_play = icon(":/Icons/play.png");
@ -1787,14 +1787,6 @@ void main_window::RepaintToolBarIcons()
// resize toolbar elements
// for highdpi resize toolbar icons and height dynamically
// choose factors to mimic Gui-Design in main_window.ui
// TODO: delete this in case Qt::AA_EnableHighDpiScaling is enabled in main.cpp
#ifdef _WIN32
const int tool_icon_height = menuBar()->sizeHint().height() * 1.5;
ui->toolBar->setIconSize(QSize(tool_icon_height, tool_icon_height));
#endif
const int tool_bar_height = ui->toolBar->sizeHint().height();
for (const auto& act : ui->toolBar->actions())
@ -1820,7 +1812,7 @@ void main_window::OnEmuRun(bool /*start_playtime*/) const
m_debugger_frame->EnableButtons(true);
#ifdef _WIN32
#ifdef HAS_QT_WIN_STUFF
m_thumb_stop->setToolTip(stop_tooltip);
m_thumb_restart->setToolTip(restart_tooltip);
m_thumb_playPause->setToolTip(pause_tooltip);
@ -1843,7 +1835,7 @@ void main_window::OnEmuResume() const
const QString pause_tooltip = tr("Pause %0").arg(title);
const QString stop_tooltip = tr("Stop %0").arg(title);
#ifdef _WIN32
#ifdef HAS_QT_WIN_STUFF
m_thumb_stop->setToolTip(stop_tooltip);
m_thumb_restart->setToolTip(restart_tooltip);
m_thumb_playPause->setToolTip(pause_tooltip);
@ -1862,7 +1854,7 @@ void main_window::OnEmuPause() const
const QString title = GetCurrentTitle();
const QString resume_tooltip = tr("Resume %0").arg(title);
#ifdef _WIN32
#ifdef HAS_QT_WIN_STUFF
m_thumb_playPause->setToolTip(resume_tooltip);
m_thumb_playPause->setIcon(m_icon_thumb_play);
#endif
@ -1886,7 +1878,7 @@ void main_window::OnEmuStop()
ui->sysPauseAct->setText(tr("&Play"));
ui->sysPauseAct->setIcon(m_icon_play);
#ifdef _WIN32
#ifdef HAS_QT_WIN_STUFF
m_thumb_playPause->setToolTip(play_tooltip);
m_thumb_playPause->setIcon(m_icon_thumb_play);
#endif
@ -1908,7 +1900,7 @@ void main_window::OnEmuStop()
ui->toolbar_start->setText(tr("Restart"));
ui->toolbar_start->setToolTip(restart_tooltip);
ui->sysRebootAct->setEnabled(true);
#ifdef _WIN32
#ifdef HAS_QT_WIN_STUFF
m_thumb_restart->setToolTip(restart_tooltip);
m_thumb_restart->setEnabled(true);
#endif
@ -1947,7 +1939,7 @@ void main_window::OnEmuReady() const
const QString play_tooltip = tr("Play %0").arg(title);
m_debugger_frame->EnableButtons(true);
#ifdef _WIN32
#ifdef HAS_QT_WIN_STUFF
m_thumb_playPause->setToolTip(play_tooltip);
m_thumb_playPause->setIcon(m_icon_thumb_play);
#endif
@ -1971,7 +1963,7 @@ void main_window::OnEmuReady() const
void main_window::EnableMenus(bool enabled) const
{
// Thumbnail Buttons
#ifdef _WIN32
#ifdef HAS_QT_WIN_STUFF
m_thumb_playPause->setEnabled(enabled);
m_thumb_stop->setEnabled(enabled);
m_thumb_restart->setEnabled(enabled);
@ -3139,14 +3131,14 @@ void main_window::CreateDockWindows()
ui->toolbar_start->setEnabled(enable_play_buttons);
ui->sysPauseAct->setEnabled(enable_play_buttons);
#ifdef _WIN32
#ifdef HAS_QT_WIN_STUFF
m_thumb_playPause->setEnabled(enable_play_buttons);
#endif
if (!tooltip.isEmpty())
{
ui->toolbar_start->setToolTip(tooltip);
#ifdef _WIN32
#ifdef HAS_QT_WIN_STUFF
m_thumb_playPause->setToolTip(tooltip);
#endif
}

View file

@ -1,6 +1,6 @@
#pragma once
#ifdef _WIN32
#ifdef HAS_QT_WIN_STUFF
#include <QWinThumbnailToolBar>
#include <QWinThumbnailToolButton>
#endif
@ -60,7 +60,7 @@ class main_window : public QMainWindow
QIcon m_icon_fullscreen_on;
QIcon m_icon_fullscreen_off;
#ifdef _WIN32
#ifdef HAS_QT_WIN_STUFF
QIcon m_icon_thumb_play;
QIcon m_icon_thumb_pause;
QIcon m_icon_thumb_stop;

View file

@ -1150,7 +1150,7 @@ void memory_viewer_panel::ShowImage(QWidget* parent, u32 addr, color_format form
{
if (object == m_canvas && (event->type() == QEvent::HoverMove || event->type() == QEvent::HoverEnter || event->type() == QEvent::HoverLeave))
{
const QPoint xy = static_cast<QHoverEvent*>(event)->pos() / m_canvas_scale;
const QPointF xy = static_cast<QHoverEvent*>(event)->position() / m_canvas_scale;
set_window_name_by_coordinates(xy.x(), xy.y());
return false;
}
@ -1159,7 +1159,7 @@ void memory_viewer_panel::ShowImage(QWidget* parent, u32 addr, color_format form
{
QLineEdit* addr_line = static_cast<memory_viewer_panel*>(parent())->m_addr_line;
const QPoint xy = static_cast<QMouseEvent*>(event)->pos() / m_canvas_scale;
const QPointF xy = static_cast<QMouseEvent*>(event)->position() / m_canvas_scale;
addr_line->setText(qstr(fmt::format("%08x", get_pointed_addr(xy.x(), xy.y()))));
Q_EMIT addr_line->returnPressed();
close();

View file

@ -182,7 +182,7 @@ void osk_dialog_frame::Create(const osk_params& params)
void osk_dialog_frame::SetOskText(const QString& text)
{
std::memcpy(osk_text.data(), utils::bless<char16_t>(text.constData()), std::min(osk_text.size(), text.size() + usz{1}) * sizeof(char16_t));
std::memcpy(osk_text.data(), utils::bless<char16_t>(text.constData()), std::min<usz>(osk_text.size(), text.size() + usz{1}) * sizeof(char16_t));
}
void osk_dialog_frame::Close(s32 status)

View file

@ -1,6 +1,6 @@
#include "progress_indicator.h"
#ifdef _WIN32
#ifdef HAS_QT_WIN_STUFF
#include <QCoreApplication>
#include <QWinTaskbarProgress>
#elif HAVE_QTDBUS
@ -10,7 +10,7 @@
progress_indicator::progress_indicator(int minimum, int maximum)
{
#ifdef _WIN32
#ifdef HAS_QT_WIN_STUFF
m_tb_button = std::make_unique<QWinTaskbarButton>();
m_tb_button->progress()->setRange(minimum, maximum);
m_tb_button->progress()->setVisible(false);
@ -25,7 +25,7 @@ progress_indicator::progress_indicator(int minimum, int maximum)
progress_indicator::~progress_indicator()
{
#ifdef _WIN32
#ifdef HAS_QT_WIN_STUFF
// QWinTaskbarProgress::hide() will crash if the application is already about to close, even if the object is not null.
if (!QCoreApplication::closingDown())
{
@ -38,7 +38,7 @@ progress_indicator::~progress_indicator()
void progress_indicator::show(QWindow* window)
{
#ifdef _WIN32
#ifdef HAS_QT_WIN_STUFF
m_tb_button->setWindow(window);
m_tb_button->progress()->show();
#else
@ -48,7 +48,7 @@ void progress_indicator::show(QWindow* window)
int progress_indicator::value() const
{
#ifdef _WIN32
#ifdef HAS_QT_WIN_STUFF
return m_tb_button->progress()->value();
#else
return m_value;
@ -57,7 +57,7 @@ int progress_indicator::value() const
void progress_indicator::set_value(int value)
{
#ifdef _WIN32
#ifdef HAS_QT_WIN_STUFF
m_tb_button->progress()->setValue(std::clamp(value, m_tb_button->progress()->minimum(), m_tb_button->progress()->maximum()));
#else
m_value = std::clamp(value, m_minimum, m_maximum);
@ -69,7 +69,7 @@ void progress_indicator::set_value(int value)
void progress_indicator::set_range(int minimum, int maximum)
{
#ifdef _WIN32
#ifdef HAS_QT_WIN_STUFF
m_tb_button->progress()->setRange(minimum, maximum);
#else
m_minimum = minimum;
@ -79,7 +79,7 @@ void progress_indicator::set_range(int minimum, int maximum)
void progress_indicator::reset()
{
#ifdef _WIN32
#ifdef HAS_QT_WIN_STUFF
m_tb_button->progress()->reset();
#else
m_value = m_minimum;
@ -91,7 +91,7 @@ void progress_indicator::reset()
void progress_indicator::signal_failure()
{
#ifdef _WIN32
#ifdef HAS_QT_WIN_STUFF
m_tb_button->progress()->stop();
#elif HAVE_QTDBUS
update_progress(0, false, true);

View file

@ -2,7 +2,7 @@
#include <QWindow>
#ifdef _WIN32
#ifdef HAS_QT_WIN_STUFF
#include <QWinTaskbarButton>
#endif
@ -23,7 +23,7 @@ public:
private:
#ifdef _WIN32
#ifdef HAS_QT_WIN_STUFF
std::unique_ptr<QWinTaskbarButton> m_tb_button;
#else
int m_value = 0;

View file

@ -3,40 +3,14 @@
LOG_CHANNEL(camera_log, "Camera");
template <>
void fmt_class_string<QCamera::Status>::format(std::string& out, u64 arg)
{
format_enum(out, arg, [](QCamera::Status value)
{
switch (value)
{
case QCamera::Status::UnavailableStatus: return "Unavailable";
case QCamera::Status::UnloadedStatus: return "Unloaded";
case QCamera::Status::LoadingStatus: return "Loading";
case QCamera::Status::UnloadingStatus: return "Unloading";
case QCamera::Status::LoadedStatus: return "Loaded";
case QCamera::Status::StandbyStatus: return "Standby";
case QCamera::Status::StartingStatus: return "Starting";
case QCamera::Status::StoppingStatus: return "Stopping";
case QCamera::Status::ActiveStatus: return "Active";
}
return unknown;
});
}
qt_camera_error_handler::qt_camera_error_handler(std::shared_ptr<QCamera> camera, std::function<void(QCamera::Status)> status_callback)
qt_camera_error_handler::qt_camera_error_handler(std::shared_ptr<QCamera> camera, std::function<void(bool)> status_callback)
: m_camera(std::move(camera))
, m_status_callback(std::move(status_callback))
{
if (m_camera)
{
connect(m_camera.get(), QOverload<QMultimedia::AvailabilityStatus>::of(&QCamera::availabilityChanged), this, &qt_camera_error_handler::handle_availability);
connect(m_camera.get(), &QCamera::stateChanged, this, &qt_camera_error_handler::handle_camera_state);
connect(m_camera.get(), &QCamera::statusChanged, this, &qt_camera_error_handler::handle_camera_status);
connect(m_camera.get(), &QCamera::activeChanged, this, &qt_camera_error_handler::handle_camera_active);
connect(m_camera.get(), &QCamera::errorOccurred, this, &qt_camera_error_handler::handle_camera_error);
connect(m_camera.get(), &QCamera::captureModeChanged, this, &qt_camera_error_handler::handle_capture_modes);
connect(m_camera.get(), QOverload<QCamera::LockStatus, QCamera::LockChangeReason>::of(&QCamera::lockStatusChanged), this, &qt_camera_error_handler::handle_lock_status);
}
}
@ -44,37 +18,17 @@ qt_camera_error_handler::~qt_camera_error_handler()
{
}
void qt_camera_error_handler::handle_availability(QMultimedia::AvailabilityStatus availability)
void qt_camera_error_handler::handle_camera_active(bool is_active)
{
camera_log.notice("Camera availability changed to %d", static_cast<int>(availability));
}
void qt_camera_error_handler::handle_camera_state(QCamera::State state)
{
camera_log.notice("Camera state changed to %d", static_cast<int>(state));
}
void qt_camera_error_handler::handle_camera_status(QCamera::Status status)
{
camera_log.notice("Camera status changed to %s", status);
camera_log.notice("Camera active status changed to %d", is_active);
if (m_status_callback)
{
m_status_callback(status);
m_status_callback(is_active);
}
}
void qt_camera_error_handler::handle_lock_status(QCamera::LockStatus status, QCamera::LockChangeReason reason)
void qt_camera_error_handler::handle_camera_error(QCamera::Error error, const QString& errorString)
{
camera_log.notice("Camera lock status changed to %d (reason=%d)", static_cast<int>(status), static_cast<int>(reason));
}
void qt_camera_error_handler::handle_capture_modes(QCamera::CaptureModes capture_modes)
{
camera_log.notice("Camera capture modes changed to %d", static_cast<int>(capture_modes));
}
void qt_camera_error_handler::handle_camera_error(QCamera::Error error)
{
camera_log.error("Error event: \"%s\" (error=%d)", m_camera ? m_camera->errorString() : "", static_cast<int>(error));
camera_log.error("Error event: \"%s\" (error=%d)", errorString, static_cast<int>(error));
}

View file

@ -8,18 +8,14 @@ class qt_camera_error_handler : public QObject
Q_OBJECT
public:
qt_camera_error_handler(std::shared_ptr<QCamera> camera, std::function<void(QCamera::Status)> status_callback);
qt_camera_error_handler(std::shared_ptr<QCamera> camera, std::function<void(bool)> status_callback);
virtual ~qt_camera_error_handler();
private Q_SLOTS:
void handle_availability(QMultimedia::AvailabilityStatus availability);
void handle_lock_status(QCamera::LockStatus, QCamera::LockChangeReason);
void handle_capture_modes(QCamera::CaptureModes capture_modes);
void handle_camera_state(QCamera::State state);
void handle_camera_status(QCamera::Status status);
void handle_camera_error(QCamera::Error error);
void handle_camera_active(bool is_active);
void handle_camera_error(QCamera::Error error, const QString& errorString);
private:
std::shared_ptr<QCamera> m_camera;
std::function<void(QCamera::Status)> m_status_callback = nullptr;
std::function<void(bool)> m_status_callback = nullptr;
};

View file

@ -5,17 +5,16 @@
#include "Emu/Io/camera_config.h"
#include "Emu/Cell/lv2/sys_event.h"
#include <QMediaService>
#include <QCameraInfo>
#include <QMediaDevices>
LOG_CHANNEL(camera_log, "Camera");
qt_camera_handler::qt_camera_handler() : camera_handler_base()
{
// List available cameras
for (const QCameraInfo& cameraInfo : QCameraInfo::availableCameras())
for (const QCameraDevice& camera_device : QMediaDevices::videoInputs())
{
camera_log.success("Found camera: name=%s, description=%s", cameraInfo.deviceName(), cameraInfo.description());
camera_log.success("Found camera: id=%s, description=%s", camera_device.id().toStdString(), camera_device.description());
}
if (!g_cfg_camera.load())
@ -29,60 +28,53 @@ qt_camera_handler::~qt_camera_handler()
Emu.BlockingCallFromMainThread([&]()
{
close_camera();
m_surface.reset();
m_camera.reset();
m_error_handler.reset();
reset();
});
}
void qt_camera_handler::set_camera(const QCameraInfo& camera_info)
void qt_camera_handler::reset()
{
m_camera.reset();
m_error_handler.reset();
m_video_sink.reset();
m_media_capture_session.reset();
}
void qt_camera_handler::set_camera(const QCameraDevice& camera_info)
{
if (camera_info.isNull())
{
m_surface.reset();
m_camera.reset();
m_error_handler.reset();
reset();
return;
}
// Determine if the camera is front facing, in which case we will need to flip the image horizontally.
const bool front_facing = camera_info.position() == QCamera::Position::FrontFace;
const bool front_facing = camera_info.position() == QCameraDevice::Position::FrontFace;
camera_log.success("Using camera: name=\"%s\", description=\"%s\", front_facing=%d", camera_info.deviceName(), camera_info.description(), front_facing);
camera_log.success("Using camera: id=\"%s\", description=\"%s\", front_facing=%d", camera_info.id().toStdString(), camera_info.description(), front_facing);
// Create camera and video surface
m_surface.reset(new qt_camera_video_surface(front_facing, nullptr));
m_media_capture_session.reset(new QMediaCaptureSession(nullptr));
m_video_sink.reset(new qt_camera_video_sink(front_facing, nullptr));
m_camera.reset(new QCamera(camera_info));
m_error_handler.reset(new qt_camera_error_handler(m_camera,
[this](QCamera::Status status)
[this](bool is_active)
{
switch (status)
if (is_active)
{
case QCamera::UnavailableStatus:
m_state = camera_handler_state::not_available;
break;
case QCamera::UnloadedStatus:
case QCamera::UnloadingStatus:
m_state = camera_handler_state::closed;
break;
case QCamera::StandbyStatus:
case QCamera::StoppingStatus:
case QCamera::LoadedStatus:
case QCamera::LoadingStatus:
m_state = camera_handler_state::open;
break;
case QCamera::StartingStatus:
case QCamera::ActiveStatus:
m_state = camera_handler_state::running;
break;
default:
camera_log.error("Ignoring unknown status %d", static_cast<int>(status));
break;
}
else
{
m_state = camera_handler_state::closed;
}
}));
// Set view finder and update the settings
m_camera->setViewfinder(m_surface.get());
// Setup video sink
m_media_capture_session->setCamera(m_camera.get());
m_media_capture_session->setVideoSink(m_video_sink.get());
// Update the settings
update_camera_settings();
}
@ -94,25 +86,25 @@ void qt_camera_handler::open_camera()
m_camera_id != camera_id)
{
camera_log.notice("Switching camera from %s to %s", m_camera_id, camera_id);
camera_log.notice("Unloading old camera...");
if (m_camera) m_camera->unload();
camera_log.notice("Stopping old camera...");
if (m_camera) m_camera->stop();
m_camera_id = camera_id;
}
QCameraInfo selected_camera;
QCameraDevice selected_camera{};
if (m_camera_id == g_cfg.io.camera_id.def)
{
selected_camera = QCameraInfo::defaultCamera();
selected_camera = QMediaDevices::defaultVideoInput();
}
else if (!m_camera_id.empty())
{
const QString camera_id = QString::fromStdString(m_camera_id);
for (const QCameraInfo& camera_info : QCameraInfo::availableCameras())
for (const QCameraDevice& camera_device : QMediaDevices::videoInputs())
{
if (camera_id == camera_info.deviceName())
if (camera_id == camera_device.id())
{
selected_camera = camera_info;
selected_camera = camera_device;
break;
}
}
@ -124,35 +116,26 @@ void qt_camera_handler::open_camera()
{
if (m_camera_id.empty()) camera_log.notice("Camera disabled");
else camera_log.error("No camera found");
m_state = camera_handler_state::not_available;
m_state = camera_handler_state::closed;
return;
}
if (m_camera->state() != QCamera::State::UnloadedState)
if (m_camera->isActive())
{
camera_log.notice("Camera already loaded");
camera_log.notice("Camera already active");
return;
}
// Load/open camera
m_camera->load();
// List all supported formats for debugging
for (const QCamera::FrameRateRange& frame_rate : m_camera->supportedViewfinderFrameRateRanges())
for (const QCameraFormat& format : m_camera->cameraDevice().videoFormats())
{
camera_log.notice("Supported frame rate range: %f-%f", frame_rate.minimumFrameRate, frame_rate.maximumFrameRate);
}
for (const QVideoFrame::PixelFormat& pixel_format : m_camera->supportedViewfinderPixelFormats())
{
camera_log.notice("Supported pixel format: %d", static_cast<int>(pixel_format));
}
for (const QSize& resolution : m_camera->supportedViewfinderResolutions())
{
camera_log.notice("Supported resolution: %dx%d", resolution.width(), resolution.height());
camera_log.notice("Supported format: pixelformat=%s, resolution=%dx%d framerate=%f-%f", format.pixelFormat(), format.resolution().width(), format.resolution().height(), format.minFrameRate(), format.maxFrameRate());
}
// Update camera and view finder settings
update_camera_settings();
m_state = camera_handler_state::open;
}
void qt_camera_handler::close_camera()
@ -163,18 +146,12 @@ void qt_camera_handler::close_camera()
{
if (m_camera_id.empty()) camera_log.notice("Camera disabled");
else camera_log.error("No camera found");
m_state = camera_handler_state::not_available;
return;
}
if (m_camera->state() == QCamera::State::UnloadedState)
{
camera_log.notice("Camera already unloaded");
m_state = camera_handler_state::closed;
return;
}
// Unload/close camera
m_camera->unload();
m_camera->stop();
}
void qt_camera_handler::start_camera()
@ -185,22 +162,16 @@ void qt_camera_handler::start_camera()
{
if (m_camera_id.empty()) camera_log.notice("Camera disabled");
else camera_log.error("No camera found");
m_state = camera_handler_state::not_available;
m_state = camera_handler_state::closed;
return;
}
if (m_camera->state() == QCamera::State::ActiveState)
if (m_camera->isActive())
{
camera_log.notice("Camera already started");
return;
}
if (m_camera->state() == QCamera::State::UnloadedState)
{
camera_log.notice("Camera not open");
open_camera();
}
// Start camera. We will start receiving frames now.
m_camera->start();
}
@ -213,11 +184,11 @@ void qt_camera_handler::stop_camera()
{
if (m_camera_id.empty()) camera_log.notice("Camera disabled");
else camera_log.error("No camera found");
m_state = camera_handler_state::not_available;
m_state = camera_handler_state::closed;
return;
}
if (m_camera->state() == QCamera::State::LoadedState)
if (!m_camera->isActive())
{
camera_log.notice("Camera already stopped");
return;
@ -232,9 +203,9 @@ void qt_camera_handler::set_format(s32 format, u32 bytesize)
m_format = format;
m_bytesize = bytesize;
if (m_surface)
if (m_video_sink)
{
m_surface->set_format(m_format, m_bytesize);
m_video_sink->set_format(m_format, m_bytesize);
}
}
@ -248,9 +219,9 @@ void qt_camera_handler::set_resolution(u32 width, u32 height)
m_width = width;
m_height = height;
if (m_surface)
if (m_video_sink)
{
m_surface->set_resolution(m_width, m_height);
m_video_sink->set_resolution(m_width, m_height);
}
}
@ -258,15 +229,15 @@ void qt_camera_handler::set_mirrored(bool mirrored)
{
m_mirrored = mirrored;
if (m_surface)
if (m_video_sink)
{
m_surface->set_mirrored(m_mirrored);
m_video_sink->set_mirrored(m_mirrored);
}
}
u64 qt_camera_handler::frame_number() const
{
return m_surface ? m_surface->frame_number() : 0;
return m_video_sink ? m_video_sink->frame_number() : 0;
}
camera_handler_base::camera_handler_state qt_camera_handler::get_image(u8* buf, u64 size, u32& width, u32& height, u64& frame_number, u64& bytes_read)
@ -280,22 +251,22 @@ camera_handler_base::camera_handler_state qt_camera_handler::get_image(u8* buf,
m_camera_id != camera_id)
{
camera_log.notice("Switching cameras");
m_state = camera_handler_state::not_available;
return camera_handler_state::not_available;
m_state = camera_handler_state::closed;
return camera_handler_state::closed;
}
if (m_camera_id.empty())
{
camera_log.notice("Camera disabled");
m_state = camera_handler_state::not_available;
return camera_handler_state::not_available;
m_state = camera_handler_state::closed;
return camera_handler_state::closed;
}
if (!m_camera || !m_surface)
if (!m_camera || !m_video_sink)
{
camera_log.fatal("Error: camera invalid");
m_state = camera_handler_state::not_available;
return camera_handler_state::not_available;
m_state = camera_handler_state::closed;
return camera_handler_state::closed;
}
// Backup current state. State may change through events.
@ -304,7 +275,7 @@ camera_handler_base::camera_handler_state qt_camera_handler::get_image(u8* buf,
if (current_state == camera_handler_state::running)
{
// Copy latest image into out buffer.
m_surface->get_image(buf, size, width, height, frame_number, bytes_read);
m_video_sink->get_image(buf, size, width, height, frame_number, bytes_read);
}
else
{
@ -317,7 +288,7 @@ camera_handler_base::camera_handler_state qt_camera_handler::get_image(u8* buf,
void qt_camera_handler::update_camera_settings()
{
// Update camera if possible. We can only do this if it is already loaded.
if (m_camera && m_camera->state() != QCamera::State::UnloadedState)
if (m_camera && m_camera->isAvailable())
{
// Load selected settings from config file
bool success = false;
@ -327,32 +298,23 @@ void qt_camera_handler::update_camera_settings()
{
camera_log.notice("Found config entry for camera \"%s\"", m_camera_id);
QCameraViewfinderSettings setting;
setting.setResolution(cfg_setting.width, cfg_setting.height);
setting.setMinimumFrameRate(cfg_setting.min_fps);
setting.setMaximumFrameRate(cfg_setting.max_fps);
setting.setPixelFormat(static_cast<QVideoFrame::PixelFormat>(cfg_setting.format));
setting.setPixelAspectRatio(cfg_setting.pixel_aspect_width, cfg_setting.pixel_aspect_height);
// List all available settings and choose the proper value if possible.
const double epsilon = 0.001;
success = false;
for (const QCameraViewfinderSettings& supported_setting : m_camera->supportedViewfinderSettings(setting))
for (const QCameraFormat& supported_setting : m_camera->cameraDevice().videoFormats())
{
if (supported_setting.resolution().width() == setting.resolution().width() &&
supported_setting.resolution().height() == setting.resolution().height() &&
supported_setting.minimumFrameRate() >= (setting.minimumFrameRate() - epsilon) &&
supported_setting.minimumFrameRate() <= (setting.minimumFrameRate() + epsilon) &&
supported_setting.maximumFrameRate() >= (setting.maximumFrameRate() - epsilon) &&
supported_setting.maximumFrameRate() <= (setting.maximumFrameRate() + epsilon) &&
supported_setting.pixelFormat() == setting.pixelFormat() &&
supported_setting.pixelAspectRatio().width() == setting.pixelAspectRatio().width() &&
supported_setting.pixelAspectRatio().height() == setting.pixelAspectRatio().height())
if (supported_setting.resolution().width() == cfg_setting.width &&
supported_setting.resolution().height() == cfg_setting.height &&
supported_setting.minFrameRate() >= (cfg_setting.min_fps - epsilon) &&
supported_setting.minFrameRate() <= (cfg_setting.min_fps + epsilon) &&
supported_setting.maxFrameRate() >= (cfg_setting.max_fps - epsilon) &&
supported_setting.maxFrameRate() <= (cfg_setting.max_fps + epsilon) &&
supported_setting.pixelFormat() == static_cast<QVideoFrameFormat::PixelFormat>(cfg_setting.format))
{
// Apply settings.
camera_log.notice("Setting view finder settings: frame_rate=%f, width=%d, height=%d, pixel_format=%s",
supported_setting.maximumFrameRate(), supported_setting.resolution().width(), supported_setting.resolution().height(), supported_setting.pixelFormat());
m_camera->setViewfinderSettings(supported_setting);
supported_setting.maxFrameRate(), supported_setting.resolution().width(), supported_setting.resolution().height(), supported_setting.pixelFormat());
m_camera->setCameraFormat(supported_setting);
success = true;
break;
}
@ -372,10 +334,10 @@ void qt_camera_handler::update_camera_settings()
}
// Update video surface if possible
if (m_surface)
if (m_video_sink)
{
m_surface->set_resolution(m_width, m_height);
m_surface->set_format(m_format, m_bytesize);
m_surface->set_mirrored(m_mirrored);
m_video_sink->set_resolution(m_width, m_height);
m_video_sink->set_format(m_format, m_bytesize);
m_video_sink->set_mirrored(m_mirrored);
}
}

View file

@ -1,12 +1,12 @@
#pragma once
#include "Emu/Io/camera_handler_base.h"
#include "qt_camera_video_surface.h"
#include "qt_camera_video_sink.h"
#include "qt_camera_error_handler.h"
#include <QCamera>
#include <QCameraImageCapture>
#include <QAbstractVideoSurface>
#include <QMediaCaptureSession>
#include <QVideoSink>
class qt_camera_handler final : public camera_handler_base
{
@ -14,7 +14,7 @@ public:
qt_camera_handler();
virtual ~qt_camera_handler();
void set_camera(const QCameraInfo& camera_info);
void set_camera(const QCameraDevice& camera_info);
void open_camera() override;
void close_camera() override;
@ -28,10 +28,12 @@ public:
camera_handler_state get_image(u8* buf, u64 size, u32& width, u32& height, u64& frame_number, u64& bytes_read) override;
private:
void reset();
void update_camera_settings();
std::string m_camera_id;
std::shared_ptr<QCamera> m_camera;
std::unique_ptr<qt_camera_video_surface> m_surface;
std::unique_ptr<QMediaCaptureSession> m_media_capture_session;
std::unique_ptr<qt_camera_video_sink> m_video_sink;
std::unique_ptr<qt_camera_error_handler> m_error_handler;
};

View file

@ -1,5 +1,5 @@
#include "stdafx.h"
#include "qt_camera_video_surface.h"
#include "qt_camera_video_sink.h"
#include "Emu/Cell/Modules/cellCamera.h"
#include "Emu/system_config.h"
@ -8,12 +8,13 @@
LOG_CHANNEL(camera_log, "Camera");
qt_camera_video_surface::qt_camera_video_surface(bool front_facing, QObject *parent)
: QAbstractVideoSurface(parent), m_front_facing(front_facing)
qt_camera_video_sink::qt_camera_video_sink(bool front_facing, QObject *parent)
: QVideoSink(parent), m_front_facing(front_facing)
{
connect(this, &QVideoSink::videoFrameChanged, this, &qt_camera_video_sink::present);
}
qt_camera_video_surface::~qt_camera_video_surface()
qt_camera_video_sink::~qt_camera_video_sink()
{
std::lock_guard lock(m_mutex);
@ -28,51 +29,7 @@ qt_camera_video_surface::~qt_camera_video_surface()
}
}
QList<QVideoFrame::PixelFormat> qt_camera_video_surface::supportedPixelFormats(QAbstractVideoBuffer::HandleType type) const
{
Q_UNUSED(type)
// Support all cameras
QList<QVideoFrame::PixelFormat> result;
result
<< QVideoFrame::Format_ARGB32
<< QVideoFrame::Format_ARGB32_Premultiplied
<< QVideoFrame::Format_RGB32
<< QVideoFrame::Format_RGB24
<< QVideoFrame::Format_RGB565
<< QVideoFrame::Format_RGB555
<< QVideoFrame::Format_ARGB8565_Premultiplied
<< QVideoFrame::Format_BGRA32
<< QVideoFrame::Format_BGRA32_Premultiplied
<< QVideoFrame::Format_BGR32
<< QVideoFrame::Format_BGR24
<< QVideoFrame::Format_BGR565
<< QVideoFrame::Format_BGR555
<< QVideoFrame::Format_BGRA5658_Premultiplied
<< QVideoFrame::Format_AYUV444
<< QVideoFrame::Format_AYUV444_Premultiplied
<< QVideoFrame::Format_YUV444
<< QVideoFrame::Format_YUV420P
<< QVideoFrame::Format_YV12
<< QVideoFrame::Format_UYVY
<< QVideoFrame::Format_YUYV
<< QVideoFrame::Format_NV12
<< QVideoFrame::Format_NV21
<< QVideoFrame::Format_IMC1
<< QVideoFrame::Format_IMC2
<< QVideoFrame::Format_IMC3
<< QVideoFrame::Format_IMC4
<< QVideoFrame::Format_Y8
<< QVideoFrame::Format_Y16
<< QVideoFrame::Format_Jpeg
<< QVideoFrame::Format_CameraRaw
<< QVideoFrame::Format_AdobeDng
<< QVideoFrame::Format_ABGR32
<< QVideoFrame::Format_YUV422P;
return result;
}
bool qt_camera_video_surface::present(const QVideoFrame& frame)
bool qt_camera_video_sink::present(const QVideoFrame& frame)
{
if (!frame.isValid())
{
@ -82,18 +39,18 @@ bool qt_camera_video_surface::present(const QVideoFrame& frame)
// Get video image. Map frame for faster read operations.
QVideoFrame tmp(frame);
if (!tmp.map(QAbstractVideoBuffer::ReadOnly))
if (!tmp.map(QVideoFrame::ReadOnly))
{
camera_log.error("Failed to map video frame");
return false;
}
// Get image. This usually also converts the image to ARGB32.
QImage image = frame.image();
QImage image = frame.toImage();
if (image.isNull())
{
camera_log.warning("Image is invalid: pixel_format=%s, format=%d", tmp.pixelFormat(), static_cast<int>(QVideoFrame::imageFormatFromPixelFormat(tmp.pixelFormat())));
camera_log.warning("Image is invalid: pixel_format=%s, format=%d", tmp.pixelFormat(), static_cast<int>(QVideoFrameFormat::imageFormatFromPixelFormat(tmp.pixelFormat())));
}
else
{
@ -293,7 +250,7 @@ bool qt_camera_video_surface::present(const QVideoFrame& frame)
return true;
}
void qt_camera_video_surface::set_format(s32 format, u32 bytesize)
void qt_camera_video_sink::set_format(s32 format, u32 bytesize)
{
camera_log.notice("Setting format: format=%d, bytesize=%d", format, bytesize);
@ -301,7 +258,7 @@ void qt_camera_video_surface::set_format(s32 format, u32 bytesize)
m_bytesize = bytesize;
}
void qt_camera_video_surface::set_resolution(u32 width, u32 height)
void qt_camera_video_sink::set_resolution(u32 width, u32 height)
{
camera_log.notice("Setting resolution: width=%d, height=%d", width, height);
@ -309,19 +266,19 @@ void qt_camera_video_surface::set_resolution(u32 width, u32 height)
m_height = height;
}
void qt_camera_video_surface::set_mirrored(bool mirrored)
void qt_camera_video_sink::set_mirrored(bool mirrored)
{
camera_log.notice("Setting mirrored: mirrored=%d", mirrored);
m_mirrored = mirrored;
}
u64 qt_camera_video_surface::frame_number() const
u64 qt_camera_video_sink::frame_number() const
{
return m_frame_number.load();
}
void qt_camera_video_surface::get_image(u8* buf, u64 size, u32& width, u32& height, u64& frame_number, u64& bytes_read)
void qt_camera_video_sink::get_image(u8* buf, u64 size, u32& width, u32& height, u64& frame_number, u64& bytes_read)
{
// Lock read buffer
std::lock_guard lock(m_mutex);
@ -348,7 +305,7 @@ void qt_camera_video_surface::get_image(u8* buf, u64 size, u32& width, u32& heig
}
}
u32 qt_camera_video_surface::read_index() const
u32 qt_camera_video_sink::read_index() const
{
// The read buffer index cannot be the same as the write index
return (m_write_index + 1u) % ::narrow<u32>(m_image_buffer.size());

View file

@ -1,18 +1,18 @@
#pragma once
#include <QAbstractVideoSurface>
#include <QVideoFrame>
#include <QVideoSink>
#include <QImage>
#include <array>
class qt_camera_video_surface final : public QAbstractVideoSurface
class qt_camera_video_sink final : public QVideoSink
{
public:
qt_camera_video_surface(bool front_facing, QObject *parent = nullptr);
virtual ~qt_camera_video_surface();
qt_camera_video_sink(bool front_facing, QObject *parent = nullptr);
virtual ~qt_camera_video_sink();
QList<QVideoFrame::PixelFormat> supportedPixelFormats(QAbstractVideoBuffer::HandleType type = QAbstractVideoBuffer::NoHandle) const override;
bool present(const QVideoFrame& frame) override;
bool present(const QVideoFrame& frame);
void set_format(s32 format, u32 bytesize);
void set_resolution(u32 width, u32 height);

View file

@ -15,8 +15,6 @@ void fmt_class_string<QMediaPlayer::Error>::format(std::string& out, u64 arg)
case QMediaPlayer::Error::FormatError: return "FormatError";
case QMediaPlayer::Error::NetworkError: return "NetworkError";
case QMediaPlayer::Error::AccessDeniedError: return "AccessDeniedError";
case QMediaPlayer::Error::ServiceMissingError: return "ServiceMissingError";
case QMediaPlayer::Error::MediaIsPlaylist: return "MediaIsPlaylist";
}
return unknown;
@ -30,7 +28,6 @@ void fmt_class_string<QMediaPlayer::MediaStatus>::format(std::string& out, u64 a
{
switch (value)
{
case QMediaPlayer::MediaStatus::UnknownMediaStatus: return "UnknownMediaStatus";
case QMediaPlayer::MediaStatus::NoMedia: return "NoMedia";
case QMediaPlayer::MediaStatus::LoadingMedia: return "LoadingMedia";
case QMediaPlayer::MediaStatus::LoadedMedia: return "LoadedMedia";
@ -46,15 +43,15 @@ void fmt_class_string<QMediaPlayer::MediaStatus>::format(std::string& out, u64 a
}
template <>
void fmt_class_string<QMediaPlayer::State>::format(std::string& out, u64 arg)
void fmt_class_string<QMediaPlayer::PlaybackState>::format(std::string& out, u64 arg)
{
format_enum(out, arg, [](QMediaPlayer::State value)
format_enum(out, arg, [](QMediaPlayer::PlaybackState value)
{
switch (value)
{
case QMediaPlayer::State::StoppedState: return "StoppedState";
case QMediaPlayer::State::PlayingState: return "PlayingState";
case QMediaPlayer::State::PausedState: return "PausedState";
case QMediaPlayer::PlaybackState::StoppedState: return "StoppedState";
case QMediaPlayer::PlaybackState::PlayingState: return "PlayingState";
case QMediaPlayer::PlaybackState::PausedState: return "PausedState";
}
return unknown;
@ -68,8 +65,8 @@ qt_music_error_handler::qt_music_error_handler(std::shared_ptr<QMediaPlayer> med
if (m_media_player)
{
connect(m_media_player.get(), &QMediaPlayer::mediaStatusChanged, this, &qt_music_error_handler::handle_media_status);
connect(m_media_player.get(), &QMediaPlayer::stateChanged, this, &qt_music_error_handler::handle_music_state);
connect(m_media_player.get(), QOverload<QMediaPlayer::Error>::of(&QMediaPlayer::error), this, &qt_music_error_handler::handle_music_error);
connect(m_media_player.get(), &QMediaPlayer::playbackStateChanged, this, &qt_music_error_handler::handle_music_state);
connect(m_media_player.get(), &QMediaPlayer::errorOccurred, this, &qt_music_error_handler::handle_music_error);
}
}
@ -87,12 +84,12 @@ void qt_music_error_handler::handle_media_status(QMediaPlayer::MediaStatus statu
}
}
void qt_music_error_handler::handle_music_state(QMediaPlayer::State state)
void qt_music_error_handler::handle_music_state(QMediaPlayer::PlaybackState state)
{
music_log.notice("New playback state: %s (state=%d)", state, static_cast<int>(state));
}
void qt_music_error_handler::handle_music_error(QMediaPlayer::Error error)
void qt_music_error_handler::handle_music_error(QMediaPlayer::Error error, const QString& errorString)
{
music_log.error("Error event: \"%s\" (error=%s)", m_media_player ? m_media_player->errorString() : "", error);
music_log.error("Error event: \"%s\" (error=%s)", errorString, error);
}

View file

@ -13,8 +13,8 @@ public:
private Q_SLOTS:
void handle_media_status(QMediaPlayer::MediaStatus status);
void handle_music_state(QMediaPlayer::State state);
void handle_music_error(QMediaPlayer::Error error);
void handle_music_state(QMediaPlayer::PlaybackState state);
void handle_music_error(QMediaPlayer::Error error, const QString& errorString);
private:
std::shared_ptr<QMediaPlayer> m_media_player;

View file

@ -4,6 +4,7 @@
#include "Utilities/Thread.h"
#include "util/logs.hpp"
#include <QAudioOutput>
#include <QUrl>
LOG_CHANNEL(music_log, "Music");
@ -13,7 +14,7 @@ qt_music_handler::qt_music_handler()
music_log.notice("Constructing Qt music handler...");
m_media_player = std::make_shared<QMediaPlayer>();
m_media_player->setAudioRole(QAudio::Role::MusicRole);
m_media_player->setAudioOutput(new QAudioOutput());
m_error_handler = std::make_unique<qt_music_error_handler>(m_media_player,
[this](QMediaPlayer::MediaStatus status)
@ -25,7 +26,6 @@ qt_music_handler::qt_music_handler()
switch (status)
{
case QMediaPlayer::MediaStatus::UnknownMediaStatus:
case QMediaPlayer::MediaStatus::NoMedia:
case QMediaPlayer::MediaStatus::LoadingMedia:
case QMediaPlayer::MediaStatus::LoadedMedia:
@ -90,7 +90,7 @@ void qt_music_handler::play(const std::string& path)
if (m_path != path)
{
m_path = path;
m_media_player->setMedia(QUrl(QString::fromStdString(path)));
m_media_player->setSource(QUrl::fromLocalFile(QString::fromStdString(path)));
}
music_log.notice("Playing music: %s", path);
@ -110,7 +110,7 @@ void qt_music_handler::fast_forward(const std::string& path)
if (m_path != path)
{
m_path = path;
m_media_player->setMedia(QUrl(QString::fromStdString(path)));
m_media_player->setSource(QUrl::fromLocalFile(QString::fromStdString(path)));
}
music_log.notice("Fast-forwarding music...");
@ -130,7 +130,7 @@ void qt_music_handler::fast_reverse(const std::string& path)
if (m_path != path)
{
m_path = path;
m_media_player->setMedia(QUrl(QString::fromStdString(path)));
m_media_player->setSource(QUrl::fromLocalFile(QString::fromStdString(path)));
}
music_log.notice("Fast-reversing music...");
@ -149,7 +149,7 @@ void qt_music_handler::set_volume(f32 volume)
{
const int new_volume = std::max<int>(0, std::min<int>(volume * 100, 100));
music_log.notice("Setting volume to %d%%", new_volume);
m_media_player->setVolume(new_volume);
m_media_player->audioOutput()->setVolume(new_volume);
});
}
@ -160,9 +160,8 @@ f32 qt_music_handler::get_volume() const
Emu.BlockingCallFromMainThread([&volume, this]()
{
const int current_volume = std::max(0, std::min(m_media_player->volume(), 100));
music_log.notice("Getting volume: %d%%", current_volume);
volume = current_volume / 100.0f;
volume = std::max(0.f, std::min(m_media_player->audioOutput()->volume(), 1.f));
music_log.notice("Getting volume: %d%%", volume);
});
return volume;

View file

@ -142,7 +142,7 @@ namespace gui
template <typename T>
void stop_future_watcher(QFutureWatcher<T>& watcher, bool cancel, std::shared_ptr<atomic_t<bool>> cancel_flag = nullptr)
{
if (watcher.isPaused() || watcher.isRunning())
if (watcher.isSuspended() || watcher.isRunning())
{
watcher.resume();

View file

@ -156,7 +156,7 @@ register_editor_dialog::register_editor_dialog(QWidget *parent, CPUDisAsm* _disa
connect(button_cancel, &QAbstractButton::clicked, this, &register_editor_dialog::reject);
connect(m_register_combo, &QComboBox::currentTextChanged, this, [this](const QString&)
{
if (const auto qvar = m_register_combo->currentData(); qvar.canConvert(QMetaType::Int))
if (const auto qvar = m_register_combo->currentData(); qvar.canConvert<int>())
{
updateRegister(qvar.toInt());
}

View file

@ -18,7 +18,6 @@
#include <QMenu>
#include <QMessageBox>
#include <QGuiApplication>
#include <QUrl>
#include <QDesktopServices>
#include <QPainter>
#include <QScreen>

View file

@ -1,5 +1,6 @@
#include <QButtonGroup>
#include <QCameraInfo>
#include <QCameraDevice>
#include <QMediaDevices>
#include <QDialogButtonBox>
#include <QFontMetrics>
#include <QPushButton>
@ -10,7 +11,6 @@
#include <QSpinBox>
#include <QTimer>
#include <QScreen>
#include <QUrl>
#include "gui_settings.h"
#include "display_sleep_control.h"
@ -1191,10 +1191,10 @@ settings_dialog::settings_dialog(std::shared_ptr<gui_settings> gui_settings, std
const std::string selected_camera = m_emu_settings->GetSetting(emu_settings_type::CameraID);
ui->cameraIdBox->addItem(tr("None", "Camera Device"), "");
ui->cameraIdBox->addItem(tr("Default", "Camera Device"), qstr(default_camera));
for (const QCameraInfo& camera_info : QCameraInfo::availableCameras())
for (const QCameraDevice& camera_info : QMediaDevices::videoInputs())
{
if (!camera_info.isNull())
ui->cameraIdBox->addItem(camera_info.description(), camera_info.deviceName());
ui->cameraIdBox->addItem(camera_info.description(), camera_info.id());
}
if (const int index = ui->cameraIdBox->findData(qstr(selected_camera)); index >= 0)
{

View file

@ -29,7 +29,6 @@
#include <QDir>
#include <QMenu>
#include <QDesktopServices>
#include <QUrl>
#include <QScrollBar>
#include <QWheelEvent>
#include <QGuiApplication>

View file

@ -10,7 +10,6 @@
#include <QDesktopServices>
#include <QMessageBox>
#include <QGuiApplication>
#include <QUrl>
#include "user_manager_dialog.h"
#include "table_item_delegate.h"