1
0
mirror of https://github.com/tomahawk-player/tomahawk.git synced 2025-08-05 13:47:26 +02:00

Pimple BufferIoDevice

This commit is contained in:
Uwe L. Korn
2013-06-16 19:02:08 +02:00
parent 45b367677d
commit 2451a0a061
3 changed files with 133 additions and 39 deletions

View File

@@ -2,6 +2,7 @@
* *
* Copyright 2010-2011, Christian Muehlhaeuser <muesli@tomahawk-player.org> * Copyright 2010-2011, Christian Muehlhaeuser <muesli@tomahawk-player.org>
* Copyright 2010-2011, Jeff Mitchell <jeff@tomahawk-player.org> * Copyright 2010-2011, Jeff Mitchell <jeff@tomahawk-player.org>
* Copyright 2013, Uwe L. Korn <uwelk@xhochy.com>
* *
* Tomahawk is free software: you can redistribute it and/or modify * Tomahawk is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@@ -17,7 +18,7 @@
* along with Tomahawk. If not, see <http://www.gnu.org/licenses/>. * along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include "BufferIoDevice.h" #include "BufferIoDevice_p.h"
#include <QCoreApplication> #include <QCoreApplication>
#include <QThread> #include <QThread>
@@ -30,18 +31,23 @@
BufferIODevice::BufferIODevice( unsigned int size, QObject* parent ) BufferIODevice::BufferIODevice( unsigned int size, QObject* parent )
: QIODevice( parent ) : QIODevice( parent )
, m_size( size ) , d_ptr( new BufferIODevicePrivate( this, size ) )
, m_received( 0 )
, m_pos( 0 )
{ {
} }
BufferIODevice::~BufferIODevice()
{
delete d_ptr;
}
bool bool
BufferIODevice::open( OpenMode mode ) BufferIODevice::open( OpenMode mode )
{ {
Q_D( BufferIODevice );
Q_UNUSED( mode ); Q_UNUSED( mode );
QMutexLocker lock( &m_mut ); QMutexLocker lock( &d->mut );
qDebug() << Q_FUNC_INFO; qDebug() << Q_FUNC_INFO;
QIODevice::open( QIODevice::ReadOnly | QIODevice::Unbuffered ); // FIXME? QIODevice::open( QIODevice::ReadOnly | QIODevice::Unbuffered ); // FIXME?
@@ -52,7 +58,8 @@ BufferIODevice::open( OpenMode mode )
void void
BufferIODevice::close() BufferIODevice::close()
{ {
QMutexLocker lock( &m_mut ); Q_D( BufferIODevice );
QMutexLocker lock( &d->mut );
qDebug() << Q_FUNC_INFO; qDebug() << Q_FUNC_INFO;
QIODevice::close(); QIODevice::close();
@@ -62,16 +69,17 @@ BufferIODevice::close()
bool bool
BufferIODevice::seek( qint64 pos ) BufferIODevice::seek( qint64 pos )
{ {
qDebug() << Q_FUNC_INFO << pos << m_size; Q_D( BufferIODevice );
qDebug() << Q_FUNC_INFO << pos << d->size;
if ( pos >= m_size ) if ( pos >= d->size )
return false; return false;
int block = blockForPos( pos ); int block = blockForPos( pos );
if ( isBlockEmpty( block ) ) if ( isBlockEmpty( block ) )
emit blockRequest( block ); emit blockRequest( block );
m_pos = pos; d->pos = pos;
qDebug() << "Finished seeking"; qDebug() << "Finished seeking";
return true; return true;
@@ -81,30 +89,40 @@ BufferIODevice::seek( qint64 pos )
void void
BufferIODevice::seeked( int block ) BufferIODevice::seeked( int block )
{ {
qDebug() << Q_FUNC_INFO << block << m_size; Q_D( BufferIODevice );
qDebug() << Q_FUNC_INFO << block << d->size;
} }
void void
BufferIODevice::inputComplete( const QString& errmsg ) BufferIODevice::inputComplete( const QString& errmsg )
{ {
Q_D( BufferIODevice );
qDebug() << Q_FUNC_INFO; qDebug() << Q_FUNC_INFO;
setErrorString( errmsg ); setErrorString( errmsg );
m_size = m_received; d->size = d->received;
emit readChannelFinished(); emit readChannelFinished();
} }
bool
BufferIODevice::isSequential() const
{
return false;
}
void void
BufferIODevice::addData( int block, const QByteArray& ba ) BufferIODevice::addData( int block, const QByteArray& ba )
{ {
Q_D( BufferIODevice );
{ {
QMutexLocker lock( &m_mut ); QMutexLocker lock( &d->mut );
while ( m_buffer.count() <= block ) while ( d->buffer.count() <= block )
m_buffer << QByteArray(); d->buffer << QByteArray();
m_buffer.replace( block, ba ); d->buffer.replace( block, ba );
} }
// If this was the last block of the transfer, check if we need to fill up gaps // If this was the last block of the transfer, check if we need to fill up gaps
@@ -116,7 +134,7 @@ BufferIODevice::addData( int block, const QByteArray& ba )
} }
} }
m_received += ba.count(); d->received += ba.count();
emit bytesWritten( ba.count() ); emit bytesWritten( ba.count() );
emit readyRead(); emit readyRead();
} }
@@ -125,21 +143,24 @@ BufferIODevice::addData( int block, const QByteArray& ba )
qint64 qint64
BufferIODevice::bytesAvailable() const BufferIODevice::bytesAvailable() const
{ {
return m_size - m_pos; Q_D( const BufferIODevice );
return d->size - d->pos;
} }
qint64 qint64
BufferIODevice::readData( char* data, qint64 maxSize ) BufferIODevice::readData( char* data, qint64 maxSize )
{ {
Q_D( BufferIODevice );
// qDebug() << Q_FUNC_INFO << m_pos << maxSize << 1; // qDebug() << Q_FUNC_INFO << m_pos << maxSize << 1;
if ( atEnd() ) if ( atEnd() )
return 0; return 0;
QByteArray ba; QByteArray ba;
ba.append( getData( m_pos, maxSize ) ); ba.append( getData( d->pos, maxSize ) );
m_pos += ba.count(); d->pos += ba.count();
// qDebug() << Q_FUNC_INFO << maxSize << ba.count() << 2; // qDebug() << Q_FUNC_INFO << maxSize << ba.count() << 2;
memcpy( data, ba.data(), ba.count() ); memcpy( data, ba.data(), ba.count() );
@@ -162,26 +183,44 @@ BufferIODevice::writeData( const char* data, qint64 maxSize )
qint64 qint64
BufferIODevice::size() const BufferIODevice::size() const
{ {
qDebug() << Q_FUNC_INFO << m_size; Q_D( const BufferIODevice );
return m_size; qDebug() << Q_FUNC_INFO << d->size;
return d->size;
} }
bool bool
BufferIODevice::atEnd() const BufferIODevice::atEnd() const
{ {
Q_D( const BufferIODevice );
// qDebug() << Q_FUNC_INFO << ( m_size <= m_pos ); // qDebug() << Q_FUNC_INFO << ( m_size <= m_pos );
return ( m_size <= m_pos ); return ( d->size <= d->pos );
}
qint64
BufferIODevice::pos() const
{
Q_D( const BufferIODevice );
return d->pos;
} }
void void
BufferIODevice::clear() BufferIODevice::clear()
{ {
QMutexLocker lock( &m_mut ); Q_D( BufferIODevice );
QMutexLocker lock( &d->mut );
m_pos = 0; d->pos = 0;
m_buffer.clear(); d->buffer.clear();
}
QIODevice::OpenMode
BufferIODevice::openMode() const
{
return QIODevice::ReadOnly | QIODevice::Unbuffered;
} }
@@ -217,8 +256,10 @@ BufferIODevice::offsetForPos( qint64 pos ) const
int int
BufferIODevice::nextEmptyBlock() const BufferIODevice::nextEmptyBlock() const
{ {
Q_D( const BufferIODevice );
int i = 0; int i = 0;
foreach( const QByteArray& ba, m_buffer ) foreach( const QByteArray& ba, d->buffer )
{ {
if ( ba.isEmpty() ) if ( ba.isEmpty() )
return i; return i;
@@ -236,9 +277,11 @@ BufferIODevice::nextEmptyBlock() const
int int
BufferIODevice::maxBlocks() const BufferIODevice::maxBlocks() const
{ {
int i = m_size / BLOCKSIZE; Q_D( const BufferIODevice );
if ( ( m_size % BLOCKSIZE ) > 0 ) int i = d->size / BLOCKSIZE;
if ( ( d->size % BLOCKSIZE ) > 0 )
i++; i++;
return i; return i;
@@ -248,22 +291,24 @@ BufferIODevice::maxBlocks() const
bool bool
BufferIODevice::isBlockEmpty( int block ) const BufferIODevice::isBlockEmpty( int block ) const
{ {
if ( block >= m_buffer.count() ) Q_D( const BufferIODevice );
if ( block >= d->buffer.count() )
return true; return true;
return m_buffer.at( block ).isEmpty(); return d->buffer.at( block ).isEmpty();
} }
QByteArray QByteArray
BufferIODevice::getData( qint64 pos, qint64 size ) BufferIODevice::getData( qint64 pos, qint64 size )
{ {
Q_D( BufferIODevice );
// qDebug() << Q_FUNC_INFO << pos << size << 1; // qDebug() << Q_FUNC_INFO << pos << size << 1;
QByteArray ba; QByteArray ba;
int block = blockForPos( pos ); int block = blockForPos( pos );
int offset = offsetForPos( pos ); int offset = offsetForPos( pos );
QMutexLocker lock( &m_mut ); QMutexLocker lock( &d->mut );
while( ba.count() < size ) while( ba.count() < size )
{ {
if ( block > maxBlocks() ) if ( block > maxBlocks() )
@@ -272,7 +317,7 @@ BufferIODevice::getData( qint64 pos, qint64 size )
if ( isBlockEmpty( block ) ) if ( isBlockEmpty( block ) )
break; break;
ba.append( m_buffer.at( block++ ).mid( offset ) ); ba.append( d->buffer.at( block++ ).mid( offset ) );
} }
// qDebug() << Q_FUNC_INFO << pos << size << 2; // qDebug() << Q_FUNC_INFO << pos << size << 2;

View File

@@ -1,6 +1,7 @@
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> === /* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
* *
* Copyright 2010-2011, Christian Muehlhaeuser <muesli@tomahawk-player.org> * Copyright 2010-2011, Christian Muehlhaeuser <muesli@tomahawk-player.org>
* Copyright 2013, Uwe L. Korn <uwelk@xhochy.com>
* *
* Tomahawk is free software: you can redistribute it and/or modify * Tomahawk is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@@ -23,12 +24,15 @@
#include <QMutexLocker> #include <QMutexLocker>
#include <QFile> #include <QFile>
class BufferIODevicePrivate;
class BufferIODevice : public QIODevice class BufferIODevice : public QIODevice
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit BufferIODevice( unsigned int size = 0, QObject* parent = 0 ); explicit BufferIODevice( unsigned int size = 0, QObject* parent = 0 );
~BufferIODevice();
virtual bool open( OpenMode mode ); virtual bool open( OpenMode mode );
virtual void close(); virtual void close();
@@ -39,16 +43,16 @@ public:
virtual qint64 bytesAvailable() const; virtual qint64 bytesAvailable() const;
virtual qint64 size() const; virtual qint64 size() const;
virtual bool atEnd() const; virtual bool atEnd() const;
virtual qint64 pos() const { return m_pos; } virtual qint64 pos() const;
void addData( int block, const QByteArray& ba ); void addData( int block, const QByteArray& ba );
void clear(); void clear();
OpenMode openMode() const { return QIODevice::ReadOnly | QIODevice::Unbuffered; } OpenMode openMode() const;
void inputComplete( const QString& errmsg = "" ); void inputComplete( const QString& errmsg = "" );
virtual bool isSequential() const { return false; } virtual bool isSequential() const;
static unsigned int blockSize(); static unsigned int blockSize();
@@ -68,11 +72,9 @@ private:
int offsetForPos( qint64 pos ) const; int offsetForPos( qint64 pos ) const;
QByteArray getData( qint64 pos, qint64 size ); QByteArray getData( qint64 pos, qint64 size );
QList<QByteArray> m_buffer; Q_DECLARE_PRIVATE( BufferIODevice )
mutable QMutex m_mut; //const methods need to lock BufferIODevicePrivate* d_ptr;
unsigned int m_size, m_received;
unsigned int m_pos;
}; };
#endif // BUFFERIODEVICE_H #endif // BUFFERIODEVICE_H

View File

@@ -0,0 +1,47 @@
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
*
* Copyright 2010-2011, Christian Muehlhaeuser <muesli@tomahawk-player.org>
* Copyright 2013, Uwe L. Korn <uwelk@xhochy.com>
*
* Tomahawk 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.
*
* Tomahawk 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 Tomahawk. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef BUFFERIODEVICE_P_H
#define BUFFERIODEVICE_P_H
#include "BufferIoDevice.h"
class BufferIODevicePrivate
{
public:
BufferIODevicePrivate( BufferIODevice* q, unsigned int size = 0 )
: q_ptr ( q )
, size( size )
, received( 0 )
, pos( 0 )
{
}
BufferIODevice* q_ptr;
Q_DECLARE_PUBLIC ( BufferIODevice )
private:
QList<QByteArray> buffer;
mutable QMutex mut;
unsigned int size;
unsigned int received;
unsigned int pos;
};
#endif // BUFFERIODEVICE_P_H