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 }