mirror of
				https://github.com/ciphervance/supercell-wx.git
				synced 2025-10-31 15:40:06 +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
 | 
