mirror of
https://github.com/tomahawk-player/tomahawk.git
synced 2025-03-20 07:49:42 +01:00
Refactor latching into it's own manager for easier handling, and clean up some corner cases
This commit is contained in:
parent
b83e9bbf82
commit
66581fcaa2
@ -33,6 +33,7 @@ set( libSources
|
||||
contextmenu.cpp
|
||||
dropjob.cpp
|
||||
playlistinterface.cpp
|
||||
LatchManager.cpp
|
||||
|
||||
sip/SipPlugin.cpp
|
||||
sip/SipHandler.cpp
|
||||
@ -246,6 +247,7 @@ set( libHeaders
|
||||
contextmenu.h
|
||||
dropjob.h
|
||||
AtticaManager.h
|
||||
LatchManager.h
|
||||
|
||||
artist.h
|
||||
album.h
|
||||
|
144
src/libtomahawk/LatchManager.cpp
Normal file
144
src/libtomahawk/LatchManager.cpp
Normal file
@ -0,0 +1,144 @@
|
||||
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
||||
*
|
||||
* Copyright 2010-2011, Leo Franchi <lfranchi@kde.org>
|
||||
*
|
||||
* Tomahawk is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Tomahawk is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "LatchManager.h"
|
||||
|
||||
#include "audio/audioengine.h"
|
||||
#include "database/database.h"
|
||||
|
||||
#include <QtCore/QStateMachine>
|
||||
#include <QtCore/QState>
|
||||
#include "sourcelist.h"
|
||||
#include "database/databasecommand_socialaction.h"
|
||||
#include "sourceplaylistinterface.h"
|
||||
|
||||
using namespace Tomahawk;
|
||||
|
||||
LatchManager::LatchManager( QObject* parent )
|
||||
: QObject( parent )
|
||||
, m_state( NotLatched )
|
||||
{
|
||||
|
||||
connect( AudioEngine::instance(), SIGNAL( playlistChanged( Tomahawk::PlaylistInterface* ) ), this, SLOT( playlistChanged( Tomahawk::PlaylistInterface* ) ) );
|
||||
connect( AudioEngine::instance(), SIGNAL( stopped() ), this, SLOT( playlistChanged() ) );
|
||||
}
|
||||
|
||||
LatchManager::~LatchManager()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
bool
|
||||
LatchManager::isLatched( const source_ptr& src )
|
||||
{
|
||||
return m_state == Latched && m_latchedOnTo == src;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
LatchManager::latchRequest( const source_ptr& source )
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
if ( isLatched( source ) )
|
||||
return;
|
||||
|
||||
m_state = Latching;
|
||||
m_waitingForLatch = source;
|
||||
AudioEngine::instance()->playItem( source->getPlaylistInterface().data(), source->getPlaylistInterface()->nextItem() );
|
||||
}
|
||||
|
||||
void
|
||||
LatchManager::playlistChanged( PlaylistInterface* )
|
||||
{
|
||||
// If we were latched on and changed, send the listening along stop
|
||||
if ( m_latchedOnTo.isNull() )
|
||||
{
|
||||
if ( m_waitingForLatch.isNull() )
|
||||
return; // Neither latched on nor waiting to be latched on, no-op
|
||||
|
||||
m_latchedOnTo = m_waitingForLatch;
|
||||
m_latchedInterface = m_waitingForLatch->getPlaylistInterface();
|
||||
m_waitingForLatch.clear();
|
||||
m_state = Latched;
|
||||
|
||||
DatabaseCommand_SocialAction* cmd = new DatabaseCommand_SocialAction();
|
||||
cmd->setSource( SourceList::instance()->getLocal() );
|
||||
cmd->setAction( "latchOn");
|
||||
cmd->setComment( m_latchedOnTo->userName() );
|
||||
cmd->setTimestamp( QDateTime::currentDateTime().toTime_t() );
|
||||
Database::instance()->enqueue( QSharedPointer< DatabaseCommand >( cmd ) );
|
||||
|
||||
// If not, then keep waiting
|
||||
return;
|
||||
}
|
||||
|
||||
// We're current latched, and the user changed playlist, so stop
|
||||
const PlaylistInterface* pi = AudioEngine::instance()->playlist();
|
||||
bool listeningAlong = false;
|
||||
source_ptr newSource;
|
||||
|
||||
if ( pi && dynamic_cast< const SourcePlaylistInterface* >( pi ) )
|
||||
{
|
||||
// Check if we're listening along to someone, to make sure it's not the same person
|
||||
const SourcePlaylistInterface* sourcepi = dynamic_cast< const SourcePlaylistInterface* >( pi );
|
||||
if ( !AudioEngine::instance()->state() == AudioEngine::Stopped )
|
||||
{
|
||||
listeningAlong = true;
|
||||
newSource = sourcepi->source();
|
||||
}
|
||||
}
|
||||
|
||||
SourcePlaylistInterface* origsourcepi = dynamic_cast< SourcePlaylistInterface* >( m_latchedInterface.data() );
|
||||
Q_ASSERT( origsourcepi );
|
||||
const source_ptr source = origsourcepi->source();
|
||||
|
||||
// if we're currently listening along to the same source, no change
|
||||
if ( listeningAlong && ( !origsourcepi->source().isNull() && origsourcepi->source()->id() == newSource->id() ) )
|
||||
return;
|
||||
|
||||
DatabaseCommand_SocialAction* cmd = new DatabaseCommand_SocialAction();
|
||||
cmd->setSource( SourceList::instance()->getLocal() );
|
||||
cmd->setAction( "latchOff");
|
||||
cmd->setComment( source->userName() );
|
||||
cmd->setTimestamp( QDateTime::currentDateTime().toTime_t() );
|
||||
Database::instance()->enqueue( QSharedPointer< DatabaseCommand >( cmd ) );
|
||||
|
||||
m_latchedOnTo.clear();
|
||||
m_waitingForLatch.clear();
|
||||
m_latchedInterface.clear();
|
||||
|
||||
m_state = NotLatched;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
LatchManager::catchUpRequest()
|
||||
{
|
||||
//it's a catch-up -- logic in audioengine should take care of it
|
||||
AudioEngine::instance()->next();
|
||||
}
|
||||
|
||||
void
|
||||
LatchManager::unlatchRequest( const source_ptr& source )
|
||||
{
|
||||
AudioEngine::instance()->playItem( source->getPlaylistInterface().data(), source->getPlaylistInterface()->nextItem() );
|
||||
|
||||
|
||||
AudioEngine::instance()->stop();
|
||||
AudioEngine::instance()->setPlaylist( 0 );
|
||||
}
|
65
src/libtomahawk/LatchManager.h
Normal file
65
src/libtomahawk/LatchManager.h
Normal file
@ -0,0 +1,65 @@
|
||||
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
||||
*
|
||||
* Copyright 2010-2011, Leo Franchi <lfranchi@kde.org>
|
||||
*
|
||||
* Tomahawk is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Tomahawk is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef LATCHMANAGER_H
|
||||
#define LATCHMANAGER_H
|
||||
|
||||
#include "dllmacro.h"
|
||||
#include "source.h"
|
||||
|
||||
#include <QtCore/QObject>
|
||||
|
||||
class QState;
|
||||
class QStateMachine;
|
||||
|
||||
namespace Tomahawk
|
||||
{
|
||||
|
||||
class DLLEXPORT LatchManager : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit LatchManager( QObject* parent = 0 );
|
||||
virtual ~LatchManager();
|
||||
|
||||
bool isLatched( const source_ptr& src );
|
||||
|
||||
public slots:
|
||||
void latchRequest( const Tomahawk::source_ptr& source );
|
||||
void unlatchRequest( const Tomahawk::source_ptr& source );
|
||||
void catchUpRequest();
|
||||
|
||||
private slots:
|
||||
|
||||
void playlistChanged( Tomahawk::PlaylistInterface* );
|
||||
private:
|
||||
enum State {
|
||||
NotLatched = 0,
|
||||
Latching,
|
||||
Latched
|
||||
};
|
||||
|
||||
State m_state;
|
||||
source_ptr m_latchedOnTo;
|
||||
source_ptr m_waitingForLatch;
|
||||
playlistinterface_ptr m_latchedInterface;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // LATCHMANAGER_H
|
@ -561,7 +561,10 @@ AudioEngine::playItem( Tomahawk::PlaylistInterface* playlist, const Tomahawk::re
|
||||
else if ( !m_playlist.isNull() && m_playlist.data()->retryMode() == PlaylistInterface::Retry )
|
||||
{
|
||||
m_waitingOnNewTrack = true;
|
||||
stop();
|
||||
if ( isStopped() )
|
||||
sendWaitingNotification();
|
||||
else
|
||||
stop();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -43,14 +43,16 @@
|
||||
#include "utils/logger.h"
|
||||
#include "items/genericpageitems.h"
|
||||
#include "items/temporarypageitem.h"
|
||||
#include <database/databasecommand_socialaction.h>
|
||||
#include <database/database.h>
|
||||
#include "database/databasecommand_socialaction.h"
|
||||
#include "database/database.h"
|
||||
#include "LatchManager.h"
|
||||
|
||||
using namespace Tomahawk;
|
||||
|
||||
|
||||
SourceTreeView::SourceTreeView( QWidget* parent )
|
||||
: QTreeView( parent )
|
||||
, m_latchManager( new LatchManager( this ) )
|
||||
, m_dragging( false )
|
||||
{
|
||||
setFrameShape( QFrame::NoFrame );
|
||||
@ -78,8 +80,8 @@ SourceTreeView::SourceTreeView( QWidget* parent )
|
||||
// setAnimated( true );
|
||||
|
||||
m_delegate = new SourceDelegate( this );
|
||||
connect( m_delegate, SIGNAL( latchOn( Tomahawk::source_ptr ) ), this, SLOT( doLatchOn( Tomahawk::source_ptr ) ), Qt::QueuedConnection );
|
||||
connect( m_delegate, SIGNAL( latchOff( Tomahawk::source_ptr ) ), this, SLOT( doLatchOff( Tomahawk::source_ptr ) ), Qt::QueuedConnection );
|
||||
connect( m_delegate, SIGNAL( latchOn( Tomahawk::source_ptr ) ), this, SIGNAL( latchRequest( Tomahawk::source_ptr ) ), Qt::QueuedConnection );
|
||||
connect( m_delegate, SIGNAL( latchOff( Tomahawk::source_ptr ) ), this, SIGNAL( unlatchRequest( Tomahawk::source_ptr ) ), Qt::QueuedConnection );
|
||||
|
||||
setItemDelegate( m_delegate );
|
||||
|
||||
@ -102,15 +104,15 @@ SourceTreeView::SourceTreeView( QWidget* parent )
|
||||
|
||||
showOfflineSources( TomahawkSettings::instance()->showOfflineSources() );
|
||||
|
||||
connect( AudioEngine::instance(), SIGNAL( playlistChanged( Tomahawk::PlaylistInterface* ) ), this, SLOT( playlistChanged( Tomahawk::PlaylistInterface* ) ) );
|
||||
connect( AudioEngine::instance(), SIGNAL( stopped() ), this, SLOT( playlistChanged() ) );
|
||||
|
||||
// Light-blue sourcetree on osx
|
||||
#ifdef Q_WS_MAC
|
||||
setStyleSheet( "SourceTreeView:active { background: #DDE4EB; } "
|
||||
"SourceTreeView { background: #EDEDED; } " );
|
||||
#endif
|
||||
|
||||
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() ) );
|
||||
}
|
||||
|
||||
SourceTreeView::~SourceTreeView()
|
||||
@ -144,18 +146,21 @@ SourceTreeView::setupMenus()
|
||||
source_ptr source = item->source();
|
||||
if ( !source.isNull() )
|
||||
{
|
||||
PlaylistInterface* pi = AudioEngine::instance()->playlist();
|
||||
if ( pi && dynamic_cast< SourcePlaylistInterface* >( pi ) )
|
||||
if ( m_latchManager->isLatched( source ) )
|
||||
{
|
||||
SourcePlaylistInterface* sourcepi = dynamic_cast< SourcePlaylistInterface* >( pi );
|
||||
if ( !sourcepi->source().isNull() && sourcepi->source()->id() == source->id() && !AudioEngine::instance()->state() == AudioEngine::Stopped )
|
||||
{
|
||||
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() ) );
|
||||
}
|
||||
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() ) );
|
||||
}
|
||||
// PlaylistInterface* pi = AudioEngine::instance()->playlist();
|
||||
// if ( pi && dynamic_cast< SourcePlaylistInterface* >( pi ) )
|
||||
// {
|
||||
// SourcePlaylistInterface* sourcepi = dynamic_cast< SourcePlaylistInterface* >( pi );
|
||||
// if ( !sourcepi->source().isNull() && sourcepi->source()->id() == source->id() && !AudioEngine::instance()->state() == AudioEngine::Stopped )
|
||||
// {
|
||||
// }
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
@ -189,7 +194,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_latchOnAction, SIGNAL( triggered() ), SLOT( latchOn() ) );
|
||||
connect( m_latchOnAction, SIGNAL( triggered() ), SLOT( latchOnOrCatchUp() ) );
|
||||
}
|
||||
|
||||
|
||||
@ -338,7 +343,7 @@ SourceTreeView::addToLocal()
|
||||
|
||||
|
||||
void
|
||||
SourceTreeView::latchOn()
|
||||
SourceTreeView::latchOnOrCatchUp()
|
||||
{
|
||||
if ( !m_contextMenuIndex.isValid() )
|
||||
return;
|
||||
@ -350,100 +355,10 @@ SourceTreeView::latchOn()
|
||||
CollectionItem* item = itemFromIndex< CollectionItem >( m_contextMenuIndex );
|
||||
source_ptr source = item->source();
|
||||
|
||||
doLatchOn( source );
|
||||
}
|
||||
if ( m_latchManager->isLatched( source ) )
|
||||
emit catchUpRequest();
|
||||
|
||||
void
|
||||
SourceTreeView::doLatchOn( const source_ptr& source )
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
|
||||
PlaylistInterface* pi = AudioEngine::instance()->playlist();
|
||||
|
||||
bool catchUp = false;
|
||||
if ( pi && dynamic_cast< SourcePlaylistInterface* >( pi ) )
|
||||
{
|
||||
SourcePlaylistInterface* sourcepi = dynamic_cast< SourcePlaylistInterface* >( pi );
|
||||
if ( !sourcepi->source().isNull() && sourcepi->source()->id() == source->id() )
|
||||
{
|
||||
//it's a catch-up -- logic in audioengine should take care of it
|
||||
AudioEngine::instance()->next();
|
||||
catchUp = true;
|
||||
m_latch = sourcepi->getSharedPointer();
|
||||
}
|
||||
}
|
||||
|
||||
DatabaseCommand_SocialAction* cmd = new DatabaseCommand_SocialAction();
|
||||
cmd->setSource( SourceList::instance()->getLocal() );
|
||||
cmd->setAction( "latchOn");
|
||||
cmd->setComment( source->userName() );
|
||||
cmd->setTimestamp( QDateTime::currentDateTime().toTime_t() );
|
||||
Database::instance()->enqueue( QSharedPointer< DatabaseCommand >( cmd ) );
|
||||
|
||||
if ( !catchUp )
|
||||
{
|
||||
m_waitingToPlayLatch = source;
|
||||
AudioEngine::instance()->playItem( source->getPlaylistInterface().data(), source->getPlaylistInterface()->nextItem() );
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
SourceTreeView::doLatchOff( const source_ptr& source )
|
||||
{
|
||||
AudioEngine::instance()->playItem( source->getPlaylistInterface().data(), source->getPlaylistInterface()->nextItem() );
|
||||
|
||||
|
||||
AudioEngine::instance()->stop();
|
||||
AudioEngine::instance()->setPlaylist( 0 );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SourceTreeView::playlistChanged( PlaylistInterface* newInterface )
|
||||
{
|
||||
Q_UNUSED( newInterface );
|
||||
// If we were latched on and changed, send the listening along stop
|
||||
if ( m_latch.isNull() )
|
||||
{
|
||||
if ( m_waitingToPlayLatch.isNull() )
|
||||
return;
|
||||
|
||||
m_latch = m_waitingToPlayLatch->getPlaylistInterface();
|
||||
m_waitingToPlayLatch.clear();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const PlaylistInterface* pi = AudioEngine::instance()->playlist();
|
||||
bool listeningAlong = false;
|
||||
source_ptr newSource;
|
||||
|
||||
if ( pi && dynamic_cast< const SourcePlaylistInterface* >( pi ) )
|
||||
{
|
||||
const SourcePlaylistInterface* sourcepi = dynamic_cast< const SourcePlaylistInterface* >( pi );
|
||||
if ( !AudioEngine::instance()->state() == AudioEngine::Stopped )
|
||||
{
|
||||
listeningAlong = true;
|
||||
newSource = sourcepi->source();
|
||||
}
|
||||
}
|
||||
|
||||
SourcePlaylistInterface* origsourcepi = dynamic_cast< SourcePlaylistInterface* >( m_latch.data() );
|
||||
Q_ASSERT( origsourcepi );
|
||||
const source_ptr source = origsourcepi->source();
|
||||
|
||||
// if we're currently listening along to the same source, no change
|
||||
if ( listeningAlong && ( !origsourcepi->source().isNull() && origsourcepi->source()->id() == newSource->id() ) )
|
||||
return;
|
||||
|
||||
DatabaseCommand_SocialAction* cmd = new DatabaseCommand_SocialAction();
|
||||
cmd->setSource( SourceList::instance()->getLocal() );
|
||||
cmd->setAction( "latchOff");
|
||||
cmd->setComment( source->userName() );
|
||||
cmd->setTimestamp( QDateTime::currentDateTime().toTime_t() );
|
||||
Database::instance()->enqueue( QSharedPointer< DatabaseCommand >( cmd ) );
|
||||
|
||||
m_latch.clear();
|
||||
emit latchRequest( source );
|
||||
}
|
||||
|
||||
void
|
||||
@ -460,7 +375,7 @@ SourceTreeView::latchOff()
|
||||
const CollectionItem* item = itemFromIndex< CollectionItem >( m_contextMenuIndex );
|
||||
const source_ptr source = item->source();
|
||||
|
||||
doLatchOff( source );
|
||||
emit unlatchRequest( source );
|
||||
}
|
||||
|
||||
|
||||
|
@ -31,6 +31,11 @@ class SourcesModel;
|
||||
class SourcesProxyModel;
|
||||
class SourceDelegate;
|
||||
|
||||
namespace Tomahawk
|
||||
{
|
||||
class LatchManager;
|
||||
}
|
||||
|
||||
class SourceTreeView : public QTreeView
|
||||
{
|
||||
Q_OBJECT
|
||||
@ -50,6 +55,10 @@ signals:
|
||||
void onOnline( const QModelIndex& index );
|
||||
void onOffline( const QModelIndex& index );
|
||||
|
||||
void latchRequest( const Tomahawk::source_ptr& source );
|
||||
void unlatchRequest( const Tomahawk::source_ptr& source );
|
||||
void catchUpRequest();
|
||||
|
||||
private slots:
|
||||
void onItemExpanded( const QModelIndex& idx );
|
||||
void onItemActivated( const QModelIndex& index );
|
||||
@ -61,12 +70,8 @@ private slots:
|
||||
void copyPlaylistLink();
|
||||
void addToLocal();
|
||||
|
||||
void latchOn();
|
||||
void doLatchOn( const Tomahawk::source_ptr& idx );
|
||||
void latchOnOrCatchUp();
|
||||
void latchOff();
|
||||
void doLatchOff( const Tomahawk::source_ptr& idx );
|
||||
|
||||
void playlistChanged( Tomahawk::PlaylistInterface* = 0 );
|
||||
|
||||
void onCustomContextMenu( const QPoint& pos );
|
||||
|
||||
@ -91,6 +96,7 @@ private:
|
||||
SourcesProxyModel* m_proxyModel;
|
||||
QModelIndex m_contextMenuIndex;
|
||||
SourceDelegate* m_delegate;
|
||||
Tomahawk::LatchManager* m_latchManager;
|
||||
|
||||
QMenu m_playlistMenu;
|
||||
QMenu m_roPlaylistMenu;
|
||||
@ -103,9 +109,6 @@ private:
|
||||
QAction* m_latchOnAction;
|
||||
QAction* m_latchOffAction;
|
||||
|
||||
Tomahawk::source_ptr m_waitingToPlayLatch;
|
||||
Tomahawk::playlistinterface_ptr m_latch;
|
||||
|
||||
bool m_dragging;
|
||||
QRect m_dropRect;
|
||||
QPersistentModelIndex m_dropIndex;
|
||||
|
Loading…
x
Reference in New Issue
Block a user