Path: blob/master/src/duckstation-qt/capturesettingswidget.cpp
7197 views
// SPDX-FileCopyrightText: 2019-2026 Connor McLaughlin <[email protected]>1// SPDX-License-Identifier: CC-BY-NC-ND-4.023#include "capturesettingswidget.h"4#include "qtutils.h"5#include "settingswindow.h"6#include "settingwidgetbinder.h"78#include "util/media_capture.h"910#include "common/error.h"1112#include "moc_capturesettingswidget.cpp"1314CaptureSettingsWidget::CaptureSettingsWidget(SettingsWindow* dialog, QWidget* parent)15: QWidget(parent), m_dialog(dialog)16{17SettingsInterface* sif = dialog->getSettingsInterface();1819m_ui.setupUi(this);2021SettingWidgetBinder::BindWidgetToEnumSetting(22sif, m_ui.screenshotSize, "Display", "ScreenshotMode", &Settings::ParseDisplayScreenshotMode,23&Settings::GetDisplayScreenshotModeName, &Settings::GetDisplayScreenshotModeDisplayName,24Settings::DEFAULT_DISPLAY_SCREENSHOT_MODE, DisplayScreenshotMode::Count);25SettingWidgetBinder::BindWidgetToEnumSetting(26sif, m_ui.screenshotFormat, "Display", "ScreenshotFormat", &Settings::ParseDisplayScreenshotFormat,27&Settings::GetDisplayScreenshotFormatName, &Settings::GetDisplayScreenshotFormatDisplayName,28Settings::DEFAULT_DISPLAY_SCREENSHOT_FORMAT, DisplayScreenshotFormat::Count);29SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.screenshotQuality, "Display", "ScreenshotQuality",30Settings::DEFAULT_DISPLAY_SCREENSHOT_QUALITY);3132SettingWidgetBinder::BindWidgetToEnumSetting(sif, m_ui.mediaCaptureBackend, "MediaCapture", "Backend",33&MediaCapture::ParseBackendName, &MediaCapture::GetBackendName,34&MediaCapture::GetBackendDisplayName,35Settings::DEFAULT_MEDIA_CAPTURE_BACKEND, MediaCaptureBackend::MaxCount);36SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.enableVideoCapture, "MediaCapture", "VideoCapture", true);37SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.videoCaptureWidth, "MediaCapture", "VideoWidth",38Settings::DEFAULT_MEDIA_CAPTURE_VIDEO_WIDTH);39SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.videoCaptureHeight, "MediaCapture", "VideoHeight",40Settings::DEFAULT_MEDIA_CAPTURE_VIDEO_HEIGHT);41SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.videoCaptureResolutionAuto, "MediaCapture", "VideoAutoSize",42false);43SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.videoCaptureBitrate, "MediaCapture", "VideoBitrate",44Settings::DEFAULT_MEDIA_CAPTURE_VIDEO_BITRATE);45SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.enableVideoCaptureArguments, "MediaCapture",46"VideoCodecUseArgs", false);47SettingWidgetBinder::BindWidgetToStringSetting(sif, m_ui.videoCaptureArguments, "MediaCapture", "AudioCodecArgs");48SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.enableAudioCapture, "MediaCapture", "AudioCapture", true);49SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.audioCaptureBitrate, "MediaCapture", "AudioBitrate",50Settings::DEFAULT_MEDIA_CAPTURE_AUDIO_BITRATE);51SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.enableVideoCaptureArguments, "MediaCapture",52"VideoCodecUseArgs", false);53SettingWidgetBinder::BindWidgetToStringSetting(sif, m_ui.audioCaptureArguments, "MediaCapture", "AudioCodecArgs");5455connect(m_ui.mediaCaptureBackend, &QComboBox::currentIndexChanged, this,56&CaptureSettingsWidget::onMediaCaptureBackendChanged);57connect(m_ui.enableVideoCapture, &QCheckBox::checkStateChanged, this,58&CaptureSettingsWidget::onMediaCaptureVideoEnabledChanged);59connect(m_ui.videoCaptureResolutionAuto, &QCheckBox::checkStateChanged, this,60&CaptureSettingsWidget::onMediaCaptureVideoAutoResolutionChanged);61connect(m_ui.enableAudioCapture, &QCheckBox::checkStateChanged, this,62&CaptureSettingsWidget::onMediaCaptureAudioEnabledChanged);6364// Init all dependent options.65onMediaCaptureBackendChanged();66onMediaCaptureAudioEnabledChanged();67onMediaCaptureVideoEnabledChanged();6869dialog->registerWidgetHelp(m_ui.screenshotSize, tr("Screenshot Size"), tr("Screen Resolution"),70tr("Determines the resolution at which screenshots will be saved. Internal resolutions "71"preserve more detail at the cost of file size."));72dialog->registerWidgetHelp(73m_ui.screenshotFormat, tr("Screenshot Format"), tr("PNG"),74tr("Selects the format which will be used to save screenshots. JPEG produces smaller files, but loses detail."));75dialog->registerWidgetHelp(m_ui.screenshotQuality, tr("Screenshot Quality"),76QStringLiteral("%1%").arg(Settings::DEFAULT_DISPLAY_SCREENSHOT_QUALITY),77tr("Selects the quality at which screenshots will be compressed. Higher values preserve "78"more detail for JPEG, and reduce file size for PNG."));79dialog->registerWidgetHelp(80m_ui.mediaCaptureBackend, tr("Backend"),81QString::fromUtf8(MediaCapture::GetBackendDisplayName(Settings::DEFAULT_MEDIA_CAPTURE_BACKEND)),82tr("Selects the framework that is used to encode video/audio."));83dialog->registerWidgetHelp(m_ui.captureContainer, tr("Container"), tr("MP4"),84tr("Determines the file format used to contain the captured audio/video."));85dialog->registerWidgetHelp(m_ui.enableVideoCapture, tr("Capture Video"), tr("Checked"),86tr("Captures video to the chosen file when media capture is started. If unchecked, the "87"file will only contain audio."));88dialog->registerWidgetHelp(89m_ui.videoCaptureCodec, tr("Video Codec"), tr("Default"),90tr("Selects which Video Codec to be used for media capture. <b>If unsure, leave it on default.<b>"));91dialog->registerWidgetHelp(m_ui.videoCaptureBitrate, tr("Video Bitrate"), tr("6000 kbps"),92tr("Sets the video bitrate to be used. Larger bitrate generally yields better video "93"quality at the cost of larger resulting file size."));94dialog->registerWidgetHelp(95m_ui.videoCaptureResolutionAuto, tr("Automatic Resolution"), tr("Unchecked"),96tr("When checked, the video capture resolution will follows the internal resolution of the running "97"game. <b>Be careful when using this setting especially when you are upscaling, as higher internal "98"resolutions (above 4x) can cause system slowdown.</b>"));99dialog->registerWidgetHelp(m_ui.enableVideoCaptureArguments, tr("Enable Extra Video Arguments"), tr("Unchecked"),100tr("Allows you to pass arguments to the selected video codec."));101dialog->registerWidgetHelp(102m_ui.videoCaptureArguments, tr("Extra Video Arguments"), tr("Empty"),103tr("Parameters passed to the selected video codec.<br><b>You must use '=' to separate key from value and ':' to "104"separate two pairs from each other.</b><br>For example: \"crf = 21 : preset = veryfast\""));105dialog->registerWidgetHelp(m_ui.enableAudioCapture, tr("Capture Audio"), tr("Checked"),106tr("Captures audio to the chosen file when media capture is started. If unchecked, the "107"file will only contain video."));108dialog->registerWidgetHelp(109m_ui.audioCaptureCodec, tr("Audio Codec"), tr("Default"),110tr("Selects which Audio Codec to be used for media capture. <b>If unsure, leave it on default.<b>"));111dialog->registerWidgetHelp(m_ui.audioCaptureBitrate, tr("Audio Bitrate"), tr("128 kbps"),112tr("Sets the audio bitrate to be used."));113dialog->registerWidgetHelp(m_ui.enableAudioCaptureArguments, tr("Enable Extra Audio Arguments"), tr("Unchecked"),114tr("Allows you to pass arguments to the selected audio codec."));115dialog->registerWidgetHelp(116m_ui.audioCaptureArguments, tr("Extra Audio Arguments"), tr("Empty"),117tr("Parameters passed to the selected audio codec.<br><b>You must use '=' to separate key from value and ':' to "118"separate two pairs from each other.</b><br>For example: \"compression_level = 4 : joint_stereo = 1\""));119}120121CaptureSettingsWidget::~CaptureSettingsWidget() = default;122123void CaptureSettingsWidget::onMediaCaptureBackendChanged()124{125SettingsInterface* const sif = m_dialog->getSettingsInterface();126const MediaCaptureBackend backend =127MediaCapture::ParseBackendName(128m_dialog129->getEffectiveStringValue("MediaCapture", "Backend",130MediaCapture::GetBackendName(Settings::DEFAULT_MEDIA_CAPTURE_BACKEND))131.c_str())132.value_or(Settings::DEFAULT_MEDIA_CAPTURE_BACKEND);133134{135SettingWidgetBinder::DisconnectWidget(m_ui.captureContainer);136m_ui.captureContainer->clear();137138for (const auto& [name, display_name] : MediaCapture::GetContainerList(backend))139{140const QString qname = QString::fromStdString(name);141m_ui.captureContainer->addItem(tr("%1 (%2)").arg(QString::fromStdString(display_name)).arg(qname), qname);142}143144SettingWidgetBinder::BindWidgetToStringSetting(sif, m_ui.captureContainer, "MediaCapture", "Container",145Settings::DEFAULT_MEDIA_CAPTURE_CONTAINER);146connect(m_ui.captureContainer, &QComboBox::currentIndexChanged, this,147&CaptureSettingsWidget::onMediaCaptureContainerChanged);148}149150onMediaCaptureContainerChanged();151}152153void CaptureSettingsWidget::onMediaCaptureContainerChanged()154{155SettingsInterface* const sif = m_dialog->getSettingsInterface();156const MediaCaptureBackend backend =157MediaCapture::ParseBackendName(158m_dialog159->getEffectiveStringValue("MediaCapture", "Backend",160MediaCapture::GetBackendName(Settings::DEFAULT_MEDIA_CAPTURE_BACKEND))161.c_str())162.value_or(Settings::DEFAULT_MEDIA_CAPTURE_BACKEND);163const std::string container = m_dialog->getEffectiveStringValue("MediaCapture", "Container", "mp4");164165{166SettingWidgetBinder::DisconnectWidget(m_ui.videoCaptureCodec);167m_ui.videoCaptureCodec->clear();168m_ui.videoCaptureCodec->addItem(tr("Default"), QVariant(QString()));169170for (const auto& [name, display_name] : MediaCapture::GetVideoCodecList(backend, container.c_str()))171{172const QString qname = QString::fromStdString(name);173m_ui.videoCaptureCodec->addItem(tr("%1 (%2)").arg(QString::fromStdString(display_name)).arg(qname), qname);174}175176SettingWidgetBinder::BindWidgetToStringSetting(sif, m_ui.videoCaptureCodec, "MediaCapture", "VideoCodec");177}178179{180SettingWidgetBinder::DisconnectWidget(m_ui.audioCaptureCodec);181m_ui.audioCaptureCodec->clear();182m_ui.audioCaptureCodec->addItem(tr("Default"), QVariant(QString()));183184for (const auto& [name, display_name] : MediaCapture::GetAudioCodecList(backend, container.c_str()))185{186const QString qname = QString::fromStdString(name);187m_ui.audioCaptureCodec->addItem(tr("%1 (%2)").arg(QString::fromStdString(display_name)).arg(qname), qname);188}189190SettingWidgetBinder::BindWidgetToStringSetting(sif, m_ui.audioCaptureCodec, "MediaCapture", "AudioCodec");191}192}193194void CaptureSettingsWidget::onMediaCaptureVideoEnabledChanged()195{196const bool enabled = m_dialog->getEffectiveBoolValue("MediaCapture", "VideoCapture", true);197m_ui.videoCaptureCodecLabel->setEnabled(enabled);198m_ui.videoCaptureCodec->setEnabled(enabled);199m_ui.videoCaptureBitrateLabel->setEnabled(enabled);200m_ui.videoCaptureBitrate->setEnabled(enabled);201m_ui.videoCaptureResolutionLabel->setEnabled(enabled);202m_ui.videoCaptureResolutionAuto->setEnabled(enabled);203m_ui.enableVideoCaptureArguments->setEnabled(enabled);204m_ui.videoCaptureArguments->setEnabled(enabled);205onMediaCaptureVideoAutoResolutionChanged();206}207208void CaptureSettingsWidget::onMediaCaptureVideoAutoResolutionChanged()209{210const bool enabled = m_dialog->getEffectiveBoolValue("MediaCapture", "VideoCapture", true);211const bool auto_enabled = m_dialog->getEffectiveBoolValue("MediaCapture", "VideoAutoSize", false);212m_ui.videoCaptureWidth->setEnabled(enabled && !auto_enabled);213m_ui.xLabel->setEnabled(enabled && !auto_enabled);214m_ui.videoCaptureHeight->setEnabled(enabled && !auto_enabled);215}216217void CaptureSettingsWidget::onMediaCaptureAudioEnabledChanged()218{219const bool enabled = m_dialog->getEffectiveBoolValue("MediaCapture", "AudioCapture", true);220m_ui.audioCaptureCodecLabel->setEnabled(enabled);221m_ui.audioCaptureCodec->setEnabled(enabled);222m_ui.audioCaptureBitrateLabel->setEnabled(enabled);223m_ui.audioCaptureBitrate->setEnabled(enabled);224m_ui.enableAudioCaptureArguments->setEnabled(enabled);225m_ui.audioCaptureArguments->setEnabled(enabled);226}227228229