File indexing completed on 2024-11-10 05:11:09
0001 /* 0002 * Copyright 2023 by Aditya Mehra <aix.m@outlook.com> 0003 * 0004 * Licensed under the Apache License, Version 2.0 (the "License"); 0005 * you may not use this file except in compliance with the License. 0006 * You may obtain a copy of the License at 0007 * 0008 * http://www.apache.org/licenses/LICENSE-2.0 0009 * 0010 * Unless required by applicable law or agreed to in writing, software 0011 * distributed under the License is distributed on an "AS IS" BASIS, 0012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 0013 * See the License for the specific language governing permissions and 0014 * limitations under the License. 0015 * 0016 */ 0017 0018 #include "mediaservice.h" 0019 0020 MediaService::MediaService(QObject *parent) 0021 : QObject(parent), 0022 m_controller(MycroftController::instance()) 0023 { 0024 m_currentPlaybackState = MediaService::StoppedState; 0025 m_currentMediaState = MediaService::NoMedia; 0026 m_selectedProviderService = MediaService::NoProvider; 0027 0028 if (m_controller->status() == MycroftController::Open){ 0029 connect(m_controller, &MycroftController::intentRecevied, this, 0030 &MediaService::onMainSocketIntentReceived); 0031 } 0032 } 0033 0034 void MediaService::unloadAudioProvider(MediaService::UnloadStateReason reason) 0035 { 0036 m_unloadingAudioService = true; 0037 m_unloadReason = reason; 0038 QObject::disconnect(m_audioProviderService, &AudioProviderService::mediaStateChanged, this, &MediaService::updateMediaStateAudioProvider); 0039 QObject::disconnect(m_audioProviderService, &AudioProviderService::playBackStateChanged, this, &MediaService::updatePlaybackStateAudioProvider); 0040 QObject::disconnect(m_audioProviderService, &AudioProviderService::spectrumChanged, this, &MediaService::updateSpectrum); 0041 QObject::disconnect(m_audioProviderService, &AudioProviderService::durationChanged, this, &MediaService::updateDuration); 0042 QObject::disconnect(m_audioProviderService, &AudioProviderService::positionChanged, this, &MediaService::updatePosition); 0043 QTimer::singleShot(2000, this, [this](){ 0044 m_audioProviderService->deleteLater(); 0045 m_audioProviderService = nullptr; 0046 if(m_unloadReason == MediaService::MediaFinished) { 0047 emitEndOfMedia(); 0048 } 0049 if(m_unloadReason == MediaService::ServiceUnloaded){ 0050 m_selectedProviderService = MediaService::NoProvider; 0051 } 0052 if(m_unloadReason == MediaService::MediaStopped){ 0053 emit positionChanged(0); 0054 emit durationChanged(0); 0055 } 0056 m_audioServiceProviderInitialized = false; 0057 emit audioProviderUnloaded(); 0058 m_unloadingAudioService = false; 0059 }); 0060 } 0061 0062 void MediaService::unloadVideoProvider(MediaService::UnloadStateReason reason) 0063 { 0064 if(!(m_currentPlaybackState == MediaService::StoppedState)){ 0065 m_videoProviderService->mediaStop(); 0066 } 0067 setVideoOutput(nullptr); 0068 setVideoSink(nullptr); 0069 m_unloadingVideoService = true; 0070 m_unloadReason = MediaService::ServiceUnloaded; 0071 emit videoProviderUnloaded(); 0072 m_unloadingVideoService = false; 0073 } 0074 0075 void MediaService::initializeAudioProvider() 0076 { 0077 m_audioProviderService = new AudioProviderService(this); 0078 QObject::connect(m_audioProviderService, &AudioProviderService::mediaStateChanged, this, &MediaService::updateMediaStateAudioProvider); 0079 QObject::connect(m_audioProviderService, &AudioProviderService::playBackStateChanged, this, &MediaService::updatePlaybackStateAudioProvider); 0080 QObject::connect(m_audioProviderService, &AudioProviderService::spectrumChanged, this, &MediaService::updateSpectrum); 0081 QObject::connect(m_audioProviderService, &AudioProviderService::durationChanged, this, &MediaService::updateDuration); 0082 QObject::connect(m_audioProviderService, &AudioProviderService::positionChanged, this, &MediaService::updatePosition); 0083 m_audioServiceProviderInitialized = true; 0084 emit audioProviderInitialized(); 0085 } 0086 0087 void MediaService::initializeVideoProvider() 0088 { 0089 m_videoProviderService = new VideoProviderService(this); 0090 m_videoServiceProviderInitialized = true; 0091 emit videoProviderInitialized(); 0092 } 0093 0094 0095 void MediaService::syncStates() 0096 { 0097 if(m_selectedProviderService == MediaService::AudioProvider) { 0098 m_audioProviderService->syncStates(); 0099 } 0100 if(m_selectedProviderService == MediaService::VideoProvider) { 0101 m_videoProviderService->syncStates(); 0102 } 0103 } 0104 0105 MediaService::PlaybackState MediaService::servicePlayBackState() const 0106 { 0107 return m_currentPlaybackState; 0108 } 0109 0110 MediaService::MediaState MediaService::serviceMediaState() const 0111 { 0112 return m_currentMediaState; 0113 } 0114 0115 void MediaService::mediaLoadUrl(const QString &url, MediaService::ProviderServiceType serviceType) 0116 { 0117 if(serviceType == MediaService::AudioProvider){ 0118 if(!evaluateUrl(url)) { 0119 m_currentMediaState = MediaService::InvalidMedia; 0120 emit mediaStateChanged(m_currentMediaState); 0121 m_currentMediaState = MediaService::NoMedia; 0122 emit mediaStateChanged(m_currentMediaState); 0123 0124 m_mediaStateSync.clear(); 0125 m_mediaStateSync.insert(QStringLiteral("status"), m_currentMediaState); 0126 m_controller->sendRequest(QStringLiteral("gui.player.media.service.current.media.status"), m_mediaStateSync); 0127 return; 0128 } 0129 } 0130 m_loadedUrl = url; 0131 changeProvider(serviceType); 0132 QTimer::singleShot(1000, this, [this](){ 0133 if(m_selectedProviderService == MediaService::AudioProvider) { 0134 if(!m_unloadingAudioService) { 0135 if(m_audioServiceProviderInitialized && (!(m_unloadReason == MediaService::MediaFinished) || !(m_unloadReason == MediaService::MediaStopped))) { 0136 QEventLoop loop; 0137 connect(this, &MediaService::audioProviderUnloaded, &loop, &QEventLoop::quit); 0138 unloadAudioProvider(MediaService::MediaChanged); 0139 loop.exec(); 0140 } 0141 initializeAudioProvider(); 0142 QUrl audioUrl = QUrl::fromUserInput(m_loadedUrl); 0143 m_audioProviderService->mediaPlay(audioUrl); 0144 } 0145 } 0146 if(m_selectedProviderService == MediaService::VideoProvider) { 0147 if(!m_videoServiceProviderInitialized){ 0148 initializeVideoProvider(); 0149 } 0150 QObject::connect(m_videoProviderService, &VideoProviderService::mediaStateChanged, this, &MediaService::updateMediaStateVideoProvider); 0151 QObject::connect(m_videoProviderService, &VideoProviderService::playBackStateChanged, this, &MediaService::updatePlaybackStateVideoProvider); 0152 QObject::connect(m_videoProviderService, &VideoProviderService::durationChanged, this, &MediaService::updateDuration); 0153 QObject::connect(m_videoProviderService, &VideoProviderService::positionChanged, this, &MediaService::updatePosition); 0154 m_videoProviderService->setVideoSink(m_videoSink); 0155 m_videoProviderService->setVideoOutput(m_videoOutput); 0156 QUrl videoUrl = QUrl::fromUserInput(m_loadedUrl); 0157 m_videoProviderService->mediaPlay(videoUrl); 0158 } 0159 }); 0160 } 0161 0162 0163 void MediaService::mediaStop() 0164 { 0165 // Depending on selected service provider call the ServiceProvider.mediaStop() method 0166 if(!m_unloadingAudioService) { 0167 if(m_selectedProviderService == MediaService::AudioProvider) { 0168 if(m_currentPlaybackState != MediaService::StoppedState){ 0169 mediaPause(); 0170 //m_audioProviderService->mediaStop(); 0171 QEventLoop loop; 0172 connect(this, &MediaService::audioProviderUnloaded, &loop, &QEventLoop::quit); 0173 unloadAudioProvider(MediaService::MediaStopped); 0174 loop.exec(); 0175 m_currentPlaybackState = MediaService::StoppedState; 0176 emit playbackStateChanged(m_currentPlaybackState); 0177 m_playbackStateSync.clear(); 0178 m_playbackStateSync.insert(QStringLiteral("state"), m_currentPlaybackState); 0179 m_controller->sendRequest(QStringLiteral("gui.player.media.service.sync.status"), m_playbackStateSync); 0180 } 0181 } 0182 } 0183 if(m_selectedProviderService == MediaService::VideoProvider) { 0184 m_videoProviderService->mediaStop(); 0185 } 0186 } 0187 0188 void MediaService::mediaPause() 0189 { 0190 if(m_selectedProviderService == MediaService::AudioProvider) { 0191 if(!m_unloadingAudioService) { 0192 m_audioProviderService->mediaPause(); 0193 } 0194 } 0195 if(m_selectedProviderService == MediaService::VideoProvider) { 0196 m_videoProviderService->mediaPause(); 0197 } 0198 } 0199 0200 void MediaService::mediaContinue() 0201 { 0202 if(m_selectedProviderService == MediaService::AudioProvider) { 0203 if(!m_unloadingAudioService) { 0204 m_audioProviderService->mediaContinue(); 0205 } 0206 } 0207 if(m_selectedProviderService == MediaService::VideoProvider) { 0208 m_videoProviderService->mediaContinue(); 0209 } 0210 } 0211 0212 void MediaService::mediaRestart() 0213 { 0214 if(m_selectedProviderService == MediaService::AudioProvider) { 0215 if(!m_unloadingAudioService) { 0216 mediaLoadUrl(m_loadedUrl, MediaService::AudioProvider); 0217 } 0218 } 0219 if(m_selectedProviderService == MediaService::VideoProvider) { 0220 m_videoProviderService->mediaRestart(); 0221 } 0222 } 0223 0224 void MediaService::mediaNext() 0225 { 0226 m_controller->sendRequest(QStringLiteral("gui.player.media.service.get.next"), m_emptyData); 0227 } 0228 0229 void MediaService::mediaPrevious() 0230 { 0231 m_controller->sendRequest(QStringLiteral("gui.player.media.service.get.previous"), m_emptyData); 0232 } 0233 0234 void MediaService::mediaRepeat() 0235 { 0236 m_controller->sendRequest(QStringLiteral("gui.player.media.service.get.repeat"), m_emptyData); 0237 } 0238 0239 void MediaService::mediaShuffle() 0240 { 0241 m_controller->sendRequest(QStringLiteral("gui.player.media.service.get.shuffle"), m_emptyData); 0242 } 0243 0244 void MediaService::mediaSeek(qint64 seekValue) 0245 { 0246 if(m_selectedProviderService == MediaService::AudioProvider) { 0247 if(!m_unloadingAudioService) { 0248 if (m_audioServiceProviderInitialized){ 0249 mediaContinue(); 0250 m_audioProviderService->mediaSeek(seekValue); 0251 } 0252 } 0253 } 0254 if(m_selectedProviderService == MediaService::VideoProvider) { 0255 m_videoProviderService->mediaSeek(seekValue); 0256 } 0257 } 0258 0259 QVariant MediaService::requestServiceInfo(QString &serviceInfoType) 0260 { 0261 if(serviceInfoType == QStringLiteral("loadedUrl")){ 0262 return m_loadedUrl; 0263 } 0264 if(serviceInfoType == QStringLiteral("receivedUrl")){ 0265 return m_receivedUrl; 0266 } 0267 if(serviceInfoType == QStringLiteral("artist")){ 0268 return m_artist; 0269 } 0270 if(serviceInfoType == QStringLiteral("album")){ 0271 return m_album; 0272 } 0273 if(serviceInfoType == QStringLiteral("title")){ 0274 return m_title; 0275 } 0276 if(serviceInfoType == QStringLiteral("thumbnail")){ 0277 return m_thumbnail; 0278 } 0279 if(serviceInfoType == QStringLiteral("repeat")){ 0280 return m_repeat; 0281 } 0282 return false; 0283 } 0284 0285 QVariantMap MediaService::requestServiceMetaData() 0286 { 0287 return m_serviceMetaData; 0288 } 0289 0290 QVariantMap MediaService::requestCommonPlayMetaData() 0291 { 0292 QVariantMap cpsMap; 0293 if(!m_artist.isEmpty()){ 0294 cpsMap.insert(QStringLiteral("artist"), m_artist); 0295 }; 0296 if(!m_title.isEmpty()){ 0297 cpsMap.insert(QStringLiteral("title"), m_title); 0298 }; 0299 if(!m_album.isEmpty()){ 0300 cpsMap.insert(QStringLiteral("album"), m_album); 0301 }; 0302 if(!m_thumbnail.isEmpty()){ 0303 cpsMap.insert(QStringLiteral("thumbnail"), m_thumbnail); 0304 }; 0305 return cpsMap; 0306 } 0307 0308 void MediaService::updatePlaybackStateAudioProvider(AudioProviderService::PlaybackState playbackState) 0309 { 0310 switch(playbackState) { 0311 case AudioProviderService::PlayingState: 0312 m_currentPlaybackState = MediaService::PlayingState; 0313 break; 0314 case AudioProviderService::PausedState: 0315 m_currentPlaybackState = MediaService::PausedState; 0316 break; 0317 case AudioProviderService::StoppedState: 0318 m_currentPlaybackState = MediaService::StoppedState; 0319 break; 0320 } 0321 emit playbackStateChanged(m_currentPlaybackState); 0322 0323 m_playbackStateSync.clear(); 0324 m_playbackStateSync.insert(QStringLiteral("state"), m_currentPlaybackState); 0325 m_controller->sendRequest(QStringLiteral("gui.player.media.service.sync.status"), m_playbackStateSync); 0326 } 0327 0328 void MediaService::updateMediaStateAudioProvider(AudioProviderService::MediaState mediaState) 0329 { 0330 switch(mediaState) { 0331 case AudioProviderService::NoMedia: 0332 m_currentMediaState = MediaService::NoMedia; 0333 break; 0334 case AudioProviderService::LoadingMedia: 0335 m_currentMediaState = MediaService::LoadingMedia; 0336 break; 0337 case AudioProviderService::LoadedMedia: 0338 m_currentMediaState = MediaService::LoadedMedia; 0339 break; 0340 case AudioProviderService::StalledMedia: 0341 m_currentMediaState = MediaService::StalledMedia; 0342 break; 0343 case AudioProviderService::BufferingMedia: 0344 m_currentMediaState = MediaService::BufferingMedia; 0345 break; 0346 case AudioProviderService::BufferedMedia: 0347 m_currentMediaState = MediaService::BufferedMedia; 0348 break; 0349 case AudioProviderService::EndOfMedia: 0350 audioServiceEndOfMedia(); 0351 break; 0352 case AudioProviderService::InvalidMedia: 0353 m_currentMediaState = MediaService::InvalidMedia; 0354 break; 0355 } 0356 emit mediaStateChanged(m_currentMediaState); 0357 0358 m_mediaStateSync.clear(); 0359 m_mediaStateSync.insert(QStringLiteral("status"), m_currentMediaState); 0360 m_controller->sendRequest(QStringLiteral("gui.player.media.service.current.media.status"), m_mediaStateSync); 0361 } 0362 0363 void MediaService::updatePlaybackStateVideoProvider(VideoProviderService::PlaybackState playbackState) 0364 { 0365 switch(playbackState) { 0366 case VideoProviderService::PlayingState: 0367 m_currentPlaybackState = MediaService::PlayingState; 0368 break; 0369 case VideoProviderService::PausedState: 0370 m_currentPlaybackState = MediaService::PausedState; 0371 break; 0372 case VideoProviderService::StoppedState: 0373 m_currentPlaybackState = MediaService::StoppedState; 0374 break; 0375 } 0376 emit playbackStateChanged(m_currentPlaybackState); 0377 0378 m_playbackStateSync.clear(); 0379 m_playbackStateSync.insert(QStringLiteral("state"), m_currentPlaybackState); 0380 m_controller->sendRequest(QStringLiteral("gui.player.media.service.sync.status"), m_playbackStateSync); 0381 } 0382 0383 void MediaService::updateMediaStateVideoProvider(VideoProviderService::MediaState mediaState) 0384 { 0385 switch(mediaState) { 0386 case VideoProviderService::NoMedia: 0387 m_currentMediaState = MediaService::NoMedia; 0388 break; 0389 case VideoProviderService::LoadingMedia: 0390 m_currentMediaState = MediaService::LoadingMedia; 0391 break; 0392 case VideoProviderService::LoadedMedia: 0393 m_currentMediaState = MediaService::LoadedMedia; 0394 break; 0395 case VideoProviderService::StalledMedia: 0396 m_currentMediaState = MediaService::StalledMedia; 0397 break; 0398 case VideoProviderService::BufferingMedia: 0399 m_currentMediaState = MediaService::BufferingMedia; 0400 break; 0401 case VideoProviderService::BufferedMedia: 0402 m_currentMediaState = MediaService::BufferedMedia; 0403 break; 0404 case VideoProviderService::EndOfMedia: 0405 mediaStop(); 0406 QTimer::singleShot(1000, this, SLOT(videoServiceEndOfMedia())); 0407 break; 0408 case VideoProviderService::InvalidMedia: 0409 m_currentMediaState = MediaService::InvalidMedia; 0410 break; 0411 } 0412 emit mediaStateChanged(m_currentMediaState); 0413 0414 m_mediaStateSync.clear(); 0415 m_mediaStateSync.insert(QStringLiteral("status"), m_currentMediaState); 0416 m_controller->sendRequest(QStringLiteral("gui.player.media.service.current.media.status"), m_mediaStateSync); 0417 } 0418 0419 QVector<double> MediaService::spectrum() const 0420 { 0421 return m_spectrum; 0422 } 0423 0424 void MediaService::updateSpectrum(QVector<double> spectrum) 0425 { 0426 m_spectrum = spectrum; 0427 emit spectrumChanged(m_spectrum); 0428 } 0429 0430 void MediaService::updatePosition(qint64 position) 0431 { 0432 emit positionChanged(position); 0433 } 0434 0435 void MediaService::updateDuration(qint64 duration) 0436 { 0437 emit durationChanged(duration); 0438 } 0439 0440 bool MediaService::evaluateUrl(const QString& url) 0441 { 0442 QUrl mediaUrl(url); 0443 0444 if (!mediaUrl.isValid()) { 0445 return false; 0446 } 0447 0448 if (mediaUrl.isLocalFile()) { 0449 return true; 0450 } 0451 0452 QNetworkAccessManager networkManager; 0453 QNetworkRequest request(mediaUrl); 0454 QNetworkReply* reply = networkManager.head(request); 0455 QEventLoop loop; 0456 0457 QObject::connect(reply, &QNetworkReply::finished, &loop, &QEventLoop::quit); 0458 loop.exec(); 0459 0460 bool isMediaUrl = (reply->error() == QNetworkReply::NoError); 0461 0462 reply->deleteLater(); 0463 0464 return isMediaUrl; 0465 } 0466 0467 void MediaService::audioServiceEndOfMedia() 0468 { 0469 if(!m_unloadingAudioService) { 0470 unloadAudioProvider(MediaService::MediaFinished); 0471 } 0472 } 0473 0474 void MediaService::videoServiceEndOfMedia() 0475 { 0476 m_currentMediaState = MediaService::EndOfMedia; 0477 emit mediaStateChanged(m_currentMediaState); 0478 0479 m_mediaStateSync.clear(); 0480 m_mediaStateSync.insert(QStringLiteral("status"), m_currentMediaState); 0481 m_controller->sendRequest(QStringLiteral("gui.player.media.service.current.media.status"), m_mediaStateSync); 0482 } 0483 0484 void MediaService::emitEndOfMedia() 0485 { 0486 m_currentMediaState = MediaService::EndOfMedia; 0487 emit mediaStateChanged(m_currentMediaState); 0488 0489 m_mediaStateSync.clear(); 0490 m_mediaStateSync.insert(QStringLiteral("status"), m_currentMediaState); 0491 m_controller->sendRequest(QStringLiteral("gui.player.media.service.current.media.status"), m_mediaStateSync); 0492 } 0493 0494 void MediaService::changeProvider(MediaService::ProviderServiceType serviceType) 0495 { 0496 if (m_selectedProviderService == serviceType) { 0497 return; 0498 } 0499 if(m_selectedProviderService == MediaService::VideoProvider){ 0500 unloadVideoProvider(MediaService::ServiceUnloaded); 0501 } 0502 0503 if(m_selectedProviderService == MediaService::AudioProvider){ 0504 QEventLoop loop; 0505 loop.connect(this, &MediaService::audioProviderUnloaded, &loop, &QEventLoop::quit); 0506 unloadAudioProvider(MediaService::ServiceUnloaded); 0507 loop.exec(); 0508 } 0509 0510 m_selectedProviderService = serviceType; 0511 emit providerServiceTypeChanged(m_selectedProviderService); 0512 } 0513 0514 void MediaService::onMainSocketIntentReceived(const QString &type, const QVariantMap &data) 0515 { 0516 0517 if(type == QStringLiteral("gui.player.media.service.play")) { 0518 m_receivedUrl = data[QStringLiteral("track")].toString(); 0519 m_repeat = data[QStringLiteral("repeat")].toBool(); 0520 0521 emit mediaLoadUrlRequested(); 0522 } 0523 0524 if(type == QStringLiteral("gui.player.media.service.pause")) { 0525 mediaPause(); 0526 emit mediaPauseRequested(); 0527 } 0528 0529 if(type == QStringLiteral("gui.player.media.service.stop")) { 0530 mediaStop(); 0531 emit mediaStopRequested(); 0532 } 0533 0534 if(type == QStringLiteral("gui.player.media.service.resume")) { 0535 mediaContinue(); 0536 emit mediaContinueRequested(); 0537 } 0538 0539 if(type == QStringLiteral("gui.player.media.service.set.meta")) { 0540 QString metaVal; 0541 0542 if(data.contains(QStringLiteral("artist"))){ 0543 metaVal = data[QStringLiteral("artist")].toString(); 0544 if(!metaVal.isEmpty()){ 0545 m_artist = metaVal; 0546 } 0547 } 0548 0549 if(data.contains(QStringLiteral("album"))){ 0550 metaVal = data[QStringLiteral("album")].toString(); 0551 if(!metaVal.isEmpty()){ 0552 m_album = metaVal; 0553 } 0554 } 0555 0556 if(data.contains(QStringLiteral("title"))){ 0557 metaVal = data[QStringLiteral("title")].toString(); 0558 if(!metaVal.isEmpty()){ 0559 m_title = metaVal; 0560 } 0561 } 0562 0563 if(data.contains(QStringLiteral("track"))){ 0564 metaVal = data[QStringLiteral("track")].toString(); 0565 if(!metaVal.isEmpty()){ 0566 m_title = metaVal; 0567 } 0568 } 0569 0570 if(data.contains(QStringLiteral("image"))){ 0571 metaVal = data[QStringLiteral("image")].toString(); 0572 if(!metaVal.isEmpty()){ 0573 m_thumbnail = metaVal; 0574 } 0575 } 0576 emit metaDataReceived(); 0577 } 0578 } 0579 0580 QVideoSink* MediaService::videoSink() const 0581 { 0582 return m_videoSink; 0583 } 0584 0585 void MediaService::setVideoSink(QVideoSink * newVideoSink) 0586 { 0587 if(m_videoSink == newVideoSink) 0588 return; 0589 0590 m_videoSink = newVideoSink; 0591 0592 emit videoSinkChanged(); 0593 } 0594 0595 QObject* MediaService::videoOutput() const 0596 { 0597 return m_videoOutput; 0598 } 0599 0600 void MediaService::setVideoOutput(QObject * newVideoOutput) 0601 { 0602 if(m_videoOutput == newVideoOutput) 0603 return; 0604 0605 m_videoOutput = newVideoOutput; 0606 0607 emit videoOutputChanged(); 0608 }