Bump libechonest to 1.2.0

This commit is contained in:
John Maguire 2011-10-26 16:45:20 +02:00
parent 4ba3cc9563
commit ba363fa475
40 changed files with 4045 additions and 530 deletions

View File

@ -19,27 +19,41 @@
#include "ArtistTypes.h"
#include "Parsing_p.h"
#include <QtNetwork/QNetworkRequest>
#include <QtNetwork/QNetworkReply>
Echonest::Artist::Artist()
: d( new ArtistData )
{
init();
}
Echonest::Artist::Artist( const QByteArray& id, const QString& name )
: d( new ArtistData )
{
init();
d->id = id;
d->name = name;
}
Echonest::Artist::Artist(const QString& name)
Echonest::Artist::Artist( const QString& name )
: d( new ArtistData )
{
init();
setName( name );
}
Echonest::Artist::Artist( const QByteArray& id )
: d( new ArtistData )
{
init();
setId( id );
}
Echonest::Artist::Artist(const Echonest::Artist& other)
: d( other.d )
{}
{
init();
}
Echonest::Artist& Echonest::Artist::operator=(const Echonest::Artist& artist)
{
@ -52,6 +66,10 @@ Echonest::Artist::~Artist()
}
void Echonest::Artist::init()
{
qRegisterMetaType<Echonest::Artist>("Echonest::Artist");
}
QByteArray Echonest::Artist::id() const
{
@ -246,6 +264,15 @@ Echonest::VideoList Echonest::Artist::videos() const
return d->videos;
}
Echonest::ForeignIds Echonest::Artist::foreignIds() const
{
return d->foreign_ids;
}
void Echonest::Artist::setForeignIds(const Echonest::ForeignIds& ids)
{
d->foreign_ids = ids;
}
QNetworkReply* Echonest::Artist::fetchAudio(int numResults, int offset) const
{
@ -258,7 +285,7 @@ QNetworkReply* Echonest::Artist::fetchBiographies(const QString& license, int nu
QUrl url = setupQuery( "biographies", numResults, offset );
if( !license.isEmpty() )
url.addQueryItem( QLatin1String( "license" ), license );
return Echonest::Config::instance()->nam()->get( QNetworkRequest( url ) );
}
@ -267,14 +294,14 @@ QNetworkReply* Echonest::Artist::fetchBlogs( bool highRelevanceOnly, int numResu
QUrl url = setupQuery( "blogs", numResults, offset );
if( highRelevanceOnly ) // false is default
url.addEncodedQueryItem( "high_relevance", "true" );
return Echonest::Config::instance()->nam()->get( QNetworkRequest( url ) );
}
QNetworkReply* Echonest::Artist::fetchFamiliarity() const
{
QUrl url = setupQuery( "familiarity", 0, -1 );
return Echonest::Config::instance()->nam()->get( QNetworkRequest( url ) );
}
@ -283,7 +310,7 @@ QNetworkReply* Echonest::Artist::fetchHotttnesss(const QString& type) const
QUrl url = setupQuery( "hotttnesss", 0, -1 );
if( type != QLatin1String( "normal" ) )
url.addQueryItem( QLatin1String( "type" ), type );
return Echonest::Config::instance()->nam()->get( QNetworkRequest( url ) );
}
@ -292,15 +319,15 @@ QNetworkReply* Echonest::Artist::fetchImages( const QString& license, int numRes
QUrl url = setupQuery( "images", numResults, offset );
if( !license.isEmpty() )
url.addQueryItem( QLatin1String( "license" ), license );
return Echonest::Config::instance()->nam()->get( QNetworkRequest( url ) );
}
QNetworkReply* Echonest::Artist::fetchProfile(Echonest::Artist::ArtistInformation information) const
QNetworkReply* Echonest::Artist::fetchProfile(Echonest::ArtistInformation information) const
{
QUrl url = setupQuery( "profile", 0, -1 );
addQueryInformation( url, information );
return Echonest::Config::instance()->nam()->get( QNetworkRequest( url ) );
}
@ -309,41 +336,38 @@ QNetworkReply* Echonest::Artist::fetchNews( bool highRelevanceOnly, int numResul
QUrl url = setupQuery( "news", numResults, offset );
if( highRelevanceOnly ) // false is default
url.addEncodedQueryItem( "high_relevance", "true" );
return Echonest::Config::instance()->nam()->get( QNetworkRequest( url ) );
}
QNetworkReply* Echonest::Artist::fetchReviews(int numResults, int offset) const
{
QUrl url = setupQuery( "reviews", numResults, offset );
return Echonest::Config::instance()->nam()->get( QNetworkRequest( url ) );
}
QNetworkReply* Echonest::Artist::fetchSimilar(const Echonest::Artist::SearchParams& params, Echonest::Artist::ArtistInformation information, int numResults, int offset )
QNetworkReply* Echonest::Artist::fetchSimilar(const Echonest::Artist::SearchParams& params, Echonest::ArtistInformation information, int numResults, int offset )
{
QUrl url = Echonest::baseGetQuery( "artist", "similar" );
addQueryInformation( url, information );
if( numResults > 0 )
url.addEncodedQueryItem( "results", QByteArray::number( numResults ) );
if( offset >= 0 )
if( offset >= 0 )
url.addEncodedQueryItem( "start", QByteArray::number( offset ) );
Echonest::Artist::SearchParams::const_iterator iter = params.constBegin();
for( ; iter < params.constEnd(); ++iter )
url.addQueryItem( QLatin1String( searchParamToString( iter->first ) ), iter->second.toString().replace( QLatin1Char( ' ' ), QLatin1Char( '+' ) ) );
return Echonest::Config::instance()->nam()->get( QNetworkRequest( url ) );
}
QNetworkReply* Echonest::Artist::fetchSongs( Echonest::Artist::ArtistInformation idspace, bool limitToIdSpace, int numResults, int offset ) const
QNetworkReply* Echonest::Artist::fetchSongs( int numResults, int offset ) const
{
QUrl url = setupQuery( "songs", numResults, offset );
addQueryInformation( url, idspace );
if( limitToIdSpace )
url.addEncodedQueryItem( "limit", "true" );
return Echonest::Config::instance()->nam()->get( QNetworkRequest( url ) );
}
@ -354,7 +378,7 @@ QNetworkReply* Echonest::Artist::fetchTerms( Echonest::Artist::TermSorting sorti
url.addEncodedQueryItem( "sort", "weight" );
else if( sorting == Echonest::Artist::Frequency )
url.addEncodedQueryItem( "sort", "frequency" );
return Echonest::Config::instance()->nam()->get( QNetworkRequest( url ) );
}
@ -369,35 +393,35 @@ QNetworkReply* Echonest::Artist::fetchUrls() const
QNetworkReply* Echonest::Artist::fetchVideo(int numResults, int offset) const
{
QUrl url = setupQuery( "video", numResults, offset );
return Echonest::Config::instance()->nam()->get( QNetworkRequest( url ) );
}
QNetworkReply* Echonest::Artist::search(const Echonest::Artist::SearchParams& params, Echonest::Artist::ArtistInformation information, bool limit)
QNetworkReply* Echonest::Artist::search(const Echonest::Artist::SearchParams& params, Echonest::ArtistInformation information, bool limit)
{
QUrl url = Echonest::baseGetQuery( "artist", "search" );
Echonest::Artist::SearchParams::const_iterator iter = params.constBegin();
for( ; iter < params.constEnd(); ++iter )
url.addQueryItem( QLatin1String( searchParamToString( iter->first ) ), iter->second.toString().replace( QLatin1Char( ' ' ), QLatin1Char( '+' ) ) );
url.addEncodedQueryItem( "limit", limit ? "true" : "false" );
addQueryInformation( url, information );
return Echonest::Config::instance()->nam()->get( QNetworkRequest( url ) );
}
QNetworkReply* Echonest::Artist::topHottt(Echonest::Artist::ArtistInformation information, int numResults, int offset, bool limit)
QNetworkReply* Echonest::Artist::topHottt(Echonest::ArtistInformation information, int numResults, int offset, bool limit)
{
QUrl url = Echonest::baseGetQuery( "artist", "top_hottt" );
addQueryInformation( url, information );
if( numResults > 0 )
url.addEncodedQueryItem( "results", QByteArray::number( numResults ) );
if( offset >= 0 )
if( offset >= 0 )
url.addEncodedQueryItem( "start", QByteArray::number( offset ) );
url.addEncodedQueryItem( "limit", limit ? "true" : "false" );
return Echonest::Config::instance()->nam()->get( QNetworkRequest( url ) );
}
@ -405,33 +429,56 @@ QNetworkReply* Echonest::Artist::topTerms(int numResults)
{
QUrl url = Echonest::baseGetQuery( "artist", "top_terms" );
url.addEncodedQueryItem( "results", QByteArray::number( numResults ) );
return Echonest::Config::instance()->nam()->get( QNetworkRequest( url ) );
}
QNetworkReply* Echonest::Artist::listTerms( const QString& type )
{
QUrl url = Echonest::baseGetQuery( "artist", "list_terms" );
url.addQueryItem( QLatin1String( "type" ), type );
return Echonest::Config::instance()->nam()->get( QNetworkRequest( url ) );
}
QNetworkReply* Echonest::Artist::suggest( const QString& name, int results )
{
QUrl url = Echonest::baseGetQuery( "artist", "suggest" );
QString realname = name;
url.addQueryItem( QLatin1String( "name" ), realname.replace( QLatin1Char( ' ' ), QLatin1Char( '+' ) ) );
url.addEncodedQueryItem( "results", QByteArray::number( results ) );
return Echonest::Config::instance()->nam()->get( QNetworkRequest( url ) );
}
int Echonest::Artist::parseProfile( QNetworkReply* reply ) throw( Echonest::ParseError )
{
Echonest::Parser::checkForErrors( reply );
QXmlStreamReader xml( reply->readAll() );
Echonest::Parser::readStatus( xml );
int numResults = Echonest::Parser::parseArtistInfoOrProfile( xml, *this );
reply->deleteLater();
return numResults;
}
Echonest::Artists Echonest::Artist::parseSearch( QNetworkReply* reply ) throw( Echonest::ParseError )
{
Echonest::Parser::checkForErrors( reply );
QXmlStreamReader xml( reply->readAll() );
QByteArray data = reply->readAll();
QXmlStreamReader xml( data );
Echonest::Parser::readStatus( xml );
Echonest::Artists artists = Echonest::Parser::parseArtists( xml );
reply->deleteLater();
return artists;
}
@ -448,21 +495,49 @@ Echonest::Artists Echonest::Artist::parseTopHottt( QNetworkReply* reply ) throw(
Echonest::TermList Echonest::Artist::parseTopTerms( QNetworkReply* reply ) throw( Echonest::ParseError )
{
Echonest::Parser::checkForErrors( reply );
QXmlStreamReader xml( reply->readAll() );
Echonest::Parser::readStatus( xml );
Echonest::TermList terms = Echonest::Parser::parseTermList( xml );
Echonest::TermList terms = Echonest::Parser::parseTopTermList( xml );
reply->deleteLater();
return terms;
}
Echonest::Artists Echonest::Artist::parseSuggest( QNetworkReply* reply ) throw( Echonest::ParseError )
{
Echonest::Parser::checkForErrors( reply );
QXmlStreamReader xml( reply->readAll() );
Echonest::Parser::readStatus( xml );
Echonest::Artists artists = Echonest::Parser::parseArtistSuggestList( xml );
reply->deleteLater();
return artists;
}
QVector< QString > Echonest::Artist::parseTermList( QNetworkReply* reply ) throw( Echonest::ParseError )
{
Echonest::Parser::checkForErrors( reply );
QXmlStreamReader xml( reply->readAll() );
Echonest::Parser::readStatus( xml );
QVector< QString > terms = Echonest::Parser::parseTermList( xml );
reply->deleteLater();
return terms;
}
QUrl Echonest::Artist::setupQuery( const QByteArray& methodName, int numResults, int start ) const
{
QUrl url = Echonest::baseGetQuery( "artist", methodName );
if( !d->id.isEmpty() )
if( !d->id.isEmpty() )
url.addEncodedQueryItem( "id", d->id );
else if( !d->name.isEmpty() ) {
QString name = d->name;
@ -474,9 +549,9 @@ QUrl Echonest::Artist::setupQuery( const QByteArray& methodName, int numResults,
}
if( numResults > 0 )
url.addEncodedQueryItem( "results", QByteArray::number( numResults ) );
if( start >= 0 )
if( start >= 0 )
url.addEncodedQueryItem( "start", QByteArray::number( start ) );
return url;
}
@ -506,41 +581,42 @@ QByteArray Echonest::Artist::searchParamToString(Echonest::Artist::SearchParam p
return "reverse";
case Sort:
return "sort";
case Mood:
return "mood";
default:
return "";
}
}
void Echonest::Artist::addQueryInformation(QUrl& url, Echonest::Artist::ArtistInformation parts)
void Echonest::Artist::addQueryInformation(QUrl& url, Echonest::ArtistInformation information)
{
if( parts.testFlag( Echonest::Artist::Audio ) )
if( information.flags().testFlag( Echonest::ArtistInformation::Audio ) )
url.addEncodedQueryItem( "bucket", "audio" );
if( parts.testFlag( Echonest::Artist::Biographies ) )
if( information.flags().testFlag( Echonest::ArtistInformation::Biographies ) )
url.addEncodedQueryItem( "bucket", "biographies" );
if( parts.testFlag( Echonest::Artist::Blogs ) )
if( information.flags().testFlag( Echonest::ArtistInformation::Blogs ) )
url.addEncodedQueryItem( "bucket", "blogs" );
if( parts.testFlag( Echonest::Artist::Familiarity ) )
if( information.flags().testFlag( Echonest::ArtistInformation::Familiarity ) )
url.addEncodedQueryItem( "bucket", "familiarity" );
if( parts.testFlag( Echonest::Artist::Hotttnesss ) )
if( information.flags().testFlag( Echonest::ArtistInformation::Hotttnesss ) )
url.addEncodedQueryItem( "bucket", "hotttnesss" );
if( parts.testFlag( Echonest::Artist::Images ) )
if( information.flags().testFlag( Echonest::ArtistInformation::Images ) )
url.addEncodedQueryItem( "bucket", "images" );
if( parts.testFlag( Echonest::Artist::News ) )
if( information.flags().testFlag( Echonest::ArtistInformation::News ) )
url.addEncodedQueryItem( "bucket", "news" );
if( parts.testFlag( Echonest::Artist::Reviews ) )
if( information.flags().testFlag( Echonest::ArtistInformation::Reviews ) )
url.addEncodedQueryItem( "bucket", "reviews" );
if( parts.testFlag( Echonest::Artist::Terms ) )
if( information.flags().testFlag( Echonest::ArtistInformation::Terms ) )
url.addEncodedQueryItem( "bucket", "terms" );
if( parts.testFlag( Echonest::Artist::Urls ) )
if( information.flags().testFlag( Echonest::ArtistInformation::Urls ) )
url.addEncodedQueryItem( "bucket", "urls" );
if( parts.testFlag( Echonest::Artist::Videos ) )
if( information.flags().testFlag( Echonest::ArtistInformation::Videos ) )
url.addEncodedQueryItem( "bucket", "video" );
if( parts.testFlag( Echonest::Artist::MusicBrainzEntries ) )
url.addEncodedQueryItem( "bucket", "id:musicbrainz" );
if( parts.testFlag( Echonest::Artist::SevenDigitalEntries ) )
url.addEncodedQueryItem( "bucket", "id:7digital" );
if( parts.testFlag( Echonest::Artist::PlaymeEntries ) )
url.addEncodedQueryItem( "bucket", "id:playme" );
if( !information.idSpaces().isEmpty() ) {
foreach( const QString& idSpace, information.idSpaces() )
url.addEncodedQueryItem( "bucket", "id:" + idSpace.toUtf8() );
}
}

View File

@ -18,14 +18,16 @@
#ifndef ECHONEST_ARTIST_H
#define ECHONEST_ARTIST_H
#include "ArtistTypes.h"
#include "Config.h"
#include "echonest_export.h"
#include "TypeInformation.h"
#include "Song.h"
#include <QDebug>
#include <QSharedData>
#include <QUrl>
#include "Config.h"
#include "ArtistTypes.h"
#include "Song.h"
class QNetworkReply;
class ArtistData;
@ -33,51 +35,33 @@ class Term;
namespace Echonest{
class Biography;
class Catalog;
class Artist;
typedef QVector< Artist > Artists;
/**
* This encapsulates an Echo Nest artist---it always holds the basic info of artist id and
* artist name, and can be queried for more data.
*
*
* It is also possible to fetch more information from a given artist name or ID by creating an Artist
* object yourself and calling the fetch() functions directly.
*/
class ECHONEST_EXPORT Artist
{
public:
enum ArtistInformationFlag {
NoInformation = 0x0000,
Audio = 0x0001,
Biographies = 0x0002,
Blogs = 0x0004,
Familiarity = 0x0008,
Hotttnesss = 0x0010,
Images = 0x0020,
News = 0x0040,
Reviews = 0x0080,
Terms = 0x0100,
Urls = 0x200,
Videos = 0x0400,
MusicBrainzEntries = 0x0800,
SevenDigitalEntries = 0x1000,
PlaymeEntries = 0x2000
};
Q_DECLARE_FLAGS( ArtistInformation, ArtistInformationFlag )
enum TermSorting {
Weight,
Frequency
} ;
/**
* The following are the various search parameters to the search() and similar() functions.
*
* Not all are acceptable for each API call, check the API documentation at
*
* Not all are acceptable for each API call, check the API documentation at
* http://developer.echonest.com/docs/v4/artist.html#search for details.
*
*
* - id QVector< QByteArray > A list of the artist IDs to be searched (e.g. [ARH6W4X1187B99274F, musicbrainz:artist:a74b1b7f-71a5-4011-9441-d0b5e4122711 ,ARH6W4X1187B99274F^2])
* - name QVector< QString > A list of artist names to be searched (e.g. [Weezer, the beatles ,the beatles^0.5])
* - description QVector< QString > A list of descriptors [ alt-rock,-emo,harp^2 ]
@ -89,6 +73,7 @@ namespace Echonest{
* - min_hotttness 0.0 < hotttnesss < 1.0 The minimum hotttnesss for returned artists
* - reverse [true, false] If true, return artists that are disimilar to the seeds
* -sort QString How to sort the results. Options: familiarity-asc, hotttnesss-asc, familiarity-desc, hotttnesss-desc.
*
*/
enum SearchParam {
Id,
@ -101,94 +86,99 @@ namespace Echonest{
MaxHotttnesss,
MinHotttnesss,
Reverse,
Sort
Sort,
IdSpace,
Mood
};
typedef QPair< Echonest::Artist::SearchParam, QVariant > SearchParamEntry;
typedef QVector< SearchParamEntry > SearchParams;
Artist();
Artist( const QByteArray& id, const QString& name );
explicit Artist( const QString& name );
explicit Artist( const QByteArray& id );
Artist( const Artist& other );
Artist& operator=( const Artist& artist );
~Artist();
virtual ~Artist();
void init();
QByteArray id() const;
void setId( const QByteArray& id );
QString name() const;
void setName( const QString& name );
/**
* The following require fetching from The Echo Nest, so return a QNetworkReply*
* that is ready for parsing when the finished() signal is emitted.
*
*
* Call parseProfile() on the Artist object to populate it with the result of the
* query.
*
*
*/
/**
* A list of audio files on the web for this artist.
*/
AudioList audio() const;
void setAudio( const AudioList& );
/**
* A list of biographies for this artist.
*/
BiographyList biographies() const;
void setBiographies( const BiographyList& );
/**
* Blogs about this artist, around the web.
*/
BlogList blogs() const;
void setBlogs( const BlogList& );
/**
* How familiar this artist is.
*/
qreal familiarity() const;
void setFamiliarity( qreal familiar );
/**
* The hotttness of this artist.
*/
qreal hotttnesss() const;
void setHotttnesss( qreal hotttnesss );
/**
* Images related to this artist.
*/
ArtistImageList images() const;
void setImages( const ArtistImageList& );
/**
* News about this artist.
*/
NewsList news() const;
void setNews( const NewsList& );
/**
* Reviews of this artist
*/
ReviewList reviews() const;
void setReviews( const ReviewList& );
/**
* Echo Nest song objects belonging to this artist.
*/
SongList songs() const;
void setSongs( const SongList& );
/**
* Terms describing this artist.
*/
TermList terms() const;
void setTerms( const TermList& );
/**
* Urls pointing to this artists' basic information around the web.
*/
@ -204,169 +194,202 @@ namespace Echonest{
void setMyspaceUrl( const QUrl& );
QUrl musicbrainzUrl() const;
void setMusicbrainzUrl( const QUrl& url );
/**
* Videos related to this artist.
*/
VideoList videos() const;
void setVideos( const VideoList& );
/**
* The list of foreign ids for this artist, if fetched.
*/
ForeignIds foreignIds() const;
void setForeignIds( const ForeignIds& ids );
/**
* Fetch a list of audio documents found on the web that are related to this artist.
*
*
* @param numResults Limit how many results are returned
* @param offset The offset of the results, if paging through results in increments.
*/
QNetworkReply* fetchAudio( int numResults = 0, int offset = -1 ) const;
/**
* Fetch a list of biographies for this artist from various places on the web.
*/
QNetworkReply* fetchBiographies( const QString& license = QString(), int numResults = 0, int offset = -1 ) const;
/**
* Fetch a list of blog articles relating to this artist.
*/
QNetworkReply* fetchBlogs( bool highRelevanceOnly = false, int numResults = 0, int offset = -1 ) const;
/**
* Fetch The Echo Nest's numerical estimate of how familiar this artist is to the world.
*/
QNetworkReply* fetchFamiliarity() const;
/**
* Fetch the numerical description of how hot this artist is.
*
*
* Currently the only supported type is 'normal'
*/
QNetworkReply* fetchHotttnesss( const QString& type = QLatin1String( "normal" ) ) const;
/**
* Fetch a list of images related to this artist.
*/
QNetworkReply* fetchImages( const QString& license = QString(), int numResults = 0, int offset = -1 ) const;
/**
* Fetch a list of news articles found on the web related to this artist.
*/
QNetworkReply* fetchNews( bool highRelevanceOnly = false, int numResults = 0, int offset = -1 ) const;
/**
* Fetch any number of pieces of artist information all at once.
*/
QNetworkReply* fetchProfile( ArtistInformation information ) const;
QNetworkReply* fetchProfile( ArtistInformation information = ArtistInformation() ) const;
/**
* Fetch reviews related to the artist.
*/
QNetworkReply* fetchReviews( int numResults = 0, int offset = -1 ) const;
/**
* Fetch a list of songs created by this artist.
*
* The idspace can be used to specify what idspace to return the results in, if none is specifed, The Echo Nest song identifiers
* are used. If limitToIdSpace is true, then only results in the requested idspace are returned.
*/
QNetworkReply* fetchSongs( ArtistInformation idspace = NoInformation, bool limitToIdSpace = false, int numResults = 0, int offset = -1 ) const;
QNetworkReply* fetchSongs( int numResults = 0, int offset = -1 ) const;
/**
* Fetch a list of the most descriptive terms for this artist.
*/
QNetworkReply* fetchTerms( TermSorting sorting = Frequency ) const;
/**
* Fetch links to the artist's official site, MusicBrainz site, MySpace site, Wikipedia article, Amazon list, and iTunes page.
*/
QNetworkReply* fetchUrls() const;
/**
* Fetch a list of video documents found on the web related to an artist.
*/
QNetworkReply* fetchVideo( int numResults = 0, int offset = -1 ) const;
/**
* Parse a completed QNetworkReply* that has fetched more information about this artist.
* This will update the artist object with the new values that have been fetched.
*
*
* @return The number of results available on the server.
*/
int parseProfile( QNetworkReply* ) throw( ParseError );
/**
* Fetch a list of similar artists given one or more artists for comparison.
*
*
* Up to five artist names or ids can be included for the similarity search.
*
*
*
*
* So they are passed as a list of [paramname, paramvalue] to be included in the query.
*
* Boosting: This method can take multiple seed artists. You an give a seed artist more or less weight by boosting the artist. A boost is an
* affinity for a seed that gives it more or less weight when making calculations based on the argument. In case seeds are not meant to be equally
* valued, the boost can help clarify where along a spectrum each argument falls. The boost is a positive floating point value, where 1 gives the normal
*
* Boosting: This method can take multiple seed artists. You an give a seed artist more or less weight by boosting the artist. A boost is an
* affinity for a seed that gives it more or less weight when making calculations based on the argument. In case seeds are not meant to be equally
* valued, the boost can help clarify where along a spectrum each argument falls. The boost is a positive floating point value, where 1 gives the normal
* weight. It is signified by appending a caret and weight to the argument.
*
*
* See http://developer.echonest.com/docs/v4/artist.html#similar for boosting examples.
*
*
* Call parseSimilar() once the returned QNetworkReply* has emitted its finished() signal
*/
static QNetworkReply* fetchSimilar( const SearchParams& params, ArtistInformation information = NoInformation, int numResults = 0, int offset = -1 );
*/
static QNetworkReply* fetchSimilar( const SearchParams& params, ArtistInformation information = ArtistInformation(), int numResults = 0, int offset = -1 );
/**
* Search for artists.
*
*
* Warning: If limit is set to true, at least one idspace must also be provided.
*
*
* One of name or description is required, but only one can be used in a query at one time
*
*
*/
static QNetworkReply* search( const SearchParams& params, ArtistInformation information = NoInformation, bool limit = false );
static QNetworkReply* search( const SearchParams& params, ArtistInformation information = ArtistInformation(), bool limit = false );
/**
* Fetch a list of the current top artists in terms of hotttnesss.
*
*
* Warning If limit is set to true, at least one idspace must also be provided in the bucket parameter.
*
*
*/
static QNetworkReply* topHottt( ArtistInformation information = NoInformation, int numResults = 0, int offset = -1, bool limit = false );
static QNetworkReply* topHottt( ArtistInformation information = ArtistInformation(), int numResults = 0, int offset = -1, bool limit = false );
/**
* Fetch a list of the top overall terms.
*/
static QNetworkReply* topTerms( int numResults = 15 );
/**
* Suggest artists based on a partial name.
*
* \param results How many results to return, between 0 and 15. Default is 10
*/
static QNetworkReply* suggest( const QString& name, int results = 10 );
/**
* Returns a list of terms of the given type, for use in other calls.
*
* \param type Which type of term to return, at the moment only 'style' or 'mood'
*/
static QNetworkReply* listTerms( const QString& type = QLatin1String("style") );
/**
* Parse the result of a fetchSimilar() call, which returns a list of artists similar to the
* original pair.
*/
static Artists parseSimilar( QNetworkReply* ) throw( ParseError );
/**
* Parse the result of an artist search.
*/
static Artists parseSearch( QNetworkReply* ) throw( ParseError );
/**
* Parse the result of a top hottness query.
*/
static Artists parseTopHottt( QNetworkReply* ) throw( ParseError );
/**
* Parse the result of a top terms query.
*/
static TermList parseTopTerms( QNetworkReply* ) throw( ParseError );
/**
* Parse the result of a suggest query
*
* Returns a list of suggested artists
*/
static Artists parseSuggest( QNetworkReply* ) throw( ParseError );
/**
* Parse the result of a termList query. Returns the list of values returned.
*/
static QVector< QString > parseTermList( QNetworkReply* ) throw( ParseError );
private:
QUrl setupQuery( const QByteArray& methodName, int numResults = 0, int start = -1 ) const;
static QByteArray searchParamToString( SearchParam param );
static void addQueryInformation( QUrl& url, ArtistInformation parts );
static void addQueryInformation( QUrl& url, ArtistInformation information );
QSharedDataPointer<ArtistData> d;
friend class Catalog;
};
ECHONEST_EXPORT QDebug operator<<(QDebug d, const Echonest::Artist& artist);
Q_DECLARE_OPERATORS_FOR_FLAGS(Artist::ArtistInformation)
} // namespace
Q_DECLARE_METATYPE( Echonest::Artist )
#endif

View File

@ -37,6 +37,30 @@ public:
{
id = other.id;
name = other.name;
audio = other.audio;
biographies = other.biographies;
blogs = other.blogs;
familiarity = other.familiarity;
hotttnesss = other.hotttnesss;
images = other.images;
news = other.news;
reviews = other.reviews;
songs = other.songs;
similar = other.similar;
terms = other.terms;
videos = other.videos;
lastfm_url = other.lastfm_url;
aolmusic_url = other.aolmusic_url;
myspace_url = other.myspace_url;
amazon_url = other.amazon_url;
itunes_url = other.itunes_url;
mb_url = other.mb_url;
foreign_ids = other.foreign_ids;
}
// The following exist in all valid Artist objects
@ -65,7 +89,9 @@ public:
QUrl amazon_url;
QUrl itunes_url;
QUrl mb_url;
Echonest::ForeignIds foreign_ids;
};
#endif

View File

@ -17,8 +17,10 @@
#include "AudioSummary.h"
#include "AudioSummary_p.h"
#include <QNetworkReply>
#include "Config.h"
#include "Parsing_p.h"
#include <QNetworkReply>
Echonest::AudioSummary::AudioSummary()
: d( new AudioSummaryData )
@ -97,14 +99,14 @@ void Echonest::AudioSummary::setBeats(const Echonest::BeatList& beats)
d->beats = beats;
}
Echonest::Analysis::AnalysisStatus Echonest::AudioSummary::detailedStatus() const
QString Echonest::AudioSummary::detailedStatus() const
{
return Echonest::statusToEnum( d->detailed_status );
return d->detailed_status;
}
void Echonest::AudioSummary::setDetailedStatus(Echonest::Analysis::AnalysisStatus status)
void Echonest::AudioSummary::setDetailedStatus( const QString& status )
{
d->detailed_status = Echonest::statusToString( status );
d->detailed_status = status;
}
qreal Echonest::AudioSummary::duration() const
@ -183,9 +185,11 @@ void Echonest::AudioSummary::setNumSamples(qint64 num)
d->num_samples = num;
}
void Echonest::AudioSummary::parseFullAnalysis(QNetworkReply* reply)
void Echonest::AudioSummary::parseFullAnalysis( QNetworkReply* reply ) throw( Echonest::ParseError )
{
Echonest::Parser::checkForErrors( reply );
Echonest::Parser::parseDetailedAudioSummary( reply, *this );
reply->deleteLater();
}
QString Echonest::AudioSummary::sampleMD5() const
@ -303,7 +307,7 @@ int Echonest::AudioSummary::mode() const
return d->mode;
}
void Echonest::AudioSummary::setAnalysisUrl(const QString& analysisUrl)
void Echonest::AudioSummary::setAnalysisUrl(const QUrl& analysisUrl)
{
d->analysis_url = analysisUrl;
}
@ -312,3 +316,24 @@ void Echonest::AudioSummary::setMode(int mode)
{
d->mode = mode;
}
qreal Echonest::AudioSummary::danceability() const
{
return d->danceability;
}
void Echonest::AudioSummary::setDanceability(qreal dance)
{
d->danceability = dance;
}
qreal Echonest::AudioSummary::energy() const
{
return d->energy;
}
void Echonest::AudioSummary::setEnergy(qreal energy)
{
d->energy = energy;
}

View File

@ -24,6 +24,7 @@
#include <QDebug>
#include "Util.h"
#include "Util.h"
#include "Config.h"
class QNetworkReply;
class QNetworkReply;
@ -84,6 +85,21 @@ namespace Echonest{
qreal loudness() const;
void setLoudness( qreal loudness );
/**
* The danceability of this track, from 0 to 1.
*/
qreal danceability() const;
void setDanceability( qreal dance );
/**
* The energy of this song, from 0 to 1.
*/
qreal energy() const;
void setEnergy( qreal energy );
/// The following require additional fetching to read ///
/** TODO: implement **/
/**
* If you wish to use any of the more detailed track analysis data,
* use this method to begin the fetch. One the returned QNetworkReply*
@ -96,7 +112,7 @@ namespace Echonest{
* information such as mode, fadein/fadeout, confidence metrics,
* and the division of the song into bars, beats, sections, and segments.
*/
void parseFullAnalysis( QNetworkReply* reply );
void parseFullAnalysis( QNetworkReply* reply ) throw( ParseError );
/// The following methods *ALL REQUIRE THAT parseFullAnalysis be called first*
@ -115,8 +131,8 @@ namespace Echonest{
/**
* Detailed status information about the analysis
*/
Analysis::AnalysisStatus detailedStatus() const;
void setDetailedStatus( Analysis::AnalysisStatus status );
QString detailedStatus() const;
void setDetailedStatus( const QString& status );
/**
* The status code of the analysis
@ -214,7 +230,7 @@ namespace Echonest{
SegmentList segments() const;
void setSegments( const SegmentList& segments );
void setAnalysisUrl( const QString& analysisUrl );
void setAnalysisUrl( const QUrl& analysisUrl );
private:
QSharedDataPointer<AudioSummaryData> d;

View File

@ -24,7 +24,9 @@
class AudioSummaryData : public QSharedData
{
public:
AudioSummaryData() {}
AudioSummaryData() : key( -1 ), tempo( -1 ), mode( -1 ), time_signature( -1 ), duration( -1 ), loudness( -1 ), samplerate( -1 ), danceability( -1 ), energy( -1 ),
analysis_time( -1 ), status( -1 ), timestamp( -1 ), end_of_fade_in( -1 ), key_confidence( -1 ), mode_confidence( -1 ), num_samples( -1 ),
start_of_fade_out( -1 ), tempo_confidence( -1 ), time_signature_confidence( -1 ) {}
AudioSummaryData(const AudioSummaryData& other)
{
key = other.key;
@ -34,6 +36,8 @@ public:
duration = other.duration;
loudness = other.loudness;
samplerate = other.samplerate;
danceability = other.danceability;
energy = other.energy;
analysis_url = other.analysis_url;
@ -70,6 +74,8 @@ public:
qreal duration;
qreal loudness;
int samplerate;
qreal danceability;
qreal energy;
QUrl analysis_url; // used to fetch the following pieces of data
@ -94,7 +100,6 @@ public:
Echonest::BeatList beats;
Echonest::SectionList sections;
Echonest::TatumList tatums;
Echonest::SegmentList segments;
};

View File

@ -1,28 +1,5 @@
add_definitions(-DQT_NO_CAST_FROM_ASCII -DQT_NO_CAST_TO_ASCII)
set(ECHONEST_LIB_MAJOR_VERSION "0")
set(ECHONEST_LIB_MINOR_VERSION "1")
set(ECHONEST_LIB_PATCH_VERSION "0")
set(ECHONEST_LIB_VERSION "${ECHONEST_LIB_MAJOR_VERSION}.${ECHONEST_LIB_MINOR_VERSION}.${ECHONEST_LIB_PATCH_VERSION}" )
set( ECHONEST_LIB_VERSION_STRING "${ECHONEST_LIB_MAJOR_VERSION}.${ECHONEST_LIB_MINOR_VERSION}.${ECHONEST_LIB_PATCH_VERSION}")
if(CMAKE_COMPILER_IS_GNUCXX)
add_definitions( -Wall -Wundef -Wcast-align -Wchar-subscripts -Wpointer-arith
-Wwrite-strings -Wpacked -Wformat-security -Wmissing-format-attribute
-Wold-style-cast -Woverloaded-virtual -Wnon-virtual-dtor -Werror )
if (NOT WIN32 AND NOT APPLE)
add_definitions( -fvisibility=hidden )
endif()
# to be added:
# -Wshadow
# FIXME we might want this one back in, but Qt 4.4.3 spits gazillions of warnings with it on Linux-64:
# -Wconversion
endif(CMAKE_COMPILER_IS_GNUCXX)
include_directories( ${CMAKE_CURRENT_SOURCE_DIR} )
include_directories( ${QJSON_INCLUDE_DIRS} ${CMAKE_CURRENT_SOURCE_DIR} )
set( LIBECHONEST_SRC
Track.cpp
@ -34,9 +11,17 @@ set( LIBECHONEST_SRC
AudioSummary.cpp
Util.cpp
ArtistTypes.cpp
Generator.cpp
Catalog.cpp
CatalogUpdateEntry.cpp
CatalogSong.cpp
CatalogArtist.cpp
CatalogItem.cpp
TypeInformation.cpp
)
set( LIBECHONEST_H
echonest_export.h
Track.h
Song.h
Artist.h
@ -44,17 +29,35 @@ set( LIBECHONEST_H
Config.h
AudioSummary.h
ArtistTypes.h
Util.h
Catalog.h
CatalogUpdateEntry.h
CatalogSong.h
CatalogArtist.h
CatalogItem.h
TypeInformation.h
)
QT4_WRAP_CPP( ${LIBECHONEST_H} )
add_library( echonest STATIC ${LIBECHONEST_SRC} )
target_link_libraries( echonest ${QT_QTCORE_LIBRARY} ${QT_QTNETWORK_LIBRARY} )
set_target_properties( echonest PROPERTIES VERSION ${ECHONEST_LIB_VERSION} SOVERSION ${ECHONEST_LIB_VERSION} )
if (CMAKE_COMPILER_IS_GNUCXX)
add_definitions( -Werror )
endif (CMAKE_COMPILER_IS_GNUCXX)
SET( OS_SPECIFIC_LINK_LIBRARIES "" )
IF( APPLE OR MINGW )
SET( OS_SPECIFIC_LINK_LIBRARIES ${QJSON_LIBRARIES} )
ELSE( APPLE OR MINGW )
SET( OS_SPECIFIC_LINK_LIBRARIES ${QJSON_LDFLAGS} )
ENDIF( APPLE OR MINGW )
add_library( echonest SHARED ${LIBECHONEST_SRC} )
target_link_libraries( echonest ${OS_SPECIFIC_LINK_LIBRARIES} ${QT_QTCORE_LIBRARY} ${QT_QTNETWORK_LIBRARY} )
set_target_properties( echonest PROPERTIES VERSION ${ECHONEST_LIB_VERSION} SOVERSION ${ECHONEST_LIB_VERSION_SONAME} )
# Clementine: "install" the headers into the binary directory
foreach(file ${LIBECHONEST_H} echonest_export.h Util.h)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/${file}
${CMAKE_CURRENT_BINARY_DIR}/echonest/${file}
COPYONLY)
${CMAKE_CURRENT_BINARY_DIR}/echonest/${file}
COPYONLY)
endforeach(file ${LIBECHONEST_H})

334
3rdparty/libechonest/Catalog.cpp vendored Normal file
View File

@ -0,0 +1,334 @@
/****************************************************************************************
* Copyright (c) 2010 Leo Franchi <lfranchi@kde.org> *
* *
* 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 "Catalog.h"
#include "Catalog_p.h"
#include "Parsing_p.h"
#include "Generator_p.h"
#include "Track_p.h"
Echonest::Catalog::Catalog()
: d( new CatalogData )
{
}
Echonest::Catalog::Catalog( const QByteArray& id )
: d( new CatalogData )
{
d->id = id;
}
Echonest::Catalog::Catalog( const Echonest::Catalog& catalog )
: d( catalog.d )
{
}
Echonest::Catalog& Echonest::Catalog::operator=( const Echonest::Catalog& other )
{
d = other.d;
return *this;
}
Echonest::Catalog::~Catalog()
{
}
Echonest::CatalogArtists Echonest::Catalog::artists() const
{
return d->artists;
}
void Echonest::Catalog::setArtists(const Echonest::CatalogArtists& artists)
{
d->artists = artists;
}
QByteArray Echonest::Catalog::id() const
{
return d->id;
}
void Echonest::Catalog::setId(const QByteArray& id)
{
d->id = id;
}
QString Echonest::Catalog::name() const
{
return d->name;
}
void Echonest::Catalog::setName(const QString& name)
{
d->name = name;
}
int Echonest::Catalog::resolved() const
{
return d->resolved;
}
void Echonest::Catalog::setResolved(int resolved)
{
d->resolved = resolved;
}
int Echonest::Catalog::pendingTickets() const
{
// return d->pending_tickets;
return 0;
}
void Echonest::Catalog::setPendingTickets(int pending)
{
// d->pending_tickets = pending;
}
Echonest::CatalogSongs Echonest::Catalog::songs() const
{
return d->songs;
}
void Echonest::Catalog::setSongs(const Echonest::CatalogSongs& songs)
{
d->songs = songs;
}
int Echonest::Catalog::total() const
{
return d->total;
}
void Echonest::Catalog::setTotal(int total)
{
d->total = total;
}
Echonest::CatalogTypes::Type Echonest::Catalog::type() const
{
return d->type;
}
void Echonest::Catalog::setType(Echonest::CatalogTypes::Type type)
{
d->type = type;
}
QNetworkReply* Echonest::Catalog::create(const QString& name, Echonest::CatalogTypes::Type type)
{
QUrl url = Echonest::baseGetQuery( "catalog", "create" );
url.addQueryItem( QLatin1String( "name" ), name );
url.addEncodedQueryItem( "type", Echonest::catalogTypeToLiteral( type ) );
QNetworkRequest request = QNetworkRequest( url );
request.setHeader( QNetworkRequest::ContentTypeHeader, QLatin1String( "multipart/form-data" ) );
qDebug() << "Sending create url:" << url.toString();
return Echonest::Config::instance()->nam()->post( request, QByteArray() );
}
QNetworkReply* Echonest::Catalog::deleteCatalog() const
{
QUrl url = Echonest::baseGetQuery( "catalog", "delete" );
Q_ASSERT( !d->id.isEmpty() );
url.addEncodedQueryItem( "id", d->id );
return Echonest::doPost( url );
}
QNetworkReply* Echonest::Catalog::list(int results, int start)
{
QUrl url = Echonest::baseGetQuery( "catalog", "list" );
addLimits( url, results, start );
return Echonest::Config::instance()->nam()->get( QNetworkRequest( url ) );
}
QNetworkReply* Echonest::Catalog::profile() const
{
QUrl url = Echonest::baseGetQuery( "catalog", "profile" );
if( !d->id.isEmpty() )
url.addEncodedQueryItem( "id", d->id );
else if( !d->name.isEmpty() )
url.addQueryItem( QLatin1String( "name" ), d->name );
else
Q_ASSERT_X( false, "Catalog", "Not enough information!" );
return Echonest::Config::instance()->nam()->get( QNetworkRequest( url ) );
}
QNetworkReply* Echonest::Catalog::status(const QByteArray& ticket)
{
QUrl url = Echonest::baseGetQuery( "catalog", "status" );
url.addEncodedQueryItem( "ticket", ticket );
return Echonest::Config::instance()->nam()->get( QNetworkRequest( url ) );
}
QNetworkReply* Echonest::Catalog::update(const Echonest::CatalogUpdateEntries& entries) const
{
QUrl url = Echonest::baseGetQuery( "catalog", "update" );
Q_ASSERT( !d->id.isEmpty() );
url.addEncodedQueryItem( "id", d->id );
return Echonest::Catalog::updatePrivate( url, entries );
}
QNetworkReply* Echonest::Catalog::updateAndCreate(const Echonest::CatalogUpdateEntries& entries)
{
QUrl url = Echonest::baseGetQuery( "catalog", "update" );
return Echonest::Catalog::updatePrivate( url, entries );
}
QNetworkReply* Echonest::Catalog::readArtistCatalog(Echonest::ArtistInformation info, int results, int start) const
{
QUrl url = Echonest::baseGetQuery( "catalog", "read" );
Artist::addQueryInformation( url, info );
return readPrivate( url, results, start );
}
QNetworkReply* Echonest::Catalog::readSongCatalog(Echonest::SongInformation info, int results, int start) const
{
QUrl url = Echonest::baseGetQuery( "catalog", "read" );
Song::addQueryInformation( url, info );
return readPrivate( url, results, start );
}
QPair< QString, QByteArray > Echonest::Catalog::parseDelete( QNetworkReply* reply ) throw( Echonest::ParseError )
{
QByteArray data = reply->readAll();
// qDebug() << "DATA:" << data;
QPair< QString, QByteArray > asd;
Echonest::Parser::checkForErrors( reply );
QXmlStreamReader xml( data );
Echonest::Parser::readStatus( xml );
// TODO, after create works :)
reply->deleteLater();
return asd;
}
Echonest::Catalogs Echonest::Catalog::parseList(QNetworkReply* reply) throw( Echonest::ParseError )
{
Echonest::Parser::checkForErrors( reply );
QXmlStreamReader xml( reply->readAll() );
Echonest::Parser::readStatus( xml );
Echonest::Catalogs catalogs = Echonest::Parser::parseCatalogList( xml );
reply->deleteLater();
return catalogs;
}
void Echonest::Catalog::parseProfile(QNetworkReply* reply) throw( Echonest::ParseError )
{
Echonest::Parser::checkForErrors( reply );
QXmlStreamReader xml( reply->readAll() );
Echonest::Parser::readStatus( xml );
Echonest::Catalog catalog = Echonest::Parser::parseCatalog( xml, true );
d = catalog.d;
reply->deleteLater();
}
void Echonest::Catalog::parseRead(QNetworkReply* reply) throw( Echonest::ParseError )
{
Echonest::Parser::checkForErrors( reply );
QXmlStreamReader xml( reply->readAll() );
Echonest::Parser::readStatus( xml );
Echonest::Catalog catalog = Echonest::Parser::parseCatalog( xml, true );
d = catalog.d;
reply->deleteLater();
}
Echonest::CatalogStatus Echonest::Catalog::parseStatus(QNetworkReply* reply) throw( Echonest::ParseError )
{
Echonest::Parser::checkForErrors( reply );
QByteArray data = reply->readAll();
// qDebug() << data;
QXmlStreamReader xml( data );
Echonest::Parser::readStatus( xml );
Echonest::CatalogStatus status = Echonest::Parser::parseCatalogStatus( xml );
reply->deleteLater();
return status;
}
QByteArray Echonest::Catalog::parseTicket(QNetworkReply* reply) throw( Echonest::ParseError )
{
Echonest::Parser::checkForErrors( reply );
QByteArray data = reply->readAll();
// qDebug() << data;
QXmlStreamReader xml( data );
Echonest::Parser::readStatus( xml );
QByteArray ticket = Echonest::Parser::parseCatalogTicket( xml );
reply->deleteLater();
return ticket;
}
Echonest::Catalog Echonest::Catalog::parseCreate(QNetworkReply* reply) throw( Echonest::ParseError )
{
QByteArray data = reply->readAll();
// qDebug() << data;
Echonest::Parser::checkForErrors( reply );
QXmlStreamReader xml( data );
Echonest::Parser::readStatus( xml );
Catalog c = Echonest::Parser::parseNewCatalog( xml );
reply->deleteLater();
return c;
}
QNetworkReply* Echonest::Catalog::updatePrivate( QUrl& url, const Echonest::CatalogUpdateEntries& entries)
{
url.addEncodedQueryItem( "data_type", "json" );
QByteArray payload = Generator::catalogEntriesToJson( entries );
url.addEncodedQueryItem( "data", payload );
return Echonest::doPost( url );
}
void Echonest::Catalog::addLimits(QUrl& url, int results, int start)
{
if( results != 30 )
url.addEncodedQueryItem( "results", QString::number( results ).toLatin1() );
if( start > -1 )
url.addEncodedQueryItem( "start", QString::number( start ).toLatin1() );
}
QNetworkReply* Echonest::Catalog::readPrivate(QUrl& url, int results, int start) const
{
Q_ASSERT( !d->id.isEmpty() );
url.addEncodedQueryItem( "id", d->id );
addLimits( url, results, start );
return Echonest::Config::instance()->nam()->get( QNetworkRequest( url ) );
}
QDebug Echonest::operator<<(QDebug d, const Echonest::Catalog& catalog)
{
return d.maybeSpace() << QString::fromLatin1( "Catalog(%1, %2, %3, %4)" ).arg( catalog.name() ).arg( QLatin1String( catalog.id() ) )
.arg( QString::fromLatin1( Echonest::catalogTypeToLiteral( catalog.type() ) ) ).arg( catalog.total() ) << catalog.artists() << catalog.songs();
}

225
3rdparty/libechonest/Catalog.h vendored Normal file
View File

@ -0,0 +1,225 @@
/****************************************************************************************
* Copyright (c) 2010 Leo Franchi <lfranchi@kde.org> *
* *
* 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/>. *
****************************************************************************************/
#ifndef ECHONEST_CATALOG_H
#define ECHONEST_CATALOG_H
#include "Artist.h"
#include "CatalogUpdateEntry.h"
#include "echonest_export.h"
#include "Song.h"
#include "TypeInformation.h"
#include "Util.h"
#include <QSharedDataPointer>
#include <QString>
#include "CatalogSong.h"
#include "CatalogArtist.h"
class QNetworkReply;
class CatalogData;
namespace Echonest
{
class Catalog;
typedef QVector< Catalog > Catalogs;
class ECHONEST_EXPORT Catalog
{
public:
Catalog();
explicit Catalog( const QByteArray& id );
Catalog( const Catalog& );
virtual ~Catalog();
Catalog& operator=( const Catalog& );
/// Basic information about the catalog
/**
* The name of this catalog.
*/
QString name() const;
void setName( const QString& name );
/**
* The id of this catalog.
*/
QByteArray id() const;
void setId( const QByteArray& id );
/**
* The type of this catalog.
*/
CatalogTypes::Type type() const;
void setType( CatalogTypes::Type type );
/**
* The total number of items in this catalog.
*/
int total() const;
void setTotal( int total );
/// The following fields only have data if the appropriate parse* methods have been called
/**
* The number of resolved items in the catalog.
*/
int resolved() const;
void setResolved( int resolved );
/**
* The number of pending tickets still to be resolved
*/
int pendingTickets() const;
void setPendingTickets( int pending );
/**
* The songs in this catalog, if this is a song catalog.
*/
CatalogSongs songs() const;
void setSongs( const CatalogSongs& songs );
/**
* The artists in this catalog, if it is an artist catalog.
*/
CatalogArtists artists() const;
void setArtists( const CatalogArtists& artists );
/**
* Update this catalog with the given items. Each item has an associated action, default is Update.
* Call parseTicket() to access the result ticket from this call.
*
* See more information about this api call at http://developer.echonest.com/docs/v4/catalog.html#update
*
* Requires catalog id.
*
* \param entries The list of entries to update the catalog with.
*/
QNetworkReply* update( const CatalogUpdateEntries& entries ) const;
/**
* Get basic information on a catalog. Only requires one of catalog id or name.
*/
QNetworkReply* profile() const;
/**
* Fetch the full list of data from this catalog. It is possible to specify specific audio
* information that you wish to have included with each item. Use the appropriate artist- or
* song-specific method calls in order to achieve this.
*
* \param info The list of desired information to be included with each item.
* \param results How many results to return in total
* \param start The index of the first result
*/
QNetworkReply* readArtistCatalog( ArtistInformation info = ArtistInformation(), int results = 30, int start = -1 ) const;
QNetworkReply* readSongCatalog( SongInformation info = SongInformation(), int results = 30, int start = -1 ) const;
/**
* Deletes this catalog from The Echo Nest. Only the API key used to create a catalog can delete it.
*/
QNetworkReply* deleteCatalog() const;
/**
* Create a new catalog with the given name and type.
*
* Parse the finished QNetworkReply with parseCreate()
*
* \param name The name of the catalog to create
* \param type The type of the catalog to create
*/
static QNetworkReply* create( const QString& name, CatalogTypes::Type type );
/**
* Returns a list of catalogs created with this key.
*/
static QNetworkReply* list( int results = 30, int start = -1 );
/**
* Creates a new catalog with the given items.
* See more information about this api call at http://developer.echonest.com/docs/v4/catalog.html#update
*
* Call parseTicket() to access the result ticket from this call.
*
* \param entries The list of entries to populate the catalog with.
*
*/
static QNetworkReply* updateAndCreate( const CatalogUpdateEntries& entries );
/**
* Checks the status of a catalog operation given a catalog ticket.
*
* Parse the result with parseStatus()
*
* \param ticket The catalog ticket returned from an update() or updateAndCreate() call
*/
static QNetworkReply* status( const QByteArray& ticket );
/**
* Parses the result of a status call, returning the status information along with information on
* item resolution if available.
*/
static CatalogStatus parseStatus( QNetworkReply* ) throw( Echonest::ParseError );
/**
* Parses the result of a profile() call. Saves the data to this catalog object.
*/
void parseProfile( QNetworkReply* ) throw( Echonest::ParseError );
/**
* Parses the result of the read*Catalog() calls. Saves the catalog data to this object.
*/
void parseRead( QNetworkReply * ) throw( Echonest::ParseError );
/**
* Parse the result of a delete call. Will throw if the catalog was not successfully deleted,
* and returns the name/id pair.
*
* \return QPair of catalogName, catalogId that was just deleted.
*/
QPair< QString, QByteArray > parseDelete( QNetworkReply* ) throw( Echonest::ParseError );
/**
* Parse the result of the list() API call. Will return a list of catalogs---each catalog only
* has id, name, type, and total tracks information.
*/
static Catalogs parseList( QNetworkReply* ) throw( Echonest::ParseError );
/**
* Parse the result of a catalog call. The calls return a ticket that can be used to check the status
* of the call with status()
*/
static QByteArray parseTicket( QNetworkReply* ) throw( Echonest::ParseError );
/**
* Parse the result of a create() call.
*/
static Catalog parseCreate( QNetworkReply* reply ) throw( Echonest::ParseError );
private:
static QNetworkReply* updatePrivate( QUrl&, const CatalogUpdateEntries& entries );
QNetworkReply* readPrivate( QUrl& url, int results, int start ) const;
static void addLimits( QUrl&, int results, int start );
QSharedDataPointer< CatalogData > d;
};
ECHONEST_EXPORT QDebug operator<<(QDebug d, const Catalog &catalog);
};
Q_DECLARE_METATYPE( Echonest::Catalog )
#endif

59
3rdparty/libechonest/CatalogArtist.cpp vendored Normal file
View File

@ -0,0 +1,59 @@
/****************************************************************************************
* Copyright (c) 2010 Leo Franchi <lfranchi@kde.org> *
* *
* 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 "CatalogArtist.h"
#include "CatalogItem_p.h"
Echonest::CatalogArtist::CatalogArtist()
{
}
Echonest::CatalogArtist::CatalogArtist(const QString& name)
: Artist( name )
{
}
Echonest::CatalogArtist::CatalogArtist(const QByteArray& id, const QString& name)
: Artist(id, name)
{
}
Echonest::CatalogArtist::CatalogArtist(const Echonest::CatalogArtist& other)
: Artist( other )
, CatalogItem( other )
{
}
Echonest::CatalogArtist::~CatalogArtist()
{
}
Echonest::CatalogArtist& Echonest::CatalogArtist::operator=(const Echonest::CatalogArtist& other)
{
Artist::operator=( other );
CatalogItem::operator=( other );
return *this;
}
Echonest::CatalogTypes::Type Echonest::CatalogArtist::type() const
{
return Echonest::CatalogTypes::Artist;
}

50
3rdparty/libechonest/CatalogArtist.h vendored Normal file
View File

@ -0,0 +1,50 @@
/****************************************************************************************
* Copyright (c) 2010 Leo Franchi <lfranchi@kde.org> *
* *
* 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/>. *
****************************************************************************************/
#ifndef ECHONEST_CATALOG_ARTIST_H
#define ECHONEST_CATALOG_ARTIST_H
#include "echonest_export.h"
#include "Artist.h"
#include "CatalogItem.h"
class CatalogArtistData;
namespace Echonest {
/**
* An artist that includes some additional information returned when getting an artist from a catalog listing.
*/
class ECHONEST_EXPORT CatalogArtist : public Artist, public CatalogItem
{
public:
CatalogArtist();
explicit CatalogArtist(const QString& name);
CatalogArtist(const QByteArray& id, const QString& name);
CatalogArtist(const Echonest::CatalogArtist& other);
virtual ~CatalogArtist();
CatalogArtist& operator=( const CatalogArtist& other );
/**
* The type of this catalog item: Artist.
*/
virtual CatalogTypes::Type type() const;
};
typedef QVector< CatalogArtist > CatalogArtists;
};
Q_DECLARE_METATYPE( Echonest::CatalogArtist )
#endif

93
3rdparty/libechonest/CatalogItem.cpp vendored Normal file
View File

@ -0,0 +1,93 @@
/****************************************************************************************
* Copyright (c) 2010 Leo Franchi <lfranchi@kde.org> *
* *
* 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 "CatalogItem.h"
#include "CatalogItem_p.h"
// just an interface.
Echonest::CatalogItem::CatalogItem()
: dd( new CatalogItemData )
{
}
Echonest::CatalogItem::CatalogItem(const Echonest::CatalogItem& other)
: dd( other.dd )
{
}
Echonest::CatalogItem::~CatalogItem()
{
}
Echonest::CatalogItem& Echonest::CatalogItem::operator=(const Echonest::CatalogItem& other)
{
dd = other.dd;
return *this;
}
QDateTime Echonest::CatalogItem::dateAdded() const
{
return dd->date_added;
}
void Echonest::CatalogItem::setDateAdded(const QDateTime& dt)
{
dd->date_added = dt;
}
QByteArray Echonest::CatalogItem::foreignId() const
{
return dd->foreign_id;
}
void Echonest::CatalogItem::setForeignId(const QByteArray& id)
{
dd->foreign_id = id;
}
Echonest::CatalogUpdateEntry Echonest::CatalogItem::request() const
{
return dd->request;
}
void Echonest::CatalogItem::setRequest(const Echonest::CatalogUpdateEntry& request)
{
dd->request = request;
}
int Echonest::CatalogItem::rating() const
{
return dd->rating;
}
void Echonest::CatalogItem::setRating(int rating)
{
dd->rating = rating;
}
int Echonest::CatalogItem::playCount() const
{
return dd->play_count;
}
void Echonest::CatalogItem::setPlayCount(int count)
{
dd->play_count = count;
}

90
3rdparty/libechonest/CatalogItem.h vendored Normal file
View File

@ -0,0 +1,90 @@
/****************************************************************************************
* Copyright (c) 2010 Leo Franchi <lfranchi@kde.org> *
* *
* 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/>. *
****************************************************************************************/
#ifndef ECHONEST_CATALOG_ITEM_H
#define ECHONEST_CATALOG_ITEM_H
#include "CatalogUpdateEntry.h"
#include "echonest_export.h"
#include "Util.h"
#include <QMetaType>
#include <QSharedPointer>
#include <QDateTime>
class CatalogItemData;
namespace Echonest {
/**
* Since catalog items can be artists or songs, and we don't know sometimes until after we parse them,
* but we need to gather a list of them. A poor man's traits class? A rich man's interface? Far from either.
*/
class ECHONEST_EXPORT CatalogItem
{
public:
CatalogItem();
CatalogItem( const CatalogItem& other );
CatalogItem& operator=( const CatalogItem& other );
virtual ~CatalogItem();
/**
* The type of this item.
*/
virtual Echonest::CatalogTypes::Type type() const = 0;
/**
* The foreign id of this item in the catalog. e.g. CAOFUDS12BB066268E:artist:ARUI8651187B9ACF52
*
* See The Echo Nest API docs for more information.
*/
QByteArray foreignId() const;
void setForeignId( const QByteArray& id );
/**
* The request that generated this catalog item
*/
CatalogUpdateEntry request() const;
void setRequest( const CatalogUpdateEntry& request );
/**
* The date and time when this item was added to the catalog
*/
QDateTime dateAdded() const;
void setDateAdded( const QDateTime& dt );
/**
* The rating of this item.
*/
int rating() const;
void setRating( int rating );
/**
* The play count of this item.
*/
int playCount() const;
void setPlayCount( int count );
protected:
QSharedPointer<CatalogItemData> dd;
};
typedef QVector< CatalogItem > CatalogItems;
};
#endif

51
3rdparty/libechonest/CatalogItem_p.h vendored Normal file
View File

@ -0,0 +1,51 @@
/****************************************************************************************
* Copyright (c) 2010 Leo Franchi <lfranchi@kde.org> *
* *
* 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/>. *
****************************************************************************************/
#ifndef ECHONEST_CATALOG_ITEM_P_H
#define ECHONEST_CATALOG_ITEM_P_H
#include "Song_p.h"
#include <QSharedData>
#include <QString>
#include <QVector>
#include <QDateTime>
#include "CatalogUpdateEntry.h"
class CatalogItemData : public QSharedData
{
public:
CatalogItemData() {}
CatalogItemData(const CatalogItemData& other)
{
foreign_id = other.foreign_id;
request = other.request;
date_added = other.date_added;
rating = other.rating;
play_count = other.play_count;
}
~CatalogItemData() {}
Echonest::CatalogUpdateEntry request;
QByteArray foreign_id;
QDateTime date_added;
int rating;
int play_count;
};
#endif

54
3rdparty/libechonest/CatalogSong.cpp vendored Normal file
View File

@ -0,0 +1,54 @@
/****************************************************************************************
* Copyright (c) 2010 Leo Franchi <lfranchi@kde.org> *
* *
* 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 "CatalogSong.h"
#include "CatalogItem_p.h"
Echonest::CatalogSong::CatalogSong()
{
}
Echonest::CatalogSong::CatalogSong(const QByteArray& id, const QString& title, const QByteArray& artistId, const QString& artistName)
: Song(id, title, artistId, artistName)
{
}
Echonest::CatalogSong::CatalogSong(const Echonest::CatalogSong& other)
: Song(other)
, CatalogItem( other )
{
}
Echonest::CatalogSong& Echonest::CatalogSong::operator=(const Echonest::CatalogSong& other)
{
Song::operator=( other );
CatalogItem::operator=( other );
return *this;
}
Echonest::CatalogSong::~CatalogSong()
{
}
Echonest::CatalogTypes::Type Echonest::CatalogSong::type() const
{
return Echonest::CatalogTypes::Song;
}

49
3rdparty/libechonest/CatalogSong.h vendored Normal file
View File

@ -0,0 +1,49 @@
/****************************************************************************************
* Copyright (c) 2010 Leo Franchi <lfranchi@kde.org> *
* *
* 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/>. *
****************************************************************************************/
#ifndef ECHONEST_CATALOG_SONG_H
#define ECHONEST_CATALOG_SONG_H
#include "echonest_export.h"
#include "Song.h"
#include "CatalogItem.h"
class CatalogSongData;
namespace Echonest {
/**
* A song that includes some additional information returned when getting a song from a catalog listing.
*/
class ECHONEST_EXPORT CatalogSong : public Song, public CatalogItem
{
public:
CatalogSong();
CatalogSong(const QByteArray& id, const QString& title, const QByteArray& artistId, const QString& artistName);
CatalogSong(const Echonest::CatalogSong& other);
virtual ~CatalogSong();
CatalogSong& operator=( const CatalogSong& other );
/**
* The type of this item: Song.
*/
virtual CatalogTypes::Type type() const;
};
typedef QVector< CatalogSong > CatalogSongs;
};
Q_DECLARE_METATYPE( Echonest::CatalogSong )
#endif

View File

@ -0,0 +1,232 @@
/****************************************************************************************
* Copyright (c) 2010 Leo Franchi <lfranchi@kde.org> *
* *
* 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 "CatalogUpdateEntry.h"
#include "CatalogUpdateEntry_p.h"
Echonest::CatalogUpdateEntry::CatalogUpdateEntry()
: d( new CatalogUpdateEntryData )
{
}
Echonest::CatalogUpdateEntry::CatalogUpdateEntry( CatalogTypes::Action action )
: d( new CatalogUpdateEntryData )
{
d->action = action;
}
Echonest::CatalogUpdateEntry::CatalogUpdateEntry( const Echonest::CatalogUpdateEntry& other )
: d( other.d )
{
}
Echonest::CatalogUpdateEntry::~CatalogUpdateEntry()
{
}
Echonest::CatalogUpdateEntry& Echonest::CatalogUpdateEntry::operator=(const Echonest::CatalogUpdateEntry& other)
{
d = other.d;
return *this;
}
QByteArray Echonest::CatalogUpdateEntry::itemId() const
{
return d->item_id;
}
void Echonest::CatalogUpdateEntry::setItemId(const QByteArray& id)
{
d->item_id = id;
}
Echonest::CatalogTypes::Action Echonest::CatalogUpdateEntry::action() const
{
return d->action;
}
void Echonest::CatalogUpdateEntry::setAction(Echonest::CatalogTypes::Action action)
{
d->action = action;
}
QByteArray Echonest::CatalogUpdateEntry::artistId() const
{
return d->artist_id;
}
void Echonest::CatalogUpdateEntry::setArtistId(const QByteArray& id)
{
d->artist_id = id;
}
QByteArray Echonest::CatalogUpdateEntry::fingerprint() const
{
return d->fp_code;
}
void Echonest::CatalogUpdateEntry::setFingerprint(const QByteArray& id)
{
d->fp_code = id;
}
void Echonest::CatalogUpdateEntry::setFingerpring(const QByteArray& id)
{
setFingerprint(id);
}
QString Echonest::CatalogUpdateEntry::artistName() const
{
return d->artist_name;
}
void Echonest::CatalogUpdateEntry::setArtistName(const QString& name)
{
d->artist_name = name;
}
bool Echonest::CatalogUpdateEntry::banned() const
{
return d->banned;
}
void Echonest::CatalogUpdateEntry::setBanned(bool banned)
{
d->bannedSet = true;
d->banned = banned;
}
int Echonest::CatalogUpdateEntry::discNumber() const
{
return d->disc_number;
}
void Echonest::CatalogUpdateEntry::setDiscNumber(int disc)
{
d->disc_number = disc;
}
bool Echonest::CatalogUpdateEntry::favorite() const
{
return d->favorite;
}
void Echonest::CatalogUpdateEntry::setFavorite(bool fav)
{
d->favoriteSet = true;
d->favorite = fav;
}
QString Echonest::CatalogUpdateEntry::genre() const
{
return d->genre;
}
void Echonest::CatalogUpdateEntry::setGenre(const QString& genre)
{
d->genre = genre;
}
int Echonest::CatalogUpdateEntry::playCount() const
{
return d->play_count;
}
void Echonest::CatalogUpdateEntry::setPlayCount(int playCount)
{
d->play_count = playCount;
}
int Echonest::CatalogUpdateEntry::rating() const
{
return d->rating;
}
void Echonest::CatalogUpdateEntry::setRating(int rating)
{
d->rating = rating;
}
QString Echonest::CatalogUpdateEntry::release() const
{
return d->release;
}
void Echonest::CatalogUpdateEntry::setRelease(const QString& release)
{
d->release = release;
}
int Echonest::CatalogUpdateEntry::skipCount() const
{
return d->skip_count;
}
void Echonest::CatalogUpdateEntry::setSkipCount(int skipCount)
{
d->skip_count = skipCount;
}
QByteArray Echonest::CatalogUpdateEntry::songId() const
{
return d->song_id;
}
void Echonest::CatalogUpdateEntry::setSongId(const QByteArray& id)
{
d->song_id = id;
}
QString Echonest::CatalogUpdateEntry::songName() const
{
return d->song_name;
}
void Echonest::CatalogUpdateEntry::setSongName(const QString& name)
{
d->song_name = name;
}
int Echonest::CatalogUpdateEntry::trackNumber() const
{
return d->track_number;
}
void Echonest::CatalogUpdateEntry::setTrackNumber(int trackNum)
{
d->track_number = trackNum;
}
QString Echonest::CatalogUpdateEntry::url() const
{
return d->url;
}
void Echonest::CatalogUpdateEntry::setUrl(const QString& url)
{
d->url = url;
}
bool Echonest::CatalogUpdateEntry::bannedSet() const
{
return d->bannedSet;
}
bool Echonest::CatalogUpdateEntry::favoriteSet() const
{
return d->favoriteSet;
}

View File

@ -0,0 +1,174 @@
/****************************************************************************************
* Copyright (c) 2010 Leo Franchi <lfranchi@kde.org> *
* *
* 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/>. *
****************************************************************************************/
#ifndef ECHONEST_CATALOG_ENTRY_H
#define ECHONEST_CATALOG_ENTRY_H
#include "echonest_export.h"
#include "Util.h"
#include <QByteArray>
#include <QSharedDataPointer>
#include <QString>
#include <QVector>
class CatalogUpdateEntryData;
namespace Echonest {
/**
* This rather simple struct collects information about a status update
*/
typedef QVector< QPair< QByteArray, QString > > CatalogStatusItem;
typedef struct CatalogStatusStruct {
CatalogTypes::TicketStatus status;
QString details;
int items_updated;
CatalogStatusItem items; // List of [ item_id, info ]
// int percent_complete;
CatalogStatusStruct() : status( CatalogTypes::Unknown ), items_updated( -1 ) {}
} CatalogStatus;
/**
* This class described a catalog entry for use in the Catalog update() call.
* All data fields are optional except Action, and only the ones specified will be sent.
*/
class ECHONEST_EXPORT CatalogUpdateEntry
{
public:
CatalogUpdateEntry();
CatalogUpdateEntry( CatalogTypes::Action action );
virtual ~CatalogUpdateEntry();
CatalogUpdateEntry( const CatalogUpdateEntry& other );
CatalogUpdateEntry& operator=( const CatalogUpdateEntry& );
/**
* Optional, the item id for the catalog entry. hash( catalog_id + item_id )
* MUST be unique. If this is not set, a unique id will be generated internally.
*/
QByteArray itemId() const;
void setItemId( const QByteArray& id );
/**
* The type of action that this item represents, required.
*/
CatalogTypes::Action action() const;
void setAction( CatalogTypes::Action action );
/**
* The Echo Nest fingerprint.
*/
QByteArray fingerprint() const;
void setFingerprint( const QByteArray& id );
// deprecated
void setFingerpring( const QByteArray& id );
/**
* The song id. Rosetta id or Echo Nest ID.
*/
QByteArray songId() const;
void setSongId( const QByteArray& id );
/**
* The song name. Mutually exclusive with song id.
*/
QString songName() const;
void setSongName( const QString& name );
/**
* The artist id, either a rosetta stone ID or an Echo Nest ID.
*/
QByteArray artistId() const;
void setArtistId( const QByteArray& id );
/**
* The artist name, mutually exclusive with artist id.
*/
QString artistName() const;
void setArtistName( const QString& name );
/**
* The release, or album, name.
*/
QString release() const;
void setRelease( const QString& release );
/**
* The genre of the item.
*/
QString genre() const;
void setGenre( const QString& genre );
/**
* The track number.
*/
int trackNumber() const;
void setTrackNumber( int trackNum );
/**
* The disc number of this item.
*/
int discNumber() const;
void setDiscNumber( int disc );
/**
* The url or the local filename or remote url.
*/
QString url() const;
void setUrl( const QString& url );
/**
* If this song was marked as a favorite or not
*/
bool favorite() const;
void setFavorite( bool fav );
/**
* If this song was banned.
*/
bool banned() const;
void setBanned( bool banned );
/**
* The play count of this item.
*/
int playCount() const;
void setPlayCount( int playCount );
/**
* The skip count of this item.
*/
int skipCount() const;
void setSkipCount( int skipCount );
/**
* The rating of this item, from 1 to 10.
*/
int rating() const;
void setRating( int rating );
bool favoriteSet() const;
bool bannedSet() const;
private:
QSharedDataPointer<CatalogUpdateEntryData> d;
};
typedef QVector<CatalogUpdateEntry> CatalogUpdateEntries;
}
#endif

View File

@ -0,0 +1,88 @@
/****************************************************************************************
* Copyright (c) 2010 Leo Franchi <lfranchi@kde.org> *
* *
* 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/>. *
****************************************************************************************/
#ifndef CATALOG_UPDATE_ENTRY_H
#define CATALOG_UPDATE_ENTRY_H
#include "Util.h"
#include <QSharedData>
#include <QByteArray>
#include <QString>
class CatalogUpdateEntryData : public QSharedData {
public:
CatalogUpdateEntryData() : action( Echonest::CatalogTypes::Update ), track_number( -1 ), disc_number( -1 ), favorite( false ),
banned( false ), play_count( -1 ), skip_count( -1 ), rating( -1 ),
favoriteSet( false ), bannedSet( false )
{}
CatalogUpdateEntryData( const CatalogUpdateEntryData& other ) {
item_id = other.item_id;
action = other.action;
fp_code = other.fp_code;
song_id = other.song_id;
song_name = other.song_name;
artist_id = other.artist_id;
artist_name = other.artist_name;
release = other.release;
genre = other.genre;
track_number = other.track_number;
disc_number = other.disc_number;
url = other.url;
favorite = other.favorite;
banned = other.banned;
play_count = other.play_count;
skip_count = other.skip_count;
rating = other.rating;
favoriteSet = other.favoriteSet;
bannedSet = other.banned;
}
Echonest::CatalogTypes::Action action;
QByteArray item_id;
QByteArray fp_code;
QByteArray song_id;
QString song_name;
QByteArray artist_id;
QString artist_name;
QString release;
QString genre;
int track_number;
int disc_number;
QString url;
bool favorite;
bool banned;
int play_count;
int skip_count;
int rating;
// internal
bool favoriteSet;
bool bannedSet;
};
#endif

57
3rdparty/libechonest/Catalog_p.h vendored Normal file
View File

@ -0,0 +1,57 @@
/****************************************************************************************
* Copyright (c) 2010 Leo Franchi <lfranchi@kde.org> *
* *
* 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/>. *
****************************************************************************************/
#ifndef ECHONEST_CATALOG_P_H
#define ECHONEST_CATALOG_P_H
#include "CatalogArtist.h"
#include "CatalogSong.h"
#include "Util.h"
#include <QSharedData>
class CatalogData : public QSharedData
{
public:
CatalogData() : total( 0 ), resolved( 0 ) {}
CatalogData( const CatalogData& other ) {
name = other.name;
id = other.id;
type = other.type;
total = other.total;
resolved = other.resolved;
songs = other.songs;
artists = other.artists;
}
~CatalogData() {}
// Fields we always get in a catalog object
QString name;
QByteArray id;
Echonest::CatalogTypes::Type type;
int total;
// Fields we sometimes get depending on the query
int resolved;
// pending_tickets
Echonest::CatalogSongs songs; // either has songs, or artists
Echonest::CatalogArtists artists;
};
#endif

View File

@ -1,5 +1,6 @@
/****************************************************************************************
* Copyright (c) 2010 Leo Franchi <lfranchi@kde.org> *
* Copyright (c) 2011 Jeff Mitchell <mitchell@kde.org> *
* *
* 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 *
@ -17,7 +18,9 @@
#include "Config.h"
#include <QNetworkAccessManager>
#include <QThread>
#include <QDebug>
#include <QMutex>
Echonest::Config* Echonest::Config::s_instance = 0;
@ -44,6 +47,13 @@ Echonest::ParseError::ParseError(Echonest::ErrorType error): exception()
type = error;
}
Echonest::ParseError::ParseError(Echonest::ErrorType error, const QString& text): exception()
{
type = error;
extraText = text;
}
Echonest::ParseError::~ParseError() throw()
{}
@ -59,6 +69,11 @@ void Echonest::ParseError::setNetworkError( QNetworkReply::NetworkError error )
const char* Echonest::ParseError::what() const throw()
{
// If we have specific error text, return that first
if( !extraText.isEmpty() )
return extraText.toLatin1().constData();
switch( type )
{
case UnknownError:
@ -97,17 +112,26 @@ QNetworkReply::NetworkError Echonest::ParseError::networkError() const throw()
class Echonest::ConfigPrivate {
public:
ConfigPrivate() : nam( new QNetworkAccessManager )
ConfigPrivate()
{
threadNamHash[ QThread::currentThread() ] = new QNetworkAccessManager();
}
~ConfigPrivate()
{
delete nam;
nam = 0;
QThread *currThread = QThread::currentThread();
if( threadNamHash.contains( currThread ) )
{
if ( ourNamSet.contains( currThread ) )
delete threadNamHash[ currThread ];
threadNamHash.remove( currThread );
ourNamSet.remove( currThread );
}
}
QNetworkAccessManager* nam;
QMutex accessMutex;
QHash< QThread*, QNetworkAccessManager* > threadNamHash;
QSet< QThread* > ourNamSet;
QByteArray apikey;
};
@ -137,16 +161,36 @@ void Echonest::Config::setNetworkAccessManager(QNetworkAccessManager* nam)
{
if( !nam )
return;
if( d->nam ) {
delete d->nam;
}
d->nam = nam;
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 )
return;
d->threadNamHash[ currThread ] = nam;
d->ourNamSet.remove( currThread );
if( oldNam )
delete oldNam;
}
QNetworkAccessManager* Echonest::Config::nam() const
{
return d->nam;
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 ];
}
Echonest::Config* Echonest::Config::instance() {

View File

@ -31,10 +31,10 @@ namespace Echonest{
/// Creates the base URL for all GET and POST requests
QUrl baseUrl();
/// Creates the base URL for GET requests.
QUrl baseGetQuery( const QByteArray& type, const QByteArray& method );
enum ErrorType {
/**
* Echo Nest API errors
@ -46,71 +46,82 @@ namespace Echonest{
RateLimitExceeded = 3,
MissingParameter = 4,
InvalidParameter = 5,
/// libechonest errors
UnfinishedQuery = 6, /// An unfinished QNetworkReply* was passed to the parse function
EmptyResult = 7,
UnknownParseError = 8,
/// QNetworkReply errors
NetworkError = 9
};
class ECHONEST_EXPORT ParseError : public std::exception
{
public:
ParseError( ErrorType error );
explicit ParseError( ErrorType error );
ParseError( ErrorType error, const QString& text );
virtual ~ParseError() throw();
ErrorType errorType() const throw();
/**
* If the ErrorType is NetworkError, this value contains the QNetworkReply
* error code that was returned.
*/
void setNetworkError( QNetworkReply::NetworkError error ) throw();
QNetworkReply::NetworkError networkError() const throw();
virtual const char* what() const throw ();
private:
ErrorType type;
QString extraText;
QNetworkReply::NetworkError nError;
};
class ConfigPrivate;
/**
* This singleton contains miscellaneous settings used to access The Echo Nest
*/
class ECHONEST_EXPORT Config {
class ECHONEST_EXPORT Config {
public:
static Config* instance();
/**
* Set the API key to be used for all API requests. This MUST be set in order
* Set the API key to be used for all API requests. This MUST be set in order
* for any web service calls to work!
*/
void setAPIKey( const QByteArray& apiKey );
QByteArray apiKey() const;
/**
* Set the QNetworkAccessManager to use to make web service requests to
* The Echo Nest.
*
*
* This will register the given QNAM for the current thread. If you call this from
* the main thread and only make calls to libechonest from the main thread, you don't
* have to do any more work. However, if you are using multiple QNAMs in different threads,
* you must call this for each QNAM in each thread so that libechonest can use the proper
* thread-local QNAM. This function is thread-safe.
*
* Note that in all threads, if you do not set a QNAM, a default one is created and returned.
* In addition, if you set your own QNAM, you are responsible for deleting it.
*
* This will take over control of the object.
*/
void setNetworkAccessManager( QNetworkAccessManager* nam );
QNetworkAccessManager* nam() const;
private:
Config();
~Config();
static Config* s_instance;
ConfigPrivate* d;
};
}
#endif

118
3rdparty/libechonest/Generator.cpp vendored Normal file
View File

@ -0,0 +1,118 @@
/****************************************************************************************
* Copyright (c) 2010 Leo Franchi <lfranchi@kde.org> *
* *
* 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 "Generator_p.h"
#include "CatalogUpdateEntry.h"
// QJSon
#include <qjson/serializer.h>
#include <QVariant>
#include <quuid.h>
#include <QDebug>
QByteArray Echonest::Generator::catalogEntriesToJson( const Echonest::CatalogUpdateEntries& items )
{
QJson::Serializer s;
QVariant itms = catalogEntriesToVariant( items );
QByteArray serialized = s.serialize( itms );
// qDebug() << "Serialized:" << serialized;
return serialized;
}
QByteArray Echonest::Generator::catalogEntryToJson( const Echonest::CatalogUpdateEntry& item )
{
QJson::Serializer s;
QVariant itm = catalogEntryToVariant( item );
QByteArray serialized = s.serialize( itm );
// qDebug() << "Serialized:" << serialized;
return serialized;
}
QVariantList Echonest::Generator::catalogEntriesToVariant( const Echonest::CatalogUpdateEntries& items )
{
// copy the catalog item into a QVariant
QVariantList itemList;
foreach( const Echonest::CatalogUpdateEntry& item, items )
itemList << catalogEntryToVariant( item );
return itemList;
}
QVariant Echonest::Generator::catalogEntryToVariant( const Echonest::CatalogUpdateEntry& item )
{
QVariantMap itemMap;
QVariantMap itm;
itemMap[ QLatin1String( "action" ) ] = Echonest::catalogUpdateActionToLiteral( item.action() );
if( item.itemId().isEmpty() )
itm[ QLatin1String( "item_id" ) ] = QUuid::createUuid().toString().replace( QLatin1Char( '{' ), QString() ).replace( QLatin1Char( '}' ), QString() );
else
itm[ QLatin1String( "item_id" ) ] = item.itemId();
if( !item.fingerprint().isEmpty() )
itm[ QLatin1String( "fp_code" ) ] = item.fingerprint();
if( !item.songId().isEmpty() )
itm[ QLatin1String( "song_id" ) ] = item.songId();
if( !item.songName().isEmpty() )
itm[ QLatin1String( "song_name" ) ] = item.songName();
if( !item.artistId().isEmpty() )
itm[ QLatin1String( "artist_id" ) ] = item.artistId();
if( !item.artistName().isEmpty() )
itm[ QLatin1String( "artist_name" ) ] = item.artistName();
if( !item.release().isEmpty() )
itm[ QLatin1String( "release" ) ] = item.release();
if( !item.genre().isEmpty() )
itm[ QLatin1String( "genre" ) ] = item.genre();
if( item.trackNumber() > -1 )
itm[ QLatin1String( "track_number" ) ] = item.trackNumber();
if( item.discNumber() > -1 )
itm[ QLatin1String( "disc_number" ) ] = item.discNumber();
if( !item.url().isEmpty() )
itm[ QLatin1String( "url" ) ] = item.url();
if( item.favoriteSet() )
itm[ QLatin1String( "favorite" ) ] = item.favorite();
if( item.bannedSet() )
itm[ QLatin1String( "banned" ) ] = item.banned();
if( item.playCount() > -1 )
itm[ QLatin1String( "play_count" ) ] = item.playCount();
if( item.skipCount() > -1 )
itm[ QLatin1String( "skip_count" ) ] = item.skipCount();
if( item.rating() > -1 )
itm[ QLatin1String( "rating" ) ] = item.rating();
itemMap[ QLatin1String( "item" ) ] = itm;
return itemMap;
}

40
3rdparty/libechonest/Generator_p.h vendored Normal file
View File

@ -0,0 +1,40 @@
/****************************************************************************************
* Copyright (c) 2010 Leo Franchi <lfranchi@kde.org> *
* *
* 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/>. *
****************************************************************************************/
#ifndef LIBECHONEST_GENERATOR_H
#define LIBECHONEST_GENERATOR_H
#include <QByteArray>
#include "CatalogUpdateEntry.h"
#include <QVariant>
namespace Echonest {
namespace Generator {
/**
* Miscellaneous functions for generating JSON to send to The Echo Nest
*/
QByteArray catalogEntriesToJson( const CatalogUpdateEntries& items );
QByteArray catalogEntryToJson( const CatalogUpdateEntry& item );
QVariantList catalogEntriesToVariant( const CatalogUpdateEntries& items );
QVariant catalogEntryToVariant( const CatalogUpdateEntry& item );
};
};
#endif

File diff suppressed because it is too large Load Diff

View File

@ -19,9 +19,11 @@
#include "Config.h"
#include <QXmlStreamReader>
#include <QtXml/QXmlStreamReader>
#include "Song.h"
#include "Artist.h"
#include "Catalog.h"
#include "Playlist.h"
class QNetworkReply;
@ -34,35 +36,43 @@ namespace Parser
*/
void checkForErrors( QNetworkReply* reply ) throw( ParseError );
// read the start element and then the status element, throwing
// read the start element and then the status element, throwing
// if the result code is not Success
void readStatus( QXmlStreamReader& xml ) throw( ParseError );
// parses a <songs></songs> block and turns them into a list of Song object
QVector< Song > parseSongList( QXmlStreamReader& xml ) throw( ParseError );
// parses a <song></song> block
Song parseSong( QXmlStreamReader& xml ) throw( ParseError );
// parses a <artist_location> block
ArtistLocation parseSongArtistLocation( QXmlStreamReader& xml ) throw( ParseError );
// parses a <track></track> block
Track parseTrack( QXmlStreamReader& xml ) throw( ParseError );
// parses a <tracks> chunk when asking for a song with tracks bucket
Tracks parseSongTrackBucket( QXmlStreamReader& xml ) throw( ParseError );
// parses an <audio_summary> chunk
AudioSummary parseAudioSummary( QXmlStreamReader& xml ) throw( ParseError );
// parses the json of the detailed audio summary
void parseDetailedAudioSummary( QNetworkReply* reply, AudioSummary& summary ) throw( ParseError );
// parses a list of artists in an <artists></artists> block
Echonest::Artists parseArtists( QXmlStreamReader& xml );
Echonest::Artists parseArtists( QXmlStreamReader& xml ) throw( ParseError );
// parses the contents of an artist fetch result, expects to be positioned after the readStatus() call
// it could be a profile query, in which case it has a bunch of different artist attributes
// or it could be a single fetch, in which case it starts with result number and offset.
// the results are saved back into the artist
int parseArtistInfoOrProfile( QXmlStreamReader&, Echonest::Artist& artist ) throw( ParseError );
// parse the individual artist attributes
void parseArtistInfo( QXmlStreamReader& xml, Echonest::Artist& artist ) throw( ParseError );
// parse each type of artist attribute
void parseAudio( QXmlStreamReader& xml, Echonest::Artist& artist ) throw( ParseError );
void parseBiographies( QXmlStreamReader& xml, Echonest::Artist& artist ) throw( ParseError );
@ -73,16 +83,39 @@ namespace Parser
void parseUrls( QXmlStreamReader& xml, Echonest::Artist& artist ) throw( ParseError );
void parseArtistSong( QXmlStreamReader& xml, Echonest::Artist& artist ) throw( ParseError );
void parseVideos( QXmlStreamReader& xml, Echonest::Artist& artist ) throw( ParseError );
void parseForeignIds( QXmlStreamReader& xml, Echonest::Artist& artist ) throw( ParseError );
void parseForeignArtistIds( QXmlStreamReader& xml, Echonest::Artist& artist ) throw( ParseError );
// parse a list of terms
TermList parseTermList( QXmlStreamReader& xml );
TermList parseTopTermList( QXmlStreamReader& xml ) throw( ParseError );
QVector< QString > parseTermList( QXmlStreamReader& xml ) throw( ParseError );
Artists parseArtistSuggestList( QXmlStreamReader& xml ) throw( ParseError );
License parseLicense( QXmlStreamReader& xml ) throw( ParseError );
QByteArray parsePlaylistSessionId( QXmlStreamReader& xml ) throw( ParseError );
}
}
// Catalog functions
Catalogs parseCatalogList( QXmlStreamReader& xml ) throw( ParseError );
Catalog parseCatalog( QXmlStreamReader& xml, bool justOne = false /* the catalog API is ugly :( */ ) throw( ParseError );
QList<CatalogItem*> parseCatalogItems( QXmlStreamReader& xml ) throw( ParseError );
void parseCatalogRequestItem( QXmlStreamReader& xml, Echonest::CatalogArtist&, Echonest::CatalogSong& ) throw( ParseError );
void saveArtistList( Catalog& catalog, QList<CatalogItem*>& );
void saveSongList( Catalog& catalog, QList<CatalogItem*>& );
Echonest::CatalogStatus parseCatalogStatus( QXmlStreamReader& xml ) throw( ParseError );
Echonest::CatalogStatusItem parseTicketUpdateInfo( QXmlStreamReader& xml ) throw( ParseError );
QByteArray parseCatalogTicket( QXmlStreamReader& xml ) throw( ParseError );
Catalog parseNewCatalog( QXmlStreamReader& xml ) throw( ParseError );
// parses a <tracks> chunk when asking for a song with tracks bucket in a catalog.read call
Tracks parseCatalogSongTracks( QXmlStreamReader& xml ) throw( ParseError );
SessionInfo parseSessionInfo( QXmlStreamReader& xml ) throw( ParseError );
QVector< QString > parseRulesList( QXmlStreamReader& xml ) throw( ParseError );
QVector< SessionItem > parseSessionSongItem( QXmlStreamReader& xml, const QString& type ) throw( ParseError );
};
};
#endif

View File

@ -17,6 +17,7 @@
#include "Playlist.h"
#include "Playlist_p.h"
#include "Parsing_p.h"
#include <QtNetwork/QNetworkReply>
Echonest::DynamicPlaylist::DynamicPlaylist()
: d( new DynamicPlaylistData )
@ -42,7 +43,7 @@ Echonest::DynamicPlaylist& Echonest::DynamicPlaylist::operator=(const Echonest::
return *this;
}
QNetworkReply* Echonest::DynamicPlaylist::start(const Echonest::DynamicPlaylist::PlaylistParams& params)
QNetworkReply* Echonest::DynamicPlaylist::start(const Echonest::DynamicPlaylist::PlaylistParams& params) const
{
// params are the same, if user passes in format parsing will throw, but it should be expected..
return generateInternal( params, "dynamic" );
@ -51,17 +52,19 @@ QNetworkReply* Echonest::DynamicPlaylist::start(const Echonest::DynamicPlaylist:
Echonest::Song Echonest::DynamicPlaylist::parseStart(QNetworkReply* reply) throw( Echonest::ParseError )
{
Echonest::Parser::checkForErrors( reply );
QXmlStreamReader xml( reply->readAll() );
QByteArray data = reply->readAll();
// qDebug() << data;
QXmlStreamReader xml( data );
Echonest::Parser::readStatus( xml );
d->sessionId = Echonest::Parser::parsePlaylistSessionId( xml );
Echonest::SongList songs = Echonest::Parser::parseSongList( xml );
if( !songs.size() == 1 )
throw new Echonest::ParseError( UnknownParseError );
throw Echonest::ParseError( UnknownParseError );
d->currentSong = songs.front();
reply->deleteLater();
return d->currentSong;
}
@ -85,16 +88,38 @@ void Echonest::DynamicPlaylist::setCurrentSong(const Echonest::Song& song)
d->currentSong = song;
}
QNetworkReply* Echonest::DynamicPlaylist::fetchNextSong(int rating)
QNetworkReply* Echonest::DynamicPlaylist::fetchNextSong(int rating) const
{
QUrl url = Echonest::baseGetQuery( "playlist", "dynamic" );
url.addEncodedQueryItem( "session_id", d->sessionId );
if( rating > 0 )
url.addEncodedQueryItem( "rating", QByteArray::number( rating ) );
return Echonest::Config::instance()->nam()->get( QNetworkRequest( url ) );
}
QNetworkReply* Echonest::DynamicPlaylist::fetchNextSong(const DynamicControls& controls) const
{
QUrl url = Echonest::baseGetQuery( "playlist", "dynamic" );
url.addEncodedQueryItem( "session_id", d->sessionId );
DynamicControls::const_iterator iter = controls.begin();
for( ; iter != controls.end(); ++iter ) {
QString value = iter->second;
url.addEncodedQueryItem( dynamicControlToString( iter->first ), value.replace( QLatin1Char( ' ' ), QLatin1Char( '+' ) ).toUtf8() );
}
return Echonest::Config::instance()->nam()->get( QNetworkRequest( url ) );
}
QNetworkReply* Echonest::DynamicPlaylist::fetchSessionInfo() const
{
QUrl url = Echonest::baseGetQuery( "playlist", "session_info" );
url.addEncodedQueryItem( "session_id", d->sessionId );
return Echonest::Config::instance()->nam()->get( QNetworkRequest( url ) );
}
@ -103,6 +128,20 @@ Echonest::Song Echonest::DynamicPlaylist::parseNextSong(QNetworkReply* reply)
return parseStart( reply );
}
Echonest::SessionInfo Echonest::DynamicPlaylist::parseSessionInfo(QNetworkReply* reply) throw( Echonest::ParseError )
{
Echonest::Parser::checkForErrors( reply );
QXmlStreamReader xml( reply->readAll() );
Echonest::Parser::readStatus( xml );
reply->deleteLater();
return Echonest::Parser::parseSessionInfo( xml );
}
QNetworkReply* Echonest::DynamicPlaylist::staticPlaylist(const Echonest::DynamicPlaylist::PlaylistParams& params)
{
return Echonest::DynamicPlaylist::generateInternal( params, "static" );
@ -111,26 +150,36 @@ QNetworkReply* Echonest::DynamicPlaylist::staticPlaylist(const Echonest::Dynamic
Echonest::SongList Echonest::DynamicPlaylist::parseStaticPlaylist(QNetworkReply* reply) throw( Echonest::ParseError )
{
Echonest::Parser::checkForErrors( reply );
QXmlStreamReader xml( reply->readAll() );
Echonest::Parser::readStatus( xml );
Echonest::SongList songs = Echonest::Parser::parseSongList( xml );
reply->deleteLater();
return songs;
}
QByteArray Echonest::DynamicPlaylist::parseXSPFPlaylist(QNetworkReply* reply) throw( Echonest::ParseError )
{
QByteArray data = reply->readAll();
Echonest::Parser::checkForErrors( reply );
reply->deleteLater();
return data;
}
QNetworkReply* Echonest::DynamicPlaylist::generateInternal(const Echonest::DynamicPlaylist::PlaylistParams& params, const QByteArray& type)
{
QUrl url = Echonest::baseGetQuery( "playlist", type );
Echonest::DynamicPlaylist::PlaylistParams::const_iterator iter = params.constBegin();
for( ; iter < params.constEnd(); ++iter ) {
if( iter->first == Format ) // If it's a format, we have to remove the xml format we automatically specify
url.removeEncodedQueryItem( "format" );
if( iter->first == Type ) { // convert type enum to string
switch( static_cast<Echonest::DynamicPlaylist::ArtistTypeEnum>( iter->second.toInt() ) )
switch( static_cast<Echonest::DynamicPlaylist::ArtistTypeEnum>( iter->second.toInt() ) )
{
case ArtistType:
url.addEncodedQueryItem( playlistParamToString( iter->first ), "artist" );
@ -141,19 +190,28 @@ QNetworkReply* Echonest::DynamicPlaylist::generateInternal(const Echonest::Dynam
case ArtistDescriptionType:
url.addEncodedQueryItem( playlistParamToString( iter->first ), "artist-description" );
break;
case CatalogType:
url.addEncodedQueryItem( playlistParamToString( iter->first ), "catalog" );
break;
case CatalogRadioType:
url.addEncodedQueryItem( playlistParamToString( iter->first ), "catalog-radio" );
break;
case SongRadioType:
url.addEncodedQueryItem( playlistParamToString( iter->first ), "song-radio" );
break;
}
} else if( iter->first == Sort ) {
url.addEncodedQueryItem( playlistParamToString( iter->first ), playlistSortToString( static_cast<Echonest::DynamicPlaylist::SortingType>( iter->second.toInt() ) ) );
} else if( iter->first == Pick ) {
url.addEncodedQueryItem( playlistParamToString( iter->first ), playlistArtistPickToString( static_cast<Echonest::DynamicPlaylist::ArtistPick>( iter->second.toInt() ) ) );
} else if( iter->first == SongInformation ){
Echonest::Song::addQueryInformation( url, Echonest::Song::SongInformation( iter->second.value< Echonest::Song::SongInformation >() ) );
Echonest::Song::addQueryInformation( url, Echonest::SongInformation( iter->second.value< Echonest::SongInformation >() ) );
} else {
url.addQueryItem( QLatin1String( playlistParamToString( iter->first ) ), iter->second.toString().replace( QLatin1Char( ' ' ), QLatin1Char( '+' ) ) );
}
}
qDebug() << "Creating playlist URL" << url;
return Echonest::Config::instance()->nam()->get( QNetworkRequest( url ) );
}
@ -175,6 +233,10 @@ QByteArray Echonest::DynamicPlaylist::playlistParamToString(Echonest::DynamicPla
return "artist_id";
case Echonest::DynamicPlaylist::Artist :
return "artist";
case Echonest::DynamicPlaylist::ArtistSeedCatalog :
return "artist_seed_catalog";
case Echonest::DynamicPlaylist::SourceCatalog :
return "seed_catalog";
case Echonest::DynamicPlaylist::SongId :
return "song_id";
case Echonest::DynamicPlaylist::Description :
@ -197,6 +259,14 @@ QByteArray Echonest::DynamicPlaylist::playlistParamToString(Echonest::DynamicPla
return "artist_max_familiarity";
case Echonest::DynamicPlaylist::ArtistMinFamiliarity :
return "artist_min_familiarity";
case Echonest::DynamicPlaylist::MinDanceability :
return "min_danceability";
case Echonest::DynamicPlaylist::MaxDanceability :
return "max_danceability";
case Echonest::DynamicPlaylist::MinEnergy :
return "min_energy";
case Echonest::DynamicPlaylist::MaxEnergy :
return "max_energy";
case Echonest::DynamicPlaylist::ArtistMaxHotttnesss :
return "artist_max_hotttnesss";
case Echonest::DynamicPlaylist::ArtistMinHotttnesss :
@ -206,13 +276,13 @@ QByteArray Echonest::DynamicPlaylist::playlistParamToString(Echonest::DynamicPla
case Echonest::DynamicPlaylist::SongMinHotttnesss :
return "song_min_hotttnesss";
case Echonest::DynamicPlaylist::ArtistMinLongitude :
return "artist_min_longitude";
return "min_longitude";
case Echonest::DynamicPlaylist::ArtistMaxLongitude :
return "artist_max_longitude";
return "max_longitude";
case Echonest::DynamicPlaylist::ArtistMinLatitude :
return "artist_min_latitude";
return "min_latitude";
case Echonest::DynamicPlaylist::ArtistMaxLatitude :
return "artist_max_latitude";
return "max_latitude";
case Echonest::DynamicPlaylist::Mode :
return "mode";
case Echonest::DynamicPlaylist::Key :
@ -227,6 +297,14 @@ QByteArray Echonest::DynamicPlaylist::playlistParamToString(Echonest::DynamicPla
return "audio";
case Echonest::DynamicPlaylist::DMCA :
return "dmca";
case Echonest::DynamicPlaylist::ChainXSPF :
return "chain_xspf";
case Echonest::DynamicPlaylist::Mood :
return "mood";
case Echonest::DynamicPlaylist::Style :
return "style";
case Echonest::DynamicPlaylist::Adventurousness :
return "adventurousness";
}
return QByteArray();
}
@ -275,6 +353,10 @@ QByteArray Echonest::DynamicPlaylist::playlistSortToString(Echonest::DynamicPlay
return "duration-asc";
case SortDurationDescending:
return "duration-desc";
case SortLoudnessAscending:
return "loudness-asc";
case SortLoudnessDescending:
return "loudness-desc";
case SortArtistFamiliarityAscending:
return "artist_familiarity-asc";
case SortArtistFamiliarityDescending:
@ -303,10 +385,35 @@ QByteArray Echonest::DynamicPlaylist::playlistSortToString(Echonest::DynamicPlay
return "key-asc";
case SortKeyDescending:
return "key-desc";
case SortEnergyAscending:
return "energy-asc";
case SortEnergyDescending:
return "energy-desc";
case SortDanceabilityAscending:
return "danceability-asc";
case SortDanceabilityDescending:
return "danceability-desc";
}
return QByteArray();
}
QByteArray Echonest::DynamicPlaylist::dynamicControlToString(Echonest::DynamicPlaylist::DynamicControlItem control)
{
switch( control )
{
case Steer:
return "steer";
case SteerDescription:
return "steer_description";
case Rating:
return "rating";
case Ban:
return "ban";
default:
return "";
}
}
QDebug Echonest::operator<<(QDebug d, const Echonest::DynamicPlaylist& playlist)
{

View File

@ -23,12 +23,40 @@
#include <QSharedData>
#include <QDebug>
#include "Artist.h"
#include <QtCore/QString>
#include "Catalog.h"
class QNetworkReply;
class DynamicPlaylistData;
namespace Echonest{
typedef struct {
qreal served_time;
QByteArray artist_id;
QByteArray id;
QString artist_name;
QString title;
int rating;
} SessionItem;
typedef struct {
TermList terms;
SongList seed_songs;
// description .. what data is in here?
Artists banned_artists;
QVector< QString > rules;
QByteArray session_id;
Artists seeds;
QVector< SessionItem > skipped_songs;
QVector< SessionItem > banned_songs;
QString playlist_type;
Catalogs seed_catalogs;
QVector< SessionItem > rated_songs;
QVector< SessionItem > history;
} SessionInfo;
/**
* This encapsulates an Echo Nest dynamic playlist. It contains a playlist ID and
* the current song, and can fetch the next song.
@ -41,15 +69,18 @@ namespace Echonest{
public:
/**
* The types of playlist that can be generated. Artist plays songs for the given artist,
* ArtistRadio takes into account similar artists, adn ArtistDescription plays songs matching
* ArtistRadio takes into account similar artists, and ArtistDescription plays songs matching
* the given description.
*/
enum ArtistTypeEnum {
ArtistType,
ArtistRadioType,
ArtistDescriptionType
ArtistDescriptionType,
CatalogType,
CatalogRadioType,
SongRadioType
};
/**
* Different ways to sort a generated playlist
*/
@ -71,9 +102,15 @@ namespace Echonest{
SortModeAscending,
SortModeDescending,
SortKeyAscending,
SortKeyDescending
SortKeyDescending,
SortLoudnessAscending,
SortLoudnessDescending,
SortEnergyAscending,
SortEnergyDescending,
SortDanceabilityAscending,
SortDanceabilityDescending
};
/**
* Different ways of picking artists in Artist radios.
*/
@ -91,18 +128,20 @@ namespace Echonest{
PickModeDescending,
PickKeyDescending
};
/**
* The various parameters that can be passed to the playlist building
* functions.
*/
enum PlaylistParam {
Type, /// The type of playlist to generate. Value is the DynamicPlaylist::ArtistTypeEnum enum
Format, /// Either xml (default) or xspf. If the result is xspf, the raw xspf playlist is returned, else the xml is parsed and exposed programmatically.
Format, /// Either xml (default) or xspf. If the result is xspf, the raw xspf playlist is returned, else the xml is parsed and exposed programmatically. If using XSPF, you must specify a catalog, the tracks bucket, and limit = true
Pick, /// How the artists are picked for each artist in ArtistType playlists. Value is Playlist::ArtistPick enum value.
Variety, /// 0 < variety < 1 The maximum variety of artists to be represented in the playlist. A higher number will allow for more variety in the artists.
ArtistId, /// ID(s) of seed artist(s) for the playlist
Artist, /// Artist names of seeds for playlist
ArtistSeedCatalog, /// ID of seed artist catalog for the playlist
SourceCatalog, /// ID of catalog (artist or song) for catalog type playlists
SongId, /// IDs of seed songs for the playlist
Description, /// Textual description for sort of songs that can be included in the playlist
Results, /// 0-100, how many sonsg to include in the playlist, default 15
@ -112,6 +151,10 @@ namespace Echonest{
MinDuration, /// 0.0 < duration < 3600.0 (seconds) the minimum duration of any song on the playlist
MaxLoudness, /// -100.0 < loudness < 100.0 (dB) the maximum loudness of any song on the playlist
MinLoudness, /// -100.0 < loudness < 100.0 (dB) the minimum loudness of any song on the playlist
MinDanceability, /// 0 < danceability < 1 a measure of the minimum danceability of the song
MaxDanceability, /// 0 < danceability < 1 a measure of the maximum danceability of the song
MinEnergy, /// 0 < danceability < 1 a measure of the maximum energy of the song
MaxEnergy, /// 0 < danceability < 1 a measure of the maximum energy of the song
ArtistMaxFamiliarity, /// 0.0 < familiarity < 1.0 the maximum artist familiarity for songs in the playlist
ArtistMinFamiliarity, /// 0.0 < familiarity < 1.0 the minimum artist familiarity for songs in the playlist
ArtistMaxHotttnesss, /// 0.0 < hotttnesss < 1.0 the maximum hotttnesss for artists in the playlist
@ -122,79 +165,116 @@ namespace Echonest{
ArtistMaxLongitude, /// -180.0 < longitude < 180.0 the maximum longitude for the location of artists in the playlist
ArtistMinLatitude, /// -90.0 < latitude < 90.0 the minimum latitude for the location of artists in the playlist
ArtistMaxLatitude, /// -90.0 < latitude < 90.0 the maximum latitude for the location of artists in the playlist
Mode, /// (minor, major) 0, 1 the mode of songs in the playlist
Mode, /// (minor, major) 0, 1 the mode of songs in the playlist
Key, /// (c, c-sharp, d, e-flat, e, f, f-sharp, g, a-flat, a, b-flat, b) 0 - 11 the key of songs in the playlist
SongInformation, /// what sort of song information should be returned. Should be an Echonest::Song::SongInformation object
Sort, /// SortingType enum, the type of sorting to use,
SongInformation, /// what sort of song information should be returned. Should be an Echonest::SongInformation object
Sort, /// SortingType enum, the type of sorting to use,
Limit, /// true, false if true songs will be limited to those that appear in the catalog specified by the id: bucket
Audio, /// true, false, if true songs will be limited to those that have associated audio
DMCA /// true, false Only valid for dynamic playlists. Sets if playlist will follow DMCA rules (see web api doc for details)
DMCA, /// true, false Only valid for dynamic playlists. Sets if playlist will follow DMCA rules (see web api doc for details)
ChainXSPF, /// true, false If true, returns an xspf for this dynamic playlist with 2 items. The second item will be a link to the API call for the next track in the chain. Please note that this sidesteps libechonest's handling of the tracks.
Mood, /// A mood to limit this playlist to, for example "happy" or "sad". Multiples of this param are okay. See the method Artist::listTerms for details on what moods are currently available
Style, /// A style to limit this playlist to, for example "happy" or "sad". Multiples of this param are okay. See the method Artist::listTerms for details on what styles are currently available
Adventurousness
};
typedef QPair< PlaylistParam, QVariant > PlaylistParamData;
typedef QVector< PlaylistParamData > PlaylistParams;
/**
* The various controls for a dynamic playlist.
*
* Please see The Echo Nest API documentation for more information
*/
enum DynamicControlItem {
Steer = 0,
SteerDescription,
Rating,
Ban
};
typedef QPair< DynamicControlItem, QString > DynamicControl;
typedef QVector< DynamicControl > DynamicControls;
DynamicPlaylist();
~DynamicPlaylist();
virtual ~DynamicPlaylist();
DynamicPlaylist( const DynamicPlaylist& other );
DynamicPlaylist& operator=( const DynamicPlaylist& playlist );
/**
* Start a dynamic playlist with the given parameters.
* Once the QNetworkReply has finished, pass it to parseStart()
* and the inital song will be populated and returned. The sessionId(), currentSong(),
* Once the QNetworkReply has finished, pass it to parseStart()
* and the inital song will be populated and returned. The sessionId(), currentSong(),
* and fetchNextSong() methods will then be useful.
*/
QNetworkReply* start( const PlaylistParams& params );
QNetworkReply* start( const PlaylistParams& params ) const;
Song parseStart( QNetworkReply* ) throw( ParseError );
/**
* The session id of this dynamic playlist. If the playlist has ended, or has not been started,
* the result is empty.
*
*
*/
QByteArray sessionId() const;
void setSessionId( const QByteArray& id );
/**
* The current song of this dynamic playlist. Once this song has been played,
* or whenever is desired, call fetchNextSong() to get the next song.
*/
Song currentSong() const;
void setCurrentSong( const Song& song );
/**
* Queries The Echo Nest for the next playable song in this
* dynamic playlist.
*
*
* Once the query has emitted the finished() signal, pass it to parseNextSong(), which will
* return the new song to play. It will also set the current song to the newly parsed song.
*
* If the playlist has no more songs, the returned song object will be have no name nor id.
*
*
* If the playlist has no more songs, the returned song object will be have no name nor id.
*
* @param rating The rating for the song that was just played. Ranges from 1 (lowest) to 5 (highest)
*
* @param controls The controls to apply when fetching the next track.
*
*/
QNetworkReply* fetchNextSong( int rating = -1);
QNetworkReply* fetchNextSong( int rating = -1 ) const;
QNetworkReply* fetchNextSong( const DynamicControls& controls ) const;
Song parseNextSong( QNetworkReply* reply );
/**
* Generate a static playlist, according to the desired criteria.
/**
* Returns a description of this dynamic playlist session
*/
QNetworkReply* fetchSessionInfo() const;
SessionInfo parseSessionInfo( QNetworkReply* reply ) throw( ParseError );;
/**
* Generate a static playlist, according to the desired criteria. Use parseXSPFPlaylist if
* you pass format=xspf to \c staticPlaylist().
*/
static QNetworkReply* staticPlaylist( const PlaylistParams& params );
static SongList parseStaticPlaylist( QNetworkReply* reply ) throw( ParseError );
/**
* Parse an xspf playlist. Returns the full xspf content with no modifications.
*/
static QByteArray parseXSPFPlaylist( QNetworkReply* reply ) throw( ParseError );
private:
static QByteArray playlistParamToString( PlaylistParam param );
static QNetworkReply* generateInternal( const PlaylistParams& params, const QByteArray& type );
static QByteArray playlistSortToString(SortingType sorting);
static QByteArray playlistArtistPickToString(ArtistPick pick);
static QByteArray dynamicControlToString(DynamicControlItem control);
QSharedDataPointer<DynamicPlaylistData> d;
};
ECHONEST_EXPORT QDebug operator<<(QDebug d, const Echonest::DynamicPlaylist& playlist);
} // namespace
}; // namespace
Q_DECLARE_METATYPE( Echonest::DynamicPlaylist )
#endif

View File

@ -26,6 +26,8 @@
#include <QtNetwork/QNetworkReply>
#include "Parsing_p.h"
#include <qxmlstream.h>
#include <qjson/serializer.h>
#include <qjson/parser.h>
Echonest::Song::Song()
: d( new SongData )
@ -40,6 +42,12 @@ Echonest::Song::Song(const QByteArray& id, const QString& title, const QByteArra
d->artistName = artistName;
}
Echonest::Song::Song(const QByteArray& id)
:d( new SongData )
{
d->id = id;
}
Echonest::Song::Song(const Echonest::Song& other)
: d( other.d )
{
@ -49,7 +57,7 @@ Echonest::Song::Song(const Echonest::Song& other)
Echonest::Song::~Song()
{
}
Echonest::Song& Echonest::Song::operator=(const Echonest::Song& song)
@ -101,6 +109,17 @@ void Echonest::Song::setArtistName(const QString& artistName)
d->artistName = artistName;
}
QString Echonest::Song::release() const
{
return d->release;
}
void Echonest::Song::setRelease(const QString& release)
{
d->release = release;
}
QVector< Echonest::Track > Echonest::Song::tracks() const
{
return d->tracks;
@ -151,45 +170,113 @@ void Echonest::Song::setArtistFamiliarity(qreal artistFamiliarity)
d->artistFamiliarity = artistFamiliarity;
}
QString Echonest::Song::artistLocation() const
Echonest::ArtistLocation Echonest::Song::artistLocation() const
{
return d->artistLocation;
}
void Echonest::Song::setArtistLocation(const QString& artistLocation)
void Echonest::Song::setArtistLocation(const Echonest::ArtistLocation& artistLocation)
{
d->artistLocation = artistLocation;
}
QNetworkReply* Echonest::Song::fetchInformation( Echonest::Song::SongInformation parts ) const
QNetworkReply* Echonest::Song::fetchInformation( Echonest::SongInformation information ) const
{
QUrl url = Echonest::baseGetQuery( "song", "profile" );
url.addEncodedQueryItem( "id", d->id );
addQueryInformation( url, parts );
addQueryInformation( url, information );
qDebug() << "Creating fetchInformation URL" << url;
return Echonest::Config::instance()->nam()->get( QNetworkRequest( url ) );
}
QNetworkReply* Echonest::Song::search( const Echonest::Song::SearchParams& params, Echonest::Song::SongInformation parts )
QNetworkReply* Echonest::Song::search( const Echonest::Song::SearchParams& params, Echonest::SongInformation information )
{
QUrl url = Echonest::baseGetQuery( "song", "search" );
addQueryInformation( url, parts );
addQueryInformation( url, information );
SearchParams::const_iterator iter = params.constBegin();
for( ; iter < params.constEnd(); ++iter )
url.addQueryItem( QLatin1String( searchParamToString( iter->first ) ), iter->second.toString() );
url.addQueryItem( QLatin1String( searchParamToString( iter->first ) ), iter->second.toString().replace( QLatin1Char( ' ' ), QLatin1Char( '+' ) ) );
qDebug() << "Creating search URL" << url;
return Echonest::Config::instance()->nam()->get( QNetworkRequest( url ) );
}
QNetworkReply* Echonest::Song::identify( const Echonest::Song::IdentifyParams& params, const Echonest::SongInformation& information )
{
QVariantMap query;
QVariantMap metadata;
IdentifyParams::const_iterator iter = params.constBegin();
for( ; iter < params.constEnd(); ++iter ) {
if( iter->first == Code )
query[ QLatin1String( identifyParamToString( iter->first ) ) ] = iter->second;
else
metadata[ QLatin1String( identifyParamToString( iter->first ) ) ] = iter->second.toString();
}
metadata[ QLatin1String( "version" ) ] = QLatin1String( "4.12" );
query[ QLatin1String( "metadata" ) ] = metadata;
QJson::Serializer s;
QByteArray data = s.serialize( query );
QUrl url = Echonest::baseGetQuery( "song", "identify" );
addQueryInformation( url, information );
qDebug() << "Creating identify URL" << url;
QNetworkRequest request( url );
request.setHeader( QNetworkRequest::ContentTypeHeader, QLatin1String( "application/octet-stream" ) );
// qDebug() << "Uploading local file to" << url;
return Echonest::Config::instance()->nam()->post( request, data );
}
Echonest::SongList Echonest::Song::parseIdentify( QNetworkReply* reply ) throw( ParseError )
{
Echonest::Parser::checkForErrors( reply );
QByteArray data = reply->readAll();
QJson::Parser p;
QVariantMap res = p.parse( data ).toMap();
// qDebug() << "Got data from identify call:" << data << res;
qDebug() << res[ QLatin1String( "response" ) ].toMap()[ QLatin1String( "songs" ) ].toList();
if( !res.contains( QLatin1String( "response" ) ) || !res[ QLatin1String( "response" ) ].toMap().contains( QLatin1String( "songs" ) ) ) {
qDebug() << "No response or songs elemnt in json...";
throw ParseError( UnknownParseError, QLatin1String( "Invalid json response" ) );
}
SongList songs;
QVariantList songsV = res[ QLatin1String( "response" ) ].toMap()[ QLatin1String( "songs" ) ].toList();
foreach( const QVariant& s, songsV ) {
QVariantMap sM = s.toMap();
Echonest::Song song;
if( sM.contains( QLatin1String( "title" ) ) )
song.setTitle( sM[ QLatin1String( "title" ) ].toString() );
if( sM.contains( QLatin1String( "artist_id" ) ) )
song.setArtistId( sM[ QLatin1String( "artist_id" ) ].toByteArray() );
if( sM.contains( QLatin1String( "artist_name" ) ) )
song.setArtistName( sM[ QLatin1String( "artist_name" ) ].toString() );
if( sM.contains( QLatin1String( "id" ) ) )
song.setId( sM[ QLatin1String( "id" ) ].toByteArray() );
songs.append( song );
}
reply->deleteLater();
return songs;
}
void Echonest::Song::parseInformation( QNetworkReply* reply ) throw( ParseError )
{
Echonest::Parser::checkForErrors( reply );
QXmlStreamReader xml( reply->readAll() );
Echonest::Parser::readStatus( xml );
// we'll just take the new data. it is given as a list even though it can only have 1 song as we specify the song id
QVector< Echonest::Song > songs = Echonest::Parser::parseSongList( xml );
@ -204,22 +291,24 @@ void Echonest::Song::parseInformation( QNetworkReply* reply ) throw( ParseError
setArtistHotttnesss( newSong.artistHotttnesss() );
if( newSong.artistFamiliarity() >= 0 )
setArtistFamiliarity( newSong.artistFamiliarity() );
if( !newSong.artistLocation().isEmpty() )
if( !newSong.artistLocation().location.isEmpty() )
setArtistLocation( newSong.artistLocation() );
reply->deleteLater();
}
QVector< Echonest::Song > Echonest::Song::parseSearch( QNetworkReply* reply ) throw( ParseError )
{
Echonest::Parser::checkForErrors( reply );
QXmlStreamReader xml( reply->readAll() );
Echonest::Parser::readStatus( xml );
QVector<Echonest::Song> songs = Echonest::Parser::parseSongList( xml );
reply->deleteLater();
return songs;
}
QByteArray Echonest::Song::searchParamToString( Echonest::Song::SearchParam param )
@ -236,6 +325,8 @@ QByteArray Echonest::Song::searchParamToString( Echonest::Song::SearchParam para
return "description";
case Echonest::Song::ArtistId:
return "artist_id";
case Echonest::Song::Start:
return "start";
case Echonest::Song::Results:
return "results";
case Echonest::Song::MaxTempo:
@ -270,6 +361,10 @@ QByteArray Echonest::Song::searchParamToString( Echonest::Song::SearchParam para
return "max_longitude";
case Echonest::Song::MinLongitude:
return "min_longitude";
case Echonest::Song::MinEnergy:
return "min_energy";
case Echonest::Song::MaxEnergy:
return "max_energy";
case Echonest::Song::Mode:
return "mode";
case Echonest::Song::Key:
@ -280,20 +375,46 @@ QByteArray Echonest::Song::searchParamToString( Echonest::Song::SearchParam para
return QByteArray();
}
void Echonest::Song::addQueryInformation(QUrl& url, Echonest::Song::SongInformation parts)
QByteArray Echonest::Song::identifyParamToString( Echonest::Song::IdentifyParam param )
{
if( parts.testFlag( Echonest::Song::AudioSummaryInformation ) )
switch( param )
{
case Echonest::Song::Code:
return "code";
case Echonest::Song::IdentifyArtist:
return "artist";
case Echonest::Song::IdentifyDuration:
return "duration";
case Echonest::Song::IdentifyGenre:
return "genre";
case Echonest::Song::IdentifyRelease:
return "release";
case Echonest::Song::IdentifyTitle:
return "title";
}
return QByteArray();
}
void Echonest::Song::addQueryInformation(QUrl& url, Echonest::SongInformation information)
{
if( information.flags().testFlag( Echonest::SongInformation::AudioSummaryInformation ) )
url.addEncodedQueryItem( "bucket", "audio_summary" );
if( parts.testFlag( Echonest::Song::Tracks ) )
if( information.flags().testFlag( Echonest::SongInformation::Tracks ) )
url.addEncodedQueryItem( "bucket", "tracks" );
if( parts.testFlag( Echonest::Song::Hotttnesss ) )
if( information.flags().testFlag( Echonest::SongInformation::Hotttnesss ) )
url.addEncodedQueryItem( "bucket", "song_hotttnesss" );
if( parts.testFlag( Echonest::Song::ArtistHotttnesss ) )
if( information.flags().testFlag( Echonest::SongInformation::ArtistHotttnesss ) )
url.addEncodedQueryItem( "bucket", "artist_hotttnesss" );
if( parts.testFlag( Echonest::Song::ArtistFamiliarity ) )
if( information.flags().testFlag( Echonest::SongInformation::ArtistFamiliarity ) )
url.addEncodedQueryItem( "bucket", "artist_familiarity" );
if( parts.testFlag( Echonest::Song::ArtistLocation ) )
if( information.flags().testFlag( Echonest::SongInformation::ArtistLocation ) )
url.addEncodedQueryItem( "bucket", "artist_location" );
if( !information.idSpaces().isEmpty() ) {
foreach( const QString& idSpace, information.idSpaces() )
url.addEncodedQueryItem( "bucket", "id:" + idSpace.toUtf8() );
}
}

View File

@ -20,6 +20,7 @@
#include "echonest_export.h"
#include "Track.h"
#include "TypeInformation.h"
#include <QSharedData>
#include <QHash>
@ -30,30 +31,23 @@
class QNetworkReply;
class SongData;
namespace Echonest{
class DynamicPlaylist; // forward declare for friend declaration
class AudioSummary;
class DynamicPlaylist; // forward declare for friend declaration
class Catalog;
class AudioSummary;
/**
* This encapsulates an Echo Nest song---use it if you wish to get information about a song,
* search for a song, etc.
*
*
* This class is implicitly shared.
*/
class ECHONEST_EXPORT Song
{
public:
enum SongInformationFlag {
AudioSummaryInformation = 0x01,
Tracks = 0x02,
Hotttnesss = 0x04,
ArtistHotttnesss = 0x08,
ArtistFamiliarity = 0x10,
ArtistLocation = 0x20
};
Q_DECLARE_FLAGS( SongInformation, SongInformationFlag )
enum SearchParam {
Title,
@ -61,6 +55,7 @@ public:
Combined,
Description,
ArtistId,
Start,
Results,
MaxTempo,
MinTempo,
@ -78,129 +73,162 @@ public:
MinHotttnesss,
MaxLongitude,
MinLongitude,
MaxEnergy,
MinEnergy,
Mode,
Key,
Sort
Sort,
};
typedef QPair< Echonest::Song::SearchParam, QVariant > SearchParamData;
typedef QVector< SearchParamData > SearchParams;
enum IdentifyParam {
Code,
IdentifyArtist,
IdentifyTitle,
IdentifyRelease,
IdentifyDuration,
IdentifyGenre
};
typedef QPair< Echonest::Song::IdentifyParam, QVariant > IdentifyParamData;
typedef QVector< IdentifyParamData > IdentifyParams;
Song();
Song( const QByteArray& id, const QString& title, const QByteArray& artistId, const QString& artistName );
Song( const QByteArray& id );
Song( const Song& other );
Song& operator=(const Song& song);
~Song();
virtual ~Song();
/**
* The following pieces of data are present in all Song objects, and do not require
* on-demand fetching.
*/
QByteArray id() const;
void setId( const QByteArray& id );
QString title() const;
void setTitle( const QString& title );
QString artistName() const;
void setArtistName( const QString& artistName );
QByteArray artistId() const;
void setArtistId( const QByteArray& artistId );
/**
QString release() const;
void setRelease( const QString& release );
/**
* The following require fetching from The Echo Nest, so call
* fetchInformation() with the type of data you want first.
*
*
* If you ask for this information before calling parseInformation()
* with the respective data, the result is undefined.
*/
/**
* The full audio summary and analysis of this song.
*
* NOTE: This will return a copy of the AudioSummary object, which
* is implicitly shared. If you make modifications to the returned
* summary, for example by calling parseFullAnalysis(), it will detach
* and you will have to call setAudioSummary() to save the changes back
* to this Song object.
*/
AudioSummary audioSummary() const;
void setAudioSummary( const AudioSummary& summary );
/**
* The associated Track objects with acoustic track information
*/
QVector< Track > tracks() const;
void setTracks( const QVector< Track >& tracks );
/**
* The "hotttnesss" metric of this song.
*/
qreal hotttnesss() const;
void setHotttnesss( qreal hotttnesss );
/**
* The "hotttnesss" metric of this song's artist.
*/
qreal artistHotttnesss() const;
void setArtistHotttnesss( qreal artistHotttnesss );
/**
* The familiarity metric of this song's artist.
*/
qreal artistFamiliarity() const;
void setArtistFamiliarity( qreal artistFamiliarity );
/**
* The location of this artist.
*/
QString artistLocation() const;
void setArtistLocation( const QString& artistLocation );
ArtistLocation artistLocation() const;
void setArtistLocation( const ArtistLocation& artistLocation );
/**
* This fetch the data from The Echo Nest for the requested data, so it
* returns a QNetworkReply*. When the finished() signal is emitted
* This fetches the data from The Echo Nest for the requested data, so it
* returns a QNetworkReply*. When the finished() signal is emitted
* from the QNetworkReply object call parseInformation() to save the
* data back to this Song object.
*
*
*/
QNetworkReply* fetchInformation( SongInformation parts ) const;
QNetworkReply* fetchInformation( SongInformation information = SongInformation() ) const;
/**
* Search for a song from The Echo Nest with the given search parameters. See
* Search for a song from The Echo Nest with the given search parameters. See
* http://developer.echonest.com/docs/v4/song.html#search for a description of the
* parameters and data types.
*
*
* The result will contain the requested information from the SongInformation flags, and
* can be extracted in the parseSearch() function.
*
*
*/
static QNetworkReply* search( const SearchParams& params, SongInformation parts );
static QNetworkReply* search( const SearchParams& params, SongInformation information = SongInformation() );
/**
* Identify a song from a given Echo Nest fingerprint hash code.
* NOTE: SongInformation is currently not parsed yet.
*
*/
static QNetworkReply* identify( const IdentifyParams& params, const SongInformation& information = SongInformation() );
/**
* Identify a song from the Echoprint hash code, this time using the output of the 'echoprint-codegen' command-line
* tool
*/
// static QNetworkReply* identify( const QByteArray& jsonData );
/**
* Parses the reply of the identify call and returns a list of songs found.
*
*/
static QVector< Song > parseIdentify( QNetworkReply* ) throw( ParseError );
/**
* Parse the result of the fetchInformation() call.
* For each requested SongInformationFlag in the original request, the respective
* data will be saved to this Song object.
*/
void parseInformation( QNetworkReply* reply ) throw( ParseError );
/**
* Parse the result of the search() call.
*/
static QVector<Song> parseSearch( QNetworkReply* reply ) throw( ParseError );
/**
* Identify a song from a given Echo Nest fingerprint hash code
*
* NOTE this is currently not supported, as the Echo Nest hash code
* generator is not currently open source, so I don't care much
* for it.
*
* static QNetworkReply* identify( ) const;
*/
QString toString() const;
friend class DynamicPlaylist;
friend class Catalog; // for access to searchParamToString
private:
static QByteArray searchParamToString( SearchParam param );
static void addQueryInformation( QUrl& url, SongInformation parts );
static QByteArray identifyParamToString( IdentifyParam param );
static void addQueryInformation( QUrl& url, SongInformation information );
QSharedDataPointer<SongData> d;
};
@ -208,10 +236,8 @@ typedef QVector< Song > SongList;
ECHONEST_EXPORT QDebug operator<<(QDebug d, const Song &song);
Q_DECLARE_OPERATORS_FOR_FLAGS(Song::SongInformation)
}; // namespace
} // namespace
Q_DECLARE_METATYPE( Echonest::Song::SongInformation )
Q_DECLARE_METATYPE( Echonest::Song )
#endif

View File

@ -28,7 +28,7 @@
class SongData : public QSharedData
{
public:
SongData() : hotttnesss( -1 ), artistHotttnesss( -1 ), artistFamiliarity( -1 ) {}
SongData() : hotttnesss( -1 ), artistHotttnesss( -1 ), artistFamiliarity( -1 ) { artistLocation.latitude = -1; artistLocation.longitude = -1; }
SongData(const SongData& other)
{
@ -51,6 +51,7 @@ public:
QString title;
QString artistName;
QByteArray artistId;
QString release;
// The rest are optional that require manual fetching to populate
Echonest::AudioSummary audioSummary;
@ -58,7 +59,7 @@ public:
qreal hotttnesss;
qreal artistHotttnesss;
qreal artistFamiliarity;
QString artistLocation;
Echonest::ArtistLocation artistLocation;
};

View File

@ -19,6 +19,7 @@
#include "Track_p.h"
#include <QNetworkReply>
#include "Config.h"
#include "Song.h"
#include <qfileinfo.h>
#include "Parsing_p.h"
@ -31,6 +32,13 @@ Echonest::Track::Track(const Echonest::Track& other)
: d( other.d )
{}
Echonest::Track::Track(const QByteArray& id)
: d( new TrackData )
{
d->id = id;
}
Echonest::Track::~Track()
{
}
@ -155,13 +163,63 @@ void Echonest::Track::setAudioSummary( const Echonest::AudioSummary& summary )
d->audio_summary = summary;
}
QString Echonest::Track::catalog() const
{
return d->catalog;
}
void Echonest::Track::setCatalog(const QString& catalog)
{
d->catalog = catalog;
}
QByteArray Echonest::Track::foreignId() const
{
return d->foreign_id;
}
void Echonest::Track::setForeignId(const QByteArray& id)
{
d->foreign_id = id;
}
QUrl Echonest::Track::previewUrl() const
{
return d->preview_url;
}
void Echonest::Track::setPreviewUrl(const QUrl& preview)
{
d->preview_url = preview;
}
QUrl Echonest::Track::releaseImage() const
{
return d->release_image;
}
void Echonest::Track::setReleaseImage(const QUrl& imgUrl)
{
d->release_image = imgUrl;
}
Echonest::Song Echonest::Track::song() const
{
return d->song;
}
void Echonest::Track::setSong(const Echonest::Song& song)
{
d->song = song;
}
QNetworkReply* Echonest::Track::profileFromTrackId( const QByteArray& id )
{
QUrl url = Echonest::baseGetQuery( "track", "profile" );
url.addEncodedQueryItem( "id", id );
url.addEncodedQueryItem( "bucket", "audio_summary" );
qDebug() << "Creating profileFromTrackId URL" << url;
return Echonest::Config::instance()->nam()->get( QNetworkRequest( url ) );
}
@ -171,7 +229,7 @@ QNetworkReply* Echonest::Track::profileFromMD5( const QByteArray& md5 )
QUrl url = Echonest::baseGetQuery( "track", "profile" );
url.addEncodedQueryItem( "md5", md5 );
url.addEncodedQueryItem( "bucket", "audio_summary" );
qDebug() << "Creating profileFromMD5 URL" << url;
return Echonest::Config::instance()->nam()->get( QNetworkRequest( url ) );
}
@ -184,7 +242,7 @@ QNetworkReply* Echonest::Track::uploadLocalFile( const QUrl& localFile, const QB
url.addEncodedQueryItem( "bucket", "audio_summary" );
url.addEncodedQueryItem( "wait", ( waitForResult ? "true" : "false" ) );
QNetworkRequest request( url );
request.setHeader( QNetworkRequest::ContentTypeHeader, QLatin1String( "application/octet-stream" ) );
// qDebug() << "Uploading local file to" << url;
return Echonest::Config::instance()->nam()->post( request, data );
@ -196,9 +254,11 @@ QNetworkReply* Echonest::Track::uploadURL( const QUrl& remoteURL, bool waitForRe
url.addEncodedQueryItem( "url", remoteURL.toEncoded() );
url.addEncodedQueryItem( "bucket", "audio_summary" );
url.addEncodedQueryItem( "wait", ( waitForResult ? "true" : "false" ) );
qDebug() << "Uploading URL:" << url;
return Echonest::Config::instance()->nam()->post( QNetworkRequest( url ), QByteArray() );
QNetworkRequest req( url );
req.setHeader( QNetworkRequest::ContentTypeHeader, QLatin1String( "application/x-www-form-urlencoded" ) );
return Echonest::Config::instance()->nam()->post( req, QByteArray() );
}
QNetworkReply* Echonest::Track::analyzeTrackId( const QByteArray& id, bool wait )
@ -207,9 +267,10 @@ QNetworkReply* Echonest::Track::analyzeTrackId( const QByteArray& id, bool wait
url.addEncodedQueryItem( "id", id );
url.addEncodedQueryItem( "bucket", "audio_summary" );
url.addEncodedQueryItem( "wait", ( wait ? "true" : "false" ) );
qDebug() << "Creating analyzeTrackId URL" << url;
return Echonest::Config::instance()->nam()->post( QNetworkRequest( url ), QByteArray() );
return Echonest::doPost( url );
// return Echonest::Config::instance()->nam()->post( QNetworkRequest( url ), QByteArray() );
}
QNetworkReply* Echonest::Track::analyzeTrackMD5( const QByteArray& md5, bool wait )
@ -218,22 +279,24 @@ QNetworkReply* Echonest::Track::analyzeTrackMD5( const QByteArray& md5, bool wai
url.addEncodedQueryItem( "md5", md5 );
url.addEncodedQueryItem( "bucket", "audio_summary" );
url.addEncodedQueryItem( "wait", ( wait ? "true" : "false" ) );
qDebug() << "Creating analyzeTrackMD5 URL" << url;
return Echonest::Config::instance()->nam()->post( QNetworkRequest( url ), QByteArray() );
return Echonest::doPost( url );
// return Echonest::Config::instance()->nam()->post( QNetworkRequest( url ), QByteArray() );
}
Echonest::Track Echonest::Track::parseProfile( QNetworkReply* finishedReply ) throw( Echonest::ParseError )
{
Echonest::Parser::checkForErrors( finishedReply );
QByteArray data = finishedReply->readAll();
qDebug() << data;
Echonest::Parser::checkForErrors( finishedReply );
QXmlStreamReader xml( data );
Echonest::Parser::readStatus( xml );
Echonest::Track track = Echonest::Parser::parseTrack( xml );
finishedReply->deleteLater();
return track;
}
@ -241,7 +304,7 @@ Echonest::Track Echonest::Track::parseProfile( QNetworkReply* finishedReply ) th
QDebug Echonest::operator<<(QDebug d, const Echonest::Track& track)
{
d << QString::fromLatin1( "Track(%1, %2, %3" ).arg( track.title() ).arg( track.artist() ).arg( track.release() );
d << QString::fromLatin1( "Track(%1, %2, %3, %4)" ).arg( QLatin1String( track.id() ) ).arg( track.title() ).arg( track.artist() ).arg( track.release() );
return d.maybeSpace();
}

View File

@ -34,7 +34,8 @@ class TrackData;
namespace Echonest
{
class Song;
/**
* Upload-based Echo Nest Track API. If you want to search The Echo Nest for songs, use the Song API.
* If you want to upload your own files and retrieve the acoustic information about them, use this Track
@ -50,6 +51,7 @@ class ECHONEST_EXPORT Track
public:
Track();
explicit Track( const QByteArray& id );
Track( const Track& other );
Track& operator=( const Track& track );
~Track();
@ -107,7 +109,42 @@ public:
*/
int bitrate() const;
void setBitrate( int );
/**
* If this track is fetched from a tracks bucket of a song search, the following information
* will be populated for some id spaces.
*/
/**
* The catalog this track is from, if not a native Echo Nest track
*/
QString catalog() const;
void setCatalog( const QString& catalog );
/**
* The foreign id of this track, that is in the \c catalog catalog.
*/
QByteArray foreignId() const;
void setForeignId( const QByteArray& id );
/**
* The release image associated with this track
*/
QUrl releaseImage() const;
void setReleaseImage( const QUrl& imgUrl );
/**
* The preview url for this track, if it exists
*/
QUrl previewUrl() const;
void setPreviewUrl( const QUrl& preview );
/**
* The Echo Nest song associated with this track, if it exists
*/
Song song() const;
void setSong( const Song& song );
/**
* The analysis status
*/
@ -121,6 +158,12 @@ public:
*
* Information about how to interpret the results of the audio summary can be found here:
* http://developer.echonest.com/docs/v4/_static/AnalyzeDocumentation_2.2.pdf
*
* NOTE: This will return a copy of the AudioSummary object, which
* is implicitly shared. If you make modifications to the returned
* summary, for example by calling parseFullAnalysis(), it will detach
* and you will have to call setAudioSummary() to save the changes back
* to this Song object.
*/
AudioSummary audioSummary() const;
void setAudioSummary( const AudioSummary& summary );
@ -177,6 +220,7 @@ private:
QSharedDataPointer<TrackData> d;
};
typedef QVector<Track> Tracks;
ECHONEST_EXPORT QDebug operator<<(QDebug d, const Echonest::Track& track);

View File

@ -18,15 +18,40 @@
#define ECHONEST_TRACK_P_H
#include "AudioSummary.h"
#include "Config.h"
#include "Song.h"
#include <QSharedData>
#include <QString>
#include <QNetworkReply>
namespace Echonest {
inline QNetworkReply* doPost(const QUrl& url)
{
// UGLY :( Build url, then extract the encded query items, put them in the POST body, and send that to the url minus the encoded params.
// The final data
QByteArray data;
int size = url.encodedQueryItems().size();
for( int i = 0; i < size; i++ ) {
const QPair< QByteArray, QByteArray > item = url.encodedQueryItems().at( i );
data.append( item.first + "=" + item.second + "&" );
}
data.truncate( data.size() - 1 ); // remove extra &
//qDebug() << "Sending data:" << data << "for method:" << url.path();
// strip the extras
QUrl url2( url.toString().mid( 0, url.toString().indexOf( QLatin1Char( '?' ) ) ) );
QNetworkRequest request = QNetworkRequest( url2 );
request.setHeader( QNetworkRequest::ContentTypeHeader, QLatin1String( "application/x-www-form-urlencoded" ) );
return Echonest::Config::instance()->nam()->post( request, data );
}
};
class TrackData : public QSharedData
{
public:
TrackData() {}
TrackData(const TrackData& other)
{
analyzer_version = other.analyzer_version;
@ -38,9 +63,13 @@ public:
samplerate = other.samplerate;
status = other.status;
title = other.title;
catalog = other.catalog;
foreign_id = other.foreign_id;
release_image = other.release_image;
preview_url = other.preview_url;
}
QString artist;
QString analyzer_version;
int bitrate;
@ -51,9 +80,17 @@ public:
int samplerate;
QString status;
QString title;
// used when fetched as a foreign id in a tracks bucket
QString catalog;
QByteArray foreign_id;
QUrl release_image;
QUrl preview_url;
// song tracks have an associated song
Echonest::Song song;
Echonest::AudioSummary audio_summary;
};
#endif

183
3rdparty/libechonest/TypeInformation.cpp vendored Normal file
View File

@ -0,0 +1,183 @@
/****************************************************************************************
* Copyright (c) 2010 Leo Franchi <lfranchi@kde.org> *
* *
* 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 "TypeInformation.h"
#include <QStringList>
namespace Echonest {
class ArtistInformationPrivate
{
public:
ArtistInformationPrivate() : flags( ArtistInformation::NoInformation )
{}
Echonest::ArtistInformation::ArtistInformationFlags flags;
QStringList idSpaces;
};
class SongInformationPrivate
{
public:
SongInformationPrivate() : flags( SongInformation::NoInformation )
{}
SongInformation::SongInformationFlags flags;
QStringList idSpaces;
};
}; // namespace
Echonest::ArtistInformation::ArtistInformation()
: d_ptr( new Echonest::ArtistInformationPrivate )
{
Q_D( ArtistInformation );
d->flags = Echonest::ArtistInformation::NoInformation;
}
Echonest::ArtistInformation::ArtistInformation( ArtistInformationFlags flags )
: d_ptr( new Echonest::ArtistInformationPrivate )
{
Q_D( ArtistInformation );
d->flags = flags;
}
Echonest::ArtistInformation::ArtistInformation( ArtistInformation::ArtistInformationFlags flags, const QStringList& idSpaces )
: d_ptr( new Echonest::ArtistInformationPrivate )
{
Q_D( Echonest::ArtistInformation );
d->flags = flags;
d->idSpaces = idSpaces;
}
Echonest::ArtistInformation::ArtistInformation( const Echonest::ArtistInformation& other )
: d_ptr( new Echonest::ArtistInformationPrivate( *other.d_ptr ) )
{
}
Echonest::ArtistInformation::~ArtistInformation()
{
delete d_ptr;
}
Echonest::ArtistInformation& Echonest::ArtistInformation::operator=( const Echonest::ArtistInformation& typeInfo )
{
d_ptr = new Echonest::ArtistInformationPrivate( *typeInfo.d_ptr );
return *this;
}
Echonest::ArtistInformation::ArtistInformationFlags Echonest::ArtistInformation::flags() const
{
Q_D( const Echonest::ArtistInformation );
return d->flags;
}
void Echonest::ArtistInformation::setArtistInformationFlags( ArtistInformationFlags flags)
{
Q_D( Echonest::ArtistInformation );
d->flags = flags;
}
QStringList Echonest::ArtistInformation::idSpaces() const
{
Q_D( const Echonest::ArtistInformation );
return d->idSpaces;
}
void Echonest::ArtistInformation::setIdSpaces(const QStringList& idspaces)
{
Q_D( Echonest::ArtistInformation );
d->idSpaces = idspaces;
}
Echonest::SongInformation::SongInformation()
: d_ptr( new Echonest::SongInformationPrivate )
{
Q_D( Echonest::SongInformation );
d->flags = Echonest::SongInformation::NoInformation;
}
Echonest::SongInformation::SongInformation( SongInformationFlags flags )
: d_ptr( new Echonest::SongInformationPrivate )
{
Q_D( SongInformation );
d->flags = flags;
}
Echonest::SongInformation::SongInformation( SongInformation::SongInformationFlags flags, const QStringList& idSpaces )
: d_ptr( new Echonest::SongInformationPrivate )
{
Q_D( Echonest::SongInformation );
d->flags = flags;
d->idSpaces = idSpaces;
}
Echonest::SongInformation::SongInformation( const Echonest::SongInformation& other )
: d_ptr( new Echonest::SongInformationPrivate( *other.d_ptr ) )
{
}
Echonest::SongInformation::~SongInformation()
{
delete d_ptr;
}
Echonest::SongInformation& Echonest::SongInformation::operator=( const Echonest::SongInformation& info )
{
d_ptr = new Echonest::SongInformationPrivate( *info.d_ptr );
return *this;
}
Echonest::SongInformation::SongInformationFlags Echonest::SongInformation::flags() const
{
Q_D( const Echonest::SongInformation );
return d->flags;
}
void Echonest::SongInformation::setSongInformationFlags( SongInformationFlags flags )
{
Q_D( Echonest::SongInformation );
d->flags = flags;
}
QStringList Echonest::SongInformation::idSpaces() const
{
Q_D( const Echonest::SongInformation );
return d->idSpaces;
}
void Echonest::SongInformation::setIdSpaces(const QStringList& idspaces)
{
Q_D( Echonest::SongInformation );
d->idSpaces = idspaces;
}

135
3rdparty/libechonest/TypeInformation.h vendored Normal file
View File

@ -0,0 +1,135 @@
/****************************************************************************************
* Copyright (c) 2010 Leo Franchi <lfranchi@kde.org> *
* *
* 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/>. *
****************************************************************************************/
#ifndef ECHONEST_TYPEINFORMATION_H
#define ECHONEST_TYPEINFORMATION_H
#include "echonest_export.h"
#include <qglobal.h>
#include <QStringList>
#include <QMetaType>
namespace Echonest {
class ArtistInformationPrivate;
class SongInformationPrivate;
/**
* This class describes what artist information to return with a query.
*
* The default behaviour is NoInformation.
*/
class ECHONEST_EXPORT ArtistInformation
{
public:
enum ArtistInformationFlag {
NoInformation = 0x0000,
Audio = 0x0001,
Biographies = 0x0002,
Blogs = 0x0004,
Familiarity = 0x0008,
Hotttnesss = 0x0010,
Images = 0x0020,
News = 0x0040,
Reviews = 0x0080,
Terms = 0x0100,
Urls = 0x200,
Videos = 0x0400,
};
Q_DECLARE_FLAGS( ArtistInformationFlags, ArtistInformationFlag )
ArtistInformation();
ArtistInformation( ArtistInformationFlags flags );
ArtistInformation( ArtistInformationFlags flags, const QStringList& idSpaces );
ArtistInformation( const ArtistInformation& other );
~ArtistInformation();
ArtistInformation& operator=( const ArtistInformation& typeInfo );
/**
* The individual pieces of information to fetch for this artist.
*
* Use \c setIdSpaces to set an id space for this query.
*/
ArtistInformationFlags flags() const;
void setArtistInformationFlags( ArtistInformationFlags flags );
/**
* The id spaces to limit this to. Do not include the "id:" prefix.
*/
QStringList idSpaces() const;
void setIdSpaces( const QStringList& idspaces );
private:
ArtistInformationPrivate* d_ptr;
Q_DECLARE_PRIVATE( ArtistInformation )
};
Q_DECLARE_OPERATORS_FOR_FLAGS( ArtistInformation::ArtistInformationFlags )
/**
* This class describes what song information to return with a query.
*
* The default behaviour is NoInformation.
*/
class ECHONEST_EXPORT SongInformation
{
public:
enum SongInformationFlag {
AudioSummaryInformation = 0x001,
Tracks = 0x002,
Hotttnesss = 0x04,
ArtistHotttnesss = 0x008,
ArtistFamiliarity = 0x010,
ArtistLocation = 0x020,
NoInformation = 0x800
};
Q_DECLARE_FLAGS( SongInformationFlags, SongInformationFlag )
SongInformation();
SongInformation( SongInformationFlags flags );
SongInformation( SongInformationFlags flags, const QStringList& idSpaces );
SongInformation( const SongInformation& other );
~SongInformation();
SongInformation& operator=( const SongInformation& info );
/**
* The individual pieces of information to fetch for this song.
* If id spaces are desired,see \c setIdSpaces for more information.
*/
SongInformationFlags flags() const;
void setSongInformationFlags( SongInformationFlags flags );
/**
* The id spaces to limit this to. Do not include the "id:" prefix.
*/
QStringList idSpaces() const;
void setIdSpaces( const QStringList& idspaces );
private:
SongInformationPrivate* d_ptr;
Q_DECLARE_PRIVATE( SongInformation )
};
Q_DECLARE_OPERATORS_FOR_FLAGS(SongInformation::SongInformationFlags)
};
Q_DECLARE_METATYPE( Echonest::ArtistInformation )
Q_DECLARE_METATYPE( Echonest::SongInformation )
#endif

View File

@ -48,3 +48,83 @@ QString Echonest::statusToString(Echonest::Analysis::AnalysisStatus status)
return QString();
}
QByteArray Echonest::catalogTypeToLiteral(Echonest::CatalogTypes::Type type)
{
switch( type )
{
case Echonest::CatalogTypes::Artist:
return "artist";
case Echonest::CatalogTypes::Song:
return "song";
default:
return "";
}
}
Echonest::CatalogTypes::Type Echonest::literalToCatalogType( const QByteArray& type )
{
if( type == "artist" )
return Echonest::CatalogTypes::Artist;
else if( type == "song" )
return Echonest::CatalogTypes::Song;
else
return Echonest::CatalogTypes::Artist;
}
QByteArray Echonest::catalogStatusToLiteral(Echonest::CatalogTypes::TicketStatus status)
{
return statusToString( static_cast<Echonest::Analysis::AnalysisStatus>( status ) ).toLatin1();
}
Echonest::CatalogTypes::TicketStatus Echonest::literalToCatalogStatus(const QByteArray& type)
{
return static_cast<Echonest::CatalogTypes::TicketStatus>( statusToEnum( QLatin1String( type ) ) );
}
/**
* Delete,
U pda*te,
Play,
Skip */
QByteArray Echonest::catalogUpdateActionToLiteral(Echonest::CatalogTypes::Action action)
{
switch( action )
{
case Echonest::CatalogTypes::Delete:
return "delete";
case Echonest::CatalogTypes::Play:
return "play";
case Echonest::CatalogTypes::Update:
return "update";
case Echonest::CatalogTypes::Skip:
return "skip";
default:
return "";
}
}
Echonest::CatalogTypes::Action Echonest::literalToCatalogUpdateAction(const QByteArray& type)
{
if( type == "delete" )
return Echonest::CatalogTypes::Delete;
else if( type == "play" )
return Echonest::CatalogTypes::Play;
else if( type == "update" )
return Echonest::CatalogTypes::Update;
else if( type == "skip" )
return Echonest::CatalogTypes::Skip;
return Echonest::CatalogTypes::Update;
}
QDebug Echonest::operator<<(QDebug d, const Echonest::ForeignId& id)
{
return d.maybeSpace() << QString::fromLatin1( "Foreign Id(%1, %2)" ).arg( id.catalog ).arg( id.foreign_id );
}
QDebug Echonest::operator<<(QDebug d, const Echonest::ArtistLocation& loc)
{
return d.maybeSpace() << QString::fromLatin1( "Artist Location(%1, %2, %3)" ).arg( loc.location ).arg( loc.latitude ).arg( loc.longitude );
}

View File

@ -17,6 +17,9 @@
#ifndef ECHONEST_UTIL_H
#define ECHONEST_UTIL_H
#include "echonest_export.h"
#include <QDebug>
#include <QVector>
#include <QUrl>
@ -36,6 +39,28 @@ namespace Echonest
};
}
namespace CatalogTypes
{
enum Type {
Artist = 0,
Song = 1
};
enum Action {
Delete,
Update,
Play,
Skip
};
enum TicketStatus {
Unknown = 0,
Pending = 1,
Complete = 2,
Error = 4
};
}
typedef struct
{
qreal confidence;
@ -73,8 +98,33 @@ namespace Echonest
QString type;
} License;
typedef struct {
QString catalog;
QString foreign_id;
} ForeignId;
typedef struct {
qreal latitude;
qreal longitude;
QString location;
} ArtistLocation;
typedef QVector< ForeignId > ForeignIds;
Analysis::AnalysisStatus statusToEnum( const QString& status );
QString statusToString( Analysis::AnalysisStatus status );
QByteArray catalogTypeToLiteral( CatalogTypes::Type );
CatalogTypes::Type literalToCatalogType( const QByteArray& type );
QByteArray catalogStatusToLiteral( CatalogTypes::TicketStatus );
CatalogTypes::TicketStatus literalToCatalogStatus( const QByteArray& type );
QByteArray catalogUpdateActionToLiteral( CatalogTypes::Action );
CatalogTypes::Action literalToCatalogUpdateAction( const QByteArray& type );
ECHONEST_EXPORT QDebug operator<<(QDebug d, const ForeignId& id);
ECHONEST_EXPORT QDebug operator<<(QDebug d, const ArtistLocation& id);
}
#endif

View File

@ -17,8 +17,8 @@
#ifndef ECHONEST_EXPORT_H
#define ECHONEST_EXPORT_H
#ifdef Q_CC_MSVC
#define ECHONEST_EXPORT __declspec(dllimport)
#ifdef _WIN32
#define ECHONEST_EXPORT __declspec(dllexport)
#elif __GNUC__ >= 4
#define ECHONEST_EXPORT __attribute__ ((visibility("default")))
#else