1
0
mirror of https://github.com/tomahawk-player/tomahawk.git synced 2025-08-21 05:11:44 +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 else
{
emit finished( m_url ); emit finished( m_url );
emit finished(); emit finished();
}
} }

View File

@@ -22,65 +22,107 @@
#include "Qnr_IoDeviceStream.h" #include "Qnr_IoDeviceStream.h"
#include <QtNetwork/QNetworkReply> #include "utils/Logger.h"
#include <QNetworkReply>
#include <QTimer>
using namespace Tomahawk; using namespace Tomahawk;
QNR_IODeviceStream::QNR_IODeviceStream(QIODevice* ioDevice, QObject* parent) // Feed Phonon in 1MiB blocks
: Phonon::AbstractMediaStream( parent ), #define BLOCK_SIZE 1048576
_ioDevice(ioDevice),
_networkReply(0) 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 ( !m_networkReply->isOpen() ) {
if (!_ioDevice->isOpen()) { m_networkReply->open(QIODevice::ReadOnly);
_ioDevice->open(QIODevice::ReadOnly);
} }
Q_ASSERT(ioDevice->isOpen()); tLog() << Q_FUNC_INFO;
Q_ASSERT(ioDevice->isReadable()); Q_ASSERT( m_networkReply->isOpen() );
// streamSize = ioDevice->size(); Q_ASSERT( m_networkReply->isReadable() );
// streamSeekable = !ioDevice->isSequential();
// if ( m_networkReply->isFinished() )
// Allow handling of QNetworkReplies WRT its isFinished() function.. {
_networkReply = qobject_cast<QNetworkReply *>(_ioDevice); // 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() QNR_IODeviceStream::~QNR_IODeviceStream()
{ {
tLog() << Q_FUNC_INFO;
} }
void QNR_IODeviceStream::reset()
void
QNR_IODeviceStream::enoughData()
{ {
_ioDevice->reset(); tLog() << Q_FUNC_INFO;
//resetDone(); m_timer->stop();
} }
void QNR_IODeviceStream::needData()
void
QNR_IODeviceStream::needData()
{ {
quint32 size = 4096; tLog() << Q_FUNC_INFO;
const QByteArray data = _ioDevice->read(size); m_timer->start();
// #ifdef __GNUC__ moreData();
// #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()) { void
// error(Phonon::NormalError, d->ioDevice->errorString()); QNR_IODeviceStream::reset()
// } {
writeData(data); tLog() << Q_FUNC_INFO;
if (_ioDevice->atEnd()) { m_pos = 0;
// If the IO device was identified as QNetworkReply also take its }
// isFinished() into account, when triggering EOD.
if (!_networkReply || _networkReply->isFinished()) {
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(); endOfData();
m_timer->stop();
} }
else
{
writeData( data );
} }
} }
void QNR_IODeviceStream::seekStream(qint64 offset)
{
_ioDevice->seek(offset);
//seekStreamDone();
}
// vim: sw=4 sts=4 et tw=100 // vim: sw=4 sts=4 et tw=100

View File

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