diff options
| -rw-r--r-- | src/plugins/Input/CMakeLists.txt | 2 | ||||
| -rw-r--r-- | src/plugins/Input/Input.pro | 2 | ||||
| -rw-r--r-- | src/plugins/Input/wavpack/CMakeLists.txt | 4 | ||||
| -rw-r--r-- | src/plugins/Input/wavpack/cueparser.cpp | 5 | ||||
| -rw-r--r-- | src/plugins/Input/wavpack/cueparser.h | 2 | ||||
| -rw-r--r-- | src/plugins/Input/wavpack/decoder_wavpack.cpp | 162 | ||||
| -rw-r--r-- | src/plugins/Input/wavpack/decoder_wavpack.h | 32 | ||||
| -rw-r--r-- | src/plugins/Input/wavpack/decoderwavpackfactory.cpp | 14 | ||||
| -rw-r--r-- | src/plugins/Input/wavpack/decoderwavpackfactory.h | 4 | ||||
| -rw-r--r-- | src/plugins/Input/wavpack/detailsdialog.cpp | 139 | ||||
| -rw-r--r-- | src/plugins/Input/wavpack/wavpack.pro | 8 | ||||
| -rw-r--r-- | src/plugins/Input/wavpack/wavpackmetadatamodel.cpp | 157 | ||||
| -rw-r--r-- | src/plugins/Input/wavpack/wavpackmetadatamodel.h (renamed from src/plugins/Input/wavpack/detailsdialog.h) | 45 |
13 files changed, 339 insertions, 237 deletions
diff --git a/src/plugins/Input/CMakeLists.txt b/src/plugins/Input/CMakeLists.txt index 66a2f46fa..0376e68da 100644 --- a/src/plugins/Input/CMakeLists.txt +++ b/src/plugins/Input/CMakeLists.txt @@ -7,7 +7,7 @@ SET(USE_VORBIS TRUE CACHE BOOL "enable/disable ogg vorbis plugin") #SET(USE_FFMPEG TRUE CACHE BOOL "enable/disable ffmpeg plugin") SET(USE_MPC TRUE CACHE BOOL "enable/disable mpc plugin") SET(USE_SNDFILE TRUE CACHE BOOL "enable/disable sndfile plugin") -#SET(USE_WAVPACK TRUE CACHE BOOL "enable/disable wavpack plugin") +SET(USE_WAVPACK TRUE CACHE BOOL "enable/disable wavpack plugin") #SET(USE_MODPLUG TRUE CACHE BOOL "enable/disable modplug plugin") #SET(USE_AAC TRUE CACHE BOOL "enable/disable aac plugin") SET(USE_CUE TRUE CACHE BOOL "enable/disable cue plugin") diff --git a/src/plugins/Input/Input.pro b/src/plugins/Input/Input.pro index 6ba4f6719..14504de50 100644 --- a/src/plugins/Input/Input.pro +++ b/src/plugins/Input/Input.pro @@ -4,7 +4,7 @@ SUBDIRS += mad cue TEMPLATE = subdirs unix{ -SUBDIRS += vorbis sndfile# wavpack +SUBDIRS += vorbis sndfile wavpack contains(CONFIG, MODPLUG_PLUGIN){ # SUBDIRS += modplug message(***************************) diff --git a/src/plugins/Input/wavpack/CMakeLists.txt b/src/plugins/Input/wavpack/CMakeLists.txt index 55fe84b53..0d7566265 100644 --- a/src/plugins/Input/wavpack/CMakeLists.txt +++ b/src/plugins/Input/wavpack/CMakeLists.txt @@ -34,14 +34,14 @@ link_directories(${WAVPACK_LIBRARY_DIRS}) SET(libwavpack_SRCS decoder_wavpack.cpp decoderwavpackfactory.cpp - detailsdialog.cpp + wavpackmetadatamodel.cpp cueparser.cpp ) SET(libwavpack_MOC_HDRS decoderwavpackfactory.h decoder_wavpack.h - detailsdialog.h + wavpackmetadatamodel.h cueparser.h ) diff --git a/src/plugins/Input/wavpack/cueparser.cpp b/src/plugins/Input/wavpack/cueparser.cpp index f9cecf264..bab5c35f7 100644 --- a/src/plugins/Input/wavpack/cueparser.cpp +++ b/src/plugins/Input/wavpack/cueparser.cpp @@ -152,6 +152,11 @@ FileInfo *CUEParser::info(int track) return &m_infoList[track - 1]; } +const QString CUEParser::trackURL(int track) +{ + return m_infoList[track - 1].path(); +} + QStringList CUEParser::splitLine(const QString &line) { //qDebug("row string = %s",qPrintable(line)); diff --git a/src/plugins/Input/wavpack/cueparser.h b/src/plugins/Input/wavpack/cueparser.h index b30b87bfa..fe3471c2c 100644 --- a/src/plugins/Input/wavpack/cueparser.h +++ b/src/plugins/Input/wavpack/cueparser.h @@ -45,6 +45,7 @@ public: qint64 length(int track); int count(); FileInfo *info(int track); + const QString trackURL(int track); private: QString m_filePath; @@ -52,7 +53,6 @@ private: QList <qint64> m_offsets; QStringList splitLine(const QString &line); qint64 getLength(const QString &str); - }; #endif diff --git a/src/plugins/Input/wavpack/decoder_wavpack.cpp b/src/plugins/Input/wavpack/decoder_wavpack.cpp index 4a8900011..ec3ca0ca2 100644 --- a/src/plugins/Input/wavpack/decoder_wavpack.cpp +++ b/src/plugins/Input/wavpack/decoder_wavpack.cpp @@ -35,16 +35,22 @@ // Decoder class -DecoderWavPack::DecoderWavPack(QObject *parent, DecoderFactory *d, Output *o, const QString &path) - : Decoder(parent, d, o) +DecoderWavPack::DecoderWavPack(const QString &path) + : Decoder() { m_path = path; m_totalTime = 0.0; m_chan = 0; m_context = 0; m_freq = 0; - m_cue_parser = 0; + m_parser = 0; m_output_buf = 0; + m_parser = 0; + length_in_bytes = 0; + m_totalBytes = 0; + m_sz = 0; + m_buf = 0; + m_offset = 0; } DecoderWavPack::~DecoderWavPack() @@ -73,24 +79,17 @@ bool DecoderWavPack::initialize() { value = (char*)malloc (cue_len * 2 + 1); WavpackGetTagItem (m_context, "cuesheet", value, cue_len + 1); - m_cue_parser = new CUEParser(value, p); - int track = m_path.section("#", -1).toInt(); - if(track > m_cue_parser->count()) + m_parser = new CUEParser(value, p); + m_track = m_path.section("#", -1).toInt(); + if(m_track > m_parser->count()) { qWarning("DecoderWavPack: invalid cuesheet comment"); return FALSE; } m_path = p; //send metadata - QMap<Qmmp::MetaData, QString> metaData = m_cue_parser->info(track)->metaData(); + QMap<Qmmp::MetaData, QString> metaData = m_parser->info(m_track)->metaData(); StateHandler::instance()->dispatch(metaData); - connect(stateHandler(),SIGNAL(aboutToFinish()),SLOT(processFinish())); - //next url - m_nextUrl.clear(); - if(track <= m_cue_parser->count() - 1) - m_nextUrl = m_cue_parser->info(track + 1)->path(); - m_totalTime = m_cue_parser->length(track); - setFragment(m_cue_parser->offset(track), m_cue_parser->length(track)); } } else @@ -108,8 +107,19 @@ bool DecoderWavPack::initialize() if (!m_output_buf) m_output_buf = new int32_t[Qmmp::globalBufferSize()/4]; configure(m_freq, m_chan, bps); - if(!m_cue_parser) + if(!m_parser) m_totalTime = (qint64) WavpackGetNumSamples(m_context) * 1000 / m_freq; + else + { + m_length = m_parser->length(m_track); + m_offset = m_parser->offset(m_track); + length_in_bytes = audioParameters().sampleRate() * + audioParameters().channels() * + audioParameters().bits() * m_length/8000; + seek(0); + } + m_totalBytes = 0; + m_sz = audioParameters().bits() * audioParameters().channels()/8; qDebug("DecoderWavPack: initialize succes"); return TRUE; } @@ -123,6 +133,8 @@ int DecoderWavPack::bitrate() qint64 DecoderWavPack::totalTime() { + if(m_parser) + return m_length; return m_totalTime; } @@ -133,19 +145,98 @@ void DecoderWavPack::deinit() if (m_context) WavpackCloseFile (m_context); m_context = 0; - if(m_cue_parser) - delete m_cue_parser; - m_cue_parser = 0; + if(m_parser) + delete m_parser; + m_parser = 0; + if(m_buf) + delete m_buf; + m_buf = 0; } -void DecoderWavPack::seekAudio(qint64 time) +void DecoderWavPack::seek(qint64 time) { - WavpackSeekSample (m_context, time * m_freq / 1000); + m_totalBytes = audioParameters().sampleRate() * + audioParameters().channels() * + audioParameters().bits() * time/8000; + if(m_parser) + time += m_offset; + WavpackSeekSample (m_context, time * m_freq / 1000); } -qint64 DecoderWavPack::readAudio(char *data, qint64 maxSize) +qint64 DecoderWavPack::read(char *data, qint64 size) { - ulong len = WavpackUnpackSamples (m_context, m_output_buf, maxSize / m_chan / 4); + if(m_parser) + { + if(length_in_bytes - m_totalBytes < m_sz) //end of cue track + return 0; + + qint64 len = 0; + + if(m_buf) //read remaining data first + { + len = qMin(m_buf_size, size); + memmove(data, m_buf, len); + if(size >= m_buf_size) + { + delete[] m_buf; + m_buf = 0; + m_buf_size = 0; + } + else + memmove(m_buf, m_buf + len, size - len); + } + else + len = wavpack_decode (data, size); + + if(len <= 0) //end of file + return 0; + + if(len + m_totalBytes <= length_in_bytes) + { + m_totalBytes += len; + return len; + } + + qint64 len2 = qMax(qint64(0), length_in_bytes - m_totalBytes); + len2 = (len2 / m_sz) * m_sz; //returned size must contain integer number of samples + m_totalBytes += len2; + //save data of the next track + if(m_buf) + delete[] m_buf; + m_buf_size = len - len2; + m_buf = new char[m_buf_size]; + memmove(m_buf, data + len2, m_buf_size); + return len2; + } + return wavpack_decode(data, size); +} + +const QString DecoderWavPack::nextURL() +{ + if(m_parser && m_track +1 <= m_parser->count()) + return m_parser->trackURL(m_track + 1); + else + return QString(); +} + +void DecoderWavPack::next() +{ + if(m_parser && m_track +1 <= m_parser->count()) + { + m_track++; + m_offset = m_parser->length(m_track); + m_length = m_parser->length(m_track); + length_in_bytes = audioParameters().sampleRate() * + audioParameters().channels() * + audioParameters().bits() * m_length/8000; + StateHandler::instance()->dispatch(m_parser->info(m_track)->metaData()); + m_totalBytes = 0; + } +} + +qint64 DecoderWavPack::wavpack_decode(char *data, qint64 size) +{ + ulong len = WavpackUnpackSamples (m_context, m_output_buf, size / m_chan / 4); uint m = 0; //convert 32 to 16 for (uint i = 0; i < len * m_chan; ++i) @@ -155,30 +246,3 @@ qint64 DecoderWavPack::readAudio(char *data, qint64 maxSize) } return len * m_chan * 2; } - -void DecoderWavPack::processFinish() -{ - if(m_cue_parser && nextUrlRequest(m_nextUrl)) - { - qDebug("DecoderFLAC: going to next track"); - int track = m_nextUrl.section("#", -1).toInt(); - QString p = QUrl(m_nextUrl).path(); - p.replace(QString(QUrl::toPercentEncoding("#")), "#"); - p.replace(QString(QUrl::toPercentEncoding("%")), "%"); - //update current fragment - mutex()->lock(); - setFragment(m_cue_parser->offset(track), m_cue_parser->length(track)); - m_totalTime = m_cue_parser->length(track); - output()->seek(0); //reset time counter - mutex()->unlock(); - // find next track - m_nextUrl.clear(); - if(track <= m_cue_parser->count() - 1) - m_nextUrl = m_cue_parser->info(track + 1)->path(); - //change track - emit playbackFinished(); - //send metadata - QMap<Qmmp::MetaData, QString> metaData = m_cue_parser->info(track)->metaData(); - stateHandler()->dispatch(metaData); - } -} diff --git a/src/plugins/Input/wavpack/decoder_wavpack.h b/src/plugins/Input/wavpack/decoder_wavpack.h index a6704abc2..dc8f6102b 100644 --- a/src/plugins/Input/wavpack/decoder_wavpack.h +++ b/src/plugins/Input/wavpack/decoder_wavpack.h @@ -30,33 +30,39 @@ class CUEParser; class DecoderWavPack : public Decoder { -Q_OBJECT public: - DecoderWavPack(QObject *, DecoderFactory *, Output *, const QString &); + DecoderWavPack(const QString &); virtual ~DecoderWavPack(); // Standard Decoder API bool initialize(); qint64 totalTime(); int bitrate(); - -private slots: - void processFinish(); + qint64 read(char *data, qint64 maxSize); + void seek(qint64 time); + const QString nextURL(); + void next(); private: - // Standard Decoder API - qint64 readAudio(char *data, qint64 maxSize); - void seekAudio(qint64 time); // helper functions void deinit(); - WavpackContext *m_context; - // output buffer - int32_t *m_output_buf; + qint64 wavpack_decode(char *data, qint64 size); + WavpackContext *m_context; + int32_t *m_output_buf; // output buffer int m_chan; quint32 m_freq; qint64 m_totalTime; - QString m_path, m_nextUrl; - CUEParser *m_cue_parser; + qint64 length_in_bytes; + qint64 m_totalBytes; + qint64 m_offset; + qint64 m_length; + QString m_path; + CUEParser *m_parser; + int m_track; + char *m_buf; //buffer for remainig data + qint64 m_buf_size; + qint64 m_sz; //sample size + }; #endif // DECODER_WAVPACK_H diff --git a/src/plugins/Input/wavpack/decoderwavpackfactory.cpp b/src/plugins/Input/wavpack/decoderwavpackfactory.cpp index ad6f192cd..d36120857 100644 --- a/src/plugins/Input/wavpack/decoderwavpackfactory.cpp +++ b/src/plugins/Input/wavpack/decoderwavpackfactory.cpp @@ -20,7 +20,7 @@ #include <QtGui> -#include "detailsdialog.h" +#include "wavpackmetadatamodel.h" #include "decoder_wavpack.h" #include "decoderwavpackfactory.h" #include "cueparser.h" @@ -53,11 +53,9 @@ const DecoderProperties DecoderWavPackFactory::properties() const return properties; } -Decoder *DecoderWavPackFactory::create(QObject *parent, QIODevice *input, - Output *output, const QString &path) +Decoder *DecoderWavPackFactory::create(const QString &p, QIODevice *) { - Q_UNUSED(input); - return new DecoderWavPack(parent, this, output, path); + return new DecoderWavPack(p); } QList<FileInfo *> DecoderWavPackFactory::createPlayList(const QString &fileName, bool useMetaData) @@ -118,11 +116,9 @@ QList<FileInfo *> DecoderWavPackFactory::createPlayList(const QString &fileName, return list; } -QObject* DecoderWavPackFactory::showDetails(QWidget *parent, const QString &path) +MetaDataModel* DecoderWavPackFactory::createMetaDataModel(const QString &path, QObject *parent) { - DetailsDialog *d = new DetailsDialog(parent, path); - d -> show(); - return d; + return new WavPackMetaDataModel(path, parent); } void DecoderWavPackFactory::showSettings(QWidget *) diff --git a/src/plugins/Input/wavpack/decoderwavpackfactory.h b/src/plugins/Input/wavpack/decoderwavpackfactory.h index 71384e00c..5fc3c5d69 100644 --- a/src/plugins/Input/wavpack/decoderwavpackfactory.h +++ b/src/plugins/Input/wavpack/decoderwavpackfactory.h @@ -41,9 +41,9 @@ public: bool supports(const QString &source) const; bool canDecode(QIODevice *input) const; const DecoderProperties properties() const; - Decoder *create(QObject *, QIODevice *, Output *, const QString &); + Decoder *create(const QString &p, QIODevice *i); QList<FileInfo *> createPlayList(const QString &fileName, bool useMetaData); - QObject* showDetails(QWidget *parent, const QString &path); + MetaDataModel* createMetaDataModel(const QString &path, QObject *parent = 0); void showSettings(QWidget *parent); void showAbout(QWidget *parent); QTranslator *createTranslator(QObject *parent); diff --git a/src/plugins/Input/wavpack/detailsdialog.cpp b/src/plugins/Input/wavpack/detailsdialog.cpp deleted file mode 100644 index c22233987..000000000 --- a/src/plugins/Input/wavpack/detailsdialog.cpp +++ /dev/null @@ -1,139 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2006-2009 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. * - ***************************************************************************/ -extern "C"{ -#include <wavpack/wavpack.h> -} - -#include <QFile> -#include <QFileInfo> - -#include "detailsdialog.h" - -#define QStringToTString_qt4(s) TagLib::String(s.toUtf8().constData(), TagLib::String::UTF8) -#define TStringToQString_qt4(s) QString::fromUtf8(s.toCString(TRUE)).trimmed() - -DetailsDialog::DetailsDialog(QWidget *parent, const QString &path) - : AbstractDetailsDialog(parent) -{ - m_path = path; - if (QFile::exists(m_path)) - { - loadWavPackInfo(); - loadTags(); - blockSaveButton(!QFileInfo(m_path).isWritable()); - } - else - blockSaveButton(); -} - -DetailsDialog::~DetailsDialog() -{} - -void DetailsDialog::loadWavPackInfo() -{ - char err[80]; - WavpackContext *ctx = WavpackOpenFileInput (m_path.toLocal8Bit(), err, - OPEN_WVC | OPEN_TAGS, 0); - if (!ctx) - { - qWarning("DetailsDialog: error: %s", err); - return; - } - QMap <QString, QString> ap; - int length = (int) WavpackGetNumSamples(ctx)/WavpackGetSampleRate(ctx); - QString text = QString("%1").arg(length/60); - text +=":"+QString("%1").arg(length % 60, 2, 10, QChar('0')); - ap.insert(tr("Length"), text); - ap.insert(tr("Sample rate"), QString("%1 " + tr("Hz")).arg((int) WavpackGetSampleRate(ctx))); - ap.insert(tr("Channels"), QString("%1").arg((int) WavpackGetNumChannels(ctx))); - ap.insert(tr("Bitrate"), QString("%1 " + tr("kbps")) - .arg((int) WavpackGetAverageBitrate(ctx, WavpackGetNumChannels(ctx))/1000)); - QFileInfo info(m_path); - ap.insert(tr("File size"), QString("%1 "+tr("KB")).arg(info.size()/1024)); - ap.insert(tr("Ratio"), QString("%1").arg(WavpackGetRatio(ctx))); - ap.insert(tr("Version"), QString("%1").arg(WavpackGetVersion(ctx))); - WavpackCloseFile (ctx); - setAudioProperties(ap); -} - -void DetailsDialog::loadTags() -{ - char err[80]; - WavpackContext *ctx = WavpackOpenFileInput (m_path.toLocal8Bit(), err, - OPEN_WVC | OPEN_TAGS, 0); - if (!ctx) - { - qWarning("DetailsDialog: error: %s", err); - return; - } - - char value[200]; - WavpackGetTagItem (ctx, "Title", value, sizeof(value)); - setMetaData(Qmmp::TITLE, QString::fromUtf8(value)); - WavpackGetTagItem (ctx, "Artist", value, sizeof(value)); - setMetaData(Qmmp::ARTIST, QString::fromUtf8(value)); - WavpackGetTagItem (ctx, "Album", value, sizeof(value)); - setMetaData(Qmmp::ALBUM, QString::fromUtf8(value)); - WavpackGetTagItem (ctx, "Comment", value, sizeof(value)); - setMetaData(Qmmp::COMMENT, QString::fromUtf8(value)); - WavpackGetTagItem (ctx, "Year", value, sizeof(value)); - setMetaData(Qmmp::YEAR, QString::fromUtf8(value)); - WavpackGetTagItem (ctx, "Track", value, sizeof(value)); - setMetaData(Qmmp::TRACK, QString::fromUtf8(value)); - WavpackGetTagItem (ctx, "Disc", value, sizeof(value)); - setMetaData(Qmmp::DISCNUMBER, QString::fromUtf8(value)); - WavpackGetTagItem (ctx, "Genre", value, sizeof(value)); - setMetaData(Qmmp::GENRE, QString::fromUtf8(value)); - WavpackGetTagItem (ctx, "Composer", value, sizeof(value)); - setMetaData(Qmmp::COMPOSER, QString::fromUtf8(value)); - WavpackCloseFile (ctx); -} - -void DetailsDialog::writeTags() -{ - char err[80]; - WavpackContext *ctx = WavpackOpenFileInput (m_path.toLocal8Bit(), err, - OPEN_WVC | OPEN_EDIT_TAGS, 0); - if (!ctx) - { - qWarning("DetailsDialog: error: %s", err); - return; - } - QByteArray value = strMetaData(Qmmp::TITLE).toUtf8(); - WavpackAppendTagItem(ctx, "Title", value, value.size()); - value = strMetaData(Qmmp::ARTIST).toUtf8(); - WavpackAppendTagItem(ctx, "Artist", value, value.size()); - value = strMetaData(Qmmp::ALBUM).toUtf8(); - WavpackAppendTagItem(ctx, "Album", value, value.size()); - value = strMetaData(Qmmp::COMMENT).toUtf8(); - WavpackAppendTagItem(ctx, "Comment", value, value.size()); - value = strMetaData(Qmmp::GENRE).toUtf8(); - WavpackAppendTagItem(ctx, "Genre", value, value.size()); - value = strMetaData(Qmmp::YEAR).toUtf8(); - WavpackAppendTagItem(ctx, "Year", value, value.size()); - value = strMetaData(Qmmp::TRACK).toUtf8(); - WavpackAppendTagItem(ctx, "Track", value, value.size()); - value = strMetaData(Qmmp::COMPOSER).toUtf8(); - WavpackAppendTagItem(ctx, "Composer", value, value.size()); - value = strMetaData(Qmmp::DISCNUMBER).toUtf8(); - WavpackAppendTagItem(ctx, "Disc", value, value.size()); - WavpackWriteTag (ctx); - WavpackCloseFile (ctx); -} diff --git a/src/plugins/Input/wavpack/wavpack.pro b/src/plugins/Input/wavpack/wavpack.pro index 3d4850006..6f94a39d8 100644 --- a/src/plugins/Input/wavpack/wavpack.pro +++ b/src/plugins/Input/wavpack/wavpack.pro @@ -2,12 +2,12 @@ include(../../plugins.pri) FORMS += HEADERS += decoderwavpackfactory.h \ decoder_wavpack.h \ - detailsdialog.h \ - cueparser.h + cueparser.h \ + wavpackmetadatamodel.h SOURCES += decoder_wavpack.cpp \ decoderwavpackfactory.cpp \ - detailsdialog.cpp \ - cueparser.cpp + cueparser.cpp \ + wavpackmetadatamodel.cpp TARGET = $$PLUGINS_PREFIX/Input/wavpack QMAKE_CLEAN = $$PLUGINS_PREFIX/Input/libwavpack.so INCLUDEPATH += ../../../ diff --git a/src/plugins/Input/wavpack/wavpackmetadatamodel.cpp b/src/plugins/Input/wavpack/wavpackmetadatamodel.cpp new file mode 100644 index 000000000..e79baac8f --- /dev/null +++ b/src/plugins/Input/wavpack/wavpackmetadatamodel.cpp @@ -0,0 +1,157 @@ +/*************************************************************************** + * Copyright (C) 2009 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 <QMap> +#include <QFileInfo> +#include "wavpackmetadatamodel.h" + +WavPackMetaDataModel::WavPackMetaDataModel(const QString &path, QObject *parent) : MetaDataModel(parent) +{ + char err[80]; + m_ctx = WavpackOpenFileInput (path.toLocal8Bit(), err, + OPEN_WVC | OPEN_EDIT_TAGS, 0); + if (!m_ctx) + { + qWarning("WavPackMetaDataModel: error: %s", err); + return; + } + m_tags << new WavPackFileTagModel(m_ctx); +} + +WavPackMetaDataModel::~WavPackMetaDataModel() +{ + while(!m_tags.isEmpty()) + delete m_tags.takeFirst(); + if(m_ctx) + WavpackCloseFile (m_ctx); +} + +QHash<QString, QString> WavPackMetaDataModel::audioProperties() +{ + QHash<QString, QString> ap; + if(!m_ctx) + return ap; + int length = (int) WavpackGetNumSamples(m_ctx)/WavpackGetSampleRate(m_ctx); + QString text = QString("%1").arg(length/60); + text +=":"+QString("%1").arg(length % 60, 2, 10, QChar('0')); + ap.insert(tr("Length"), text); + ap.insert(tr("Sample rate"), QString("%1 " + tr("Hz")).arg((int) WavpackGetSampleRate(m_ctx))); + ap.insert(tr("Channels"), QString("%1").arg((int) WavpackGetNumChannels(m_ctx))); + ap.insert(tr("Bitrate"), QString("%1 " + tr("kbps")) + .arg((int) WavpackGetAverageBitrate(m_ctx, WavpackGetNumChannels(m_ctx))/1000)); + /*QFileInfo info(m_path); + ap.insert(tr("File size"), QString("%1 "+tr("KB")).arg(info.size()/1024));*/ + ap.insert(tr("Ratio"), QString("%1").arg(WavpackGetRatio(m_ctx))); + ap.insert(tr("Version"), QString("%1").arg(WavpackGetVersion(m_ctx))); + return ap; +} + +QList<TagModel* > WavPackMetaDataModel::tags() +{ + return m_tags; +} + +WavPackFileTagModel::WavPackFileTagModel(WavpackContext *ctx) : TagModel(TagModel::Save) +{ + m_ctx = ctx; +} + +WavPackFileTagModel::~WavPackFileTagModel() +{} + +const QString WavPackFileTagModel::name() +{ + return "ID3v1/APEv2"; +} + +const QString WavPackFileTagModel::value(Qmmp::MetaData key) +{ + char value[200]; + switch((int) key) + { + case Qmmp::TITLE: + WavpackGetTagItem (m_ctx, "Title", value, sizeof(value)); + break; + case Qmmp::ARTIST: + WavpackGetTagItem (m_ctx, "Artist", value, sizeof(value)); + break; + case Qmmp::ALBUM: + WavpackGetTagItem (m_ctx, "Album", value, sizeof(value)); + break; + case Qmmp::COMMENT: + WavpackGetTagItem (m_ctx, "Comment", value, sizeof(value)); + break; + case Qmmp::YEAR: + WavpackGetTagItem (m_ctx, "Year", value, sizeof(value)); + break; + case Qmmp::TRACK: + WavpackGetTagItem (m_ctx, "Track", value, sizeof(value)); + break; + case Qmmp::DISCNUMBER: + WavpackGetTagItem (m_ctx, "Disc", value, sizeof(value)); + break; + case Qmmp::GENRE: + WavpackGetTagItem (m_ctx, "Genre", value, sizeof(value)); + break; + case Qmmp::COMPOSER: + WavpackGetTagItem (m_ctx, "Composer", value, sizeof(value)); + } + return QString::fromUtf8(value); +} + +void WavPackFileTagModel::setValue(Qmmp::MetaData key, const QString &value) +{ + int size = value.toUtf8().size(); + char *v = value.toUtf8().data(); + switch((int) key) + { + case Qmmp::TITLE: + WavpackAppendTagItem (m_ctx, "Title", v, size); + break; + case Qmmp::ARTIST: + WavpackAppendTagItem (m_ctx, "Artist", v, size); + break; + case Qmmp::ALBUM: + WavpackAppendTagItem (m_ctx, "Album", v, size); + break; + case Qmmp::COMMENT: + WavpackAppendTagItem (m_ctx, "Comment", v, size); + break; + case Qmmp::YEAR: + WavpackAppendTagItem (m_ctx, "Year", v, size); + break; + case Qmmp::TRACK: + WavpackAppendTagItem (m_ctx, "Track", v, size); + break; + case Qmmp::DISCNUMBER: + WavpackAppendTagItem (m_ctx, "Disc", v, size); + break; + case Qmmp::GENRE: + WavpackAppendTagItem (m_ctx, "Genre", v, size); + break; + case Qmmp::COMPOSER: + WavpackAppendTagItem (m_ctx, "Composer", v, size); + } +} + +void WavPackFileTagModel::save() +{ + WavpackWriteTag (m_ctx); +} diff --git a/src/plugins/Input/wavpack/detailsdialog.h b/src/plugins/Input/wavpack/wavpackmetadatamodel.h index 07978859d..8d322fcd8 100644 --- a/src/plugins/Input/wavpack/detailsdialog.h +++ b/src/plugins/Input/wavpack/wavpackmetadatamodel.h @@ -1,5 +1,5 @@ /*************************************************************************** - * Copyright (C) 2006-2009 by Ilya Kotov * + * Copyright (C) 2009 by Ilya Kotov * * forkotov02@hotmail.ru * * * * This program is free software; you can redistribute it and/or modify * @@ -17,28 +17,41 @@ * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ -#ifndef DETAILSDIALOG_H -#define DETAILSDIALOG_H -#include <qmmp/abstractdetailsdialog.h> +#ifndef WAVPACKMETADATAMODEL_H +#define WAVPACKMETADATAMODEL_H -/** - @author Ilya Kotov <forkotov02@hotmail.ru> -*/ -class DetailsDialog : public AbstractDetailsDialog +extern "C"{ +#include <wavpack/wavpack.h> +} +#include <qmmp/metadatamodel.h> + +class WavPackMetaDataModel : public MetaDataModel { Q_OBJECT public: - DetailsDialog(QWidget *parent = 0, const QString &path = 0); + WavPackMetaDataModel(const QString &path, QObject *parent); + ~WavPackMetaDataModel(); + QHash<QString, QString> audioProperties(); + QList<TagModel* > tags(); - ~DetailsDialog(); +private: + WavpackContext *m_ctx; + QList <TagModel *> m_tags; +}; -private: - void loadWavPackInfo(); - void loadTags(); - void writeTags(); - QString m_path; +class WavPackFileTagModel : public TagModel +{ +public: + WavPackFileTagModel(WavpackContext *ctx); + ~WavPackFileTagModel(); + const QString name(); + const QString value(Qmmp::MetaData key); + void setValue(Qmmp::MetaData key, const QString &value); + void save(); +private: + WavpackContext *m_ctx; }; -#endif +#endif // WAVPACKMETADATAMODEL_H |
