1 #include "downloaditem.h"
2 #include "networkaccess.h"
5 #include <QDesktopServices>
12 DownloadItem::DownloadItem(Video *video, QUrl url, QString filename, QObject *parent)
15 , m_startedSaving(false)
16 , m_finishedDownloading(false)
23 speedCheckTimer = new QTimer(this);
24 speedCheckTimer->setInterval(2000);
25 speedCheckTimer->setSingleShot(true);
26 connect(speedCheckTimer, SIGNAL(timeout()), SLOT(speedCheck()));
29 DownloadItem::~DownloadItem() {
30 if (m_reply) delete m_reply;
31 if (video) delete video;
34 void DownloadItem::start() {
35 m_reply = The::http()->simpleGet(m_url);
39 void DownloadItem::init() {
48 m_startedSaving = false;
49 m_finishedDownloading = false;
51 // attach to the m_reply
52 m_url = m_reply->url();
53 connect(m_reply, SIGNAL(readyRead()), this, SLOT(downloadReadyRead()));
54 connect(m_reply, SIGNAL(error(QNetworkReply::NetworkError)),
55 this, SLOT(error(QNetworkReply::NetworkError)));
56 connect(m_reply, SIGNAL(downloadProgress(qint64, qint64)),
57 this, SLOT(downloadProgress(qint64, qint64)));
58 connect(m_reply, SIGNAL(metaDataChanged()),
59 this, SLOT(metaDataChanged()));
60 connect(m_reply, SIGNAL(finished()),
61 this, SLOT(requestFinished()));
63 // start timer for the download estimation
64 m_downloadTime.start();
65 speedCheckTimer->start();
67 if (m_reply->error() != QNetworkReply::NoError) {
68 error(m_reply->error());
74 void DownloadItem::stop() {
81 void DownloadItem::open() {
82 QFileInfo info(m_file);
83 QUrl url = QUrl::fromLocalFile(info.absoluteFilePath());
84 QDesktopServices::openUrl(url);
87 void DownloadItem::openFolder() {
88 QFileInfo info(m_file);
89 QUrl url = QUrl::fromLocalFile(info.absolutePath());
90 QDesktopServices::openUrl(url);
93 void DownloadItem::tryAgain() {
100 m_reply = The::http()->simpleGet(m_url);
102 emit statusChanged();
105 void DownloadItem::downloadReadyRead() {
107 if (!m_file.isOpen()) {
108 if (!m_file.open(QIODevice::ReadWrite)) {
109 qDebug() << QString("Error opening output file: %1").arg(m_file.errorString());
111 emit statusChanged();
114 emit statusChanged();
117 if (-1 == m_file.write(m_reply->readAll())) {
119 downloadInfoLabel->setText(tr("Error saving: %1")
120 .arg(m_output.errorString()));
124 m_startedSaving = true;
125 if (m_status != Downloading) {
126 // m_status = Downloading;
127 // emit statusChanged();
128 } else if (m_finishedDownloading)
133 void DownloadItem::error(QNetworkReply::NetworkError) {
136 qWarning() << m_reply->errorString() << m_reply->url().toEncoded();
137 m_errorMessage = m_reply->errorString();
146 QString DownloadItem::errorMessage() const {
147 return m_errorMessage;
150 void DownloadItem::metaDataChanged() {
151 QVariant locationHeader = m_reply->header(QNetworkRequest::LocationHeader);
152 if (locationHeader.isValid()) {
153 m_url = locationHeader.toUrl();
154 // qDebug() << "Redirecting to" << m_url;
155 m_reply->deleteLater();
156 m_reply = The::http()->simpleGet(m_url);
161 #ifdef DOWNLOADMANAGER_DEBUG
162 qDebug() << "DownloadItem::" << __FUNCTION__ << "not handled.";
166 int DownloadItem::initialBufferSize() {
167 // qDebug() << video->getDefinitionCode();
168 switch (video->getDefinitionCode()) {
179 void DownloadItem::downloadProgress(qint64 bytesReceived, qint64 bytesTotal) {
181 // qDebug() << bytesReceived << bytesTotal << m_downloadTime.elapsed();
183 if (m_lastProgressTime.elapsed() < 150) return;
184 m_lastProgressTime.start();
186 m_bytesReceived = bytesReceived;
188 if (m_status != Downloading) {
190 int neededBytes = (int) (bytesTotal * .001);
191 // qDebug() << bytesReceived << bytesTotal << neededBytes << m_downloadTime.elapsed();
192 int bufferSize = initialBufferSize();
193 if (bytesReceived > bufferSize
194 && bytesReceived > neededBytes
195 && (m_downloadTime.elapsed() > 1000)) {
196 emit bufferProgress(100);
197 m_status = Downloading;
198 emit statusChanged();
200 int bufferPercent = bytesReceived * 100 / qMax(bufferSize, neededBytes);
201 emit bufferProgress(bufferPercent);
206 if (bytesTotal > 0) {
207 int percent = bytesReceived * 100 / bytesTotal;
208 if (percent != this->percent) {
209 this->percent = percent;
210 emit progress(percent);
217 void DownloadItem::speedCheck() {
218 if (!m_reply) return;
219 if (m_bytesReceived < initialBufferSize() / 3) {
220 m_reply->disconnect();
222 m_reply->deleteLater();
226 qDebug() << "Retrying...";
227 connect(video, SIGNAL(gotStreamUrl(QUrl)), SLOT(gotStreamUrl(QUrl)));
228 video->loadStreamUrl();
232 void DownloadItem::gotStreamUrl(QUrl streamUrl) {
234 Video *video = static_cast<Video *>(sender());
236 qDebug() << "Cannot get sender";
239 video->disconnect(this);
241 m_reply = The::http()->simpleGet(video->getStreamUrl());
245 qint64 DownloadItem::bytesTotal() const {
246 if (!m_reply) return 0;
247 return m_reply->header(QNetworkRequest::ContentLengthHeader).toULongLong();
250 qint64 DownloadItem::bytesReceived() const {
251 return m_bytesReceived;
254 double DownloadItem::remainingTime() const {
255 if (m_finishedDownloading)
258 double timeRemaining = ((double)(bytesTotal() - bytesReceived())) / currentSpeed();
260 // When downloading the eta should never be 0
261 if (timeRemaining == 0)
264 return timeRemaining;
267 double DownloadItem::currentSpeed() const {
268 if (m_finishedDownloading)
271 return m_bytesReceived * 1000.0 / m_downloadTime.elapsed();
274 void DownloadItem::requestFinished() {
276 m_finishedDownloading = true;
277 if (!m_startedSaving) {
278 qDebug() << "Request finished but never started saving";
281 if (m_status == Starting) {
282 m_status = Downloading;
283 emit statusChanged();
287 emit statusChanged();
291 QString DownloadItem::formattedFilesize(qint64 size) {
293 if (size < 1024) return tr("%1 bytes").arg(size);
294 else if (size < 1024*1024) return tr("%1 KB").arg(size/1024);
295 else if (size < 1024*1024*1024) return tr("%1 MB").arg(size/1024/1024);
296 else return tr("%1 GB").arg(size/1024/1024/1024);
301 } else if (size < 1024*1024) {
308 return QString(QLatin1String("%1 %2")).arg(size).arg(unit);
311 QString DownloadItem::formattedSpeed(double speed) {
313 static const int K = 1024;
314 if (speed < K) return tr("%1 bytes/s").arg(speed);
315 else if (speed < K*K) return tr("%1 KB/s").arg(speed/K);
316 else if (speed < K*K*K) return tr("%1 MB/s").arg(speed/K/K);
317 else return tr("%1 GB/s").arg(speed/K/K/K);
319 int speedInt = (int) speed;
321 if (speedInt < 1024) {
322 unit = tr("bytes/sec");
323 } else if (speedInt < 1024*1024) {
327 speedInt /= 1024*1024;
330 return QString(QLatin1String("%1 %2")).arg(speedInt).arg(unit);
333 QString DownloadItem::formattedTime(double timeRemaining) {
334 QString timeRemainingString = tr("seconds");
335 if (timeRemaining > 60) {
336 timeRemaining = timeRemaining / 60;
337 timeRemainingString = tr("minutes");
339 timeRemaining = floor(timeRemaining);
340 return tr("%4 %5 remaining")
342 .arg(timeRemainingString);