File indexing completed on 2025-01-19 04:23:47
0001 /*************************************************************************** 0002 SPDX-FileCopyrightText: 2014 (c) Sujith Haridasan <sujith.haridasan@kdemail.net> 0003 SPDX-FileCopyrightText: 2014 (c) Ashish Madeti <ashishmadeti@gmail.com> 0004 SPDX-FileCopyrightText: 2016 (c) Matthieu Gallien <matthieu_gallien@yahoo.fr> 0005 0006 SPDX-License-Identifier: GPL-3.0-or-later 0007 ***************************************************************************/ 0008 0009 #include "mediaplayer2player.h" 0010 #include "mpris2.h" 0011 0012 #include "../../services/local/player.h" 0013 #include "../../services/local/playlist.h" 0014 0015 #include <QCryptographicHash> 0016 #include <QDBusConnection> 0017 #include <QDBusMessage> 0018 #include <QStringList> 0019 0020 #include "utils/bae.h" 0021 #include <MauiKit3/Core/fmh.h> 0022 0023 static const double MAX_RATE = 1.0; 0024 static const double MIN_RATE = 1.0; 0025 0026 MediaPlayer2Player::MediaPlayer2Player(Playlist *playListControler, Player *audioPlayer, bool showProgressOnTaskBar, QObject *parent) 0027 : QDBusAbstractAdaptor(parent) 0028 , m_playListControler(playListControler) 0029 , m_audioPlayer(audioPlayer) 0030 , mProgressIndicatorSignal(QDBusMessage::createSignal(QStringLiteral("/org/maui/vvave"), QStringLiteral("com.canonical.Unity.LauncherEntry"), QStringLiteral("Update"))) 0031 , mShowProgressOnTaskBar(showProgressOnTaskBar) 0032 { 0033 if (!m_playListControler) { 0034 return; 0035 } 0036 0037 connect(m_playListControler, &Playlist::currentIndexChanged, this, &MediaPlayer2Player::playerSourceChanged, Qt::QueuedConnection); 0038 connect(m_playListControler, &Playlist::canPlayChanged, this, &MediaPlayer2Player::playControlEnabledChanged); 0039 connect(m_playListControler, &Playlist::canPlayChanged, this, &MediaPlayer2Player::skipBackwardControlEnabledChanged); 0040 connect(m_playListControler, &Playlist::canPlayChanged, this, &MediaPlayer2Player::skipForwardControlEnabledChanged); 0041 connect(m_audioPlayer, &Player::stateChanged, this, &MediaPlayer2Player::playerPlaybackStateChanged); 0042 connect(m_audioPlayer, &Player::stateChanged, this, &MediaPlayer2Player::playerIsSeekableChanged); 0043 // connect(m_audioPlayer, &Player::posChanged, this, &MediaPlayer2Player::audioPositionChanged); 0044 connect(m_audioPlayer, &Player::durationChanged, this, &MediaPlayer2Player::audioDurationChanged); 0045 connect(m_audioPlayer, &Player::volumeChanged, this, &MediaPlayer2Player::playerVolumeChanged); 0046 0047 m_volume = m_audioPlayer->getVolume() / 100; 0048 m_canPlay = m_playListControler->canPlay(); 0049 signalPropertiesChange(QStringLiteral("Volume"), Volume()); 0050 0051 m_mediaPlayerPresent = 1; 0052 } 0053 0054 MediaPlayer2Player::~MediaPlayer2Player() = default; 0055 0056 QString MediaPlayer2Player::PlaybackStatus() const 0057 { 0058 QString result; 0059 0060 if (!m_playListControler) { 0061 result = QStringLiteral("Stopped"); 0062 return result; 0063 } 0064 0065 if (m_audioPlayer->getState() == QMediaPlayer::StoppedState) { 0066 result = QStringLiteral("Stopped"); 0067 } else if (m_audioPlayer->getState() == QMediaPlayer::PlayingState) { 0068 result = QStringLiteral("Playing"); 0069 } else { 0070 result = QStringLiteral("Paused"); 0071 } 0072 0073 if (mShowProgressOnTaskBar) { 0074 QVariantMap parameters; 0075 0076 if (m_audioPlayer->getState() == QMediaPlayer::StoppedState || m_audioPlayer->getDuration() == 0) { 0077 parameters.insert(QStringLiteral("progress-visible"), false); 0078 parameters.insert(QStringLiteral("progress"), 0); 0079 } else { 0080 parameters.insert(QStringLiteral("progress-visible"), true); 0081 parameters.insert(QStringLiteral("progress"), qRound(static_cast<double>(m_position / m_audioPlayer->getDuration())) / 1000.0); 0082 } 0083 0084 mProgressIndicatorSignal.setArguments({QStringLiteral("application://org.maui.vvave.desktop"), parameters}); 0085 0086 QDBusConnection::sessionBus().send(mProgressIndicatorSignal); 0087 } 0088 0089 return result; 0090 } 0091 0092 bool MediaPlayer2Player::CanGoNext() const 0093 { 0094 return m_canGoNext; 0095 } 0096 0097 void MediaPlayer2Player::Next() 0098 { 0099 emit next(); 0100 0101 if (m_playListControler) { 0102 m_playListControler->next(); 0103 } 0104 } 0105 0106 bool MediaPlayer2Player::CanGoPrevious() const 0107 { 0108 return m_canGoPrevious; 0109 } 0110 0111 void MediaPlayer2Player::Previous() 0112 { 0113 emit previous(); 0114 0115 if (m_playListControler) { 0116 m_playListControler->previous(); 0117 } 0118 } 0119 0120 bool MediaPlayer2Player::CanPause() const 0121 { 0122 return m_canPlay; 0123 } 0124 0125 void MediaPlayer2Player::Pause() 0126 { 0127 if (m_playListControler) { 0128 m_audioPlayer->pause(); 0129 } 0130 } 0131 0132 void MediaPlayer2Player::PlayPause() 0133 { 0134 emit playPause(); 0135 0136 if (m_playListControler) { 0137 m_audioPlayer->pause(); 0138 } 0139 } 0140 0141 void MediaPlayer2Player::Stop() 0142 { 0143 emit stop(); 0144 0145 if (m_playListControler) { 0146 m_audioPlayer->stop(); 0147 } 0148 } 0149 0150 bool MediaPlayer2Player::CanPlay() const 0151 { 0152 return m_canPlay; 0153 } 0154 0155 void MediaPlayer2Player::Play() 0156 { 0157 if (m_playListControler) { 0158 m_audioPlayer->play(); 0159 } 0160 } 0161 0162 double MediaPlayer2Player::Volume() const 0163 { 0164 return m_volume; 0165 } 0166 0167 void MediaPlayer2Player::setVolume(double volume) 0168 { 0169 m_volume = qBound(0.0, volume, 1.0); 0170 emit volumeChanged(m_volume); 0171 0172 m_audioPlayer->setVolume(100 * m_volume); 0173 0174 signalPropertiesChange(QStringLiteral("Volume"), Volume()); 0175 } 0176 0177 QVariantMap MediaPlayer2Player::Metadata() const 0178 { 0179 return m_metadata; 0180 } 0181 0182 qlonglong MediaPlayer2Player::Position() const 0183 { 0184 return m_position; 0185 } 0186 0187 void MediaPlayer2Player::setPropertyPosition(int newPositionInMs) 0188 { 0189 m_position = qlonglong(newPositionInMs) * 1000; 0190 0191 Q_EMIT Seeked(m_position); 0192 0193 /* only sent new progress when it has advanced more than 1 % 0194 * to limit DBus traffic 0195 */ 0196 const auto incrementalProgress = static_cast<double>(newPositionInMs - mPreviousProgressPosition) / m_audioPlayer->getDuration(); 0197 if (mShowProgressOnTaskBar && (incrementalProgress > 0.01 || incrementalProgress < 0)) { 0198 mPreviousProgressPosition = newPositionInMs; 0199 QVariantMap parameters; 0200 parameters.insert(QStringLiteral("progress-visible"), true); 0201 parameters.insert(QStringLiteral("progress"), static_cast<double>(newPositionInMs) / m_audioPlayer->getDuration()); 0202 0203 mProgressIndicatorSignal.setArguments({QStringLiteral("application://org.maui.vvave.desktop"), parameters}); 0204 0205 QDBusConnection::sessionBus().send(mProgressIndicatorSignal); 0206 } 0207 } 0208 0209 double MediaPlayer2Player::Rate() const 0210 { 0211 return m_rate; 0212 } 0213 0214 void MediaPlayer2Player::setRate(double newRate) 0215 { 0216 if (newRate <= 0.0001 && newRate >= -0.0001) { 0217 Pause(); 0218 } else { 0219 m_rate = qBound(MinimumRate(), newRate, MaximumRate()); 0220 emit rateChanged(m_rate); 0221 0222 signalPropertiesChange(QStringLiteral("Rate"), Rate()); 0223 } 0224 } 0225 0226 double MediaPlayer2Player::MinimumRate() const 0227 { 0228 return MIN_RATE; 0229 } 0230 0231 double MediaPlayer2Player::MaximumRate() const 0232 { 0233 return MAX_RATE; 0234 } 0235 0236 bool MediaPlayer2Player::CanSeek() const 0237 { 0238 return m_playerIsSeekableChanged; 0239 } 0240 0241 bool MediaPlayer2Player::CanControl() const 0242 { 0243 return true; 0244 } 0245 0246 void MediaPlayer2Player::Seek(qlonglong Offset) 0247 { 0248 if (mediaPlayerPresent()) { 0249 auto offset = (m_position + Offset) / 1000; 0250 m_audioPlayer->setPos(int(offset)); 0251 } 0252 } 0253 0254 void MediaPlayer2Player::emitSeeked(int pos) 0255 { 0256 emit Seeked(qlonglong(pos) * 1000); 0257 } 0258 0259 void MediaPlayer2Player::SetPosition(const QDBusObjectPath &trackId, qlonglong pos) 0260 { 0261 if (trackId.path() == m_currentTrackId) { 0262 m_audioPlayer->setPos(int(pos / 1000)); 0263 } 0264 } 0265 0266 void MediaPlayer2Player::OpenUri(const QString &uri) 0267 { 0268 Q_UNUSED(uri); 0269 } 0270 0271 void MediaPlayer2Player::playerSourceChanged() 0272 { 0273 if (!m_playListControler) { 0274 return; 0275 } 0276 0277 setCurrentTrack(m_playListControler->currentIndex()); 0278 } 0279 0280 void MediaPlayer2Player::playControlEnabledChanged() 0281 { 0282 if (!m_playListControler) { 0283 return; 0284 } 0285 0286 m_canPlay = m_playListControler->canPlay(); 0287 0288 signalPropertiesChange(QStringLiteral("CanPause"), CanPause()); 0289 signalPropertiesChange(QStringLiteral("CanPlay"), CanPlay()); 0290 0291 emit canPauseChanged(); 0292 emit canPlayChanged(); 0293 } 0294 0295 void MediaPlayer2Player::skipBackwardControlEnabledChanged() 0296 { 0297 if (!m_playListControler) { 0298 return; 0299 } 0300 0301 m_canGoPrevious = m_playListControler->canGoPrevious(); 0302 0303 signalPropertiesChange(QStringLiteral("CanGoPrevious"), CanGoPrevious()); 0304 emit canGoPreviousChanged(); 0305 } 0306 0307 void MediaPlayer2Player::skipForwardControlEnabledChanged() 0308 { 0309 if (!m_playListControler) { 0310 return; 0311 } 0312 0313 m_canGoNext = m_playListControler->canGoNext(); 0314 0315 signalPropertiesChange(QStringLiteral("CanGoNext"), CanGoNext()); 0316 emit canGoNextChanged(); 0317 } 0318 0319 void MediaPlayer2Player::playerPlaybackStateChanged() 0320 { 0321 signalPropertiesChange(QStringLiteral("PlaybackStatus"), PlaybackStatus()); 0322 emit playbackStatusChanged(); 0323 0324 playerIsSeekableChanged(); 0325 } 0326 0327 void MediaPlayer2Player::playerIsSeekableChanged() 0328 { 0329 m_playerIsSeekableChanged = m_audioPlayer->getState() == QMediaPlayer::State::PausedState || m_audioPlayer->getState() == QMediaPlayer::State::PlayingState; 0330 0331 signalPropertiesChange(QStringLiteral("CanSeek"), CanSeek()); 0332 emit canSeekChanged(); 0333 } 0334 0335 void MediaPlayer2Player::audioPositionChanged() 0336 { 0337 setPropertyPosition(static_cast<int>(m_audioPlayer->getPos())); 0338 } 0339 0340 void MediaPlayer2Player::audioDurationChanged() 0341 { 0342 m_metadata = getMetadataOfCurrentTrack(); 0343 signalPropertiesChange(QStringLiteral("Metadata"), Metadata()); 0344 0345 skipBackwardControlEnabledChanged(); 0346 skipForwardControlEnabledChanged(); 0347 playerPlaybackStateChanged(); 0348 playerIsSeekableChanged(); 0349 setPropertyPosition(static_cast<int>(m_audioPlayer->getPos())); 0350 } 0351 0352 void MediaPlayer2Player::playerVolumeChanged() 0353 { 0354 setVolume(m_audioPlayer->getVolume() / 100.0); 0355 } 0356 0357 int MediaPlayer2Player::currentTrack() const 0358 { 0359 return m_playListControler->currentIndex(); 0360 } 0361 0362 void MediaPlayer2Player::setCurrentTrack(int newTrackPosition) 0363 { 0364 m_currentTrack = m_playListControler->currentTrack().value("url").toString(); 0365 m_currentTrackId = QDBusObjectPath(QLatin1String("/org/maui/vvave/playlist/") + QString::number(newTrackPosition)).path(); 0366 0367 emit currentTrackChanged(); 0368 0369 m_metadata = getMetadataOfCurrentTrack(); 0370 signalPropertiesChange(QStringLiteral("Metadata"), Metadata()); 0371 } 0372 0373 QVariantMap MediaPlayer2Player::getMetadataOfCurrentTrack() 0374 { 0375 auto result = QVariantMap(); 0376 0377 if (m_currentTrackId.isEmpty()) { 0378 return {}; 0379 } 0380 0381 result[QStringLiteral("mpris:trackid")] = QVariant::fromValue<QDBusObjectPath>(QDBusObjectPath(m_currentTrackId)); 0382 result[QStringLiteral("mpris:length")] = qlonglong(m_audioPlayer->getDuration()) * 1000; 0383 // convert milli-seconds into micro-seconds 0384 0385 auto track = m_playListControler->currentTrack(); 0386 result[QStringLiteral("xesam:title")] = track["title"].toString(); 0387 result[QStringLiteral("xesam:url")] = track["url"].toString(); 0388 0389 result[QStringLiteral("xesam:album")] = track["album"].toString(); 0390 ; 0391 0392 result[QStringLiteral("xesam:artist")] = QStringList{track["artist"].toString()}; 0393 0394 FMH::MODEL data{{FMH::MODEL_KEY::ARTIST, track["artist"].toString()}, {FMH::MODEL_KEY::ALBUM, track["album"].toString()}}; 0395 0396 if (BAE::artworkCache(data, FMH::MODEL_KEY::ALBUM)) 0397 { 0398 result[QStringLiteral("mpris:artUrl")] = QUrl(data[FMH::MODEL_KEY::ARTWORK]).toString(); 0399 } 0400 0401 return result; 0402 } 0403 0404 int MediaPlayer2Player::mediaPlayerPresent() const 0405 { 0406 return m_mediaPlayerPresent; 0407 } 0408 0409 bool MediaPlayer2Player::showProgressOnTaskBar() const 0410 { 0411 return mShowProgressOnTaskBar; 0412 } 0413 0414 void MediaPlayer2Player::setShowProgressOnTaskBar(bool value) 0415 { 0416 mShowProgressOnTaskBar = value; 0417 0418 QVariantMap parameters; 0419 0420 if (!mShowProgressOnTaskBar || m_audioPlayer->getState() == QMediaPlayer::StoppedState || m_audioPlayer->getDuration() == 0) { 0421 parameters.insert(QStringLiteral("progress-visible"), false); 0422 parameters.insert(QStringLiteral("progress"), 0); 0423 } else { 0424 parameters.insert(QStringLiteral("progress-visible"), true); 0425 parameters.insert(QStringLiteral("progress"), qRound(static_cast<double>(m_position / m_audioPlayer->getDuration())) / 1000.0); 0426 } 0427 0428 mProgressIndicatorSignal.setArguments({QStringLiteral("application://org.maui.vvave.desktop"), parameters}); 0429 0430 QDBusConnection::sessionBus().send(mProgressIndicatorSignal); 0431 } 0432 0433 void MediaPlayer2Player::setMediaPlayerPresent(int status) 0434 { 0435 if (m_mediaPlayerPresent != status) { 0436 m_mediaPlayerPresent = status; 0437 emit mediaPlayerPresentChanged(); 0438 0439 signalPropertiesChange(QStringLiteral("CanGoNext"), CanGoNext()); 0440 signalPropertiesChange(QStringLiteral("CanGoPrevious"), CanGoPrevious()); 0441 signalPropertiesChange(QStringLiteral("CanPause"), CanPause()); 0442 signalPropertiesChange(QStringLiteral("CanPlay"), CanPlay()); 0443 emit canGoNextChanged(); 0444 emit canGoPreviousChanged(); 0445 emit canPauseChanged(); 0446 emit canPlayChanged(); 0447 } 0448 } 0449 0450 void MediaPlayer2Player::signalPropertiesChange(const QString &property, const QVariant &value) 0451 { 0452 QVariantMap properties; 0453 properties[property] = value; 0454 const int ifaceIndex = metaObject()->indexOfClassInfo("D-Bus Interface"); 0455 QDBusMessage msg = QDBusMessage::createSignal(QStringLiteral("/org/mpris/MediaPlayer2"), QStringLiteral("org.freedesktop.DBus.Properties"), QStringLiteral("PropertiesChanged")); 0456 0457 msg << QLatin1String(metaObject()->classInfo(ifaceIndex).value()); 0458 msg << properties; 0459 msg << QStringList(); 0460 0461 QDBusConnection::sessionBus().send(msg); 0462 } 0463 0464 #include "moc_mediaplayer2player.cpp"