From 6dbf1a86fb7dab9b376454065cf78d6ded8b0c2a Mon Sep 17 00:00:00 2001 From: Leo Franchi Date: Thu, 20 Jan 2011 19:05:02 -0500 Subject: [PATCH] add support for all 3 types of artist matches --- .../playlist/dynamic/GeneratorInterface.h | 1 + .../dynamic/echonest/EchonestControl.cpp | 13 +++- .../dynamic/echonest/EchonestControl.h | 5 +- .../dynamic/echonest/EchonestGenerator.cpp | 77 +++++++++++++++---- .../dynamic/echonest/EchonestGenerator.h | 5 +- 5 files changed, 79 insertions(+), 22 deletions(-) diff --git a/src/libtomahawk/playlist/dynamic/GeneratorInterface.h b/src/libtomahawk/playlist/dynamic/GeneratorInterface.h index ea0478b36..9f42e2003 100644 --- a/src/libtomahawk/playlist/dynamic/GeneratorInterface.h +++ b/src/libtomahawk/playlist/dynamic/GeneratorInterface.h @@ -94,6 +94,7 @@ public: void removeControl( const dyncontrol_ptr& control ); signals: + void controlsInvalid( const QString& shortTitle, const QString& message ); void onDemandFailed(); void generated( const QList< Tomahawk::query_ptr>& queries ); void nextTrackGenerated( const Tomahawk::query_ptr& track ); diff --git a/src/libtomahawk/playlist/dynamic/echonest/EchonestControl.cpp b/src/libtomahawk/playlist/dynamic/echonest/EchonestControl.cpp index 17d092265..bf8e9b954 100644 --- a/src/libtomahawk/playlist/dynamic/echonest/EchonestControl.cpp +++ b/src/libtomahawk/playlist/dynamic/echonest/EchonestControl.cpp @@ -31,6 +31,7 @@ Tomahawk::EchonestControl::EchonestControl( const QString& selectedType, const Q connect( &m_editingTimer, SIGNAL( timeout() ), this, SIGNAL( changed() ) ); updateWidgets(); + updateData(); } QWidget* @@ -62,6 +63,11 @@ Tomahawk::EchonestControl::setSelectedType ( const QString& type ) Echonest::DynamicPlaylist::PlaylistParamData Tomahawk::EchonestControl::toENParam() const { + if( m_overrideType != -1 ) { + Echonest::DynamicPlaylist::PlaylistParamData newData = m_data; + newData.first = static_cast( m_overrideType ); + return newData; + } return m_data; } @@ -95,7 +101,6 @@ void Tomahawk::EchonestControl::setMatch(const QString& match) updateWidgetsFromData(); } - void Tomahawk::EchonestControl::updateWidgets() { @@ -103,6 +108,7 @@ Tomahawk::EchonestControl::updateWidgets() delete m_input.data(); if( !m_match.isNull() ) delete m_match.data(); + m_overrideType = -1; // make sure the widgets are the proper kind for the selected type, and hook up to their slots if( selectedType() == "Artist" ) { @@ -113,6 +119,7 @@ Tomahawk::EchonestControl::updateWidgets() match->addItem( "Limit To", Echonest::DynamicPlaylist::ArtistType ); match->addItem( "Similar To", Echonest::DynamicPlaylist::ArtistRadioType ); + match->addItem( "Description", Echonest::DynamicPlaylist::ArtistDescriptionType ); m_matchString = match->currentText(); m_matchData = match->itemData( match->currentIndex() ).toString(); @@ -143,6 +150,10 @@ Tomahawk::EchonestControl::updateData() if( combo ) { m_matchString = combo->currentText(); m_matchData = combo->itemData( combo->currentIndex() ).toString(); + + // EN HACK: artist-description radio needs description= fields not artist= fields + if( m_matchData.toInt() == Echonest::DynamicPlaylist::ArtistDescriptionType ) + m_overrideType = Echonest::DynamicPlaylist::Description; } QLineEdit* edit = qobject_cast( m_input.data() ); if( edit && !edit->text().isEmpty() ) { diff --git a/src/libtomahawk/playlist/dynamic/echonest/EchonestControl.h b/src/libtomahawk/playlist/dynamic/echonest/EchonestControl.h index 82c5e2350..07ac91d70 100644 --- a/src/libtomahawk/playlist/dynamic/echonest/EchonestControl.h +++ b/src/libtomahawk/playlist/dynamic/echonest/EchonestControl.h @@ -41,7 +41,7 @@ public: virtual void setInput(const QString& input); virtual void setMatch(const QString& match); - + /// DO NOT USE IF YOU ARE NOT A DBCMD explicit EchonestControl( const QString& type, const QStringList& typeSelectors, QObject* parent = 0 ); @@ -57,6 +57,7 @@ private: void updateWidgetsFromData(); Echonest::DynamicPlaylist::PlaylistParam m_currentType; + int m_overrideType; QWeakPointer< QWidget > m_input; QWeakPointer< QWidget > m_match; @@ -70,8 +71,6 @@ private: friend class EchonestGenerator; }; -typedef QSharedPointer encontrol_ptr; - }; #endif diff --git a/src/libtomahawk/playlist/dynamic/echonest/EchonestGenerator.cpp b/src/libtomahawk/playlist/dynamic/echonest/EchonestGenerator.cpp index dda01b280..9ae911e93 100644 --- a/src/libtomahawk/playlist/dynamic/echonest/EchonestGenerator.cpp +++ b/src/libtomahawk/playlist/dynamic/echonest/EchonestGenerator.cpp @@ -21,7 +21,6 @@ using namespace Tomahawk; - EchonestFactory::EchonestFactory() {} @@ -77,22 +76,32 @@ void EchonestGenerator::generate ( int number ) { // convert to an echonest query, and fire it off - Echonest::DynamicPlaylist::PlaylistParams params = getParams(); - params.append( Echonest::DynamicPlaylist::PlaylistParamData( Echonest::DynamicPlaylist::Results, number ) ); - QNetworkReply* reply = Echonest::DynamicPlaylist::staticPlaylist( params ); - qDebug() << "Generating a static playlist from echonest!" << reply->url().toString(); - connect( reply, SIGNAL( finished() ), this, SLOT( staticFinished() ) ); - + try { + Echonest::DynamicPlaylist::PlaylistParams params = getParams(); + + params.append( Echonest::DynamicPlaylist::PlaylistParamData( Echonest::DynamicPlaylist::Results, number ) ); + QNetworkReply* reply = Echonest::DynamicPlaylist::staticPlaylist( params ); + qDebug() << "Generating a static playlist from echonest!" << reply->url().toString(); + connect( reply, SIGNAL( finished() ), this, SLOT( staticFinished() ) ); + } catch( std::runtime_error& e ) { + qWarning() << "Got invalid controls!" << e.what(); + emit controlsInvalid( "Controls were not valid", QString::fromLatin1( e.what() ) ); + } } void EchonestGenerator::startOnDemand() { - Echonest::DynamicPlaylist::PlaylistParams params = getParams(); - - QNetworkReply* reply = m_dynPlaylist->start( params ); - qDebug() << "starting a dynamic playlist from echonest!" << reply->url().toString(); - connect( reply, SIGNAL( finished() ), this, SLOT( dynamicStarted() ) ); + try { + Echonest::DynamicPlaylist::PlaylistParams params = getParams(); + + QNetworkReply* reply = m_dynPlaylist->start( params ); + qDebug() << "starting a dynamic playlist from echonest!" << reply->url().toString(); + connect( reply, SIGNAL( finished() ), this, SLOT( dynamicStarted() ) ); + } catch( std::runtime_error& e ) { + qWarning() << "Got invalid controls!" << e.what(); + emit controlsInvalid( "Controls were not valid", QString::fromLatin1( e.what() ) ); + } } void @@ -136,7 +145,8 @@ EchonestGenerator::staticFinished() emit generated( queries ); } -Echonest::DynamicPlaylist::PlaylistParams EchonestGenerator::getParams() const +Echonest::DynamicPlaylist::PlaylistParams +EchonestGenerator::getParams() const throw( std::runtime_error ) { Echonest::DynamicPlaylist::PlaylistParams params; foreach( const dyncontrol_ptr& control, m_controls ) { @@ -182,11 +192,46 @@ EchonestGenerator::dynamicFetched() } -// tries to heuristically determine what sort of radio this is based on the controls Echonest::DynamicPlaylist::ArtistTypeEnum -EchonestGenerator::determineRadioType() const +EchonestGenerator::determineRadioType() const throw( std::runtime_error ) { - // TODO + /** + * so we try to match the best type of echonest playlist, based on the controls + * the types are artist, artist-radio, artist-description, catalog, catalog-radio, song-radio. we don't care about the catalog ones. + */ + + /// 1. artist: If all the artist controls are Limit-To. If some were but not all, error out. + bool artistOnly = true; + bool someArtist = false; + foreach( const dyncontrol_ptr& control, m_controls ) { + if( control->selectedType() == "Artist" && static_cast( control->match().toInt() ) != Echonest::DynamicPlaylist::ArtistType ) { + artistOnly = false; + } else if( control->selectedType() == "Artist" && static_cast( control->match().toInt() ) == Echonest::DynamicPlaylist::ArtistType ) { + someArtist = true; + } + } + if( someArtist && artistOnly ) { + return Echonest::DynamicPlaylist::ArtistType; + } else if( someArtist && !artistOnly ) { + throw std::runtime_error( "All artist match types must be the same" ); + } + + /// 2. artist-description: If all the artist entries are Description. If some were but not all, error out. + bool artistDescOnly = true; + bool someArtistDescFound = false; + + foreach( const dyncontrol_ptr& control, m_controls ) { + if( control->selectedType() == "Artist" && static_cast( control->match().toInt() ) == Echonest::DynamicPlaylist::ArtistDescriptionType ) { + someArtistDescFound = true; + } else if( control->selectedType() == "Artist" && static_cast( control->match().toInt() ) != Echonest::DynamicPlaylist::ArtistDescriptionType ) { + artistDescOnly = false; + } + } + if( someArtistDescFound && artistDescOnly ) { + return Echonest::DynamicPlaylist::ArtistDescriptionType; + } else if( someArtistDescFound && !artistDescOnly ) // fail, must be all artist desc + throw std::runtime_error( "All artist match types must be the same" ); + return Echonest::DynamicPlaylist::ArtistRadioType; } diff --git a/src/libtomahawk/playlist/dynamic/echonest/EchonestGenerator.h b/src/libtomahawk/playlist/dynamic/echonest/EchonestGenerator.h index 1a5122b5c..93d49e500 100644 --- a/src/libtomahawk/playlist/dynamic/echonest/EchonestGenerator.h +++ b/src/libtomahawk/playlist/dynamic/echonest/EchonestGenerator.h @@ -17,6 +17,7 @@ #ifndef ECHONEST_GENERATOR_H #define ECHONEST_GENERATOR_H +#include #include #include "playlist/dynamic/GeneratorInterface.h" @@ -55,10 +56,10 @@ private slots: void dynamicFetched(); private: - Echonest::DynamicPlaylist::PlaylistParams getParams() const; + Echonest::DynamicPlaylist::PlaylistParams getParams() const throw( std::runtime_error ); query_ptr queryFromSong( const Echonest::Song& song ); + Echonest::DynamicPlaylist::ArtistTypeEnum determineRadioType() const throw( std::runtime_error ); - Echonest::DynamicPlaylist::ArtistTypeEnum determineRadioType() const; Echonest::DynamicPlaylist* m_dynPlaylist; QPixmap m_logo; };