diff options
| author | trialuser02 <trialuser02@90c681e8-e032-0410-971d-27865f9a5e38> | 2019-04-24 13:40:22 +0000 |
|---|---|---|
| committer | trialuser02 <trialuser02@90c681e8-e032-0410-971d-27865f9a5e38> | 2019-04-24 13:40:22 +0000 |
| commit | 4225912c24618c25b84ef134c006ea8986b54cac (patch) | |
| tree | bef7ee8b14200e5f232936eee4da01b061229182 /src | |
| parent | 123801afa00c7eeaa0063bc56d951a7164908d42 (diff) | |
| download | qmmp-4225912c24618c25b84ef134c006ea8986b54cac.tar.gz qmmp-4225912c24618c25b84ef134c006ea8986b54cac.tar.bz2 qmmp-4225912c24618c25b84ef134c006ea8986b54cac.zip | |
added CueParser class
git-svn-id: http://svn.code.sf.net/p/qmmp-dev/code/trunk/qmmp@8787 90c681e8-e032-0410-971d-27865f9a5e38
Diffstat (limited to 'src')
| -rw-r--r-- | src/qmmp/cueparser.cpp | 293 | ||||
| -rw-r--r-- | src/qmmp/cueparser.h | 61 | ||||
| -rw-r--r-- | src/qmmp/qmmp.pro | 6 |
3 files changed, 358 insertions, 2 deletions
diff --git a/src/qmmp/cueparser.cpp b/src/qmmp/cueparser.cpp new file mode 100644 index 000000000..bc4907837 --- /dev/null +++ b/src/qmmp/cueparser.cpp @@ -0,0 +1,293 @@ +/*************************************************************************** + * Copyright (C) 2008-2019 by Ilya Kotov * + * forkotov02@ya.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., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#include <QTextStream> +#include <QTextCodec> +#include "cueparser.h" + +CueParser::CueParser(const QByteArray &data, const QByteArray &codecName) +{ + QString artist, album, genre, date, comment, file; + double album_peak = 0.0, album_gain = 0.0; + QTextStream textStream(data); + + if(codecName.isEmpty()) + { + textStream.setCodec("UTF-8"); + } + else + { + QTextCodec *codec = QTextCodec::codecForName(codecName); + textStream.setCodec(codec ? codec : QTextCodec::codecForName("UTF-8")); + } + + while (!textStream.atEnd()) + { + QString line = textStream.readLine().trimmed(); + QStringList words = splitLine(line); + if(words.size() < 2) + continue; + + if(words[0] == "FILE") + { + file = words[1]; + m_files << file; + } + else if(words[0] == "PERFORMER") + { + if(m_tracks.isEmpty()) + artist = words[1]; + else + m_tracks.last()->info.setValue(Qmmp::ARTIST, words[1]); + } + else if(words[0] == "TITLE") + { + if(m_tracks.isEmpty()) + album = words[1]; + else + m_tracks.last()->info.setValue(Qmmp::TITLE, words[1]); + } + else if(words[0] == "TRACK") + { + TrackInfo info; + info.setValue(Qmmp::TRACK, words[1].toInt()); + info.setValue(Qmmp::ALBUM, album); + info.setValue(Qmmp::GENRE, genre); + info.setValue(Qmmp::YEAR, date); + info.setValue(Qmmp::COMMENT, comment); + info.setValue(Qmmp::ARTIST, artist); + info.setValue(Qmmp::ALBUMARTIST, artist); + info.setValue(Qmmp::REPLAYGAIN_ALBUM_GAIN, album_gain); + info.setValue(Qmmp::REPLAYGAIN_ALBUM_PEAK, album_peak); + + m_tracks << new CUETrack; + m_tracks.last()->info = info; + m_tracks.last()->offset = 0; + } + else if(words[0] == "INDEX" && words[1] == "01") + { + if(m_tracks.isEmpty()) + continue; + m_tracks.last()->offset = getLength(words[2]); + m_tracks.last()->file = file; + } + else if(words[0] == "REM") + { + if(words.size() < 3) + continue; + if(words[1] == "GENRE") + genre = words[2]; + else if(words[1] == "DATE") + 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()->info.setValue(Qmmp::REPLAYGAIN_TRACK_GAIN, words[2].toDouble()); + else if(words[1] == "REPLAYGAIN_TRACK_PEAK" && !m_tracks.isEmpty()) + m_tracks.last()->info.setValue(Qmmp::REPLAYGAIN_TRACK_PEAK, words[2].toDouble()); + } + } + if(m_tracks.isEmpty()) + { + qWarning("CueParser: invalid cue data"); + return; + } + + /*QList<TrackInfo *> f_list = MetaDataManager::instance()->createPlayList(m_filePath, TrackInfo::Properties); + if(!f_list.isEmpty()) + { + //calculate last item length + m_tracks.last()->info.setDuration(qMax(0LL, f_list.first()->duration() - m_tracks.last()->offset)); + //add properties + foreach(CUETrack *cueTrack, m_tracks) + cueTrack->info.setValues(f_list.first()->properties()); + qDeleteAll(f_list); + f_list.clear(); + }*/ +} + +CueParser::~CueParser() +{ + qDeleteAll(m_tracks); + m_tracks.clear(); +} + +const QStringList &CueParser::files() const +{ + return m_files; +} + +qint64 CueParser::offset(int track) const +{ + if(track < 0 || track >= m_tracks.count()) + { + qWarning("CueParser: invalid track number: %d", track); + return 0; + } + return m_tracks.at(track)->offset; +} + +qint64 CueParser::duration(int track) const +{ + if(track < 0 || track >= m_tracks.count()) + { + qWarning("CueParser: invalid track number: %d", track); + return 0; + } + return m_tracks.at(track)->info.duration(); +} + +const QString CueParser::file(int track) const +{ + if(track < 0 || track >= m_tracks.count()) + { + qWarning("CueParser: invalid track number: %d", track); + return 0; + } + return m_tracks.at(track)->file; +} + +const QString CueParser::url(int track) const +{ + if(track < 0 || track >= m_tracks.count()) + { + qWarning("CueParser: invalid track number: %d", track); + return 0; + } + return m_tracks.at(track)->info.path(); +} + +int CueParser::count() const +{ + return m_tracks.count(); +} + +const QMap<Qmmp::ReplayGainKey, double> CueParser::replayGain(int track) const +{ + if(track < 0 || track >= m_tracks.count()) + { + qWarning("CueParser: invalid track number: %d", track); + return QMap<Qmmp::ReplayGainKey, double>(); + } + return m_tracks.at(track)->info.replayGainInfo(); +} + +void CueParser::setDuration(const QString &file, qint64 duration) +{ + for(int i = 0; i < m_tracks.count(); ++i) + { + CUETrack *track = m_tracks.at(i); + if(track->file == file) + { + if((i == m_tracks.count() - 1) || (m_tracks.at(i + 1)->file != track->file)) + track->info.setDuration(duration - track->offset); + else + track->info.setDuration(m_tracks.at(i + 1)->offset - track->offset); + + if(track->info.duration() < 0) + track->info.setDuration(0); + } + } +} + +void CueParser::setDuration(qint64 duration) +{ + for(int i = 0; i < m_tracks.count(); ++i) + { + CUETrack *track = m_tracks.at(i); + + if(i == m_tracks.count() - 1) + track->info.setDuration(duration - track->offset); + else + track->info.setDuration(m_tracks.at(i + 1)->offset - track->offset); + + if(track->info.duration() < 0) + track->info.setDuration(0); + } +} + +void CueParser::setProperties(const QString &file, const QMap<Qmmp::TrackProperty, QString> &properties) +{ + for(CUETrack *track : m_tracks) + { + if(track->file == file) + track->info.setValues(properties); + } +} + +void CueParser::setProperties(const QMap<Qmmp::TrackProperty, QString> &properties) +{ + for(CUETrack *track : m_tracks) + track->info.setValues(properties); +} + +void CueParser::setUrl(const QString &scheme, const QString &path) +{ + for(int i = 0; i < m_tracks.count(); ++i) + m_tracks.at(i)->info.setPath(QString("%1://%2#%3").arg(scheme).arg(path).arg(i + 1)); +} + +QStringList CueParser::splitLine(const QString &line) +{ + //qDebug("raw string = %s",qPrintable(line)); + QStringList list; + QString buf = line.trimmed(); + if(buf.isEmpty()) + return list; + while (!buf.isEmpty()) + { + //qDebug(qPrintable(buf)); + if(buf.startsWith('"')) + { + int end = buf.indexOf('"',1); + if(end == -1) //ignore invalid line + { + list.clear(); + qWarning("CueParser: unable to parse line: %s",qPrintable(line)); + return list; + } + list << buf.mid (1, end - 1); + buf.remove (0, end+1); + } + else + { + int end = buf.indexOf(' ', 0); + if(end < 0) + end = buf.size(); + list << buf.mid (0, end); + buf.remove (0, end); + } + buf = buf.trimmed(); + } + return list; +} + +qint64 CueParser::getLength(const QString &str) +{ + QStringList list = str.split(":"); + if(list.size() == 2) + return (qint64)list.at(0).toInt()*60000 + list.at(1).toInt()*1000; + else if(list.size() == 3) + return (qint64)list.at(0).toInt()*60000 + list.at(1).toInt()*1000 + list.at(2).toInt()*1000/75; + return 0; +} diff --git a/src/qmmp/cueparser.h b/src/qmmp/cueparser.h new file mode 100644 index 000000000..1d55f51dd --- /dev/null +++ b/src/qmmp/cueparser.h @@ -0,0 +1,61 @@ +/*************************************************************************** + * Copyright (C) 2008-2019 by Ilya Kotov * + * forkotov02@ya.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., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ +#ifndef CUEPARSER_H +#define CUEPARSER_H + +#include <QByteArray> +#include <QString> +#include <QList> +#include <QStringList> +#include "trackinfo.h" +#include "qmmp_export.h" + +class QMMP_EXPORT CueParser +{ +public: + CueParser(const QByteArray &data, const QByteArray &codecName = QByteArray()); + ~CueParser(); + const QStringList &files() const; + qint64 offset(int track) const; + qint64 duration(int track) const; + const QString file(int track) const; + const QString url(int track) const; + int count() const; + const QMap<Qmmp::ReplayGainKey, double> replayGain(int track) const; + void setDuration(const QString &file, qint64 duration); + void setDuration(qint64 duration); + void setProperties(const QString &file, const QMap<Qmmp::TrackProperty, QString> &properties); + void setProperties(const QMap<Qmmp::TrackProperty, QString> &properties); + void setUrl(const QString &scheme, const QString &path); + +private: + struct CUETrack + { + TrackInfo info; + QString file; + qint64 offset = 0; + }; + QList<CUETrack *> m_tracks; + QStringList m_files; + QStringList splitLine(const QString &line); + qint64 getLength(const QString &str); +}; + +#endif // CUEPARSER_H diff --git a/src/qmmp/qmmp.pro b/src/qmmp/qmmp.pro index 7ebb9a0e8..9152b8bff 100644 --- a/src/qmmp/qmmp.pro +++ b/src/qmmp/qmmp.pro @@ -41,7 +41,8 @@ HEADERS += \ visualbuffer_p.h \ qmmp_export.h \ trackinfo.h \ - volumehandler.h + volumehandler.h \ + cueparser.h SOURCES += recycler.cpp \ decoder.cpp \ output.cpp \ @@ -75,7 +76,8 @@ SOURCES += recycler.cpp \ dithering.cpp \ visualbuffer.cpp \ trackinfo.cpp \ - volumehandler.cpp + volumehandler.cpp \ + cueparser.cpp unix:TARGET = ../../lib/qmmp$$APP_NAME_SUFFIX win32:TARGET = ../../../bin/qmmp |
