citra_qt: Add video dumping UI
QtConcurrent is used to stop the video dumping in another thread.
This commit is contained in:
parent
526d53af99
commit
8202c55cd5
|
@ -326,6 +326,7 @@ void Config::ReadValues() {
|
||||||
UISettings::values.movie_record_path = ReadSetting("movieRecordPath").toString();
|
UISettings::values.movie_record_path = ReadSetting("movieRecordPath").toString();
|
||||||
UISettings::values.movie_playback_path = ReadSetting("moviePlaybackPath").toString();
|
UISettings::values.movie_playback_path = ReadSetting("moviePlaybackPath").toString();
|
||||||
UISettings::values.screenshot_path = ReadSetting("screenshotPath").toString();
|
UISettings::values.screenshot_path = ReadSetting("screenshotPath").toString();
|
||||||
|
UISettings::values.video_dumping_path = ReadSetting("videoDumpingPath").toString();
|
||||||
UISettings::values.game_dir_deprecated = ReadSetting("gameListRootDir", ".").toString();
|
UISettings::values.game_dir_deprecated = ReadSetting("gameListRootDir", ".").toString();
|
||||||
UISettings::values.game_dir_deprecated_deepscan =
|
UISettings::values.game_dir_deprecated_deepscan =
|
||||||
ReadSetting("gameListDeepScan", false).toBool();
|
ReadSetting("gameListDeepScan", false).toBool();
|
||||||
|
@ -594,6 +595,7 @@ void Config::SaveValues() {
|
||||||
WriteSetting("movieRecordPath", UISettings::values.movie_record_path);
|
WriteSetting("movieRecordPath", UISettings::values.movie_record_path);
|
||||||
WriteSetting("moviePlaybackPath", UISettings::values.movie_playback_path);
|
WriteSetting("moviePlaybackPath", UISettings::values.movie_playback_path);
|
||||||
WriteSetting("screenshotPath", UISettings::values.screenshot_path);
|
WriteSetting("screenshotPath", UISettings::values.screenshot_path);
|
||||||
|
WriteSetting("videoDumpingPath", UISettings::values.video_dumping_path);
|
||||||
qt_config->beginWriteArray("gamedirs");
|
qt_config->beginWriteArray("gamedirs");
|
||||||
for (int i = 0; i < UISettings::values.game_dirs.size(); ++i) {
|
for (int i = 0; i < UISettings::values.game_dirs.size(); ++i) {
|
||||||
qt_config->setArrayIndex(i);
|
qt_config->setArrayIndex(i);
|
||||||
|
|
|
@ -57,6 +57,7 @@
|
||||||
#include "common/scm_rev.h"
|
#include "common/scm_rev.h"
|
||||||
#include "common/scope_exit.h"
|
#include "common/scope_exit.h"
|
||||||
#include "core/core.h"
|
#include "core/core.h"
|
||||||
|
#include "core/dumping/backend.h"
|
||||||
#include "core/file_sys/archive_extsavedata.h"
|
#include "core/file_sys/archive_extsavedata.h"
|
||||||
#include "core/file_sys/archive_source_sd_savedata.h"
|
#include "core/file_sys/archive_source_sd_savedata.h"
|
||||||
#include "core/frontend/applets/default_applets.h"
|
#include "core/frontend/applets/default_applets.h"
|
||||||
|
@ -67,6 +68,8 @@
|
||||||
#include "core/movie.h"
|
#include "core/movie.h"
|
||||||
#include "core/settings.h"
|
#include "core/settings.h"
|
||||||
#include "game_list_p.h"
|
#include "game_list_p.h"
|
||||||
|
#include "video_core/renderer_base.h"
|
||||||
|
#include "video_core/video_core.h"
|
||||||
|
|
||||||
#ifdef USE_DISCORD_PRESENCE
|
#ifdef USE_DISCORD_PRESENCE
|
||||||
#include "citra_qt/discord_impl.h"
|
#include "citra_qt/discord_impl.h"
|
||||||
|
@ -601,6 +604,17 @@ void GMainWindow::ConnectMenuEvents() {
|
||||||
connect(ui.action_Capture_Screenshot, &QAction::triggered, this,
|
connect(ui.action_Capture_Screenshot, &QAction::triggered, this,
|
||||||
&GMainWindow::OnCaptureScreenshot);
|
&GMainWindow::OnCaptureScreenshot);
|
||||||
|
|
||||||
|
#ifndef ENABLE_FFMPEG
|
||||||
|
ui.action_Dump_Video->setEnabled(false);
|
||||||
|
#endif
|
||||||
|
connect(ui.action_Dump_Video, &QAction::triggered, [this] {
|
||||||
|
if (ui.action_Dump_Video->isChecked()) {
|
||||||
|
OnStartVideoDumping();
|
||||||
|
} else {
|
||||||
|
OnStopVideoDumping();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// Help
|
// Help
|
||||||
connect(ui.action_Open_Citra_Folder, &QAction::triggered, this,
|
connect(ui.action_Open_Citra_Folder, &QAction::triggered, this,
|
||||||
&GMainWindow::OnOpenCitraFolder);
|
&GMainWindow::OnOpenCitraFolder);
|
||||||
|
@ -862,10 +876,25 @@ void GMainWindow::BootGame(const QString& filename) {
|
||||||
if (ui.action_Fullscreen->isChecked()) {
|
if (ui.action_Fullscreen->isChecked()) {
|
||||||
ShowFullscreen();
|
ShowFullscreen();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (video_dumping_on_start) {
|
||||||
|
Layout::FramebufferLayout layout{
|
||||||
|
Layout::FrameLayoutFromResolutionScale(VideoCore::GetResolutionScaleFactor())};
|
||||||
|
Core::System::GetInstance().VideoDumper().StartDumping(video_dumping_path.toStdString(),
|
||||||
|
"webm", layout);
|
||||||
|
video_dumping_on_start = false;
|
||||||
|
video_dumping_path.clear();
|
||||||
|
}
|
||||||
OnStartGame();
|
OnStartGame();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GMainWindow::ShutdownGame() {
|
void GMainWindow::ShutdownGame() {
|
||||||
|
if (Core::System::GetInstance().VideoDumper().IsDumping()) {
|
||||||
|
game_shutdown_delayed = true;
|
||||||
|
OnStopVideoDumping();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
discord_rpc->Pause();
|
discord_rpc->Pause();
|
||||||
OnStopRecordingPlayback();
|
OnStopRecordingPlayback();
|
||||||
emu_thread->RequestStop();
|
emu_thread->RequestStop();
|
||||||
|
@ -1595,6 +1624,51 @@ void GMainWindow::OnCaptureScreenshot() {
|
||||||
OnStartGame();
|
OnStartGame();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GMainWindow::OnStartVideoDumping() {
|
||||||
|
const QString path = QFileDialog::getSaveFileName(
|
||||||
|
this, tr("Save Video"), UISettings::values.video_dumping_path, tr("WebM Videos (*.webm)"));
|
||||||
|
if (path.isEmpty()) {
|
||||||
|
ui.action_Dump_Video->setChecked(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
UISettings::values.video_dumping_path = QFileInfo(path).path();
|
||||||
|
if (emulation_running) {
|
||||||
|
Layout::FramebufferLayout layout{
|
||||||
|
Layout::FrameLayoutFromResolutionScale(VideoCore::GetResolutionScaleFactor())};
|
||||||
|
Core::System::GetInstance().VideoDumper().StartDumping(path.toStdString(), "webm", layout);
|
||||||
|
} else {
|
||||||
|
video_dumping_on_start = true;
|
||||||
|
video_dumping_path = path;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GMainWindow::OnStopVideoDumping() {
|
||||||
|
ui.action_Dump_Video->setChecked(false);
|
||||||
|
|
||||||
|
if (video_dumping_on_start) {
|
||||||
|
video_dumping_on_start = false;
|
||||||
|
video_dumping_path.clear();
|
||||||
|
} else {
|
||||||
|
const bool was_dumping = Core::System::GetInstance().VideoDumper().IsDumping();
|
||||||
|
if (!was_dumping)
|
||||||
|
return;
|
||||||
|
OnPauseGame();
|
||||||
|
|
||||||
|
auto future =
|
||||||
|
QtConcurrent::run([] { Core::System::GetInstance().VideoDumper().StopDumping(); });
|
||||||
|
auto* future_watcher = new QFutureWatcher<void>(this);
|
||||||
|
connect(future_watcher, &QFutureWatcher<void>::finished, this, [this] {
|
||||||
|
if (game_shutdown_delayed) {
|
||||||
|
game_shutdown_delayed = false;
|
||||||
|
ShutdownGame();
|
||||||
|
} else {
|
||||||
|
OnStartGame();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
future_watcher->setFuture(future);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void GMainWindow::UpdateStatusBar() {
|
void GMainWindow::UpdateStatusBar() {
|
||||||
if (emu_thread == nullptr) {
|
if (emu_thread == nullptr) {
|
||||||
status_bar_update_timer.stop();
|
status_bar_update_timer.stop();
|
||||||
|
|
|
@ -184,6 +184,8 @@ private slots:
|
||||||
void OnPlayMovie();
|
void OnPlayMovie();
|
||||||
void OnStopRecordingPlayback();
|
void OnStopRecordingPlayback();
|
||||||
void OnCaptureScreenshot();
|
void OnCaptureScreenshot();
|
||||||
|
void OnStartVideoDumping();
|
||||||
|
void OnStopVideoDumping();
|
||||||
void OnCoreError(Core::System::ResultStatus, std::string);
|
void OnCoreError(Core::System::ResultStatus, std::string);
|
||||||
/// Called whenever a user selects Help->About Citra
|
/// Called whenever a user selects Help->About Citra
|
||||||
void OnMenuAboutCitra();
|
void OnMenuAboutCitra();
|
||||||
|
@ -230,6 +232,12 @@ private:
|
||||||
bool movie_record_on_start = false;
|
bool movie_record_on_start = false;
|
||||||
QString movie_record_path;
|
QString movie_record_path;
|
||||||
|
|
||||||
|
// Video dumping
|
||||||
|
bool video_dumping_on_start = false;
|
||||||
|
QString video_dumping_path;
|
||||||
|
// Whether game shutdown is delayed due to video dumping
|
||||||
|
bool game_shutdown_delayed = false;
|
||||||
|
|
||||||
// Debugger panes
|
// Debugger panes
|
||||||
ProfilerWidget* profilerWidget;
|
ProfilerWidget* profilerWidget;
|
||||||
MicroProfileDialog* microProfileDialog;
|
MicroProfileDialog* microProfileDialog;
|
||||||
|
|
|
@ -158,6 +158,7 @@
|
||||||
<addaction name="menu_Frame_Advance"/>
|
<addaction name="menu_Frame_Advance"/>
|
||||||
<addaction name="separator"/>
|
<addaction name="separator"/>
|
||||||
<addaction name="action_Capture_Screenshot"/>
|
<addaction name="action_Capture_Screenshot"/>
|
||||||
|
<addaction name="action_Dump_Video"/>
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="QMenu" name="menu_Help">
|
<widget class="QMenu" name="menu_Help">
|
||||||
<property name="title">
|
<property name="title">
|
||||||
|
@ -336,6 +337,14 @@
|
||||||
<string>Capture Screenshot</string>
|
<string>Capture Screenshot</string>
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
|
<action name="action_Dump_Video">
|
||||||
|
<property name="checkable">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Dump Video</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
<action name="action_View_Lobby">
|
<action name="action_View_Lobby">
|
||||||
<property name="enabled">
|
<property name="enabled">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
|
|
|
@ -93,6 +93,7 @@ struct Values {
|
||||||
QString movie_record_path;
|
QString movie_record_path;
|
||||||
QString movie_playback_path;
|
QString movie_playback_path;
|
||||||
QString screenshot_path;
|
QString screenshot_path;
|
||||||
|
QString video_dumping_path;
|
||||||
QString game_dir_deprecated;
|
QString game_dir_deprecated;
|
||||||
bool game_dir_deprecated_deepscan;
|
bool game_dir_deprecated_deepscan;
|
||||||
QList<UISettings::GameDir> game_dirs;
|
QList<UISettings::GameDir> game_dirs;
|
||||||
|
|
Reference in New Issue