#include #include #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 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(); }