diff --git a/rpcs3/rpcs3.vcxproj b/rpcs3/rpcs3.vcxproj
index b8f0a02209..95bcae1b89 100644
--- a/rpcs3/rpcs3.vcxproj
+++ b/rpcs3/rpcs3.vcxproj
@@ -328,6 +328,9 @@
true
+
+ true
+
true
@@ -610,6 +613,9 @@
true
+
+ true
+
true
@@ -865,6 +871,7 @@
+
@@ -930,6 +937,16 @@
$(QTDIR)\bin\moc.exe;%(FullPath)
$(QTDIR)\bin\moc.exe;%(FullPath)
+
+ Moc%27ing music_player_dialog.h...
+ .\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp
+ "$(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_CONCURRENT_LIB -D%(PreprocessorDefinitions) "-I.\..\3rdparty\wolfssl\wolfssl" "-I.\..\3rdparty\curl\curl\include" "-I.\..\3rdparty\libusb\libusb\libusb" "-I$(VULKAN_SDK)\Include" "-I$(QTDIR)\include" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtCore" "-I.\debug" "-I.\QTGeneratedFiles\$(ConfigurationName)" "-I.\QTGeneratedFiles" "-I$(QTDIR)\include\QtConcurrent"
+ Moc%27ing music_player_dialog.h...
+ .\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp
+ "$(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_CONCURRENT_LIB -D%(PreprocessorDefinitions) "-I.\..\3rdparty\wolfssl\wolfssl" "-I.\..\3rdparty\curl\curl\include" "-I.\..\3rdparty\libusb\libusb\libusb" "-I$(VULKAN_SDK)\Include" "-I$(QTDIR)\include" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtCore" "-I.\release" "-I.\QTGeneratedFiles\$(ConfigurationName)" "-I.\QTGeneratedFiles" "-I$(QTDIR)\include\QtConcurrent"
+ $(QTDIR)\bin\moc.exe;%(FullPath)
+ $(QTDIR)\bin\moc.exe;%(FullPath)
+
Moc%27ing pad_settings_dialog.h...
.\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp
@@ -1067,6 +1084,7 @@
+
@@ -1937,6 +1955,18 @@
"$(QTDIR)\bin\uic.exe" -o ".\QTGeneratedFiles\ui_%(Filename).h" "%(FullPath)"
+
+
+ $(QTDIR)\bin\uic.exe;%(AdditionalInputs)
+ Uic%27ing %(Identity)...
+ .\QTGeneratedFiles\ui_%(Filename).h;%(Outputs)
+ "$(QTDIR)\bin\uic.exe" -o ".\QTGeneratedFiles\ui_%(Filename).h" "%(FullPath)"
+ $(QTDIR)\bin\uic.exe;%(AdditionalInputs)
+ Uic%27ing %(Identity)...
+ .\QTGeneratedFiles\ui_%(Filename).h;%(Outputs)
+ "$(QTDIR)\bin\uic.exe" -o ".\QTGeneratedFiles\ui_%(Filename).h" "%(FullPath)"
+
+
$(QTDIR)\bin\uic.exe;%(AdditionalInputs)
diff --git a/rpcs3/rpcs3.vcxproj.filters b/rpcs3/rpcs3.vcxproj.filters
index 582e8ac59b..6394ef671d 100644
--- a/rpcs3/rpcs3.vcxproj.filters
+++ b/rpcs3/rpcs3.vcxproj.filters
@@ -273,6 +273,12 @@
Generated Files\Release
+
+ Generated Files\Debug
+
+
+ Generated Files\Release
+
Generated Files\Debug
@@ -435,6 +441,9 @@
Gui
+
+ Gui\misc dialogs
+
Generated Files\Debug
@@ -1202,6 +1211,9 @@
Generated Files
+
+ Generated Files
+
Generated Files
@@ -1423,6 +1435,9 @@
Form Files
+
+ Form Files
+
Form Files
@@ -1480,6 +1495,9 @@
Gui
+
+ Gui\misc dialogs
+
Gui\dev tools
diff --git a/rpcs3/rpcs3qt/CMakeLists.txt b/rpcs3/rpcs3qt/CMakeLists.txt
index 1c8875c372..68fa4b9e76 100644
--- a/rpcs3/rpcs3qt/CMakeLists.txt
+++ b/rpcs3/rpcs3qt/CMakeLists.txt
@@ -57,6 +57,7 @@ add_library(rpcs3_ui STATIC
movie_item.cpp
movie_item_base.cpp
msg_dialog_frame.cpp
+ music_player_dialog.cpp
osk_dialog_frame.cpp
pad_led_settings_dialog.cpp
pad_motion_settings_dialog.cpp
@@ -119,6 +120,7 @@ add_library(rpcs3_ui STATIC
about_dialog.ui
camera_settings_dialog.ui
main_window.ui
+ music_player_dialog.ui
pad_led_settings_dialog.ui
pad_motion_settings_dialog.ui
pad_settings_dialog.ui
diff --git a/rpcs3/rpcs3qt/main_window.cpp b/rpcs3/rpcs3qt/main_window.cpp
index c72d7f4c62..5fd5bac9c6 100644
--- a/rpcs3/rpcs3qt/main_window.cpp
+++ b/rpcs3/rpcs3qt/main_window.cpp
@@ -41,6 +41,7 @@
#include "basic_mouse_settings_dialog.h"
#include "vfs_tool_dialog.h"
#include "welcome_dialog.h"
+#include "music_player_dialog.h"
#include
#include
@@ -3143,6 +3144,12 @@ void main_window::CreateConnects()
dlg->show();
});
+ connect(ui->actionMusic_Player, &QAction::triggered, this, [this]()
+ {
+ music_player_dialog* dlg = new music_player_dialog(this);
+ dlg->open();
+ });
+
connect(ui->showDebuggerAct, &QAction::triggered, this, [this](bool checked)
{
checked ? m_debugger_frame->show() : m_debugger_frame->hide();
diff --git a/rpcs3/rpcs3qt/main_window.ui b/rpcs3/rpcs3qt/main_window.ui
index 9cf59d35a0..845874d00b 100644
--- a/rpcs3/rpcs3qt/main_window.ui
+++ b/rpcs3/rpcs3qt/main_window.ui
@@ -318,6 +318,7 @@
+
@@ -1424,6 +1425,11 @@
Prefer Game Data Icons
+
+
+ Music Player
+
+
diff --git a/rpcs3/rpcs3qt/music_player_dialog.cpp b/rpcs3/rpcs3qt/music_player_dialog.cpp
new file mode 100644
index 0000000000..89c262bb85
--- /dev/null
+++ b/rpcs3/rpcs3qt/music_player_dialog.cpp
@@ -0,0 +1,47 @@
+#include "music_player_dialog.h"
+#include "ui_music_player_dialog.h"
+#include "qt_music_handler.h"
+#include "Emu/System.h"
+#include "Emu/VFS.h"
+
+#include
+#include
+
+music_player_dialog::music_player_dialog(QWidget* parent)
+ : QDialog(parent), ui(new Ui::music_player_dialog)
+{
+ setAttribute(Qt::WA_DeleteOnClose);
+
+ ui->setupUi(this);
+
+ m_handler = std::make_unique();
+
+ connect(ui->fileSelectButton, &QPushButton::clicked, this, [this](){ select_file(); });
+ connect(ui->playButton, &QPushButton::clicked, this, [this](){ m_handler->play(m_file_path); });
+ connect(ui->pauseButton, &QPushButton::clicked, this, [this](){ m_handler->pause(); });
+ connect(ui->stopButton, &QPushButton::clicked, this, [this](){ m_handler->stop(); });
+ connect(ui->forwardButton, &QPushButton::clicked, this, [this](){ m_handler->fast_forward(m_file_path); });
+ connect(ui->reverseButton, &QPushButton::clicked, this, [this](){ m_handler->fast_reverse(m_file_path); });
+ connect(ui->volumeSlider, &QSlider::valueChanged, this, [this](int value){ m_handler->set_volume(std::clamp(value / 100.0f, 0.0f, 1.0f)); });
+}
+
+music_player_dialog::~music_player_dialog()
+{
+}
+
+void music_player_dialog::select_file()
+{
+ // Initialize Emu if not yet initialized (e.g. Emu.Kill() was previously invoked) before using some of the following vfs:: functions (e.g. vfs::get())
+ if (Emu.IsStopped())
+ {
+ Emu.Init();
+ }
+
+ const std::string vfs_dir_path = vfs::get("/dev_hdd0/music");
+ const QString file_path = QFileDialog::getOpenFileName(this, tr("Select audio file"), QString::fromStdString(vfs_dir_path), tr("Audio files (*.mp3;*.wav;*.aac;*.ogg;*.flac;*.m4a;*.alac);;All files (*.*)"));
+
+ if (!file_path.isEmpty())
+ {
+ m_file_path = file_path.toStdString();
+ }
+}
diff --git a/rpcs3/rpcs3qt/music_player_dialog.h b/rpcs3/rpcs3qt/music_player_dialog.h
new file mode 100644
index 0000000000..a3fdc852ed
--- /dev/null
+++ b/rpcs3/rpcs3qt/music_player_dialog.h
@@ -0,0 +1,26 @@
+#pragma once
+
+#include
+
+class music_handler_base;
+
+namespace Ui
+{
+ class music_player_dialog;
+}
+
+class music_player_dialog : public QDialog
+{
+ Q_OBJECT
+
+public:
+ explicit music_player_dialog(QWidget* parent = nullptr);
+ ~music_player_dialog();
+
+private:
+ void select_file();
+
+ std::unique_ptr ui;
+ std::unique_ptr m_handler;
+ std::string m_file_path;
+};
diff --git a/rpcs3/rpcs3qt/music_player_dialog.ui b/rpcs3/rpcs3qt/music_player_dialog.ui
new file mode 100644
index 0000000000..27728cebee
--- /dev/null
+++ b/rpcs3/rpcs3qt/music_player_dialog.ui
@@ -0,0 +1,167 @@
+
+
+ music_player_dialog
+
+
+
+ 0
+ 0
+ 400
+ 300
+
+
+
+ Music Player
+
+
+ -
+
+
-
+
+
+ Qt::Orientation::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+ Select file
+
+
+
+ -
+
+
+ Qt::Orientation::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+
+
+ -
+
+
+ 6
+
+
+ 0
+
+
-
+
+
+
+
+
+
+
+
+
+ -
+
+
+
+
+
+
+
+
+
+ -
+
+
+
+
+
+
+
+
+
+ -
+
+
+
+
+
+
+
+
+
+ -
+
+
+
+
+
+
+
+
+
+ -
+
+
+ Qt::Orientation::Horizontal
+
+
+ QSizePolicy::Policy::MinimumExpanding
+
+
+
+ 0
+ 0
+
+
+
+
+ -
+
+
+ Vol:
+
+
+
+ -
+
+
+ 100
+
+
+ 50
+
+
+ Qt::Orientation::Horizontal
+
+
+
+
+
+ -
+
+
+ Qt::Orientation::Vertical
+
+
+
+ 20
+ 40
+
+
+
+
+
+
+
+
+
diff --git a/rpcs3/rpcs3qt/qt_music_handler.cpp b/rpcs3/rpcs3qt/qt_music_handler.cpp
index 40224d05f2..e2a3b79df8 100644
--- a/rpcs3/rpcs3qt/qt_music_handler.cpp
+++ b/rpcs3/rpcs3qt/qt_music_handler.cpp
@@ -69,11 +69,12 @@ qt_music_handler::qt_music_handler()
music_log.notice("Constructing Qt music handler...");
m_media_player = std::make_unique();
- m_media_player->setAudioOutput(new QAudioOutput());
+ m_media_player->setAudioOutput(new QAudioOutput(m_media_player.get()));
connect(m_media_player.get(), &QMediaPlayer::mediaStatusChanged, this, &qt_music_handler::handle_media_status);
connect(m_media_player.get(), &QMediaPlayer::playbackStateChanged, this, &qt_music_handler::handle_music_state);
connect(m_media_player.get(), &QMediaPlayer::errorOccurred, this, &qt_music_handler::handle_music_error);
+ connect(m_media_player->audioOutput(), &QAudioOutput::volumeChanged, this, &qt_music_handler::handle_volume_change);
}
qt_music_handler::~qt_music_handler()
@@ -250,3 +251,8 @@ void qt_music_handler::handle_music_error(QMediaPlayer::Error error, const QStri
{
music_log.error("Error event: \"%s\" (error=%s)", errorString, error);
}
+
+void qt_music_handler::handle_volume_change(float volume) const
+{
+ music_log.notice("Volume changed: %f", volume);
+}
diff --git a/rpcs3/rpcs3qt/qt_music_handler.h b/rpcs3/rpcs3qt/qt_music_handler.h
index 9e62e06ce2..559995a4cb 100644
--- a/rpcs3/rpcs3qt/qt_music_handler.h
+++ b/rpcs3/rpcs3qt/qt_music_handler.h
@@ -26,6 +26,7 @@ private Q_SLOTS:
void handle_media_status(QMediaPlayer::MediaStatus status);
void handle_music_state(QMediaPlayer::PlaybackState state);
void handle_music_error(QMediaPlayer::Error error, const QString& errorString);
+ void handle_volume_change(float volume) const;
private:
mutable std::mutex m_mutex;