aboutsummaryrefslogtreecommitdiff
path: root/src/plugins/Input/archive/decoder_archive.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/Input/archive/decoder_archive.cpp')
-rw-r--r--src/plugins/Input/archive/decoder_archive.cpp159
1 files changed, 159 insertions, 0 deletions
diff --git a/src/plugins/Input/archive/decoder_archive.cpp b/src/plugins/Input/archive/decoder_archive.cpp
new file mode 100644
index 000000000..89f93cf9a
--- /dev/null
+++ b/src/plugins/Input/archive/decoder_archive.cpp
@@ -0,0 +1,159 @@
+#include <QFile>
+#include <archive_entry.h>
+#include "archiveinputdevice.h"
+#include "decoder_archive.h"
+
+DecoderArchive::DecoderArchive(const QString &url)
+{
+ m_url = url;
+ m_archive = 0;
+ m_decoder = 0;
+ m_input = 0;
+}
+
+DecoderArchive::~DecoderArchive()
+{
+ if(m_decoder)
+ {
+ delete m_decoder;
+ m_decoder = 0;
+ }
+ if(m_input)
+ {
+ delete m_input;
+ m_input = 0;
+ }
+ if(m_archive)
+ {
+ archive_read_close(m_archive);
+ archive_read_free(m_archive);
+ m_archive = 0;
+ }
+}
+
+bool DecoderArchive::initialize()
+{
+ QString filePath = m_url.section("#", -1);
+ QString archivePath = m_url;
+ archivePath.remove(QRegExp("^.+://"));
+ archivePath.remove(QRegExp("#.+$"));
+
+ if(!QFile::exists(archivePath))
+ {
+ qWarning("DecoderArc: file '%s' not found", qPrintable(archivePath));
+ return false;
+ }
+
+ QList<DecoderFactory*> filtered;
+ foreach (DecoderFactory *fact, Decoder::enabledFactories())
+ {
+ if(fact->properties().noInput)
+ continue;
+
+ foreach(QString filter, fact->properties().filters)
+ {
+ QRegExp regexp(filter, Qt::CaseInsensitive, QRegExp::Wildcard);
+ if (regexp.exactMatch(filePath))
+ {
+ filtered.append(fact);
+ break;
+ }
+ }
+ }
+
+ if(filtered.isEmpty())
+ {
+ qWarning("DecoderArc: unable to find decoder");
+ return false;
+ }
+
+ m_archive = archive_read_new();
+ archive_read_support_filter_all(m_archive);
+ archive_read_support_format_all(m_archive);
+
+ int r = archive_read_open_filename(m_archive, archivePath.toLocal8Bit().constData(), 10240);
+ if (r != ARCHIVE_OK)
+ {
+ qWarning("DecoderArc: unable to open file '%s', error code: %d", qPrintable(archivePath), r);
+ return false;
+ }
+
+ struct archive_entry *entry = 0;
+
+ while (archive_read_next_header(m_archive, &entry) == ARCHIVE_OK)
+ {
+ QString pathName = QString::fromLocal8Bit(archive_entry_pathname(entry));
+ if(!pathName.startsWith("/"))
+ pathName.prepend("/");
+
+ if(archive_entry_filetype(entry) == AE_IFREG && filePath == pathName)
+ {
+ m_input = new ArchiveInputDevice(m_archive, entry, 0);
+ break;
+ }
+ archive_read_data_skip(m_archive);
+ }
+
+ if(!m_input)
+ {
+ qWarning("DecoderArc: unable to find file '%s' inside archive '%s'", qPrintable(filePath),
+ qPrintable(archivePath));
+ return false;
+ }
+
+ DecoderFactory *factory = 0;
+ if(filtered.size() == 1)
+ factory = filtered.first();
+ else
+ {
+ //several factories, so trying to determine by content
+ foreach (DecoderFactory *fact, filtered)
+ {
+ if(fact->canDecode(m_input))
+ {
+ factory = fact;
+ break;
+ }
+ }
+ }
+
+ if(!factory)
+ {
+ qWarning("DecoderArc: unable to find supported decoder factory");
+ return false;
+ }
+
+ qDebug("DecoderArc: selected decoder: %s", qPrintable(factory->properties().shortName));
+ qDebug("+");
+ m_decoder = factory->create(m_url, m_input);
+ qDebug("+1");
+ if(!m_decoder->initialize())
+ {
+ qWarning("DecoderArc: unable to initialize decoder");
+ return false;
+ }
+ qDebug("+2");
+ configure(m_decoder->audioParameters().sampleRate(), m_decoder->audioParameters().channelMap(),
+ m_decoder->audioParameters().format());
+ return true;
+}
+
+qint64 DecoderArchive::totalTime() const
+{
+ return m_decoder->totalTime();
+}
+
+void DecoderArchive::seek(qint64 time)
+{
+ m_decoder->seek(time);
+}
+
+qint64 DecoderArchive::read(unsigned char *data, qint64 maxSize)
+{
+ return m_decoder->read(data, maxSize);
+}
+
+int DecoderArchive::bitrate() const
+{
+ return m_decoder->bitrate();
+}