1
0
mirror of https://github.com/RPCS3/rpcs3.git synced 2024-11-22 02:32:36 +01:00

Qt: Add camera settings dialog

This commit is contained in:
Megamouse 2021-10-22 16:58:55 +02:00
parent 9dc6d920ce
commit e51656e070
20 changed files with 795 additions and 133 deletions

8
3rdparty/qt5.cmake vendored
View File

@ -2,17 +2,17 @@ add_library(3rdparty_qt5 INTERFACE)
set(QT_MIN_VER 5.15.2)
find_package(Qt5 ${QT_MIN_VER} CONFIG COMPONENTS Widgets Concurrent Multimedia)
find_package(Qt5 ${QT_MIN_VER} CONFIG COMPONENTS Widgets Concurrent Multimedia MultimediaWidgets)
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)
target_link_libraries(3rdparty_qt5 INTERFACE Qt5::Widgets Qt5::WinExtras Qt5::Concurrent Qt5::Multimedia Qt5::MultimediaWidgets)
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)
target_link_libraries(3rdparty_qt5 INTERFACE Qt5::Widgets Qt5::DBus Qt5::Concurrent Qt5::Multimedia Qt5::MultimediaWidgets)
target_compile_definitions(3rdparty_qt5 INTERFACE -DHAVE_QTDBUS)
else()
target_link_libraries(3rdparty_qt5 INTERFACE Qt5::Widgets Qt5::Concurrent Qt5::Multimedia)
target_link_libraries(3rdparty_qt5 INTERFACE Qt5::Widgets Qt5::Concurrent Qt5::Multimedia Qt5::MultimediaWidgets)
endif()
target_include_directories(3rdparty_qt5 INTERFACE ${Qt5Gui_PRIVATE_INCLUDE_DIRS})
endif()

View File

@ -359,6 +359,7 @@ target_link_libraries(rpcs3_emu
# Io
target_sources(rpcs3_emu PRIVATE
Io/camera_config.cpp
Io/interception.cpp
Io/KeyboardHandler.cpp
Io/pad_config.cpp

View File

@ -0,0 +1,125 @@
#include "stdafx.h"
#include "camera_config.h"
#include <charconv>
LOG_CHANNEL(camera_log, "Camera");
cfg_camera g_cfg_camera;
cfg_camera::cfg_camera()
#ifdef _WIN32
: path(fs::get_config_dir() + "config/camera.yml")
#else
: path(fs::get_config_dir() + "camera.yml")
#endif
{
}
bool cfg_camera::load()
{
camera_log.notice("Loading camera config from '%s'", path);
if (fs::file cfg_file{ path, fs::read })
{
return from_string(cfg_file.to_string());
}
from_default();
return false;
}
void cfg_camera::save() const
{
camera_log.notice("Saving camera config to '%s'", path);
fs::pending_file cfg_file(path);
if (!cfg_file.file || (cfg_file.file.write(to_string()), !cfg_file.commit()))
{
camera_log.error("Failed to save camera config to '%s'", path);
}
}
cfg_camera::camera_setting cfg_camera::get_camera_setting(const std::string& camera, bool& success)
{
camera_setting setting;
const std::string value = cameras.get_value(camera);
success = !value.empty();
if (success)
{
setting.from_string(cameras.get_value(camera));
}
return setting;
}
void cfg_camera::set_camera_setting(const std::string& camera, const camera_setting& setting)
{
if (camera.empty())
{
camera_log.error("String '%s' cannot be used as camera key.", camera);
return;
}
cameras.set_value(camera, setting.to_string());
}
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);
}
void cfg_camera::camera_setting::from_string(const std::string& text)
{
if (text.empty())
{
return;
}
const std::vector<std::string> list = fmt::split(text, { "," });
if (list.size() != member_count)
{
camera_log.error("String '%s' cannot be interpreted as camera_setting.", text);
return;
}
const auto to_integer = [](const std::string& str, int& out) -> bool
{
auto [ptr, ec] = std::from_chars(str.c_str(), str.c_str() + str.size(), out);
if (ec != std::errc{})
{
camera_log.error("String '%s' cannot be interpreted as integer.", str);
return false;
}
return true;
};
const auto to_double = [](const std::string& str, double& out) -> bool
{
char* end{};
out = std::strtod(str.c_str(), &end);
if (end != str.c_str() + str.size())
{
camera_log.error("String '%s' cannot be interpreted as double.", str);
return false;
}
return true;
};
if (!to_integer(list.at(0), width) ||
!to_integer(list.at(1), height) ||
!to_double(list.at(2), min_fps) ||
!to_double(list.at(3), max_fps) ||
!to_integer(list.at(4), format) ||
!to_integer(list.at(5), pixel_aspect_width) ||
!to_integer(list.at(6), pixel_aspect_height))
{
width = 0;
height = 0;
min_fps = 0;
max_fps = 0;
format = 0;
pixel_aspect_width = 0;
pixel_aspect_height = 0;
}
}

View File

@ -0,0 +1,34 @@
#pragma once
#include "Utilities/Config.h"
struct cfg_camera final : cfg::node
{
cfg_camera();
bool load();
void save() const;
struct camera_setting
{
int width = 0;
int height = 0;
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;
std::string to_string() const;
void from_string(const std::string& text);
};
camera_setting get_camera_setting(const std::string& camera, bool& success);
void set_camera_setting(const std::string& camera, const camera_setting& setting);
const std::string path;
cfg::map_entry cameras{ this, "Cameras" }; // <camera>: <width>,<height>,<min_fps>,<max_fps>,<format>,<pixel_aspect_width>,<pixel_aspect_height>
};
extern cfg_camera g_cfg_camera;

View File

@ -96,11 +96,9 @@ void cfg_profile::save() const
{
input_log.notice("Saving pad profile config to '%s'", path);
if (auto cfg_file = fs::file(path, fs::rewrite))
{
cfg_file.write(to_string());
}
else
fs::pending_file cfg_file(path);
if (!cfg_file.file || (cfg_file.file.write(to_string()), !cfg_file.commit()))
{
input_log.error("Failed to save pad profile config to '%s'", path);
}

View File

@ -25,12 +25,9 @@ void cfg_rpcn::save() const
}
#endif
fs::file cfg_file(cfg_rpcn::get_path(), fs::rewrite);
if (cfg_file)
{
cfg_file.write(to_string());
}
else
fs::pending_file cfg_file(cfg_rpcn::get_path());
if (!cfg_file.file || (cfg_file.file.write(to_string()), !cfg_file.commit()))
{
rpcn_log.error("Could not save config: %s", cfg_rpcn::get_path());
}

View File

@ -63,6 +63,7 @@
<ClCompile Include="Emu\cache_utils.cpp" />
<ClCompile Include="Emu\Cell\Modules\libfs_utility_init.cpp" />
<ClCompile Include="Emu\Cell\Modules\sys_crashdump.cpp" />
<ClCompile Include="Emu\Io\camera_config.cpp" />
<ClCompile Include="Emu\Io\Turntable.cpp" />
<ClCompile Include="Emu\Io\GHLtar.cpp" />
<ClCompile Include="Emu\Io\Buzz.cpp" />
@ -445,6 +446,7 @@
<ClInclude Include="Emu\Cell\Modules\cellStorage.h" />
<ClInclude Include="Emu\Cell\Modules\libfs_utility_init.h" />
<ClInclude Include="Emu\Cell\Modules\sys_crashdump.h" />
<ClInclude Include="Emu\Io\camera_config.h" />
<ClInclude Include="Emu\Io\camera_handler_base.h" />
<ClInclude Include="Emu\Io\Null\null_camera_handler.h" />
<ClInclude Include="Emu\Io\Turntable.h" />

View File

@ -1009,6 +1009,9 @@
<ClCompile Include="Emu\vfs_config.cpp">
<Filter>Emu</Filter>
</ClCompile>
<ClCompile Include="Emu\Io\camera_config.cpp">
<Filter>Emu\Io</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="Crypto\aes.h">
@ -2005,6 +2008,9 @@
<ClInclude Include="Emu\Io\Null\null_camera_handler.h">
<Filter>Emu\Io\Null</Filter>
</ClInclude>
<ClInclude Include="Emu\Io\camera_config.h">
<Filter>Emu\Io</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<None Include="Emu\RSX\Common\Interpreter\FragmentInterpreter.glsl">

View File

@ -71,7 +71,7 @@
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<AdditionalIncludeDirectories>..\3rdparty\flatbuffers\include;..\3rdparty\wolfssl\wolfssl;..\3rdparty\curl\curl\include;..\3rdparty\libusb\libusb\libusb;$(VULKAN_SDK)\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;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>..\3rdparty\flatbuffers\include;..\3rdparty\wolfssl\wolfssl;..\3rdparty\curl\curl\include;..\3rdparty\libusb\libusb\libusb;$(VULKAN_SDK)\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;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalOptions>-Zc:strictStrings -Zc:throwingNew- -w34100 -w34189 -w44996 -w44456 -w44457 -w44458 %(AdditionalOptions)</AdditionalOptions>
<AssemblerListingLocation>release\</AssemblerListingLocation>
<BrowseInformation>false</BrowseInformation>
@ -79,7 +79,7 @@
<DisableSpecificWarnings>4577;4467;%(DisableSpecificWarnings)</DisableSpecificWarnings>
<ObjectFileName>$(IntDir)</ObjectFileName>
<Optimization>MaxSpeed</Optimization>
<PreprocessorDefinitions>_WINDOWS;UNICODE;WIN32;WIN64;WITH_DISCORD_RPC;QT_NO_DEBUG;QT_WIDGETS_LIB;QT_GUI_LIB;QT_CORE_LIB;NDEBUG;QT_WINEXTRAS_LIB;QT_CONCURRENT_LIB;QT_MULTIMEDIA_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>_WINDOWS;UNICODE;WIN32;WIN64;WITH_DISCORD_RPC;QT_NO_DEBUG;QT_WIDGETS_LIB;QT_GUI_LIB;QT_CORE_LIB;NDEBUG;QT_WINEXTRAS_LIB;QT_CONCURRENT_LIB;QT_MULTIMEDIA_LIB;QT_MULTIMEDIAWIDGETS_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessToFile>false</PreprocessToFile>
<ProgramDataBaseFileName>$(IntDir)vc$(PlatformToolsetVersion).pdb</ProgramDataBaseFileName>
<RuntimeTypeInfo>true</RuntimeTypeInfo>
@ -88,7 +88,7 @@
<WarningLevel>Level3</WarningLevel>
</ClCompile>
<Link>
<AdditionalDependencies>Ole32.lib;gdi32.lib;..\hidapi.lib;..\libusb-1.0.lib;winmm.lib;OpenAL.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;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>Ole32.lib;gdi32.lib;..\hidapi.lib;..\libusb-1.0.lib;winmm.lib;OpenAL.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;%(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>
@ -122,7 +122,7 @@
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<AdditionalIncludeDirectories>..\3rdparty\flatbuffers\include;..\3rdparty\wolfssl\wolfssl;..\3rdparty\curl\curl\include;..\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;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>..\3rdparty\flatbuffers\include;..\3rdparty\wolfssl\wolfssl;..\3rdparty\curl\curl\include;..\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;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalOptions>-Zc:strictStrings -Zc:throwingNew- -w34100 -w34189 -w44996 -w44456 -w44457 -w44458 %(AdditionalOptions)</AdditionalOptions>
<AssemblerListingLocation>debug\</AssemblerListingLocation>
<BrowseInformation>false</BrowseInformation>
@ -130,7 +130,7 @@
<DisableSpecificWarnings>4577;4467;%(DisableSpecificWarnings)</DisableSpecificWarnings>
<ObjectFileName>$(IntDir)</ObjectFileName>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>_WINDOWS;UNICODE;WIN32;WIN64;QT_WIDGETS_LIB;QT_GUI_LIB;QT_CORE_LIB;QT_WINEXTRAS_LIB;QT_CONCURRENT_LIB;QT_MULTIMEDIA_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>_WINDOWS;UNICODE;WIN32;WIN64;QT_WIDGETS_LIB;QT_GUI_LIB;QT_CORE_LIB;QT_WINEXTRAS_LIB;QT_CONCURRENT_LIB;QT_MULTIMEDIA_LIB;QT_MULTIMEDIAWIDGETS_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessToFile>false</PreprocessToFile>
<RuntimeTypeInfo>true</RuntimeTypeInfo>
<SuppressStartupBanner>true</SuppressStartupBanner>
@ -139,7 +139,7 @@
<ProgramDataBaseFileName>$(IntDir)vc$(PlatformToolsetVersion).pdb</ProgramDataBaseFileName>
</ClCompile>
<Link>
<AdditionalDependencies>Ole32.lib;gdi32.lib;..\hidapi.lib;..\libusb-1.0.lib;winmm.lib;OpenAL.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;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>Ole32.lib;gdi32.lib;..\hidapi.lib;..\libusb-1.0.lib;winmm.lib;OpenAL.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;%(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>
@ -198,6 +198,9 @@
<ClCompile Include="QTGeneratedFiles\Debug\moc_call_stack_list.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="QTGeneratedFiles\Debug\moc_camera_settings_dialog.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="QTGeneratedFiles\Debug\moc_cg_disasm_window.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
</ClCompile>
@ -399,6 +402,9 @@
<ClCompile Include="QTGeneratedFiles\Release\moc_call_stack_list.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="QTGeneratedFiles\Release\moc_camera_settings_dialog.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="QTGeneratedFiles\Release\moc_cg_disasm_window.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
</ClCompile>
@ -580,6 +586,7 @@
<ClCompile Include="rpcs3qt\breakpoint_handler.cpp" />
<ClCompile Include="rpcs3qt\breakpoint_list.cpp" />
<ClCompile Include="rpcs3qt\call_stack_list.cpp" />
<ClCompile Include="rpcs3qt\camera_settings_dialog.cpp" />
<ClCompile Include="rpcs3qt\cheat_manager.cpp" />
<ClCompile Include="rpcs3qt\config_adapter.cpp" />
<ClCompile Include="rpcs3qt\curl_handle.cpp" />
@ -831,6 +838,7 @@
<ClInclude Include="Input\pad_thread.h" />
<ClInclude Include="Input\product_info.h" />
<ClInclude Include="QTGeneratedFiles\ui_about_dialog.h" />
<ClInclude Include="QTGeneratedFiles\ui_camera_settings_dialog.h" />
<ClInclude Include="QTGeneratedFiles\ui_main_window.h" />
<ClInclude Include="QTGeneratedFiles\ui_pad_led_settings_dialog.h" />
<ClInclude Include="QTGeneratedFiles\ui_pad_settings_dialog.h" />
@ -889,6 +897,16 @@
<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>
<CustomBuild Include="rpcs3qt\camera_settings_dialog.h">
<AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(QTDIR)\bin\moc.exe;%(FullPath)</AdditionalInputs>
<Message Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Moc%27ing %(Identity)...</Message>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">.\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp</Outputs>
<Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">"$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -D_WINDOWS -DUNICODE -DWIN32 -DWIN64 -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CORE_LIB -DQT_WINEXTRAS_LIB -DQT_CONCURRENT_LIB -DQT_MULTIMEDIA_LIB -D%(PreprocessorDefinitions) "-I.\..\3rdparty\flatbuffers\include" "-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.\debug" "-I$(QTDIR)\mkspecs\win32-msvc2015" "-I.\QTGeneratedFiles\$(ConfigurationName)" "-I.\QTGeneratedFiles" "-I$(QTDIR)\include\QtWinExtras" "-I$(QTDIR)\include\QtConcurrent" "-I$(QTDIR)\include\QtMultimedia"</Command>
<AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(QTDIR)\bin\moc.exe;%(FullPath)</AdditionalInputs>
<Message Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Moc%27ing %(Identity)...</Message>
<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 -DQT_MULTIMEDIA_LIB -D%(PreprocessorDefinitions) "-I.\..\3rdparty\flatbuffers\include" "-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" "-I$(QTDIR)\include\QtMultimedia"</Command>
</CustomBuild>
<ClInclude Include="rpcs3qt\category.h" />
<ClInclude Include="rpcs3qt\config_adapter.h" />
<ClInclude Include="rpcs3qt\curl_handle.h" />
@ -1481,6 +1499,16 @@
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">.\QTGeneratedFiles\ui_%(Filename).h;%(Outputs)</Outputs>
<Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">"$(QTDIR)\bin\uic.exe" -o ".\QTGeneratedFiles\ui_%(Filename).h" "%(FullPath)"</Command>
</CustomBuild>
<CustomBuild Include="rpcs3qt\camera_settings_dialog.ui">
<AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(QTDIR)\bin\uic.exe;%(AdditionalInputs)</AdditionalInputs>
<Message Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Uic%27ing %(Identity)...</Message>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">.\QTGeneratedFiles\ui_%(Filename).h;%(Outputs)</Outputs>
<Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">"$(QTDIR)\bin\uic.exe" -o ".\QTGeneratedFiles\ui_%(Filename).h" "%(FullPath)"</Command>
<AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(QTDIR)\bin\uic.exe;%(AdditionalInputs)</AdditionalInputs>
<Message Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Uic%27ing %(Identity)...</Message>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">.\QTGeneratedFiles\ui_%(Filename).h;%(Outputs)</Outputs>
<Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">"$(QTDIR)\bin\uic.exe" -o ".\QTGeneratedFiles\ui_%(Filename).h" "%(FullPath)"</Command>
</CustomBuild>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets" />

View File

@ -795,6 +795,15 @@
<ClCompile Include="QTGeneratedFiles\Release\moc_qt_camera_error_handler.cpp">
<Filter>Generated Files\Release</Filter>
</ClCompile>
<ClCompile Include="rpcs3qt\camera_settings_dialog.cpp">
<Filter>Gui\settings</Filter>
</ClCompile>
<ClCompile Include="QTGeneratedFiles\Debug\moc_camera_settings_dialog.cpp">
<Filter>Generated Files\Debug</Filter>
</ClCompile>
<ClCompile Include="QTGeneratedFiles\Release\moc_camera_settings_dialog.cpp">
<Filter>Generated Files\Release</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="Input\ds4_pad_handler.h">
@ -935,6 +944,9 @@
<ClInclude Include="rpcs3qt\qt_camera_handler.h">
<Filter>Io\camera</Filter>
</ClInclude>
<ClInclude Include="QTGeneratedFiles\ui_camera_settings_dialog.h">
<Filter>Generated Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<CustomBuild Include="debug\moc_predefs.h.cbt">
@ -1165,6 +1177,12 @@
<CustomBuild Include="rpcs3qt\qt_camera_error_handler.h">
<Filter>Io\camera</Filter>
</CustomBuild>
<CustomBuild Include="rpcs3qt\camera_settings_dialog.ui">
<Filter>Form Files</Filter>
</CustomBuild>
<CustomBuild Include="rpcs3qt\camera_settings_dialog.h">
<Filter>Gui\settings</Filter>
</CustomBuild>
</ItemGroup>
<ItemGroup>
<Image Include="rpcs3.ico" />

View File

@ -7,6 +7,7 @@ set(SRC_FILES
breakpoint_handler.cpp
breakpoint_list.cpp
call_stack_list.cpp
camera_settings_dialog.cpp
cg_disasm_window.cpp
cheat_manager.cpp
config_adapter.cpp
@ -83,6 +84,7 @@ set(SRC_FILES
set(UI_FILES
about_dialog.ui
camera_settings_dialog.ui
main_window.ui
pad_led_settings_dialog.ui
pad_settings_dialog.ui

View File

@ -0,0 +1,285 @@
#include "stdafx.h"
#include "camera_settings_dialog.h"
#include "ui_camera_settings_dialog.h"
#include "Emu/Io/camera_config.h"
#include <QCameraInfo>
#include <QMessageBox>
#include <QPushButton>
LOG_CHANNEL(camera_log, "Camera");
template <>
void fmt_class_string<QVideoFrame::PixelFormat>::format(std::string& out, u64 arg)
{
format_enum(out, arg, [](QVideoFrame::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";
}
return unknown;
});
}
Q_DECLARE_METATYPE(QCameraInfo);
camera_settings_dialog::camera_settings_dialog(QWidget* parent)
: QDialog(parent)
, ui(new Ui::camera_settings_dialog)
{
ui->setupUi(this);
load_config();
for (const QCameraInfo& camera_info : QCameraInfo::availableCameras())
{
if (camera_info.isNull()) continue;
ui->combo_camera->addItem(camera_info.description(), QVariant::fromValue(camera_info));
}
connect(ui->combo_camera, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &camera_settings_dialog::handle_camera_change);
connect(ui->combo_settings, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &camera_settings_dialog::handle_settings_change);
connect(ui->buttonBox, &QDialogButtonBox::clicked, [this](QAbstractButton* button)
{
if (button == ui->buttonBox->button(QDialogButtonBox::Save))
{
save_config();
accept();
}
else if (button == ui->buttonBox->button(QDialogButtonBox::Apply))
{
save_config();
}
});
if (ui->combo_camera->count() == 0)
{
ui->combo_camera->setEnabled(false);
ui->combo_settings->setEnabled(false);
ui->buttonBox->button(QDialogButtonBox::Save)->setEnabled(false);
ui->buttonBox->button(QDialogButtonBox::Apply)->setEnabled(false);
}
else
{
// TODO: show camera ID somewhere
ui->combo_camera->setCurrentIndex(0);
}
}
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>())
{
ui->combo_settings->clear();
return;
}
const QCameraInfo camera_info = ui->combo_camera->itemData(index).value<QCameraInfo>();
if (camera_info.isNull())
{
ui->combo_settings->clear();
return;
}
m_camera.reset(new QCamera(camera_info));
m_camera->setViewfinder(ui->viewfinder);
if (!m_camera->isAvailable())
{
ui->combo_settings->clear();
QMessageBox::warning(this, tr("Camera not available"), tr("The selected camera is not available.\nIt might be blocked by another application."));
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
{
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.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)
{
if (setting.isNull()) continue;
const QString description = tr("%0x%1, %2-%3 FPS, Format=%4, PixelAspectRatio=%5x%6")
.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());
ui->combo_settings->addItem(description, QVariant::fromValue(setting));
}
ui->combo_settings->blockSignals(false);
if (ui->combo_settings->count() == 0)
{
ui->combo_settings->setEnabled(false);
}
else
{
// Load selected settings from config file
int index = 0;
bool success = false;
const std::string key = camera_info.deviceName().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>();
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())
{
index = i;
break;
}
}
}
ui->combo_settings->setCurrentIndex(std::max<int>(0, index));
ui->combo_settings->setEnabled(true);
// Update config to match user interface outcome
const QCameraViewfinderSettings setting = ui->combo_settings->currentData().value<QCameraViewfinderSettings>();
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.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);
}
}
void camera_settings_dialog::handle_settings_change(int index)
{
if (!m_camera)
{
return;
}
if (!m_camera->isAvailable())
{
QMessageBox::warning(this, tr("Camera not available"), tr("The selected camera is not available.\nIt might be blocked by another application."));
return;
}
if (index >= 0 && ui->combo_settings->itemData(index).canConvert<QCameraViewfinderSettings>() && ui->combo_camera->currentData().canConvert<QCameraInfo>())
{
const QCameraViewfinderSettings setting = ui->combo_settings->itemData(index).value<QCameraViewfinderSettings>();
if (!setting.isNull())
{
m_camera->setViewfinderSettings(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.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);
}
m_camera->start();
}
void camera_settings_dialog::load_config()
{
if (!g_cfg_camera.load())
{
camera_log.notice("Could not load camera config. Using defaults.");
}
}
void camera_settings_dialog::save_config()
{
g_cfg_camera.save();
}

View File

@ -0,0 +1,29 @@
#pragma once
#include <QCamera>
#include <QDialog>
namespace Ui
{
class camera_settings_dialog;
}
class camera_settings_dialog : public QDialog
{
Q_OBJECT
public:
camera_settings_dialog(QWidget* parent = nullptr);
virtual ~camera_settings_dialog();
private Q_SLOTS:
void handle_camera_change(int index);
void handle_settings_change(int index);
private:
void load_config();
void save_config();
Ui::camera_settings_dialog* ui;
std::shared_ptr<QCamera> m_camera;
};

View File

@ -0,0 +1,130 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>camera_settings_dialog</class>
<widget class="QDialog" name="camera_settings_dialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>356</width>
<height>380</height>
</rect>
</property>
<property name="windowTitle">
<string>Camera Settings</string>
</property>
<layout class="QVBoxLayout" name="mainLayout" stretch="0,1,0">
<item>
<layout class="QHBoxLayout" name="settingsLayout" stretch="1,2">
<item>
<widget class="QGroupBox" name="gbCamera">
<property name="title">
<string>Camera</string>
</property>
<layout class="QVBoxLayout" name="camera_layout">
<item>
<widget class="QComboBox" name="combo_camera">
<property name="placeholderText">
<string>No cameras found</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="gbSettings">
<property name="title">
<string>Settings</string>
</property>
<layout class="QVBoxLayout" name="settings_layout">
<item>
<widget class="QComboBox" name="combo_settings">
<property name="placeholderText">
<string>No settings found</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QGroupBox" name="gbPreview">
<property name="title">
<string>Preview</string>
</property>
<layout class="QVBoxLayout" name="preview_layout">
<item>
<widget class="QCameraViewfinder" name="viewfinder" native="true">
<property name="minimumSize">
<size>
<width>64</width>
<height>48</height>
</size>
</property>
<property name="autoFillBackground">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Apply|QDialogButtonBox::Cancel|QDialogButtonBox::Save</set>
</property>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>QCameraViewfinder</class>
<extends>QWidget</extends>
<header>qcameraviewfinder.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>camera_settings_dialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>camera_settings_dialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@ -28,6 +28,7 @@
#include "category.h"
#include "gui_settings.h"
#include "input_dialog.h"
#include "camera_settings_dialog.h"
#include <thread>
#include <charconv>
@ -1652,6 +1653,7 @@ void main_window::OnEmuStop()
#endif
}
ui->actionManage_Users->setEnabled(true);
ui->confCamerasAct->setEnabled(true);
if (std::exchange(m_sys_menu_opened, false))
{
@ -1691,6 +1693,7 @@ void main_window::OnEmuReady() const
EnableMenus(true);
ui->actionManage_Users->setEnabled(false);
ui->confCamerasAct->setEnabled(false);
}
void main_window::EnableMenus(bool enabled) const
@ -2116,6 +2119,12 @@ void main_window::CreateConnects()
connect(ui->confPadsAct, &QAction::triggered, this, open_pad_settings);
connect(ui->confCamerasAct, &QAction::triggered, this, [this]()
{
camera_settings_dialog dlg(this);
dlg.exec();
});
connect(ui->confRPCNAct, &QAction::triggered, this, [this]()
{
rpcn_settings_dialog dlg(this);

View File

@ -220,6 +220,7 @@
<addaction name="confGPUAct"/>
<addaction name="separator"/>
<addaction name="confPadsAct"/>
<addaction name="confCamerasAct"/>
<addaction name="confAudioAct"/>
<addaction name="confIOAct"/>
<addaction name="confSystemAct"/>
@ -1175,6 +1176,11 @@
<string>Patch Creator</string>
</property>
</action>
<action name="confCamerasAct">
<property name="text">
<string>Cameras</string>
</property>
</action>
</widget>
<layoutdefault spacing="6" margin="11"/>
<resources>

View File

@ -1,6 +1,7 @@
#include "stdafx.h"
#include "qt_camera_handler.h"
#include "Emu/system_config.h"
#include "Emu/Io/camera_config.h"
#include <QMediaService>
#include <QCameraInfo>
@ -14,6 +15,8 @@ qt_camera_handler::qt_camera_handler() : camera_handler_base()
{
camera_log.success("Found camera: name=%s, description=%s", cameraInfo.deviceName().toStdString(), cameraInfo.description().toStdString());
}
g_cfg_camera.load();
}
qt_camera_handler::~qt_camera_handler()
@ -218,14 +221,15 @@ void qt_camera_handler::set_format(s32 format, u32 bytesize)
m_format = format;
m_bytesize = bytesize;
update_camera_settings();
if (m_surface)
{
m_surface->set_format(m_format, m_bytesize);
}
}
void qt_camera_handler::set_frame_rate(u32 frame_rate)
{
m_frame_rate = frame_rate;
update_camera_settings();
}
void qt_camera_handler::set_resolution(u32 width, u32 height)
@ -233,14 +237,20 @@ void qt_camera_handler::set_resolution(u32 width, u32 height)
m_width = width;
m_height = height;
update_camera_settings();
if (m_surface)
{
m_surface->set_resolution(m_width, m_height);
}
}
void qt_camera_handler::set_mirrored(bool mirrored)
{
m_mirrored = mirrored;
update_camera_settings();
if (m_surface)
{
m_surface->set_mirrored(m_mirrored);
}
}
u64 qt_camera_handler::frame_number() const
@ -298,73 +308,55 @@ 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)
{
// List all available settings in a cascading fashion and choose the proper value if possible.
// After each step, the next one will only list the settings that are compatible with the prior ones.
QCameraViewfinderSettings settings;
// Load selected settings from config file
bool success = false;
cfg_camera::camera_setting cfg_setting = g_cfg_camera.get_camera_setting(m_camera_id, success);
// Set resolution if possible.
const QList<QSize> resolutions = m_camera->supportedViewfinderResolutions(settings);
if (resolutions.isEmpty())
if (success)
{
camera_log.warning("No resolution available for the view finder settings: frame_rate=%f, width=%d, height=%d, pixel_format=%d",
settings.maximumFrameRate(), settings.resolution().width(), settings.resolution().height(), static_cast<int>(settings.pixelFormat()));
}
for (const QSize& resolution : resolutions)
{
if (static_cast<int>(m_width) == resolution.width() && static_cast<int>(m_height) == resolution.height())
{
settings.setResolution(resolution.width(), resolution.height());
break;
}
}
camera_log.notice("Found config entry for camera \"%s\"", m_camera_id);
// Set frame rate if possible.
const QList<QCamera::FrameRateRange> frame_rate_ranges = m_camera->supportedViewfinderFrameRateRanges(settings);
if (frame_rate_ranges.isEmpty())
{
camera_log.warning("No frame rate available for the view finder settings: frame_rate=%f, width=%d, height=%d, pixel_format=%d",
settings.maximumFrameRate(), settings.resolution().width(), settings.resolution().height(), static_cast<int>(settings.pixelFormat()));
}
for (const QCamera::FrameRateRange& frame_rate : frame_rate_ranges)
{
// Some cameras do not have an exact match, so let's approximate.
if (static_cast<qreal>(m_frame_rate) >= (frame_rate.maximumFrameRate - 0.5) && static_cast<qreal>(m_frame_rate) <= (frame_rate.maximumFrameRate + 0.5))
{
// Lock the frame rate by setting the min and max to the same value.
settings.setMinimumFrameRate(m_frame_rate);
settings.setMaximumFrameRate(m_frame_rate);
break;
}
}
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);
// Set pixel format if possible. (Unused for now, because formats differ between Qt and cell)
const QList<QVideoFrame::PixelFormat> pixel_formats = m_camera->supportedViewfinderPixelFormats(settings);
if (pixel_formats.isEmpty())
// 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))
{
camera_log.warning("No pixel format available for the view finder settings: frame_rate=%f, width=%d, height=%d, pixel_format=%d",
settings.maximumFrameRate(), settings.resolution().width(), settings.resolution().height(), static_cast<int>(settings.pixelFormat()));
}
for (const QVideoFrame::PixelFormat& pixel_format : pixel_formats)
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 (pixel_format == QVideoFrame::Format_RGB32)
{
settings.setPixelFormat(pixel_format);
break;
}
}
if (m_camera->supportedViewfinderSettings(settings).isEmpty())
{
camera_log.warning("No camera setting available for the view finder settings: frame_rate=%f, width=%d, height=%d, pixel_format=%d",
settings.maximumFrameRate(), settings.resolution().width(), settings.resolution().height(), static_cast<int>(settings.pixelFormat()));
}
else
{
camera_log.notice("Setting view finder settings: frame_rate=%f, width=%d, height=%d, pixel_format=%d",
settings.maximumFrameRate(), settings.resolution().width(), settings.resolution().height(), static_cast<int>(settings.pixelFormat()));
// Apply settings.
m_camera->setViewfinderSettings(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);
success = true;
break;
}
}
if (!success)
{
camera_log.warning("No matching camera setting available for the camera config: max_fps=%f, width=%d, height=%d, format=%d",
cfg_setting.max_fps, cfg_setting.width, cfg_setting.height, cfg_setting.format);
}
}
if (!success)
{
camera_log.notice("Using default view finder settings");
}
}

View File

@ -93,7 +93,7 @@ bool qt_camera_video_surface::present(const QVideoFrame& frame)
if (image.isNull())
{
camera_log.warning("Image is invalid: pixel_format=%d, format=%d", static_cast<int>(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>(QVideoFrame::imageFormatFromPixelFormat(tmp.pixelFormat())));
}
else
{

View File

@ -978,11 +978,11 @@ settings_dialog::settings_dialog(std::shared_ptr<gui_settings> gui_settings, std
cfg_log.error("The selected camera was not found. Selecting default camera as fallback.");
ui->cameraIdBox->setCurrentIndex(ui->cameraIdBox->findData(qstr(default_camera)));
}
connect(ui->cameraIdBox, QOverload<int>::of(&QComboBox::currentIndexChanged), [this](int index)
connect(ui->cameraIdBox, QOverload<int>::of(&QComboBox::currentIndexChanged), this, [this](int index)
{
if (index >= 0) m_emu_settings->SetSetting(emu_settings_type::CameraID, ui->cameraIdBox->itemData(index).toString().toStdString());
});
connect(m_emu_settings.get(), &emu_settings::RestoreDefaultsSignal, [this, default_camera]()
connect(m_emu_settings.get(), &emu_settings::RestoreDefaultsSignal, this, [this, default_camera]()
{
m_emu_settings->SetSetting(emu_settings_type::CameraID, default_camera);
ui->cameraIdBox->setCurrentIndex(ui->cameraIdBox->findData(qstr(default_camera)));

View File

@ -1415,14 +1415,14 @@
<layout class="QVBoxLayout" name="inputTab_layout">
<item>
<layout class="QGridLayout" name="ioGridLayout">
<item row="0" column="0">
<widget class="QGroupBox" name="gb_keyboard_handler">
<item row="1" column="2">
<widget class="QGroupBox" name="gb_turntable_emulated">
<property name="title">
<string>Keyboard Handler</string>
<string>DJ Hero emulated turntable</string>
</property>
<layout class="QVBoxLayout" name="gb_keyboard_handler_layout">
<layout class="QVBoxLayout" name="gb_turntable_emulated_layout">
<item>
<widget class="QComboBox" name="keyboardHandlerBox"/>
<widget class="QComboBox" name="turntableBox"/>
</item>
</layout>
</widget>
@ -1439,30 +1439,6 @@
</layout>
</widget>
</item>
<item row="0" column="2">
<widget class="QGroupBox" name="gb_buzz_emulated">
<property name="title">
<string>Buzz! emulated controller</string>
</property>
<layout class="QVBoxLayout" name="gb_buzz_emulated_layout">
<item>
<widget class="QComboBox" name="buzzBox"/>
</item>
</layout>
</widget>
</item>
<item row="1" column="2">
<widget class="QGroupBox" name="gb_turntable_emulated">
<property name="title">
<string>DJ Hero emulated turntable</string>
</property>
<layout class="QVBoxLayout" name="gb_turntable_emulated_layout">
<item>
<widget class="QComboBox" name="turntableBox"/>
</item>
</layout>
</widget>
</item>
<item row="0" column="1">
<widget class="QGroupBox" name="gb_camera_type">
<property name="title">
@ -1475,7 +1451,43 @@
</layout>
</widget>
</item>
<item row="1" column="1">
<item row="2" column="0">
<widget class="QGroupBox" name="gb_move_handler">
<property name="title">
<string>Move Handler</string>
</property>
<layout class="QVBoxLayout" name="gb_move_handler_layout">
<item>
<widget class="QComboBox" name="moveBox"/>
</item>
</layout>
</widget>
</item>
<item row="0" column="0">
<widget class="QGroupBox" name="gb_keyboard_handler">
<property name="title">
<string>Keyboard Handler</string>
</property>
<layout class="QVBoxLayout" name="gb_keyboard_handler_layout">
<item>
<widget class="QComboBox" name="keyboardHandlerBox"/>
</item>
</layout>
</widget>
</item>
<item row="0" column="2">
<widget class="QGroupBox" name="gb_buzz_emulated">
<property name="title">
<string>Buzz! emulated controller</string>
</property>
<layout class="QVBoxLayout" name="gb_buzz_emulated_layout">
<item>
<widget class="QComboBox" name="buzzBox"/>
</item>
</layout>
</widget>
</item>
<item row="3" column="1">
<widget class="QGroupBox" name="gb_camera_flip">
<property name="title">
<string>Camera Flip</string>
@ -1487,7 +1499,7 @@
</layout>
</widget>
</item>
<item row="2" column="1">
<item row="1" column="1">
<widget class="QGroupBox" name="gb_camera_setting">
<property name="title">
<string>Camera Handler</string>
@ -1511,19 +1523,7 @@
</layout>
</widget>
</item>
<item row="2" column="0">
<widget class="QGroupBox" name="gb_move_handler">
<property name="title">
<string>Move Handler</string>
</property>
<layout class="QVBoxLayout" name="gb_move_handler_layout">
<item>
<widget class="QComboBox" name="moveBox"/>
</item>
</layout>
</widget>
</item>
<item row="2" column="2">
<item row="2" column="1">
<widget class="QGroupBox" name="gb_camera_id">
<property name="title">
<string>Camera</string>