mirror of
https://github.com/tomahawk-player/tomahawk.git
synced 2025-03-18 23:09:42 +01:00
Added DownloadManager and DownloadJob.
This commit is contained in:
parent
40dfa8faa0
commit
55feb3f3e1
@ -15,6 +15,8 @@ set( libGuiSources
|
||||
ActionCollection.cpp
|
||||
|
||||
ContextMenu.cpp
|
||||
DownloadManager.cpp
|
||||
DownloadJob.cpp
|
||||
DropJob.cpp
|
||||
GlobalActionManager.cpp
|
||||
ViewPage.cpp
|
||||
|
446
src/libtomahawk/DownloadJob.cpp
Normal file
446
src/libtomahawk/DownloadJob.cpp
Normal file
@ -0,0 +1,446 @@
|
||||
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
||||
*
|
||||
* Copyright 2015, Christian Muehlhaeuser <muesli@tomahawk-player.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 "DownloadJob.h"
|
||||
|
||||
#include "Track.h"
|
||||
#include "TomahawkSettings.h"
|
||||
#include "utils/NetworkAccessManager.h"
|
||||
#include "utils/Logger.h"
|
||||
|
||||
|
||||
DownloadJob::DownloadJob( const Tomahawk::track_ptr& track, DownloadFormat format, bool tryResuming, DownloadJob::TrackState state )
|
||||
: m_state( state )
|
||||
, m_retries( 0 )
|
||||
, m_tryResuming( tryResuming )
|
||||
, m_reply( 0 )
|
||||
, m_file( 0 )
|
||||
, m_rcvdStamp( 0 )
|
||||
, m_rcvdEmit( 0 )
|
||||
, m_rcvdSize( 0 )
|
||||
, m_fileSize( 0 )
|
||||
, m_format( format )
|
||||
, m_track( track )
|
||||
{
|
||||
m_finished = ( state == Finished );
|
||||
}
|
||||
|
||||
|
||||
DownloadJob::~DownloadJob()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
DownloadJob::progressPercentage() const
|
||||
{
|
||||
if ( m_fileSize == 0 )
|
||||
return 0;
|
||||
|
||||
return ( (double)m_rcvdSize / (double)m_fileSize ) * 100.0;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DownloadJob::setState( TrackState state )
|
||||
{
|
||||
TrackState oldState = m_state;
|
||||
m_state = state;
|
||||
|
||||
emit stateChanged( state, oldState );
|
||||
|
||||
if ( m_state == Finished )
|
||||
{
|
||||
m_rcvdSize = m_fileSize;
|
||||
emit finished();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
QString
|
||||
DownloadJob::localFile() const
|
||||
{
|
||||
return m_localFile;
|
||||
}
|
||||
|
||||
|
||||
QString
|
||||
DownloadJob::localPath() const
|
||||
{
|
||||
QDir dir = TomahawkSettings::instance()->downloadsPath();
|
||||
|
||||
if ( !dir.exists() )
|
||||
{
|
||||
dir.mkpath( "." );
|
||||
}
|
||||
|
||||
QString path = QString( "%1/%2" ).arg( safeEncode( m_track->artist(), true ) ).arg( safeEncode( m_track->album(), true ) );
|
||||
dir.mkpath( path );
|
||||
|
||||
return QString( dir.path() + "/" + path ).replace( "//", "/" );
|
||||
}
|
||||
|
||||
|
||||
QUrl
|
||||
DownloadJob::prepareFilename()
|
||||
{
|
||||
QString filename = QString( "%1. %2.%3" ).arg( m_track->albumpos() ).arg( safeEncode( m_track->track() ) ).arg( m_format.extension );
|
||||
QString path = localPath();
|
||||
QString localFile = QString( path + "/" + filename );
|
||||
|
||||
if ( !m_tryResuming )
|
||||
{
|
||||
QFileInfo fileInfo( localFile );
|
||||
unsigned int dupe = 1;
|
||||
while ( dupe < 100 )
|
||||
{
|
||||
QFileInfo fi( localFile );
|
||||
if ( fi.exists() )
|
||||
{
|
||||
QString dupeToken = QString( " (%1)" ).arg( dupe++ );
|
||||
localFile = path + "/" + fileInfo.completeBaseName() + dupeToken + "." + fileInfo.suffix();
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
QFileInfo fileInfo( localFile );
|
||||
unsigned int dupe = 1;
|
||||
QString lastFound = localFile;
|
||||
while ( dupe < 100 )
|
||||
{
|
||||
QFileInfo fi( localFile );
|
||||
if ( fi.exists() )
|
||||
{
|
||||
lastFound = localFile;
|
||||
QString dupeToken = QString( " (%1)" ).arg( dupe++ );
|
||||
localFile = path + "/" + fileInfo.completeBaseName() + dupeToken + "." + fileInfo.suffix();
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
localFile = lastFound;
|
||||
}
|
||||
|
||||
tLog() << "Storing file as" << localFile << m_tryResuming;
|
||||
return QUrl( localFile );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DownloadJob::retry()
|
||||
{
|
||||
tLog() << Q_FUNC_INFO;
|
||||
|
||||
m_retries = 0;
|
||||
m_reply = 0;
|
||||
m_file = 0;
|
||||
m_rcvdSize = 0;
|
||||
m_fileSize = 0;
|
||||
m_finished = false;
|
||||
m_tryResuming = true;
|
||||
|
||||
setState( Waiting );
|
||||
emit updated();
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
DownloadJob::download()
|
||||
{
|
||||
QUrl localFile = prepareFilename();
|
||||
|
||||
if ( m_file )
|
||||
{
|
||||
tLog() << "Recovering from failed download for track:" << toString() << "-" << m_retries << "retries so far.";
|
||||
m_finished = false;
|
||||
delete m_file;
|
||||
m_file = 0;
|
||||
}
|
||||
|
||||
tLog() << "Saving download to file:" << localFile << localFile.toLocalFile();
|
||||
|
||||
m_file = new QFile( localFile.toString() );
|
||||
m_localFile = localFile.toString();
|
||||
|
||||
if ( m_tryResuming && checkForResumedFile() )
|
||||
return true;
|
||||
|
||||
m_reply = Tomahawk::Utils::nam()->get( QNetworkRequest( m_format.url ) );
|
||||
|
||||
connect( m_reply, SIGNAL( error( QNetworkReply::NetworkError ) ), SLOT( onDownloadError( QNetworkReply::NetworkError ) ) );
|
||||
connect( m_reply, SIGNAL( downloadProgress( qint64, qint64 ) ), SLOT( onDownloadProgress( qint64, qint64 ) ) );
|
||||
connect( m_reply, SIGNAL( finished() ), SLOT( onDownloadNetworkFinished() ) );
|
||||
|
||||
setState( Running );
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DownloadJob::pause()
|
||||
{
|
||||
if ( !m_reply )
|
||||
return;
|
||||
|
||||
setState( Paused );
|
||||
// m_reply->setReadBufferSize( 0 );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DownloadJob::resume()
|
||||
{
|
||||
tLog() << Q_FUNC_INFO << m_finished << m_rcvdSize << m_fileSize;
|
||||
if ( !m_reply )
|
||||
{
|
||||
tLog() << "Initiating paused download from previous session:" << toString();
|
||||
download();
|
||||
return;
|
||||
}
|
||||
|
||||
setState( Running );
|
||||
// m_reply->setReadBufferSize( 65536 );
|
||||
|
||||
onDownloadProgress( m_fileSize, m_fileSize );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DownloadJob::abort()
|
||||
{
|
||||
tLog() << Q_FUNC_INFO << toString();
|
||||
setState( Aborted );
|
||||
|
||||
if ( m_reply )
|
||||
{
|
||||
m_reply->abort();
|
||||
m_reply->deleteLater();
|
||||
m_reply = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DownloadJob::onDownloadError( QNetworkReply::NetworkError code )
|
||||
{
|
||||
if ( code == QNetworkReply::NoError )
|
||||
return;
|
||||
if ( m_state == Aborted )
|
||||
return;
|
||||
|
||||
tLog() << "Download error for track:" << toString() << "-" << code;
|
||||
|
||||
if ( ++m_retries > 3 )
|
||||
{
|
||||
setState( Failed );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_tryResuming = true;
|
||||
download();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DownloadJob::onDownloadProgress( qint64 rcvd, qint64 total )
|
||||
{
|
||||
if ( m_reply == 0 )
|
||||
return;
|
||||
|
||||
if ( rcvd >= m_fileSize && m_fileSize > 0 )
|
||||
{
|
||||
m_finished = true;
|
||||
}
|
||||
|
||||
if ( state() == Paused )
|
||||
return;
|
||||
|
||||
m_rcvdSize = rcvd;
|
||||
m_fileSize = total;
|
||||
|
||||
qint64 now = QDateTime::currentDateTime().toMSecsSinceEpoch();
|
||||
if ( ( now - 50 > m_rcvdStamp ) || ( rcvd == total ) )
|
||||
{
|
||||
m_rcvdStamp = now;
|
||||
if ( ( m_rcvdSize - 16384 > m_rcvdEmit ) || ( rcvd == total ) )
|
||||
{
|
||||
m_rcvdEmit = m_rcvdSize;
|
||||
emit progress( progressPercentage() );
|
||||
}
|
||||
}
|
||||
|
||||
if ( !m_file )
|
||||
return;
|
||||
|
||||
if ( !m_file->isOpen() )
|
||||
{
|
||||
if ( m_tryResuming && checkForResumedFile() )
|
||||
return;
|
||||
|
||||
if ( !m_file->open( QIODevice::WriteOnly ) )
|
||||
{
|
||||
tLog() << Q_FUNC_INFO << "Failed opening file:" << m_file->fileName();
|
||||
setState( Failed );
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
QByteArray data = m_reply->readAll();
|
||||
if ( data.length() == 0 )
|
||||
return;
|
||||
|
||||
if ( m_file->write( data ) < 0 )
|
||||
{
|
||||
tLog() << Q_FUNC_INFO << "Failed writing to file:" << data.length();
|
||||
onDownloadError( QNetworkReply::UnknownContentError );
|
||||
return;
|
||||
}
|
||||
|
||||
if ( m_rcvdSize >= m_fileSize && m_fileSize > 0 )
|
||||
{
|
||||
onDownloadFinished();
|
||||
}
|
||||
else if ( m_reply->isFinished() && m_reply->bytesAvailable() == 0 )
|
||||
{
|
||||
if ( ( m_fileSize > 0 && m_rcvdSize < m_fileSize ) || m_rcvdSize == 0 )
|
||||
{
|
||||
onDownloadError( QNetworkReply::UnknownContentError );
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DownloadJob::onDownloadNetworkFinished()
|
||||
{
|
||||
tLog() << Q_FUNC_INFO << m_rcvdSize << m_fileSize;
|
||||
if ( m_reply && m_reply->bytesAvailable() > 0 )
|
||||
{
|
||||
tLog() << "Expecting more data!";
|
||||
return;
|
||||
}
|
||||
|
||||
if ( ( m_fileSize > 0 && m_rcvdSize < m_fileSize ) || m_rcvdSize == 0 )
|
||||
{
|
||||
if ( m_reply )
|
||||
onDownloadError( QNetworkReply::UnknownContentError );
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DownloadJob::onDownloadFinished()
|
||||
{
|
||||
tLog() << Q_FUNC_INFO << m_rcvdSize << m_fileSize;
|
||||
if ( state() == Paused )
|
||||
{
|
||||
m_finished = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if ( ( m_fileSize > 0 && m_rcvdSize < m_fileSize ) || m_rcvdSize == 0 )
|
||||
{
|
||||
onDownloadError( QNetworkReply::UnknownContentError );
|
||||
return;
|
||||
}
|
||||
|
||||
disconnect( m_reply, SIGNAL( error( QNetworkReply::NetworkError ) ), this, SLOT( onDownloadError( QNetworkReply::NetworkError ) ) );
|
||||
disconnect( m_reply, SIGNAL( downloadProgress( qint64, qint64 ) ), this, SLOT( onDownloadProgress( qint64, qint64 ) ) );
|
||||
disconnect( m_reply, SIGNAL( finished() ), this, SLOT( onDownloadNetworkFinished() ) );
|
||||
m_reply->abort();
|
||||
|
||||
if ( m_file && m_file->isOpen() )
|
||||
{
|
||||
m_file->flush();
|
||||
m_file->close();
|
||||
}
|
||||
|
||||
delete m_file;
|
||||
m_file = 0;
|
||||
|
||||
m_finishedTimestamp = QDateTime::currentDateTimeUtc();
|
||||
setState( Finished );
|
||||
tLog() << Q_FUNC_INFO << "Finished downloading:" << toString();
|
||||
tLog() << Q_FUNC_INFO << m_finished;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
DownloadJob::checkForResumedFile()
|
||||
{
|
||||
tLog() << Q_FUNC_INFO;
|
||||
if ( !m_tryResuming )
|
||||
return false;
|
||||
|
||||
QUrl localFile = prepareFilename();
|
||||
QFileInfo fi( localFile.toString() );
|
||||
|
||||
tLog() << Q_FUNC_INFO << m_fileSize << fi.size();
|
||||
|
||||
if ( fi.size() > 0 && fi.exists() && fi.size() == m_fileSize )
|
||||
{
|
||||
tLog() << Q_FUNC_INFO << "Detected previously finished download.";
|
||||
m_rcvdSize = fi.size();
|
||||
m_finished = true;
|
||||
onDownloadFinished();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
QString
|
||||
DownloadJob::safeEncode( const QString& filename, bool removeTrailingDots ) const
|
||||
{
|
||||
//FIXME: make it a regexp
|
||||
QString res = QString( filename ).toLatin1().replace( "/", "_" ).replace( "\\", "_" )
|
||||
.replace( "*", "_" ).replace( "?", "_" ).replace( "%", "_" )
|
||||
.replace( "'", "_" ).replace( "\"", "_" )
|
||||
.replace( ":", "_" ).replace( "#", "_" )
|
||||
.replace( "<", "_" ).replace( ">", "_" );
|
||||
|
||||
if ( removeTrailingDots )
|
||||
{
|
||||
while ( res.endsWith( "." ) )
|
||||
res = res.left( res.count() - 1 );
|
||||
}
|
||||
|
||||
return res.left( 127 );
|
||||
}
|
||||
|
||||
|
||||
QString
|
||||
DownloadJob::toString() const
|
||||
{
|
||||
return m_track->toString();
|
||||
}
|
||||
|
||||
|
||||
DownloadFormat
|
||||
DownloadJob::format() const
|
||||
{
|
||||
return m_format;
|
||||
}
|
117
src/libtomahawk/DownloadJob.h
Normal file
117
src/libtomahawk/DownloadJob.h
Normal file
@ -0,0 +1,117 @@
|
||||
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
||||
*
|
||||
* Copyright 2015, Christian Muehlhaeuser <muesli@tomahawk-player.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 DOWNLOADJOB_H
|
||||
#define DOWNLOADJOB_H
|
||||
|
||||
#include <QDir>
|
||||
#include <QObject>
|
||||
#include <QFile>
|
||||
#include <QUrl>
|
||||
#include <QPixmap>
|
||||
#include <QDomElement>
|
||||
#include <QNetworkReply>
|
||||
#include <QDateTime>
|
||||
|
||||
#include "Track.h"
|
||||
|
||||
struct DownloadFormat
|
||||
{
|
||||
QUrl url;
|
||||
QString extension;
|
||||
QString mimetype;
|
||||
};
|
||||
|
||||
class DownloadJob : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
enum TrackState
|
||||
{ Waiting = 0, Running, Paused, Failed, Finished, Aborted, Any };
|
||||
|
||||
DownloadJob( const Tomahawk::track_ptr& track, DownloadFormat format, bool tryResuming = false, DownloadJob::TrackState state = Waiting );
|
||||
~DownloadJob();
|
||||
|
||||
QString toString() const;
|
||||
|
||||
TrackState state() const { return m_state; }
|
||||
unsigned int retries() const { return m_retries; }
|
||||
|
||||
int progressPercentage() const;
|
||||
long receivedSize() const { return m_rcvdSize; }
|
||||
long fileSize() const { return m_fileSize; }
|
||||
|
||||
QString localPath() const;
|
||||
QString localFile() const;
|
||||
DownloadFormat format() const;
|
||||
|
||||
QDateTime finishedTimestamp() const { return m_finishedTimestamp; }
|
||||
void setFinishedTimestamp( const QDateTime& timestamp ) { m_finishedTimestamp = timestamp; }
|
||||
|
||||
void setState( TrackState state );
|
||||
|
||||
public slots:
|
||||
bool download();
|
||||
void pause();
|
||||
void resume();
|
||||
void retry();
|
||||
void abort();
|
||||
|
||||
signals:
|
||||
void updated();
|
||||
void progress( int percentage );
|
||||
void stateChanged( DownloadJob::TrackState newState, DownloadJob::TrackState oldState );
|
||||
void finished();
|
||||
|
||||
private slots:
|
||||
void onDownloadNetworkFinished();
|
||||
void onDownloadError( QNetworkReply::NetworkError code );
|
||||
void onDownloadProgress( qint64, qint64 );
|
||||
void onDownloadFinished();
|
||||
|
||||
private:
|
||||
void storeState();
|
||||
QString safeEncode( const QString& filename, bool removeTrailingDots = false ) const;
|
||||
bool checkForResumedFile();
|
||||
QUrl prepareFilename();
|
||||
|
||||
TrackState m_state;
|
||||
unsigned int m_retries;
|
||||
bool m_tryResuming;
|
||||
|
||||
QNetworkReply* m_reply;
|
||||
QFile* m_file;
|
||||
|
||||
qint64 m_rcvdStamp;
|
||||
long m_rcvdEmit;
|
||||
long m_rcvdSize;
|
||||
long m_fileSize;
|
||||
bool m_finished;
|
||||
|
||||
QString m_localFile;
|
||||
|
||||
QDateTime m_finishedTimestamp;
|
||||
|
||||
DownloadFormat m_format;
|
||||
Tomahawk::track_ptr m_track;
|
||||
};
|
||||
|
||||
typedef QSharedPointer<DownloadJob> downloadjob_ptr;
|
||||
|
||||
#endif // DOWNLOADJOB_H
|
239
src/libtomahawk/DownloadManager.cpp
Normal file
239
src/libtomahawk/DownloadManager.cpp
Normal file
@ -0,0 +1,239 @@
|
||||
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
||||
*
|
||||
* Copyright 2015, Christian Muehlhaeuser <muesli@tomahawk-player.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 "DownloadManager.h"
|
||||
|
||||
#include <QTimer>
|
||||
|
||||
#include "utils/Logger.h"
|
||||
|
||||
DownloadManager* DownloadManager::s_instance = 0;
|
||||
|
||||
|
||||
DownloadManager*
|
||||
DownloadManager::instance()
|
||||
{
|
||||
if ( !s_instance )
|
||||
{
|
||||
s_instance = new DownloadManager();
|
||||
}
|
||||
|
||||
return s_instance;
|
||||
}
|
||||
|
||||
|
||||
DownloadManager::DownloadManager()
|
||||
: m_globalState( true )
|
||||
{
|
||||
tLog() << Q_FUNC_INFO << "Initializing DownloadManager.";
|
||||
|
||||
QTimer::singleShot( 0, this, SLOT( resumeJobs() ) );
|
||||
}
|
||||
|
||||
|
||||
DownloadManager::~DownloadManager()
|
||||
{
|
||||
tLog() << Q_FUNC_INFO << "Shutting down DownloadManager.";
|
||||
|
||||
QList< downloadjob_ptr > jl;
|
||||
foreach ( const downloadjob_ptr& job, jobs() )
|
||||
{
|
||||
jl << job;
|
||||
}
|
||||
|
||||
// TomahawkSettings::instance()->storeJobs( jl );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DownloadManager::resumeJobs()
|
||||
{
|
||||
tLog() << Q_FUNC_INFO;
|
||||
|
||||
/* QList<downloadjob_ptr> jobs = TomahawkSettings::instance()->storedJobs();
|
||||
for ( int i = jobs.count() - 1; i >= 0; i-- )
|
||||
{
|
||||
downloadjob_ptr job = jobs.at( i );
|
||||
addJob( job );
|
||||
}
|
||||
|
||||
tLog() << Q_FUNC_INFO << "Restored" << jobs.count() << "existing jobs.";*/
|
||||
}
|
||||
|
||||
|
||||
QList<downloadjob_ptr>
|
||||
DownloadManager::jobs( DownloadJob::TrackState state ) const
|
||||
{
|
||||
if ( state < 0 )
|
||||
return m_jobs;
|
||||
|
||||
QList<downloadjob_ptr> jobs;
|
||||
foreach ( const downloadjob_ptr& job, m_jobs )
|
||||
{
|
||||
if ( job.isNull() )
|
||||
continue;
|
||||
|
||||
if ( state == DownloadJob::TrackState::Any || job->state() == state )
|
||||
jobs << job;
|
||||
}
|
||||
|
||||
return jobs;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
DownloadManager::addJob( const downloadjob_ptr& job )
|
||||
{
|
||||
if ( job.isNull() )
|
||||
{
|
||||
tLog() << "Found invalid download job - ignoring!";
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( containsJob( job ) )
|
||||
{
|
||||
tLog() << "Found duplicate download job - ignoring:" << job->toString();
|
||||
return false;
|
||||
}
|
||||
|
||||
m_jobs << job;
|
||||
emit jobAdded( job );
|
||||
|
||||
connect( job.data(), SIGNAL( finished() ), SLOT( checkJobs() ) );
|
||||
connect( job.data(), SIGNAL( stateChanged( DownloadJob::TrackState, DownloadJob::TrackState ) ), SLOT( checkJobs() ) ) ;
|
||||
// connect( job.data(), SIGNAL( stateChanged( DownloadJob::TrackState, DownloadJob::TrackState ) ), SIGNAL( stateChanged( DownloadJob::TrackState, DownloadJob::TrackState ) ) );
|
||||
|
||||
checkJobs();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
DownloadManager::removeJob( const downloadjob_ptr& job )
|
||||
{
|
||||
tLog() << "Removing job:" << job->toString();
|
||||
job->abort();
|
||||
m_jobs.removeAll( job );
|
||||
emit jobRemoved( job );
|
||||
|
||||
checkJobs();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
DownloadManager::containsJob( const downloadjob_ptr& job ) const
|
||||
{
|
||||
return m_jobs.contains( job );
|
||||
}
|
||||
|
||||
|
||||
downloadjob_ptr
|
||||
DownloadManager::currentJob() const
|
||||
{
|
||||
QList<downloadjob_ptr> j = jobs( DownloadJob::TrackState::Running );
|
||||
if ( j.count() )
|
||||
return j.first();
|
||||
|
||||
j = jobs( DownloadJob::TrackState::Paused );
|
||||
if ( j.count() )
|
||||
return j.first();
|
||||
|
||||
j = jobs( DownloadJob::TrackState::Waiting );
|
||||
if ( j.count() )
|
||||
return j.first();
|
||||
|
||||
return downloadjob_ptr();
|
||||
}
|
||||
|
||||
|
||||
|
||||
DownloadManager::DownloadManagerState
|
||||
DownloadManager::state() const
|
||||
{
|
||||
if ( !currentJob().isNull() )
|
||||
{
|
||||
switch ( currentJob()->state() )
|
||||
{
|
||||
case DownloadJob::TrackState::Waiting:
|
||||
return DownloadManager::DownloadManagerState::Waiting;
|
||||
|
||||
case DownloadJob::TrackState::Paused:
|
||||
return DownloadManager::DownloadManagerState::Paused;
|
||||
|
||||
case DownloadJob::TrackState::Running:
|
||||
return DownloadManager::DownloadManagerState::Running;
|
||||
}
|
||||
}
|
||||
|
||||
return DownloadManager::DownloadManagerState::Waiting;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DownloadManager::checkJobs()
|
||||
{
|
||||
if ( !m_globalState )
|
||||
return;
|
||||
|
||||
if ( state() == DownloadManager::DownloadManagerState::Waiting && !currentJob().isNull() )
|
||||
{
|
||||
downloadjob_ptr job = currentJob();
|
||||
/* connect( job.data(), SIGNAL( finished() ), SLOT( checkJobs() ) );
|
||||
connect( job.data(), SIGNAL( stateChanged( DownloadJob::TrackState, DownloadJob::TrackState ) ), SLOT( checkJobs() ) ) ;
|
||||
connect( job.data(), SIGNAL( stateChanged( DownloadJob::TrackState, DownloadJob::TrackState ) ), SIGNAL( stateChanged( Track::TrackState, Track::TrackState ) ) );*/
|
||||
|
||||
job->download();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DownloadManager::pause()
|
||||
{
|
||||
tLog() << Q_FUNC_INFO;
|
||||
|
||||
m_globalState = false;
|
||||
foreach ( const downloadjob_ptr& job, jobs( DownloadJob::TrackState::Running ) )
|
||||
{
|
||||
job->pause();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DownloadManager::resume()
|
||||
{
|
||||
tLog() << Q_FUNC_INFO;
|
||||
|
||||
m_globalState = true;
|
||||
|
||||
if ( jobs( DownloadJob::TrackState::Paused ).count() )
|
||||
{
|
||||
foreach ( const downloadjob_ptr& job, jobs( DownloadJob::TrackState::Paused ) )
|
||||
{
|
||||
tLog() << "Resuming job:" << job->toString();
|
||||
job->resume();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
checkJobs();
|
||||
}
|
70
src/libtomahawk/DownloadManager.h
Normal file
70
src/libtomahawk/DownloadManager.h
Normal file
@ -0,0 +1,70 @@
|
||||
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
||||
*
|
||||
* Copyright 2015, Christian Muehlhaeuser <muesli@tomahawk-player.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 DOWNLOADMANAGER_H
|
||||
#define DOWNLOADMANAGER_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QDateTime>
|
||||
#include <QUrl>
|
||||
|
||||
#include "DownloadJob.h"
|
||||
|
||||
class DownloadManager : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
enum DownloadManagerState { None, Running, Paused, Waiting };
|
||||
static DownloadManager* instance();
|
||||
|
||||
DownloadManager();
|
||||
~DownloadManager();
|
||||
|
||||
DownloadManagerState state() const;
|
||||
|
||||
QList<downloadjob_ptr> jobs( DownloadJob::TrackState state = DownloadJob::TrackState::Any ) const;
|
||||
bool containsJob( const downloadjob_ptr& job ) const;
|
||||
downloadjob_ptr currentJob() const;
|
||||
|
||||
public slots:
|
||||
bool addJob( const downloadjob_ptr& job );
|
||||
bool removeJob( const downloadjob_ptr& job );
|
||||
void checkJobs();
|
||||
|
||||
void pause();
|
||||
void resume();
|
||||
|
||||
void resumeJobs();
|
||||
|
||||
signals:
|
||||
void jobAdded( const downloadjob_ptr& job );
|
||||
void jobRemoved( const downloadjob_ptr& job );
|
||||
|
||||
void stateChanged( DownloadManagerState newState, DownloadManagerState oldState );
|
||||
|
||||
private slots:
|
||||
|
||||
private:
|
||||
QList< downloadjob_ptr > m_jobs;
|
||||
bool m_globalState;
|
||||
|
||||
static DownloadManager* s_instance;
|
||||
};
|
||||
|
||||
#endif // DOWNLOADMANAGER_H
|
Loading…
x
Reference in New Issue
Block a user