Add libechonest into 3rdparty, and add a basic echonest artist info fetcher.
This commit is contained in:
parent
7f3e91226c
commit
d035b1abc2
545
3rdparty/libechonest/Artist.cpp
vendored
Normal file
545
3rdparty/libechonest/Artist.cpp
vendored
Normal file
@ -0,0 +1,545 @@
|
||||
/****************************************************************************************
|
||||
* 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 "Artist.h"
|
||||
#include "Artist_p.h"
|
||||
#include "ArtistTypes.h"
|
||||
#include "Parsing_p.h"
|
||||
|
||||
Echonest::Artist::Artist()
|
||||
: d( new ArtistData )
|
||||
{
|
||||
}
|
||||
|
||||
Echonest::Artist::Artist( const QByteArray& id, const QString& name )
|
||||
: d( new ArtistData )
|
||||
{
|
||||
d->id = id;
|
||||
d->name = name;
|
||||
}
|
||||
|
||||
Echonest::Artist::Artist(const Echonest::Artist& other)
|
||||
: d( other.d )
|
||||
{}
|
||||
|
||||
Echonest::Artist& Echonest::Artist::operator=(const Echonest::Artist& artist)
|
||||
{
|
||||
d = artist.d;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Echonest::Artist::~Artist()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
QByteArray Echonest::Artist::id() const
|
||||
{
|
||||
return d->id;
|
||||
}
|
||||
|
||||
QString Echonest::Artist::name() const
|
||||
{
|
||||
return d->name;
|
||||
}
|
||||
|
||||
void Echonest::Artist::setId(const QByteArray& id)
|
||||
{
|
||||
d->id = id;
|
||||
}
|
||||
|
||||
void Echonest::Artist::setName(const QString& name)
|
||||
{
|
||||
d->name = name;
|
||||
}
|
||||
|
||||
Echonest::AudioList Echonest::Artist::audio() const
|
||||
{
|
||||
return d->audio;
|
||||
}
|
||||
|
||||
void Echonest::Artist::setAudio(const Echonest::AudioList& audio)
|
||||
{
|
||||
d->audio = audio;
|
||||
}
|
||||
|
||||
|
||||
Echonest::BiographyList Echonest::Artist::biographies() const
|
||||
{
|
||||
return d->biographies;
|
||||
}
|
||||
|
||||
void Echonest::Artist::setBiographies(const Echonest::BiographyList& bios )
|
||||
{
|
||||
d->biographies = bios;
|
||||
}
|
||||
|
||||
Echonest::BlogList Echonest::Artist::blogs() const
|
||||
{
|
||||
return d->blogs;
|
||||
}
|
||||
|
||||
void Echonest::Artist::setBlogs(const Echonest::BlogList& blogs )
|
||||
{
|
||||
d->blogs = blogs;
|
||||
}
|
||||
|
||||
qreal Echonest::Artist::familiarity() const
|
||||
{
|
||||
return d->familiarity;
|
||||
}
|
||||
|
||||
void Echonest::Artist::setFamiliarity(qreal familiar)
|
||||
{
|
||||
d->familiarity = familiar;
|
||||
}
|
||||
|
||||
qreal Echonest::Artist::hotttnesss() const
|
||||
{
|
||||
return d->hotttnesss;
|
||||
}
|
||||
|
||||
void Echonest::Artist::setHotttnesss(qreal hotttnesss)
|
||||
{
|
||||
d->hotttnesss = hotttnesss;
|
||||
}
|
||||
|
||||
Echonest::ArtistImageList Echonest::Artist::images() const
|
||||
{
|
||||
return d->images;
|
||||
}
|
||||
|
||||
void Echonest::Artist::setImages(const Echonest::ArtistImageList& imgs)
|
||||
{
|
||||
d->images = imgs;
|
||||
}
|
||||
|
||||
Echonest::NewsList Echonest::Artist::news() const
|
||||
{
|
||||
return d->news;
|
||||
}
|
||||
|
||||
void Echonest::Artist::setNews(const Echonest::NewsList& news)
|
||||
{
|
||||
d->news = news;
|
||||
}
|
||||
|
||||
Echonest::ReviewList Echonest::Artist::reviews() const
|
||||
{
|
||||
return d->reviews;
|
||||
}
|
||||
|
||||
void Echonest::Artist::setReviews(const Echonest::ReviewList& reviews)
|
||||
{
|
||||
d->reviews = reviews;
|
||||
}
|
||||
|
||||
Echonest::SongList Echonest::Artist::songs() const
|
||||
{
|
||||
return d->songs;
|
||||
}
|
||||
|
||||
void Echonest::Artist::setSongs(const Echonest::SongList& songs)
|
||||
{
|
||||
d->songs = songs;
|
||||
}
|
||||
|
||||
Echonest::TermList Echonest::Artist::terms() const
|
||||
{
|
||||
return d->terms;
|
||||
}
|
||||
|
||||
void Echonest::Artist::setTerms(const Echonest::TermList& terms)
|
||||
{
|
||||
d->terms = terms;
|
||||
}
|
||||
|
||||
QUrl Echonest::Artist::amazonUrl() const
|
||||
{
|
||||
return d->amazon_url;
|
||||
}
|
||||
|
||||
void Echonest::Artist::setVideos(const Echonest::VideoList& videos)
|
||||
{
|
||||
d->videos = videos;
|
||||
}
|
||||
|
||||
void Echonest::Artist::setAmazonUrl(const QUrl& url)
|
||||
{
|
||||
d->amazon_url = url;
|
||||
}
|
||||
|
||||
|
||||
QUrl Echonest::Artist::aolMusicUrl() const
|
||||
{
|
||||
return d->aolmusic_url;
|
||||
}
|
||||
|
||||
void Echonest::Artist::setAolMusicUrl(const QUrl& url)
|
||||
{
|
||||
d->aolmusic_url = url;
|
||||
}
|
||||
|
||||
QUrl Echonest::Artist::itunesUrl() const
|
||||
{
|
||||
return d->itunes_url;
|
||||
}
|
||||
|
||||
void Echonest::Artist::setItunesUrl( const QUrl& url )
|
||||
{
|
||||
d->itunes_url = url;
|
||||
}
|
||||
|
||||
QUrl Echonest::Artist::lastFmUrl() const
|
||||
{
|
||||
return d->lastfm_url;
|
||||
}
|
||||
|
||||
void Echonest::Artist::setLastFmUrl(const QUrl& url )
|
||||
{
|
||||
d->lastfm_url = url;
|
||||
}
|
||||
|
||||
QUrl Echonest::Artist::myspaceUrl() const
|
||||
{
|
||||
return d->myspace_url;
|
||||
}
|
||||
|
||||
void Echonest::Artist::setMyspaceUrl( const QUrl& url )
|
||||
{
|
||||
d->myspace_url = url;
|
||||
}
|
||||
|
||||
QUrl Echonest::Artist::musicbrainzUrl() const
|
||||
{
|
||||
return d->mb_url;
|
||||
}
|
||||
|
||||
void Echonest::Artist::setMusicbrainzUrl(const QUrl& url)
|
||||
{
|
||||
d->mb_url = url;
|
||||
}
|
||||
|
||||
|
||||
Echonest::VideoList Echonest::Artist::videos() const
|
||||
{
|
||||
return d->videos;
|
||||
}
|
||||
|
||||
|
||||
QNetworkReply* Echonest::Artist::fetchAudio(int numResults, int offset) const
|
||||
{
|
||||
QUrl url = setupQuery( "audio", numResults, offset );
|
||||
return Echonest::Config::instance()->nam()->get( QNetworkRequest( url ) );
|
||||
}
|
||||
|
||||
QNetworkReply* Echonest::Artist::fetchBiographies(const QString& license, int numResults, int offset) const
|
||||
{
|
||||
QUrl url = setupQuery( "biographies", numResults, offset );
|
||||
if( !license.isEmpty() )
|
||||
url.addQueryItem( QLatin1String( "license" ), license );
|
||||
|
||||
return Echonest::Config::instance()->nam()->get( QNetworkRequest( url ) );
|
||||
}
|
||||
|
||||
QNetworkReply* Echonest::Artist::fetchBlogs( bool highRelevanceOnly, int numResults, int offset ) const
|
||||
{
|
||||
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 ) );
|
||||
}
|
||||
|
||||
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 ) );
|
||||
}
|
||||
|
||||
QNetworkReply* Echonest::Artist::fetchImages( const QString& license, int numResults, int offset ) const
|
||||
{
|
||||
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
|
||||
{
|
||||
QUrl url = setupQuery( "profile", 0, -1 );
|
||||
addQueryInformation( url, information );
|
||||
|
||||
return Echonest::Config::instance()->nam()->get( QNetworkRequest( url ) );
|
||||
}
|
||||
|
||||
QNetworkReply* Echonest::Artist::fetchNews( bool highRelevanceOnly, int numResults, int offset ) const
|
||||
{
|
||||
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 )
|
||||
{
|
||||
QUrl url = Echonest::baseGetQuery( "artist", "similar" );
|
||||
addQueryInformation( url, information );
|
||||
|
||||
if( numResults > 0 )
|
||||
url.addEncodedQueryItem( "results", QByteArray::number( numResults ) );
|
||||
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
|
||||
{
|
||||
QUrl url = setupQuery( "songs", numResults, offset );
|
||||
addQueryInformation( url, idspace );
|
||||
if( limitToIdSpace )
|
||||
url.addEncodedQueryItem( "limit", "true" );
|
||||
|
||||
return Echonest::Config::instance()->nam()->get( QNetworkRequest( url ) );
|
||||
}
|
||||
|
||||
QNetworkReply* Echonest::Artist::fetchTerms( Echonest::Artist::TermSorting sorting ) const
|
||||
{
|
||||
QUrl url = setupQuery( "terms", 0, -1 );
|
||||
if( sorting == Echonest::Artist::Weight )
|
||||
url.addEncodedQueryItem( "sort", "weight" );
|
||||
else if( sorting == Echonest::Artist::Frequency )
|
||||
url.addEncodedQueryItem( "sort", "frequency" );
|
||||
|
||||
return Echonest::Config::instance()->nam()->get( QNetworkRequest( url ) );
|
||||
}
|
||||
|
||||
|
||||
QNetworkReply* Echonest::Artist::fetchUrls() const
|
||||
{
|
||||
QUrl url = setupQuery( "urls", 0, -1 );
|
||||
|
||||
return Echonest::Config::instance()->nam()->get( QNetworkRequest( url ) );
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
QUrl url = Echonest::baseGetQuery( "artist", "top_hottt" );
|
||||
addQueryInformation( url, information );
|
||||
|
||||
if( numResults > 0 )
|
||||
url.addEncodedQueryItem( "results", QByteArray::number( numResults ) );
|
||||
if( offset >= 0 )
|
||||
url.addEncodedQueryItem( "start", QByteArray::number( offset ) );
|
||||
|
||||
url.addEncodedQueryItem( "limit", limit ? "true" : "false" );
|
||||
|
||||
return Echonest::Config::instance()->nam()->get( QNetworkRequest( url ) );
|
||||
}
|
||||
|
||||
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 ) );
|
||||
}
|
||||
|
||||
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 );
|
||||
|
||||
return numResults;
|
||||
}
|
||||
|
||||
Echonest::Artists Echonest::Artist::parseSearch( QNetworkReply* reply ) throw( Echonest::ParseError )
|
||||
{
|
||||
Echonest::Parser::checkForErrors( reply );
|
||||
|
||||
QXmlStreamReader xml( reply->readAll() );
|
||||
|
||||
Echonest::Parser::readStatus( xml );
|
||||
|
||||
Echonest::Artists artists = Echonest::Parser::parseArtists( xml );
|
||||
|
||||
return artists;
|
||||
}
|
||||
|
||||
Echonest::Artists Echonest::Artist::parseSimilar( QNetworkReply* reply ) throw( Echonest::ParseError )
|
||||
{
|
||||
return parseSearch( reply );
|
||||
}
|
||||
|
||||
Echonest::Artists Echonest::Artist::parseTopHottt( QNetworkReply* reply ) throw( Echonest::ParseError )
|
||||
{
|
||||
return parseSearch( reply );
|
||||
}
|
||||
|
||||
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 );
|
||||
|
||||
return terms;
|
||||
}
|
||||
|
||||
|
||||
QUrl Echonest::Artist::setupQuery( const QByteArray& methodName, int numResults, int start ) const
|
||||
{
|
||||
QUrl url = Echonest::baseGetQuery( "artist", methodName );
|
||||
if( !d->id.isEmpty() )
|
||||
url.addEncodedQueryItem( "id", d->id );
|
||||
else if( !d->name.isEmpty() ) {
|
||||
QString name = d->name;
|
||||
name.replace( QLatin1Char( ' ' ), QLatin1Char( '+' ) );
|
||||
url.addQueryItem( QLatin1String( "name" ), name );
|
||||
} else {
|
||||
qWarning() << "Artist method" << methodName << "called on an artist object without name or id!";
|
||||
return QUrl();
|
||||
}
|
||||
if( numResults > 0 )
|
||||
url.addEncodedQueryItem( "results", QByteArray::number( numResults ) );
|
||||
if( start >= 0 )
|
||||
url.addEncodedQueryItem( "start", QByteArray::number( start ) );
|
||||
|
||||
return url;
|
||||
}
|
||||
|
||||
QByteArray Echonest::Artist::searchParamToString(Echonest::Artist::SearchParam param)
|
||||
{
|
||||
switch( param )
|
||||
{
|
||||
case Id:
|
||||
return "id";
|
||||
case Name:
|
||||
return "name";
|
||||
case Results:
|
||||
return "results";
|
||||
case Description:
|
||||
return "description";
|
||||
case FuzzyMatch:
|
||||
return "fuzzy_match";
|
||||
case MaxFamiliarity:
|
||||
return "max_familiarity";
|
||||
case MinFamiliarity:
|
||||
return "min_familiarity";
|
||||
case MaxHotttnesss:
|
||||
return "max_hotttnesss";
|
||||
case MinHotttnesss:
|
||||
return "min_hotttnesss";
|
||||
case Reverse:
|
||||
return "reverse";
|
||||
case Sort:
|
||||
return "sort";
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
void Echonest::Artist::addQueryInformation(QUrl& url, Echonest::Artist::ArtistInformation parts)
|
||||
{
|
||||
if( parts.testFlag( Echonest::Artist::Audio ) )
|
||||
url.addEncodedQueryItem( "bucket", "audio" );
|
||||
if( parts.testFlag( Echonest::Artist::Biographies ) )
|
||||
url.addEncodedQueryItem( "bucket", "biographies" );
|
||||
if( parts.testFlag( Echonest::Artist::Blogs ) )
|
||||
url.addEncodedQueryItem( "bucket", "blogs" );
|
||||
if( parts.testFlag( Echonest::Artist::Familiarity ) )
|
||||
url.addEncodedQueryItem( "bucket", "familiarity" );
|
||||
if( parts.testFlag( Echonest::Artist::Hotttnesss ) )
|
||||
url.addEncodedQueryItem( "bucket", "hotttnesss" );
|
||||
if( parts.testFlag( Echonest::Artist::Images ) )
|
||||
url.addEncodedQueryItem( "bucket", "images" );
|
||||
if( parts.testFlag( Echonest::Artist::News ) )
|
||||
url.addEncodedQueryItem( "bucket", "news" );
|
||||
if( parts.testFlag( Echonest::Artist::Reviews ) )
|
||||
url.addEncodedQueryItem( "bucket", "reviews" );
|
||||
if( parts.testFlag( Echonest::Artist::Terms ) )
|
||||
url.addEncodedQueryItem( "bucket", "terms" );
|
||||
if( parts.testFlag( Echonest::Artist::Urls ) )
|
||||
url.addEncodedQueryItem( "bucket", "urls" );
|
||||
if( parts.testFlag( Echonest::Artist::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" );
|
||||
}
|
||||
|
||||
|
||||
QDebug Echonest::operator<<(QDebug d, const Echonest::Artist& artist)
|
||||
{
|
||||
return d.maybeSpace() << QString::fromLatin1( "Artist(%1, %2)" ).arg( artist.name() ).arg( QString::fromLatin1(artist.id()) );
|
||||
}
|
||||
|
370
3rdparty/libechonest/Artist.h
vendored
Normal file
370
3rdparty/libechonest/Artist.h
vendored
Normal file
@ -0,0 +1,370 @@
|
||||
/****************************************************************************************
|
||||
* 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_ARTIST_H
|
||||
#define ECHONEST_ARTIST_H
|
||||
|
||||
#include "echonest_export.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QSharedData>
|
||||
#include <QUrl>
|
||||
#include "Config.h"
|
||||
#include "ArtistTypes.h"
|
||||
#include "Song.h"
|
||||
|
||||
class QNetworkReply;
|
||||
class ArtistData;
|
||||
class Term;
|
||||
namespace Echonest{
|
||||
|
||||
class Biography;
|
||||
|
||||
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
|
||||
* 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 ]
|
||||
* - results 0 < results < 200, (Default=15) The number of results desired
|
||||
* - min_results 0 < results < 200, (Default=0) Indicates the minimum number of results to be returned regardless of constraints
|
||||
* - max_familiarity 0.0 < familiarity < 1.0 The maximum familiarity for returned artists
|
||||
* - min_familiarity 0.0 < familiarity < 1.0 The minimum familiarity for returned artists
|
||||
* - max_hotttnesss 0.0 < hotttnesss < 1.0 The maximum hotttnesss for returned artists
|
||||
* - 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,
|
||||
Name,
|
||||
Results,
|
||||
Description,
|
||||
FuzzyMatch,
|
||||
MaxFamiliarity,
|
||||
MinFamiliarity,
|
||||
MaxHotttnesss,
|
||||
MinHotttnesss,
|
||||
Reverse,
|
||||
Sort
|
||||
};
|
||||
typedef QPair< Echonest::Artist::SearchParam, QVariant > SearchParamEntry;
|
||||
typedef QVector< SearchParamEntry > SearchParams;
|
||||
|
||||
Artist();
|
||||
Artist( const QByteArray& id, const QString& name );
|
||||
Artist( const Artist& other );
|
||||
Artist& operator=( const Artist& artist );
|
||||
~Artist();
|
||||
|
||||
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.
|
||||
*/
|
||||
QUrl lastFmUrl() const;
|
||||
void setLastFmUrl( const QUrl& );
|
||||
QUrl aolMusicUrl() const;
|
||||
void setAolMusicUrl( const QUrl& );
|
||||
QUrl amazonUrl() const;
|
||||
void setAmazonUrl( const QUrl& );
|
||||
QUrl itunesUrl() const;
|
||||
void setItunesUrl( const QUrl& );
|
||||
QUrl myspaceUrl() const;
|
||||
void setMyspaceUrl( const QUrl& );
|
||||
QUrl musicbrainzUrl() const;
|
||||
void setMusicbrainzUrl( const QUrl& url );
|
||||
|
||||
/**
|
||||
* Videos related to this artist.
|
||||
*/
|
||||
VideoList videos() const;
|
||||
void setVideos( const VideoList& );
|
||||
|
||||
/**
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* 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
|
||||
* 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 );
|
||||
|
||||
/**
|
||||
* 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 );
|
||||
|
||||
/**
|
||||
* 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 );
|
||||
|
||||
/**
|
||||
* Fetch a list of the top overall terms.
|
||||
*/
|
||||
static QNetworkReply* topTerms( int numResults = 15 );
|
||||
|
||||
/**
|
||||
* 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 );
|
||||
|
||||
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 );
|
||||
|
||||
QSharedDataPointer<ArtistData> d;
|
||||
};
|
||||
|
||||
ECHONEST_EXPORT QDebug operator<<(QDebug d, const Echonest::Artist& artist);
|
||||
|
||||
Q_DECLARE_OPERATORS_FOR_FLAGS(Artist::ArtistInformation)
|
||||
} // namespace
|
||||
#endif
|
572
3rdparty/libechonest/ArtistTypes.cpp
vendored
Normal file
572
3rdparty/libechonest/ArtistTypes.cpp
vendored
Normal file
@ -0,0 +1,572 @@
|
||||
/****************************************************************************************
|
||||
* 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 "ArtistTypes.h"
|
||||
|
||||
#include "ArtistTypes_p.h"
|
||||
|
||||
#include <QUrl>
|
||||
#include <QDateTime>
|
||||
|
||||
Echonest::ArtistImage::ArtistImage() : d( new ArtistImageData )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
Echonest::ArtistImage::ArtistImage(const Echonest::ArtistImage& other)
|
||||
{
|
||||
d = other.d;
|
||||
}
|
||||
|
||||
Echonest::ArtistImage& Echonest::ArtistImage::operator=(const Echonest::ArtistImage& img)
|
||||
{
|
||||
d = img.d;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Echonest::ArtistImage::~ArtistImage()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
QUrl Echonest::ArtistImage::url() const
|
||||
{
|
||||
return d->url;
|
||||
}
|
||||
|
||||
void Echonest::ArtistImage::setUrl(const QUrl& url)
|
||||
{
|
||||
d->url = url;
|
||||
}
|
||||
|
||||
Echonest::License Echonest::ArtistImage::license() const
|
||||
{
|
||||
return d->license;
|
||||
}
|
||||
|
||||
void Echonest::ArtistImage::setLicense(const Echonest::License& license)
|
||||
{
|
||||
d->license = license;
|
||||
}
|
||||
|
||||
Echonest::AudioFile::AudioFile() : d( new AudioFileData )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
Echonest::AudioFile::AudioFile(const Echonest::AudioFile& other)
|
||||
{
|
||||
d = other.d;
|
||||
}
|
||||
|
||||
Echonest::AudioFile& Echonest::AudioFile::operator=(const Echonest::AudioFile& artist)
|
||||
{
|
||||
d = artist.d;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Echonest::AudioFile::~AudioFile()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void Echonest::AudioFile::setTitle(const QString& title)
|
||||
{
|
||||
d->title = title;
|
||||
}
|
||||
|
||||
QString Echonest::AudioFile::title() const
|
||||
{
|
||||
return d->title;
|
||||
}
|
||||
|
||||
|
||||
QString Echonest::AudioFile::artist() const
|
||||
{
|
||||
return d->artist;
|
||||
}
|
||||
|
||||
void Echonest::AudioFile::setArtist(const QString& artist)
|
||||
{
|
||||
d->artist = artist;
|
||||
}
|
||||
|
||||
QDateTime Echonest::AudioFile::date() const
|
||||
{
|
||||
return d->date;
|
||||
}
|
||||
|
||||
void Echonest::AudioFile::setDate(const QDateTime& date)
|
||||
{
|
||||
d->date = date;
|
||||
}
|
||||
|
||||
QString Echonest::AudioFile::release() const
|
||||
{
|
||||
return d->release;
|
||||
}
|
||||
|
||||
void Echonest::AudioFile::setRelease(const QString& release)
|
||||
{
|
||||
d->release = release;
|
||||
}
|
||||
|
||||
QByteArray Echonest::AudioFile::id() const
|
||||
{
|
||||
return d->id;
|
||||
}
|
||||
|
||||
void Echonest::AudioFile::setId(const QByteArray& id)
|
||||
{
|
||||
d->id = id;
|
||||
}
|
||||
|
||||
qreal Echonest::AudioFile::length() const
|
||||
{
|
||||
return d->length;
|
||||
}
|
||||
|
||||
void Echonest::AudioFile::setLength(qreal length)
|
||||
{
|
||||
d->length = length;
|
||||
}
|
||||
|
||||
QUrl Echonest::AudioFile::link() const
|
||||
{
|
||||
return d->link;
|
||||
}
|
||||
|
||||
void Echonest::AudioFile::setLink(const QUrl& url)
|
||||
{
|
||||
d->link = url;
|
||||
}
|
||||
|
||||
QUrl Echonest::AudioFile::url() const
|
||||
{
|
||||
return d->url;
|
||||
}
|
||||
|
||||
void Echonest::AudioFile::setUrl(const QUrl& url)
|
||||
{
|
||||
d->url = url;
|
||||
}
|
||||
|
||||
Echonest::Biography::Biography() : d( new BiographyData )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
Echonest::Biography::Biography(const Echonest::Biography& other)
|
||||
{
|
||||
d = other.d;
|
||||
}
|
||||
|
||||
Echonest::Biography& Echonest::Biography::operator=(const Echonest::Biography& biblio)
|
||||
{
|
||||
d = biblio.d;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Echonest::Biography::~Biography()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
Echonest::License Echonest::Biography::license() const
|
||||
{
|
||||
return d->license;
|
||||
}
|
||||
|
||||
void Echonest::Biography::setLicense(const Echonest::License& license)
|
||||
{
|
||||
d->license = license;
|
||||
}
|
||||
|
||||
QString Echonest::Biography::site() const
|
||||
{
|
||||
return d->site;
|
||||
}
|
||||
|
||||
void Echonest::Biography::setSite(const QString& site)
|
||||
{
|
||||
d->site = site;
|
||||
}
|
||||
|
||||
QString Echonest::Biography::text() const
|
||||
{
|
||||
return d->text;
|
||||
}
|
||||
|
||||
void Echonest::Biography::setText(const QString& text)
|
||||
{
|
||||
d->text = text;
|
||||
}
|
||||
|
||||
QUrl Echonest::Biography::url() const
|
||||
{
|
||||
return d->url;
|
||||
}
|
||||
|
||||
void Echonest::Biography::setUrl(const QUrl& url)
|
||||
{
|
||||
d->url = url;
|
||||
}
|
||||
|
||||
Echonest::Blog::Blog() : d( new BlogData )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
Echonest::Blog::Blog(const Echonest::Blog& other) : d( other.d )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
Echonest::Blog& Echonest::Blog::operator=(const Echonest::Blog& other)
|
||||
{
|
||||
d = other.d;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Echonest::Blog::~Blog()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
QDateTime Echonest::Blog::dateFound() const
|
||||
{
|
||||
return d->date_found;
|
||||
}
|
||||
|
||||
void Echonest::Blog::setDateFound(const QDateTime& date)
|
||||
{
|
||||
d->date_found = date;
|
||||
}
|
||||
|
||||
QDateTime Echonest::Blog::datePosted() const
|
||||
{
|
||||
return d->date_posted;
|
||||
}
|
||||
|
||||
void Echonest::Blog::setDatePosted(const QDateTime& date)
|
||||
{
|
||||
d->date_posted = date;
|
||||
}
|
||||
|
||||
QByteArray Echonest::Blog::id() const
|
||||
{
|
||||
return d->id;
|
||||
}
|
||||
|
||||
void Echonest::Blog::setId(const QByteArray& id)
|
||||
{
|
||||
d->id = id;
|
||||
}
|
||||
|
||||
QString Echonest::Blog::name() const
|
||||
{
|
||||
return d->name;
|
||||
}
|
||||
|
||||
void Echonest::Blog::setName(const QString& name)
|
||||
{
|
||||
d->name = name;
|
||||
}
|
||||
|
||||
QString Echonest::Blog::summary() const
|
||||
{
|
||||
return d->summary;
|
||||
}
|
||||
|
||||
void Echonest::Blog::setSummary(const QString& text)
|
||||
{
|
||||
d->summary = text;
|
||||
}
|
||||
|
||||
QUrl Echonest::Blog::url() const
|
||||
{
|
||||
return d->url;
|
||||
}
|
||||
|
||||
void Echonest::Blog::setUrl(const QUrl& url)
|
||||
{
|
||||
d->url = url;
|
||||
}
|
||||
|
||||
Echonest::Review::Review() : d( new ReviewData )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
Echonest::Review::Review(const Echonest::Review& other) : d( other.d )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
Echonest::Review& Echonest::Review::operator=(const Echonest::Review& other)
|
||||
{
|
||||
d = other.d;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Echonest::Review::~Review()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
QDateTime Echonest::Review::dateFound() const
|
||||
{
|
||||
return d->date_found;
|
||||
}
|
||||
|
||||
void Echonest::Review::setDateFound(const QDateTime& date)
|
||||
{
|
||||
d->date_found = date;
|
||||
}
|
||||
|
||||
QDateTime Echonest::Review::dateReviewed() const
|
||||
{
|
||||
return d->date_reviewed;
|
||||
}
|
||||
|
||||
void Echonest::Review::setDateReviewed(const QDateTime& date)
|
||||
{
|
||||
d->date_reviewed = date;
|
||||
}
|
||||
|
||||
QByteArray Echonest::Review::id() const
|
||||
{
|
||||
return d->id;
|
||||
}
|
||||
|
||||
void Echonest::Review::setId(const QByteArray& id)
|
||||
{
|
||||
d->id = id;
|
||||
}
|
||||
|
||||
QUrl Echonest::Review::imageUrl() const
|
||||
{
|
||||
return d->image_url;
|
||||
}
|
||||
|
||||
void Echonest::Review::setImageUrl(const QUrl& imageUrl)
|
||||
{
|
||||
d->image_url = imageUrl;
|
||||
}
|
||||
|
||||
QString Echonest::Review::name() const
|
||||
{
|
||||
return d->name;
|
||||
}
|
||||
|
||||
void Echonest::Review::setName(const QString& name)
|
||||
{
|
||||
d->name = name;
|
||||
}
|
||||
|
||||
QString Echonest::Review::release() const
|
||||
{
|
||||
return d->release;
|
||||
}
|
||||
|
||||
void Echonest::Review::setRelease(const QString& release)
|
||||
{
|
||||
d->release = release;
|
||||
}
|
||||
|
||||
QString Echonest::Review::summary() const
|
||||
{
|
||||
return d->summary;
|
||||
}
|
||||
|
||||
void Echonest::Review::setSummary(const QString& text)
|
||||
{
|
||||
d->summary = text;
|
||||
}
|
||||
|
||||
QUrl Echonest::Review::url() const
|
||||
{
|
||||
return d->url;
|
||||
}
|
||||
|
||||
void Echonest::Review::setUrl(const QUrl& url)
|
||||
{
|
||||
d->url = url;
|
||||
}
|
||||
|
||||
Echonest::Term::Term() : d( new TermData )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
Echonest::Term::Term(const Echonest::Term& other) : d( other.d )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
Echonest::Term& Echonest::Term::operator=(const Echonest::Term& other)
|
||||
{
|
||||
d = other.d;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Echonest::Term::~Term()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
qreal Echonest::Term::frequency() const
|
||||
{
|
||||
return d->frequency;
|
||||
}
|
||||
|
||||
void Echonest::Term::setFrequency(qreal freq)
|
||||
{
|
||||
d->frequency = freq;
|
||||
}
|
||||
|
||||
QString Echonest::Term::name() const
|
||||
{
|
||||
return d->name;
|
||||
}
|
||||
|
||||
void Echonest::Term::setName(const QString& name)
|
||||
{
|
||||
d->name = name;
|
||||
}
|
||||
|
||||
qreal Echonest::Term::weight() const
|
||||
{
|
||||
return d->weight;
|
||||
}
|
||||
|
||||
void Echonest::Term::setWeight(qreal weight)
|
||||
{
|
||||
d->weight = weight;
|
||||
}
|
||||
|
||||
Echonest::Video::Video() : d( new VideoData )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
Echonest::Video::Video(const Echonest::Video& other) : d( other.d )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
Echonest::Video& Echonest::Video::operator=(const Echonest::Video& other)
|
||||
{
|
||||
d = other.d;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Echonest::Video::~Video()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
QDateTime Echonest::Video::dateFound() const
|
||||
{
|
||||
return d->date_found;
|
||||
}
|
||||
|
||||
void Echonest::Video::setDateFound(const QDateTime& date)
|
||||
{
|
||||
d->date_found = date;
|
||||
}
|
||||
|
||||
QByteArray Echonest::Video::id() const
|
||||
{
|
||||
return d->id;
|
||||
}
|
||||
|
||||
void Echonest::Video::setId(const QByteArray& id)
|
||||
{
|
||||
d->id = id;
|
||||
}
|
||||
|
||||
QUrl Echonest::Video::imageUrl() const
|
||||
{
|
||||
return d->image_url;
|
||||
}
|
||||
|
||||
void Echonest::Video::setImageUrl(const QUrl& imageUrl)
|
||||
{
|
||||
d->image_url = imageUrl;
|
||||
}
|
||||
|
||||
QString Echonest::Video::site() const
|
||||
{
|
||||
return d->site;
|
||||
}
|
||||
|
||||
void Echonest::Video::setSite(const QString& site)
|
||||
{
|
||||
d->site = site;
|
||||
}
|
||||
|
||||
QString Echonest::Video::title() const
|
||||
{
|
||||
return d->title;
|
||||
}
|
||||
|
||||
void Echonest::Video::setTitle(const QString& title)
|
||||
{
|
||||
d->title = title;
|
||||
}
|
||||
|
||||
QUrl Echonest::Video::url() const
|
||||
{
|
||||
return d->url;
|
||||
}
|
||||
|
||||
void Echonest::Video::setUrl(const QUrl& url)
|
||||
{
|
||||
d->url = url;
|
||||
}
|
||||
|
||||
QDebug Echonest::operator<<(QDebug d, const Echonest::AudioFile& audio)
|
||||
{
|
||||
return d.maybeSpace() << QString::fromLatin1( "AudioFile [%1, %2, %3, %4]" ).arg( audio.title() ) .arg( audio.artist() ).arg( audio.release() ).arg( audio.url().toString() );
|
||||
}
|
||||
QDebug Echonest::operator<<(QDebug d, const Echonest::Biography& biblio)
|
||||
{
|
||||
return d.maybeSpace() << QString::fromLatin1( "Bibliography [%1, %2, %3, %4]" ).arg( biblio.site() ).arg( biblio.url().toString() ).arg( biblio.license().type ).arg( biblio.text().left( 100 ) );
|
||||
}
|
||||
QDebug Echonest::operator<<(QDebug d, const Echonest::Blog& blog)
|
||||
{
|
||||
return d.maybeSpace() << QString::fromLatin1( "Blog [%1, %2, %3, %4, %5, %6]" ).arg( blog.name() ).arg( blog.datePosted().toString() ).arg( blog.dateFound().toString() ).arg( blog.url().toString() ).arg( QLatin1String( blog.id() ) ).arg( blog.summary().left( 100 ) );
|
||||
}
|
||||
QDebug Echonest::operator<<(QDebug d, const Echonest::ArtistImage& img)
|
||||
{
|
||||
return d.maybeSpace() << QString::fromLatin1( "ArtistImage [%1, %2]" ).arg( img.url().toString() ).arg( img.license().type );
|
||||
}
|
||||
QDebug Echonest::operator<<(QDebug d, const Echonest::Review& review)
|
||||
{
|
||||
return d.maybeSpace() << QString::fromLatin1( "Review [%1, %2, %3]" ).arg( review.name() ).arg( review.release() ).arg( review.summary().left( 100 ) );
|
||||
}
|
||||
QDebug Echonest::operator<<(QDebug d, const Echonest::Term& term)
|
||||
{
|
||||
return d.maybeSpace() << QString::fromLatin1( "Term [%1, %2, %3]" ).arg( term.name() ).arg( term.frequency() ).arg( term.weight() );
|
||||
}
|
||||
QDebug Echonest::operator<<(QDebug d, const Echonest::Video& video)
|
||||
{
|
||||
return d.maybeSpace() << QString::fromLatin1( "Video [%1, %2, %3]" ).arg( video.title() ).arg( video.site() ).arg( video.url().toString() );
|
||||
}
|
390
3rdparty/libechonest/ArtistTypes.h
vendored
Normal file
390
3rdparty/libechonest/ArtistTypes.h
vendored
Normal file
@ -0,0 +1,390 @@
|
||||
/****************************************************************************************
|
||||
* 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_ARTISTTYPES_H
|
||||
#define ECHONEST_ARTISTTYPES_H
|
||||
|
||||
#include "echonest_export.h"
|
||||
#include "Util.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QSharedData>
|
||||
|
||||
class QDateTime;
|
||||
class QUrl;
|
||||
class AudioFileData;
|
||||
class BiographyData;
|
||||
class BlogData;
|
||||
class ArtistImageData;
|
||||
class ReviewData;
|
||||
class TermData;
|
||||
class VideoData;
|
||||
|
||||
namespace Echonest{
|
||||
|
||||
/**
|
||||
* A link to an audio file related to an artist on the web.
|
||||
*/
|
||||
class ECHONEST_EXPORT AudioFile
|
||||
{
|
||||
|
||||
public:
|
||||
AudioFile();
|
||||
AudioFile( const AudioFile& other );
|
||||
AudioFile& operator=( const AudioFile& artist );
|
||||
~AudioFile();
|
||||
|
||||
/**
|
||||
* The title of the audio file.
|
||||
*/
|
||||
QString title() const;
|
||||
void setTitle( const QString& title );
|
||||
|
||||
/**
|
||||
* The artist name that this audio file is related to.
|
||||
*/
|
||||
QString artist() const;
|
||||
void setArtist( const QString& );
|
||||
|
||||
/**
|
||||
* The URL pointing to the audio file.
|
||||
*/
|
||||
QUrl url() const;
|
||||
void setUrl( const QUrl& url );
|
||||
|
||||
/**
|
||||
* The length of the referenced audio file.
|
||||
*/
|
||||
qreal length() const;
|
||||
void setLength( qreal length );
|
||||
|
||||
/**
|
||||
* The link to the website where the audio file is from.
|
||||
*/
|
||||
QUrl link() const;
|
||||
void setLink( const QUrl& url );
|
||||
|
||||
/**
|
||||
* The date that this audio was posted.
|
||||
*/
|
||||
QDateTime date() const;
|
||||
void setDate( const QDateTime& );
|
||||
|
||||
/**
|
||||
* The released album name of this audio file.
|
||||
*/
|
||||
QString release() const;
|
||||
void setRelease( const QString& release );
|
||||
|
||||
/**
|
||||
* The unique identifier for this artist audio file.
|
||||
*/
|
||||
QByteArray id() const;
|
||||
void setId( const QByteArray& id );
|
||||
|
||||
private:
|
||||
QSharedDataPointer<AudioFileData> d;
|
||||
};
|
||||
|
||||
/**
|
||||
* A biography of an artist, including the full text content
|
||||
* of the biography itself.
|
||||
*/
|
||||
class ECHONEST_EXPORT Biography {
|
||||
|
||||
public:
|
||||
Biography();
|
||||
Biography( const Biography& other );
|
||||
Biography& operator=( const Biography& biblio );
|
||||
~Biography();
|
||||
|
||||
/**
|
||||
* The URL to the biography.
|
||||
*/
|
||||
QUrl url() const;
|
||||
void setUrl( const QUrl& url );
|
||||
|
||||
/**
|
||||
* The text contents of the biography. May be very long.
|
||||
*/
|
||||
QString text() const;
|
||||
void setText( const QString& text );
|
||||
|
||||
/**
|
||||
* The site that this biography is from.
|
||||
*/
|
||||
QString site() const;
|
||||
void setSite( const QString& site );
|
||||
|
||||
/**
|
||||
* The license that this biography is licensed under.
|
||||
*/
|
||||
License license() const;
|
||||
void setLicense( const License& license );
|
||||
private:
|
||||
QSharedDataPointer<BiographyData> d;
|
||||
};
|
||||
|
||||
/**
|
||||
* A blog post about a certain artist or track.
|
||||
*/
|
||||
class ECHONEST_EXPORT Blog {
|
||||
|
||||
public:
|
||||
Blog();
|
||||
Blog( const Blog& other );
|
||||
Blog& operator=( const Blog& other );
|
||||
~Blog();
|
||||
|
||||
/**
|
||||
* The name of the blog or news article.
|
||||
*/
|
||||
QString name() const;
|
||||
void setName( const QString& name );
|
||||
|
||||
/**
|
||||
* The URL to the blog post or news article.
|
||||
*/
|
||||
QUrl url() const;
|
||||
void setUrl( const QUrl& url );
|
||||
|
||||
/**
|
||||
* The date when the blog post or news article was posted.
|
||||
*/
|
||||
QDateTime datePosted() const;
|
||||
void setDatePosted( const QDateTime& date );
|
||||
|
||||
/**
|
||||
* The date when this blog post or news article was found by The Echo Nest.
|
||||
*/
|
||||
QDateTime dateFound() const;
|
||||
void setDateFound( const QDateTime& date );
|
||||
|
||||
/**
|
||||
* A short summary of the blog or article.
|
||||
*/
|
||||
QString summary() const;
|
||||
void setSummary( const QString& text );
|
||||
|
||||
/**
|
||||
* The unique identifier for this entry.
|
||||
*/
|
||||
QByteArray id() const;
|
||||
void setId( const QByteArray& id );
|
||||
|
||||
private:
|
||||
QSharedDataPointer<BlogData> d;
|
||||
};
|
||||
|
||||
/**
|
||||
* A news article about an artist.
|
||||
*/
|
||||
typedef Blog NewsArticle;
|
||||
|
||||
/**
|
||||
* An image related to an artist.
|
||||
*/
|
||||
class ECHONEST_EXPORT ArtistImage {
|
||||
|
||||
public:
|
||||
ArtistImage();
|
||||
ArtistImage( const ArtistImage& other );
|
||||
ArtistImage& operator=( const ArtistImage& img );
|
||||
~ArtistImage();
|
||||
|
||||
/**
|
||||
* The image url.
|
||||
*/
|
||||
QUrl url() const;
|
||||
void setUrl( const QUrl& url );
|
||||
|
||||
/**
|
||||
* The license that governs this image.
|
||||
*/
|
||||
License license() const;
|
||||
void setLicense( const License& license );
|
||||
|
||||
private:
|
||||
QSharedDataPointer<ArtistImageData> d;
|
||||
};
|
||||
|
||||
/**
|
||||
* A review of an artist, album, or track.
|
||||
*/
|
||||
class ECHONEST_EXPORT Review {
|
||||
|
||||
public:
|
||||
Review();
|
||||
Review( const Review& other );
|
||||
Review& operator=( const Review& other );
|
||||
~Review();
|
||||
|
||||
/**
|
||||
* The name of the review site.
|
||||
*/
|
||||
QString name() const;
|
||||
void setName( const QString& name );
|
||||
|
||||
/**
|
||||
* The URL to the review.
|
||||
*/
|
||||
QUrl url() const;
|
||||
void setUrl( const QUrl& url );
|
||||
|
||||
/**
|
||||
* The date when the review was posted.
|
||||
*/
|
||||
QDateTime dateReviewed() const;
|
||||
void setDateReviewed( const QDateTime& date );
|
||||
|
||||
/**
|
||||
* The date when this review was found and indexed by The Echo Nest
|
||||
*/
|
||||
QDateTime dateFound() const;
|
||||
void setDateFound( const QDateTime& date );
|
||||
|
||||
/**
|
||||
* A summary of the review.
|
||||
*/
|
||||
QString summary() const;
|
||||
void setSummary( const QString& text );
|
||||
|
||||
/**
|
||||
* The url to an image associated with the review, if it exists.
|
||||
*/
|
||||
QUrl imageUrl() const;
|
||||
void setImageUrl( const QUrl& imageUrl );
|
||||
|
||||
/**
|
||||
* The album being reviewed if it is an album review, including specific release info, if it exists.
|
||||
*/
|
||||
QString release() const;
|
||||
void setRelease( const QString& release );
|
||||
|
||||
/**
|
||||
* The unique identifier for this entry.
|
||||
*/
|
||||
QByteArray id() const;
|
||||
void setId( const QByteArray& id );
|
||||
|
||||
private:
|
||||
QSharedDataPointer<ReviewData> d;
|
||||
};
|
||||
|
||||
/**
|
||||
* A term used to describe an artist or track.
|
||||
*/
|
||||
class ECHONEST_EXPORT Term {
|
||||
|
||||
public:
|
||||
Term();
|
||||
Term( const Term& other );
|
||||
Term& operator=( const Term& img );
|
||||
~Term();
|
||||
|
||||
/**
|
||||
* The term name.
|
||||
*/
|
||||
QString name() const;
|
||||
void setName( const QString& name );
|
||||
|
||||
/**
|
||||
* The frequency that this term is mentioned in relation to the artist/track.
|
||||
*/
|
||||
qreal frequency() const;
|
||||
void setFrequency( qreal freq );
|
||||
|
||||
/**
|
||||
* The weight that The Echo Nest assigns to this term.
|
||||
*/
|
||||
qreal weight() const;
|
||||
void setWeight( qreal weight );
|
||||
|
||||
private:
|
||||
QSharedDataPointer<TermData> d;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* A link to a video related to an artist.
|
||||
*/
|
||||
class ECHONEST_EXPORT Video {
|
||||
|
||||
public:
|
||||
Video();
|
||||
Video( const Video& other );
|
||||
Video& operator=( const Video& other );
|
||||
~Video();
|
||||
|
||||
/**
|
||||
* The title of the video
|
||||
*/
|
||||
QString title() const;
|
||||
void setTitle( const QString& title );
|
||||
|
||||
/**
|
||||
* The URL to the title.
|
||||
*/
|
||||
QUrl url() const;
|
||||
void setUrl( const QUrl& url );
|
||||
|
||||
/**
|
||||
* The site that the video is from.
|
||||
*/
|
||||
QString site() const;
|
||||
void setSite( const QString& site );
|
||||
|
||||
/**
|
||||
* The date when this video was found
|
||||
*/
|
||||
QDateTime dateFound() const;
|
||||
void setDateFound( const QDateTime& date );
|
||||
|
||||
/**
|
||||
* The url to an image associated with this video, if it exists.
|
||||
*/
|
||||
QUrl imageUrl() const;
|
||||
void setImageUrl( const QUrl& imageUrl );
|
||||
|
||||
/**
|
||||
* The unique identifier for this video.
|
||||
*/
|
||||
QByteArray id() const;
|
||||
void setId( const QByteArray& id );
|
||||
|
||||
private:
|
||||
QSharedDataPointer<VideoData> d;
|
||||
};
|
||||
|
||||
ECHONEST_EXPORT QDebug operator<<(QDebug d, const Echonest::AudioFile& artist);
|
||||
ECHONEST_EXPORT QDebug operator<<(QDebug d, const Echonest::Biography& biblio);
|
||||
ECHONEST_EXPORT QDebug operator<<(QDebug d, const Echonest::Blog& blog);
|
||||
ECHONEST_EXPORT QDebug operator<<(QDebug d, const Echonest::ArtistImage& img);
|
||||
ECHONEST_EXPORT QDebug operator<<(QDebug d, const Echonest::Review& review);
|
||||
ECHONEST_EXPORT QDebug operator<<(QDebug d, const Echonest::Term& term);
|
||||
ECHONEST_EXPORT QDebug operator<<(QDebug d, const Echonest::Video& video);
|
||||
|
||||
typedef QVector< AudioFile > AudioList;
|
||||
typedef QVector< Biography > BiographyList;
|
||||
typedef QVector< Blog > BlogList;
|
||||
typedef QVector< ArtistImage > ArtistImageList;
|
||||
typedef QVector< NewsArticle > NewsList;
|
||||
typedef QVector< Review > ReviewList;
|
||||
typedef QVector< Term > TermList;
|
||||
typedef QVector< Video > VideoList;
|
||||
|
||||
} // namespace
|
||||
#endif
|
166
3rdparty/libechonest/ArtistTypes_p.h
vendored
Normal file
166
3rdparty/libechonest/ArtistTypes_p.h
vendored
Normal file
@ -0,0 +1,166 @@
|
||||
/****************************************************************************************
|
||||
* 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_ARTISTTYPES_P_H
|
||||
#define ECHONEST_ARTISTTYPES_P_H
|
||||
|
||||
#include "Util.h"
|
||||
|
||||
#include <QSharedData>
|
||||
#include <QString>
|
||||
#include <QVector>
|
||||
#include <QDate>
|
||||
#include <QUrl>
|
||||
|
||||
class AudioFileData : public QSharedData
|
||||
{
|
||||
public:
|
||||
AudioFileData() {}
|
||||
AudioFileData( const AudioFileData& other ) {
|
||||
title = other.title;
|
||||
artist = other.artist;
|
||||
url = other.url;
|
||||
length = other.length;
|
||||
link = other.link;
|
||||
date = other.date;
|
||||
id = other.id;
|
||||
release = other.release;
|
||||
}
|
||||
|
||||
QString title;
|
||||
QString artist;
|
||||
QUrl url;
|
||||
qreal length;
|
||||
QUrl link;
|
||||
QDateTime date;
|
||||
QString release;
|
||||
QByteArray id;
|
||||
};
|
||||
|
||||
class BiographyData : public QSharedData
|
||||
{
|
||||
public:
|
||||
BiographyData() {}
|
||||
BiographyData( const BiographyData& other ) {
|
||||
url = other.url;
|
||||
text = other.text;
|
||||
site = other.site;
|
||||
license = other.license;
|
||||
}
|
||||
|
||||
QUrl url;
|
||||
QString text;
|
||||
QString site;
|
||||
Echonest::License license;
|
||||
};
|
||||
|
||||
class BlogData : public QSharedData
|
||||
{
|
||||
public:
|
||||
BlogData() {}
|
||||
BlogData( const BlogData& other ) {
|
||||
name = other.name;
|
||||
url = other.url;
|
||||
date_posted = other.date_posted;
|
||||
date_found = other.date_found;
|
||||
summary = other.summary;
|
||||
id = other.id;
|
||||
}
|
||||
|
||||
QString name;
|
||||
QUrl url;
|
||||
QDateTime date_posted;
|
||||
QDateTime date_found;
|
||||
QString summary;
|
||||
QByteArray id;
|
||||
};
|
||||
|
||||
class ArtistImageData : public QSharedData
|
||||
{
|
||||
public:
|
||||
ArtistImageData() {}
|
||||
ArtistImageData( const ArtistImageData& other ) {
|
||||
url = other.url;
|
||||
license = other.license;
|
||||
}
|
||||
|
||||
QUrl url;
|
||||
Echonest::License license;
|
||||
};
|
||||
|
||||
class ReviewData : public QSharedData
|
||||
{
|
||||
public:
|
||||
ReviewData() {}
|
||||
ReviewData( const ReviewData& other ) {
|
||||
name = other.name;
|
||||
url = other.url;
|
||||
summary = other.summary;
|
||||
date_reviewed = other.date_reviewed;
|
||||
date_found = other.date_found;
|
||||
image_url = other.image_url;
|
||||
release = other.release;
|
||||
id = other.id;
|
||||
}
|
||||
|
||||
QString name;
|
||||
QUrl url;
|
||||
QString summary;
|
||||
QDateTime date_reviewed;
|
||||
QDateTime date_found;
|
||||
QUrl image_url;
|
||||
QString release;
|
||||
QByteArray id;
|
||||
};
|
||||
|
||||
class TermData : public QSharedData
|
||||
{
|
||||
public:
|
||||
TermData() {}
|
||||
TermData( const TermData& other ) {
|
||||
name = other.name;
|
||||
frequency = other.frequency;
|
||||
weight = other.weight;
|
||||
}
|
||||
|
||||
QString name;
|
||||
qreal frequency;
|
||||
qreal weight;
|
||||
};
|
||||
|
||||
class VideoData : public QSharedData
|
||||
{
|
||||
public:
|
||||
VideoData() {}
|
||||
VideoData( const VideoData& other ) {
|
||||
title = other.title;
|
||||
url = other.url;
|
||||
site = other.site;
|
||||
date_found = other.date_found;
|
||||
image_url = other.image_url;
|
||||
id = other.id;
|
||||
}
|
||||
|
||||
QString title;
|
||||
QUrl url;
|
||||
QString site;
|
||||
QDateTime date_found;
|
||||
QUrl image_url;
|
||||
QByteArray id;
|
||||
};
|
||||
|
||||
|
||||
#endif
|
71
3rdparty/libechonest/Artist_p.h
vendored
Normal file
71
3rdparty/libechonest/Artist_p.h
vendored
Normal file
@ -0,0 +1,71 @@
|
||||
/****************************************************************************************
|
||||
* 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_ARTIST_P_H
|
||||
#define ECHONEST_ARTIST_P_H
|
||||
|
||||
#include "Song.h"
|
||||
#include "ArtistTypes.h"
|
||||
|
||||
#include <QSharedData>
|
||||
#include <QString>
|
||||
#include <QVector>
|
||||
|
||||
namespace Echonest {
|
||||
class Artist;
|
||||
}
|
||||
|
||||
class ArtistData : public QSharedData
|
||||
{
|
||||
public:
|
||||
ArtistData() : familiarity( -1 ), hotttnesss( -1 ) {}
|
||||
ArtistData( const QByteArray& id, const QString& name ) : id( id ), name( name ), familiarity( -1 ), hotttnesss( -1 ) {}
|
||||
ArtistData(const ArtistData& other)
|
||||
{
|
||||
id = other.id;
|
||||
name = other.name;
|
||||
}
|
||||
|
||||
// The following exist in all valid Artist objects
|
||||
QByteArray id;
|
||||
QString name;
|
||||
|
||||
//The following are populated on demand, and may not exist
|
||||
Echonest::AudioList audio;
|
||||
Echonest::BiographyList biographies;
|
||||
Echonest::BlogList blogs;
|
||||
|
||||
qreal familiarity;
|
||||
qreal hotttnesss;
|
||||
|
||||
Echonest::ArtistImageList images;
|
||||
Echonest::NewsList news;
|
||||
Echonest::ReviewList reviews;
|
||||
Echonest::SongList songs;
|
||||
QVector<Echonest::Artist> similar;
|
||||
Echonest::TermList terms;
|
||||
Echonest::VideoList videos;
|
||||
|
||||
QUrl lastfm_url;
|
||||
QUrl aolmusic_url;
|
||||
QUrl myspace_url;
|
||||
QUrl amazon_url;
|
||||
QUrl itunes_url;
|
||||
QUrl mb_url;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
314
3rdparty/libechonest/AudioSummary.cpp
vendored
Normal file
314
3rdparty/libechonest/AudioSummary.cpp
vendored
Normal file
@ -0,0 +1,314 @@
|
||||
/****************************************************************************************
|
||||
* 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 "AudioSummary.h"
|
||||
|
||||
#include "AudioSummary_p.h"
|
||||
#include <QNetworkReply>
|
||||
#include "Config.h"
|
||||
|
||||
Echonest::AudioSummary::AudioSummary()
|
||||
: d( new AudioSummaryData )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
Echonest::AudioSummary::AudioSummary(const Echonest::AudioSummary& other)
|
||||
:d( other.d )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
Echonest::AudioSummary::~AudioSummary()
|
||||
{}
|
||||
|
||||
QDebug Echonest::operator<<(QDebug d, const Echonest::AudioSummary& summary)
|
||||
{
|
||||
// d << summary
|
||||
return d.maybeSpace();
|
||||
}
|
||||
|
||||
Echonest::AudioSummary& Echonest::AudioSummary::operator=(const Echonest::AudioSummary& audio)
|
||||
{
|
||||
d = audio.d;
|
||||
return *this;
|
||||
}
|
||||
|
||||
int Echonest::AudioSummary::analysisStatus() const
|
||||
{
|
||||
return d->status;
|
||||
}
|
||||
|
||||
void Echonest::AudioSummary::setAnalysisStatus(int status)
|
||||
{
|
||||
d->status = status;
|
||||
}
|
||||
|
||||
qreal Echonest::AudioSummary::analysisTime() const
|
||||
{
|
||||
return d->analysis_time;
|
||||
}
|
||||
|
||||
void Echonest::AudioSummary::setAnalysisTime(qreal time)
|
||||
{
|
||||
d->analysis_time = time;
|
||||
}
|
||||
|
||||
QString Echonest::AudioSummary::analyzerVersion() const
|
||||
{
|
||||
return d->analyzer_version;
|
||||
}
|
||||
|
||||
void Echonest::AudioSummary::setAnalyzerVersion(QString version)
|
||||
{
|
||||
d->analyzer_version = version;
|
||||
}
|
||||
|
||||
Echonest::BarList Echonest::AudioSummary::bars() const
|
||||
{
|
||||
return d->bars;
|
||||
}
|
||||
|
||||
void Echonest::AudioSummary::setBars(const Echonest::BarList& bars)
|
||||
{
|
||||
d->bars = bars;
|
||||
}
|
||||
|
||||
Echonest::BeatList Echonest::AudioSummary::beats() const
|
||||
{
|
||||
return d->beats;
|
||||
}
|
||||
|
||||
void Echonest::AudioSummary::setBeats(const Echonest::BeatList& beats)
|
||||
{
|
||||
d->beats = beats;
|
||||
}
|
||||
|
||||
Echonest::Analysis::AnalysisStatus Echonest::AudioSummary::detailedStatus() const
|
||||
{
|
||||
return Echonest::statusToEnum( d->detailed_status );
|
||||
}
|
||||
|
||||
void Echonest::AudioSummary::setDetailedStatus(Echonest::Analysis::AnalysisStatus status)
|
||||
{
|
||||
d->detailed_status = Echonest::statusToString( status );
|
||||
}
|
||||
|
||||
qreal Echonest::AudioSummary::duration() const
|
||||
{
|
||||
return d->duration;
|
||||
}
|
||||
|
||||
void Echonest::AudioSummary::setDuration(qreal duration)
|
||||
{
|
||||
d->duration = duration;
|
||||
}
|
||||
|
||||
|
||||
qreal Echonest::AudioSummary::endOfFadeIn() const
|
||||
{
|
||||
return d->end_of_fade_in;
|
||||
}
|
||||
|
||||
void Echonest::AudioSummary::setEndOfFadeIn(qreal time)
|
||||
{
|
||||
d->end_of_fade_in = time;
|
||||
}
|
||||
|
||||
QNetworkReply* Echonest::AudioSummary::fetchFullAnalysis() const
|
||||
{
|
||||
return Echonest::Config::instance()->nam()->get( QNetworkRequest( QUrl( d->analysis_url ) ) );
|
||||
}
|
||||
|
||||
int Echonest::AudioSummary::key() const
|
||||
{
|
||||
return d->key;
|
||||
}
|
||||
|
||||
void Echonest::AudioSummary::setKey(int key)
|
||||
{
|
||||
d->key = key;
|
||||
}
|
||||
|
||||
qreal Echonest::AudioSummary::keyConfidence() const
|
||||
{
|
||||
return d->key_confidence;
|
||||
}
|
||||
|
||||
void Echonest::AudioSummary::setKeyConfidence(qreal confidence)
|
||||
{
|
||||
d->key_confidence = confidence;
|
||||
}
|
||||
|
||||
qreal Echonest::AudioSummary::loudness() const
|
||||
{
|
||||
return d->loudness;
|
||||
}
|
||||
|
||||
void Echonest::AudioSummary::setLoudness(qreal loudness)
|
||||
{
|
||||
d->loudness = loudness;
|
||||
}
|
||||
|
||||
qreal Echonest::AudioSummary::modeConfidence() const
|
||||
{
|
||||
return d->mode_confidence;
|
||||
}
|
||||
|
||||
void Echonest::AudioSummary::setModeConfidence(qreal confidence)
|
||||
{
|
||||
d->mode_confidence = confidence;
|
||||
}
|
||||
|
||||
qint64 Echonest::AudioSummary::numSamples() const
|
||||
{
|
||||
return d->num_samples;
|
||||
}
|
||||
|
||||
void Echonest::AudioSummary::setNumSamples(qint64 num)
|
||||
{
|
||||
d->num_samples = num;
|
||||
}
|
||||
|
||||
void Echonest::AudioSummary::parseFullAnalysis(QNetworkReply* reply)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
QString Echonest::AudioSummary::sampleMD5() const
|
||||
{
|
||||
return d->sample_md5;
|
||||
}
|
||||
|
||||
void Echonest::AudioSummary::setSampleMD5(const QString& md5)
|
||||
{
|
||||
d->sample_md5 = md5;
|
||||
}
|
||||
|
||||
qreal Echonest::AudioSummary::sampleRate() const
|
||||
{
|
||||
return d->samplerate;
|
||||
}
|
||||
|
||||
void Echonest::AudioSummary::setSampleRate(qreal sampleRate)
|
||||
{
|
||||
d->samplerate = sampleRate;
|
||||
}
|
||||
|
||||
Echonest::SectionList Echonest::AudioSummary::sections() const
|
||||
{
|
||||
return d->sections;
|
||||
}
|
||||
|
||||
void Echonest::AudioSummary::setSections(const Echonest::SectionList& sections)
|
||||
{
|
||||
d->sections = sections;
|
||||
}
|
||||
|
||||
Echonest::SegmentList Echonest::AudioSummary::segments() const
|
||||
{
|
||||
return d->segments;
|
||||
}
|
||||
|
||||
void Echonest::AudioSummary::setSegments(const Echonest::SegmentList& segments)
|
||||
{
|
||||
d->segments = segments;
|
||||
}
|
||||
|
||||
void Echonest::AudioSummary::setStartOfFadeOut(qreal time)
|
||||
{
|
||||
d->start_of_fade_out = time;
|
||||
}
|
||||
|
||||
Echonest::TatumList Echonest::AudioSummary::tatums() const
|
||||
{
|
||||
return d->tatums;
|
||||
}
|
||||
|
||||
void Echonest::AudioSummary::setTatums(const Echonest::TatumList& tatums)
|
||||
{
|
||||
d->tatums = tatums;
|
||||
}
|
||||
|
||||
qreal Echonest::AudioSummary::startOfFadeOut() const
|
||||
{
|
||||
return d->start_of_fade_out;
|
||||
}
|
||||
|
||||
qreal Echonest::AudioSummary::tempo() const
|
||||
{
|
||||
return d->tempo;
|
||||
}
|
||||
|
||||
void Echonest::AudioSummary::setTempo(qreal tempo)
|
||||
{
|
||||
d->tempo = tempo;
|
||||
}
|
||||
|
||||
qreal Echonest::AudioSummary::tempoConfidence() const
|
||||
{
|
||||
return d->tempo_confidence;
|
||||
}
|
||||
|
||||
void Echonest::AudioSummary::setTempoConfidence(qreal confidence)
|
||||
{
|
||||
d->tempo_confidence = confidence;
|
||||
}
|
||||
|
||||
int Echonest::AudioSummary::timeSignature() const
|
||||
{
|
||||
return d->time_signature;
|
||||
}
|
||||
|
||||
void Echonest::AudioSummary::setTimeSignature(int timeSignature)
|
||||
{
|
||||
d->time_signature = timeSignature;
|
||||
}
|
||||
|
||||
qreal Echonest::AudioSummary::timeSignatureConfidence() const
|
||||
{
|
||||
return d->time_signature_confidence;
|
||||
}
|
||||
|
||||
void Echonest::AudioSummary::setTimeSignatureConfidence(qreal confidence)
|
||||
{
|
||||
d->time_signature_confidence = confidence;
|
||||
}
|
||||
|
||||
void Echonest::AudioSummary::setTimestamp(qreal timestamp)
|
||||
{
|
||||
d->timestamp = timestamp;
|
||||
}
|
||||
|
||||
qreal Echonest::AudioSummary::timestamp() const
|
||||
{
|
||||
return d->timestamp;
|
||||
}
|
||||
|
||||
int Echonest::AudioSummary::mode() const
|
||||
{
|
||||
return d->mode;
|
||||
}
|
||||
|
||||
void Echonest::AudioSummary::setAnalysisUrl(const QString& analysisUrl)
|
||||
{
|
||||
d->analysis_url = analysisUrl;
|
||||
}
|
||||
|
||||
void Echonest::AudioSummary::setMode(int mode)
|
||||
{
|
||||
d->mode = mode;
|
||||
}
|
227
3rdparty/libechonest/AudioSummary.h
vendored
Normal file
227
3rdparty/libechonest/AudioSummary.h
vendored
Normal file
@ -0,0 +1,227 @@
|
||||
/****************************************************************************************
|
||||
* 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_AUDIOSUMMARY_H
|
||||
#define ECHONEST_AUDIOSUMMARY_H
|
||||
|
||||
#include "echonest_export.h"
|
||||
|
||||
#include <QSharedData>
|
||||
#include <QDebug>
|
||||
#include "Util.h"
|
||||
#include "Util.h"
|
||||
|
||||
class QNetworkReply;
|
||||
class QNetworkReply;
|
||||
class AudioSummaryData;
|
||||
|
||||
namespace Echonest{
|
||||
|
||||
/**
|
||||
* This encapsulates the audio summary of an Echo Nest track or song.
|
||||
*
|
||||
* It has two batches of data: the more generic acoustic information about the
|
||||
* song is always populated, and additional detailed information about the song
|
||||
* such as bars, beats, segments, tatus, and sections, can be fetched as well as
|
||||
* an additional step.
|
||||
*
|
||||
* This class is implicitly shared.
|
||||
*/
|
||||
class ECHONEST_EXPORT AudioSummary
|
||||
{
|
||||
public:
|
||||
AudioSummary();
|
||||
AudioSummary( const AudioSummary& other );
|
||||
~AudioSummary();
|
||||
|
||||
AudioSummary& operator=( const AudioSummary& audio );
|
||||
|
||||
int key() const;
|
||||
void setKey( int key );
|
||||
|
||||
/**
|
||||
* The track's tempo.
|
||||
*/
|
||||
qreal tempo() const;
|
||||
void setTempo( qreal tempo );
|
||||
|
||||
/**
|
||||
* The track's mode.
|
||||
*/
|
||||
int mode() const;
|
||||
void setMode( int mode );
|
||||
|
||||
/**
|
||||
* The track's time signature, or -1 if it there is one, or 1 if it is
|
||||
* too complex.
|
||||
*/
|
||||
int timeSignature() const;
|
||||
void setTimeSignature( int timeSignature );
|
||||
|
||||
/**
|
||||
* The duration of the song, in msecs.
|
||||
*/
|
||||
qreal duration() const;
|
||||
void setDuration( qreal duration );
|
||||
|
||||
/**
|
||||
* The loudness of the song, in dB.
|
||||
*/
|
||||
qreal loudness() const;
|
||||
void setLoudness( qreal loudness );
|
||||
|
||||
/**
|
||||
* If you wish to use any of the more detailed track analysis data,
|
||||
* use this method to begin the fetch. One the returned QNetworkReply*
|
||||
* has emitted the finished() signal, call parseFullAnalysis.
|
||||
*/
|
||||
QNetworkReply* fetchFullAnalysis() const;
|
||||
|
||||
/**
|
||||
* Parses the result of a fetchFullAnalysis() call. This contains
|
||||
* information such as mode, fadein/fadeout, confidence metrics,
|
||||
* and the division of the song into bars, beats, sections, and segments.
|
||||
*/
|
||||
void parseFullAnalysis( QNetworkReply* reply );
|
||||
|
||||
/// The following methods *ALL REQUIRE THAT parseFullAnalysis be called first*
|
||||
|
||||
/**
|
||||
* How long it took to analyze this track.
|
||||
*/
|
||||
qreal analysisTime() const;
|
||||
void setAnalysisTime( qreal time );
|
||||
|
||||
/**
|
||||
* The version of the analyzer used on this track.
|
||||
*/
|
||||
QString analyzerVersion() const;
|
||||
void setAnalyzerVersion( QString version );
|
||||
|
||||
/**
|
||||
* Detailed status information about the analysis
|
||||
*/
|
||||
Analysis::AnalysisStatus detailedStatus() const;
|
||||
void setDetailedStatus( Analysis::AnalysisStatus status );
|
||||
|
||||
/**
|
||||
* The status code of the analysis
|
||||
*/
|
||||
int analysisStatus() const;
|
||||
void setAnalysisStatus( int status );
|
||||
|
||||
/**
|
||||
* The timestamp of the analysis.
|
||||
*/
|
||||
qreal timestamp() const;
|
||||
void setTimestamp( qreal timestamp );
|
||||
|
||||
/** ECHONEST_EXPORT
|
||||
* The sample rate of the track.
|
||||
*/
|
||||
qreal sampleRate() const;
|
||||
void setSampleRate( qreal sampleRate );
|
||||
|
||||
/**
|
||||
* The end of the track's fade in in msec.
|
||||
*/
|
||||
qreal endOfFadeIn() const;
|
||||
void setEndOfFadeIn( qreal time );
|
||||
|
||||
/**
|
||||
* The start of the fade out in msec.
|
||||
*/
|
||||
qreal startOfFadeOut() const;
|
||||
void setStartOfFadeOut( qreal time );
|
||||
|
||||
/**
|
||||
* The confidence of the key item.
|
||||
*/
|
||||
qreal keyConfidence() const;
|
||||
void setKeyConfidence( qreal confidence );
|
||||
|
||||
/**
|
||||
* The confidence of the mode item.
|
||||
*/
|
||||
qreal modeConfidence() const;
|
||||
void setModeConfidence( qreal confidence );
|
||||
|
||||
/**
|
||||
* The confidence of the tempo item.
|
||||
*/
|
||||
qreal tempoConfidence() const;
|
||||
void setTempoConfidence( qreal confidence );
|
||||
|
||||
/**
|
||||
* The confidence of the time signature item.
|
||||
*/
|
||||
qreal timeSignatureConfidence() const;
|
||||
void setTimeSignatureConfidence( qreal confidence );
|
||||
|
||||
/**
|
||||
* The number of samples in this track.
|
||||
*/
|
||||
qint64 numSamples() const;
|
||||
void setNumSamples( qint64 num );
|
||||
|
||||
/**
|
||||
* The MD5 of the sample.
|
||||
*/
|
||||
QString sampleMD5() const;
|
||||
void setSampleMD5( const QString& md5 );
|
||||
|
||||
/**
|
||||
* List of bars that are in the track.
|
||||
*/
|
||||
BarList bars() const;
|
||||
void setBars( const BarList& bars );
|
||||
|
||||
/**
|
||||
* List of beats in the track.
|
||||
*/
|
||||
BeatList beats() const;
|
||||
void setBeats( const BeatList& beats );
|
||||
|
||||
/**
|
||||
* List of sections in the track.
|
||||
*/
|
||||
SectionList sections() const;
|
||||
void setSections( const SectionList& sections );
|
||||
|
||||
/**
|
||||
* List of tatums in the track
|
||||
*/
|
||||
TatumList tatums() const;
|
||||
void setTatums( const TatumList& tatums );
|
||||
|
||||
/**
|
||||
* List of segments in the track with associated acoustic data.
|
||||
*/
|
||||
SegmentList segments() const;
|
||||
void setSegments( const SegmentList& segments );
|
||||
|
||||
void setAnalysisUrl( const QString& analysisUrl );
|
||||
|
||||
private:
|
||||
QSharedDataPointer<AudioSummaryData> d;
|
||||
};
|
||||
|
||||
ECHONEST_EXPORT QDebug operator<<(QDebug d, const Echonest::AudioSummary& summary);
|
||||
|
||||
|
||||
} // namespace
|
||||
#endif
|
100
3rdparty/libechonest/AudioSummary_p.h
vendored
Normal file
100
3rdparty/libechonest/AudioSummary_p.h
vendored
Normal file
@ -0,0 +1,100 @@
|
||||
/****************************************************************************************
|
||||
* 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 "Util.h"
|
||||
|
||||
#include <QSharedData>
|
||||
#include <QString>
|
||||
#include <QUrl>
|
||||
#include <QVector>
|
||||
|
||||
class AudioSummaryData : public QSharedData
|
||||
{
|
||||
public:
|
||||
AudioSummaryData() {}
|
||||
AudioSummaryData(const AudioSummaryData& other)
|
||||
{
|
||||
key = other.key;
|
||||
tempo = other.tempo;
|
||||
mode = other.mode;
|
||||
time_signature = other.time_signature;
|
||||
duration = other.duration;
|
||||
loudness = other.loudness;
|
||||
samplerate = other.samplerate;
|
||||
|
||||
analysis_url = other.analysis_url;
|
||||
|
||||
analysis_time = other.analysis_time;
|
||||
analyzer_version = other.analyzer_version;
|
||||
detailed_status = other.detailed_status;
|
||||
status = other.status;
|
||||
timestamp = other.timestamp;
|
||||
|
||||
end_of_fade_in = other.end_of_fade_in;
|
||||
key_confidence = other.key_confidence;
|
||||
loudness = other.loudness;
|
||||
mode_confidence = other.mode_confidence;
|
||||
num_samples = other.num_samples;
|
||||
sample_md5 = other.sample_md5;
|
||||
start_of_fade_out = other.start_of_fade_out;
|
||||
tempo_confidence = other.tempo_confidence;
|
||||
time_signature = other.time_signature;
|
||||
time_signature_confidence = other.time_signature_confidence;
|
||||
|
||||
bars = other.bars;
|
||||
beats = other.beats;
|
||||
sections = other.sections;
|
||||
tatums = other.tatums;
|
||||
segments = other.segments;
|
||||
|
||||
}
|
||||
|
||||
// basic data that always exists in an Audio Summary object
|
||||
int key;
|
||||
qreal tempo;
|
||||
int mode;
|
||||
int time_signature;
|
||||
qreal duration;
|
||||
qreal loudness;
|
||||
int samplerate;
|
||||
|
||||
QUrl analysis_url; // used to fetch the following pieces of data
|
||||
|
||||
// meta section
|
||||
qreal analysis_time;
|
||||
QString analyzer_version;
|
||||
QString detailed_status;
|
||||
int status;
|
||||
qreal timestamp;
|
||||
|
||||
// track section
|
||||
qreal end_of_fade_in;
|
||||
qreal key_confidence;
|
||||
qreal mode_confidence;
|
||||
qint64 num_samples;
|
||||
QString sample_md5;
|
||||
qreal start_of_fade_out;
|
||||
qreal tempo_confidence;
|
||||
qreal time_signature_confidence;
|
||||
|
||||
Echonest::BarList bars;
|
||||
Echonest::BeatList beats;
|
||||
Echonest::SectionList sections;
|
||||
Echonest::TatumList tatums;
|
||||
|
||||
Echonest::SegmentList segments;
|
||||
|
||||
};
|
58
3rdparty/libechonest/CMakeLists.txt
vendored
Normal file
58
3rdparty/libechonest/CMakeLists.txt
vendored
Normal file
@ -0,0 +1,58 @@
|
||||
|
||||
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 )
|
||||
add_definitions( -fvisibility=hidden )
|
||||
# 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} )
|
||||
|
||||
set( LIBECHONEST_SRC
|
||||
Track.cpp
|
||||
Song.cpp
|
||||
Artist.cpp
|
||||
Playlist.cpp
|
||||
Config.cpp
|
||||
Parsing.cpp
|
||||
AudioSummary.cpp
|
||||
Util.cpp
|
||||
ArtistTypes.cpp
|
||||
)
|
||||
|
||||
set( LIBECHONEST_H
|
||||
Track.h
|
||||
Song.h
|
||||
Artist.h
|
||||
Playlist.h
|
||||
Config.h
|
||||
AudioSummary.h
|
||||
ArtistTypes.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} )
|
||||
|
||||
# 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)
|
||||
endforeach(file ${LIBECHONEST_H})
|
127
3rdparty/libechonest/Config.cpp
vendored
Normal file
127
3rdparty/libechonest/Config.cpp
vendored
Normal file
@ -0,0 +1,127 @@
|
||||
/****************************************************************************************
|
||||
* 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 "Config.h"
|
||||
|
||||
#include <QNetworkAccessManager>
|
||||
#include <QDebug>
|
||||
|
||||
Echonest::Config* Echonest::Config::s_instance = 0;
|
||||
|
||||
QUrl Echonest::baseUrl()
|
||||
{
|
||||
QUrl url;
|
||||
url.setScheme( QLatin1String( "http" ) );
|
||||
url.setHost( QLatin1String( "developer.echonest.com" ) );
|
||||
return url;
|
||||
}
|
||||
|
||||
|
||||
QUrl Echonest::baseGetQuery(const QByteArray& type, const QByteArray& method)
|
||||
{
|
||||
QUrl url = baseUrl();
|
||||
url.setPath( QString::fromLatin1( "/api/v4/%1/%2" ).arg( QLatin1String( type ) ).arg( QLatin1String( method ) ) );
|
||||
url.addEncodedQueryItem( "api_key", Echonest::Config::instance()->apiKey() );
|
||||
url.addEncodedQueryItem( "format", "xml" );
|
||||
return url;
|
||||
}
|
||||
|
||||
Echonest::ParseError::ParseError(Echonest::ErrorType error): exception()
|
||||
{
|
||||
type = error;
|
||||
}
|
||||
|
||||
Echonest::ParseError::~ParseError() throw()
|
||||
{}
|
||||
|
||||
Echonest::ErrorType Echonest::ParseError::errorType() const
|
||||
{
|
||||
return type;
|
||||
}
|
||||
|
||||
void Echonest::ParseError::setNetworkError( QNetworkReply::NetworkError error )
|
||||
{
|
||||
nError = error;
|
||||
}
|
||||
|
||||
QNetworkReply::NetworkError Echonest::ParseError::networkError() const
|
||||
{
|
||||
return nError;
|
||||
}
|
||||
|
||||
|
||||
|
||||
class Echonest::ConfigPrivate {
|
||||
public:
|
||||
ConfigPrivate() : nam( new QNetworkAccessManager )
|
||||
{
|
||||
}
|
||||
|
||||
~ConfigPrivate()
|
||||
{
|
||||
delete nam;
|
||||
nam = 0;
|
||||
}
|
||||
|
||||
QNetworkAccessManager* nam;
|
||||
QByteArray apikey;
|
||||
};
|
||||
|
||||
Echonest::Config::Config()
|
||||
: d( new Echonest::ConfigPrivate )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
Echonest::Config::~Config()
|
||||
{
|
||||
delete d;
|
||||
}
|
||||
|
||||
void Echonest::Config::setAPIKey(const QByteArray& apiKey)
|
||||
{
|
||||
d->apikey = apiKey;
|
||||
}
|
||||
|
||||
QByteArray Echonest::Config::apiKey() const
|
||||
{
|
||||
return d->apikey;
|
||||
}
|
||||
|
||||
|
||||
void Echonest::Config::setNetworkAccessManager(QNetworkAccessManager* nam)
|
||||
{
|
||||
if( !nam )
|
||||
return;
|
||||
|
||||
if( d->nam ) {
|
||||
delete d->nam;
|
||||
}
|
||||
d->nam = nam;
|
||||
}
|
||||
|
||||
QNetworkAccessManager* Echonest::Config::nam() const
|
||||
{
|
||||
return d->nam;
|
||||
}
|
||||
|
||||
Echonest::Config* Echonest::Config::instance() {
|
||||
if ( !s_instance ) {
|
||||
s_instance = new Config;
|
||||
}
|
||||
|
||||
return s_instance;
|
||||
}
|
115
3rdparty/libechonest/Config.h
vendored
Normal file
115
3rdparty/libechonest/Config.h
vendored
Normal file
@ -0,0 +1,115 @@
|
||||
/****************************************************************************************
|
||||
* 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_CONFIG_H
|
||||
#define ECHONEST_CONFIG_H
|
||||
|
||||
#include "echonest_export.h"
|
||||
|
||||
#include <QByteArray>
|
||||
#include <QUrl>
|
||||
|
||||
#include <exception>
|
||||
#include <QNetworkReply>
|
||||
|
||||
class QNetworkAccessManager;
|
||||
|
||||
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
|
||||
*/
|
||||
UnknownError = -1,
|
||||
NoError = 0,
|
||||
MissingAPIKey = 1,
|
||||
NotAllowed = 2,
|
||||
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 ParseError : public std::exception
|
||||
{
|
||||
public:
|
||||
ParseError( ErrorType error );
|
||||
virtual ~ParseError() throw();
|
||||
|
||||
ErrorType errorType() const;
|
||||
|
||||
/**
|
||||
* If the ErrorType is NetworkError, this value contains the QNetworkReply
|
||||
* error code that was returned.
|
||||
*/
|
||||
void setNetworkError( QNetworkReply::NetworkError error );
|
||||
QNetworkReply::NetworkError networkError() const;
|
||||
|
||||
private:
|
||||
ErrorType type;
|
||||
QNetworkReply::NetworkError nError;
|
||||
};
|
||||
|
||||
class ConfigPrivate;
|
||||
/**
|
||||
* This singleton contains miscellaneous settings used to access The Echo Nest
|
||||
*/
|
||||
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
|
||||
* 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 take over control of the object.
|
||||
*/
|
||||
void setNetworkAccessManager( QNetworkAccessManager* nam );
|
||||
QNetworkAccessManager* nam() const;
|
||||
|
||||
|
||||
private:
|
||||
Config();
|
||||
~Config();
|
||||
|
||||
static Config* s_instance;
|
||||
|
||||
ConfigPrivate* d;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
601
3rdparty/libechonest/Parsing.cpp
vendored
Normal file
601
3rdparty/libechonest/Parsing.cpp
vendored
Normal file
@ -0,0 +1,601 @@
|
||||
/****************************************************************************************
|
||||
* 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 "Parsing_p.h"
|
||||
|
||||
#include "Util.h"
|
||||
|
||||
#include <QNetworkReply>
|
||||
#include "Artist.h"
|
||||
#include <QDateTime>
|
||||
|
||||
void Echonest::Parser::checkForErrors( QNetworkReply* reply ) throw( Echonest::ParseError )
|
||||
{
|
||||
if( !reply )
|
||||
throw new ParseError( Echonest::UnknownError );
|
||||
|
||||
if( !reply->isFinished() )
|
||||
throw new ParseError( Echonest::UnfinishedQuery );
|
||||
|
||||
if( reply->error() != QNetworkReply::NoError ) {
|
||||
ParseError* err = new ParseError( Echonest::NetworkError );
|
||||
err->setNetworkError( reply->error() );
|
||||
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
void Echonest::Parser::readStatus( QXmlStreamReader& xml ) throw( Echonest::ParseError )
|
||||
{
|
||||
if( xml.readNextStartElement() ) {
|
||||
// sanity checks
|
||||
if( xml.name() != QLatin1String( "response" ) )
|
||||
throw new ParseError( UnknownParseError );
|
||||
|
||||
if( xml.readNextStartElement() ) {
|
||||
if( xml.name() != "status" )
|
||||
throw new ParseError( UnknownParseError );
|
||||
|
||||
// only check the error code for now
|
||||
xml.readNextStartElement();
|
||||
double version = xml.readElementText().toDouble();
|
||||
// TODO use version for something?
|
||||
Q_UNUSED(version);
|
||||
xml.readNextStartElement();
|
||||
Echonest::ErrorType code = static_cast< Echonest::ErrorType >( xml.readElementText().toInt() );
|
||||
xml.readNextStartElement();
|
||||
QString msg = xml.readElementText();
|
||||
xml.readNextStartElement();
|
||||
|
||||
if( code != Echonest::NoError ) {
|
||||
throw new ParseError( code );
|
||||
}
|
||||
|
||||
xml.readNext();
|
||||
}
|
||||
|
||||
} else {
|
||||
throw new ParseError( UnknownParseError );
|
||||
}
|
||||
}
|
||||
|
||||
QVector< Echonest::Song > Echonest::Parser::parseSongList( QXmlStreamReader& xml ) throw( Echonest::ParseError )
|
||||
{
|
||||
QVector< Echonest::Song > songs;
|
||||
|
||||
xml.readNext();
|
||||
while( !( xml.name() == "songs" && xml.tokenType() == QXmlStreamReader::EndElement ) ) {
|
||||
// parse a song
|
||||
songs.append( parseSong( xml ) );
|
||||
}
|
||||
return songs;
|
||||
}
|
||||
|
||||
Echonest::Song Echonest::Parser::parseSong( QXmlStreamReader& xml ) throw( Echonest::ParseError )
|
||||
{
|
||||
if( xml.name() != "song" )
|
||||
throw new ParseError( Echonest::UnknownParseError );
|
||||
|
||||
Echonest::Song song;
|
||||
while( !( xml.name() == "song" && xml.tokenType() == QXmlStreamReader::EndElement ) ) {
|
||||
if( xml.name() == "id" && xml.isStartElement() )
|
||||
song.setId( xml.readElementText().toLatin1() );
|
||||
else if( xml.name() == "title" && xml.isStartElement() )
|
||||
song.setTitle( xml.readElementText() );
|
||||
else if( xml.name() == "artist_id" && xml.isStartElement() )
|
||||
song.setArtistId( xml.readElementText().toLatin1() );
|
||||
else if( xml.name() == "artist_name" && xml.isStartElement() )
|
||||
song.setArtistName( xml.readElementText() );
|
||||
else if( xml.name() == "song_hotttnesss" && xml.isStartElement() )
|
||||
song.setHotttnesss( xml.readElementText().toDouble() );
|
||||
else if( xml.name() == "artist_hotttnesss" && xml.isStartElement() )
|
||||
song.setArtistHotttnesss( xml.readElementText().toDouble() );
|
||||
else if( xml.name() == "artist_familiarity" && xml.isStartElement() )
|
||||
song.setArtistFamiliarity( xml.readElementText().toDouble() );
|
||||
else if( xml.name() == "artist_location" && xml.isStartElement() ) {
|
||||
while( !( xml.name() == "location" && xml.tokenType() == QXmlStreamReader::EndElement ) ) {
|
||||
xml.readNextStartElement();
|
||||
if( xml.name() == "location" )
|
||||
song.setArtistLocation( xml.readElementText() );
|
||||
}
|
||||
xml.readNext();
|
||||
} else if( xml.name() == "audio_summary" && xml.isStartElement() ) {
|
||||
song.setAudioSummary( parseAudioSummary( xml ) );
|
||||
}
|
||||
xml.readNext();
|
||||
}
|
||||
xml.readNext(); // skip past the last </song>
|
||||
|
||||
return song;
|
||||
}
|
||||
|
||||
Echonest::Track Echonest::Parser::parseTrack( QXmlStreamReader& xml ) throw( Echonest::ParseError )
|
||||
{
|
||||
if( xml.name() != "track" ) {
|
||||
throw new ParseError( Echonest::UnknownParseError );
|
||||
}
|
||||
|
||||
Echonest::Track track;
|
||||
while( !( xml.name() == "track" && xml.tokenType() == QXmlStreamReader::EndElement ) ) {
|
||||
if( xml.name() == "id" && xml.isStartElement() )
|
||||
track.setId( xml.readElementText().toLatin1() );
|
||||
else if( xml.name() == "title" && xml.isStartElement() )
|
||||
track.setTitle( xml.readElementText() );
|
||||
else if( xml.name() == "artist" && xml.isStartElement() )
|
||||
track.setArtist( xml.readElementText() );
|
||||
else if( xml.name() == "status" && xml.isStartElement() )
|
||||
track.setStatus( Echonest::statusToEnum( xml.readElementText() ) );
|
||||
else if( xml.name() == "analyzer_version" && xml.isStartElement() )
|
||||
track.setAnalyzerVersion( xml.readElementText() );
|
||||
else if( xml.name() == "release" && xml.isStartElement() )
|
||||
track.setRelease( xml.readElementText() );
|
||||
else if( xml.name() == "audio_md5" && xml.isStartElement() )
|
||||
track.setAudioMD5( xml.readElementText().toLatin1() );
|
||||
else if( xml.name() == "bitrate" && xml.isStartElement() )
|
||||
track.setBitrate( xml.readElementText().toInt() );
|
||||
else if( xml.name() == "samplerate" && xml.isStartElement() )
|
||||
track.setSamplerate( xml.readElementText().toInt() );
|
||||
else if( xml.name() == "md5" && xml.isStartElement() )
|
||||
track.setMD5( xml.readElementText().toLatin1() );
|
||||
else if( xml.name() == "audio_summary" && xml.isStartElement() ) {
|
||||
track.setAudioSummary( parseAudioSummary( xml ) );
|
||||
continue;
|
||||
}
|
||||
xml.readNext();
|
||||
}
|
||||
xml.readNext(); // skip past the last
|
||||
|
||||
return track;
|
||||
}
|
||||
|
||||
|
||||
Echonest::AudioSummary Echonest::Parser::parseAudioSummary( QXmlStreamReader& xml ) throw( Echonest::ParseError )
|
||||
{
|
||||
if( xml.name() != "audio_summary" ) {
|
||||
throw new ParseError( Echonest::UnknownParseError );
|
||||
}
|
||||
|
||||
Echonest::AudioSummary summary;
|
||||
while( !( xml.name() == "audio_summary" && xml.tokenType() == QXmlStreamReader::EndElement ) ) {
|
||||
if( xml.name() == "key" && xml.isStartElement() )
|
||||
summary.setKey( xml.readElementText().toInt() );
|
||||
else if( xml.name() == "analysis_url" && xml.isStartElement() )
|
||||
summary.setAnalysisUrl( xml.readElementText() );
|
||||
else if( xml.name() == "tempo" && xml.isStartElement() )
|
||||
summary.setTempo( xml.readElementText().toDouble() );
|
||||
else if( xml.name() == "mode" && xml.isStartElement() )
|
||||
summary.setMode( xml.readElementText().toInt() );
|
||||
else if( xml.name() == "time_signature" && xml.isStartElement() )
|
||||
summary.setTimeSignature( xml.readElementText().toInt() );
|
||||
else if( xml.name() == "duration" && xml.isStartElement() )
|
||||
summary.setDuration( xml.readElementText().toDouble() );
|
||||
else if( xml.name() == "loudness" && xml.isStartElement() )
|
||||
summary.setLoudness( xml.readElementText().toDouble() );
|
||||
|
||||
xml.readNext();
|
||||
}
|
||||
|
||||
return summary;
|
||||
}
|
||||
|
||||
|
||||
Echonest::Artists Echonest::Parser::parseArtists( QXmlStreamReader& xml )
|
||||
{
|
||||
// we expect to be in an <artists> start element
|
||||
if( xml.name() != "artists" || !xml.isStartElement() )
|
||||
throw new ParseError( Echonest::UnknownParseError );
|
||||
|
||||
xml.readNextStartElement();
|
||||
|
||||
Echonest::Artists artists;
|
||||
while( xml.name() != "artists" || !xml.isEndElement() ) {
|
||||
if( xml.name() != "artist" || !xml.isStartElement() )
|
||||
throw new Echonest::ParseError( Echonest::UnknownParseError );
|
||||
Echonest::Artist artist;
|
||||
while( xml.name() != "artist" || !xml.isEndElement() ) {
|
||||
parseArtistInfo( xml, artist );
|
||||
xml.readNextStartElement();
|
||||
}
|
||||
artists.append( artist );
|
||||
|
||||
xml.readNext();
|
||||
}
|
||||
return artists;
|
||||
}
|
||||
|
||||
int Echonest::Parser::parseArtistInfoOrProfile( QXmlStreamReader& xml , Echonest::Artist& artist ) throw( Echonest::ParseError )
|
||||
{
|
||||
if( xml.name() == "start" ) { // this is an individual info query, so lets read it
|
||||
xml.readNextStartElement();
|
||||
xml.readNext();
|
||||
|
||||
int results = -1;
|
||||
if( xml.name() == "total" ) {
|
||||
results = xml.readElementText().toInt();
|
||||
xml.readNextStartElement();
|
||||
}
|
||||
|
||||
parseArtistInfo( xml, artist );
|
||||
|
||||
return results;
|
||||
} else if( xml.name() == "songs" ) {
|
||||
parseArtistSong( xml, artist );
|
||||
} else if( xml.name() == "urls" ) { // urls also has no start/total
|
||||
parseUrls( xml, artist );
|
||||
} else { // this is either a profile query, or a familiarity or hotttness query, so save all the data we find
|
||||
while( !( xml.name() == "artist" && xml.tokenType() == QXmlStreamReader::EndElement ) ) {
|
||||
parseArtistInfo( xml, artist );
|
||||
xml.readNextStartElement();
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Echonest::Parser::parseArtistInfo( QXmlStreamReader& xml, Echonest::Artist& artist ) throw( Echonest::ParseError )
|
||||
{
|
||||
// parse each sort of artist information
|
||||
if( xml.name() == "audio" ) {
|
||||
parseAudio( xml, artist );
|
||||
} else if( xml.name() == "biographies" ) {
|
||||
parseBiographies( xml, artist );
|
||||
} else if( xml.name() == "familiarity" ) {
|
||||
artist.setFamiliarity( xml.readElementText().toDouble() );
|
||||
} else if( xml.name() == "hotttnesss" ) {
|
||||
artist.setHotttnesss( xml.readElementText().toDouble() );
|
||||
} else if( xml.name() == "images" ) {
|
||||
parseImages( xml, artist );
|
||||
} else if( xml.name() == "news" ) {
|
||||
parseNewsOrBlogs( xml, artist, true );
|
||||
} else if( xml.name() == "blogs" ) {
|
||||
parseNewsOrBlogs( xml, artist, false );
|
||||
} else if( xml.name() == "reviews" ) {
|
||||
parseReviews( xml, artist );
|
||||
} else if( xml.name() == "terms" ) {
|
||||
parseTerms( xml, artist );
|
||||
} else if( xml.name() == "urls" ) {
|
||||
parseTerms( xml, artist );
|
||||
} else if( xml.name() == "songs" ) {
|
||||
parseArtistSong( xml, artist );
|
||||
} else if( xml.name() == "video" ) {
|
||||
parseVideos( xml, artist );
|
||||
} else if( xml.name() == "foreign_ids" ) {
|
||||
parseForeignIds( xml, artist );
|
||||
} else if( xml.name() == "name" ) {
|
||||
artist.setName( xml.readElementText() );
|
||||
} else if( xml.name() == "id" ) {
|
||||
artist.setId( xml.readElementText().toLatin1() );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// parse each type of artist attribute
|
||||
|
||||
void Echonest::Parser::parseAudio( QXmlStreamReader& xml, Echonest::Artist& artist ) throw( Echonest::ParseError )
|
||||
{
|
||||
if( xml.name() != "audio" || xml.tokenType() != QXmlStreamReader::StartElement )
|
||||
throw new Echonest::ParseError( Echonest::UnknownParseError );
|
||||
|
||||
xml.readNextStartElement();
|
||||
Echonest::AudioList audioList;
|
||||
while( xml.name() != "audio" || xml.tokenType() != QXmlStreamReader::EndElement ) {
|
||||
Echonest::AudioFile audio;
|
||||
do {
|
||||
xml.readNext();
|
||||
|
||||
if( xml.name() == "title" )
|
||||
audio.setTitle( xml.readElementText() );
|
||||
else if( xml.name() == "url" )
|
||||
audio.setUrl( QUrl( xml.readElementText() ) );
|
||||
else if( xml.name() == "artist" )
|
||||
audio.setArtist( xml.readElementText() );
|
||||
else if( xml.name() == "date" )
|
||||
audio.setDate( QDateTime::fromString( xml.readElementText(), Qt::ISODate ) );
|
||||
else if( xml.name() == "length" )
|
||||
audio.setLength( xml.readElementText().toDouble() );
|
||||
else if( xml.name() == "link" )
|
||||
audio.setLink( QUrl( xml.readElementText() ) );
|
||||
else if( xml.name() == "release" )
|
||||
audio.setRelease( xml.readElementText() );
|
||||
else if( xml.name() == "id" )
|
||||
audio.setId( xml.readElementText().toLatin1() );
|
||||
|
||||
} while( xml.name() != "audio" || xml.tokenType() != QXmlStreamReader::EndElement );
|
||||
audioList.append( audio );
|
||||
xml.readNext();
|
||||
}
|
||||
artist.setAudio( audioList );
|
||||
}
|
||||
|
||||
void Echonest::Parser::parseBiographies( QXmlStreamReader& xml, Echonest::Artist& artist ) throw( Echonest::ParseError )
|
||||
{
|
||||
if( xml.name() != "biographies" || xml.tokenType() != QXmlStreamReader::StartElement )
|
||||
throw new Echonest::ParseError( Echonest::UnknownParseError );
|
||||
|
||||
xml.readNextStartElement();
|
||||
Echonest::BiographyList bios;
|
||||
while( xml.name() != "biographies" || xml.tokenType() != QXmlStreamReader::EndElement ) {
|
||||
Echonest::Biography bio;
|
||||
do {
|
||||
xml.readNext();
|
||||
|
||||
if( xml.name() == "text" )
|
||||
bio.setText( xml.readElementText() );
|
||||
else if( xml.name() == "site" )
|
||||
bio.setSite( xml.readElementText() );
|
||||
else if( xml.name() == "url" )
|
||||
bio.setUrl( QUrl( xml.readElementText() ) );
|
||||
else if( xml.name() == "license" )
|
||||
bio.setLicense( parseLicense( xml) );
|
||||
|
||||
} while( xml.name() != "biography" || xml.tokenType() != QXmlStreamReader::EndElement );
|
||||
bios.append( bio );
|
||||
xml.readNext();
|
||||
}
|
||||
artist.setBiographies( bios );
|
||||
}
|
||||
|
||||
|
||||
void Echonest::Parser::parseImages( QXmlStreamReader& xml, Echonest::Artist& artist ) throw( Echonest::ParseError )
|
||||
{
|
||||
if( xml.name() != "images" || xml.tokenType() != QXmlStreamReader::StartElement )
|
||||
throw new Echonest::ParseError( Echonest::UnknownParseError );
|
||||
|
||||
xml.readNextStartElement();
|
||||
Echonest::ArtistImageList imgs;
|
||||
while( xml.name() != "images" || xml.tokenType() != QXmlStreamReader::EndElement ) {
|
||||
Echonest::ArtistImage img;
|
||||
do {
|
||||
xml.readNext();
|
||||
|
||||
if( xml.name() == "url" )
|
||||
img.setUrl( QUrl( xml.readElementText() ) );
|
||||
else if( xml.name() == "license" )
|
||||
img.setLicense( parseLicense( xml) );
|
||||
|
||||
} while( xml.name() != "image" || xml.tokenType() != QXmlStreamReader::EndElement );
|
||||
imgs.append( img );
|
||||
xml.readNext();
|
||||
}
|
||||
artist.setImages( imgs );
|
||||
}
|
||||
|
||||
void Echonest::Parser::parseNewsOrBlogs( QXmlStreamReader& xml, Echonest::Artist& artist, bool news ) throw( Echonest::ParseError )
|
||||
{
|
||||
if( news && ( xml.name() != "news" || xml.tokenType() != QXmlStreamReader::StartElement ) )
|
||||
throw new Echonest::ParseError( Echonest::UnknownParseError );
|
||||
else if( !news && ( xml.name() != "blogs" || xml.tokenType() != QXmlStreamReader::StartElement ) )
|
||||
throw new Echonest::ParseError( Echonest::UnknownParseError );
|
||||
|
||||
xml.readNextStartElement();
|
||||
Echonest::NewsList newsList;
|
||||
while( !( ( xml.name() == "news" || xml.name() == "blogs" ) && xml.tokenType() == QXmlStreamReader::EndElement ) ) {
|
||||
Echonest::NewsArticle news;
|
||||
do {
|
||||
xml.readNextStartElement();
|
||||
|
||||
if( xml.name() == "name" )
|
||||
news.setName( xml.readElementText() );
|
||||
else if( xml.name() == "url" )
|
||||
news.setUrl( QUrl( xml.readElementText() ) );
|
||||
else if( xml.name() == "summary" )
|
||||
news.setSummary( xml.readElementText() );
|
||||
else if( xml.name() == "date_found" )
|
||||
news.setDateFound( QDateTime::fromString( xml.readElementText(), Qt::ISODate ) );
|
||||
else if( xml.name() == "id" )
|
||||
news.setId( xml.readElementText().toLatin1() );
|
||||
else if( xml.name() == "date_posted" )
|
||||
news.setDatePosted( QDateTime::fromString( xml.readElementText(), Qt::ISODate ) );
|
||||
|
||||
} while( !( ( xml.name() == "news" || xml.name() == "blog" ) && xml.tokenType() == QXmlStreamReader::EndElement ) );
|
||||
newsList.append( news );
|
||||
xml.readNext();
|
||||
}
|
||||
if( news )
|
||||
artist.setNews( newsList );
|
||||
else
|
||||
artist.setBlogs( newsList );
|
||||
}
|
||||
|
||||
void Echonest::Parser::parseReviews( QXmlStreamReader& xml, Echonest::Artist& artist ) throw( Echonest::ParseError )
|
||||
{
|
||||
if( xml.name() != "reviews" || xml.tokenType() != QXmlStreamReader::StartElement )
|
||||
throw new Echonest::ParseError( Echonest::UnknownParseError );
|
||||
|
||||
xml.readNextStartElement();
|
||||
Echonest::ReviewList reviews;
|
||||
while( xml.name() != "reviews" || xml.tokenType() != QXmlStreamReader::EndElement ) {
|
||||
Echonest::Review review;
|
||||
do {
|
||||
xml.readNextStartElement();
|
||||
|
||||
if( xml.name() == "url" )
|
||||
review.setUrl( QUrl( xml.readElementText() ) );
|
||||
else if( xml.name() == "name" )
|
||||
review.setName( xml.readElementText() );
|
||||
else if( xml.name() == "summary" )
|
||||
review.setSummary( xml.readElementText() );
|
||||
else if( xml.name() == "date_found" )
|
||||
review.setDateFound( QDateTime::fromString( xml.readElementText(), Qt::ISODate ) );
|
||||
else if( xml.name() == "image" )
|
||||
review.setImageUrl( QUrl( xml.readElementText() ) );
|
||||
else if( xml.name() == "release" )
|
||||
review.setRelease( xml.readElementText() );
|
||||
else if( xml.name() == "id" )
|
||||
review.setId( xml.readElementText().toLatin1() );
|
||||
|
||||
} while( xml.name() != "review" || xml.tokenType() != QXmlStreamReader::EndElement );
|
||||
reviews.append( review );
|
||||
xml.readNext();
|
||||
}
|
||||
artist.setReviews( reviews );
|
||||
}
|
||||
|
||||
void Echonest::Parser::parseArtistSong( QXmlStreamReader& xml, Echonest::Artist& artist ) throw( Echonest::ParseError )
|
||||
{
|
||||
if( xml.name() != "songs" || xml.tokenType() != QXmlStreamReader::StartElement )
|
||||
throw new Echonest::ParseError( Echonest::UnknownParseError );
|
||||
|
||||
xml.readNextStartElement();
|
||||
Echonest::SongList songs;
|
||||
while( xml.name() != "songs" || xml.tokenType() != QXmlStreamReader::EndElement ) {
|
||||
if( xml.name() == "song" && xml.isStartElement() )
|
||||
{
|
||||
Echonest::Song song;
|
||||
while( xml.name() != "song" || !xml.isEndElement() ) {
|
||||
if( xml.name() == "id" && xml.isStartElement() )
|
||||
song.setId( xml.readElementText().toLatin1() );
|
||||
else if( xml.name() == "title" && xml.isStartElement() )
|
||||
song.setTitle( xml.readElementText() );
|
||||
xml.readNextStartElement();
|
||||
}
|
||||
songs.append( song );
|
||||
}
|
||||
xml.readNext();
|
||||
}
|
||||
artist.setSongs( songs );
|
||||
}
|
||||
|
||||
void Echonest::Parser::parseTerms( QXmlStreamReader& xml, Echonest::Artist& artist ) throw( Echonest::ParseError )
|
||||
{
|
||||
if( xml.name() != "terms" || xml.tokenType() != QXmlStreamReader::StartElement )
|
||||
throw new Echonest::ParseError( Echonest::UnknownParseError );
|
||||
|
||||
artist.setTerms( parseTermList( xml ) );
|
||||
}
|
||||
|
||||
void Echonest::Parser::parseUrls( QXmlStreamReader& xml, Echonest::Artist& artist ) throw( Echonest::ParseError )
|
||||
{
|
||||
if( xml.name() != "urls" || xml.tokenType() != QXmlStreamReader::StartElement )
|
||||
throw new Echonest::ParseError( Echonest::UnknownParseError );
|
||||
|
||||
xml.readNextStartElement();
|
||||
xml.readNextStartElement();
|
||||
|
||||
while( xml.name() != "urls" || !xml.isEndElement() ) {
|
||||
if( xml.name() == "lastfm_url" )
|
||||
artist.setLastFmUrl( QUrl( xml.readElementText() ) );
|
||||
else if( xml.name() == "aolmusic_url" )
|
||||
artist.setAolMusicUrl( QUrl( xml.readElementText() ) );
|
||||
else if( xml.name() == "myspace_url" )
|
||||
artist.setMyspaceUrl( QUrl( xml.readElementText() ) );
|
||||
else if( xml.name() == "amazon_url" )
|
||||
artist.setAmazonUrl( QUrl( xml.readElementText() ) );
|
||||
else if( xml.name() == "itunes_url" )
|
||||
artist.setItunesUrl( QUrl( xml.readElementText() ) );
|
||||
else if( xml.name() == "mb_url" )
|
||||
artist.setMusicbrainzUrl( QUrl( xml.readElementText() ) );
|
||||
|
||||
xml.readNextStartElement();
|
||||
}
|
||||
xml.readNextStartElement();
|
||||
}
|
||||
|
||||
void Echonest::Parser::parseVideos( QXmlStreamReader& xml, Echonest::Artist& artist ) throw( Echonest::ParseError )
|
||||
{
|
||||
if( xml.name() != "video" || xml.tokenType() != QXmlStreamReader::StartElement )
|
||||
throw new Echonest::ParseError( Echonest::UnknownParseError );
|
||||
|
||||
Echonest::VideoList videos;
|
||||
while( xml.name() == "video" && xml.isStartElement() ) {
|
||||
|
||||
Echonest::Video video;
|
||||
|
||||
while( xml.name() != "video" || !xml.isEndElement() ) {
|
||||
if( xml.name() == "title" )
|
||||
video.setTitle( xml.readElementText() );
|
||||
else if( xml.name() == "url" )
|
||||
video.setUrl( QUrl( xml.readElementText() ) );
|
||||
else if( xml.name() == "site" )
|
||||
video.setSite( xml.readElementText() );
|
||||
else if( xml.name() == "date_found" )
|
||||
video.setDateFound( QDateTime::fromString( xml.readElementText(), Qt::ISODate ) );
|
||||
else if( xml.name() == "image_url" )
|
||||
video.setImageUrl( QUrl( xml.readElementText() ) );
|
||||
else if( xml.name() == "id" )
|
||||
video.setId( xml.readElementText().toLatin1() );
|
||||
|
||||
xml.readNextStartElement();
|
||||
}
|
||||
videos.append( video );
|
||||
|
||||
xml.readNextStartElement();
|
||||
}
|
||||
artist.setVideos( videos );
|
||||
}
|
||||
|
||||
Echonest::TermList Echonest::Parser::parseTermList( QXmlStreamReader& xml )
|
||||
{
|
||||
if( xml.name() != "terms" || xml.tokenType() != QXmlStreamReader::StartElement )
|
||||
throw new Echonest::ParseError( Echonest::UnknownParseError );
|
||||
|
||||
Echonest::TermList terms;
|
||||
while( xml.name() == "terms" && xml.isStartElement() ) {
|
||||
|
||||
Echonest::Term term;
|
||||
|
||||
while( xml.name() != "terms" || !xml.isEndElement() ) {
|
||||
if( xml.name() == "frequency" )
|
||||
term.setFrequency( xml.readElementText().toDouble() );
|
||||
else if( xml.name() == "name" )
|
||||
term.setName( xml.readElementText() );
|
||||
else if( xml.name() == "weight" )
|
||||
term.setWeight( xml.readElementText().toDouble() );
|
||||
|
||||
xml.readNextStartElement();
|
||||
}
|
||||
terms.append( term );
|
||||
|
||||
xml.readNextStartElement();
|
||||
}
|
||||
return terms;
|
||||
}
|
||||
|
||||
void Echonest::Parser::parseForeignIds( QXmlStreamReader& xml, Echonest::Artist& artist ) throw( Echonest::ParseError )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
Echonest::License Echonest::Parser::parseLicense( QXmlStreamReader& xml ) throw( Echonest::ParseError )
|
||||
{
|
||||
if( xml.name() != "license" || xml.tokenType() != QXmlStreamReader::StartElement )
|
||||
throw new Echonest::ParseError( Echonest::UnknownParseError );
|
||||
|
||||
Echonest::License license;
|
||||
while( xml.name() != "license" || xml.tokenType() != QXmlStreamReader::EndElement ) {
|
||||
if( xml.name() == "type" )
|
||||
license.type = xml.readElementText();
|
||||
else if( xml.name() == "attribution" )
|
||||
license.attribution = xml.readElementText();
|
||||
else if( xml.name() == "url" )
|
||||
license.url = QUrl( xml.readElementText() );
|
||||
|
||||
xml.readNext();
|
||||
}
|
||||
|
||||
xml.readNextStartElement();
|
||||
return license;
|
||||
}
|
||||
|
||||
QByteArray Echonest::Parser::parsePlaylistSessionId( QXmlStreamReader& xml ) throw( ParseError )
|
||||
{
|
||||
if( xml.name() != "session_id" || xml.tokenType() != QXmlStreamReader::StartElement )
|
||||
throw new Echonest::ParseError( Echonest::UnknownParseError );
|
||||
|
||||
QByteArray sessionId = xml.readElementText().toLatin1();
|
||||
xml.readNext(); //read to next start element
|
||||
return sessionId;
|
||||
}
|
87
3rdparty/libechonest/Parsing_p.h
vendored
Normal file
87
3rdparty/libechonest/Parsing_p.h
vendored
Normal file
@ -0,0 +1,87 @@
|
||||
/****************************************************************************************
|
||||
* 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_PARSING_P_H
|
||||
#define ECHONEST_PARSING_P_H
|
||||
|
||||
#include "Config.h"
|
||||
|
||||
#include <QXmlStreamReader>
|
||||
#include "Song.h"
|
||||
#include "Artist.h"
|
||||
|
||||
class QNetworkReply;
|
||||
|
||||
namespace Echonest
|
||||
{
|
||||
namespace Parser
|
||||
{
|
||||
/**
|
||||
* Internal helper parsing functions for QXmlStreamParser
|
||||
*/
|
||||
|
||||
void checkForErrors( QNetworkReply* reply ) throw( ParseError );
|
||||
|
||||
// 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 <track></track> block
|
||||
Track parseTrack( QXmlStreamReader& xml ) throw( ParseError );
|
||||
|
||||
// parses an <audio_summary> chunk
|
||||
AudioSummary parseAudioSummary( QXmlStreamReader& xml ) throw( ParseError );
|
||||
|
||||
// parses a list of artists in an <artists></artists> block
|
||||
Echonest::Artists parseArtists( QXmlStreamReader& xml );
|
||||
|
||||
// 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 );
|
||||
void parseImages( QXmlStreamReader& xml, Echonest::Artist& artist ) throw( ParseError );
|
||||
void parseNewsOrBlogs( QXmlStreamReader& xml, Echonest::Artist& artist, bool news = true ) throw( ParseError );
|
||||
void parseReviews( QXmlStreamReader& xml, Echonest::Artist& artist ) throw( ParseError );
|
||||
void parseTerms( QXmlStreamReader& xml, Echonest::Artist& artist ) throw( ParseError );
|
||||
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 );
|
||||
|
||||
// parse a list of terms
|
||||
TermList parseTermList( QXmlStreamReader& xml );
|
||||
|
||||
License parseLicense( QXmlStreamReader& xml ) throw( ParseError );
|
||||
|
||||
QByteArray parsePlaylistSessionId( QXmlStreamReader& xml ) throw( ParseError );
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
315
3rdparty/libechonest/Playlist.cpp
vendored
Normal file
315
3rdparty/libechonest/Playlist.cpp
vendored
Normal file
@ -0,0 +1,315 @@
|
||||
/****************************************************************************************
|
||||
* 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 "Playlist.h"
|
||||
#include "Playlist_p.h"
|
||||
#include "Parsing_p.h"
|
||||
|
||||
Echonest::DynamicPlaylist::DynamicPlaylist()
|
||||
: d( new DynamicPlaylistData )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
Echonest::DynamicPlaylist::DynamicPlaylist(const Echonest::DynamicPlaylist& other)
|
||||
: d( other.d )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
Echonest::DynamicPlaylist::~DynamicPlaylist()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
Echonest::DynamicPlaylist& Echonest::DynamicPlaylist::operator=(const Echonest::DynamicPlaylist& playlist)
|
||||
{
|
||||
d = playlist.d;
|
||||
return *this;
|
||||
}
|
||||
|
||||
QNetworkReply* Echonest::DynamicPlaylist::start(const Echonest::DynamicPlaylist::PlaylistParams& params)
|
||||
{
|
||||
// params are the same, if user passes in format parsing will throw, but it should be expected..
|
||||
return generateInternal( params, "dynamic" );
|
||||
}
|
||||
|
||||
Echonest::Song Echonest::DynamicPlaylist::parseStart(QNetworkReply* reply) throw( Echonest::ParseError )
|
||||
{
|
||||
Echonest::Parser::checkForErrors( reply );
|
||||
|
||||
QXmlStreamReader xml( reply->readAll() );
|
||||
|
||||
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 );
|
||||
|
||||
d->currentSong = songs.front();
|
||||
|
||||
return d->currentSong;
|
||||
}
|
||||
|
||||
QByteArray Echonest::DynamicPlaylist::sessionId() const
|
||||
{
|
||||
return d->sessionId;
|
||||
}
|
||||
|
||||
void Echonest::DynamicPlaylist::setSessionId(const QByteArray& id)
|
||||
{
|
||||
d->sessionId = id;
|
||||
}
|
||||
|
||||
Echonest::Song Echonest::DynamicPlaylist::currentSong() const
|
||||
{
|
||||
return d->currentSong;
|
||||
}
|
||||
|
||||
void Echonest::DynamicPlaylist::setCurrentSong(const Echonest::Song& song)
|
||||
{
|
||||
d->currentSong = song;
|
||||
}
|
||||
|
||||
QNetworkReply* Echonest::DynamicPlaylist::fetchNextSong(int rating)
|
||||
{
|
||||
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 ) );
|
||||
|
||||
}
|
||||
|
||||
|
||||
Echonest::Song Echonest::DynamicPlaylist::parseNextSong(QNetworkReply* reply)
|
||||
{
|
||||
return parseStart( reply );
|
||||
}
|
||||
|
||||
QNetworkReply* Echonest::DynamicPlaylist::staticPlaylist(const Echonest::DynamicPlaylist::PlaylistParams& params)
|
||||
{
|
||||
return Echonest::DynamicPlaylist::generateInternal( params, "static" );
|
||||
}
|
||||
|
||||
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 );
|
||||
return songs;
|
||||
}
|
||||
|
||||
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() ) )
|
||||
{
|
||||
case ArtistType:
|
||||
url.addEncodedQueryItem( playlistParamToString( iter->first ), "artist" );
|
||||
break;
|
||||
case ArtistRadioType:
|
||||
url.addEncodedQueryItem( playlistParamToString( iter->first ), "artist-radio" );
|
||||
break;
|
||||
case ArtistDescriptionType:
|
||||
url.addEncodedQueryItem( playlistParamToString( iter->first ), "artist-description" );
|
||||
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 >() ) );
|
||||
} 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 ) );
|
||||
}
|
||||
|
||||
|
||||
QByteArray Echonest::DynamicPlaylist::playlistParamToString(Echonest::DynamicPlaylist::PlaylistParam param)
|
||||
{
|
||||
switch( param )
|
||||
{
|
||||
case Echonest::DynamicPlaylist::Type :
|
||||
return "type";
|
||||
case Echonest::DynamicPlaylist::Format :
|
||||
return "format";
|
||||
case Echonest::DynamicPlaylist::Pick:
|
||||
return "artist_pick";
|
||||
case Echonest::DynamicPlaylist::Variety :
|
||||
return "variety";
|
||||
case Echonest::DynamicPlaylist::ArtistId :
|
||||
return "artist_id";
|
||||
case Echonest::DynamicPlaylist::Artist :
|
||||
return "artist";
|
||||
case Echonest::DynamicPlaylist::SongId :
|
||||
return "song_id";
|
||||
case Echonest::DynamicPlaylist::Description :
|
||||
return "description";
|
||||
case Echonest::DynamicPlaylist::Results :
|
||||
return "results";
|
||||
case Echonest::DynamicPlaylist::MaxTempo :
|
||||
return "max_tempo";
|
||||
case Echonest::DynamicPlaylist::MinTempo :
|
||||
return "min_tempo";
|
||||
case Echonest::DynamicPlaylist::MaxDuration :
|
||||
return "max_duration";
|
||||
case Echonest::DynamicPlaylist::MinDuration :
|
||||
return "min_duration";
|
||||
case Echonest::DynamicPlaylist::MaxLoudness :
|
||||
return "max_loudness";
|
||||
case Echonest::DynamicPlaylist::MinLoudness :
|
||||
return "min_loudness";
|
||||
case Echonest::DynamicPlaylist::ArtistMaxFamiliarity :
|
||||
return "artist_max_familiarity";
|
||||
case Echonest::DynamicPlaylist::ArtistMinFamiliarity :
|
||||
return "artist_min_familiarity";
|
||||
case Echonest::DynamicPlaylist::ArtistMaxHotttnesss :
|
||||
return "artist_max_hotttnesss";
|
||||
case Echonest::DynamicPlaylist::ArtistMinHotttnesss :
|
||||
return "artist_min_hotttnesss";
|
||||
case Echonest::DynamicPlaylist::SongMaxHotttnesss :
|
||||
return "song_max_hotttnesss";
|
||||
case Echonest::DynamicPlaylist::SongMinHotttnesss :
|
||||
return "song_min_hotttnesss";
|
||||
case Echonest::DynamicPlaylist::ArtistMinLongitude :
|
||||
return "artist_min_longitude";
|
||||
case Echonest::DynamicPlaylist::ArtistMaxLongitude :
|
||||
return "artist_max_longitude";
|
||||
case Echonest::DynamicPlaylist::ArtistMinLatitude :
|
||||
return "artist_min_latitude";
|
||||
case Echonest::DynamicPlaylist::ArtistMaxLatitude :
|
||||
return "artist_max_latitude";
|
||||
case Echonest::DynamicPlaylist::Mode :
|
||||
return "mode";
|
||||
case Echonest::DynamicPlaylist::Key :
|
||||
return "key";
|
||||
case Echonest::DynamicPlaylist::SongInformation:
|
||||
return "bucket";
|
||||
case Echonest::DynamicPlaylist::Sort :
|
||||
return "sort";
|
||||
case Echonest::DynamicPlaylist::Limit :
|
||||
return "limit";
|
||||
case Echonest::DynamicPlaylist::Audio :
|
||||
return "audio";
|
||||
case Echonest::DynamicPlaylist::DMCA :
|
||||
return "dmca";
|
||||
}
|
||||
return QByteArray();
|
||||
}
|
||||
|
||||
QByteArray Echonest::DynamicPlaylist::playlistArtistPickToString(Echonest::DynamicPlaylist::ArtistPick pick)
|
||||
{
|
||||
switch( pick )
|
||||
{
|
||||
case PickSongHotttnesssAscending:
|
||||
return "song_hotttnesss-asc";
|
||||
case PickTempoAscending:
|
||||
return "tempo-asc";
|
||||
case PickDurationAscending:
|
||||
return "duration-asc";
|
||||
case PickLoudnessAscending:
|
||||
return "loudness-asc";
|
||||
case PickModeAscending:
|
||||
return "mode-asc";
|
||||
case PickKeyAscending:
|
||||
return "key-asc";
|
||||
case PickSongHotttnesssDescending:
|
||||
return "song_hotttnesss-desc";
|
||||
case PickTempoDescending:
|
||||
return "tempo-desc";
|
||||
case PickDurationDescending:
|
||||
return "duration-desc";
|
||||
case PickLoudnessDescending:
|
||||
return "loudness-desc";
|
||||
case PickModeDescending:
|
||||
return "mode-desc";
|
||||
case PickKeyDescending:
|
||||
return "key-desc";
|
||||
}
|
||||
return QByteArray();
|
||||
}
|
||||
|
||||
QByteArray Echonest::DynamicPlaylist::playlistSortToString(Echonest::DynamicPlaylist::SortingType sorting)
|
||||
{
|
||||
switch( sorting )
|
||||
{
|
||||
case SortTempoAscending:
|
||||
return "tempo-asc";
|
||||
case SortTempoDescending:
|
||||
return "tempo-desc";
|
||||
case SortDurationAscending:
|
||||
return "duration-asc";
|
||||
case SortDurationDescending:
|
||||
return "duration-desc";
|
||||
case SortArtistFamiliarityAscending:
|
||||
return "artist_familiarity-asc";
|
||||
case SortArtistFamiliarityDescending:
|
||||
return "artist_familiarity-desc";
|
||||
case SortArtistHotttnessAscending:
|
||||
return "artist_hotttnesss-asc";
|
||||
case SortArtistHotttnessDescending:
|
||||
return "artist_hotttnesss-desc";
|
||||
case SortSongHotttnesssAscending:
|
||||
return "song_hotttnesss-asc";
|
||||
case SortSongHotttnesssDescending:
|
||||
return "song_hotttnesss-desc";
|
||||
case SortLatitudeAscending:
|
||||
return "latitude-asc";
|
||||
case SortLatitudeDescending:
|
||||
return "latitude-desc";
|
||||
case SortLongitudeAscending:
|
||||
return "longitude-asc";
|
||||
case SortLongitudeDescending:
|
||||
return "longitude-desc";
|
||||
case SortModeAscending:
|
||||
return "mode-asc";
|
||||
case SortModeDescending:
|
||||
return "mode-desc";
|
||||
case SortKeyAscending:
|
||||
return "key-asc";
|
||||
case SortKeyDescending:
|
||||
return "key-desc";
|
||||
}
|
||||
return QByteArray();
|
||||
}
|
||||
|
||||
|
||||
QDebug Echonest::operator<<(QDebug d, const Echonest::DynamicPlaylist& playlist)
|
||||
{
|
||||
d << QString::fromLatin1( "DynamicPlaylist(%1, %2)" ).arg( QLatin1String( playlist.sessionId() ), playlist.currentSong().toString() );
|
||||
return d.maybeSpace();
|
||||
}
|
200
3rdparty/libechonest/Playlist.h
vendored
Normal file
200
3rdparty/libechonest/Playlist.h
vendored
Normal file
@ -0,0 +1,200 @@
|
||||
/****************************************************************************************
|
||||
* 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_PLAYLIST_H
|
||||
#define ECHONEST_PLAYLIST_H
|
||||
|
||||
#include "echonest_export.h"
|
||||
#include "Song.h"
|
||||
|
||||
#include <QSharedData>
|
||||
#include <QDebug>
|
||||
|
||||
class QNetworkReply;
|
||||
class DynamicPlaylistData;
|
||||
|
||||
namespace Echonest{
|
||||
|
||||
/**
|
||||
* This encapsulates an Echo Nest dynamic playlist. It contains a playlist ID and
|
||||
* the current song, and can fetch the next song.
|
||||
*
|
||||
* See http://developer.echonest.com/docs/v4/playlist.html#dynamic
|
||||
* for more information
|
||||
*/
|
||||
class ECHONEST_EXPORT DynamicPlaylist
|
||||
{
|
||||
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
|
||||
* the given description.
|
||||
*/
|
||||
enum ArtistTypeEnum {
|
||||
ArtistType,
|
||||
ArtistRadioType,
|
||||
ArtistDescriptionType
|
||||
};
|
||||
|
||||
/**
|
||||
* Different ways to sort a generated playlist
|
||||
*/
|
||||
enum SortingType {
|
||||
SortTempoAscending,
|
||||
SortTempoDescending,
|
||||
SortDurationAscending,
|
||||
SortDurationDescending,
|
||||
SortArtistFamiliarityAscending,
|
||||
SortArtistFamiliarityDescending,
|
||||
SortArtistHotttnessAscending,
|
||||
SortArtistHotttnessDescending,
|
||||
SortSongHotttnesssAscending,
|
||||
SortSongHotttnesssDescending,
|
||||
SortLatitudeAscending,
|
||||
SortLatitudeDescending,
|
||||
SortLongitudeAscending,
|
||||
SortLongitudeDescending,
|
||||
SortModeAscending,
|
||||
SortModeDescending,
|
||||
SortKeyAscending,
|
||||
SortKeyDescending
|
||||
};
|
||||
|
||||
/**
|
||||
* Different ways of picking artists in Artist radios.
|
||||
*/
|
||||
enum ArtistPick {
|
||||
PickSongHotttnesssAscending,
|
||||
PickTempoAscending,
|
||||
PickDurationAscending,
|
||||
PickLoudnessAscending,
|
||||
PickModeAscending,
|
||||
PickKeyAscending,
|
||||
PickSongHotttnesssDescending,
|
||||
PickTempoDescending,
|
||||
PickDurationDescending,
|
||||
PickLoudnessDescending,
|
||||
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.
|
||||
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
|
||||
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
|
||||
MaxTempo, /// 0.0 < tempo < 500.0 (BPM) The maximum tempo for any included songs
|
||||
MinTempo, /// 0.0 < tempo < 500.0 (BPM) the minimum tempo for any included songs
|
||||
MaxDuration, /// 0.0 < duration < 3600.0 (seconds) the maximum duration of any song on the playlist
|
||||
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
|
||||
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
|
||||
ArtistMinHotttnesss, /// 0.0 < hotttnesss < 1.0 the maximum hotttnesss for artists in the playlist
|
||||
SongMaxHotttnesss, /// 0.0 < hotttnesss < 1.0 the maximum hotttnesss for songs in the playlist
|
||||
SongMinHotttnesss, /// 0.0 < hotttnesss < 1.0 the maximum hotttnesss for songs in the playlist
|
||||
ArtistMinLongitude, /// -180.0 < longitude < 180.0 the minimum longitude for the location of artists in the playlist
|
||||
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
|
||||
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,
|
||||
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)
|
||||
};
|
||||
|
||||
typedef QPair< PlaylistParam, QVariant > PlaylistParamData;
|
||||
typedef QVector< PlaylistParamData > PlaylistParams;
|
||||
|
||||
DynamicPlaylist();
|
||||
~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(),
|
||||
* and fetchNextSong() methods will then be useful.
|
||||
*/
|
||||
QNetworkReply* start( const PlaylistParams& params );
|
||||
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.
|
||||
*
|
||||
* @param rating The rating for the song that was just played. Ranges from 1 (lowest) to 5 (highest)
|
||||
*
|
||||
*/
|
||||
QNetworkReply* fetchNextSong( int rating = -1);
|
||||
Song parseNextSong( QNetworkReply* reply );
|
||||
|
||||
/**
|
||||
* Generate a static playlist, according to the desired criteria.
|
||||
*/
|
||||
static QNetworkReply* staticPlaylist( const PlaylistParams& params );
|
||||
static SongList parseStaticPlaylist( 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);
|
||||
|
||||
QSharedDataPointer<DynamicPlaylistData> d;
|
||||
};
|
||||
|
||||
ECHONEST_EXPORT QDebug operator<<(QDebug d, const Echonest::DynamicPlaylist& playlist);
|
||||
|
||||
|
||||
} // namespace
|
||||
#endif
|
34
3rdparty/libechonest/Playlist_p.h
vendored
Normal file
34
3rdparty/libechonest/Playlist_p.h
vendored
Normal file
@ -0,0 +1,34 @@
|
||||
/****************************************************************************************
|
||||
* 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 "Song.h"
|
||||
#include <QSharedData>
|
||||
#include <QString>
|
||||
|
||||
class DynamicPlaylistData : public QSharedData
|
||||
{
|
||||
public:
|
||||
DynamicPlaylistData() {}
|
||||
DynamicPlaylistData(const DynamicPlaylistData& other)
|
||||
{
|
||||
sessionId = other.sessionId;
|
||||
currentSong = other.currentSong;
|
||||
}
|
||||
|
||||
QByteArray sessionId;
|
||||
Echonest::Song currentSong;
|
||||
};
|
||||
|
311
3rdparty/libechonest/Song.cpp
vendored
Normal file
311
3rdparty/libechonest/Song.cpp
vendored
Normal file
@ -0,0 +1,311 @@
|
||||
/****************************************************************************************
|
||||
* 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 "Song.h"
|
||||
|
||||
#include "Config.h"
|
||||
#include "Song_p.h"
|
||||
#include "AudioSummary.h"
|
||||
|
||||
#include <QNetworkReply>
|
||||
#include <QDebug>
|
||||
|
||||
#include <QtNetwork/QNetworkReply>
|
||||
#include "Parsing_p.h"
|
||||
#include <qxmlstream.h>
|
||||
|
||||
Echonest::Song::Song()
|
||||
: d( new SongData )
|
||||
{}
|
||||
|
||||
Echonest::Song::Song(const QByteArray& id, const QString& title, const QByteArray& artistId, const QString& artistName)
|
||||
:d( new SongData )
|
||||
{
|
||||
d->id = id;
|
||||
d->title = title;
|
||||
d->artistId = artistId;
|
||||
d->artistName = artistName;
|
||||
}
|
||||
|
||||
Echonest::Song::Song(const Echonest::Song& other)
|
||||
: d( other.d )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
Echonest::Song::~Song()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
Echonest::Song& Echonest::Song::operator=(const Echonest::Song& song)
|
||||
{
|
||||
d = song.d;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
|
||||
QByteArray Echonest::Song::id() const
|
||||
{
|
||||
return d->id;
|
||||
}
|
||||
|
||||
void Echonest::Song::setId(const QByteArray& id)
|
||||
{
|
||||
d->id = id;
|
||||
}
|
||||
|
||||
|
||||
QString Echonest::Song::title() const
|
||||
{
|
||||
return d->title;
|
||||
}
|
||||
|
||||
void Echonest::Song::setTitle(const QString& title)
|
||||
{
|
||||
d->title = title;
|
||||
}
|
||||
|
||||
QByteArray Echonest::Song::artistId() const
|
||||
{
|
||||
return d->artistId;
|
||||
}
|
||||
|
||||
void Echonest::Song::setArtistId(const QByteArray& artistId)
|
||||
{
|
||||
d->artistId = artistId;
|
||||
}
|
||||
|
||||
QString Echonest::Song::artistName() const
|
||||
{
|
||||
return d->artistName;
|
||||
}
|
||||
|
||||
void Echonest::Song::setArtistName(const QString& artistName)
|
||||
{
|
||||
d->artistName = artistName;
|
||||
}
|
||||
|
||||
QVector< Echonest::Track > Echonest::Song::tracks() const
|
||||
{
|
||||
return d->tracks;
|
||||
}
|
||||
|
||||
void Echonest::Song::setTracks(const QVector< Echonest::Track >& tracks)
|
||||
{
|
||||
d->tracks = tracks;
|
||||
}
|
||||
|
||||
qreal Echonest::Song::hotttnesss() const
|
||||
{
|
||||
return d->hotttnesss;
|
||||
}
|
||||
|
||||
void Echonest::Song::setHotttnesss(qreal hotttnesss)
|
||||
{
|
||||
d->hotttnesss = hotttnesss;
|
||||
}
|
||||
|
||||
qreal Echonest::Song::artistHotttnesss() const
|
||||
{
|
||||
return d->artistHotttnesss;
|
||||
}
|
||||
|
||||
void Echonest::Song::setArtistHotttnesss(qreal artistHotttnesss)
|
||||
{
|
||||
d->artistHotttnesss = artistHotttnesss;
|
||||
}
|
||||
|
||||
Echonest::AudioSummary Echonest::Song::audioSummary() const
|
||||
{
|
||||
return d->audioSummary;
|
||||
}
|
||||
|
||||
void Echonest::Song::setAudioSummary(const Echonest::AudioSummary& summary)
|
||||
{
|
||||
d->audioSummary = summary;
|
||||
}
|
||||
|
||||
qreal Echonest::Song::artistFamiliarity() const
|
||||
{
|
||||
return d->artistFamiliarity;
|
||||
}
|
||||
|
||||
void Echonest::Song::setArtistFamiliarity(qreal artistFamiliarity)
|
||||
{
|
||||
d->artistFamiliarity = artistFamiliarity;
|
||||
}
|
||||
|
||||
QString Echonest::Song::artistLocation() const
|
||||
{
|
||||
return d->artistLocation;
|
||||
}
|
||||
|
||||
void Echonest::Song::setArtistLocation(const QString& artistLocation)
|
||||
{
|
||||
d->artistLocation = artistLocation;
|
||||
}
|
||||
|
||||
QNetworkReply* Echonest::Song::fetchInformation( Echonest::Song::SongInformation parts ) const
|
||||
{
|
||||
QUrl url = Echonest::baseGetQuery( "song", "profile" );
|
||||
url.addEncodedQueryItem( "id", d->id );
|
||||
addQueryInformation( url, parts );
|
||||
|
||||
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 )
|
||||
{
|
||||
QUrl url = Echonest::baseGetQuery( "song", "search" );
|
||||
addQueryInformation( url, parts );
|
||||
|
||||
SearchParams::const_iterator iter = params.constBegin();
|
||||
for( ; iter < params.constEnd(); ++iter )
|
||||
url.addQueryItem( QLatin1String( searchParamToString( iter->first ) ), iter->second.toString() );
|
||||
|
||||
qDebug() << "Creating search URL" << url;
|
||||
return Echonest::Config::instance()->nam()->get( QNetworkRequest( url ) );
|
||||
}
|
||||
|
||||
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 );
|
||||
if( !songs.size() == 1 ) { // no data for this song. returned empty.
|
||||
return;
|
||||
}
|
||||
// copy any non-default values
|
||||
Echonest::Song newSong = songs.at( 0 );
|
||||
if( newSong.hotttnesss() >= 0 )
|
||||
setHotttnesss( newSong.hotttnesss() );
|
||||
if( newSong.artistHotttnesss() >= 0 )
|
||||
setArtistHotttnesss( newSong.artistHotttnesss() );
|
||||
if( newSong.artistFamiliarity() >= 0 )
|
||||
setArtistFamiliarity( newSong.artistFamiliarity() );
|
||||
if( !newSong.artistLocation().isEmpty() )
|
||||
setArtistLocation( newSong.artistLocation() );
|
||||
|
||||
}
|
||||
|
||||
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 );
|
||||
|
||||
return songs;
|
||||
|
||||
}
|
||||
|
||||
QByteArray Echonest::Song::searchParamToString( Echonest::Song::SearchParam param )
|
||||
{
|
||||
switch( param )
|
||||
{
|
||||
case Echonest::Song::Title:
|
||||
return "title";
|
||||
case Echonest::Song::Artist:
|
||||
return "artist";
|
||||
case Echonest::Song::Combined:
|
||||
return "combined";
|
||||
case Echonest::Song::Description:
|
||||
return "description";
|
||||
case Echonest::Song::ArtistId:
|
||||
return "artist_id";
|
||||
case Echonest::Song::Results:
|
||||
return "results";
|
||||
case Echonest::Song::MaxTempo:
|
||||
return "max_tempo";
|
||||
case Echonest::Song::MinTempo:
|
||||
return "min_tempo";
|
||||
case Echonest::Song::MaxDanceability:
|
||||
return "max_danceability";
|
||||
case Echonest::Song::MinDanceability:
|
||||
return "min_danceability";
|
||||
case Echonest::Song::MaxComplexity:
|
||||
return "max_complexity";
|
||||
case Echonest::Song::MinComplexity:
|
||||
return "min_complexity";
|
||||
case Echonest::Song::MaxDuration:
|
||||
return "max_duration";
|
||||
case Echonest::Song::MinDuration:
|
||||
return "min_duration";
|
||||
case Echonest::Song::MaxLoudness:
|
||||
return "max_loudness";
|
||||
case Echonest::Song::MinLoudness:
|
||||
return "min_loudness";
|
||||
case Echonest::Song::MaxFamiliarity:
|
||||
return "max_familiarity";
|
||||
case Echonest::Song::MinFamiliarity:
|
||||
return "min_familiarity";
|
||||
case Echonest::Song::MaxHotttnesss:
|
||||
return "max_hotttnesss";
|
||||
case Echonest::Song::MinHotttnesss:
|
||||
return "min_hotttnesss";
|
||||
case Echonest::Song::MaxLongitude:
|
||||
return "max_longitude";
|
||||
case Echonest::Song::MinLongitude:
|
||||
return "min_longitude";
|
||||
case Echonest::Song::Mode:
|
||||
return "mode";
|
||||
case Echonest::Song::Key:
|
||||
return "key";
|
||||
case Echonest::Song::Sort:
|
||||
return "sort";
|
||||
}
|
||||
return QByteArray();
|
||||
}
|
||||
|
||||
void Echonest::Song::addQueryInformation(QUrl& url, Echonest::Song::SongInformation parts)
|
||||
{
|
||||
if( parts.testFlag( Echonest::Song::AudioSummaryInformation ) )
|
||||
url.addEncodedQueryItem( "bucket", "audio_summary" );
|
||||
if( parts.testFlag( Echonest::Song::Tracks ) )
|
||||
url.addEncodedQueryItem( "bucket", "tracks" );
|
||||
if( parts.testFlag( Echonest::Song::Hotttnesss ) )
|
||||
url.addEncodedQueryItem( "bucket", "song_hotttnesss" );
|
||||
if( parts.testFlag( Echonest::Song::ArtistHotttnesss ) )
|
||||
url.addEncodedQueryItem( "bucket", "artist_hotttnesss" );
|
||||
if( parts.testFlag( Echonest::Song::ArtistFamiliarity ) )
|
||||
url.addEncodedQueryItem( "bucket", "artist_familiarity" );
|
||||
if( parts.testFlag( Echonest::Song::ArtistLocation ) )
|
||||
url.addEncodedQueryItem( "bucket", "artist_location" );
|
||||
}
|
||||
|
||||
|
||||
QString Echonest::Song::toString() const
|
||||
{
|
||||
return QString::fromLatin1( "Song(%1, %2, %3, %4)" ).arg( title() ).arg( artistName() ).arg( QString::fromLatin1( id() ) ).arg( QString::fromLatin1( artistId() ) );
|
||||
}
|
||||
|
||||
|
||||
QDebug Echonest::operator<<(QDebug d, const Echonest::Song& song)
|
||||
{
|
||||
d << song.toString();
|
||||
return d.maybeSpace();
|
||||
}
|
||||
|
217
3rdparty/libechonest/Song.h
vendored
Normal file
217
3rdparty/libechonest/Song.h
vendored
Normal file
@ -0,0 +1,217 @@
|
||||
/****************************************************************************************
|
||||
* 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_SONG_H
|
||||
#define ECHONEST_SONG_H
|
||||
|
||||
#include "echonest_export.h"
|
||||
#include "Track.h"
|
||||
|
||||
#include <QSharedData>
|
||||
#include <QHash>
|
||||
#include <QVariant>
|
||||
#include <QDebug>
|
||||
#include <QVector>
|
||||
#include "Config.h"
|
||||
|
||||
class QNetworkReply;
|
||||
class SongData;
|
||||
namespace Echonest{
|
||||
|
||||
class DynamicPlaylist; // forward declare for friend declaration
|
||||
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,
|
||||
Artist,
|
||||
Combined,
|
||||
Description,
|
||||
ArtistId,
|
||||
Results,
|
||||
MaxTempo,
|
||||
MinTempo,
|
||||
MaxDanceability,
|
||||
MinDanceability,
|
||||
MaxComplexity,
|
||||
MinComplexity,
|
||||
MaxDuration,
|
||||
MinDuration,
|
||||
MaxLoudness,
|
||||
MinLoudness,
|
||||
MaxFamiliarity,
|
||||
MinFamiliarity,
|
||||
MaxHotttnesss,
|
||||
MinHotttnesss,
|
||||
MaxLongitude,
|
||||
MinLongitude,
|
||||
Mode,
|
||||
Key,
|
||||
Sort
|
||||
};
|
||||
typedef QPair< Echonest::Song::SearchParam, QVariant > SearchParamData;
|
||||
typedef QVector< SearchParamData > SearchParams;
|
||||
|
||||
Song();
|
||||
Song( const QByteArray& id, const QString& title, const QByteArray& artistId, const QString& artistName );
|
||||
Song( const Song& other );
|
||||
Song& operator=(const Song& song);
|
||||
~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 );
|
||||
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
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 );
|
||||
|
||||
/**
|
||||
* This fetch 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;
|
||||
|
||||
/**
|
||||
* 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 );
|
||||
|
||||
/**
|
||||
* 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;
|
||||
private:
|
||||
static QByteArray searchParamToString( SearchParam param );
|
||||
static void addQueryInformation( QUrl& url, SongInformation parts );
|
||||
|
||||
QSharedDataPointer<SongData> d;
|
||||
};
|
||||
|
||||
typedef QVector< Song > SongList;
|
||||
|
||||
ECHONEST_EXPORT QDebug operator<<(QDebug d, const Song &song);
|
||||
|
||||
Q_DECLARE_OPERATORS_FOR_FLAGS(Song::SongInformation)
|
||||
|
||||
} // namespace
|
||||
|
||||
Q_DECLARE_METATYPE( Echonest::Song::SongInformation )
|
||||
|
||||
#endif
|
66
3rdparty/libechonest/Song_p.h
vendored
Normal file
66
3rdparty/libechonest/Song_p.h
vendored
Normal file
@ -0,0 +1,66 @@
|
||||
/****************************************************************************************
|
||||
* 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_SONG_P_H
|
||||
#define ECHONEST_SONG_P_H
|
||||
|
||||
#include "Track.h"
|
||||
#include "AudioSummary.h"
|
||||
|
||||
#include <QSharedData>
|
||||
#include <QString>
|
||||
#include <QVector>
|
||||
|
||||
|
||||
class SongData : public QSharedData
|
||||
{
|
||||
public:
|
||||
SongData() : hotttnesss( -1 ), artistHotttnesss( -1 ), artistFamiliarity( -1 ) {}
|
||||
|
||||
SongData(const SongData& other)
|
||||
{
|
||||
id = other.id;
|
||||
title = other.title;
|
||||
artistName = other.artistName;
|
||||
artistId = other.artistId;
|
||||
|
||||
audioSummary = other.audioSummary;
|
||||
tracks = other.tracks;
|
||||
hotttnesss = other.hotttnesss;
|
||||
artistHotttnesss = other.artistHotttnesss;
|
||||
artistFamiliarity = other.artistFamiliarity;
|
||||
artistLocation = other.artistLocation;
|
||||
}
|
||||
|
||||
~SongData() {}
|
||||
|
||||
QByteArray id;
|
||||
QString title;
|
||||
QString artistName;
|
||||
QByteArray artistId;
|
||||
|
||||
// The rest are optional that require manual fetching to populate
|
||||
Echonest::AudioSummary audioSummary;
|
||||
QVector<Echonest::Track> tracks;
|
||||
qreal hotttnesss;
|
||||
qreal artistHotttnesss;
|
||||
qreal artistFamiliarity;
|
||||
QString artistLocation;
|
||||
|
||||
|
||||
};
|
||||
|
||||
#endif
|
247
3rdparty/libechonest/Track.cpp
vendored
Normal file
247
3rdparty/libechonest/Track.cpp
vendored
Normal file
@ -0,0 +1,247 @@
|
||||
/****************************************************************************************
|
||||
* 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 "Track.h"
|
||||
|
||||
#include "Track_p.h"
|
||||
#include <QNetworkReply>
|
||||
#include "Config.h"
|
||||
#include <qfileinfo.h>
|
||||
#include "Parsing_p.h"
|
||||
|
||||
Echonest::Track::Track()
|
||||
: d( new TrackData )
|
||||
{
|
||||
}
|
||||
|
||||
Echonest::Track::Track(const Echonest::Track& other)
|
||||
: d( other.d )
|
||||
{}
|
||||
|
||||
Echonest::Track::~Track()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
Echonest::Track& Echonest::Track::operator=(const Echonest::Track& track)
|
||||
{
|
||||
d = track.d;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
QString Echonest::Track::artist() const
|
||||
{
|
||||
return d->artist;
|
||||
}
|
||||
|
||||
void Echonest::Track::setArtist(const QString& artist)
|
||||
{
|
||||
d->artist = artist;
|
||||
}
|
||||
|
||||
|
||||
QString Echonest::Track::title() const
|
||||
{
|
||||
return d->title;
|
||||
}
|
||||
|
||||
void Echonest::Track::setTitle(const QString& title)
|
||||
{
|
||||
d->title = title;
|
||||
}
|
||||
|
||||
QByteArray Echonest::Track::id() const
|
||||
{
|
||||
return d->id;
|
||||
}
|
||||
|
||||
void Echonest::Track::setId(const QByteArray& id)
|
||||
{
|
||||
d->id = id;
|
||||
}
|
||||
|
||||
QByteArray Echonest::Track::md5() const
|
||||
{
|
||||
return d->md5;
|
||||
}
|
||||
|
||||
void Echonest::Track::setMD5(const QByteArray& md5)
|
||||
{
|
||||
d->md5 = md5;
|
||||
}
|
||||
|
||||
|
||||
QString Echonest::Track::release() const
|
||||
{
|
||||
return d->release;
|
||||
}
|
||||
|
||||
void Echonest::Track::setRelease(const QString& release)
|
||||
{
|
||||
d->release = release;
|
||||
}
|
||||
|
||||
QString Echonest::Track::analyzerVersion() const
|
||||
{
|
||||
return d->analyzer_version;
|
||||
}
|
||||
|
||||
void Echonest::Track::setAnalyzerVersion(const QString& analyzerVersion)
|
||||
{
|
||||
d->analyzer_version = analyzerVersion;
|
||||
}
|
||||
|
||||
int Echonest::Track::bitrate() const
|
||||
{
|
||||
return d->bitrate;
|
||||
}
|
||||
|
||||
void Echonest::Track::setBitrate(int bitrate)
|
||||
{
|
||||
d->bitrate = bitrate;
|
||||
}
|
||||
|
||||
int Echonest::Track::samplerate() const
|
||||
{
|
||||
return d->samplerate;
|
||||
}
|
||||
|
||||
void Echonest::Track::setSamplerate(int samplerate)
|
||||
{
|
||||
d->samplerate = samplerate;
|
||||
}
|
||||
|
||||
QByteArray Echonest::Track::audioMD5() const
|
||||
{
|
||||
return d->audio_md5;
|
||||
}
|
||||
|
||||
void Echonest::Track::setAudioMD5(const QByteArray& md5)
|
||||
{
|
||||
d->audio_md5 = md5;
|
||||
}
|
||||
|
||||
Echonest::Analysis::AnalysisStatus Echonest::Track::status() const
|
||||
{
|
||||
return Echonest::statusToEnum( d->status );
|
||||
}
|
||||
|
||||
void Echonest::Track::setStatus( Echonest::Analysis::AnalysisStatus status )
|
||||
{
|
||||
d->status = Echonest::statusToString( status );
|
||||
}
|
||||
|
||||
Echonest::AudioSummary Echonest::Track::audioSummary() const
|
||||
{
|
||||
return d->audio_summary;
|
||||
}
|
||||
|
||||
void Echonest::Track::setAudioSummary( const Echonest::AudioSummary& summary )
|
||||
{
|
||||
d->audio_summary = summary;
|
||||
}
|
||||
|
||||
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 ) );
|
||||
}
|
||||
|
||||
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 ) );
|
||||
}
|
||||
|
||||
QNetworkReply* Echonest::Track::uploadLocalFile( const QUrl& localFile, const QByteArray& data, bool waitForResult )
|
||||
{
|
||||
QUrl url = Echonest::baseGetQuery( "track", "upload" );
|
||||
QFileInfo info( localFile.path() );
|
||||
url.addQueryItem( QLatin1String( "filetype" ), info.suffix() );
|
||||
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 );
|
||||
}
|
||||
|
||||
QNetworkReply* Echonest::Track::uploadURL( const QUrl& remoteURL, bool waitForResult )
|
||||
{
|
||||
QUrl url = Echonest::baseGetQuery( "track", "upload" );
|
||||
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() );
|
||||
}
|
||||
|
||||
QNetworkReply* Echonest::Track::analyzeTrackId( const QByteArray& id, bool wait )
|
||||
{
|
||||
QUrl url = Echonest::baseGetQuery( "track", "analyze" );
|
||||
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() );
|
||||
}
|
||||
|
||||
QNetworkReply* Echonest::Track::analyzeTrackMD5( const QByteArray& md5, bool wait )
|
||||
{
|
||||
QUrl url = Echonest::baseGetQuery( "track", "analyze" );
|
||||
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() );
|
||||
}
|
||||
|
||||
Echonest::Track Echonest::Track::parseProfile( QNetworkReply* finishedReply ) throw( Echonest::ParseError )
|
||||
{
|
||||
Echonest::Parser::checkForErrors( finishedReply );
|
||||
|
||||
QByteArray data = finishedReply->readAll();
|
||||
qDebug() << data;
|
||||
QXmlStreamReader xml( data );
|
||||
|
||||
Echonest::Parser::readStatus( xml );
|
||||
Echonest::Track track = Echonest::Parser::parseTrack( xml );
|
||||
|
||||
return track;
|
||||
}
|
||||
|
||||
|
||||
|
||||
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() );
|
||||
return d.maybeSpace();
|
||||
}
|
||||
|
185
3rdparty/libechonest/Track.h
vendored
Normal file
185
3rdparty/libechonest/Track.h
vendored
Normal file
@ -0,0 +1,185 @@
|
||||
/****************************************************************************************
|
||||
* 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_TRACK_H
|
||||
#define ECHONEST_TRACK_H
|
||||
|
||||
#include "AudioSummary.h"
|
||||
#include "echonest_export.h"
|
||||
#include "Util.h"
|
||||
|
||||
#include <QObject>
|
||||
#include <QString>
|
||||
#include <QDebug>
|
||||
#include <QSharedData>
|
||||
#include <QUrl>
|
||||
#include "Config.h"
|
||||
|
||||
class QNetworkReply;
|
||||
class TrackData;
|
||||
|
||||
namespace Echonest
|
||||
{
|
||||
|
||||
/**
|
||||
* 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
|
||||
* class. You can also fetch acoustic information from a track if you have the Track ID or MD5 of the file.
|
||||
*
|
||||
* A Track encapsulates the audio analysis from The Echo Nest.
|
||||
*
|
||||
* This class is implicitly shared.
|
||||
*
|
||||
*/
|
||||
class ECHONEST_EXPORT Track
|
||||
{
|
||||
public:
|
||||
|
||||
Track();
|
||||
Track( const Track& other );
|
||||
Track& operator=( const Track& track );
|
||||
~Track();
|
||||
|
||||
/**
|
||||
* The track's artist.
|
||||
*/
|
||||
QString artist() const;
|
||||
void setArtist( const QString& artist );
|
||||
|
||||
/**
|
||||
* The track's title.
|
||||
*/
|
||||
QString title() const;
|
||||
void setTitle( const QString& title );
|
||||
|
||||
/**
|
||||
* The Echo Nest artist ID for this track.
|
||||
*/
|
||||
QByteArray id() const;
|
||||
void setId( const QByteArray& id );
|
||||
|
||||
/**
|
||||
* The MD5 hash of the track.
|
||||
*/
|
||||
QByteArray md5() const;
|
||||
void setMD5( const QByteArray& md5 );
|
||||
|
||||
/**
|
||||
* The album name of this track.
|
||||
*/
|
||||
QString release() const;
|
||||
void setRelease( const QString& release );
|
||||
|
||||
/**
|
||||
* The MD5 hashsum of the audio data.
|
||||
*/
|
||||
QByteArray audioMD5() const;
|
||||
void setAudioMD5( const QByteArray& md5 );
|
||||
|
||||
/**
|
||||
* The analyzer version that was used in this track's analysis.
|
||||
*/
|
||||
QString analyzerVersion() const;
|
||||
void setAnalyzerVersion( const QString& analyzerVersion );
|
||||
|
||||
/**
|
||||
* The samplerate of the track
|
||||
*/
|
||||
int samplerate() const;
|
||||
void setSamplerate( int samplerate );
|
||||
|
||||
/**
|
||||
* The bitrate of the track
|
||||
*/
|
||||
int bitrate() const;
|
||||
void setBitrate( int );
|
||||
|
||||
/**
|
||||
* The analysis status
|
||||
*/
|
||||
Analysis::AnalysisStatus status() const;
|
||||
void setStatus( Analysis::AnalysisStatus );
|
||||
|
||||
/**
|
||||
* The full audio summary of the track. This contains information about the track's bars,
|
||||
* beats, sections, and detailed segment information as well as more metadata about the song's
|
||||
* acoustic properties.
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
AudioSummary audioSummary() const;
|
||||
void setAudioSummary( const AudioSummary& summary );
|
||||
|
||||
/**
|
||||
* Get a track object from the md5 hash of a song's contents.
|
||||
*
|
||||
* Call parseProfile() to get the track itself once the
|
||||
* QNetworkReply() emits the finished() signal.
|
||||
*/
|
||||
static QNetworkReply* profileFromMD5( const QByteArray& md5 );
|
||||
|
||||
/**
|
||||
* Get a track object from an Echo Nest track id.
|
||||
*
|
||||
* Call parseProfile() to get the track itself once the
|
||||
* QNetworkReply() emits the finished() signal.
|
||||
*/
|
||||
static QNetworkReply* profileFromTrackId( const QByteArray& id );
|
||||
|
||||
/**
|
||||
* Upload a track to The Echo Nest for analysis. The file can either be
|
||||
* a local filetype and include the file data as a parameter, or a url to a file on the internet.
|
||||
*
|
||||
* When the QNetworkReply emits its finished() signal, you can call parseProfile()
|
||||
* to get the resulting Track object. Be sure to check the status of the new track,
|
||||
* as it might be 'pending', which means it is still being analyzed and must be asked
|
||||
* for again later.
|
||||
*
|
||||
* Note that in the case of uploading a local file, the data QByteArray must stay in scope for the
|
||||
* whole completion of the upload operation.
|
||||
*/
|
||||
static QNetworkReply* uploadLocalFile( const QUrl& localFile, const QByteArray& data, bool waitForResult = true );
|
||||
static QNetworkReply* uploadURL( const QUrl& remoteURL, bool waitForResult = true );
|
||||
|
||||
/**
|
||||
* Analyze a previously uploaded track with the current version of the analyzer.
|
||||
* It can be referenced by either track ID or file md5.
|
||||
*/
|
||||
static QNetworkReply* analyzeTrackId( const QByteArray& id, bool wait = true );
|
||||
static QNetworkReply* analyzeTrackMD5( const QByteArray& id, bool wait = true );
|
||||
|
||||
/**
|
||||
* Parse the result of a track request, and turn it into a
|
||||
* Track object.
|
||||
*
|
||||
* Call this function after the QNetworkReply* object returned
|
||||
* from the parse*, upload*, and analyze* emits its finished() signal
|
||||
*/
|
||||
static Track parseProfile( QNetworkReply* ) throw( ParseError );
|
||||
|
||||
private:
|
||||
|
||||
QSharedDataPointer<TrackData> d;
|
||||
};
|
||||
|
||||
ECHONEST_EXPORT QDebug operator<<(QDebug d, const Echonest::Track& track);
|
||||
|
||||
|
||||
} // namespace
|
||||
|
||||
#endif
|
59
3rdparty/libechonest/Track_p.h
vendored
Normal file
59
3rdparty/libechonest/Track_p.h
vendored
Normal 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/>. *
|
||||
****************************************************************************************/
|
||||
|
||||
#ifndef ECHONEST_TRACK_P_H
|
||||
#define ECHONEST_TRACK_P_H
|
||||
|
||||
#include "AudioSummary.h"
|
||||
|
||||
#include <QSharedData>
|
||||
#include <QString>
|
||||
|
||||
class TrackData : public QSharedData
|
||||
{
|
||||
public:
|
||||
TrackData() {}
|
||||
|
||||
TrackData(const TrackData& other)
|
||||
{
|
||||
analyzer_version = other.analyzer_version;
|
||||
artist = other.artist;
|
||||
bitrate = other.bitrate;
|
||||
id = other.id;
|
||||
md5 = other.md5;
|
||||
release = other.release;
|
||||
samplerate = other.samplerate;
|
||||
status = other.status;
|
||||
title = other.title;
|
||||
|
||||
}
|
||||
|
||||
QString artist;
|
||||
QString analyzer_version;
|
||||
int bitrate;
|
||||
QByteArray id;
|
||||
QByteArray md5;
|
||||
QString release;
|
||||
QByteArray audio_md5;
|
||||
int samplerate;
|
||||
QString status;
|
||||
QString title;
|
||||
|
||||
Echonest::AudioSummary audio_summary;
|
||||
|
||||
};
|
||||
|
||||
#endif
|
49
3rdparty/libechonest/Util.cpp
vendored
Normal file
49
3rdparty/libechonest/Util.cpp
vendored
Normal 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/>. *
|
||||
****************************************************************************************/
|
||||
|
||||
#include "Util.h"
|
||||
|
||||
#include <QString>
|
||||
|
||||
Echonest::Analysis::AnalysisStatus Echonest::statusToEnum(const QString& status)
|
||||
{
|
||||
if( status == QLatin1String("unknown") ) {
|
||||
return Echonest::Analysis::Unknown;
|
||||
} else if( status == QLatin1String("pending") ) {
|
||||
return Echonest::Analysis::Pending;
|
||||
} else if( status == QLatin1String("complete") ) {
|
||||
return Echonest::Analysis::Complete;
|
||||
} else if( status == QLatin1String("error" )) {
|
||||
return Echonest::Analysis::Error;
|
||||
}
|
||||
return Echonest::Analysis::Unknown;
|
||||
}
|
||||
|
||||
QString Echonest::statusToString(Echonest::Analysis::AnalysisStatus status)
|
||||
{
|
||||
switch( status )
|
||||
{
|
||||
case Echonest::Analysis::Unknown:
|
||||
return QLatin1String( "unknown" );
|
||||
case Echonest::Analysis::Pending:
|
||||
return QLatin1String( "pending" );
|
||||
case Echonest::Analysis::Complete:
|
||||
return QLatin1String( "complete" );
|
||||
case Echonest::Analysis::Error:
|
||||
return QLatin1String( "error" );
|
||||
}
|
||||
return QString();
|
||||
}
|
80
3rdparty/libechonest/Util.h
vendored
Normal file
80
3rdparty/libechonest/Util.h
vendored
Normal file
@ -0,0 +1,80 @@
|
||||
/****************************************************************************************
|
||||
* 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_UTIL_H
|
||||
#define ECHONEST_UTIL_H
|
||||
|
||||
#include <QVector>
|
||||
#include <QUrl>
|
||||
|
||||
/**
|
||||
* Some shared declarations
|
||||
*/
|
||||
|
||||
namespace Echonest
|
||||
{
|
||||
namespace Analysis
|
||||
{
|
||||
enum AnalysisStatus {
|
||||
Unknown = 0,
|
||||
Pending = 1,
|
||||
Complete = 2,
|
||||
Error = 4
|
||||
};
|
||||
}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
qreal confidence;
|
||||
qreal duration;
|
||||
qreal start;
|
||||
} AudioChunk;
|
||||
|
||||
typedef AudioChunk Bar;
|
||||
typedef AudioChunk Beat;
|
||||
typedef AudioChunk Section;
|
||||
typedef AudioChunk Tatum;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
qreal confidence;
|
||||
qreal duration;
|
||||
qreal loudness_max;
|
||||
qreal loudness_max_time;
|
||||
qreal loudness_start;
|
||||
QVector< qreal > pitches;
|
||||
qreal start;
|
||||
QVector< qreal > timbre;
|
||||
} Segment;
|
||||
|
||||
|
||||
typedef QVector< Bar > BarList;
|
||||
typedef QVector< Beat > BeatList;
|
||||
typedef QVector< Section > SectionList;
|
||||
typedef QVector< Tatum > TatumList;
|
||||
typedef QVector< Segment > SegmentList;
|
||||
|
||||
typedef struct {
|
||||
QUrl url;
|
||||
QString attribution;
|
||||
QString type;
|
||||
} License;
|
||||
|
||||
Analysis::AnalysisStatus statusToEnum( const QString& status );
|
||||
QString statusToString( Analysis::AnalysisStatus status );
|
||||
}
|
||||
|
||||
#endif
|
28
3rdparty/libechonest/echonest_export.h
vendored
Normal file
28
3rdparty/libechonest/echonest_export.h
vendored
Normal file
@ -0,0 +1,28 @@
|
||||
/****************************************************************************************
|
||||
* 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_EXPORT_H
|
||||
#define ECHONEST_EXPORT_H
|
||||
|
||||
#ifdef Q_CC_MSVC
|
||||
#define ECHONEST_EXPORT __declspec(dllimport)
|
||||
#elif __GNUC__ >= 4
|
||||
#define ECHONEST_EXPORT __attribute__ ((visibility("default")))
|
||||
#else
|
||||
#define ECHONEST_EXPORT
|
||||
#endif
|
||||
|
||||
#endif
|
0
3rdparty/libechonest/libechonest_export.h
vendored
Normal file
0
3rdparty/libechonest/libechonest_export.h
vendored
Normal file
@ -208,6 +208,8 @@ else (USE_SYSTEM_QXT)
|
||||
endif (NOT APPLE)
|
||||
endif (USE_SYSTEM_QXT)
|
||||
|
||||
set(ECHONEST_INCLUDE_DIRS ${CMAKE_BINARY_DIR}/3rdparty/libechonest)
|
||||
|
||||
# Subdirectories
|
||||
add_subdirectory(src)
|
||||
if (WIN32)
|
||||
@ -215,6 +217,7 @@ if (WIN32)
|
||||
endif (WIN32)
|
||||
add_subdirectory(3rdparty/universalchardet)
|
||||
add_subdirectory(3rdparty/fancytabwidget)
|
||||
add_subdirectory(3rdparty/libechonest)
|
||||
add_subdirectory(tests)
|
||||
add_subdirectory(dist)
|
||||
add_subdirectory(tools/ultimate_lyrics_parser)
|
||||
|
@ -1,6 +1,7 @@
|
||||
<RCC>
|
||||
<qresource prefix="/">
|
||||
<file>mainwindow.css</file>
|
||||
<file>songinfo.css</file>
|
||||
<file>schema.sql</file>
|
||||
<file>volumeslider-handle_glow.png</file>
|
||||
<file>volumeslider-handle.png</file>
|
||||
|
8
data/songinfo.css
Normal file
8
data/songinfo.css
Normal file
@ -0,0 +1,8 @@
|
||||
QScrollArea {
|
||||
background: palette(base);
|
||||
}
|
||||
|
||||
QTextEdit {
|
||||
border: 0px;
|
||||
}
|
||||
|
@ -17,6 +17,7 @@ include_directories(${LIBPROJECTM_INCLUDE_DIRS})
|
||||
include_directories(${QTSINGLEAPPLICATION_INCLUDE_DIRS})
|
||||
include_directories(${QTIOCOMPRESSOR_INCLUDE_DIRS})
|
||||
include_directories(${QXT_INCLUDE_DIRS})
|
||||
include_directories(${ECHONEST_INCLUDE_DIRS})
|
||||
|
||||
cmake_policy(SET CMP0011 NEW)
|
||||
include(../cmake/AddEngine.cmake)
|
||||
@ -127,6 +128,11 @@ set(SOURCES
|
||||
radio/savedradio.cpp
|
||||
radio/somafmservice.cpp
|
||||
|
||||
songinfo/artistinfofetcher.cpp
|
||||
songinfo/artistinfoprovider.cpp
|
||||
songinfo/artistinfoview.cpp
|
||||
songinfo/collapsibleinfopane.cpp
|
||||
songinfo/echonestartistinfo.cpp
|
||||
songinfo/htmlscraper.cpp
|
||||
songinfo/lyricfetcher.cpp
|
||||
songinfo/lyricprovider.cpp
|
||||
@ -257,6 +263,11 @@ set(HEADERS
|
||||
radio/savedradio.h
|
||||
radio/somafmservice.h
|
||||
|
||||
songinfo/artistinfofetcher.h
|
||||
songinfo/artistinfoprovider.h
|
||||
songinfo/artistinfoview.h
|
||||
songinfo/collapsibleinfopane.h
|
||||
songinfo/echonestartistinfo.h
|
||||
songinfo/htmlscraper.h
|
||||
songinfo/lyricfetcher.h
|
||||
songinfo/lyricprovider.h
|
||||
@ -681,6 +692,7 @@ add_dependencies(clementine_lib pot)
|
||||
target_link_libraries(clementine_lib
|
||||
chardet
|
||||
fancytabwidget
|
||||
echonest
|
||||
${GOBJECT_LIBRARIES}
|
||||
${GLIB_LIBRARIES}
|
||||
${TAGLIB_LIBRARIES}
|
||||
|
@ -46,6 +46,8 @@
|
||||
#include <glib-object.h>
|
||||
#include <glib/gutils.h>
|
||||
|
||||
#include <echonest/Config.h>
|
||||
|
||||
#ifdef Q_WS_X11
|
||||
# include <QDBusConnection>
|
||||
# include <QDBusMetaType>
|
||||
@ -198,6 +200,9 @@ int main(int argc, char *argv[]) {
|
||||
|
||||
NetworkAccessManager network;
|
||||
|
||||
Echonest::Config::instance()->setAPIKey("DFLFLJBUF4EGTXHIG");
|
||||
Echonest::Config::instance()->setNetworkAccessManager(network.network());
|
||||
|
||||
// MPRIS DBus interface.
|
||||
#ifdef Q_WS_X11
|
||||
qDBusRegisterMetaType<DBusStatus>();
|
||||
|
39
src/songinfo/artistinfofetcher.cpp
Normal file
39
src/songinfo/artistinfofetcher.cpp
Normal file
@ -0,0 +1,39 @@
|
||||
/* This file is part of Clementine.
|
||||
|
||||
Clementine 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 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Clementine 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 Clementine. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "artistinfofetcher.h"
|
||||
#include "echonestartistinfo.h"
|
||||
|
||||
ArtistInfoFetcher::ArtistInfoFetcher(QObject* parent)
|
||||
: QObject(parent),
|
||||
next_id_(1)
|
||||
{
|
||||
AddProvider(new EchoNestArtistInfo(this));
|
||||
}
|
||||
|
||||
void ArtistInfoFetcher::AddProvider(ArtistInfoProvider* provider) {
|
||||
providers_ << provider;
|
||||
connect(provider, SIGNAL(ImageReady(int,QUrl)), SIGNAL(ImageReady(int,QUrl)));
|
||||
connect(provider, SIGNAL(InfoReady(int,QString,QWidget*)), SIGNAL(InfoReady(int,QString,QWidget*)));
|
||||
}
|
||||
|
||||
int ArtistInfoFetcher::FetchInfo(const QString& artist) {
|
||||
const int id = next_id_ ++;
|
||||
foreach (ArtistInfoProvider* provider, providers_) {
|
||||
provider->FetchInfo(id, artist);
|
||||
}
|
||||
return id;
|
||||
}
|
46
src/songinfo/artistinfofetcher.h
Normal file
46
src/songinfo/artistinfofetcher.h
Normal file
@ -0,0 +1,46 @@
|
||||
/* This file is part of Clementine.
|
||||
|
||||
Clementine 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 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Clementine 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 Clementine. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef ARTISTINFOFETCHER_H
|
||||
#define ARTISTINFOFETCHER_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QUrl>
|
||||
|
||||
class ArtistInfoProvider;
|
||||
|
||||
class ArtistInfoFetcher : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
ArtistInfoFetcher(QObject* parent = 0);
|
||||
|
||||
int FetchInfo(const QString& artist);
|
||||
|
||||
signals:
|
||||
void ImageReady(int id, const QUrl& url);
|
||||
void InfoReady(int id, const QString& title, QWidget* widget);
|
||||
|
||||
private:
|
||||
void AddProvider(ArtistInfoProvider* provider);
|
||||
|
||||
private:
|
||||
QList<ArtistInfoProvider*> providers_;
|
||||
|
||||
int next_id_;
|
||||
};
|
||||
|
||||
#endif // ARTISTINFOFETCHER_H
|
22
src/songinfo/artistinfoprovider.cpp
Normal file
22
src/songinfo/artistinfoprovider.cpp
Normal file
@ -0,0 +1,22 @@
|
||||
/* This file is part of Clementine.
|
||||
|
||||
Clementine 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 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Clementine 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 Clementine. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "artistinfoprovider.h"
|
||||
|
||||
ArtistInfoProvider::ArtistInfoProvider(QObject* parent)
|
||||
: QObject(parent)
|
||||
{
|
||||
}
|
36
src/songinfo/artistinfoprovider.h
Normal file
36
src/songinfo/artistinfoprovider.h
Normal file
@ -0,0 +1,36 @@
|
||||
/* This file is part of Clementine.
|
||||
|
||||
Clementine 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 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Clementine 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 Clementine. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef ARTISTINFOPROVIDER_H
|
||||
#define ARTISTINFOPROVIDER_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QUrl>
|
||||
|
||||
class ArtistInfoProvider : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
ArtistInfoProvider(QObject* parent = 0);
|
||||
|
||||
virtual void FetchInfo(int id, const QString& artist) = 0;
|
||||
|
||||
signals:
|
||||
void ImageReady(int id, const QUrl& url);
|
||||
void InfoReady(int id, const QString& title, QWidget* widget);
|
||||
};
|
||||
|
||||
#endif // ARTISTINFOPROVIDER_H
|
95
src/songinfo/artistinfoview.cpp
Normal file
95
src/songinfo/artistinfoview.cpp
Normal file
@ -0,0 +1,95 @@
|
||||
/* This file is part of Clementine.
|
||||
|
||||
Clementine 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 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Clementine 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 Clementine. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "artistinfofetcher.h"
|
||||
#include "artistinfoview.h"
|
||||
#include "collapsibleinfopane.h"
|
||||
|
||||
#include <QFile>
|
||||
#include <QScrollArea>
|
||||
#include <QTextEdit>
|
||||
#include <QVBoxLayout>
|
||||
#include <QtDebug>
|
||||
|
||||
ArtistInfoView::ArtistInfoView(QWidget *parent)
|
||||
: SongInfoBase(parent),
|
||||
fetcher_(new ArtistInfoFetcher(this)),
|
||||
current_request_id_(-1),
|
||||
scroll_area_(new QScrollArea),
|
||||
container_(new QVBoxLayout)
|
||||
{
|
||||
connect(fetcher_, SIGNAL(ImageReady(int,QUrl)), SLOT(ImageReady(int,QUrl)));
|
||||
connect(fetcher_, SIGNAL(InfoReady(int,QString,QWidget*)), SLOT(InfoReady(int,QString,QWidget*)));
|
||||
|
||||
// Add the top-level scroll area
|
||||
setLayout(new QVBoxLayout);
|
||||
layout()->setContentsMargins(0, 0, 0, 0);
|
||||
layout()->addWidget(scroll_area_);
|
||||
|
||||
// Add a container widget to the scroll area
|
||||
QWidget* container_widget = new QWidget;
|
||||
container_widget->setLayout(container_);
|
||||
container_widget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
|
||||
container_->setSizeConstraint(QLayout::SetNoConstraint);
|
||||
scroll_area_->setWidget(container_widget);
|
||||
scroll_area_->setWidgetResizable(true);
|
||||
|
||||
// Add a spacer to the bottom of the container
|
||||
container_->addSpacerItem(new QSpacerItem(0, 0, QSizePolicy::Fixed, QSizePolicy::Expanding));
|
||||
|
||||
// Set stylesheet
|
||||
QFile stylesheet(":/songinfo.css");
|
||||
stylesheet.open(QIODevice::ReadOnly);
|
||||
setStyleSheet(QString::fromAscii(stylesheet.readAll()));
|
||||
}
|
||||
|
||||
ArtistInfoView::~ArtistInfoView() {
|
||||
}
|
||||
|
||||
void ArtistInfoView::AddChild(QWidget* widget) {
|
||||
children_ << widget;
|
||||
container_->insertWidget(container_->count() - 1, widget);
|
||||
widget->show();
|
||||
}
|
||||
|
||||
void ArtistInfoView::Clear() {
|
||||
qDeleteAll(children_);
|
||||
children_.clear();
|
||||
}
|
||||
|
||||
void ArtistInfoView::Update(const Song& metadata) {
|
||||
Clear();
|
||||
current_request_id_ = fetcher_->FetchInfo(metadata.artist());
|
||||
}
|
||||
|
||||
void ArtistInfoView::ImageReady(int id, const QUrl& url) {
|
||||
if (id != current_request_id_)
|
||||
return;
|
||||
|
||||
qDebug() << "Image" << url;
|
||||
}
|
||||
|
||||
void ArtistInfoView::InfoReady(int id, const QString& title, QWidget* widget) {
|
||||
if (id != current_request_id_) {
|
||||
delete widget;
|
||||
return;
|
||||
}
|
||||
|
||||
CollapsibleInfoPane* pane = new CollapsibleInfoPane(this);
|
||||
pane->SetTitle(title);
|
||||
pane->SetWidget(widget);
|
||||
AddChild(pane);
|
||||
}
|
54
src/songinfo/artistinfoview.h
Normal file
54
src/songinfo/artistinfoview.h
Normal file
@ -0,0 +1,54 @@
|
||||
/* This file is part of Clementine.
|
||||
|
||||
Clementine 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 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Clementine 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 Clementine. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef ARTISTINFOVIEW_H
|
||||
#define ARTISTINFOVIEW_H
|
||||
|
||||
#include "songinfobase.h"
|
||||
|
||||
class ArtistInfoFetcher;
|
||||
|
||||
class QScrollArea;
|
||||
class QVBoxLayout;
|
||||
|
||||
class ArtistInfoView : public SongInfoBase {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
ArtistInfoView(QWidget* parent = 0);
|
||||
~ArtistInfoView();
|
||||
|
||||
protected:
|
||||
void Update(const Song& metadata);
|
||||
|
||||
private:
|
||||
void AddChild(QWidget* widget);
|
||||
void Clear();
|
||||
|
||||
private slots:
|
||||
void ImageReady(int id, const QUrl& url);
|
||||
void InfoReady(int id, const QString& title, QWidget* widget);
|
||||
|
||||
private:
|
||||
ArtistInfoFetcher* fetcher_;
|
||||
int current_request_id_;
|
||||
|
||||
QScrollArea* scroll_area_;
|
||||
QVBoxLayout* container_;
|
||||
QList<QWidget*> children_;
|
||||
};
|
||||
|
||||
#endif // ARTISTINFOVIEW_H
|
99
src/songinfo/collapsibleinfopane.cpp
Normal file
99
src/songinfo/collapsibleinfopane.cpp
Normal file
@ -0,0 +1,99 @@
|
||||
/* This file is part of Clementine.
|
||||
|
||||
Clementine 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 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Clementine 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 Clementine. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "collapsibleinfopane.h"
|
||||
|
||||
#include <QStylePainter>
|
||||
#include <QStyleOption>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
const int CollapsibleInfoPane::kMargin = 6;
|
||||
const int CollapsibleInfoPane::kTitleHeight = 20;
|
||||
|
||||
CollapsibleInfoPane::CollapsibleInfoPane(QWidget* parent)
|
||||
: QWidget(parent),
|
||||
widget_(NULL),
|
||||
expanded_(true)
|
||||
{
|
||||
QVBoxLayout* layout = new QVBoxLayout(this);
|
||||
layout->setContentsMargins(kMargin, kTitleHeight, kMargin, 0);
|
||||
setLayout(layout);
|
||||
|
||||
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Maximum);
|
||||
setMinimumHeight(kTitleHeight);
|
||||
}
|
||||
|
||||
void CollapsibleInfoPane::SetTitle(const QString& title) {
|
||||
title_ = title;
|
||||
update();
|
||||
}
|
||||
|
||||
void CollapsibleInfoPane::SetWidget(QWidget* widget) {
|
||||
if (widget_)
|
||||
delete widget_;
|
||||
|
||||
widget_ = widget;
|
||||
layout()->addWidget(widget);
|
||||
}
|
||||
|
||||
void CollapsibleInfoPane::Collapse() {
|
||||
expanded_ = false;
|
||||
update();
|
||||
}
|
||||
|
||||
void CollapsibleInfoPane::Expand() {
|
||||
expanded_ = true;
|
||||
update();
|
||||
}
|
||||
|
||||
void CollapsibleInfoPane::paintEvent(QPaintEvent* e) {
|
||||
QStylePainter p(this);
|
||||
|
||||
QRect title_rect(0, 0, width(), kTitleHeight);
|
||||
QRect indicator_rect(0, 0, kTitleHeight, kTitleHeight);
|
||||
QRect text_rect(title_rect);
|
||||
text_rect.setLeft(kTitleHeight + 6);
|
||||
|
||||
// Draw the background
|
||||
const QColor bg_color_1(palette().color(QPalette::Highlight));
|
||||
const QColor bg_color_2(palette().color(QPalette::Highlight).lighter(125));
|
||||
const QColor bg_border(palette().color(QPalette::Dark));
|
||||
QLinearGradient bg_brush(title_rect.topLeft(), title_rect.bottomLeft());
|
||||
bg_brush.setColorAt(0.0, bg_color_1);
|
||||
bg_brush.setColorAt(0.5, bg_color_2);
|
||||
bg_brush.setColorAt(1.0, bg_color_1);
|
||||
|
||||
p.setPen(bg_border);
|
||||
p.drawLine(title_rect.topLeft(), title_rect.topRight());
|
||||
p.drawLine(title_rect.bottomLeft(), title_rect.bottomRight());
|
||||
|
||||
p.setPen(Qt::NoPen);
|
||||
p.fillRect(title_rect, bg_brush);
|
||||
|
||||
// Draw the expand/collapse indicator
|
||||
QStyleOption opt;
|
||||
opt.initFrom(this);
|
||||
opt.rect = indicator_rect;
|
||||
opt.state |= QStyle::State_Children;
|
||||
if (expanded_)
|
||||
opt.state |= QStyle::State_Open;
|
||||
|
||||
p.drawPrimitive(QStyle::PE_IndicatorBranch, opt);
|
||||
|
||||
// Draw the title text
|
||||
p.setPen(palette().color(QPalette::HighlightedText));
|
||||
p.drawText(text_rect, Qt::AlignLeft | Qt::AlignVCenter, title_);
|
||||
}
|
47
src/songinfo/collapsibleinfopane.h
Normal file
47
src/songinfo/collapsibleinfopane.h
Normal file
@ -0,0 +1,47 @@
|
||||
/* This file is part of Clementine.
|
||||
|
||||
Clementine 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 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Clementine 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 Clementine. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef COLLAPSIBLEINFOPANE_H
|
||||
#define COLLAPSIBLEINFOPANE_H
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
class CollapsibleInfoPane : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
CollapsibleInfoPane(QWidget* parent = 0);
|
||||
|
||||
static const int kTitleHeight;
|
||||
static const int kMargin;
|
||||
|
||||
void SetTitle(const QString& title);
|
||||
void SetWidget(QWidget* widget);
|
||||
|
||||
public slots:
|
||||
void Expand();
|
||||
void Collapse();
|
||||
|
||||
protected:
|
||||
void paintEvent(QPaintEvent* e);
|
||||
|
||||
private:
|
||||
QString title_;
|
||||
QWidget* widget_;
|
||||
bool expanded_;
|
||||
};
|
||||
|
||||
#endif // COLLAPSIBLEINFOPANE_H
|
89
src/songinfo/echonestartistinfo.cpp
Normal file
89
src/songinfo/echonestartistinfo.cpp
Normal file
@ -0,0 +1,89 @@
|
||||
/* This file is part of Clementine.
|
||||
|
||||
Clementine 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 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Clementine 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 Clementine. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "echonestartistinfo.h"
|
||||
|
||||
#include <QTextEdit>
|
||||
|
||||
#include <echonest/Artist.h>
|
||||
|
||||
#include <boost/scoped_ptr.hpp>
|
||||
|
||||
struct EchoNestArtistInfo::Request {
|
||||
Request(int id) : id_(id), artist_(new Echonest::Artist) {}
|
||||
|
||||
int id_;
|
||||
boost::scoped_ptr<Echonest::Artist> artist_;
|
||||
QList<QNetworkReply*> pending_replies_;
|
||||
};
|
||||
|
||||
EchoNestArtistInfo::EchoNestArtistInfo(QObject* parent)
|
||||
: ArtistInfoProvider(parent)
|
||||
{
|
||||
}
|
||||
|
||||
void EchoNestArtistInfo::FetchInfo(int id, const QString& artist_name) {
|
||||
boost::shared_ptr<Request> request(new Request(id));
|
||||
request->artist_->setName(artist_name);
|
||||
|
||||
ConnectReply(request, request->artist_->fetchBiographies(), SLOT(BiographiesFinished()));
|
||||
ConnectReply(request, request->artist_->fetchImages(), SLOT(ImagesFinished()));
|
||||
|
||||
requests_ << request;
|
||||
}
|
||||
|
||||
void EchoNestArtistInfo::ConnectReply(
|
||||
boost::shared_ptr<Request> request, QNetworkReply* reply, const char* slot) {
|
||||
request->pending_replies_ << reply;
|
||||
connect(reply, SIGNAL(finished()), slot);
|
||||
}
|
||||
|
||||
EchoNestArtistInfo::RequestPtr EchoNestArtistInfo::ReplyFinished(QNetworkReply* reply) {
|
||||
reply->deleteLater();
|
||||
|
||||
foreach (RequestPtr request, requests_) {
|
||||
if (request->pending_replies_.contains(reply)) {
|
||||
request->artist_->parseProfile(reply);
|
||||
request->pending_replies_.removeAll(reply);
|
||||
|
||||
if (request->pending_replies_.isEmpty()) {
|
||||
requests_.removeAll(request);
|
||||
}
|
||||
|
||||
return request;
|
||||
}
|
||||
}
|
||||
return RequestPtr();
|
||||
}
|
||||
|
||||
void EchoNestArtistInfo::ImagesFinished() {
|
||||
RequestPtr request = ReplyFinished(qobject_cast<QNetworkReply*>(sender()));
|
||||
|
||||
foreach (const Echonest::ArtistImage& image, request->artist_->images()) {
|
||||
emit ImageReady(request->id_, image.url());
|
||||
}
|
||||
}
|
||||
|
||||
void EchoNestArtistInfo::BiographiesFinished() {
|
||||
RequestPtr request = ReplyFinished(qobject_cast<QNetworkReply*>(sender()));
|
||||
|
||||
foreach (const Echonest::Biography& bio, request->artist_->biographies()) {
|
||||
QTextEdit* editor = new QTextEdit;
|
||||
editor->setHtml(bio.text());
|
||||
|
||||
emit InfoReady(request->id_, tr("Biography from %1").arg(bio.site()), editor);
|
||||
}
|
||||
}
|
49
src/songinfo/echonestartistinfo.h
Normal file
49
src/songinfo/echonestartistinfo.h
Normal file
@ -0,0 +1,49 @@
|
||||
/* This file is part of Clementine.
|
||||
|
||||
Clementine 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 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Clementine 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 Clementine. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef ECHONESTARTISTINFO_H
|
||||
#define ECHONESTARTISTINFO_H
|
||||
|
||||
#include "artistinfoprovider.h"
|
||||
|
||||
#include <boost/shared_ptr.hpp>
|
||||
|
||||
class QNetworkReply;
|
||||
|
||||
class EchoNestArtistInfo : public ArtistInfoProvider {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
EchoNestArtistInfo(QObject* parent = 0);
|
||||
|
||||
void FetchInfo(int id, const QString& artist);
|
||||
|
||||
private slots:
|
||||
void BiographiesFinished();
|
||||
void ImagesFinished();
|
||||
|
||||
private:
|
||||
struct Request;
|
||||
typedef boost::shared_ptr<Request> RequestPtr;
|
||||
|
||||
void ConnectReply(RequestPtr request, QNetworkReply* reply, const char* slot);
|
||||
RequestPtr ReplyFinished(QNetworkReply* reply);
|
||||
|
||||
private:
|
||||
QList<RequestPtr> requests_;
|
||||
};
|
||||
|
||||
#endif // ECHONESTARTISTINFO_H
|
@ -312,6 +312,10 @@ msgstr ""
|
||||
msgid "Behavior"
|
||||
msgstr ""
|
||||
|
||||
#, qt-format
|
||||
msgid "Biography from %1"
|
||||
msgstr ""
|
||||
|
||||
msgid "Bit rate"
|
||||
msgstr "معدل البت"
|
||||
|
||||
|
@ -313,6 +313,10 @@ msgstr ""
|
||||
msgid "Behavior"
|
||||
msgstr ""
|
||||
|
||||
#, qt-format
|
||||
msgid "Biography from %1"
|
||||
msgstr ""
|
||||
|
||||
msgid "Bit rate"
|
||||
msgstr ""
|
||||
|
||||
|
@ -322,6 +322,10 @@ msgstr "Blau Bàsic"
|
||||
msgid "Behavior"
|
||||
msgstr "Comportament"
|
||||
|
||||
#, qt-format
|
||||
msgid "Biography from %1"
|
||||
msgstr ""
|
||||
|
||||
msgid "Bit rate"
|
||||
msgstr "Taxa de bits"
|
||||
|
||||
|
@ -314,6 +314,10 @@ msgstr "Jednoduchá modrá"
|
||||
msgid "Behavior"
|
||||
msgstr "Chování"
|
||||
|
||||
#, qt-format
|
||||
msgid "Biography from %1"
|
||||
msgstr ""
|
||||
|
||||
msgid "Bit rate"
|
||||
msgstr "Datový tok"
|
||||
|
||||
|
@ -314,6 +314,10 @@ msgstr "Basal blå"
|
||||
msgid "Behavior"
|
||||
msgstr "Adfærd"
|
||||
|
||||
#, qt-format
|
||||
msgid "Biography from %1"
|
||||
msgstr ""
|
||||
|
||||
msgid "Bit rate"
|
||||
msgstr "Bitrate"
|
||||
|
||||
|
@ -320,6 +320,10 @@ msgstr "Standardblau"
|
||||
msgid "Behavior"
|
||||
msgstr "Verhalten"
|
||||
|
||||
#, qt-format
|
||||
msgid "Biography from %1"
|
||||
msgstr ""
|
||||
|
||||
msgid "Bit rate"
|
||||
msgstr "Bitrate"
|
||||
|
||||
|
@ -321,6 +321,10 @@ msgstr "Βασικό μπλε"
|
||||
msgid "Behavior"
|
||||
msgstr "Συμπεριφορά"
|
||||
|
||||
#, qt-format
|
||||
msgid "Biography from %1"
|
||||
msgstr ""
|
||||
|
||||
msgid "Bit rate"
|
||||
msgstr "Ρυθμός bit"
|
||||
|
||||
|
@ -312,6 +312,10 @@ msgstr "Basic Blue"
|
||||
msgid "Behavior"
|
||||
msgstr "Behaviour"
|
||||
|
||||
#, qt-format
|
||||
msgid "Biography from %1"
|
||||
msgstr ""
|
||||
|
||||
msgid "Bit rate"
|
||||
msgstr "Bit rate"
|
||||
|
||||
|
@ -312,6 +312,10 @@ msgstr "Basic Blue"
|
||||
msgid "Behavior"
|
||||
msgstr "Behaviour"
|
||||
|
||||
#, qt-format
|
||||
msgid "Biography from %1"
|
||||
msgstr ""
|
||||
|
||||
msgid "Bit rate"
|
||||
msgstr "Bit rate"
|
||||
|
||||
|
@ -322,6 +322,10 @@ msgstr "Azul básico"
|
||||
msgid "Behavior"
|
||||
msgstr "Comportamiento"
|
||||
|
||||
#, qt-format
|
||||
msgid "Biography from %1"
|
||||
msgstr ""
|
||||
|
||||
msgid "Bit rate"
|
||||
msgstr "Tasa de bits"
|
||||
|
||||
|
@ -313,6 +313,10 @@ msgstr ""
|
||||
msgid "Behavior"
|
||||
msgstr ""
|
||||
|
||||
#, qt-format
|
||||
msgid "Biography from %1"
|
||||
msgstr ""
|
||||
|
||||
msgid "Bit rate"
|
||||
msgstr "Bittivirta"
|
||||
|
||||
|
@ -325,6 +325,10 @@ msgstr "Bleu standard"
|
||||
msgid "Behavior"
|
||||
msgstr "Comportement"
|
||||
|
||||
#, qt-format
|
||||
msgid "Biography from %1"
|
||||
msgstr ""
|
||||
|
||||
msgid "Bit rate"
|
||||
msgstr "Débit"
|
||||
|
||||
|
@ -313,6 +313,10 @@ msgstr "Azul básico"
|
||||
msgid "Behavior"
|
||||
msgstr "Comportamento"
|
||||
|
||||
#, qt-format
|
||||
msgid "Biography from %1"
|
||||
msgstr ""
|
||||
|
||||
msgid "Bit rate"
|
||||
msgstr "Taxa de bits"
|
||||
|
||||
|
@ -318,6 +318,10 @@ msgstr "Egyszerű kék"
|
||||
msgid "Behavior"
|
||||
msgstr "Viselkedés"
|
||||
|
||||
#, qt-format
|
||||
msgid "Biography from %1"
|
||||
msgstr ""
|
||||
|
||||
msgid "Bit rate"
|
||||
msgstr "Bitráta"
|
||||
|
||||
|
@ -325,6 +325,10 @@ msgstr "Blu di base"
|
||||
msgid "Behavior"
|
||||
msgstr "Comportamento"
|
||||
|
||||
#, qt-format
|
||||
msgid "Biography from %1"
|
||||
msgstr ""
|
||||
|
||||
msgid "Bit rate"
|
||||
msgstr "Bitrate"
|
||||
|
||||
|
@ -312,6 +312,10 @@ msgstr ""
|
||||
msgid "Behavior"
|
||||
msgstr ""
|
||||
|
||||
#, qt-format
|
||||
msgid "Biography from %1"
|
||||
msgstr ""
|
||||
|
||||
msgid "Bit rate"
|
||||
msgstr ""
|
||||
|
||||
|
@ -313,6 +313,10 @@ msgstr ""
|
||||
msgid "Behavior"
|
||||
msgstr ""
|
||||
|
||||
#, qt-format
|
||||
msgid "Biography from %1"
|
||||
msgstr ""
|
||||
|
||||
msgid "Bit rate"
|
||||
msgstr ""
|
||||
|
||||
|
@ -313,6 +313,10 @@ msgstr "Blå"
|
||||
msgid "Behavior"
|
||||
msgstr ""
|
||||
|
||||
#, qt-format
|
||||
msgid "Biography from %1"
|
||||
msgstr ""
|
||||
|
||||
msgid "Bit rate"
|
||||
msgstr "Bitrate"
|
||||
|
||||
|
@ -321,6 +321,10 @@ msgstr "Basic Blue"
|
||||
msgid "Behavior"
|
||||
msgstr "Gedrag"
|
||||
|
||||
#, qt-format
|
||||
msgid "Biography from %1"
|
||||
msgstr ""
|
||||
|
||||
msgid "Bit rate"
|
||||
msgstr "Bitsnelheid"
|
||||
|
||||
|
@ -312,6 +312,10 @@ msgstr "Blau estandard"
|
||||
msgid "Behavior"
|
||||
msgstr "Compòrtament"
|
||||
|
||||
#, qt-format
|
||||
msgid "Biography from %1"
|
||||
msgstr ""
|
||||
|
||||
msgid "Bit rate"
|
||||
msgstr "Debit binari"
|
||||
|
||||
|
@ -321,6 +321,10 @@ msgstr "Prosty niebieski"
|
||||
msgid "Behavior"
|
||||
msgstr "Tryb"
|
||||
|
||||
#, qt-format
|
||||
msgid "Biography from %1"
|
||||
msgstr ""
|
||||
|
||||
msgid "Bit rate"
|
||||
msgstr "Bitrate"
|
||||
|
||||
|
@ -321,6 +321,10 @@ msgstr "Azul básico"
|
||||
msgid "Behavior"
|
||||
msgstr "Comportamento"
|
||||
|
||||
#, qt-format
|
||||
msgid "Biography from %1"
|
||||
msgstr ""
|
||||
|
||||
msgid "Bit rate"
|
||||
msgstr "Taxa de \"bits\""
|
||||
|
||||
|
@ -318,6 +318,10 @@ msgstr "Azul básico"
|
||||
msgid "Behavior"
|
||||
msgstr "Comportamento"
|
||||
|
||||
#, qt-format
|
||||
msgid "Biography from %1"
|
||||
msgstr ""
|
||||
|
||||
msgid "Bit rate"
|
||||
msgstr "Taxa de bits"
|
||||
|
||||
|
@ -312,6 +312,10 @@ msgstr ""
|
||||
msgid "Behavior"
|
||||
msgstr "Comportament"
|
||||
|
||||
#, qt-format
|
||||
msgid "Biography from %1"
|
||||
msgstr ""
|
||||
|
||||
msgid "Bit rate"
|
||||
msgstr "Rată de biți"
|
||||
|
||||
|
@ -316,6 +316,10 @@ msgstr "Стандартно голубой"
|
||||
msgid "Behavior"
|
||||
msgstr "Поведение"
|
||||
|
||||
#, qt-format
|
||||
msgid "Biography from %1"
|
||||
msgstr ""
|
||||
|
||||
msgid "Bit rate"
|
||||
msgstr "Битрейт"
|
||||
|
||||
|
@ -318,6 +318,10 @@ msgstr "Základná modrá"
|
||||
msgid "Behavior"
|
||||
msgstr "Správanie"
|
||||
|
||||
#, qt-format
|
||||
msgid "Biography from %1"
|
||||
msgstr ""
|
||||
|
||||
msgid "Bit rate"
|
||||
msgstr "Bit rate"
|
||||
|
||||
|
@ -317,6 +317,10 @@ msgstr "Preprosta modra"
|
||||
msgid "Behavior"
|
||||
msgstr "Obnašanje"
|
||||
|
||||
#, qt-format
|
||||
msgid "Biography from %1"
|
||||
msgstr ""
|
||||
|
||||
msgid "Bit rate"
|
||||
msgstr "Bitna hitrost"
|
||||
|
||||
|
@ -313,6 +313,10 @@ msgstr "Основно плаво"
|
||||
msgid "Behavior"
|
||||
msgstr "Понашање"
|
||||
|
||||
#, qt-format
|
||||
msgid "Biography from %1"
|
||||
msgstr ""
|
||||
|
||||
msgid "Bit rate"
|
||||
msgstr "Битски проток"
|
||||
|
||||
|
@ -313,6 +313,10 @@ msgstr "Basblå"
|
||||
msgid "Behavior"
|
||||
msgstr "Beteende"
|
||||
|
||||
#, qt-format
|
||||
msgid "Biography from %1"
|
||||
msgstr ""
|
||||
|
||||
msgid "Bit rate"
|
||||
msgstr "Bithastighet"
|
||||
|
||||
|
@ -317,6 +317,10 @@ msgstr "Temel Mavi"
|
||||
msgid "Behavior"
|
||||
msgstr "Davranış"
|
||||
|
||||
#, qt-format
|
||||
msgid "Biography from %1"
|
||||
msgstr ""
|
||||
|
||||
msgid "Bit rate"
|
||||
msgstr "Bit oranı"
|
||||
|
||||
|
@ -303,6 +303,10 @@ msgstr ""
|
||||
msgid "Behavior"
|
||||
msgstr ""
|
||||
|
||||
#, qt-format
|
||||
msgid "Biography from %1"
|
||||
msgstr ""
|
||||
|
||||
msgid "Bit rate"
|
||||
msgstr ""
|
||||
|
||||
|
@ -317,6 +317,10 @@ msgstr "Стандартний синій"
|
||||
msgid "Behavior"
|
||||
msgstr "Поведінка"
|
||||
|
||||
#, qt-format
|
||||
msgid "Biography from %1"
|
||||
msgstr ""
|
||||
|
||||
msgid "Bit rate"
|
||||
msgstr "Бітова швидкість"
|
||||
|
||||
|
@ -312,6 +312,10 @@ msgstr ""
|
||||
msgid "Behavior"
|
||||
msgstr ""
|
||||
|
||||
#, qt-format
|
||||
msgid "Biography from %1"
|
||||
msgstr ""
|
||||
|
||||
msgid "Bit rate"
|
||||
msgstr "比特率"
|
||||
|
||||
|
@ -317,6 +317,10 @@ msgstr ""
|
||||
msgid "Behavior"
|
||||
msgstr "行為"
|
||||
|
||||
#, qt-format
|
||||
msgid "Biography from %1"
|
||||
msgstr ""
|
||||
|
||||
msgid "Bit rate"
|
||||
msgstr "位元率"
|
||||
|
||||
|
@ -54,6 +54,7 @@
|
||||
#include "radio/radioview.h"
|
||||
#include "radio/radioviewcontainer.h"
|
||||
#include "radio/savedradio.h"
|
||||
#include "songinfo/artistinfoview.h"
|
||||
#include "songinfo/lyricfetcher.h"
|
||||
#include "songinfo/lyricview.h"
|
||||
#include "transcoder/transcodedialog.h"
|
||||
@ -142,6 +143,7 @@ MainWindow::MainWindow(NetworkAccessManager* network, Engine::Type engine, QWidg
|
||||
radio_view_(new RadioViewContainer(this)),
|
||||
device_view_(new DeviceView(this)),
|
||||
lyric_view_(new LyricView(this)),
|
||||
artist_info_view_(new ArtistInfoView(this)),
|
||||
settings_dialog_(NULL),
|
||||
cover_manager_(NULL),
|
||||
equalizer_(new Equalizer),
|
||||
@ -179,14 +181,14 @@ MainWindow::MainWindow(NetworkAccessManager* network, Engine::Type engine, QWidg
|
||||
ui_->volume->setValue(player_->GetVolume());
|
||||
|
||||
// Add tabs to the fancy tab widget
|
||||
AddFancyTab(library_view_, IconLoader::Load("folder-sound"), tr("Library"));
|
||||
AddFancyTab(file_view_, IconLoader::Load("document-open"), tr("Files"));
|
||||
AddFancyTab(radio_view_, QIcon(":last.fm/icon_radio.png"), tr("Internet"));
|
||||
AddFancyTab(device_view_, IconLoader::Load("multimedia-player-ipod-mini-blue"), tr("Devices"));
|
||||
ui_->tabs->addTab(library_view_, IconLoader::Load("folder-sound"), tr("Library"));
|
||||
ui_->tabs->addTab(file_view_, IconLoader::Load("document-open"), tr("Files"));
|
||||
ui_->tabs->addTab(radio_view_, QIcon(":last.fm/icon_radio.png"), tr("Internet"));
|
||||
ui_->tabs->addTab(device_view_, IconLoader::Load("multimedia-player-ipod-mini-blue"), tr("Devices"));
|
||||
ui_->tabs->addSpacer();
|
||||
AddFancyTab(lyric_view_, IconLoader::Load("view-media-lyrics"), tr("Lyrics"));
|
||||
AddFancyTab(new QWidget, IconLoader::Load("view-media-lyrics"), tr("Song info"));
|
||||
AddFancyTab(new QWidget, IconLoader::Load("view-media-lyrics"), tr("Artist info"));
|
||||
ui_->tabs->addTab(lyric_view_, IconLoader::Load("view-media-lyrics"), tr("Lyrics"));
|
||||
ui_->tabs->addTab(new QWidget, IconLoader::Load("view-media-lyrics"), tr("Song info"));
|
||||
ui_->tabs->addTab(artist_info_view_, IconLoader::Load("view-media-lyrics"), tr("Artist info"));
|
||||
|
||||
ui_->tabs->statusBar()->hide();
|
||||
ui_->tabs->setBackgroundPixmap(QPixmap(":/sidebar_background.png"));
|
||||
@ -491,6 +493,7 @@ MainWindow::MainWindow(NetworkAccessManager* network, Engine::Type engine, QWidg
|
||||
// Lyrics
|
||||
lyric_view_->set_network(network);
|
||||
ConnectInfoView(lyric_view_);
|
||||
ConnectInfoView(artist_info_view_);
|
||||
|
||||
// Analyzer
|
||||
ui_->analyzer->SetEngine(player_->GetEngine());
|
||||
@ -1579,10 +1582,6 @@ void MainWindow::ShowVisualisations() {
|
||||
#endif // ENABLE_VISUALISATIONS
|
||||
}
|
||||
|
||||
void MainWindow::AddFancyTab(QWidget* widget, const QIcon& icon, const QString& label) {
|
||||
ui_->tabs->addTab(widget, icon, label);
|
||||
}
|
||||
|
||||
void MainWindow::ConnectInfoView(SongInfoBase* view) {
|
||||
connect(playlists_, SIGNAL(CurrentSongChanged(Song)), view, SLOT(SongChanged(Song)));
|
||||
connect(player_, SIGNAL(PlaylistFinished()), view, SLOT(SongFinished()));
|
||||
|
@ -33,6 +33,7 @@
|
||||
class About;
|
||||
class AddStreamDialog;
|
||||
class AlbumCoverManager;
|
||||
class ArtistInfoView;
|
||||
class CommandlineOptions;
|
||||
class Database;
|
||||
class DeviceManager;
|
||||
@ -196,7 +197,6 @@ class MainWindow : public QMainWindow, public PlatformInterface {
|
||||
void AddLibrarySongsToPlaylist(bool clear_first, const SongList& songs);
|
||||
void AddDeviceSongsToPlaylist(bool clear_first, const SongList& songs);
|
||||
void AddUrls(bool play_now, const QList<QUrl>& urls);
|
||||
void AddFancyTab(QWidget* widget, const QIcon& icon, const QString& label);
|
||||
void ConnectInfoView(SongInfoBase* view);
|
||||
|
||||
private:
|
||||
@ -225,6 +225,7 @@ class MainWindow : public QMainWindow, public PlatformInterface {
|
||||
RadioViewContainer* radio_view_;
|
||||
DeviceView* device_view_;
|
||||
LyricView* lyric_view_;
|
||||
ArtistInfoView* artist_info_view_;
|
||||
|
||||
boost::scoped_ptr<SettingsDialog> settings_dialog_;
|
||||
boost::scoped_ptr<AddStreamDialog> add_stream_dialog_;
|
||||
|
Loading…
x
Reference in New Issue
Block a user