Qt: Implement FIFO Player
This commit is contained in:
parent
aa8bf71333
commit
474b1c2d5c
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
@ -56,7 +57,7 @@ extern bool IsPlayingBackFifologWithBrokenEFBCopies;
|
||||||
class FifoPlayer
|
class FifoPlayer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
typedef void (*CallbackFunc)(void);
|
using CallbackFunc = std::function<void()>;
|
||||||
|
|
||||||
~FifoPlayer();
|
~FifoPlayer();
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
@ -13,7 +14,7 @@
|
||||||
class FifoRecorder
|
class FifoRecorder
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
typedef void (*CallbackFunc)(void);
|
using CallbackFunc = std::function<void()>;
|
||||||
|
|
||||||
FifoRecorder();
|
FifoRecorder();
|
||||||
|
|
||||||
|
@ -56,7 +57,7 @@ private:
|
||||||
bool m_WasRecording = false;
|
bool m_WasRecording = false;
|
||||||
bool m_RequestedRecordingEnd = false;
|
bool m_RequestedRecordingEnd = false;
|
||||||
s32 m_RecordFramesRemaining = 0;
|
s32 m_RecordFramesRemaining = 0;
|
||||||
CallbackFunc m_FinishedCb = nullptr;
|
CallbackFunc m_FinishedCb;
|
||||||
std::unique_ptr<FifoDataFile> m_File;
|
std::unique_ptr<FifoDataFile> m_File;
|
||||||
|
|
||||||
// Accessed only from video thread
|
// Accessed only from video thread
|
||||||
|
|
|
@ -18,6 +18,7 @@ set(CMAKE_AUTOMOC ON)
|
||||||
|
|
||||||
set(SRCS
|
set(SRCS
|
||||||
AboutDialog.cpp
|
AboutDialog.cpp
|
||||||
|
FIFOPlayerWindow.cpp
|
||||||
HotkeyScheduler.cpp
|
HotkeyScheduler.cpp
|
||||||
Host.cpp
|
Host.cpp
|
||||||
InDevelopmentWarning.cpp
|
InDevelopmentWarning.cpp
|
||||||
|
|
|
@ -83,6 +83,7 @@
|
||||||
<QtMoc Include="Config\InfoWidget.h" />
|
<QtMoc Include="Config\InfoWidget.h" />
|
||||||
<QtMoc Include="Config\PropertiesDialog.h" />
|
<QtMoc Include="Config\PropertiesDialog.h" />
|
||||||
<QtMoc Include="Config\SettingsWindow.h" />
|
<QtMoc Include="Config\SettingsWindow.h" />
|
||||||
|
<QtMoc Include="FIFOPlayerWindow.h" />
|
||||||
<QtMoc Include="GameList\GameFile.h" />
|
<QtMoc Include="GameList\GameFile.h" />
|
||||||
<QtMoc Include="GameList\GameList.h" />
|
<QtMoc Include="GameList\GameList.h" />
|
||||||
<QtMoc Include="GameList\GameListModel.h" />
|
<QtMoc Include="GameList\GameListModel.h" />
|
||||||
|
@ -118,6 +119,7 @@
|
||||||
<ClCompile Include="$(QtMocOutPrefix)CheatWarningWidget.cpp" />
|
<ClCompile Include="$(QtMocOutPrefix)CheatWarningWidget.cpp" />
|
||||||
<ClCompile Include="$(QtMocOutPrefix)ControllersWindow.cpp" />
|
<ClCompile Include="$(QtMocOutPrefix)ControllersWindow.cpp" />
|
||||||
<ClCompile Include="$(QtMocOutPrefix)EnhancementsWidget.cpp" />
|
<ClCompile Include="$(QtMocOutPrefix)EnhancementsWidget.cpp" />
|
||||||
|
<ClCompile Include="$(QtMocOutPrefix)FIFOPlayerWindow.cpp" />
|
||||||
<ClCompile Include="$(QtMocOutPrefix)FilesystemWidget.cpp" />
|
<ClCompile Include="$(QtMocOutPrefix)FilesystemWidget.cpp" />
|
||||||
<ClCompile Include="$(QtMocOutPrefix)WindowActivationEventFilter.cpp" />
|
<ClCompile Include="$(QtMocOutPrefix)WindowActivationEventFilter.cpp" />
|
||||||
<ClCompile Include="$(QtMocOutPrefix)GameList.cpp" />
|
<ClCompile Include="$(QtMocOutPrefix)GameList.cpp" />
|
||||||
|
@ -198,6 +200,7 @@
|
||||||
<ClCompile Include="Config\LogWidget.cpp" />
|
<ClCompile Include="Config\LogWidget.cpp" />
|
||||||
<ClCompile Include="Config\PropertiesDialog.cpp" />
|
<ClCompile Include="Config\PropertiesDialog.cpp" />
|
||||||
<ClCompile Include="Config\SettingsWindow.cpp" />
|
<ClCompile Include="Config\SettingsWindow.cpp" />
|
||||||
|
<ClCompile Include="FIFOPlayerWindow.cpp" />
|
||||||
<ClCompile Include="GameList\GameFile.cpp" />
|
<ClCompile Include="GameList\GameFile.cpp" />
|
||||||
<ClCompile Include="GameList\GameFileCache.cpp" />
|
<ClCompile Include="GameList\GameFileCache.cpp" />
|
||||||
<ClCompile Include="GameList\GameList.cpp" />
|
<ClCompile Include="GameList\GameList.cpp" />
|
||||||
|
|
|
@ -0,0 +1,342 @@
|
||||||
|
// Copyright 2017 Dolphin Emulator Project
|
||||||
|
// Licensed under GPLv2+
|
||||||
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
#include "DolphinQt2/FIFOPlayerWindow.h"
|
||||||
|
|
||||||
|
#include <QCheckBox>
|
||||||
|
#include <QDialogButtonBox>
|
||||||
|
#include <QFileDialog>
|
||||||
|
#include <QGroupBox>
|
||||||
|
#include <QHBoxLayout>
|
||||||
|
#include <QLabel>
|
||||||
|
#include <QMessageBox>
|
||||||
|
#include <QPushButton>
|
||||||
|
#include <QSpinBox>
|
||||||
|
#include <QVBoxLayout>
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
#include "Core/Core.h"
|
||||||
|
#include "Core/FifoPlayer/FifoDataFile.h"
|
||||||
|
#include "Core/FifoPlayer/FifoPlaybackAnalyzer.h"
|
||||||
|
#include "Core/FifoPlayer/FifoPlayer.h"
|
||||||
|
#include "Core/FifoPlayer/FifoRecorder.h"
|
||||||
|
|
||||||
|
#include "DolphinQt2/QtUtils/QueueOnObject.h"
|
||||||
|
#include "DolphinQt2/Settings.h"
|
||||||
|
|
||||||
|
FIFOPlayerWindow::FIFOPlayerWindow(QWidget* parent) : QDialog(parent)
|
||||||
|
{
|
||||||
|
setWindowTitle(tr("FIFO Player"));
|
||||||
|
|
||||||
|
CreateWidgets();
|
||||||
|
ConnectWidgets();
|
||||||
|
|
||||||
|
UpdateInfo();
|
||||||
|
|
||||||
|
UpdateControls();
|
||||||
|
|
||||||
|
FifoPlayer::GetInstance().SetFileLoadedCallback(
|
||||||
|
[this] { QueueOnObject(this, &FIFOPlayerWindow::OnFIFOLoaded); });
|
||||||
|
FifoPlayer::GetInstance().SetFrameWrittenCallback(
|
||||||
|
[this] { QueueOnObject(this, &FIFOPlayerWindow::OnFIFOLoaded); });
|
||||||
|
|
||||||
|
connect(&Settings::Instance(), &Settings::EmulationStateChanged, this, [this](Core::State state) {
|
||||||
|
if (state == Core::State::Running)
|
||||||
|
OnEmulationStarted();
|
||||||
|
else if (state == Core::State::Uninitialized)
|
||||||
|
OnEmulationStopped();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
FIFOPlayerWindow::~FIFOPlayerWindow()
|
||||||
|
{
|
||||||
|
FifoPlayer::GetInstance().SetFileLoadedCallback({});
|
||||||
|
FifoPlayer::GetInstance().SetFrameWrittenCallback({});
|
||||||
|
}
|
||||||
|
|
||||||
|
void FIFOPlayerWindow::CreateWidgets()
|
||||||
|
{
|
||||||
|
auto* layout = new QVBoxLayout;
|
||||||
|
|
||||||
|
// Info
|
||||||
|
auto* info_group = new QGroupBox(tr("File Info"));
|
||||||
|
auto* info_layout = new QHBoxLayout;
|
||||||
|
|
||||||
|
m_info_label = new QLabel;
|
||||||
|
info_layout->addWidget(m_info_label);
|
||||||
|
info_group->setLayout(info_layout);
|
||||||
|
|
||||||
|
m_info_label->setFixedHeight(QFontMetrics(font()).lineSpacing() * 3);
|
||||||
|
|
||||||
|
// Object Range
|
||||||
|
auto* object_range_group = new QGroupBox(tr("Object Range"));
|
||||||
|
auto* object_range_layout = new QHBoxLayout;
|
||||||
|
|
||||||
|
m_object_range_from = new QSpinBox;
|
||||||
|
m_object_range_from_label = new QLabel(tr("From:"));
|
||||||
|
m_object_range_to = new QSpinBox;
|
||||||
|
m_object_range_to_label = new QLabel(tr("To:"));
|
||||||
|
|
||||||
|
object_range_layout->addWidget(m_object_range_from_label);
|
||||||
|
object_range_layout->addWidget(m_object_range_from);
|
||||||
|
object_range_layout->addWidget(m_object_range_to_label);
|
||||||
|
object_range_layout->addWidget(m_object_range_to);
|
||||||
|
object_range_group->setLayout(object_range_layout);
|
||||||
|
|
||||||
|
// Frame Range
|
||||||
|
auto* frame_range_group = new QGroupBox(tr("Frame Range"));
|
||||||
|
auto* frame_range_layout = new QHBoxLayout;
|
||||||
|
|
||||||
|
m_frame_range_from = new QSpinBox;
|
||||||
|
m_frame_range_from_label = new QLabel(tr("From:"));
|
||||||
|
m_frame_range_to = new QSpinBox;
|
||||||
|
m_frame_range_to_label = new QLabel(tr("To:"));
|
||||||
|
|
||||||
|
frame_range_layout->addWidget(m_frame_range_from_label);
|
||||||
|
frame_range_layout->addWidget(m_frame_range_from);
|
||||||
|
frame_range_layout->addWidget(m_frame_range_to_label);
|
||||||
|
frame_range_layout->addWidget(m_frame_range_to);
|
||||||
|
frame_range_group->setLayout(frame_range_layout);
|
||||||
|
|
||||||
|
// Playback Options
|
||||||
|
auto* playback_group = new QGroupBox(tr("Playback Options"));
|
||||||
|
auto* playback_layout = new QGridLayout;
|
||||||
|
m_early_memory_updates = new QCheckBox(tr("Early Memory Updates"));
|
||||||
|
|
||||||
|
playback_layout->addWidget(object_range_group, 0, 0);
|
||||||
|
playback_layout->addWidget(frame_range_group, 0, 1);
|
||||||
|
playback_layout->addWidget(m_early_memory_updates, 1, 0, 1, -1);
|
||||||
|
playback_group->setLayout(playback_layout);
|
||||||
|
|
||||||
|
// Recording Options
|
||||||
|
auto* recording_group = new QGroupBox(tr("Recording Options"));
|
||||||
|
auto* recording_layout = new QHBoxLayout;
|
||||||
|
m_frame_record_count = new QSpinBox;
|
||||||
|
m_frame_record_count_label = new QLabel(tr("Frames to Record:"));
|
||||||
|
|
||||||
|
m_frame_record_count->setMinimum(1);
|
||||||
|
m_frame_record_count->setMaximum(3600);
|
||||||
|
m_frame_record_count->setValue(3);
|
||||||
|
|
||||||
|
recording_layout->addWidget(m_frame_record_count_label);
|
||||||
|
recording_layout->addWidget(m_frame_record_count);
|
||||||
|
recording_group->setLayout(recording_layout);
|
||||||
|
|
||||||
|
m_button_box = new QDialogButtonBox(QDialogButtonBox::Close);
|
||||||
|
|
||||||
|
// Action Buttons
|
||||||
|
m_load = m_button_box->addButton(tr("Load..."), QDialogButtonBox::ActionRole);
|
||||||
|
m_save = m_button_box->addButton(tr("Save..."), QDialogButtonBox::ActionRole);
|
||||||
|
m_record = m_button_box->addButton(tr("Record"), QDialogButtonBox::ActionRole);
|
||||||
|
m_stop = m_button_box->addButton(tr("Stop"), QDialogButtonBox::ActionRole);
|
||||||
|
|
||||||
|
layout->addWidget(info_group);
|
||||||
|
layout->addWidget(playback_group);
|
||||||
|
layout->addWidget(recording_group);
|
||||||
|
layout->addWidget(m_button_box);
|
||||||
|
|
||||||
|
setLayout(layout);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FIFOPlayerWindow::ConnectWidgets()
|
||||||
|
{
|
||||||
|
connect(m_load, &QPushButton::pressed, this, &FIFOPlayerWindow::LoadRecording);
|
||||||
|
connect(m_save, &QPushButton::pressed, this, &FIFOPlayerWindow::SaveRecording);
|
||||||
|
connect(m_record, &QPushButton::pressed, this, &FIFOPlayerWindow::StartRecording);
|
||||||
|
connect(m_stop, &QPushButton::pressed, this, &FIFOPlayerWindow::StopRecording);
|
||||||
|
connect(m_button_box, &QDialogButtonBox::rejected, this, &FIFOPlayerWindow::reject);
|
||||||
|
connect(m_early_memory_updates, &QCheckBox::toggled, this,
|
||||||
|
&FIFOPlayerWindow::OnEarlyMemoryUpdatesChanged);
|
||||||
|
connect(m_frame_range_from, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), this,
|
||||||
|
&FIFOPlayerWindow::OnLimitsChanged);
|
||||||
|
connect(m_frame_range_to, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), this,
|
||||||
|
&FIFOPlayerWindow::OnLimitsChanged);
|
||||||
|
|
||||||
|
connect(m_object_range_from, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), this,
|
||||||
|
&FIFOPlayerWindow::OnLimitsChanged);
|
||||||
|
connect(m_object_range_to, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), this,
|
||||||
|
&FIFOPlayerWindow::OnLimitsChanged);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FIFOPlayerWindow::LoadRecording()
|
||||||
|
{
|
||||||
|
QString path = QFileDialog::getOpenFileName(this, tr("Open FIFO log"), QString(),
|
||||||
|
tr("Dolphin FIFO Log (*.dff)"));
|
||||||
|
|
||||||
|
if (path.isEmpty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
emit LoadFIFORequested(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FIFOPlayerWindow::SaveRecording()
|
||||||
|
{
|
||||||
|
QString path = QFileDialog::getSaveFileName(this, tr("Save FIFO log"), QString(),
|
||||||
|
tr("Dolphin FIFO Log (*.dff)"));
|
||||||
|
|
||||||
|
if (path.isEmpty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
FifoDataFile* file = FifoRecorder::GetInstance().GetRecordedFile();
|
||||||
|
|
||||||
|
bool result = file->Save(path.toStdString());
|
||||||
|
|
||||||
|
if (!result)
|
||||||
|
QMessageBox::critical(this, tr("Error"), tr("Failed to save FIFO log."));
|
||||||
|
}
|
||||||
|
|
||||||
|
void FIFOPlayerWindow::StartRecording()
|
||||||
|
{
|
||||||
|
// Start recording
|
||||||
|
FifoRecorder::GetInstance().StartRecording(m_frame_record_count->value(), [this] {
|
||||||
|
QueueOnObject(this, [this] { OnRecordingDone(); });
|
||||||
|
});
|
||||||
|
|
||||||
|
UpdateControls();
|
||||||
|
|
||||||
|
UpdateInfo();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FIFOPlayerWindow::StopRecording()
|
||||||
|
{
|
||||||
|
FifoRecorder::GetInstance().StopRecording();
|
||||||
|
|
||||||
|
UpdateControls();
|
||||||
|
UpdateInfo();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FIFOPlayerWindow::OnEmulationStarted()
|
||||||
|
{
|
||||||
|
UpdateControls();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FIFOPlayerWindow::OnEmulationStopped()
|
||||||
|
{
|
||||||
|
// If we have previously been recording, stop now.
|
||||||
|
if (FifoRecorder::GetInstance().IsRecording())
|
||||||
|
StopRecording();
|
||||||
|
|
||||||
|
UpdateControls();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FIFOPlayerWindow::OnRecordingDone()
|
||||||
|
{
|
||||||
|
UpdateInfo();
|
||||||
|
UpdateControls();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FIFOPlayerWindow::UpdateInfo()
|
||||||
|
{
|
||||||
|
if (FifoPlayer::GetInstance().IsPlaying())
|
||||||
|
{
|
||||||
|
FifoDataFile* file = FifoPlayer::GetInstance().GetFile();
|
||||||
|
m_info_label->setText(
|
||||||
|
tr("%1 frame(s)\n%2 object(s)\nCurrent Frame: %3")
|
||||||
|
.arg(QString::number(file->GetFrameCount()),
|
||||||
|
QString::number(FifoPlayer::GetInstance().GetFrameObjectCount()),
|
||||||
|
QString::number(FifoPlayer::GetInstance().GetCurrentFrameNum())));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (FifoRecorder::GetInstance().IsRecordingDone())
|
||||||
|
{
|
||||||
|
FifoDataFile* file = FifoRecorder::GetInstance().GetRecordedFile();
|
||||||
|
size_t fifo_bytes = 0;
|
||||||
|
size_t mem_bytes = 0;
|
||||||
|
|
||||||
|
for (u32 i = 0; i < file->GetFrameCount(); ++i)
|
||||||
|
{
|
||||||
|
fifo_bytes += file->GetFrame(i).fifoData.size();
|
||||||
|
for (const auto& mem_update : file->GetFrame(i).memoryUpdates)
|
||||||
|
mem_bytes += mem_update.data.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
m_info_label->setText(tr("%1 FIFO bytes\n%2 memory bytes\n%3 frames")
|
||||||
|
.arg(QString::number(fifo_bytes), QString::number(mem_bytes),
|
||||||
|
QString::number(file->GetFrameCount())));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Core::IsRunning() && FifoRecorder::GetInstance().IsRecording())
|
||||||
|
{
|
||||||
|
m_info_label->setText(tr("Recording..."));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_info_label->setText(tr("No file loaded / recorded."));
|
||||||
|
}
|
||||||
|
|
||||||
|
void FIFOPlayerWindow::OnFIFOLoaded()
|
||||||
|
{
|
||||||
|
FifoDataFile* file = FifoPlayer::GetInstance().GetFile();
|
||||||
|
|
||||||
|
auto object_count = FifoPlayer::GetInstance().GetFrameObjectCount();
|
||||||
|
auto frame_count = file->GetFrameCount();
|
||||||
|
|
||||||
|
m_frame_range_to->setMaximum(frame_count);
|
||||||
|
m_object_range_to->setMaximum(object_count);
|
||||||
|
|
||||||
|
m_frame_range_to->setValue(frame_count);
|
||||||
|
m_object_range_to->setValue(object_count);
|
||||||
|
|
||||||
|
UpdateInfo();
|
||||||
|
UpdateLimits();
|
||||||
|
UpdateControls();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FIFOPlayerWindow::OnEarlyMemoryUpdatesChanged(bool enabled)
|
||||||
|
{
|
||||||
|
FifoPlayer::GetInstance().SetEarlyMemoryUpdates(enabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FIFOPlayerWindow::OnLimitsChanged()
|
||||||
|
{
|
||||||
|
FifoPlayer& player = FifoPlayer::GetInstance();
|
||||||
|
|
||||||
|
player.SetFrameRangeStart(m_frame_range_from->value());
|
||||||
|
player.SetFrameRangeEnd(m_frame_range_to->value());
|
||||||
|
player.SetObjectRangeStart(m_object_range_from->value());
|
||||||
|
player.SetObjectRangeEnd(m_object_range_to->value());
|
||||||
|
UpdateLimits();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FIFOPlayerWindow::UpdateLimits()
|
||||||
|
{
|
||||||
|
m_frame_range_from->setMaximum(std::max(m_frame_range_to->value() - 1, 0));
|
||||||
|
m_frame_range_to->setMinimum(m_frame_range_from->value() + 1);
|
||||||
|
m_object_range_from->setMaximum(std::max(m_object_range_to->value() - 1, 0));
|
||||||
|
m_object_range_to->setMinimum(m_object_range_from->value() + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FIFOPlayerWindow::UpdateControls()
|
||||||
|
{
|
||||||
|
bool running = Core::IsRunning();
|
||||||
|
bool is_recording = FifoRecorder::GetInstance().IsRecording();
|
||||||
|
bool is_playing = FifoPlayer::GetInstance().IsPlaying();
|
||||||
|
|
||||||
|
m_frame_range_from->setEnabled(is_playing);
|
||||||
|
m_frame_range_from_label->setEnabled(is_playing);
|
||||||
|
m_frame_range_to->setEnabled(is_playing);
|
||||||
|
m_frame_range_to_label->setEnabled(is_playing);
|
||||||
|
m_object_range_from->setEnabled(is_playing);
|
||||||
|
m_object_range_from_label->setEnabled(is_playing);
|
||||||
|
m_object_range_to->setEnabled(is_playing);
|
||||||
|
m_object_range_to_label->setEnabled(is_playing);
|
||||||
|
|
||||||
|
m_early_memory_updates->setEnabled(is_playing);
|
||||||
|
|
||||||
|
bool enable_frame_record_count = !is_playing && !is_recording;
|
||||||
|
|
||||||
|
m_frame_record_count_label->setEnabled(enable_frame_record_count);
|
||||||
|
m_frame_record_count->setEnabled(enable_frame_record_count);
|
||||||
|
|
||||||
|
m_load->setEnabled(!running);
|
||||||
|
m_record->setEnabled(running && !is_playing);
|
||||||
|
|
||||||
|
m_stop->setVisible(running && is_recording);
|
||||||
|
m_record->setVisible(!m_stop->isVisible());
|
||||||
|
|
||||||
|
m_save->setEnabled(FifoRecorder::GetInstance().IsRecordingDone());
|
||||||
|
}
|
|
@ -0,0 +1,62 @@
|
||||||
|
// Copyright 2017 Dolphin Emulator Project
|
||||||
|
// Licensed under GPLv2+
|
||||||
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QDialog>
|
||||||
|
|
||||||
|
class QCheckBox;
|
||||||
|
class QDialogButtonBox;
|
||||||
|
class QLabel;
|
||||||
|
class QPushButton;
|
||||||
|
class QSpinBox;
|
||||||
|
|
||||||
|
class FIFOPlayerWindow : public QDialog
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit FIFOPlayerWindow(QWidget* parent = nullptr);
|
||||||
|
~FIFOPlayerWindow();
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void LoadFIFORequested(const QString& path);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void CreateWidgets();
|
||||||
|
void ConnectWidgets();
|
||||||
|
|
||||||
|
void LoadRecording();
|
||||||
|
void SaveRecording();
|
||||||
|
void StartRecording();
|
||||||
|
void StopRecording();
|
||||||
|
|
||||||
|
void OnEmulationStarted();
|
||||||
|
void OnEmulationStopped();
|
||||||
|
void OnLimitsChanged();
|
||||||
|
void OnEarlyMemoryUpdatesChanged(bool enabled);
|
||||||
|
void OnRecordingDone();
|
||||||
|
void OnFIFOLoaded();
|
||||||
|
|
||||||
|
void UpdateControls();
|
||||||
|
void UpdateInfo();
|
||||||
|
void UpdateLimits();
|
||||||
|
|
||||||
|
QLabel* m_info_label;
|
||||||
|
QPushButton* m_load;
|
||||||
|
QPushButton* m_save;
|
||||||
|
QPushButton* m_record;
|
||||||
|
QPushButton* m_stop;
|
||||||
|
QSpinBox* m_frame_range_from;
|
||||||
|
QLabel* m_frame_range_from_label;
|
||||||
|
QSpinBox* m_frame_range_to;
|
||||||
|
QLabel* m_frame_range_to_label;
|
||||||
|
QSpinBox* m_frame_record_count;
|
||||||
|
QLabel* m_frame_record_count_label;
|
||||||
|
QSpinBox* m_object_range_from;
|
||||||
|
QLabel* m_object_range_from_label;
|
||||||
|
QSpinBox* m_object_range_to;
|
||||||
|
QLabel* m_object_range_to_label;
|
||||||
|
QCheckBox* m_early_memory_updates;
|
||||||
|
QDialogButtonBox* m_button_box;
|
||||||
|
};
|
|
@ -45,6 +45,7 @@
|
||||||
#include "DolphinQt2/Config/LogWidget.h"
|
#include "DolphinQt2/Config/LogWidget.h"
|
||||||
#include "DolphinQt2/Config/Mapping/MappingWindow.h"
|
#include "DolphinQt2/Config/Mapping/MappingWindow.h"
|
||||||
#include "DolphinQt2/Config/SettingsWindow.h"
|
#include "DolphinQt2/Config/SettingsWindow.h"
|
||||||
|
#include "DolphinQt2/FIFOPlayerWindow.h"
|
||||||
#include "DolphinQt2/Host.h"
|
#include "DolphinQt2/Host.h"
|
||||||
#include "DolphinQt2/HotkeyScheduler.h"
|
#include "DolphinQt2/HotkeyScheduler.h"
|
||||||
#include "DolphinQt2/MainWindow.h"
|
#include "DolphinQt2/MainWindow.h"
|
||||||
|
@ -155,9 +156,15 @@ void MainWindow::CreateComponents()
|
||||||
m_stack = new QStackedWidget(this);
|
m_stack = new QStackedWidget(this);
|
||||||
m_controllers_window = new ControllersWindow(this);
|
m_controllers_window = new ControllersWindow(this);
|
||||||
m_settings_window = new SettingsWindow(this);
|
m_settings_window = new SettingsWindow(this);
|
||||||
|
|
||||||
m_hotkey_window = new MappingWindow(this, MappingWindow::Type::MAPPING_HOTKEYS, 0);
|
m_hotkey_window = new MappingWindow(this, MappingWindow::Type::MAPPING_HOTKEYS, 0);
|
||||||
|
|
||||||
m_log_widget = new LogWidget(this);
|
m_log_widget = new LogWidget(this);
|
||||||
m_log_config_widget = new LogConfigWidget(this);
|
m_log_config_widget = new LogConfigWidget(this);
|
||||||
|
m_fifo_window = new FIFOPlayerWindow(this);
|
||||||
|
|
||||||
|
connect(m_fifo_window, &FIFOPlayerWindow::LoadFIFORequested, this,
|
||||||
|
static_cast<void (MainWindow::*)(const QString&)>(&MainWindow::StartGame));
|
||||||
|
|
||||||
#if defined(HAVE_XRANDR) && HAVE_XRANDR
|
#if defined(HAVE_XRANDR) && HAVE_XRANDR
|
||||||
m_graphics_window = new GraphicsWindow(
|
m_graphics_window = new GraphicsWindow(
|
||||||
|
@ -215,6 +222,7 @@ void MainWindow::ConnectMenuBar()
|
||||||
connect(m_menu_bar, &MenuBar::PerformOnlineUpdate, this, &MainWindow::PerformOnlineUpdate);
|
connect(m_menu_bar, &MenuBar::PerformOnlineUpdate, this, &MainWindow::PerformOnlineUpdate);
|
||||||
connect(m_menu_bar, &MenuBar::BootWiiSystemMenu, this, &MainWindow::BootWiiSystemMenu);
|
connect(m_menu_bar, &MenuBar::BootWiiSystemMenu, this, &MainWindow::BootWiiSystemMenu);
|
||||||
connect(m_menu_bar, &MenuBar::StartNetPlay, this, &MainWindow::ShowNetPlaySetupDialog);
|
connect(m_menu_bar, &MenuBar::StartNetPlay, this, &MainWindow::ShowNetPlaySetupDialog);
|
||||||
|
connect(m_menu_bar, &MenuBar::ShowFIFOPlayer, this, &MainWindow::ShowFIFOPlayer);
|
||||||
|
|
||||||
// Movie
|
// Movie
|
||||||
connect(m_menu_bar, &MenuBar::PlayRecording, this, &MainWindow::OnPlayRecording);
|
connect(m_menu_bar, &MenuBar::PlayRecording, this, &MainWindow::OnPlayRecording);
|
||||||
|
@ -590,6 +598,13 @@ void MainWindow::ShowNetPlaySetupDialog()
|
||||||
m_netplay_setup_dialog->activateWindow();
|
m_netplay_setup_dialog->activateWindow();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MainWindow::ShowFIFOPlayer()
|
||||||
|
{
|
||||||
|
m_fifo_window->show();
|
||||||
|
m_fifo_window->raise();
|
||||||
|
m_fifo_window->activateWindow();
|
||||||
|
}
|
||||||
|
|
||||||
void MainWindow::StateLoad()
|
void MainWindow::StateLoad()
|
||||||
{
|
{
|
||||||
QString path = QFileDialog::getOpenFileName(this, tr("Select a File"), QDir::currentPath(),
|
QString path = QFileDialog::getOpenFileName(this, tr("Select a File"), QDir::currentPath(),
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
#include "DolphinQt2/ToolBar.h"
|
#include "DolphinQt2/ToolBar.h"
|
||||||
|
|
||||||
struct BootParameters;
|
struct BootParameters;
|
||||||
|
class FIFOPlayerWindow;
|
||||||
class HotkeyScheduler;
|
class HotkeyScheduler;
|
||||||
class LogConfigWidget;
|
class LogConfigWidget;
|
||||||
class LogWidget;
|
class LogWidget;
|
||||||
|
@ -98,6 +99,7 @@ private:
|
||||||
void ShowAboutDialog();
|
void ShowAboutDialog();
|
||||||
void ShowHotkeyDialog();
|
void ShowHotkeyDialog();
|
||||||
void ShowNetPlaySetupDialog();
|
void ShowNetPlaySetupDialog();
|
||||||
|
void ShowFIFOPlayer();
|
||||||
|
|
||||||
void NetPlayInit();
|
void NetPlayInit();
|
||||||
bool NetPlayJoin();
|
bool NetPlayJoin();
|
||||||
|
@ -137,4 +139,5 @@ private:
|
||||||
GraphicsWindow* m_graphics_window;
|
GraphicsWindow* m_graphics_window;
|
||||||
LogWidget* m_log_widget;
|
LogWidget* m_log_widget;
|
||||||
LogConfigWidget* m_log_config_widget;
|
LogConfigWidget* m_log_config_widget;
|
||||||
|
FIFOPlayerWindow* m_fifo_window;
|
||||||
};
|
};
|
||||||
|
|
|
@ -116,6 +116,8 @@ void MenuBar::AddToolsMenu()
|
||||||
AddAction(gc_ipl, tr("PAL"), this, [this] { emit BootGameCubeIPL(DiscIO::Region::PAL); });
|
AddAction(gc_ipl, tr("PAL"), this, [this] { emit BootGameCubeIPL(DiscIO::Region::PAL); });
|
||||||
|
|
||||||
AddAction(tools_menu, tr("Start &NetPlay..."), this, &MenuBar::StartNetPlay);
|
AddAction(tools_menu, tr("Start &NetPlay..."), this, &MenuBar::StartNetPlay);
|
||||||
|
AddAction(tools_menu, tr("FIFO Player"), this, &MenuBar::ShowFIFOPlayer);
|
||||||
|
|
||||||
tools_menu->addSeparator();
|
tools_menu->addSeparator();
|
||||||
|
|
||||||
// Label will be set by a NANDRefresh later
|
// Label will be set by a NANDRefresh later
|
||||||
|
|
|
@ -62,6 +62,8 @@ signals:
|
||||||
|
|
||||||
// Tools
|
// Tools
|
||||||
void BootGameCubeIPL(DiscIO::Region region);
|
void BootGameCubeIPL(DiscIO::Region region);
|
||||||
|
void ShowFIFOPlayer();
|
||||||
|
void ShowAboutDialog();
|
||||||
|
|
||||||
// Options
|
// Options
|
||||||
void Configure();
|
void Configure();
|
||||||
|
@ -77,8 +79,6 @@ signals:
|
||||||
void GameListPlatformVisibilityToggled(const QString& row, bool visible);
|
void GameListPlatformVisibilityToggled(const QString& row, bool visible);
|
||||||
void GameListRegionVisibilityToggled(const QString& row, bool visible);
|
void GameListRegionVisibilityToggled(const QString& row, bool visible);
|
||||||
|
|
||||||
void ShowAboutDialog();
|
|
||||||
|
|
||||||
// Movie
|
// Movie
|
||||||
void PlayRecording();
|
void PlayRecording();
|
||||||
void StartRecording();
|
void StartRecording();
|
||||||
|
|
Loading…
Reference in New Issue