X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=src%2Fdownloaditem.cpp;h=58714e026143ebc5a53b2104ee35248dbd18bbe2;hb=HEAD;hp=f70624be170554c1275c5436aa5216150d42f819;hpb=c449f3a0f783b74807783ab9618d4b8232e4fae3;p=minitube diff --git a/src/downloaditem.cpp b/src/downloaditem.cpp index f70624b..58714e0 100644 --- a/src/downloaditem.cpp +++ b/src/downloaditem.cpp @@ -1,12 +1,34 @@ +/* $BEGIN_LICENSE + +This file is part of Minitube. +Copyright 2009, Flavio Tordini + +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 . + +$END_LICENSE */ + #include "downloaditem.h" -#include "networkaccess.h" +#include "http.h" +#include "httputils.h" #include "video.h" #include +#include -namespace The { - NetworkAccess* http(); -} +#ifdef APP_MAC +#include "macutils.h" +#endif DownloadItem::DownloadItem(Video *video, QUrl url, QString filename, QObject *parent) : QObject(parent) @@ -14,6 +36,8 @@ DownloadItem::DownloadItem(Video *video, QUrl url, QString filename, QObject *pa , m_startedSaving(false) , m_finishedDownloading(false) , m_url(url) + , m_offset(0) + , sendStatusChanges(true) , m_file(filename) , m_reply(0) , video(video) @@ -23,15 +47,87 @@ 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() { - if (m_reply) delete m_reply; - if (video) delete video; + if (m_reply) { + delete m_reply; + m_reply = 0; + } + if (video) { + delete video; + video = 0; + } +} + +bool DownloadItem::needsDownload(qint64 offset) { + return offset < m_offset || offset > m_offset + m_bytesReceived; +} + +bool DownloadItem::isBuffered(qint64 offset) { + QMap::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::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::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(); } @@ -39,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; @@ -60,6 +153,7 @@ void DownloadItem::init() { this, SLOT(requestFinished())); // start timer for the download estimation + m_totalTime = 0; m_downloadTime.start(); speedCheckTimer->start(); @@ -71,8 +165,12 @@ void DownloadItem::init() { void DownloadItem::stop() { - if (m_reply) + if (m_reply) { + m_reply->disconnect(); m_reply->abort(); + m_reply->deleteLater(); + m_reply = 0; + } m_status = Idle; emit statusChanged(); } @@ -85,27 +183,25 @@ void DownloadItem::open() { void DownloadItem::openFolder() { QFileInfo info(m_file); +#ifdef APP_MAC + mac::showInFinder(info.absoluteFilePath()); +#else QUrl url = QUrl::fromLocalFile(info.absolutePath()); QDesktopServices::openUrl(url); +#endif } void DownloadItem::tryAgain() { - if (m_reply) - m_reply->abort(); - - if (m_file.exists()) - m_file.remove(); - - m_reply = The::http()->simpleGet(m_url); - init(); - emit statusChanged(); + stop(); + start(); } void DownloadItem::downloadReadyRead() { + if (!m_reply) return; if (!m_file.isOpen()) { if (!m_file.open(QIODevice::ReadWrite)) { - qDebug() << QString("Error opening output file: %1").arg(m_file.errorString()); + qWarning() << QString("Error opening output file: %1").arg(m_file.errorString()); stop(); emit statusChanged(); return; @@ -113,31 +209,24 @@ void DownloadItem::downloadReadyRead() { emit statusChanged(); } + // qWarning() << __PRETTY_FUNCTION__ << m_file.pos(); if (-1 == m_file.write(m_reply->readAll())) { - /* - downloadInfoLabel->setText(tr("Error saving: %1") - .arg(m_output.errorString())); - stopButton->click(); - */ + qWarning() << "Error saving." << m_file.errorString(); } else { + m_startedSaving = true; - if (m_status != Downloading) { - // m_status = Downloading; - // emit statusChanged(); - } else if (m_finishedDownloading) - requestFinished(); + + // if (m_finishedDownloading) requestFinished(); } } void DownloadItem::error(QNetworkReply::NetworkError) { -#ifdef DOWNLOADMANAGER_DEBUG - qDebug() << "DownloadItem::" << __FUNCTION__ << m_reply->errorString() << m_url; -#endif - - qDebug() << m_reply->errorString(); + if (m_reply) { + qWarning() << m_reply->errorString() << m_reply->url().toEncoded(); + m_errorMessage = m_reply->errorString(); + } - m_errorMessage = m_reply->errorString(); m_reply = 0; m_status = Failed; @@ -149,54 +238,58 @@ QString DownloadItem::errorMessage() const { } void DownloadItem::metaDataChanged() { + if (!m_reply) return; QVariant locationHeader = m_reply->header(QNetworkRequest::LocationHeader); if (locationHeader.isValid()) { m_url = locationHeader.toUrl(); // qDebug() << "Redirecting to" << m_url; - m_reply->deleteLater(); - m_reply = The::http()->simpleGet(m_url); - init(); + tryAgain(); return; } - -#ifdef DOWNLOADMANAGER_DEBUG - qDebug() << "DownloadItem::" << __FUNCTION__ << "not handled."; -#endif + // qDebug() << m_reply->rawHeaderList(); } int DownloadItem::initialBufferSize() { // qDebug() << video->getDefinitionCode(); switch (video->getDefinitionCode()) { case 18: - return 1024*192; - case 22: return 1024*512; + case 22: + return 1024*1024; case 37: - return 1024*768; + return 1024*1024*2; } return 1024*128; } void DownloadItem::downloadProgress(qint64 bytesReceived, qint64 bytesTotal) { - if (m_lastProgressTime.elapsed() < 150) return; - m_lastProgressTime.start(); + // qDebug() << __PRETTY_FUNCTION__ << bytesReceived << bytesTotal << m_downloadTime.elapsed(); m_bytesReceived = bytesReceived; + if (!sendStatusChanges) return; + + if (m_lastProgressTime.elapsed() < 150) return; + m_lastProgressTime.start(); + if (m_status != Downloading) { - int neededBytes = (int) (bytesTotal * .01); - // qDebug() << bytesReceived << bytesTotal << neededBytes << m_downloadTime.elapsed(); + int neededBytes = (int) (bytesTotal * .005); int bufferSize = initialBufferSize(); + if (bufferSize > bytesTotal) bufferSize = bytesTotal; + // qDebug() << bytesReceived << bytesTotal << neededBytes << bufferSize << m_downloadTime.elapsed(); if (bytesReceived > bufferSize - && bytesReceived > neededBytes - && m_downloadTime.elapsed() > 1000 ) { + && 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); } @@ -215,20 +308,20 @@ void DownloadItem::downloadProgress(qint64 bytesReceived, qint64 bytesTotal) { void DownloadItem::speedCheck() { if (!m_reply) return; - if (m_bytesReceived < initialBufferSize() / 3) { - m_reply->disconnect(); - m_reply->abort(); - m_reply->deleteLater(); - m_reply = 0; + int bytesTotal = m_reply->size(); + int bufferSize = initialBufferSize(); + if (bufferSize > bytesTotal) bufferSize = 0; + if (m_bytesReceived < bufferSize / 3) { + stop(); // too slow! retry qDebug() << "Retrying..."; - connect(video, SIGNAL(gotStreamUrl(QUrl)), SLOT(gotStreamUrl(QUrl))); + connect(video, SIGNAL(gotStreamUrl(QUrl)), SLOT(gotStreamUrl(QUrl)), Qt::UniqueConnection); video->loadStreamUrl(); } } -void DownloadItem::gotStreamUrl(QUrl streamUrl) { +void DownloadItem::gotStreamUrl(QUrl /*streamUrl*/) { Video *video = static_cast