Files
fmviewer3/project/fm_viewer/fav/QIODeviceIO.cpp
2026-02-21 17:11:31 +09:00

257 lines
7.0 KiB
C++

/******************************************************************************
QtAV: Multimedia framework based on Qt and FFmpeg
Copyright (C) 2012-2016 Wang Bin <wbsecg1@gmail.com>
* This file is part of QtAV (from 2014)
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
******************************************************************************/
#include "MediaIO.h"
#include "MediaIO_p.h"
#include "mkid.h"
#include "factory.h"
#include <QtCore/QFile>
#ifndef TEST_QTAV_QIODeviceIO
#include "Logger.h"
#else
#include <QtDebug>
#endif
namespace FAV {
class QIODeviceIOPrivate;
class QIODeviceIO : public MediaIO
{
Q_OBJECT
Q_PROPERTY(QIODevice* device READ device WRITE setDevice NOTIFY deviceChanged)
DPTR_DECLARE_PRIVATE(QIODeviceIO)
public:
QIODeviceIO();
virtual QString name() const Q_DECL_OVERRIDE;
// MUST open/close outside
void setDevice(QIODevice *dev); // set private in QFileIO etc
QIODevice* device() const;
virtual bool isSeekable() const Q_DECL_OVERRIDE;
virtual bool isWritable() const Q_DECL_OVERRIDE;
virtual qint64 read(char *data, qint64 maxSize) Q_DECL_OVERRIDE;
virtual qint64 write(const char *data, qint64 maxSize) Q_DECL_OVERRIDE;
virtual bool seek(qint64 offset, int from) Q_DECL_OVERRIDE;
virtual qint64 position() const Q_DECL_OVERRIDE;
/*!
* \brief size
* \return <=0 if not support
*/
virtual qint64 size() const Q_DECL_OVERRIDE;
Q_SIGNALS:
void deviceChanged();
protected:
QIODeviceIO(QIODeviceIOPrivate &d);
};
typedef QIODeviceIO MediaIOQIODevice;
static const MediaIOId MediaIOId_QIODevice = mkid::id32base36_6<'Q','I','O','D','e','v'>::value;
static const char kQIODevName[] = "QIODevice";
FACTORY_REGISTER(MediaIO, QIODevice, kQIODevName)
class QIODeviceIOPrivate : public MediaIOPrivate
{
public:
QIODeviceIOPrivate()
: MediaIOPrivate()
, dev(0)
{}
QIODevice *dev;
};
QIODeviceIO::QIODeviceIO() : MediaIO(*new QIODeviceIOPrivate()) {}
QIODeviceIO::QIODeviceIO(QIODeviceIOPrivate &d) : MediaIO(d) {}
QString QIODeviceIO::name() const { return QLatin1String(kQIODevName);}
void QIODeviceIO::setDevice(QIODevice *dev)
{
DPTR_D(QIODeviceIO);
if (d.dev == dev)
return;
d.dev = dev;
emit deviceChanged();
}
QIODevice* QIODeviceIO::device() const
{
return d_func().dev;
}
bool QIODeviceIO::isSeekable() const
{
DPTR_D(const QIODeviceIO);
return d.dev && !d.dev->isSequential();
}
bool QIODeviceIO::isWritable() const
{
DPTR_D(const QIODeviceIO);
return d.dev && d.dev->isWritable();
}
qint64 QIODeviceIO::read(char *data, qint64 maxSize)
{
DPTR_D(QIODeviceIO);
if (!d.dev)
return 0;
return d.dev->read(data, maxSize);
}
qint64 QIODeviceIO::write(const char *data, qint64 maxSize)
{
DPTR_D(QIODeviceIO);
if (!d.dev)
return 0;
return d.dev->write(data, maxSize);
}
bool QIODeviceIO::seek(qint64 offset, int from)
{
DPTR_D(QIODeviceIO);
if (!d.dev)
return false;
if (from == SEEK_END) {
offset = d.dev->size() - offset;
} else if (from == SEEK_CUR) {
offset = d.dev->pos() + offset;
}
return d.dev->seek(offset);
}
qint64 QIODeviceIO::position() const
{
DPTR_D(const QIODeviceIO);
if (!d.dev)
return 0;
return d.dev->pos();
}
qint64 QIODeviceIO::size() const
{
DPTR_D(const QIODeviceIO);
if (!d.dev)
return 0;
return d.dev->size(); // sequential device returns bytesAvailable()
}
// qrc support
static const char kQFileName[] = "QFile";
class QFileIOPrivate;
class QFileIO Q_DECL_FINAL: public QIODeviceIO
{
DPTR_DECLARE_PRIVATE(QFileIO)
public:
QFileIO();
QString name() const Q_DECL_OVERRIDE { return QLatin1String(kQFileName);}
const QStringList& protocols() const Q_DECL_OVERRIDE
{
static QStringList p = QStringList() << QStringLiteral("") << QStringLiteral("qrc") << QStringLiteral("qfile")
#ifdef Q_OS_ANDROID
<< QStringLiteral("assets")
#endif
#ifdef Q_OS_IOS
<< QStringLiteral("assets-library")
#endif
;
return p;
}
protected:
void onUrlChanged() Q_DECL_OVERRIDE;
private:
using QIODeviceIO::setDevice;
};
typedef QFileIO MediaIOQFile;
static const MediaIOId MediaIOId_QFile = mkid::id32base36_5<'Q','F','i','l','e'>::value;
FACTORY_REGISTER(MediaIO, QFile, kQFileName)
class QFileIOPrivate Q_DECL_FINAL: public QIODeviceIOPrivate
{
public:
QFileIOPrivate() : QIODeviceIOPrivate() {}
~QFileIOPrivate() {
if (file.isOpen())
file.close();
}
QFile file;
};
QFileIO::QFileIO()
: QIODeviceIO(*new QFileIOPrivate())
{
setDevice(&d_func().file);
}
void QFileIO::onUrlChanged()
{
DPTR_D(QFileIO);
if (d.file.isOpen())
d.file.close();
QString path(url());
if (path.startsWith(QLatin1String("qrc:"))) {
path = path.mid(3);
} else if (path.startsWith(QLatin1String("qfile:"))) {
path = path.mid(6);
#ifdef Q_OS_WIN
int p = path.indexOf(QLatin1Char(':'));
if (p < 1) {
qWarning("invalid path. ':' wrong position");
return;
}
p -= 1;
QChar c = path.at(p).toUpper();
if (c < QLatin1Char('A') || c > QLatin1Char('Z')) {
qWarning("invalid path. wrong driver");
return;
}
const QString path_maybe = path.mid(p);
qDebug() << path_maybe;
--p;
while (p > 0) {
c = path.at(p);
if (c != QLatin1Char('\\') && c != QLatin1Char('/')) {
qWarning("invalid path. wrong dir seperator");
return;
}
--p;
}
path = path_maybe;
#endif
}
d.file.setFileName(path);
if (path.isEmpty())
return;
if (!d.file.open(QIODevice::ReadOnly))
qWarning() << "Failed to open [" << d.file.fileName() << "]: " << d.file.errorString();
}
} //namespace FAV
#include "QIODeviceIO.moc"
#ifdef TEST_QTAV_QIODeviceIO
int main(int, char**)
{
QtAV::QFileIO fi;
qDebug() << "protocols: " << fi.protocols();
fi.setUrl("qrc:/QtAV.svg");
QByteArray data(1024, 0);
fi.read(data.data(), data.size());
qDebug("QFileIO url: %s, seekable: %d, size: %lld", fi.url().toUtf8().constData(), fi.isSeekable(), fi.size());
qDebug() << data;
return 0;
}
#endif