mirror of
https://github.com/tomahawk-player/tomahawk.git
synced 2025-03-24 09:49:42 +01:00
Add the ability to listen along in real-time. Won't automatically switch
if you (currently, might need to tweak) have <= 6 seconds left of the current track...after a while if you get further behind it'll automatically correct. Can toggle via source context menu right now, need to work in an icon. If you pause the music, it turns off real-time if it's on.
This commit is contained in:
parent
7cd51a6108
commit
9242a7c942
@ -22,8 +22,7 @@
|
||||
#include "audio/audioengine.h"
|
||||
#include "database/database.h"
|
||||
|
||||
#include <QtCore/QStateMachine>
|
||||
#include <QtCore/QState>
|
||||
#include <QtGui/QAction>
|
||||
#include "sourcelist.h"
|
||||
#include "database/databasecommand_socialaction.h"
|
||||
#include "sourceplaylistinterface.h"
|
||||
@ -82,7 +81,9 @@ LatchManager::playlistChanged( Tomahawk::playlistinterface_ptr )
|
||||
cmd->setTimestamp( QDateTime::currentDateTime().toTime_t() );
|
||||
Database::instance()->enqueue( QSharedPointer< DatabaseCommand >( cmd ) );
|
||||
|
||||
ActionCollection::instance()->getAction( "latchOn" )->setText( tr( "&Catch Up" ) );
|
||||
QAction *latchOnAction = ActionCollection::instance()->getAction( "latchOn" );
|
||||
latchOnAction->setText( tr( "&Catch Up" ) );
|
||||
latchOnAction->setIcon( QIcon() );
|
||||
|
||||
// If not, then keep waiting
|
||||
return;
|
||||
@ -117,7 +118,9 @@ LatchManager::playlistChanged( Tomahawk::playlistinterface_ptr )
|
||||
|
||||
m_state = NotLatched;
|
||||
|
||||
ActionCollection::instance()->getAction( "latchOn" )->setText( tr( "&Listen Along" ) );
|
||||
QAction *latchOnAction = ActionCollection::instance()->getAction( "latchOn" );
|
||||
latchOnAction->setText( tr( "&Listen Along" ) );
|
||||
latchOnAction->setIcon( QIcon( RESPATH "images/headphones-sidebar.png" ) );
|
||||
}
|
||||
|
||||
|
||||
@ -128,6 +131,7 @@ LatchManager::catchUpRequest()
|
||||
AudioEngine::instance()->next();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
LatchManager::unlatchRequest( const source_ptr& source )
|
||||
{
|
||||
@ -135,5 +139,19 @@ LatchManager::unlatchRequest( const source_ptr& source )
|
||||
AudioEngine::instance()->stop();
|
||||
AudioEngine::instance()->setPlaylist( Tomahawk::playlistinterface_ptr() );
|
||||
|
||||
ActionCollection::instance()->getAction( "latchOn" )->setText( tr( "&Listen Along" ) );
|
||||
QAction *latchOnAction = ActionCollection::instance()->getAction( "latchOn" );
|
||||
latchOnAction->setText( tr( "&Listen Along" ) );
|
||||
latchOnAction->setIcon( QIcon( RESPATH "images/headphones-sidebar.png" ) );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
LatchManager::latchModeChangeRequest( const Tomahawk::source_ptr& source, bool realtime )
|
||||
{
|
||||
if ( !isLatched( source ) )
|
||||
return;
|
||||
|
||||
source->getPlaylistInterface()->setLatchMode( realtime ? Tomahawk::PlaylistInterface::RealTime : Tomahawk::PlaylistInterface::StayOnSong );
|
||||
if ( realtime )
|
||||
catchUpRequest();
|
||||
}
|
||||
|
@ -43,6 +43,7 @@ public slots:
|
||||
void latchRequest( const Tomahawk::source_ptr& source );
|
||||
void unlatchRequest( const Tomahawk::source_ptr& source );
|
||||
void catchUpRequest();
|
||||
void latchModeChangeRequest( const Tomahawk::source_ptr& source, bool realtime );
|
||||
|
||||
private slots:
|
||||
void playlistChanged( Tomahawk::playlistinterface_ptr );
|
||||
|
@ -46,6 +46,10 @@ ActionCollection::initActions()
|
||||
latchOff->setIcon( QIcon( RESPATH "images/headphones-off.png" ) );
|
||||
m_actionCollection[ "latchOff" ] = latchOff;
|
||||
|
||||
QAction *realtimeFollowingAlong = new QAction( tr( "&Follow in real-time" ), this );
|
||||
realtimeFollowingAlong->setCheckable( true );
|
||||
m_actionCollection[ "realtimeFollowingAlong" ] = realtimeFollowingAlong;
|
||||
|
||||
bool isPublic = TomahawkSettings::instance()->privateListeningMode() == TomahawkSettings::PublicListening;
|
||||
QAction *privacyToggle = new QAction( ( isPublic ? tr( "&Listen Privately" ) : tr( "&Listen Publicly" ) ), this );
|
||||
privacyToggle->setIcon( QIcon( RESPATH "images/private-listening.png" ) );
|
||||
|
@ -21,7 +21,7 @@
|
||||
|
||||
#include "dllmacro.h"
|
||||
|
||||
#include <QAction>
|
||||
#include <QtGui/QAction>
|
||||
|
||||
class DLLEXPORT ActionCollection : public QObject
|
||||
{
|
||||
|
@ -228,12 +228,12 @@ AudioEngine::canGoNext()
|
||||
m_playlist.data()->skipRestrictions() == PlaylistInterface::NoSkipForwards )
|
||||
return false;
|
||||
|
||||
if ( !m_currentTrack.isNull() && !m_playlist.data()->hasNextItem() &&
|
||||
( m_playlist.data()->currentItem().isNull() || ( m_currentTrack->id() == m_playlist.data()->currentItem()->id() ) ) )
|
||||
if ( !m_currentTrack.isNull() && !m_playlist->hasNextItem() &&
|
||||
( m_playlist->currentItem().isNull() || ( m_currentTrack->id() == m_playlist->currentItem()->id() ) ) )
|
||||
{
|
||||
//For instance, when doing a catch-up while listening along, but the person
|
||||
//you're following hasn't started a new track yet...don't do anything
|
||||
tDebug( LOGEXTRA ) << Q_FUNC_INFO << "catch up";
|
||||
tDebug( LOGEXTRA ) << Q_FUNC_INFO << "catch up, but same track or can't move on because don't have next track or it wasn't resolved";
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -580,6 +580,14 @@ AudioEngine::playItem( Tomahawk::playlistinterface_ptr playlist, const Tomahawk:
|
||||
void
|
||||
AudioEngine::playlistNextTrackReady()
|
||||
{
|
||||
// If in real-time and you have a few seconds left, you're probably lagging -- finish it up
|
||||
if ( m_playlist && m_playlist->latchMode() == PlaylistInterface::RealTime && ( m_waitingOnNewTrack || m_currentTrack.isNull() || m_currentTrack->id() == 0 || ( currentTrackTotalTime() - currentTime() > 6000 ) ) )
|
||||
{
|
||||
m_waitingOnNewTrack = false;
|
||||
loadNextTrack();
|
||||
return;
|
||||
}
|
||||
|
||||
if ( !m_waitingOnNewTrack )
|
||||
return;
|
||||
|
||||
|
@ -24,6 +24,7 @@ using namespace Tomahawk;
|
||||
|
||||
PlaylistInterface::PlaylistInterface ()
|
||||
: QObject()
|
||||
, m_latchMode( StayOnSong )
|
||||
{
|
||||
qRegisterMetaType<Tomahawk::PlaylistInterface::RepeatMode>( "Tomahawk::PlaylistInterface::RepeatMode" );
|
||||
}
|
||||
|
@ -39,6 +39,7 @@ public:
|
||||
enum SeekRestrictions { NoSeekRestrictions, NoSeek };
|
||||
enum SkipRestrictions { NoSkipRestrictions, NoSkipForwards, NoSkipBackwards, NoSkip };
|
||||
enum RetryMode { NoRetry, Retry };
|
||||
enum LatchMode { StayOnSong, RealTime };
|
||||
|
||||
explicit PlaylistInterface();
|
||||
virtual ~PlaylistInterface();
|
||||
@ -55,14 +56,20 @@ public:
|
||||
virtual Tomahawk::result_ptr siblingItem( int itemsAway ) = 0;
|
||||
|
||||
virtual PlaylistInterface::RepeatMode repeatMode() const = 0;
|
||||
|
||||
virtual bool shuffled() const = 0;
|
||||
|
||||
virtual PlaylistInterface::ViewMode viewMode() const { return Unknown; }
|
||||
|
||||
virtual PlaylistInterface::SeekRestrictions seekRestrictions() const { return NoSeekRestrictions; }
|
||||
virtual PlaylistInterface::SkipRestrictions skipRestrictions() const { return NoSkipRestrictions; }
|
||||
|
||||
virtual PlaylistInterface::RetryMode retryMode() const { return NoRetry; }
|
||||
virtual quint32 retryInterval() const { return 30000; }
|
||||
|
||||
virtual PlaylistInterface::LatchMode latchMode() const { return m_latchMode; }
|
||||
virtual void setLatchMode( PlaylistInterface::LatchMode latchMode ) { m_latchMode = latchMode; }
|
||||
|
||||
virtual QString filter() const { return m_filter; }
|
||||
virtual void setFilter( const QString& pattern ) { m_filter = pattern; }
|
||||
|
||||
@ -84,6 +91,9 @@ signals:
|
||||
void sourceTrackCountChanged( unsigned int tracks );
|
||||
void nextTrackReady();
|
||||
|
||||
protected:
|
||||
LatchMode m_latchMode;
|
||||
|
||||
private:
|
||||
Q_DISABLE_COPY( PlaylistInterface )
|
||||
|
||||
|
@ -20,20 +20,26 @@
|
||||
|
||||
#include "source.h"
|
||||
#include "pipeline.h"
|
||||
#include "audio/audioengine.h"
|
||||
|
||||
#include "utils/logger.h"
|
||||
|
||||
using namespace Tomahawk;
|
||||
|
||||
|
||||
SourcePlaylistInterface::SourcePlaylistInterface( Tomahawk::Source *source )
|
||||
SourcePlaylistInterface::SourcePlaylistInterface( Tomahawk::Source *source, Tomahawk::PlaylistInterface::LatchMode latchMode )
|
||||
: PlaylistInterface()
|
||||
, m_source( source )
|
||||
, m_currentItem( 0 )
|
||||
, m_gotNextItem( false )
|
||||
{
|
||||
setLatchMode( latchMode );
|
||||
|
||||
if ( !m_source.isNull() )
|
||||
connect( m_source.data(), SIGNAL( playbackStarted( const Tomahawk::query_ptr& ) ), SLOT( onSourcePlaybackStarted( const Tomahawk::query_ptr& ) ) );
|
||||
|
||||
if ( AudioEngine::instance() )
|
||||
connect( AudioEngine::instance(), SIGNAL( paused() ), SLOT( audioPaused() ) );
|
||||
}
|
||||
|
||||
|
||||
@ -95,7 +101,7 @@ QList<Tomahawk::query_ptr>
|
||||
SourcePlaylistInterface::tracks()
|
||||
{
|
||||
QList<Tomahawk::query_ptr> tracks;
|
||||
return tracks; // FIXME
|
||||
return tracks; // FIXME (with what?)
|
||||
}
|
||||
|
||||
|
||||
|
@ -35,7 +35,7 @@ class DLLEXPORT SourcePlaylistInterface : public Tomahawk::PlaylistInterface
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
SourcePlaylistInterface( Tomahawk::Source *source );
|
||||
SourcePlaylistInterface( Tomahawk::Source *source, Tomahawk::PlaylistInterface::LatchMode latchMode = PlaylistInterface::RealTime );
|
||||
virtual ~SourcePlaylistInterface();
|
||||
|
||||
QList<Tomahawk::query_ptr> tracks();
|
||||
@ -64,6 +64,7 @@ public:
|
||||
public slots:
|
||||
virtual void setRepeatMode( PlaylistInterface::RepeatMode ) {}
|
||||
virtual void setShuffled( bool ) {}
|
||||
virtual void audioPaused() { setLatchMode( PlaylistInterface::StayOnSong ); }
|
||||
|
||||
private slots:
|
||||
void onSourcePlaybackStarted( const Tomahawk::query_ptr& query );
|
||||
|
@ -118,6 +118,7 @@ SourceTreeView::SourceTreeView( QWidget* parent )
|
||||
connect( this, SIGNAL( latchRequest( Tomahawk::source_ptr ) ), m_latchManager, SLOT( latchRequest( Tomahawk::source_ptr ) ) );
|
||||
connect( this, SIGNAL( unlatchRequest( Tomahawk::source_ptr ) ), m_latchManager, SLOT( unlatchRequest( Tomahawk::source_ptr ) ) );
|
||||
connect( this, SIGNAL( catchUpRequest() ), m_latchManager, SLOT( catchUpRequest() ) );
|
||||
connect( this, SIGNAL( latchModeChangeRequest( Tomahawk::source_ptr, bool ) ), m_latchManager, SLOT( latchModeChangeRequest( Tomahawk::source_ptr, bool ) ) );
|
||||
|
||||
connect( ActionCollection::instance(), SIGNAL( privacyModeChanged() ), SLOT( repaint() ) );
|
||||
}
|
||||
@ -162,10 +163,14 @@ SourceTreeView::setupMenus()
|
||||
{
|
||||
if ( m_latchManager->isLatched( source ) )
|
||||
{
|
||||
m_latchMenu.addSeparator();
|
||||
QAction *latchOffAction = ActionCollection::instance()->getAction( "latchOff" );
|
||||
m_latchMenu.addAction( latchOffAction );
|
||||
connect( latchOffAction, SIGNAL( triggered() ), SLOT( latchOff() ), Qt::QueuedConnection );
|
||||
connect( latchOffAction, SIGNAL( triggered() ), SLOT( latchOff() ) );
|
||||
m_latchMenu.addSeparator();
|
||||
QAction *latchRealtimeAction = ActionCollection::instance()->getAction( "realtimeFollowingAlong" );
|
||||
latchRealtimeAction->setChecked( source->getPlaylistInterface()->latchMode() == Tomahawk::PlaylistInterface::RealTime );
|
||||
m_latchMenu.addAction( latchRealtimeAction );
|
||||
connect( latchRealtimeAction, SIGNAL( toggled( bool ) ), SLOT( latchModeToggled( bool ) ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -416,6 +421,24 @@ SourceTreeView::latchOff( const Tomahawk::source_ptr& source )
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SourceTreeView::latchModeToggled( bool checked )
|
||||
{
|
||||
|
||||
disconnect( this, SLOT( latchOff() ) );
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
if ( !m_contextMenuIndex.isValid() )
|
||||
return;
|
||||
|
||||
SourcesModel::RowType type = ( SourcesModel::RowType )model()->data( m_contextMenuIndex, SourcesModel::SourceTreeItemTypeRole ).toInt();
|
||||
if( type != SourcesModel::Collection )
|
||||
return;
|
||||
|
||||
const SourceItem* item = itemFromIndex< SourceItem >( m_contextMenuIndex );
|
||||
const source_ptr source = item->source();
|
||||
emit latchModeChangeRequest( source, checked );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SourceTreeView::renamePlaylist()
|
||||
|
@ -58,6 +58,7 @@ signals:
|
||||
void latchRequest( const Tomahawk::source_ptr& source );
|
||||
void unlatchRequest( const Tomahawk::source_ptr& source );
|
||||
void catchUpRequest();
|
||||
void latchModeChangeRequest( const Tomahawk::source_ptr& source, bool realtime );
|
||||
|
||||
private slots:
|
||||
void onItemExpanded( const QModelIndex& idx );
|
||||
@ -75,6 +76,7 @@ private slots:
|
||||
void latchOff();
|
||||
void latchOnOrCatchUp( const Tomahawk::source_ptr& source );
|
||||
void latchOff( const Tomahawk::source_ptr& source );
|
||||
void latchModeToggled( bool checked );
|
||||
|
||||
void onCustomContextMenu( const QPoint& pos );
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user