File indexing completed on 2025-01-19 04:24:32

0001 /****************************************************************************************
0002  * Copyright (c) 2010 Andrew Coder <andrew.coder@gmail.com>                             *
0003  *                                                                                      *
0004  * This program is free software; you can redistribute it and/or modify it under        *
0005  * the terms of the GNU General Public License as published by the Free Software        *
0006  * Foundation; either version 2 of the License, or (at your option) any later           *
0007  * version.                                                                             *
0008  *                                                                                      *
0009  * This program is distributed in the hope that it will be useful, but WITHOUT ANY      *
0010  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A      *
0011  * PARTICULAR PURPOSE. See the GNU General Public License for more details.             *
0012  *                                                                                      *
0013  * You should have received a copy of the GNU General Public License along with         *
0014  * this program.  If not, see <http://www.gnu.org/licenses/>.                           *
0015  ****************************************************************************************/
0016 
0017 #define DEBUG_PREFIX "Playdar::Controller"
0018 
0019 #include "Controller.h"
0020 
0021 #include "Query.h"
0022 #include "core/support/Debug.h"
0023 
0024 #include <QJsonDocument>
0025 #include <QJsonObject>
0026 #include <QJsonParseError>
0027 #include <QMap>
0028 #include <QString>
0029 #include <QUrl>
0030 #include <QUrlQuery>
0031 #include <QVariant>
0032 #include <QVariantMap>
0033 
0034 #include <KIO/Job>
0035 
0036 
0037 namespace Playdar {
0038     
0039     Controller::Controller( bool queriesShouldWaitForSolutions )
0040         : m_errorState( ErrorState( NoError ) )
0041         , m_queriesShouldWaitForSolutions( queriesShouldWaitForSolutions )
0042         
0043     {
0044         DEBUG_BLOCK
0045     }
0046     
0047     Controller::~Controller()
0048     {
0049         DEBUG_BLOCK
0050     }
0051     
0052     void
0053     Controller::resolve( const QString &artist, const QString &album, const QString &title )
0054     {
0055         DEBUG_BLOCK
0056         
0057         debug() << "Querying playdar for artist name = " << artist
0058                 << ", album name = " << album << ", and track title = " << title;
0059         
0060         const QString baseUrl( "http://localhost:60210/api/?method=resolve" );
0061         QUrl resolveUrl( baseUrl );
0062         QUrlQuery query( resolveUrl );
0063         query.addQueryItem( QString( "artist" ), artist );
0064         query.addQueryItem( QString( "album" ), album );
0065         query.addQueryItem( QString( "track" ), title );
0066         resolveUrl.setQuery( query );
0067         
0068         debug() << "Starting storedGetJob for " << resolveUrl.url();
0069         
0070         KJob* resolveJob = KIO::storedGet( resolveUrl, KIO::Reload, KIO::HideProgressInfo );
0071         connect( resolveJob, &KJob::result, this, &Controller::processQuery );
0072     }
0073     
0074     void
0075     Controller::getResults( Query* query )
0076     {
0077         DEBUG_BLOCK
0078         
0079         const QString baseUrl( "http://localhost:60210/api/?method=get_results" );
0080         QUrl getResultsUrl( baseUrl );
0081         QUrlQuery q( getResultsUrl );
0082 
0083         q.addQueryItem( QString( "qid" ), query->qid() );
0084         getResultsUrl.setQuery( q );
0085 
0086         KJob* getResultsJob = KIO::storedGet( getResultsUrl, KIO::Reload, KIO::HideProgressInfo );
0087         connect( getResultsJob, &KJob::result, query, &Query::receiveResults );
0088     }
0089     
0090     void
0091     Controller::getResultsLongPoll( Query* query )
0092     {
0093         DEBUG_BLOCK
0094         
0095         const QString baseUrl( "http://localhost:60210/api/?method=get_results_long" );
0096         QUrl getResultsUrl( baseUrl );
0097         QUrlQuery q( getResultsUrl );
0098 
0099         q.addQueryItem( QString( "qid" ), query->qid() );
0100         getResultsUrl.setQuery( q );
0101 
0102         KJob* getResultsJob = KIO::storedGet( getResultsUrl, KIO::Reload, KIO::HideProgressInfo );
0103         connect( getResultsJob, &KJob::result, query, &Query::receiveResults );
0104     }
0105     
0106     QUrl
0107     Controller::urlForSid( const QString &sid ) const
0108     {
0109         DEBUG_BLOCK
0110         
0111         const QString baseUrl( "http://localhost:60210/sid/" );
0112         QUrl playableUrl( baseUrl );
0113         
0114         playableUrl = playableUrl.adjusted(QUrl::StripTrailingSlash);
0115         playableUrl.setPath(playableUrl.path() + QLatin1Char('/') + ( sid ));
0116         
0117         return playableUrl;
0118     }
0119     
0120     void
0121     Controller::status()
0122     {
0123         // DEBUG_BLOCK
0124         
0125         const QString baseUrl( "http://localhost:60210/api/?method=stat" );
0126         QUrl statusUrl( baseUrl );
0127         
0128         KJob* statusJob = KIO::storedGet( statusUrl, KIO::Reload, KIO::HideProgressInfo );
0129         connect( statusJob, &KJob::result, this, &Controller::processStatus );
0130     }
0131     
0132     void
0133     Controller::processStatus( KJob *statusJob )
0134     {
0135         if( statusJob->error() != 0 ) {
0136             // debug() << "Error getting status from Playdar";
0137             Q_EMIT playdarError( Playdar::Controller::ErrorState( ExternalError ) );
0138             return;
0139         }
0140         
0141         debug() << "Processing received JSON data...";
0142         KIO::StoredTransferJob* storedStatusJob = static_cast<KIO::StoredTransferJob*>( statusJob );
0143         
0144         QJsonParseError err;
0145         auto doc = QJsonDocument::fromJson( storedStatusJob->data(), &err );
0146 
0147         if ( err.error != QJsonParseError::NoError )
0148             debug() << "Error parsing JSON Data:" << err.errorString();
0149 
0150         if( !doc.isObject() )
0151         {
0152             debug() << "Parsed Json data is not an object";
0153             return;
0154         }
0155 
0156         auto object = doc.object();
0157         
0158         if( !object.contains("name") )
0159         {
0160             debug() << "Expected a service name from Playdar, received none";
0161             Q_EMIT playdarError( Playdar::Controller::ErrorState( MissingServiceName ) );
0162             return;
0163         }
0164         if( object.value("name").toString() != QStringLiteral( "playdar" ) )
0165         {
0166             debug() << "Expected Playdar, got response from some other service";
0167             Q_EMIT playdarError( Playdar::Controller::ErrorState( WrongServiceName ) );
0168             return;
0169         }
0170         
0171         debug() << "All good! Emitting playdarReady()";
0172         Q_EMIT playdarReady();
0173     }
0174     
0175     void
0176     Controller::processQuery( KJob *queryJob )
0177     {
0178         DEBUG_BLOCK
0179         
0180         if( queryJob->error() != 0 )
0181         {
0182             debug() << "Error getting qid from Playdar";
0183             Q_EMIT playdarError( Playdar::Controller::ErrorState( ExternalError ) );
0184             return;
0185         }
0186         
0187         debug() << "Processing received JSON data...";
0188         KIO::StoredTransferJob* storedQueryJob =
0189             static_cast<KIO::StoredTransferJob*>( queryJob );
0190         
0191         QJsonParseError err;
0192         auto doc = QJsonDocument::fromJson( storedQueryJob->data(), &err );
0193 
0194         if ( err.error != QJsonParseError::NoError )
0195             debug() << "Error parsing JSON Data:" << err.errorString();
0196 
0197         if( !doc.isObject() )
0198         {
0199             debug() << "Parsed Json data is not an object";
0200             return;
0201         }
0202 
0203         auto object = doc.object();
0204 
0205         if( !object.contains( "qid" ) )
0206         {
0207             debug() << "Expected qid in Playdar's response, but didn't get it";
0208             Q_EMIT playdarError( Playdar::Controller::ErrorState( MissingQid ) );
0209             return;
0210         }
0211         
0212         Query* query = new Query( object.value( "qid" ).toString(), this, m_queriesShouldWaitForSolutions );
0213         
0214         debug() << "All good! Emitting queryReady( Playdar::Query* )...";
0215         Q_EMIT queryReady( query );
0216         
0217         connect( query, &Query::playdarError, this, &Controller::playdarError );
0218     }
0219 }