aboutsummaryrefslogtreecommitdiff
path: root/src/plugins/Input/flac
diff options
context:
space:
mode:
authortrialuser02 <trialuser02@90c681e8-e032-0410-971d-27865f9a5e38>2011-10-20 12:53:23 +0000
committertrialuser02 <trialuser02@90c681e8-e032-0410-971d-27865f9a5e38>2011-10-20 12:53:23 +0000
commit5d057136dcfb9a7dca90783510d905d6aa097ca6 (patch)
tree0554dfdcd607e39d672a7f06f2cf023d4983d518 /src/plugins/Input/flac
parent48c3e2d337beb7f39e894ea8f6b965d0dcfdcdd2 (diff)
downloadqmmp-5d057136dcfb9a7dca90783510d905d6aa097ca6.tar.gz
qmmp-5d057136dcfb9a7dca90783510d905d6aa097ca6.tar.bz2
qmmp-5d057136dcfb9a7dca90783510d905d6aa097ca6.zip
cue parser: added replaygain support (Closes issue 279)
git-svn-id: http://svn.code.sf.net/p/qmmp-dev/code/trunk/qmmp@2413 90c681e8-e032-0410-971d-27865f9a5e38
Diffstat (limited to 'src/plugins/Input/flac')
-rw-r--r--src/plugins/Input/flac/cueparser.cpp119
-rw-r--r--src/plugins/Input/flac/cueparser.h21
-rw-r--r--src/plugins/Input/flac/decoder_flac.cpp2
3 files changed, 111 insertions, 31 deletions
diff --git a/src/plugins/Input/flac/cueparser.cpp b/src/plugins/Input/flac/cueparser.cpp
index 89c39c889..afe277919 100644
--- a/src/plugins/Input/flac/cueparser.cpp
+++ b/src/plugins/Input/flac/cueparser.cpp
@@ -1,5 +1,5 @@
/***************************************************************************
- * Copyright (C) 2008-2010 by Ilya Kotov *
+ * Copyright (C) 2008-2011 by Ilya Kotov *
* forkotov02@hotmail.ru *
* *
* This program is free software; you can redistribute it and/or modify *
@@ -18,8 +18,13 @@
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
+#include <QFile>
+#include <QDir>
+#include <QDirIterator>
+#include <QSettings>
#include <QTextStream>
#include <QTextCodec>
+#include <qmmp/decoder.h>
#include <qmmp/metadatamanager.h>
#include "cueparser.h"
@@ -30,6 +35,7 @@ CUEParser::CUEParser(const QByteArray &array, const QString &fileName)
textStream.setCodec("UTF-8");
m_filePath = fileName;
QString artist;
+ double album_peak = 0.0, album_gain = 0.0;
while (!textStream.atEnd())
{
QString line = textStream.readLine().trimmed();
@@ -39,17 +45,17 @@ CUEParser::CUEParser(const QByteArray &array, const QString &fileName)
if (words[0] == "PERFORMER")
{
- if(m_infoList.isEmpty())
+ if(m_tracks.isEmpty())
artist = words[1];
else
- m_infoList.last().setMetaData(Qmmp::ARTIST, words[1]);
+ m_tracks.last()->info.setMetaData(Qmmp::ARTIST, words[1]);
}
else if (words[0] == "TITLE")
{
- if(m_infoList.isEmpty())
+ if(m_tracks.isEmpty())
album = words[1];
else
- m_infoList.last().setMetaData(Qmmp::TITLE, words[1]);
+ m_tracks.last()->info.setMetaData(Qmmp::TITLE, words[1]);
}
else if (words[0] == "TRACK")
{
@@ -65,17 +71,21 @@ CUEParser::CUEParser(const QByteArray &array, const QString &fileName)
info.setMetaData(Qmmp::YEAR, date);
info.setMetaData(Qmmp::COMMENT, comment);
info.setMetaData(Qmmp::ARTIST, artist);
- m_infoList << info;
- m_offsets << 0;
+
+ m_tracks << new CUETrack;
+ m_tracks.last()->info = info;
+ m_tracks.last()->offset = 0;
+ m_tracks.last()->replayGain.insert(Qmmp::REPLAYGAIN_ALBUM_GAIN, album_gain);
+ m_tracks.last()->replayGain.insert(Qmmp::REPLAYGAIN_ALBUM_PEAK, album_peak);
}
else if (words[0] == "INDEX" && words[1] == "01")
{
- if (m_infoList.isEmpty())
+ if (m_tracks.isEmpty())
continue;
- m_offsets.last() = getLength(words[2]);
- int c = m_infoList.count();
+ m_tracks.last()->offset = getLength(words[2]);
+ int c = m_tracks.count();
if(c > 1)
- m_infoList[c - 2].setLength(m_offsets[c - 1] - m_offsets[c - 2]);
+ m_tracks[c - 2]->info.setLength(m_tracks[c - 1]->offset - m_tracks[c - 2]->offset);
}
else if (words[0] == "REM")
{
@@ -87,9 +97,17 @@ CUEParser::CUEParser(const QByteArray &array, const QString &fileName)
date = words[2];
else if (words[1] == "COMMENT")
comment = words[2];
+ else if (words[1] == "REPLAYGAIN_ALBUM_GAIN")
+ album_gain = words[2].toDouble();
+ else if (words[1] == "REPLAYGAIN_ALBUM_PEAK")
+ album_peak = words[2].toDouble();
+ else if (words[1] == "REPLAYGAIN_TRACK_GAIN" && !m_tracks.isEmpty())
+ m_tracks.last()->replayGain.insert(Qmmp::REPLAYGAIN_TRACK_GAIN, words[2].toDouble());
+ else if (words[1] == "REPLAYGAIN_TRACK_PEAK" && !m_tracks.isEmpty())
+ m_tracks.last()->replayGain.insert(Qmmp::REPLAYGAIN_TRACK_PEAK, words[2].toDouble());
}
}
- if(m_infoList.isEmpty())
+ if(m_tracks.isEmpty())
{
qWarning("CUEParser: invalid cue file");
return;
@@ -97,24 +115,25 @@ CUEParser::CUEParser(const QByteArray &array, const QString &fileName)
//calculate last item length
QList <FileInfo *> f_list = MetaDataManager::instance()->createPlayList(m_filePath, false);
qint64 l = f_list.isEmpty() ? 0 : f_list.at(0)->length() * 1000;
- if (l > m_offsets.last())
- m_infoList.last().setLength(l - m_offsets.last());
+ if (l > m_tracks.last()->offset)
+ m_tracks.last()->info.setLength(l - m_tracks.last()->offset);
else
- m_infoList.last().setLength(0);
+ m_tracks.last()->info.setLength(0);
}
-
CUEParser::~CUEParser()
{
+ qDeleteAll(m_tracks);
+ m_tracks.clear();
}
QList<FileInfo*> CUEParser::createPlayList()
{
QList<FileInfo*> list;
- foreach(FileInfo info, m_infoList)
+ foreach(CUETrack *track, m_tracks)
{
- list << new FileInfo(info);
- list.last()->setLength(list.last()->length()/1000);
+ list << new FileInfo(track->info);
+ list.last()->setLength(track->info.length()/1000);
}
return list;
}
@@ -126,27 +145,32 @@ const QString CUEParser::filePath() const
qint64 CUEParser::offset(int track) const
{
- return m_offsets.at(track - 1);
+ return m_tracks.at(track - 1)->offset;
}
qint64 CUEParser::length(int track) const
{
- return m_infoList.at(track - 1).length();
+ return m_tracks.at(track - 1)->info.length();
}
int CUEParser::count() const
{
- return m_infoList.count();
+ return m_tracks.count();
}
FileInfo *CUEParser::info(int track)
{
- return &m_infoList[track - 1];
+ return &m_tracks.at(track - 1)->info;
}
const QString CUEParser::trackURL(int track) const
{
- return m_infoList[track - 1].path();
+ return m_tracks.at(track - 1)->info.path();
+}
+
+const QMap<Qmmp::ReplayGainKey, double> CUEParser::replayGain(int track) const
+{
+ return m_tracks.at(track - 1)->replayGain;
}
QStringList CUEParser::splitLine(const QString &line)
@@ -187,3 +211,50 @@ qint64 CUEParser::getLength(const QString &str)
return (qint64)list.at(0).toInt()*60000 + list.at(1).toInt()*1000 + list.at(2).toInt()*1000/75;
return 0;
}
+
+QString CUEParser::getDirtyPath(const QString &cue, const QString &path)
+{
+
+ if (Decoder::findByPath(path) || ! m_dirty)
+ return path;
+
+ QStringList candidates;
+ QDirIterator it(QFileInfo(path).dir().path(), QDir::Files);
+ while (it.hasNext())
+ {
+ it.next();
+ QString f = it.filePath();
+ if ((f != cue) && Decoder::findByPath(f))
+ candidates.push_back(f);
+ }
+
+ if (candidates.empty())
+ return path;
+ else if (candidates.count() == 1)
+ return candidates.first();
+
+ int dot = cue.lastIndexOf('.');
+ if (dot != -1)
+ {
+ QRegExp r(QRegExp::escape(cue.left(dot)) + "\\.[^\\.]+$");
+
+ int index = candidates.indexOf(r);
+ int rindex = candidates.lastIndexOf(r);
+
+ if ((index != -1) && (index == rindex))
+ return candidates[index];
+ }
+ dot = path.lastIndexOf('.');
+ if (dot != -1)
+ {
+ QRegExp r(QRegExp::escape(path.left(dot)) + "\\.[^\\.]+$");
+
+ int index = candidates.indexOf(r);
+ int rindex = candidates.lastIndexOf(r);
+
+ if ((index != -1) && (index == rindex))
+ return candidates[index];
+ }
+
+ return path;
+}
diff --git a/src/plugins/Input/flac/cueparser.h b/src/plugins/Input/flac/cueparser.h
index 5e4e0ea2d..2437065cf 100644
--- a/src/plugins/Input/flac/cueparser.h
+++ b/src/plugins/Input/flac/cueparser.h
@@ -1,5 +1,5 @@
/***************************************************************************
- * Copyright (C) 2008-2009 by Ilya Kotov *
+ * Copyright (C) 2008-2011 by Ilya Kotov *
* forkotov02@hotmail.ru *
* *
* This program is free software; you can redistribute it and/or modify *
@@ -22,10 +22,10 @@
#include <QList>
#include <QMap>
-#include <QByteArray>
#include <QString>
#include <QStringList>
-
+#include <QUrl>
+#include <qmmp/qmmp.h>
#include <qmmp/fileinfo.h>
@@ -46,14 +46,21 @@ public:
int count() const;
FileInfo *info(int track);
const QString trackURL(int track) const;
+ const QMap<Qmmp::ReplayGainKey, double> replayGain(int track) const;
private:
- QString m_filePath;
- QList <FileInfo> m_infoList;
- QList <qint64> m_offsets;
+ struct CUETrack
+ {
+ FileInfo info;
+ qint64 offset;
+ QMap<Qmmp::ReplayGainKey, double> replayGain;
+ };
+ QList <CUETrack * > m_tracks;
+ bool m_dirty;
QStringList splitLine(const QString &line);
qint64 getLength(const QString &str);
-
+ QString getDirtyPath(const QString &cue, const QString &path);
+ QString m_filePath;
};
#endif
diff --git a/src/plugins/Input/flac/decoder_flac.cpp b/src/plugins/Input/flac/decoder_flac.cpp
index 00b0636aa..f6aee476e 100644
--- a/src/plugins/Input/flac/decoder_flac.cpp
+++ b/src/plugins/Input/flac/decoder_flac.cpp
@@ -426,6 +426,7 @@ bool DecoderFLAC::initialize()
length_in_bytes = audioParameters().sampleRate() *
audioParameters().channels() *
audioParameters().sampleSize() * m_length/1000;
+ setReplayGainInfo(m_parser->replayGain(m_track));
seek(0);
}
m_totalBytes = 0;
@@ -542,6 +543,7 @@ void DecoderFLAC::next()
audioParameters().channels() *
audioParameters().sampleSize() * m_length/1000;
addMetaData(m_parser->info(m_track)->metaData());
+ setReplayGainInfo(m_parser->replayGain(m_track));
m_totalBytes = 0;
}
}