mirror of
https://github.com/ciphervance/supercell-wx.git
synced 2025-10-30 22:10:05 +00:00
176 lines
4.8 KiB
C++
176 lines
4.8 KiB
C++
#include <scwx/qt/manager/media_manager.hpp>
|
|
#include <scwx/util/logger.hpp>
|
|
|
|
#include <QAudioDevice>
|
|
#include <QAudioOutput>
|
|
#include <QMediaDevices>
|
|
#include <QMediaPlayer>
|
|
#include <QThread>
|
|
#include <QUrl>
|
|
|
|
namespace scwx::qt::manager
|
|
{
|
|
|
|
static const std::string logPrefix_ = "scwx::qt::manager::media_manager";
|
|
static const auto logger_ = scwx::util::Logger::Create(logPrefix_);
|
|
|
|
class MediaManager::Impl
|
|
{
|
|
public:
|
|
explicit Impl()
|
|
{
|
|
mediaParent_ = std::make_unique<QObject>();
|
|
mediaParent_->moveToThread(&thread_);
|
|
|
|
thread_.start();
|
|
|
|
QMetaObject::invokeMethod(
|
|
mediaParent_.get(),
|
|
[this]()
|
|
{
|
|
// QObjects are managed by the parent
|
|
// NOLINTBEGIN(cppcoreguidelines-owning-memory)
|
|
|
|
logger_->debug("Creating QMediaDevices");
|
|
mediaDevices_ = new QMediaDevices(mediaParent_.get());
|
|
logger_->debug("Creating QMediaPlayer");
|
|
mediaPlayer_ = new QMediaPlayer(mediaParent_.get());
|
|
logger_->debug("Creating QAudioOutput");
|
|
audioOutput_ = new QAudioOutput(mediaParent_.get());
|
|
|
|
// NOLINTEND(cppcoreguidelines-owning-memory)
|
|
|
|
logger_->debug("Audio device: {}",
|
|
audioOutput_->device().description().toStdString());
|
|
|
|
mediaPlayer_->setAudioOutput(audioOutput_);
|
|
|
|
ConnectSignals();
|
|
});
|
|
}
|
|
|
|
~Impl()
|
|
{
|
|
// Delete the media parent
|
|
mediaParent_.reset();
|
|
|
|
thread_.quit();
|
|
thread_.wait();
|
|
}
|
|
|
|
Impl(const Impl&) = delete;
|
|
Impl& operator=(const Impl&) = delete;
|
|
Impl(const Impl&&) = delete;
|
|
Impl& operator=(const Impl&&) = delete;
|
|
|
|
void ConnectSignals();
|
|
|
|
QThread thread_ {};
|
|
|
|
std::unique_ptr<QObject> mediaParent_ {nullptr};
|
|
QMediaDevices* mediaDevices_ {nullptr};
|
|
QMediaPlayer* mediaPlayer_ {nullptr};
|
|
QAudioOutput* audioOutput_ {nullptr};
|
|
};
|
|
|
|
MediaManager::MediaManager() : p(std::make_unique<Impl>()) {}
|
|
MediaManager::~MediaManager() = default;
|
|
|
|
MediaManager::MediaManager(MediaManager&&) noexcept = default;
|
|
MediaManager& MediaManager::operator=(MediaManager&&) noexcept = default;
|
|
|
|
void MediaManager::Impl::ConnectSignals()
|
|
{
|
|
QObject::connect(
|
|
mediaDevices_,
|
|
&QMediaDevices::audioOutputsChanged,
|
|
mediaParent_.get(),
|
|
[this]()
|
|
{ audioOutput_->setDevice(QMediaDevices::defaultAudioOutput()); });
|
|
|
|
QObject::connect(audioOutput_,
|
|
&QAudioOutput::deviceChanged,
|
|
mediaParent_.get(),
|
|
[this]()
|
|
{
|
|
logger_->debug(
|
|
"Audio device changed: {}",
|
|
audioOutput_->device().description().toStdString());
|
|
});
|
|
|
|
QObject::connect(mediaPlayer_,
|
|
&QMediaPlayer::errorOccurred,
|
|
mediaParent_.get(),
|
|
[](QMediaPlayer::Error error, const QString& errorString)
|
|
{
|
|
logger_->error("Error {}: {}",
|
|
static_cast<int>(error),
|
|
errorString.toStdString());
|
|
});
|
|
}
|
|
|
|
void MediaManager::Play(types::AudioFile media)
|
|
{
|
|
const std::string path = types::GetMediaPath(media);
|
|
Play(path);
|
|
}
|
|
|
|
void MediaManager::Play(const std::string& mediaPath)
|
|
{
|
|
logger_->debug("Playing audio: {}", mediaPath);
|
|
|
|
if (p->mediaPlayer_ == nullptr)
|
|
{
|
|
logger_->warn("Media player is not yet initialized");
|
|
return;
|
|
}
|
|
|
|
if (mediaPath.starts_with(':'))
|
|
{
|
|
QMetaObject::invokeMethod(
|
|
p->mediaPlayer_,
|
|
&QMediaPlayer::setSource,
|
|
QUrl(QString("qrc%1").arg(QString::fromStdString(mediaPath))));
|
|
}
|
|
else
|
|
{
|
|
QMetaObject::invokeMethod(
|
|
p->mediaPlayer_,
|
|
&QMediaPlayer::setSource,
|
|
QUrl::fromLocalFile(QString::fromStdString(mediaPath)));
|
|
}
|
|
|
|
QMetaObject::invokeMethod(p->mediaPlayer_, &QMediaPlayer::setPosition, 0);
|
|
QMetaObject::invokeMethod(p->mediaPlayer_, &QMediaPlayer::play);
|
|
}
|
|
|
|
void MediaManager::Stop()
|
|
{
|
|
if (p->mediaPlayer_ == nullptr)
|
|
{
|
|
logger_->warn("Media player is not yet initialized");
|
|
return;
|
|
}
|
|
|
|
QMetaObject::invokeMethod(p->mediaPlayer_, &QMediaPlayer::stop);
|
|
}
|
|
|
|
std::shared_ptr<MediaManager> MediaManager::Instance()
|
|
{
|
|
static std::weak_ptr<MediaManager> mediaManagerReference_ {};
|
|
static std::mutex instanceMutex_ {};
|
|
|
|
std::unique_lock lock(instanceMutex_);
|
|
|
|
std::shared_ptr<MediaManager> mediaManager = mediaManagerReference_.lock();
|
|
|
|
if (mediaManager == nullptr)
|
|
{
|
|
mediaManager = std::make_shared<MediaManager>();
|
|
mediaManagerReference_ = mediaManager;
|
|
}
|
|
|
|
return mediaManager;
|
|
}
|
|
|
|
} // namespace scwx::qt::manager
|