1
0
mirror of https://github.com/tomahawk-player/tomahawk.git synced 2025-07-31 03:10:12 +02:00

add support for Echo Nest "style" and "mood" parameters to playlists

This commit is contained in:
Leo Franchi
2011-05-23 18:40:05 -04:00
parent 0e92d6913c
commit 03c7c0e35f
3 changed files with 100 additions and 13 deletions

View File

@@ -25,6 +25,7 @@
#include <QComboBox>
#include <QLineEdit>
#include <QLabel>
#include "EchonestGenerator.h"
Tomahawk::EchonestControl::EchonestControl( const QString& selectedType, const QStringList& typeSelectors, QObject* parent )
@@ -315,6 +316,31 @@ Tomahawk::EchonestControl::updateWidgets()
connect( combo, SIGNAL( activated( int ) ), this, SLOT( updateData() ) );
connect( combo, SIGNAL( activated( int ) ), this, SLOT( editingFinished() ) );
match->hide();
combo->hide();
m_match = QWeakPointer< QWidget >( match );
m_input = QWeakPointer< QWidget >( combo );
} else if( selectedType() == "Mood" || selectedType() == "Style" ) {
if( selectedType() == "Mood" )
m_currentType = Echonest::DynamicPlaylist::Mood;
else
m_currentType = Echonest::DynamicPlaylist::Style;
QLabel* match = new QLabel( tr( "is" ) );
QComboBox* combo = new QComboBox;
QVector< QString > src = selectedType() == "Mood" ? EchonestGenerator::moods() : EchonestGenerator::styles();
foreach( const QString& item, src ) {
combo->addItem( item, item );
}
m_matchString = match->text();
m_matchData = match->text();
connect( combo, SIGNAL( activated( int ) ), this, SLOT( updateData() ) );
connect( combo, SIGNAL( activated( int ) ), this, SLOT( editingFinished() ) );
match->hide();
combo->hide();
m_match = QWeakPointer< QWidget >( match );
@@ -384,7 +410,7 @@ Tomahawk::EchonestControl::updateData()
updateFromComboAndSlider();
} else if( selectedType() == "Danceability" || selectedType() == "Energy" || selectedType() == "Artist Familiarity" || selectedType() == "Artist Hotttnesss" || selectedType() == "Song Hotttnesss" ) {
updateFromComboAndSlider( true );
} else if( selectedType() == "Mode" || selectedType() == "Key" ) {
} else if( selectedType() == "Mode" || selectedType() == "Key" || selectedType() == "Mood" || selectedType() == "Style" ) {
updateFromLabelAndCombo();
} else if( selectedType() == "Sorting" ) {
QComboBox* match = qobject_cast<QComboBox*>( m_match.data() );
@@ -453,7 +479,7 @@ Tomahawk::EchonestControl::updateWidgetsFromData()
updateToComboAndSlider();
} else if( selectedType() == "Danceability" || selectedType() == "Energy" || selectedType() == "Artist Familiarity" || selectedType() == "Artist Hotttnesss" || selectedType() == "Song Hotttnesss" ) {
updateToComboAndSlider( true );
} else if( selectedType() == "Mode" || selectedType() == "Key" ) {
} else if( selectedType() == "Mode" || selectedType() == "Key" || selectedType() == "Mood" || selectedType() == "Style" ) {
updateToLabelAndCombo();
} else if( selectedType() == "Sorting" ) {
QComboBox* match = qobject_cast<QComboBox*>( m_match.data() );
@@ -564,6 +590,11 @@ Tomahawk::EchonestControl::calculateSummary()
QString ascdesc = qobject_cast< QComboBox* >( m_match.data() )->currentText().toLower();
summary = QString( "sorted in %1 %2 order" ).arg( ascdesc ).arg( sortType );
} else if( selectedType() == "Mood" || selectedType() == "Style" ) {
Q_ASSERT( !m_input.isNull() );
Q_ASSERT( qobject_cast< QComboBox* >( m_input.data() ) );
QString text = qobject_cast< QComboBox* >( m_input.data() )->currentText().toLower();
summary = QString( "with %1 %2" ).arg( selectedType() == "Mood" ? "mood" : "style" ).arg( text );
}
m_summary = summary;
}

View File

@@ -24,6 +24,9 @@
using namespace Tomahawk;
QVector< QString > EchonestGenerator::s_moods = QVector< QString >();
QVector< QString > EchonestGenerator::s_styles = QVector< QString >();
EchonestFactory::EchonestFactory()
{}
@@ -42,7 +45,7 @@ EchonestFactory::createControl( const QString& controlType )
QStringList
EchonestFactory::typeSelectors() const
{
return QStringList() << "Artist" << "Artist Description" << "Variety" << "Tempo" << "Duration" << "Loudness"
return QStringList() << "Artist" << "Artist Description" << "Song" << "Mood" << "Style" << "Variety" << "Tempo" << "Duration" << "Loudness"
<< "Danceability" << "Energy" << "Artist Familiarity" << "Artist Hotttnesss" << "Song Hotttnesss"
<< "Longitude" << "Latitude" << "Mode" << "Key" << "Sorting";
}
@@ -55,6 +58,14 @@ EchonestGenerator::EchonestGenerator ( QObject* parent )
m_type = "echonest";
m_mode = OnDemand;
m_logo.load( RESPATH "/images/echonest_logo.png" );
// fetch style and moods
QNetworkReply* style = Echonest::Artist::listTerms( "style" );
connect( style, SIGNAL( finished() ), this, SLOT( stylesReceived() ) );
QNetworkReply* moods = Echonest::Artist::listTerms( "mood" );
connect( moods, SIGNAL( finished() ), this, SLOT( moodsReceived() ) );
// qDebug() << "ECHONEST:" << m_logo.size();
}
@@ -408,3 +419,40 @@ EchonestGenerator::sentenceSummary()
return sentence;
}
QVector< QString >
EchonestGenerator::moods()
{
return s_moods;
}
void
EchonestGenerator::moodsReceived()
{
QNetworkReply* r = qobject_cast< QNetworkReply* >( sender() );
Q_ASSERT( r );
try {
s_moods = Echonest::Artist::parseTermList( r );
} catch( Echonest::ParseError& e ) {
qWarning() << "Echonest failed to parse moods list";
}
}
QVector< QString >
EchonestGenerator::styles()
{
return s_styles;
}
void
EchonestGenerator::stylesReceived()
{
QNetworkReply* r = qobject_cast< QNetworkReply* >( sender() );
Q_ASSERT( r );
try {
s_styles = Echonest::Artist::parseTermList( r );
} catch( Echonest::ParseError& e ) {
qWarning() << "Echonest failed to parse styles list";
}
}

View File

@@ -1,5 +1,5 @@
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
*
*
* Copyright 2010-2011, Christian Muehlhaeuser <muesli@tomahawk-player.org>
*
* Tomahawk is free software: you can redistribute it and/or modify
@@ -28,7 +28,7 @@
#include "dllmacro.h"
namespace Tomahawk
namespace Tomahawk
{
class EchonestSteerer;
@@ -37,19 +37,19 @@ class DLLEXPORT EchonestFactory : public GeneratorFactoryInterface
{
public:
EchonestFactory();
virtual GeneratorInterface* create();
virtual dyncontrol_ptr createControl( const QString& controlType = QString() );
virtual QStringList typeSelectors() const;
};
class EchonestGenerator : public GeneratorInterface
{
Q_OBJECT
public:
explicit EchonestGenerator( QObject* parent = 0 );
virtual ~EchonestGenerator();
virtual dyncontrol_ptr createControl( const QString& type = QString() );
virtual QPixmap logo();
virtual void generate ( int number = -1 );
@@ -58,26 +58,34 @@ public:
virtual QString sentenceSummary();
virtual bool onDemandSteerable() const { return true; }
virtual QWidget* steeringWidget();
static QVector< QString > styles();
static QVector< QString > moods();
private slots:
void staticFinished();
void dynamicStarted();
void dynamicFetched();
// steering controls
void steerField( const QString& field );
void steerDescription( const QString& desc );
void resetSteering();
void stylesReceived();
void moodsReceived();
private:
Echonest::DynamicPlaylist::PlaylistParams getParams() const throw( std::runtime_error );
query_ptr queryFromSong( const Echonest::Song& song );
void appendRadioType( Echonest::DynamicPlaylist::PlaylistParams& params ) const throw( std::runtime_error );
bool onlyThisArtistType( Echonest::DynamicPlaylist::ArtistTypeEnum type ) const throw( std::runtime_error );
Echonest::DynamicPlaylist* m_dynPlaylist;
QPixmap m_logo;
static QVector< QString > s_styles;
static QVector< QString > s_moods;
QWeakPointer<EchonestSteerer> m_steerer;
bool m_steeredSinceLastTrack;
Echonest::DynamicPlaylist::DynamicControl m_steerData;