diff options
| author | trialuser02 <trialuser02@90c681e8-e032-0410-971d-27865f9a5e38> | 2008-10-30 21:01:26 +0000 |
|---|---|---|
| committer | trialuser02 <trialuser02@90c681e8-e032-0410-971d-27865f9a5e38> | 2008-10-30 21:01:26 +0000 |
| commit | 311224cda472f8d308884353960cab6231bb769d (patch) | |
| tree | 2407b572357a1a4cc10e184493da528fe69109c4 | |
| parent | 304dc519d9d68b3861af998a997c5f2a97c9235d (diff) | |
| download | qmmp-311224cda472f8d308884353960cab6231bb769d.tar.gz qmmp-311224cda472f8d308884353960cab6231bb769d.tar.bz2 qmmp-311224cda472f8d308884353960cab6231bb769d.zip | |
AAC plugin: fixed seeking; id3v2 tags support
git-svn-id: http://svn.code.sf.net/p/qmmp-dev/code/trunk/qmmp@606 90c681e8-e032-0410-971d-27865f9a5e38
| -rw-r--r-- | src/plugins/Input/CMakeLists.txt | 4 | ||||
| -rw-r--r-- | src/plugins/Input/aac/CMakeLists.txt | 2 | ||||
| -rw-r--r-- | src/plugins/Input/aac/aac.pro | 6 | ||||
| -rw-r--r-- | src/plugins/Input/aac/aacfile.cpp | 9 | ||||
| -rw-r--r-- | src/plugins/Input/aac/aacfile.h | 10 | ||||
| -rw-r--r-- | src/plugins/Input/aac/decoder_aac.cpp | 7 | ||||
| -rw-r--r-- | src/plugins/Input/aac/decoderaacfactory.cpp | 22 | ||||
| -rw-r--r-- | src/plugins/Input/aac/tagextractor.cpp | 115 | ||||
| -rw-r--r-- | src/plugins/Input/aac/tagextractor.h | 68 |
9 files changed, 218 insertions, 25 deletions
diff --git a/src/plugins/Input/CMakeLists.txt b/src/plugins/Input/CMakeLists.txt index 1164598c0..c5c82edef 100644 --- a/src/plugins/Input/CMakeLists.txt +++ b/src/plugins/Input/CMakeLists.txt @@ -50,6 +50,6 @@ IF(USE_AAC) add_subdirectory(aac) ENDIF(USE_AAC) -IF(USE_CUE) +IF(USE_CUE AND TAGLIB_FOUND) add_subdirectory(cue) -ENDIF(USE_CUE) +ENDIF(USE_CUE AND TAGLIB_FOUND) diff --git a/src/plugins/Input/aac/CMakeLists.txt b/src/plugins/Input/aac/CMakeLists.txt index 1da0221c8..ae9d22b32 100644 --- a/src/plugins/Input/aac/CMakeLists.txt +++ b/src/plugins/Input/aac/CMakeLists.txt @@ -39,6 +39,7 @@ SET(libaac_SRCS decoderaacfactory.cpp detailsdialog.cpp aacfile.cpp + tagextractor.cpp ) SET(libaac_MOC_HDRS @@ -46,6 +47,7 @@ SET(libaac_MOC_HDRS decoder_aac.h detailsdialog.h aacfile.h + tagextractor.h ) #SET(libaac_RCCS translations/translations.qrc) diff --git a/src/plugins/Input/aac/aac.pro b/src/plugins/Input/aac/aac.pro index 5bc0cb38a..01e2bbff0 100644 --- a/src/plugins/Input/aac/aac.pro +++ b/src/plugins/Input/aac/aac.pro @@ -4,11 +4,13 @@ FORMS += detailsdialog.ui HEADERS += decoderaacfactory.h \ decoder_aac.h \ detailsdialog.h \ - aacfile.h + aacfile.h \ + tagextractor.h SOURCES += decoder_aac.cpp \ decoderaacfactory.cpp \ detailsdialog.cpp \ - aacfile.cpp + aacfile.cpp \ + tagextractor.cpp TARGET =$$PLUGINS_PREFIX/Input/aac QMAKE_CLEAN =$$PLUGINS_PREFIX/Input/libaac.so diff --git a/src/plugins/Input/aac/aacfile.cpp b/src/plugins/Input/aac/aacfile.cpp index f25c31202..8df0592f5 100644 --- a/src/plugins/Input/aac/aacfile.cpp +++ b/src/plugins/Input/aac/aacfile.cpp @@ -22,6 +22,7 @@ #include <neaacdec.h> +#include "tagextractor.h" #include "aacfile.h" #define MAX_CHANNELS 6 @@ -34,6 +35,7 @@ AACFile::AACFile(QIODevice *i) m_isValid = FALSE; m_length = 0; m_bitrate = 0; + m_ext = 0; m_input = i; uchar buf[AAC_BUFFER_SIZE]; qint64 buf_at = i->peek((char *) buf, AAC_BUFFER_SIZE); @@ -52,6 +54,8 @@ AACFile::AACFile(QIODevice *i) return; } memmove (buf, buf + tag_size, buf_at - tag_size); + + m_ext = new TagExtractor(i); } //try to determenate header type; if (buf[0] == 0xff && ((buf[1] & 0xf6) == 0xf0)) @@ -165,3 +169,8 @@ bool AACFile::isValid() { return m_isValid; } + +const QMap<Qmmp::MetaData, QString> AACFile::metaData() +{ + return m_ext ? m_ext->id3v2tag() : QMap<Qmmp::MetaData, QString>(); +} diff --git a/src/plugins/Input/aac/aacfile.h b/src/plugins/Input/aac/aacfile.h index 4199a3c05..3c9c2bf48 100644 --- a/src/plugins/Input/aac/aacfile.h +++ b/src/plugins/Input/aac/aacfile.h @@ -20,7 +20,14 @@ #ifndef AACFILE_H #define AACFILE_H + +#include <QMap> +#include <QString> + +#include <qmmp/qmmp.h> + class QIODevice; +class TagExtractor; /** @author Ilya Kotov <forkotov02@hotmail.ru> @@ -35,6 +42,7 @@ public: qint64 length(); quint32 bitrate(); bool isValid(); + const QMap<Qmmp::MetaData, QString> metaData(); private: void parseADTS(); @@ -42,6 +50,8 @@ private: quint32 m_bitrate; QIODevice *m_input; bool m_isValid; + QMap<Qmmp::MetaData, QString> m_metaData; + TagExtractor *m_ext; }; #endif diff --git a/src/plugins/Input/aac/decoder_aac.cpp b/src/plugins/Input/aac/decoder_aac.cpp index 65d91e4ed..6953a686c 100644 --- a/src/plugins/Input/aac/decoder_aac.cpp +++ b/src/plugins/Input/aac/decoder_aac.cpp @@ -240,6 +240,11 @@ qint64 DecoderAAC::aac_decode(void *out) if ((size = frame_info.samples * 2) > 0) memcpy((void *) (m_output_buf + m_output_at), out, size); + if (frame_info.error > 0) + { + m_input_at = 0; + qDebug("DecoderAAC: %s", NeAACDecGetErrorMessage(frame_info.error)); + } } return size; } @@ -285,7 +290,7 @@ void DecoderAAC::run() if (m_seekTime >= 0 && m_totalTime) { input()->seek(m_seekTime * input()->size() / m_totalTime); - NeAACDecPostSeekReset (data()->handle, -1); + NeAACDecPostSeekReset (data()->handle, 0); m_input_at = 0; m_seekTime = -1.0; } diff --git a/src/plugins/Input/aac/decoderaacfactory.cpp b/src/plugins/Input/aac/decoderaacfactory.cpp index 2f5b621ee..9b91f1d45 100644 --- a/src/plugins/Input/aac/decoderaacfactory.cpp +++ b/src/plugins/Input/aac/decoderaacfactory.cpp @@ -63,29 +63,11 @@ QList<FileInfo *> DecoderAACFactory::createPlayList(const QString &fileName) { FileInfo *info = new FileInfo(fileName); - /*TagLib::FileRef fileRef(fileName.toLocal8Bit ()); - TagLib::Tag *tag = fileRef.tag(); - if (tag && !tag->isEmpty()) - { - info->setMetaData(Qmmp::ALBUM, - QString::fromUtf8(tag->album().toCString(TRUE)).trimmed()); - info->setMetaData(Qmmp::ARTIST, - QString::fromUtf8(tag->artist().toCString(TRUE)).trimmed()); - info->setMetaData(Qmmp::COMMENT, - QString::fromUtf8(tag->comment().toCString(TRUE)).trimmed()); - info->setMetaData(Qmmp::GENRE, - QString::fromUtf8(tag->genre().toCString(TRUE)).trimmed()); - info->setMetaData(Qmmp::TITLE, - QString::fromUtf8(tag->title().toCString(TRUE)).trimmed()); - info->setMetaData(Qmmp::YEAR, tag->year()); - info->setMetaData(Qmmp::TRACK, tag->track()); - } - if (fileRef.audioProperties()) - info->setLength(fileRef.audioProperties()->length());*/ QFile file(fileName); - if(file.open(QIODevice::ReadOnly)) + if (file.open(QIODevice::ReadOnly)) { AACFile aac_file(&file); + info->setMetaData(aac_file.metaData()); info->setLength(aac_file.length()); } QList <FileInfo*> list; diff --git a/src/plugins/Input/aac/tagextractor.cpp b/src/plugins/Input/aac/tagextractor.cpp new file mode 100644 index 000000000..1385c8a85 --- /dev/null +++ b/src/plugins/Input/aac/tagextractor.cpp @@ -0,0 +1,115 @@ +/*************************************************************************** + * Copyright (C) 2008 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program 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 2 of the License, or * + * (at your option) any later version. * + * * + * This program 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 this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include <QIODevice> +#include <QSettings> +#include <QByteArray> +#include <QBuffer> +#include <QTextCodec> +#include <QSettings> +#include <QDir> +#include <stdlib.h> + +#include "tagextractor.h" + +TagExtractor::TagExtractor(QIODevice *d) +{ + m_d = d; +} + + +TagExtractor::~TagExtractor() +{ +} + +const QMap<Qmmp::MetaData, QString> TagExtractor::id3v2tag() +{ + QByteArray array = m_d->peek(2048); + int offset = array.indexOf("ID3"); + if (offset < 0) + return m_tag; + ID3v2Tag taglib_tag(&array, offset); + if (taglib_tag.isEmpty()) + return m_tag; + + TagLib::String album = taglib_tag.album(); + TagLib::String artist = taglib_tag.artist(); + TagLib::String comment = taglib_tag.comment(); + TagLib::String genre = taglib_tag.genre(); + TagLib::String title = taglib_tag.title(); + + QSettings settings(QDir::homePath()+"/.qmmp/qmmprc", QSettings::IniFormat); + settings.beginGroup("MAD"); + QByteArray name = settings.value("ID3v2_encoding","UTF-8").toByteArray (); + bool utf = FALSE; + QTextCodec *codec = 0; + if (name.contains("UTF")) + { + codec = QTextCodec::codecForName ("UTF-8"); + utf = TRUE; + } + else + codec = QTextCodec::codecForName(name); + settings.endGroup(); + + if (!codec) + codec = QTextCodec::codecForName ("UTF-8"); + + m_tag.insert(Qmmp::ALBUM, + codec->toUnicode(album.toCString(utf)).trimmed()); + m_tag.insert(Qmmp::ARTIST, + codec->toUnicode(artist.toCString(utf)).trimmed()); + m_tag.insert(Qmmp::COMMENT, + codec->toUnicode(comment.toCString(utf)).trimmed()); + m_tag.insert(Qmmp::GENRE, + codec->toUnicode(genre.toCString(utf)).trimmed()); + m_tag.insert(Qmmp::TITLE, + codec->toUnicode(title.toCString(utf)).trimmed()); + m_tag.insert(Qmmp::YEAR, + QString::number(taglib_tag.year())); + m_tag.insert(Qmmp::TRACK, + QString::number(taglib_tag.track())); + + return m_tag; + +} + +ID3v2Tag::ID3v2Tag(QByteArray *array, long offset) : TagLib::ID3v2::Tag() +{ + m_buf = new QBuffer(array); + m_buf->open(QIODevice::ReadOnly); + m_offset = offset; + read(); +} + +void ID3v2Tag::read () +{ + m_buf->seek(m_offset); + uint to_read = TagLib::ID3v2::Header::size(); + if (to_read > 2048 - uint(m_offset)) + return; + header()->setData(TagLib::ByteVector(m_buf->read(to_read).data(), to_read)); + to_read = header()->tagSize(); + if (!to_read || 2048 < m_offset + TagLib::ID3v2::Header::size()) + return; + QByteArray array = m_buf->read(to_read); + TagLib::ByteVector v(array.data(), array.size()); + parse(v); +} diff --git a/src/plugins/Input/aac/tagextractor.h b/src/plugins/Input/aac/tagextractor.h new file mode 100644 index 000000000..707719535 --- /dev/null +++ b/src/plugins/Input/aac/tagextractor.h @@ -0,0 +1,68 @@ +/*************************************************************************** + * Copyright (C) 2008 by Ilya Kotov * + * forkotov02@hotmail.ru * + * * + * This program 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 2 of the License, or * + * (at your option) any later version. * + * * + * This program 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 this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#ifndef TAGEXTRACTOR_H +#define TAGEXTRACTOR_H + +#include <QMap> + +#include <taglib/tag.h> +#include <taglib/fileref.h> +#include <taglib/id3v1tag.h> +#include <taglib/id3v2tag.h> +#include <taglib/id3v2header.h> + +#include <qmmp/qmmp.h> + +class QIODevice; +class QBuffer; +class QByteArray; + +/** + @author Ilya Kotov <forkotov02@hotmail.ru> +*/ +class TagExtractor +{ +public: + TagExtractor(QIODevice *d); + + ~TagExtractor(); + + const QMap<Qmmp::MetaData, QString> id3v2tag(); + +private: + QMap<Qmmp::MetaData, QString> m_tag; + QIODevice *m_d; + +}; + +class ID3v2Tag : public TagLib::ID3v2::Tag +{ +public: + ID3v2Tag(QByteArray *array, long offset); + +protected: + void read (); + +private: + QBuffer *m_buf; + long m_offset; +}; + +#endif |
