1
0
mirror of https://github.com/tomahawk-player/tomahawk.git synced 2025-08-19 12:21:52 +02:00

Buffer HTTP streams to make them seekable

This commit is contained in:
Uwe L. Korn
2013-09-01 15:16:23 +02:00
parent 17e7afee65
commit 03158c3bbc
3 changed files with 98 additions and 46 deletions

View File

@@ -118,6 +118,8 @@ NetworkReply::networkLoadFinished()
}
}
else
{
emit finished( m_url );
emit finished();
}
}

View File

@@ -22,64 +22,106 @@
#include "Qnr_IoDeviceStream.h"
#include <QtNetwork/QNetworkReply>
#include "utils/Logger.h"
#include <QNetworkReply>
#include <QTimer>
using namespace Tomahawk;
QNR_IODeviceStream::QNR_IODeviceStream(QIODevice* ioDevice, QObject* parent)
: Phonon::AbstractMediaStream( parent ),
_ioDevice(ioDevice),
_networkReply(0)
// Feed Phonon in 1MiB blocks
#define BLOCK_SIZE 1048576
QNR_IODeviceStream::QNR_IODeviceStream( QNetworkReply* reply, QObject* parent )
: Phonon::AbstractMediaStream( parent )
, m_networkReply( reply )
, m_pos( 0 )
, m_timer( new QTimer( this ) )
{
_ioDevice->reset();
if (!_ioDevice->isOpen()) {
_ioDevice->open(QIODevice::ReadOnly);
if ( !m_networkReply->isOpen() ) {
m_networkReply->open(QIODevice::ReadOnly);
}
Q_ASSERT(ioDevice->isOpen());
Q_ASSERT(ioDevice->isReadable());
// streamSize = ioDevice->size();
// streamSeekable = !ioDevice->isSequential();
//
// Allow handling of QNetworkReplies WRT its isFinished() function..
_networkReply = qobject_cast<QNetworkReply *>(_ioDevice);
tLog() << Q_FUNC_INFO;
Q_ASSERT( m_networkReply->isOpen() );
Q_ASSERT( m_networkReply->isReadable() );
if ( m_networkReply->isFinished() )
{
// All data is ready, read it!
m_data = m_networkReply->readAll();
Q_ASSERT( m_networkReply->atEnd() );
setStreamSeekable( true );
setStreamSize( m_data.size() );
tLog() << Q_FUNC_INFO << "Got data of size:" << m_data.size();
}
else
{
Q_ASSERT( false );
// TODO: Connect to finished() signal
}
m_timer->setInterval( 0 );
connect( m_timer, SIGNAL( timeout() ), SLOT( moreData() ) );
}
QNR_IODeviceStream::~QNR_IODeviceStream()
{
tLog() << Q_FUNC_INFO;
}
void QNR_IODeviceStream::reset()
void
QNR_IODeviceStream::enoughData()
{
_ioDevice->reset();
//resetDone();
tLog() << Q_FUNC_INFO;
m_timer->stop();
}
void QNR_IODeviceStream::needData()
void
QNR_IODeviceStream::needData()
{
quint32 size = 4096;
const QByteArray data = _ioDevice->read(size);
// #ifdef __GNUC__
// #warning TODO 4.5 - make sure we do not break anything without this, it is preventing IODs from working when they did not yet emit readyRead()
// #endif
// if (data.isEmpty() && !d->ioDevice->atEnd()) {
// error(Phonon::NormalError, d->ioDevice->errorString());
// }
writeData(data);
if (_ioDevice->atEnd()) {
// If the IO device was identified as QNetworkReply also take its
// isFinished() into account, when triggering EOD.
if (!_networkReply || _networkReply->isFinished()) {
endOfData();
}
tLog() << Q_FUNC_INFO;
m_timer->start();
moreData();
}
void
QNR_IODeviceStream::reset()
{
tLog() << Q_FUNC_INFO;
m_pos = 0;
}
void
QNR_IODeviceStream::seekStream( qint64 offset )
{
tLog() << Q_FUNC_INFO;
m_pos = offset;
}
void
QNR_IODeviceStream::moreData()
{
QByteArray data = m_data.mid( m_pos, BLOCK_SIZE );
tLog() << Q_FUNC_INFO << data.size();
m_pos += data.size();
if (m_data.size() == 0
// && m_networkReply->atEnd()
// && m_networkReply->isFinished()
)
{
// We're done.
endOfData();
m_timer->stop();
}
else
{
writeData( data );
}
}
void QNR_IODeviceStream::seekStream(qint64 offset)
{
_ioDevice->seek(offset);
//seekStreamDone();
}

View File

@@ -26,9 +26,11 @@
#include "DllMacro.h"
#include <phonon/abstractmediastream.h>
#include <QByteArray>
class QNetworkReply;
class QIODevice;
class QTimer;
namespace Tomahawk
{
@@ -37,16 +39,22 @@ class DLLEXPORT QNR_IODeviceStream : public Phonon::AbstractMediaStream
{
Q_OBJECT
public:
explicit QNR_IODeviceStream(QIODevice *ioDevice, QObject *parent = 0);
explicit QNR_IODeviceStream( QNetworkReply* reply, QObject *parent = 0 );
~QNR_IODeviceStream();
void reset();
void needData();
void seekStream(qint64);
virtual void enoughData();
virtual void needData();
virtual void reset();
virtual void seekStream( qint64 offset );
private slots:
void moreData();
private:
QIODevice *_ioDevice;
QNetworkReply *_networkReply;
QByteArray m_data;
QNetworkReply *m_networkReply;
qint64 m_pos;
QTimer* m_timer;
};
} // namespace Tomahawk