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:
@@ -118,6 +118,8 @@ NetworkReply::networkLoadFinished()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
emit finished( m_url );
|
emit finished( m_url );
|
||||||
emit finished();
|
emit finished();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -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
|
||||||
|
@@ -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
|
||||||
|
Reference in New Issue
Block a user