]> git.sur5r.net Git - minitube/blobdiff - src/downloaditem.cpp
Update upstream source from tag 'upstream/3.9.1'
[minitube] / src / downloaditem.cpp
index 05995370968b5fa1b07aed5298e0c6a2971f5342..58714e026143ebc5a53b2104ee35248dbd18bbe2 100644 (file)
@@ -1,5 +1,26 @@
+/* $BEGIN_LICENSE
+
+This file is part of Minitube.
+Copyright 2009, Flavio Tordini <flavio.tordini@gmail.com>
+
+Minitube 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.
+
+Minitube 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 Minitube.  If not, see <http://www.gnu.org/licenses/>.
+
+$END_LICENSE */
+
 #include "downloaditem.h"
-#include "networkaccess.h"
+#include "http.h"
+#include "httputils.h"
 #include "video.h"
 
 #include <QDesktopServices>
 #include "macutils.h"
 #endif
 
-namespace The {
-    NetworkAccess* http();
-}
-
 DownloadItem::DownloadItem(Video *video, QUrl url, QString filename, QObject *parent)
     : QObject(parent)
     , m_bytesReceived(0)
     , m_startedSaving(false)
     , m_finishedDownloading(false)
     , m_url(url)
+    , m_offset(0)
+    , sendStatusChanges(true)
     , m_file(filename)
     , m_reply(0)
     , video(video)
@@ -28,6 +47,9 @@ DownloadItem::DownloadItem(Video *video, QUrl url, QString filename, QObject *pa
     speedCheckTimer->setInterval(2000);
     speedCheckTimer->setSingleShot(true);
     connect(speedCheckTimer, SIGNAL(timeout()), SLOT(speedCheck()));
+
+    if (m_file.exists())
+        m_file.remove();
 }
 
 DownloadItem::~DownloadItem() {
@@ -41,8 +63,71 @@ DownloadItem::~DownloadItem() {
     }
 }
 
+bool DownloadItem::needsDownload(qint64 offset) {
+    return offset < m_offset || offset > m_offset + m_bytesReceived;
+}
+
+bool DownloadItem::isBuffered(qint64 offset) {
+    QMap<qint64, qint64>::iterator i;
+    for (i = buffers.begin(); i != buffers.end(); ++i) {
+        if (offset >= i.key() && offset <= i.value()) {
+            // qDebug() << "Buffered! " << i.key() << ":" << i.value();
+            return true;
+        }
+    }
+    // qDebug() << offset << "is not buffered";
+    return false;
+}
+
+qint64 DownloadItem::blankAtOffset(qint64 offset) {
+    // qDebug() << buffers;
+    QMap<qint64, qint64>::iterator i;
+    for (i = buffers.begin(); i != buffers.end(); ++i) {
+        if (offset >= i.key() && offset <= i.value()) {
+            // qDebug() << "Offset was" << offset << "now" << i.value();
+            return i.value() + 1;
+        }
+    }
+    return offset;
+}
+
+void DownloadItem::seekTo(qint64 offset, bool sendStatusChanges) {
+    // qDebug() << __PRETTY_FUNCTION__ << offset << sendStatusChanges;
+    stop();
+    if (m_bytesReceived > 0) {
+        bool bufferModified = false;
+        QMap<qint64, qint64>::iterator i;
+        for (i = buffers.begin(); i != buffers.end(); ++i) {
+            if (m_offset - 1 <= i.value()) {
+                /*
+                qDebug() << "Extending existing buffer "
+                         << i.key() << i.value() << "now" << m_offset + m_bytesReceived;
+                */
+                bufferModified = true;
+                i.value() = m_offset + m_bytesReceived;
+                break;
+            }
+        }
+        if (!bufferModified)
+            buffers.insert(m_offset, m_offset + m_bytesReceived);
+    }
+    m_offset = offset;
+    this->sendStatusChanges = sendStatusChanges;
+    bool seekSuccess = m_file.seek(offset);
+    if (!seekSuccess) {
+        qWarning() << "Cannot seek to offset" << offset << "in file" << m_file.fileName();
+        return;
+    }
+    start();
+}
+
 void DownloadItem::start() {
-    m_reply = The::http()->simpleGet(m_url);
+    // qDebug() << "Starting download at" << m_offset;
+    HttpRequest req;
+    req.url = m_url;
+    if (m_offset > 0) req.offset = m_offset;
+    m_reply = HttpUtils::yt().networkReply(req);
+
     init();
 }
 
@@ -50,11 +135,8 @@ void DownloadItem::init() {
     if (!m_reply)
         return;
 
-    if (m_file.exists())
-        m_file.remove();
-
     m_status = Starting;
-
+    m_bytesReceived = 0;
     m_startedSaving = false;
     m_finishedDownloading = false;
 
@@ -71,6 +153,7 @@ void DownloadItem::init() {
             this, SLOT(requestFinished()));
 
     // start timer for the download estimation
+    m_totalTime = 0;
     m_downloadTime.start();
     speedCheckTimer->start();
 
@@ -126,6 +209,7 @@ void DownloadItem::downloadReadyRead() {
         emit statusChanged();
     }
 
+    // qWarning() << __PRETTY_FUNCTION__ << m_file.pos();
     if (-1 == m_file.write(m_reply->readAll())) {
         qWarning() << "Error saving." << m_file.errorString();
     } else {
@@ -158,14 +242,11 @@ void DownloadItem::metaDataChanged() {
     QVariant locationHeader = m_reply->header(QNetworkRequest::LocationHeader);
     if (locationHeader.isValid()) {
         m_url = locationHeader.toUrl();
-        qDebug() << "Redirecting to" << m_url;
+        // qDebug() << "Redirecting to" << m_url;
         tryAgain();
         return;
     }
-
-#ifdef DOWNLOADMANAGER_DEBUG
-    qDebug() << "DownloadItem::" << __FUNCTION__ << "not handled.";
-#endif
+    // qDebug() << m_reply->rawHeaderList();
 }
 
 int DownloadItem::initialBufferSize() {
@@ -183,13 +264,15 @@ int DownloadItem::initialBufferSize() {
 
 void DownloadItem::downloadProgress(qint64 bytesReceived, qint64 bytesTotal) {
 
-    // qDebug() << bytesReceived << bytesTotal << m_downloadTime.elapsed();
+    // qDebug() << __PRETTY_FUNCTION__ << bytesReceived << bytesTotal << m_downloadTime.elapsed();
+
+    m_bytesReceived = bytesReceived;
+
+    if (!sendStatusChanges) return;
 
     if (m_lastProgressTime.elapsed() < 150) return;
     m_lastProgressTime.start();
 
-    m_bytesReceived = bytesReceived;
-
     if (m_status != Downloading) {
 
         int neededBytes = (int) (bytesTotal * .005);
@@ -197,13 +280,16 @@ void DownloadItem::downloadProgress(qint64 bytesReceived, qint64 bytesTotal) {
         if (bufferSize > bytesTotal) bufferSize = bytesTotal;
         // qDebug() << bytesReceived << bytesTotal << neededBytes << bufferSize << m_downloadTime.elapsed();
         if (bytesReceived > bufferSize
-            && bytesReceived > neededBytes
-            && m_downloadTime.elapsed() > 2000) {
+                && bytesReceived > neededBytes
+                && m_downloadTime.elapsed() > 2000) {
             emit bufferProgress(100);
             m_status = Downloading;
             emit statusChanged();
         } else {
-            int bufferPercent = bytesReceived * 100 / qMax(bufferSize, neededBytes);
+            int bytes = qMax(bufferSize, neededBytes);
+            int bufferPercent = 0;
+            if (bytes > 0)
+                bufferPercent = bytesReceived * 100 / bytes;
             emit bufferProgress(bufferPercent);
         }
 
@@ -261,7 +347,10 @@ double DownloadItem::remainingTime() const {
     if (m_finishedDownloading)
         return -1.0;
 
-    double timeRemaining = ((double)(bytesTotal() - bytesReceived())) / currentSpeed();
+    double speed = currentSpeed();
+    double timeRemaining = 0.0;
+    if (speed > 0.0)
+        timeRemaining = ((double)(bytesTotal() - bytesReceived())) / speed;
 
     // When downloading the eta should never be 0
     if (timeRemaining == 0)
@@ -274,7 +363,11 @@ double DownloadItem::currentSpeed() const {
     if (m_finishedDownloading)
         return -1.0;
 
-    return m_bytesReceived * 1000.0 / m_downloadTime.elapsed();
+    int elapsed = m_downloadTime.elapsed();
+    double speed = -1.0;
+    if (elapsed > 0)
+        speed = m_bytesReceived * 1000.0 / elapsed;
+    return speed;
 }
 
 void DownloadItem::requestFinished() {
@@ -296,8 +389,9 @@ void DownloadItem::requestFinished() {
         m_status = Downloading;
         emit statusChanged();
     }
-    m_file.close();
+    if (m_offset == 0) m_file.close();
     m_status = Finished;
+    m_totalTime = m_downloadTime.elapsed() / 1000.0;
     emit statusChanged();
     emit finished();
     m_reply->deleteLater();
@@ -333,14 +427,15 @@ QString DownloadItem::formattedSpeed(double speed) {
     return QString(QLatin1String("%1 %2")).arg(speedInt).arg(unit);
 }
 
-QString DownloadItem::formattedTime(double timeRemaining) {
+QString DownloadItem::formattedTime(double timeRemaining, bool remaining) {
     QString timeRemainingString = tr("seconds");
     if (timeRemaining > 60) {
         timeRemaining = timeRemaining / 60;
         timeRemainingString = tr("minutes");
     }
     timeRemaining = floor(timeRemaining);
-    return tr("%4 %5 remaining")
+    QString msg = remaining ? tr("%4 %5 remaining") : "%4 %5";
+    return msg
             .arg(timeRemaining)
             .arg(timeRemainingString);
 }