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