mirror of
https://github.com/tomahawk-player/tomahawk.git
synced 2025-08-01 20:00:13 +02:00
add support for Echo Nest "style" and "mood" parameters to playlists
This commit is contained in:
@@ -25,6 +25,7 @@
|
|||||||
#include <QComboBox>
|
#include <QComboBox>
|
||||||
#include <QLineEdit>
|
#include <QLineEdit>
|
||||||
#include <QLabel>
|
#include <QLabel>
|
||||||
|
#include "EchonestGenerator.h"
|
||||||
|
|
||||||
|
|
||||||
Tomahawk::EchonestControl::EchonestControl( const QString& selectedType, const QStringList& typeSelectors, QObject* parent )
|
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( updateData() ) );
|
||||||
connect( combo, SIGNAL( activated( int ) ), this, SLOT( editingFinished() ) );
|
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();
|
match->hide();
|
||||||
combo->hide();
|
combo->hide();
|
||||||
m_match = QWeakPointer< QWidget >( match );
|
m_match = QWeakPointer< QWidget >( match );
|
||||||
@@ -384,7 +410,7 @@ Tomahawk::EchonestControl::updateData()
|
|||||||
updateFromComboAndSlider();
|
updateFromComboAndSlider();
|
||||||
} else if( selectedType() == "Danceability" || selectedType() == "Energy" || selectedType() == "Artist Familiarity" || selectedType() == "Artist Hotttnesss" || selectedType() == "Song Hotttnesss" ) {
|
} else if( selectedType() == "Danceability" || selectedType() == "Energy" || selectedType() == "Artist Familiarity" || selectedType() == "Artist Hotttnesss" || selectedType() == "Song Hotttnesss" ) {
|
||||||
updateFromComboAndSlider( true );
|
updateFromComboAndSlider( true );
|
||||||
} else if( selectedType() == "Mode" || selectedType() == "Key" ) {
|
} else if( selectedType() == "Mode" || selectedType() == "Key" || selectedType() == "Mood" || selectedType() == "Style" ) {
|
||||||
updateFromLabelAndCombo();
|
updateFromLabelAndCombo();
|
||||||
} else if( selectedType() == "Sorting" ) {
|
} else if( selectedType() == "Sorting" ) {
|
||||||
QComboBox* match = qobject_cast<QComboBox*>( m_match.data() );
|
QComboBox* match = qobject_cast<QComboBox*>( m_match.data() );
|
||||||
@@ -453,7 +479,7 @@ Tomahawk::EchonestControl::updateWidgetsFromData()
|
|||||||
updateToComboAndSlider();
|
updateToComboAndSlider();
|
||||||
} else if( selectedType() == "Danceability" || selectedType() == "Energy" || selectedType() == "Artist Familiarity" || selectedType() == "Artist Hotttnesss" || selectedType() == "Song Hotttnesss" ) {
|
} else if( selectedType() == "Danceability" || selectedType() == "Energy" || selectedType() == "Artist Familiarity" || selectedType() == "Artist Hotttnesss" || selectedType() == "Song Hotttnesss" ) {
|
||||||
updateToComboAndSlider( true );
|
updateToComboAndSlider( true );
|
||||||
} else if( selectedType() == "Mode" || selectedType() == "Key" ) {
|
} else if( selectedType() == "Mode" || selectedType() == "Key" || selectedType() == "Mood" || selectedType() == "Style" ) {
|
||||||
updateToLabelAndCombo();
|
updateToLabelAndCombo();
|
||||||
} else if( selectedType() == "Sorting" ) {
|
} else if( selectedType() == "Sorting" ) {
|
||||||
QComboBox* match = qobject_cast<QComboBox*>( m_match.data() );
|
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();
|
QString ascdesc = qobject_cast< QComboBox* >( m_match.data() )->currentText().toLower();
|
||||||
|
|
||||||
summary = QString( "sorted in %1 %2 order" ).arg( ascdesc ).arg( sortType );
|
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;
|
m_summary = summary;
|
||||||
}
|
}
|
||||||
|
@@ -24,6 +24,9 @@
|
|||||||
|
|
||||||
using namespace Tomahawk;
|
using namespace Tomahawk;
|
||||||
|
|
||||||
|
QVector< QString > EchonestGenerator::s_moods = QVector< QString >();
|
||||||
|
QVector< QString > EchonestGenerator::s_styles = QVector< QString >();
|
||||||
|
|
||||||
EchonestFactory::EchonestFactory()
|
EchonestFactory::EchonestFactory()
|
||||||
{}
|
{}
|
||||||
|
|
||||||
@@ -42,7 +45,7 @@ EchonestFactory::createControl( const QString& controlType )
|
|||||||
QStringList
|
QStringList
|
||||||
EchonestFactory::typeSelectors() const
|
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"
|
<< "Danceability" << "Energy" << "Artist Familiarity" << "Artist Hotttnesss" << "Song Hotttnesss"
|
||||||
<< "Longitude" << "Latitude" << "Mode" << "Key" << "Sorting";
|
<< "Longitude" << "Latitude" << "Mode" << "Key" << "Sorting";
|
||||||
}
|
}
|
||||||
@@ -55,6 +58,14 @@ EchonestGenerator::EchonestGenerator ( QObject* parent )
|
|||||||
m_type = "echonest";
|
m_type = "echonest";
|
||||||
m_mode = OnDemand;
|
m_mode = OnDemand;
|
||||||
m_logo.load( RESPATH "/images/echonest_logo.png" );
|
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();
|
// qDebug() << "ECHONEST:" << m_logo.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -408,3 +419,40 @@ EchonestGenerator::sentenceSummary()
|
|||||||
return sentence;
|
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";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
||||||
*
|
*
|
||||||
* Copyright 2010-2011, Christian Muehlhaeuser <muesli@tomahawk-player.org>
|
* Copyright 2010-2011, Christian Muehlhaeuser <muesli@tomahawk-player.org>
|
||||||
*
|
*
|
||||||
* Tomahawk is free software: you can redistribute it and/or modify
|
* Tomahawk is free software: you can redistribute it and/or modify
|
||||||
@@ -28,7 +28,7 @@
|
|||||||
|
|
||||||
#include "dllmacro.h"
|
#include "dllmacro.h"
|
||||||
|
|
||||||
namespace Tomahawk
|
namespace Tomahawk
|
||||||
{
|
{
|
||||||
|
|
||||||
class EchonestSteerer;
|
class EchonestSteerer;
|
||||||
@@ -37,19 +37,19 @@ class DLLEXPORT EchonestFactory : public GeneratorFactoryInterface
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
EchonestFactory();
|
EchonestFactory();
|
||||||
|
|
||||||
virtual GeneratorInterface* create();
|
virtual GeneratorInterface* create();
|
||||||
virtual dyncontrol_ptr createControl( const QString& controlType = QString() );
|
virtual dyncontrol_ptr createControl( const QString& controlType = QString() );
|
||||||
virtual QStringList typeSelectors() const;
|
virtual QStringList typeSelectors() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
class EchonestGenerator : public GeneratorInterface
|
class EchonestGenerator : public GeneratorInterface
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
explicit EchonestGenerator( QObject* parent = 0 );
|
explicit EchonestGenerator( QObject* parent = 0 );
|
||||||
virtual ~EchonestGenerator();
|
virtual ~EchonestGenerator();
|
||||||
|
|
||||||
virtual dyncontrol_ptr createControl( const QString& type = QString() );
|
virtual dyncontrol_ptr createControl( const QString& type = QString() );
|
||||||
virtual QPixmap logo();
|
virtual QPixmap logo();
|
||||||
virtual void generate ( int number = -1 );
|
virtual void generate ( int number = -1 );
|
||||||
@@ -58,26 +58,34 @@ public:
|
|||||||
virtual QString sentenceSummary();
|
virtual QString sentenceSummary();
|
||||||
virtual bool onDemandSteerable() const { return true; }
|
virtual bool onDemandSteerable() const { return true; }
|
||||||
virtual QWidget* steeringWidget();
|
virtual QWidget* steeringWidget();
|
||||||
|
|
||||||
|
static QVector< QString > styles();
|
||||||
|
static QVector< QString > moods();
|
||||||
private slots:
|
private slots:
|
||||||
void staticFinished();
|
void staticFinished();
|
||||||
void dynamicStarted();
|
void dynamicStarted();
|
||||||
void dynamicFetched();
|
void dynamicFetched();
|
||||||
|
|
||||||
// steering controls
|
// steering controls
|
||||||
void steerField( const QString& field );
|
void steerField( const QString& field );
|
||||||
void steerDescription( const QString& desc );
|
void steerDescription( const QString& desc );
|
||||||
void resetSteering();
|
void resetSteering();
|
||||||
|
|
||||||
|
void stylesReceived();
|
||||||
|
void moodsReceived();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Echonest::DynamicPlaylist::PlaylistParams getParams() const throw( std::runtime_error );
|
Echonest::DynamicPlaylist::PlaylistParams getParams() const throw( std::runtime_error );
|
||||||
query_ptr queryFromSong( const Echonest::Song& song );
|
query_ptr queryFromSong( const Echonest::Song& song );
|
||||||
void appendRadioType( Echonest::DynamicPlaylist::PlaylistParams& params ) const throw( std::runtime_error );
|
void appendRadioType( Echonest::DynamicPlaylist::PlaylistParams& params ) const throw( std::runtime_error );
|
||||||
bool onlyThisArtistType( Echonest::DynamicPlaylist::ArtistTypeEnum type ) const throw( std::runtime_error );
|
bool onlyThisArtistType( Echonest::DynamicPlaylist::ArtistTypeEnum type ) const throw( std::runtime_error );
|
||||||
|
|
||||||
Echonest::DynamicPlaylist* m_dynPlaylist;
|
Echonest::DynamicPlaylist* m_dynPlaylist;
|
||||||
QPixmap m_logo;
|
QPixmap m_logo;
|
||||||
|
|
||||||
|
static QVector< QString > s_styles;
|
||||||
|
static QVector< QString > s_moods;
|
||||||
|
|
||||||
QWeakPointer<EchonestSteerer> m_steerer;
|
QWeakPointer<EchonestSteerer> m_steerer;
|
||||||
bool m_steeredSinceLastTrack;
|
bool m_steeredSinceLastTrack;
|
||||||
Echonest::DynamicPlaylist::DynamicControl m_steerData;
|
Echonest::DynamicPlaylist::DynamicControl m_steerData;
|
||||||
|
Reference in New Issue
Block a user