1
0
mirror of https://github.com/tomahawk-player/tomahawk.git synced 2025-08-06 06:07:37 +02:00

Listen along -- fix bug where catching up to the same track would stop audio. Also allow option to stop listening.

This commit is contained in:
Jeff Mitchell
2011-06-18 11:12:34 -04:00
parent 0abb46f3e6
commit c760d26b68
5 changed files with 114 additions and 31 deletions

View File

@@ -111,14 +111,14 @@ AudioEngine::play()
{
m_mediaObject->play();
emit resumed();
Tomahawk::InfoSystem::InfoCriteriaHash trackInfo;
Tomahawk::InfoSystem::InfoCriteriaHash trackInfo;
trackInfo["title"] = m_currentTrack->track();
trackInfo["artist"] = m_currentTrack->artist()->name();
trackInfo["album"] = m_currentTrack->album()->name();
Tomahawk::InfoSystem::InfoSystem::instance()->pushInfo(
s_aeInfoIdentifier, Tomahawk::InfoSystem::InfoNowResumed,
QVariant::fromValue< Tomahawk::InfoSystem::InfoCriteriaHash >( trackInfo ) );
trackInfo["title"] = m_currentTrack->track();
trackInfo["artist"] = m_currentTrack->artist()->name();
trackInfo["album"] = m_currentTrack->album()->name();
Tomahawk::InfoSystem::InfoSystem::instance()->pushInfo(
s_aeInfoIdentifier, Tomahawk::InfoSystem::InfoNowResumed,
QVariant::fromValue< Tomahawk::InfoSystem::InfoCriteriaHash >( trackInfo ) );
}
else
loadNextTrack();
@@ -143,7 +143,8 @@ AudioEngine::stop()
qDebug() << Q_FUNC_INFO;
m_mediaObject->stop();
m_retryTimer.stop();
setCurrentTrack( Tomahawk::result_ptr() );
emit stopped();
Tomahawk::InfoSystem::InfoSystem::instance()->pushInfo(
@@ -155,6 +156,10 @@ void
AudioEngine::previous()
{
qDebug() << Q_FUNC_INFO;
if ( !m_playlist )
return;
if ( m_playlist->skipRestrictions() == PlaylistInterface::NoSkip ||
m_playlist->skipRestrictions() == PlaylistInterface::NoSkipBackwards )
return;
@@ -167,6 +172,10 @@ void
AudioEngine::next()
{
qDebug() << Q_FUNC_INFO;
if ( !m_playlist )
return;
if ( m_playlist->skipRestrictions() == PlaylistInterface::NoSkip ||
m_playlist->skipRestrictions() == PlaylistInterface::NoSkipForwards )
return;
@@ -178,6 +187,9 @@ AudioEngine::next()
void
AudioEngine::seek( int ms )
{
if ( !m_playlist )
return;
if ( m_playlist->seekRestrictions() == PlaylistInterface::NoSeek )
return;
@@ -345,7 +357,7 @@ AudioEngine::loadNextTrack()
else
{
stop();
if ( m_playlist->retryMode() == Tomahawk::PlaylistInterface::Retry )
if ( m_playlist && m_playlist->retryMode() == Tomahawk::PlaylistInterface::Retry )
{
m_retryTimer.setInterval( m_playlist->retryInterval() );
m_retryTimer.start();

View File

@@ -28,6 +28,7 @@ using namespace Tomahawk;
SourcePlaylistInterface::SourcePlaylistInterface( Tomahawk::source_ptr& source )
: PlaylistInterface( this )
, m_source( source )
, m_currentItem( 0 )
, m_gotNextSong( false )
{
connect( source.data(), SIGNAL( playbackStarted( const Tomahawk::query_ptr& ) ), SLOT( onSourcePlaybackStarted( const Tomahawk::query_ptr& ) ) );
@@ -39,15 +40,21 @@ SourcePlaylistInterface::siblingItem( int itemsAway )
{
Q_UNUSED( itemsAway );
qDebug() << Q_FUNC_INFO;
if ( !m_gotNextSong || m_source.isNull() || m_source->currentTrack().isNull() || m_source->currentTrack()->results().isEmpty() )
if ( m_source.isNull() || m_source->currentTrack().isNull() || m_source->currentTrack()->results().isEmpty() )
{
qDebug() << Q_FUNC_INFO << " Results were empty for current track or source no longer valid";
m_currentItem = Tomahawk::result_ptr();
return m_currentItem;
}
else if ( !m_gotNextSong )
{
qDebug() << Q_FUNC_INFO << " This song was already fetched";
return Tomahawk::result_ptr();
}
m_gotNextSong = false;
return m_source->currentTrack()->results().first();
m_currentItem = m_source->currentTrack()->results().first();
return m_currentItem;
}
@@ -55,15 +62,21 @@ Tomahawk::result_ptr
SourcePlaylistInterface::nextItem()
{
qDebug() << Q_FUNC_INFO;
if ( !m_gotNextSong || m_source.isNull() || m_source->currentTrack().isNull() || m_source->currentTrack()->results().isEmpty() )
if ( m_source.isNull() || m_source->currentTrack().isNull() || m_source->currentTrack()->results().isEmpty() )
{
qDebug() << Q_FUNC_INFO << " Results were empty for current track or source no longer valid";
m_currentItem = Tomahawk::result_ptr();
return m_currentItem;
}
else if ( !m_gotNextSong )
{
qDebug() << Q_FUNC_INFO << " This song was already fetched";
return Tomahawk::result_ptr();
}
m_gotNextSong = false;
return m_source->currentTrack()->results().first();
m_currentItem = m_source->currentTrack()->results().first();
return m_currentItem;
}
@@ -74,6 +87,16 @@ SourcePlaylistInterface::tracks()
}
void
SourcePlaylistInterface::reset()
{
if ( !m_currentItem.isNull() )
m_gotNextSong = true;
else
m_gotNextSong = false;
}
void
SourcePlaylistInterface::onSourcePlaybackStarted( const Tomahawk::query_ptr& query )
{

View File

@@ -45,6 +45,7 @@ public:
virtual Tomahawk::result_ptr siblingItem( int itemsAway );
virtual Tomahawk::result_ptr nextItem();
virtual Tomahawk::result_ptr currentItem() { return m_currentItem; }
virtual PlaylistInterface::RepeatMode repeatMode() const { return PlaylistInterface::NoRepeat; }
virtual PlaylistInterface::SeekRestrictions seekRestrictions() const { return PlaylistInterface::NoSeek; }
@@ -57,6 +58,8 @@ public:
virtual Tomahawk::source_ptr source() const { return m_source; }
virtual void reset();
public slots:
virtual void setRepeatMode( PlaylistInterface::RepeatMode ) {}
virtual void setShuffled( bool ) {}
@@ -74,6 +77,7 @@ private slots:
private:
Tomahawk::source_ptr m_source;
Tomahawk::result_ptr m_currentItem;
bool m_gotNextSong;
};

View File

@@ -127,7 +127,7 @@ SourceTreeView::setupMenus()
{
m_playlistMenu.clear();
m_roPlaylistMenu.clear();
m_followMenu.clear();
m_latchMenu.clear();
bool readonly = true;
SourcesModel::RowType type = ( SourcesModel::RowType )model()->data( m_contextMenuIndex, SourcesModel::SourceTreeItemTypeRole ).toInt();
@@ -142,6 +142,8 @@ SourceTreeView::setupMenus()
}
}
m_latchOnAction = m_latchMenu.addAction( tr( "&Listen Along" ) );
if ( type == SourcesModel::Collection )
{
CollectionItem* item = itemFromIndex< CollectionItem >( m_contextMenuIndex );
@@ -153,12 +155,13 @@ SourceTreeView::setupMenus()
{
SourcePlaylistInterface* sourcepi = dynamic_cast< SourcePlaylistInterface* >( pi );
if ( !sourcepi->source().isNull() && sourcepi->source()->id() == source->id() )
m_followAction = m_followMenu.addAction( tr( "&Catch Up" ) );
else
m_followAction = m_followMenu.addAction( tr( "&Listen Along" ) );
{
m_latchOnAction->setText( tr( "&Catch Up" ) );
m_latchMenu.addSeparator();
m_latchOffAction = m_latchMenu.addAction( tr( "&Stop Listening Along" ) );
connect( m_latchOffAction, SIGNAL( triggered() ), SLOT( latchOff() ) );
}
}
else
m_followAction = m_followMenu.addAction( tr( "&Listen Along" ) );
}
}
@@ -192,7 +195,7 @@ SourceTreeView::setupMenus()
connect( m_deletePlaylistAction, SIGNAL( triggered() ), SLOT( deletePlaylist() ) );
connect( m_copyPlaylistAction, SIGNAL( triggered() ), SLOT( copyPlaylistLink() ) );
connect( m_addToLocalAction, SIGNAL( triggered() ), SLOT( addToLocal() ) );
connect( m_followAction, SIGNAL( triggered() ), SLOT( follow() ) );
connect( m_latchOnAction, SIGNAL( triggered() ), SLOT( latchOn() ) );
}
@@ -329,7 +332,7 @@ void SourceTreeView::addToLocal()
void
SourceTreeView::follow()
SourceTreeView::latchOn()
{
qDebug() << Q_FUNC_INFO;
QModelIndex idx = m_contextMenuIndex;
@@ -337,12 +340,51 @@ SourceTreeView::follow()
return;
SourcesModel::RowType type = ( SourcesModel::RowType )model()->data( m_contextMenuIndex, SourcesModel::SourceTreeItemTypeRole ).toInt();
if( type == SourcesModel::Collection )
if( type != SourcesModel::Collection )
return;
CollectionItem* item = itemFromIndex< CollectionItem >( m_contextMenuIndex );
source_ptr source = item->source();
PlaylistInterface* pi = AudioEngine::instance()->playlist();
if ( pi && dynamic_cast< SourcePlaylistInterface* >( pi ) )
{
CollectionItem* item = itemFromIndex< CollectionItem >( m_contextMenuIndex );
source_ptr source = item->source();
AudioEngine::instance()->playItem( source->getPlaylistInterface().data(), source->getPlaylistInterface()->nextItem() );
SourcePlaylistInterface* sourcepi = dynamic_cast< SourcePlaylistInterface* >( pi );
if ( !sourcepi->source().isNull() && sourcepi->source()->id() == source->id() )
{
//it's a catch-up -- if they're trying to catch-up in the same track, don't do anything
//so that you don't repeat the track and/or cause the retry timer to fire
if ( !AudioEngine::instance()->currentTrack().isNull() &&
AudioEngine::instance()->currentTrack()->id() == sourcepi->currentItem()->id() )
return;
}
}
AudioEngine::instance()->playItem( source->getPlaylistInterface().data(), source->getPlaylistInterface()->nextItem() );
}
void
SourceTreeView::latchOff()
{
qDebug() << Q_FUNC_INFO;
QModelIndex idx = m_contextMenuIndex;
if ( !idx.isValid() )
return;
SourcesModel::RowType type = ( SourcesModel::RowType )model()->data( m_contextMenuIndex, SourcesModel::SourceTreeItemTypeRole ).toInt();
if( type != SourcesModel::Collection )
return;
PlaylistInterface* pi = AudioEngine::instance()->playlist();
if ( pi && dynamic_cast< SourcePlaylistInterface* >( pi ) )
{
SourcePlaylistInterface* sourcepi = dynamic_cast< SourcePlaylistInterface* >( pi );
sourcepi->reset();
}
AudioEngine::instance()->stop();
AudioEngine::instance()->setPlaylist( 0 );
}
@@ -381,7 +423,7 @@ SourceTreeView::onCustomContextMenu( const QPoint& pos )
{
CollectionItem* item = itemFromIndex< CollectionItem >( m_contextMenuIndex );
if ( !item->source()->isLocal() )
m_followMenu.exec( mapToGlobal( pos ) );
m_latchMenu.exec( mapToGlobal( pos ) );
}
}

View File

@@ -56,7 +56,8 @@ private slots:
void copyPlaylistLink();
void addToLocal();
void follow();
void latchOn();
void latchOff();
void onCustomContextMenu( const QPoint& pos );
protected:
@@ -83,13 +84,14 @@ private:
QMenu m_playlistMenu;
QMenu m_roPlaylistMenu;
QMenu m_followMenu;
QMenu m_latchMenu;
QAction* m_loadPlaylistAction;
QAction* m_renamePlaylistAction;
QAction* m_deletePlaylistAction;
QAction* m_copyPlaylistAction;
QAction* m_addToLocalAction;
QAction* m_followAction;
QAction* m_latchOnAction;
QAction* m_latchOffAction;
bool m_dragging;
QRect m_dropRect;