diff --git a/src/audio/audioengine.cpp b/src/audio/audioengine.cpp index d8b2d29d0..970bdb4de 100644 --- a/src/audio/audioengine.cpp +++ b/src/audio/audioengine.cpp @@ -97,6 +97,7 @@ AudioEngine::stop() m_audio->stopPlayback(); + setCurrentTrack( Tomahawk::result_ptr() ); emit stopped(); } @@ -157,16 +158,7 @@ AudioEngine::loadTrack( const Tomahawk::result_ptr& result ) err = true; else { - m_lastTrack = m_currentTrack; - if ( !m_lastTrack.isNull() ) - { - DatabaseCommand_LogPlayback* cmd = new DatabaseCommand_LogPlayback( m_lastTrack, m_timeElapsed ); - Database::instance()->enqueue( QSharedPointer(cmd) ); - - emit finished( m_lastTrack ); - } - - m_currentTrack = result; + setCurrentTrack( result ); io = Servent::instance()->getIODeviceForUrl( m_currentTrack ); if ( !io || io.isNull() ) @@ -311,10 +303,14 @@ AudioEngine::setStreamData( long sampleRate, int channels ) if ( sampleRate < 44100 ) sampleRate = 44100; + m_audio->initAudio( sampleRate, channels ); if ( m_audio->startPlayback() ) { emit started( m_currentTrack ); + + DatabaseCommand_LogPlayback* cmd = new DatabaseCommand_LogPlayback( m_currentTrack, DatabaseCommand_LogPlayback::Started ); + Database::instance()->enqueue( QSharedPointer(cmd) ); } else { @@ -352,6 +348,22 @@ AudioEngine::clearBuffers() } +void +AudioEngine::setCurrentTrack( const Tomahawk::result_ptr& result ) +{ + m_lastTrack = m_currentTrack; + if ( !m_lastTrack.isNull() ) + { + DatabaseCommand_LogPlayback* cmd = new DatabaseCommand_LogPlayback( m_lastTrack, DatabaseCommand_LogPlayback::Finished, m_timeElapsed ); + Database::instance()->enqueue( QSharedPointer(cmd) ); + + emit finished( m_lastTrack ); + } + + m_currentTrack = result; +} + + void AudioEngine::run() { diff --git a/src/audio/audioengine.h b/src/audio/audioengine.h index 6a4c69252..0c78f0afe 100644 --- a/src/audio/audioengine.h +++ b/src/audio/audioengine.h @@ -80,6 +80,8 @@ private slots: void engineLoop(); void loop(); + void setCurrentTrack( const Tomahawk::result_ptr& result ); + private: void run(); void clearBuffers(); diff --git a/src/infowidgets/sourceinfowidget.cpp b/src/infowidgets/sourceinfowidget.cpp index f3a739330..8ab452ef7 100644 --- a/src/infowidgets/sourceinfowidget.cpp +++ b/src/infowidgets/sourceinfowidget.cpp @@ -29,6 +29,8 @@ SourceInfoWidget::SourceInfoWidget( const Tomahawk::source_ptr& source, QWidget* ui->historyView->setModel( m_historyModel ); m_historyModel->loadHistory( source ); + connect( source.data(), SIGNAL( playbackFinished( Tomahawk::query_ptr ) ), SLOT( onPlaybackFinished( Tomahawk::query_ptr ) ) ); + ui->recentCollectionView->setColumnHidden( TrackModel::Bitrate, true ); ui->recentCollectionView->setColumnHidden( TrackModel::Origin, true ); ui->recentCollectionView->setColumnHidden( TrackModel::Filesize, true ); @@ -49,6 +51,13 @@ SourceInfoWidget::~SourceInfoWidget() } +void +SourceInfoWidget::onPlaybackFinished( const Tomahawk::query_ptr& query ) +{ + m_historyModel->insertTrack( 0, query ); +} + + void SourceInfoWidget::changeEvent( QEvent* e ) { diff --git a/src/infowidgets/sourceinfowidget.h b/src/infowidgets/sourceinfowidget.h index e3bb93047..1fe064980 100644 --- a/src/infowidgets/sourceinfowidget.h +++ b/src/infowidgets/sourceinfowidget.h @@ -27,6 +27,9 @@ public: protected: void changeEvent( QEvent* e ); +private slots: + void onPlaybackFinished( const Tomahawk::query_ptr& query ); + private: Ui::SourceInfoWidget *ui; diff --git a/src/libtomahawk/database/databasecommand_addfiles.cpp b/src/libtomahawk/database/databasecommand_addfiles.cpp index c4cabccc5..0426d8638 100644 --- a/src/libtomahawk/database/databasecommand_addfiles.cpp +++ b/src/libtomahawk/database/databasecommand_addfiles.cpp @@ -38,16 +38,16 @@ DatabaseCommand_AddFiles::postCommitHook() // collection browser will update/fade in etc. Collection* coll = source()->collection().data(); - connect( this, SIGNAL( notify( const QList&, Tomahawk::collection_ptr ) ), - coll, SIGNAL( setTracks( const QList&, Tomahawk::collection_ptr ) ), + connect( this, SIGNAL( notify( QList, Tomahawk::collection_ptr ) ), + coll, SIGNAL( setTracks( QList, Tomahawk::collection_ptr ) ), Qt::QueuedConnection ); // do it like this so it gets called in the right thread: emit notify( m_files, source()->collection() ); // also re-calc the collection stats, to updates the "X tracks" in the sidebar etc: DatabaseCommand_CollectionStats* cmd = new DatabaseCommand_CollectionStats( source() ); - connect( cmd, SIGNAL( done( const QVariantMap& ) ), - source().data(), SLOT( setStats( const QVariantMap& ) ), Qt::QueuedConnection ); + connect( cmd, SIGNAL( done( QVariantMap ) ), + source().data(), SLOT( setStats( QVariantMap ) ), Qt::QueuedConnection ); Database::instance()->enqueue( QSharedPointer( cmd ) ); if( source()->isLocal() ) diff --git a/src/libtomahawk/database/databasecommand_logplayback.cpp b/src/libtomahawk/database/databasecommand_logplayback.cpp index 2c4932972..1aa617859 100644 --- a/src/libtomahawk/database/databasecommand_logplayback.cpp +++ b/src/libtomahawk/database/databasecommand_logplayback.cpp @@ -5,6 +5,7 @@ #include "collection.h" #include "database/database.h" #include "databaseimpl.h" +#include "pipeline.h" #include "network/servent.h" using namespace Tomahawk; @@ -16,6 +17,28 @@ DatabaseCommand_LogPlayback::postCommitHook() { qDebug() << Q_FUNC_INFO; + connect( this, SIGNAL( trackPlaying( Tomahawk::query_ptr ) ), + source().data(), SIGNAL( playbackStarted( Tomahawk::query_ptr ) ), Qt::QueuedConnection ); + connect( this, SIGNAL( trackPlayed( Tomahawk::query_ptr ) ), + source().data(), SIGNAL( playbackFinished( Tomahawk::query_ptr ) ), Qt::QueuedConnection ); + + QVariantMap m; + m.insert( "track", m_track ); + m.insert( "artist", m_artist ); + m.insert( "qid", uuid() ); + Tomahawk::query_ptr q( new Tomahawk::Query( m ) ); + + Tomahawk::Pipeline::instance()->add( q ); + + if ( m_action == Finished ) + { + emit trackPlayed( q ); + } + else if ( m_action == Started ) + { + emit trackPlaying( q ); + } + if( source()->isLocal() ) Servent::instance()->triggerDBSync(); } @@ -27,6 +50,9 @@ DatabaseCommand_LogPlayback::exec( DatabaseImpl* dbi ) qDebug() << Q_FUNC_INFO; Q_ASSERT( !source().isNull() ); + if ( m_action != Finished ) + return; + TomahawkSqlQuery query = dbi->newquery(); query.prepare( "INSERT INTO playback_log(source,track,playtime,secs_played) " "VALUES (?, ?, ?, ?)" ); diff --git a/src/libtomahawk/database/databasecommand_logplayback.h b/src/libtomahawk/database/databasecommand_logplayback.h index bcf2f4e5e..35709b328 100644 --- a/src/libtomahawk/database/databasecommand_logplayback.h +++ b/src/libtomahawk/database/databasecommand_logplayback.h @@ -17,14 +17,21 @@ Q_PROPERTY( QString artist READ artist WRITE setArtist ) Q_PROPERTY( QString track READ track WRITE setTrack ) Q_PROPERTY( unsigned int playtime READ playtime WRITE setPlaytime ) Q_PROPERTY( unsigned int secsPlayed READ secsPlayed WRITE setSecsPlayed ) +Q_PROPERTY( int action READ action WRITE setAction ) public: + enum Action + { + Started = 1, + Finished = 2 + }; + explicit DatabaseCommand_LogPlayback( QObject* parent = 0 ) : DatabaseCommandLoggable( parent ) {} - explicit DatabaseCommand_LogPlayback( const Tomahawk::result_ptr& result, unsigned int secsPlayed, QObject* parent = 0 ) - : DatabaseCommandLoggable( parent ), m_result( result ), m_secsPlayed( secsPlayed ) + explicit DatabaseCommand_LogPlayback( const Tomahawk::result_ptr& result, Action action, unsigned int secsPlayed = 0, QObject* parent = 0 ) + : DatabaseCommandLoggable( parent ), m_result( result ), m_secsPlayed( secsPlayed ), m_action( action ) { m_playtime = QDateTime::currentDateTimeUtc().toTime_t(); setSource( SourceList::instance()->getLocal() ); @@ -51,6 +58,13 @@ public: unsigned int secsPlayed() const { return m_secsPlayed; } void setSecsPlayed( unsigned int i ) { m_secsPlayed = i; } + int action() const { return m_action; } + void setAction( int a ) { m_action = (Action)a; } + +signals: + void trackPlaying( const Tomahawk::query_ptr& query ); + void trackPlayed( const Tomahawk::query_ptr& query ); + private: Tomahawk::result_ptr m_result; @@ -58,6 +72,7 @@ private: QString m_track; unsigned int m_playtime; unsigned int m_secsPlayed; + Action m_action; }; #endif // DATABASECOMMAND_LOGPLAYBACK_H diff --git a/src/libtomahawk/database/databasecommand_playbackhistory.cpp b/src/libtomahawk/database/databasecommand_playbackhistory.cpp index 75f97848c..697be4916 100644 --- a/src/libtomahawk/database/databasecommand_playbackhistory.cpp +++ b/src/libtomahawk/database/databasecommand_playbackhistory.cpp @@ -20,7 +20,8 @@ DatabaseCommand_PlaybackHistory::exec( DatabaseImpl* dbi ) QString sql = QString( "SELECT track, playtime, secs_played " "FROM playback_log " - "%1" ).arg( whereToken ); + "%1 " + "ORDER BY playtime DESC").arg( whereToken ); query.prepare( sql ); query.exec(); diff --git a/src/libtomahawk/result.h b/src/libtomahawk/result.h index ed6299c59..b10a65087 100644 --- a/src/libtomahawk/result.h +++ b/src/libtomahawk/result.h @@ -23,6 +23,7 @@ public: float score() const; RID id() const; + collection_ptr collection() const { return m_collection; } Tomahawk::artist_ptr artist() const { return m_artist; } diff --git a/src/libtomahawk/source.h b/src/libtomahawk/source.h index 58adb6071..70ff14bc0 100644 --- a/src/libtomahawk/source.h +++ b/src/libtomahawk/source.h @@ -29,7 +29,7 @@ public: bool isLocal() const { return m_isLocal; } bool isOnline() const { return m_online; } - const QString& userName() const { return m_username; } + QString userName() const { return m_username; } QString friendlyName() const; void setFriendlyName( const QString& fname ) { m_friendlyname = fname; } @@ -53,6 +53,9 @@ signals: void stats( const QVariantMap& ); void usernameChanged( const QString& ); + void playbackStarted( const Tomahawk::query_ptr& query ); + void playbackFinished( const Tomahawk::query_ptr& query ); + // this signal is emitted from DBSyncConnection: void loadingStateChanged( DBSyncConnection::State newstate, DBSyncConnection::State oldstate, const QString& info ); diff --git a/src/playlist/playlistmodel.cpp b/src/playlist/playlistmodel.cpp index 1ad542222..531948582 100644 --- a/src/playlist/playlistmodel.cpp +++ b/src/playlist/playlistmodel.cpp @@ -154,27 +154,50 @@ PlaylistModel::appendTrack( const Tomahawk::query_ptr& query ) } +void +PlaylistModel::insertTrack( unsigned int row, const Tomahawk::query_ptr& query ) +{ + if ( query.isNull() ) + return; + + QList< Tomahawk::query_ptr > ql; + ql << query; + + onTracksInserted( row, ql ); +} + + void PlaylistModel::onTracksAdded( const QList& tracks, const Tomahawk::collection_ptr& collection ) +{ + onTracksInserted( rowCount( QModelIndex() ), tracks, collection ); +} + + +void +PlaylistModel::onTracksInserted( unsigned int row, const QList& tracks, const Tomahawk::collection_ptr& collection ) { if ( !tracks.count() ) return; - int c = rowCount( QModelIndex() ); + int c = row; QPair< int, int > crows; crows.first = c; crows.second = c + tracks.count() - 1; emit beginInsertRows( QModelIndex(), crows.first, crows.second ); + int i = 0; PlItem* plitem; foreach( const query_ptr& query, tracks ) { plentry_ptr entry = plentry_ptr( new PlaylistEntry() ); entry->setQuery( query ); - plitem = new PlItem( entry, m_rootItem ); - plitem->index = createIndex( m_rootItem->children.count() - 1, 0, plitem ); + plitem = new PlItem( entry, m_rootItem, row + i ); + plitem->index = createIndex( row + i, 0, plitem ); + + i++; connect( plitem, SIGNAL( dataChanged() ), SLOT( onDataChanged() ) ); } diff --git a/src/playlist/playlistmodel.h b/src/playlist/playlistmodel.h index 1019d94de..015b05aeb 100644 --- a/src/playlist/playlistmodel.h +++ b/src/playlist/playlistmodel.h @@ -35,6 +35,7 @@ public: void loadHistory( const Tomahawk::source_ptr& source, unsigned int amount = 100 ); void appendTrack( const Tomahawk::query_ptr& query ); + void insertTrack( unsigned int row, const Tomahawk::query_ptr& query ); virtual void removeIndex( const QModelIndex& index, bool moreToCome = false ); @@ -54,6 +55,7 @@ private slots: void onPlaylistChanged( bool waitForUpdate = true ); void onTracksAdded( const QList& tracks, const Tomahawk::collection_ptr& collection = Tomahawk::collection_ptr() ); + void onTracksInserted( unsigned int row, const QList& tracks, const Tomahawk::collection_ptr& collection = Tomahawk::collection_ptr() ); private: QList playlistEntries() const; diff --git a/src/sourcetree/sourcetreeitemwidget.cpp b/src/sourcetree/sourcetreeitemwidget.cpp index edfffc93b..3bb46ba63 100644 --- a/src/sourcetree/sourcetreeitemwidget.cpp +++ b/src/sourcetree/sourcetreeitemwidget.cpp @@ -39,6 +39,8 @@ SourceTreeItemWidget::SourceTreeItemWidget( const source_ptr& source, QWidget* p connect( source.data(), SIGNAL( stats( QVariantMap ) ), SLOT( gotStats( QVariantMap ) ) ); + connect( source.data(), SIGNAL( playbackStarted( Tomahawk::query_ptr ) ), SLOT( onPlaybackStarted( Tomahawk::query_ptr ) ) ); + ui->avatarImage->setPixmap( QPixmap( RESPATH "images/user-avatar.png" ) ); displayname = source->friendlyName(); @@ -52,7 +54,9 @@ SourceTreeItemWidget::SourceTreeItemWidget( const source_ptr& source, QWidget* p } ui->nameLabel->setText( displayname ); + ui->activityLabel->setText( tr( "Idle" ) ); ui->infoLabel->setForegroundRole( QPalette::Dark ); + ui->activityLabel->setForegroundRole( QPalette::Dark ); connect( ui->onOffButton, SIGNAL( clicked() ), SIGNAL( clicked() ) ); connect( ui->infoButton, SIGNAL( clicked() ), SLOT( onInfoButtonClicked() ) ); @@ -124,6 +128,13 @@ SourceTreeItemWidget::onLoadingStateChanged( DBSyncConnection::State newstate, D } +void +SourceTreeItemWidget::onPlaybackStarted( const Tomahawk::query_ptr& query ) +{ + ui->activityLabel->setText( tr( "Playing: %1 by %2" ).arg( query->track() ).arg( query->artist() ) ); +} + + void SourceTreeItemWidget::onOnline() { diff --git a/src/sourcetree/sourcetreeitemwidget.h b/src/sourcetree/sourcetreeitemwidget.h index eae2c115e..6414521b5 100644 --- a/src/sourcetree/sourcetreeitemwidget.h +++ b/src/sourcetree/sourcetreeitemwidget.h @@ -32,6 +32,8 @@ private slots: void gotStats( const QVariantMap& stats ); void onLoadingStateChanged( DBSyncConnection::State newstate, DBSyncConnection::State oldstate, const QString& info ); + void onPlaybackStarted( const Tomahawk::query_ptr& query ); + void onInfoButtonClicked(); private: diff --git a/src/sourcetree/sourcetreeitemwidget.ui b/src/sourcetree/sourcetreeitemwidget.ui index 030f82753..3933cba59 100644 --- a/src/sourcetree/sourcetreeitemwidget.ui +++ b/src/sourcetree/sourcetreeitemwidget.ui @@ -7,7 +7,7 @@ 0 0 359 - 44 + 58 @@ -19,13 +19,13 @@ 0 - 44 + 58 16777215 - 44 + 58 @@ -103,14 +103,11 @@ 4 - - 0 - 4 - + 75 @@ -129,6 +126,13 @@ + + + + TextLabel + + + @@ -192,6 +196,11 @@ QPushButton
imagebutton.h
+ + ElidedLabel + QLabel +
elidedlabel.h
+
diff --git a/src/tomahawkapp.cpp b/src/tomahawkapp.cpp index 875ed2fcf..bfa94e4a4 100644 --- a/src/tomahawkapp.cpp +++ b/src/tomahawkapp.cpp @@ -265,6 +265,7 @@ TomahawkApp::registerMetaTypes() // Extra definition for namespaced-versions of signals/slots required qRegisterMetaType< Tomahawk::collection_ptr >("Tomahawk::collection_ptr"); qRegisterMetaType< Tomahawk::result_ptr >("Tomahawk::result_ptr"); + qRegisterMetaType< Tomahawk::query_ptr >("Tomahawk::query_ptr"); qRegisterMetaType< Tomahawk::source_ptr >("Tomahawk::source_ptr"); qRegisterMetaType< QList >("QList"); qRegisterMetaType< QList >("QList"); diff --git a/src/widgets/welcomewidget.cpp b/src/widgets/welcomewidget.cpp index dd9015044..bb49e2b2f 100644 --- a/src/widgets/welcomewidget.cpp +++ b/src/widgets/welcomewidget.cpp @@ -61,6 +61,15 @@ WelcomeWidget::onSourceAdded( const Tomahawk::source_ptr& source ) { connect( source->collection().data(), SIGNAL( playlistsAdded( QList ) ), SLOT( updatePlaylists() ) ); connect( source->collection().data(), SIGNAL( playlistsDeleted( QList ) ), SLOT( updatePlaylists() ) ); + + connect( source.data(), SIGNAL( playbackFinished( Tomahawk::query_ptr ) ), SLOT( onPlaybackFinished( Tomahawk::query_ptr ) ) ); +} + + +void +WelcomeWidget::onPlaybackFinished( const Tomahawk::query_ptr& query ) +{ + m_tracksModel->insertTrack( 0, query ); } diff --git a/src/widgets/welcomewidget.h b/src/widgets/welcomewidget.h index 6f8514c48..707c5945e 100644 --- a/src/widgets/welcomewidget.h +++ b/src/widgets/welcomewidget.h @@ -77,6 +77,7 @@ public slots: private slots: void onSourceAdded( const Tomahawk::source_ptr& source ); void onPlaylistActivated( QListWidgetItem* item ); + void onPlaybackFinished( const Tomahawk::query_ptr& query ); private: Ui::WelcomeWidget *ui;