2010-10-02 18:23:33 +02:00
|
|
|
/****************************************************************************************
|
|
|
|
* Copyright (c) 2010 Leo Franchi <lfranchi@kde.org> *
|
2011-10-26 16:45:20 +02:00
|
|
|
* Copyright (c) 2011 Jeff Mitchell <mitchell@kde.org> *
|
2010-10-02 18:23:33 +02:00
|
|
|
* *
|
|
|
|
* This program is free software; you can redistribute it and/or modify it under *
|
|
|
|
* the terms of the GNU General Public License as published by the Free Software *
|
|
|
|
* Foundation; either version 2 of the License, or (at your option) any later *
|
|
|
|
* version. *
|
|
|
|
* *
|
|
|
|
* This program is distributed in the hope that it will be useful, but WITHOUT ANY *
|
|
|
|
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A *
|
|
|
|
* PARTICULAR PURPOSE. See the GNU General Public License for more details. *
|
|
|
|
* *
|
|
|
|
* You should have received a copy of the GNU General Public License along with *
|
|
|
|
* this program. If not, see <http://www.gnu.org/licenses/>. *
|
|
|
|
****************************************************************************************/
|
|
|
|
|
|
|
|
#include "Config.h"
|
|
|
|
|
|
|
|
#include <QNetworkAccessManager>
|
2011-10-26 16:45:20 +02:00
|
|
|
#include <QThread>
|
2010-10-02 18:23:33 +02:00
|
|
|
#include <QDebug>
|
2011-10-26 16:45:20 +02:00
|
|
|
#include <QMutex>
|
2010-10-02 18:23:33 +02:00
|
|
|
|
|
|
|
Echonest::Config* Echonest::Config::s_instance = 0;
|
|
|
|
|
|
|
|
QUrl Echonest::baseUrl()
|
|
|
|
{
|
|
|
|
QUrl url;
|
|
|
|
url.setScheme( QLatin1String( "http" ) );
|
|
|
|
url.setHost( QLatin1String( "developer.echonest.com" ) );
|
|
|
|
return url;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
QUrl Echonest::baseGetQuery(const QByteArray& type, const QByteArray& method)
|
|
|
|
{
|
|
|
|
QUrl url = baseUrl();
|
|
|
|
url.setPath( QString::fromLatin1( "/api/v4/%1/%2" ).arg( QLatin1String( type ) ).arg( QLatin1String( method ) ) );
|
|
|
|
url.addEncodedQueryItem( "api_key", Echonest::Config::instance()->apiKey() );
|
|
|
|
url.addEncodedQueryItem( "format", "xml" );
|
|
|
|
return url;
|
|
|
|
}
|
|
|
|
|
|
|
|
Echonest::ParseError::ParseError(Echonest::ErrorType error): exception()
|
|
|
|
{
|
|
|
|
type = error;
|
|
|
|
}
|
|
|
|
|
2011-10-26 16:45:20 +02:00
|
|
|
Echonest::ParseError::ParseError(Echonest::ErrorType error, const QString& text): exception()
|
|
|
|
{
|
|
|
|
type = error;
|
|
|
|
extraText = text;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-10-02 18:23:33 +02:00
|
|
|
Echonest::ParseError::~ParseError() throw()
|
|
|
|
{}
|
|
|
|
|
2010-10-04 23:49:56 +02:00
|
|
|
Echonest::ErrorType Echonest::ParseError::errorType() const throw()
|
2010-10-02 18:23:33 +02:00
|
|
|
{
|
|
|
|
return type;
|
|
|
|
}
|
|
|
|
|
2010-10-04 23:49:56 +02:00
|
|
|
void Echonest::ParseError::setNetworkError( QNetworkReply::NetworkError error ) throw()
|
2010-10-02 18:23:33 +02:00
|
|
|
{
|
|
|
|
nError = error;
|
|
|
|
}
|
|
|
|
|
2010-10-04 23:49:56 +02:00
|
|
|
const char* Echonest::ParseError::what() const throw()
|
|
|
|
{
|
2011-10-26 16:45:20 +02:00
|
|
|
|
|
|
|
// If we have specific error text, return that first
|
|
|
|
if( !extraText.isEmpty() )
|
|
|
|
return extraText.toLatin1().constData();
|
|
|
|
|
2010-10-04 23:49:56 +02:00
|
|
|
switch( type )
|
|
|
|
{
|
|
|
|
case UnknownError:
|
|
|
|
return "Unknown Echo Nest Error";
|
|
|
|
case NoError:
|
|
|
|
return "No Error";
|
|
|
|
case MissingAPIKey:
|
|
|
|
return "Missing Echo Nest API Key";
|
|
|
|
case NotAllowed:
|
|
|
|
return "Method not allowed";
|
|
|
|
case RateLimitExceeded:
|
|
|
|
return "Rate limit exceeded";
|
|
|
|
case MissingParameter:
|
|
|
|
return "Missing parameter";
|
|
|
|
case InvalidParameter:
|
|
|
|
return "Invalid parameter";
|
|
|
|
case UnfinishedQuery:
|
|
|
|
return "Unfinished query object";
|
|
|
|
case EmptyResult:
|
|
|
|
return "No results";
|
|
|
|
case NetworkError:
|
|
|
|
return "Network Error";
|
|
|
|
case UnknownParseError:
|
|
|
|
return "Unknown Parse Error";
|
|
|
|
}
|
|
|
|
return "";
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
QNetworkReply::NetworkError Echonest::ParseError::networkError() const throw()
|
2010-10-02 18:23:33 +02:00
|
|
|
{
|
|
|
|
return nError;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class Echonest::ConfigPrivate {
|
|
|
|
public:
|
2011-10-26 16:45:20 +02:00
|
|
|
ConfigPrivate()
|
2010-10-02 18:23:33 +02:00
|
|
|
{
|
2011-10-26 16:45:20 +02:00
|
|
|
threadNamHash[ QThread::currentThread() ] = new QNetworkAccessManager();
|
2010-10-02 18:23:33 +02:00
|
|
|
}
|
2011-10-26 16:45:20 +02:00
|
|
|
|
2010-10-02 18:23:33 +02:00
|
|
|
~ConfigPrivate()
|
|
|
|
{
|
2011-10-26 16:45:20 +02:00
|
|
|
QThread *currThread = QThread::currentThread();
|
|
|
|
if( threadNamHash.contains( currThread ) )
|
|
|
|
{
|
|
|
|
if ( ourNamSet.contains( currThread ) )
|
|
|
|
delete threadNamHash[ currThread ];
|
|
|
|
threadNamHash.remove( currThread );
|
|
|
|
ourNamSet.remove( currThread );
|
|
|
|
}
|
2010-10-02 18:23:33 +02:00
|
|
|
}
|
2011-10-26 16:45:20 +02:00
|
|
|
|
|
|
|
QMutex accessMutex;
|
|
|
|
QHash< QThread*, QNetworkAccessManager* > threadNamHash;
|
|
|
|
QSet< QThread* > ourNamSet;
|
2010-10-02 18:23:33 +02:00
|
|
|
QByteArray apikey;
|
|
|
|
};
|
|
|
|
|
|
|
|
Echonest::Config::Config()
|
|
|
|
: d( new Echonest::ConfigPrivate )
|
|
|
|
{
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
Echonest::Config::~Config()
|
|
|
|
{
|
|
|
|
delete d;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Echonest::Config::setAPIKey(const QByteArray& apiKey)
|
|
|
|
{
|
|
|
|
d->apikey = apiKey;
|
|
|
|
}
|
|
|
|
|
|
|
|
QByteArray Echonest::Config::apiKey() const
|
|
|
|
{
|
|
|
|
return d->apikey;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Echonest::Config::setNetworkAccessManager(QNetworkAccessManager* nam)
|
|
|
|
{
|
|
|
|
if( !nam )
|
|
|
|
return;
|
2011-10-26 16:45:20 +02:00
|
|
|
|
|
|
|
QMutexLocker l( &d->accessMutex );
|
|
|
|
QThread* currThread = QThread::currentThread();
|
|
|
|
QNetworkAccessManager* oldNam = 0;
|
|
|
|
if( d->threadNamHash.contains( currThread ) && d->ourNamSet.contains( currThread ) )
|
|
|
|
oldNam = d->threadNamHash[ currThread ];
|
|
|
|
|
|
|
|
if( oldNam == nam )
|
2011-11-23 16:10:33 +01:00
|
|
|
{
|
|
|
|
// If we're being passed back our own NAM, assume they want to
|
|
|
|
// ensure that we don't delete it out from under them
|
|
|
|
d->ourNamSet.remove( currThread );
|
2011-10-26 16:45:20 +02:00
|
|
|
return;
|
2011-11-23 16:10:33 +01:00
|
|
|
}
|
2011-10-26 16:45:20 +02:00
|
|
|
|
|
|
|
d->threadNamHash[ currThread ] = nam;
|
|
|
|
d->ourNamSet.remove( currThread );
|
|
|
|
|
|
|
|
if( oldNam )
|
|
|
|
delete oldNam;
|
2010-10-02 18:23:33 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
QNetworkAccessManager* Echonest::Config::nam() const
|
|
|
|
{
|
2011-10-26 16:45:20 +02:00
|
|
|
QMutexLocker l( &d->accessMutex );
|
|
|
|
QThread* currThread = QThread::currentThread();
|
|
|
|
if( !d->threadNamHash.contains( currThread ) )
|
|
|
|
{
|
|
|
|
QNetworkAccessManager *newNam = new QNetworkAccessManager();
|
|
|
|
d->threadNamHash[ currThread ] = newNam;
|
|
|
|
d->ourNamSet.insert( currThread );
|
|
|
|
return newNam;
|
|
|
|
}
|
|
|
|
|
|
|
|
return d->threadNamHash[ currThread ];
|
2010-10-02 18:23:33 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
Echonest::Config* Echonest::Config::instance() {
|
|
|
|
if ( !s_instance ) {
|
|
|
|
s_instance = new Config;
|
|
|
|
}
|
|
|
|
|
|
|
|
return s_instance;
|
|
|
|
}
|