File indexing completed on 2024-04-14 04:43:56
0001 /* 0002 SPDX-FileCopyrightText: 2017 (c) Matthieu Gallien <matthieu_gallien@yahoo.fr> 0003 0004 SPDX-License-Identifier: LGPL-3.0-or-later 0005 */ 0006 0007 #include "audiowrapper.h" 0008 #include "powermanagementinterface.h" 0009 0010 #include "qtMultimediaLogging.h" 0011 0012 #include <QTimer> 0013 #include <QAudio> 0014 #include <QAudioOutput> 0015 0016 #include "config-upnp-qt.h" 0017 0018 class AudioWrapperPrivate 0019 { 0020 0021 public: 0022 0023 PowerManagementInterface mPowerInterface; 0024 0025 QMediaPlayer mPlayer; 0026 0027 QAudioOutput mOutput; 0028 0029 qint64 mSavedPosition = 0.0; 0030 0031 qint64 mUndoSavedPosition = 0.0; 0032 0033 bool mHasSavedPosition = false; 0034 0035 }; 0036 0037 AudioWrapper::AudioWrapper(QObject *parent) : QObject(parent), d(std::make_unique<AudioWrapperPrivate>()) 0038 { 0039 d->mPlayer.setAudioOutput(&d->mOutput); 0040 connect(&d->mOutput, &QAudioOutput::mutedChanged, this, &AudioWrapper::playerMutedChanged); 0041 connect(&d->mOutput, &QAudioOutput::volumeChanged, this, &AudioWrapper::playerVolumeChanged); 0042 connect(&d->mPlayer, &QMediaPlayer::sourceChanged, this, &AudioWrapper::sourceChanged); 0043 connect(&d->mPlayer, &QMediaPlayer::playbackStateChanged, this, &AudioWrapper::playbackStateChanged); 0044 connect(&d->mPlayer, &QMediaPlayer::playbackStateChanged, this, &AudioWrapper::playerStateChanged); 0045 connect(&d->mPlayer, QOverload<QMediaPlayer::Error, const QString &>::of(&QMediaPlayer::errorOccurred), this, &AudioWrapper::errorChanged); 0046 connect(&d->mPlayer, &QMediaPlayer::mediaStatusChanged, this, &AudioWrapper::statusChanged); 0047 connect(&d->mPlayer, &QMediaPlayer::mediaStatusChanged, this, &AudioWrapper::mediaStatusChanged); 0048 connect(&d->mPlayer, &QMediaPlayer::durationChanged, this, &AudioWrapper::durationChanged); 0049 connect(&d->mPlayer, &QMediaPlayer::positionChanged, this, &AudioWrapper::positionChanged); 0050 connect(&d->mPlayer, &QMediaPlayer::seekableChanged, this, &AudioWrapper::seekableChanged); 0051 } 0052 0053 AudioWrapper::~AudioWrapper() 0054 { 0055 d->mPowerInterface.setPreventSleep(false); 0056 } 0057 0058 bool AudioWrapper::muted() const 0059 { 0060 return d->mOutput.isMuted(); 0061 } 0062 0063 qreal AudioWrapper::volume() const 0064 { 0065 auto realVolume = static_cast<qreal>(d->mOutput.volume() / 100.0); 0066 auto userVolume = static_cast<qreal>(QAudio::convertVolume(realVolume, QAudio::LinearVolumeScale, QAudio::LogarithmicVolumeScale)); 0067 0068 return userVolume * 100.0; 0069 } 0070 0071 QUrl AudioWrapper::source() const 0072 { 0073 return d->mPlayer.source(); 0074 } 0075 0076 QMediaPlayer::Error AudioWrapper::error() const 0077 { 0078 if (d->mPlayer.error() != QMediaPlayer::NoError) { 0079 qDebug() << "AudioWrapper::error" << d->mPlayer.errorString(); 0080 } 0081 0082 return d->mPlayer.error(); 0083 } 0084 0085 qint64 AudioWrapper::duration() const 0086 { 0087 return d->mPlayer.duration(); 0088 } 0089 0090 qint64 AudioWrapper::position() const 0091 { 0092 return d->mPlayer.position(); 0093 } 0094 0095 bool AudioWrapper::seekable() const 0096 { 0097 return d->mPlayer.isSeekable(); 0098 } 0099 0100 QMediaPlayer::PlaybackState AudioWrapper::playbackState() const 0101 { 0102 return d->mPlayer.playbackState(); 0103 } 0104 0105 QMediaPlayer::MediaStatus AudioWrapper::status() const 0106 { 0107 return d->mPlayer.mediaStatus(); 0108 } 0109 0110 void AudioWrapper::setMuted(bool muted) 0111 { 0112 d->mOutput.setMuted(muted); 0113 } 0114 0115 void AudioWrapper::setVolume(qreal volume) 0116 { 0117 qCDebug(orgKdeElisaPlayerQtMultimedia) << "AudioWrapper::setVolume" << volume; 0118 0119 auto realVolume = static_cast<qreal>(QAudio::convertVolume(volume / 100.0, QAudio::LogarithmicVolumeScale, QAudio::LinearVolumeScale)); 0120 d->mOutput.setVolume(qRound(realVolume * 100)); 0121 } 0122 0123 void AudioWrapper::setSource(const QUrl &source) 0124 { 0125 qCDebug(orgKdeElisaPlayerQtMultimedia) << "AudioWrapper::setSource" << source; 0126 d->mPlayer.setSource({source}); 0127 } 0128 0129 void AudioWrapper::setPosition(qint64 position) 0130 { 0131 qCDebug(orgKdeElisaPlayerQtMultimedia) << "AudioWrapper::setPosition" << position; 0132 0133 if (d->mPlayer.duration() <= 0) { 0134 savePosition(position); 0135 return; 0136 } 0137 0138 d->mPlayer.setPosition(position); 0139 } 0140 0141 void AudioWrapper::play() 0142 { 0143 qCDebug(orgKdeElisaPlayerQtMultimedia) << "AudioWrapper::play"; 0144 0145 d->mPlayer.play(); 0146 0147 if (d->mHasSavedPosition) { 0148 qCDebug(orgKdeElisaPlayerQtMultimedia) << "AudioWrapper::playerDurationSignalChanges" << "restore old position" << d->mSavedPosition; 0149 0150 setPosition(d->mSavedPosition); 0151 d->mHasSavedPosition = false; 0152 } 0153 } 0154 0155 void AudioWrapper::pause() 0156 { 0157 qCDebug(orgKdeElisaPlayerQtMultimedia) << "AudioWrapper::pause"; 0158 0159 d->mPlayer.pause(); 0160 } 0161 0162 void AudioWrapper::stop() 0163 { 0164 qCDebug(orgKdeElisaPlayerQtMultimedia) << "AudioWrapper::stop"; 0165 0166 d->mPlayer.stop(); 0167 } 0168 0169 void AudioWrapper::seek(qint64 position) 0170 { 0171 qCDebug(orgKdeElisaPlayerQtMultimedia) << "AudioWrapper::seek" << position; 0172 0173 d->mPlayer.setPosition(position); 0174 } 0175 0176 void AudioWrapper::mediaStatusChanged() 0177 { 0178 qCDebug(orgKdeElisaPlayerQtMultimedia) << "AudioWrapper::mediaStatusChanged" << d->mPlayer.mediaStatus(); 0179 } 0180 0181 void AudioWrapper::playerStateChanged() 0182 { 0183 qCDebug(orgKdeElisaPlayerQtMultimedia) << "AudioWrapper::playerStateChanged" << d->mPlayer.playbackState(); 0184 0185 switch(d->mPlayer.playbackState()) 0186 { 0187 case QMediaPlayer::PlaybackState::StoppedState: 0188 Q_EMIT stopped(); 0189 d->mPowerInterface.setPreventSleep(false); 0190 break; 0191 case QMediaPlayer::PlaybackState::PlayingState: 0192 Q_EMIT playing(); 0193 d->mPowerInterface.setPreventSleep(true); 0194 break; 0195 case QMediaPlayer::PlaybackState::PausedState: 0196 Q_EMIT paused(); 0197 d->mPowerInterface.setPreventSleep(false); 0198 break; 0199 } 0200 } 0201 0202 void AudioWrapper::playerVolumeChanged() 0203 { 0204 qCDebug(orgKdeElisaPlayerQtMultimedia) << "AudioWrapper::playerVolumeChanged" << d->mOutput.volume(); 0205 0206 QTimer::singleShot(0, [this]() {Q_EMIT volumeChanged();}); 0207 } 0208 0209 void AudioWrapper::playerMutedChanged() 0210 { 0211 qCDebug(orgKdeElisaPlayerQtMultimedia) << "AudioWrapper::playerMutedChanged"; 0212 0213 QTimer::singleShot(0, [this]() {Q_EMIT mutedChanged(muted());}); 0214 } 0215 0216 void AudioWrapper::playerStateSignalChanges(QMediaPlayer::PlaybackState newState) 0217 { 0218 qCDebug(orgKdeElisaPlayerQtMultimedia) << "AudioWrapper::playerStateSignalChanges" << newState; 0219 0220 QMetaObject::invokeMethod(this, [this, newState]() {Q_EMIT playbackStateChanged(newState);}, Qt::QueuedConnection); 0221 } 0222 0223 void AudioWrapper::mediaStatusSignalChanges(QMediaPlayer::MediaStatus newStatus) 0224 { 0225 qCDebug(orgKdeElisaPlayerQtMultimedia) << "AudioWrapper::mediaStatusSignalChanges" << newStatus; 0226 0227 QMetaObject::invokeMethod(this, [this, newStatus]() {Q_EMIT statusChanged(newStatus);}, Qt::QueuedConnection); 0228 } 0229 0230 void AudioWrapper::playerDurationSignalChanges(qint64 newDuration) 0231 { 0232 qCDebug(orgKdeElisaPlayerQtMultimedia) << "AudioWrapper::playerDurationSignalChanges" << newDuration; 0233 0234 QMetaObject::invokeMethod(this, [this, newDuration]() {Q_EMIT durationChanged(newDuration);}, Qt::QueuedConnection); 0235 } 0236 0237 void AudioWrapper::playerPositionSignalChanges(qint64 newPosition) 0238 { 0239 qCDebug(orgKdeElisaPlayerQtMultimedia) << "AudioWrapper::playerPositionSignalChanges" << newPosition; 0240 0241 QMetaObject::invokeMethod(this, [this, newPosition]() {Q_EMIT positionChanged(newPosition);}, Qt::QueuedConnection); 0242 } 0243 0244 void AudioWrapper::playerVolumeSignalChanges() 0245 { 0246 QMetaObject::invokeMethod(this, [this]() {Q_EMIT volumeChanged();}, Qt::QueuedConnection); 0247 } 0248 0249 void AudioWrapper::playerMutedSignalChanges(bool isMuted) 0250 { 0251 QMetaObject::invokeMethod(this, [this, isMuted]() {Q_EMIT mutedChanged(isMuted);}, Qt::QueuedConnection); 0252 } 0253 0254 void AudioWrapper::playerSeekableSignalChanges(bool isSeekable) 0255 { 0256 QMetaObject::invokeMethod(this, [this, isSeekable]() {Q_EMIT seekableChanged(isSeekable);}, Qt::QueuedConnection); 0257 } 0258 0259 void AudioWrapper::saveUndoPosition(qint64 position) 0260 { 0261 qCDebug(orgKdeElisaPlayerQtMultimedia) << "AudioWrapper::saveUndoPosition" << position; 0262 0263 d->mUndoSavedPosition = position; 0264 } 0265 0266 void AudioWrapper::restoreUndoPosition() 0267 { 0268 qCDebug(orgKdeElisaPlayerQtMultimedia) << "AudioWrapper::restoreUndoPosition"; 0269 0270 d->mHasSavedPosition = true; 0271 d->mSavedPosition = d->mUndoSavedPosition; 0272 } 0273 0274 void AudioWrapper::savePosition(qint64 position) 0275 { 0276 qCDebug(orgKdeElisaPlayerQtMultimedia) << "AudioWrapper::savePosition" << position; 0277 0278 if (!d->mHasSavedPosition) { 0279 d->mHasSavedPosition = true; 0280 d->mSavedPosition = position; 0281 qCDebug(orgKdeElisaPlayerQtMultimedia) << "AudioWrapper::savePosition" << "restore old position" << d->mSavedPosition; 0282 } 0283 } 0284 0285 0286 #include "moc_audiowrapper.cpp"