mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2025-06-01 16:23:17 +00:00
Add playback of background/title music in game list (#1033)
* add playback of background/title music * clang_format * add windows multimedia build instructions * fix typo accidentally made to arm * address comments * loop music * feedback * fix CI * add newline * playBGM off by default --------- Co-authored-by: Charles <charles@superfocus.ai>
This commit is contained in:
parent
ddb82a690b
commit
54e2179337
17 changed files with 181 additions and 17 deletions
32
src/qt_gui/background_music_player.cpp
Normal file
32
src/qt_gui/background_music_player.cpp
Normal file
|
@ -0,0 +1,32 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "background_music_player.h"
|
||||
|
||||
BackgroundMusicPlayer::BackgroundMusicPlayer(QObject* parent) : QObject(parent) {
|
||||
m_mediaPlayer = new QMediaPlayer(this);
|
||||
m_audioOutput = new QAudioOutput(this);
|
||||
m_mediaPlayer->setAudioOutput(m_audioOutput);
|
||||
m_mediaPlayer->setLoops(QMediaPlayer::Infinite);
|
||||
}
|
||||
|
||||
void BackgroundMusicPlayer::playMusic(const QString& snd0path) {
|
||||
if (snd0path.isEmpty()) {
|
||||
stopMusic();
|
||||
return;
|
||||
}
|
||||
const auto newMusic = QUrl::fromLocalFile(snd0path);
|
||||
if (m_mediaPlayer->playbackState() == QMediaPlayer::PlayingState &&
|
||||
m_currentMusic == newMusic) {
|
||||
// already playing the correct music
|
||||
return;
|
||||
}
|
||||
|
||||
m_currentMusic = newMusic;
|
||||
m_mediaPlayer->setSource(newMusic);
|
||||
m_mediaPlayer->play();
|
||||
}
|
||||
|
||||
void BackgroundMusicPlayer::stopMusic() {
|
||||
m_mediaPlayer->stop();
|
||||
}
|
28
src/qt_gui/background_music_player.h
Normal file
28
src/qt_gui/background_music_player.h
Normal file
|
@ -0,0 +1,28 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QAudioOutput>
|
||||
#include <QMediaPlayer>
|
||||
#include <QObject>
|
||||
|
||||
class BackgroundMusicPlayer : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
static BackgroundMusicPlayer& getInstance() {
|
||||
static BackgroundMusicPlayer instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
void playMusic(const QString& snd0path);
|
||||
void stopMusic();
|
||||
|
||||
private:
|
||||
BackgroundMusicPlayer(QObject* parent = nullptr);
|
||||
|
||||
QMediaPlayer* m_mediaPlayer;
|
||||
QAudioOutput* m_audioOutput;
|
||||
QUrl m_currentMusic;
|
||||
};
|
|
@ -39,6 +39,15 @@ GameGridFrame::GameGridFrame(std::shared_ptr<GameInfoClass> game_info_get, QWidg
|
|||
});
|
||||
}
|
||||
|
||||
void GameGridFrame::PlayBackgroundMusic(QTableWidgetItem* item) {
|
||||
if (!item) {
|
||||
BackgroundMusicPlayer::getInstance().stopMusic();
|
||||
return;
|
||||
}
|
||||
const auto snd0path = QString::fromStdString(m_game_info->m_games[item->row()].snd0_path);
|
||||
BackgroundMusicPlayer::getInstance().playMusic(snd0path);
|
||||
}
|
||||
|
||||
void GameGridFrame::PopulateGameGrid(QVector<GameInfo> m_games_search, bool fromSearch) {
|
||||
QVector<GameInfo> m_games_;
|
||||
this->clearContents();
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
#include <QScrollBar>
|
||||
|
||||
#include "background_music_player.h"
|
||||
#include "common/config.h"
|
||||
#include "game_info.h"
|
||||
#include "game_list_utils.h"
|
||||
|
@ -19,6 +20,7 @@ Q_SIGNALS:
|
|||
public Q_SLOTS:
|
||||
void SetGridBackgroundImage(int row, int column);
|
||||
void RefreshGridBackgroundImage();
|
||||
void PlayBackgroundMusic(QTableWidgetItem* item);
|
||||
|
||||
private:
|
||||
QImage backgroundImage;
|
||||
|
|
|
@ -32,6 +32,7 @@ public:
|
|||
QString iconpath = QString::fromStdString(game.icon_path);
|
||||
game.icon = QImage(iconpath);
|
||||
game.pic_path = game.path + "/sce_sys/pic1.png";
|
||||
game.snd0_path = game.path + "/sce_sys/snd0.at9";
|
||||
if (const auto title = psf.GetString("TITLE"); title.has_value()) {
|
||||
game.name = *title;
|
||||
}
|
||||
|
|
|
@ -68,6 +68,15 @@ GameListFrame::GameListFrame(std::shared_ptr<GameInfoClass> game_info_get, QWidg
|
|||
});
|
||||
}
|
||||
|
||||
void GameListFrame::PlayBackgroundMusic(QTableWidgetItem* item) {
|
||||
if (!item) {
|
||||
BackgroundMusicPlayer::getInstance().stopMusic();
|
||||
return;
|
||||
}
|
||||
const auto snd0path = QString::fromStdString(m_game_info->m_games[item->row()].snd0_path);
|
||||
BackgroundMusicPlayer::getInstance().playMusic(snd0path);
|
||||
}
|
||||
|
||||
void GameListFrame::PopulateGameList() {
|
||||
this->setRowCount(m_game_info->m_games.size());
|
||||
ResizeIcons(icon_size);
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
#include <QScrollBar>
|
||||
|
||||
#include "background_music_player.h"
|
||||
#include "game_info.h"
|
||||
#include "game_list_utils.h"
|
||||
#include "gui_context_menus.h"
|
||||
|
@ -21,6 +22,7 @@ public Q_SLOTS:
|
|||
void RefreshListBackgroundImage();
|
||||
void SortNameAscending(int columnIndex);
|
||||
void SortNameDescending(int columnIndex);
|
||||
void PlayBackgroundMusic(QTableWidgetItem* item);
|
||||
|
||||
private:
|
||||
void SetTableItem(int row, int column, QString itemStr);
|
||||
|
|
|
@ -7,6 +7,7 @@ struct GameInfo {
|
|||
std::string path; // root path of game directory (normally directory that contains eboot.bin)
|
||||
std::string icon_path; // path of icon0.png
|
||||
std::string pic_path; // path of pic1.png
|
||||
std::string snd0_path; // path of snd0.at9
|
||||
QImage icon;
|
||||
std::string size;
|
||||
// variables extracted from param.sfo
|
||||
|
|
|
@ -501,9 +501,29 @@ void MainWindow::CreateConnects() {
|
|||
isIconBlack = false;
|
||||
}
|
||||
});
|
||||
|
||||
connect(m_game_grid_frame.get(), &QTableWidget::cellClicked, this,
|
||||
&MainWindow::PlayBackgroundMusic);
|
||||
connect(m_game_list_frame.get(), &QTableWidget::cellClicked, this,
|
||||
&MainWindow::PlayBackgroundMusic);
|
||||
}
|
||||
|
||||
void MainWindow::PlayBackgroundMusic() {
|
||||
if (isGameRunning || !Config::getPlayBGM()) {
|
||||
BackgroundMusicPlayer::getInstance().stopMusic();
|
||||
return;
|
||||
}
|
||||
int itemID = isTableList ? m_game_list_frame->currentItem()->row()
|
||||
: m_game_grid_frame->crtRow * m_game_grid_frame->columnCnt +
|
||||
m_game_grid_frame->crtColumn;
|
||||
|
||||
const auto snd0path = QString::fromStdString(m_game_info->m_games[itemID].snd0_path);
|
||||
BackgroundMusicPlayer::getInstance().playMusic(snd0path);
|
||||
}
|
||||
|
||||
void MainWindow::StartGame() {
|
||||
isGameRunning = true;
|
||||
BackgroundMusicPlayer::getInstance().stopMusic();
|
||||
QString gamePath = "";
|
||||
int table_mode = Config::getTableMode();
|
||||
if (table_mode == 0) {
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include <QDragEnterEvent>
|
||||
#include <QTranslator>
|
||||
|
||||
#include "background_music_player.h"
|
||||
#include "common/config.h"
|
||||
#include "common/path_util.h"
|
||||
#include "core/file_format/psf.h"
|
||||
|
@ -63,9 +64,11 @@ private:
|
|||
void BootGame();
|
||||
void AddRecentFiles(QString filePath);
|
||||
void LoadTranslation();
|
||||
void PlayBackgroundMusic();
|
||||
QIcon RecolorIcon(const QIcon& icon, bool isWhite);
|
||||
bool isIconBlack = false;
|
||||
bool isTableList = true;
|
||||
bool isGameRunning = false;
|
||||
QActionGroup* m_icon_size_act_group = nullptr;
|
||||
QActionGroup* m_list_mode_act_group = nullptr;
|
||||
QActionGroup* m_theme_act_group = nullptr;
|
||||
|
|
|
@ -134,6 +134,9 @@ SettingsDialog::SettingsDialog(std::span<const QString> physical_devices, QWidge
|
|||
auto checkUpdate = new CheckUpdate(true);
|
||||
checkUpdate->exec();
|
||||
});
|
||||
|
||||
connect(ui->playBGMCheckBox, &QCheckBox::stateChanged, this,
|
||||
[](int val) { Config::setPlayBGM(val); });
|
||||
}
|
||||
|
||||
// GPU TAB
|
||||
|
@ -192,7 +195,7 @@ void SettingsDialog::LoadValuesFromConfig() {
|
|||
ui->dumpShadersCheckBox->setChecked(Config::dumpShaders());
|
||||
ui->nullGpuCheckBox->setChecked(Config::nullGpu());
|
||||
ui->dumpPM4CheckBox->setChecked(Config::dumpPM4());
|
||||
|
||||
ui->playBGMCheckBox->setChecked(Config::getPlayBGM());
|
||||
ui->fullscreenCheckBox->setChecked(Config::isFullscreenMode());
|
||||
ui->showSplashCheckBox->setChecked(Config::showSplash());
|
||||
ui->ps4proCheckBox->setChecked(Config::isNeoMode());
|
||||
|
|
|
@ -52,7 +52,7 @@
|
|||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>836</width>
|
||||
<height>428</height>
|
||||
<height>432</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
|
@ -70,7 +70,7 @@
|
|||
</attribute>
|
||||
<layout class="QVBoxLayout" name="generalTabVLayout" stretch="0,0">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="generalTabHLayout" stretch="1,1,1">
|
||||
<layout class="QHBoxLayout" name="generalTabHLayoutTop" stretch="1,1,1">
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="systemTabLayoutLeft">
|
||||
<item>
|
||||
|
@ -340,19 +340,55 @@
|
|||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="GUITabLayoutMiddle" stretch="1">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="GUIgroupBox">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>GUI Settings</string>
|
||||
</property>
|
||||
<widget class="QWidget" name="verticalLayoutWidget_3">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>10</x>
|
||||
<y>30</y>
|
||||
<width>241</width>
|
||||
<height>41</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="playBGMCheckBox">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Play title music</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Expanding</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>500</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
<enum>QSizePolicy::Policy::Expanding</enum>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue