diff options
| author | trialuser02 <trialuser02@90c681e8-e032-0410-971d-27865f9a5e38> | 2015-02-02 10:10:49 +0000 |
|---|---|---|
| committer | trialuser02 <trialuser02@90c681e8-e032-0410-971d-27865f9a5e38> | 2015-02-02 10:10:49 +0000 |
| commit | 264f3ddbe777c212620a2e5c66c1b9f358f833e7 (patch) | |
| tree | 6db54ed8111453e687c6ce8569cadf37df2f8c27 /src/qmmpui/metadataformatter.cpp | |
| parent | 8eccc97170a4ea592aa3fe38fed1294e86df0b1c (diff) | |
| download | qmmp-264f3ddbe777c212620a2e5c66c1b9f358f833e7.tar.gz qmmp-264f3ddbe777c212620a2e5c66c1b9f358f833e7.tar.bz2 qmmp-264f3ddbe777c212620a2e5c66c1b9f358f833e7.zip | |
enabled new metadata formatter
git-svn-id: http://svn.code.sf.net/p/qmmp-dev/code/trunk/qmmp@4710 90c681e8-e032-0410-971d-27865f9a5e38
Diffstat (limited to 'src/qmmpui/metadataformatter.cpp')
| -rw-r--r-- | src/qmmpui/metadataformatter.cpp | 412 |
1 files changed, 348 insertions, 64 deletions
diff --git a/src/qmmpui/metadataformatter.cpp b/src/qmmpui/metadataformatter.cpp index c19b49674..f1b70eeb0 100644 --- a/src/qmmpui/metadataformatter.cpp +++ b/src/qmmpui/metadataformatter.cpp @@ -1,5 +1,5 @@ /*************************************************************************** - * Copyright (C) 2009-2014 by Ilya Kotov * + * Copyright (C) 2015 by Ilya Kotov * * forkotov02@hotmail.ru * * * * This program is free software; you can redistribute it and/or modify * @@ -21,66 +21,76 @@ /* Syntax: -%p - artist -%a - album -%aa - album artist -%t - title -%n - track, -%NN - 2-digit track -%g - genre -%c - comment -%C - composer -%D - disc number -%f - file name -%F - full path -%y - year -%l - duration -%if(A,B,C) -%if(A&B&C,D,E) +%p - artist, +%a - album, +%aa - album artist, +%t - title, +%n - track number, +%NN - 2-digit track number, +%g - genre, +%c - comment, +%C - composer, +%D - disc number, +%f - file name, +%F - full path, +%y - year, +%l - duration, +%if(A,B,C) or %if(A&B&C,D,E) - condition. */ #include <QStringList> #include <QUrl> #include "metadataformatter.h" -MetaDataFormatter::MetaDataFormatter(const QString &format) +MetaDataFormatter::MetaDataFormatter(const QString &pattern) { - m_format = format; + m_fieldNames.insert("t", Qmmp::TITLE); + m_fieldNames.insert("p", Qmmp::ARTIST); + m_fieldNames.insert("aa", Qmmp::ALBUMARTIST); + m_fieldNames.insert("a", Qmmp::ALBUM); + m_fieldNames.insert("c", Qmmp::COMMENT); + m_fieldNames.insert("g", Qmmp::GENRE); + m_fieldNames.insert("C", Qmmp::COMPOSER); + m_fieldNames.insert("y", Qmmp::YEAR); + m_fieldNames.insert("n", Qmmp::TRACK); + m_fieldNames.insert("D", Qmmp::DISCNUMBER); + m_fieldNames.insert("F", Qmmp::URL); + m_fieldNames.insert("NN", Param::TWO_DIGIT_TRACK); + m_fieldNames.insert("l", Param::DURATION); + m_fieldNames.insert("f", Param::FILE_NAME); + + if(!pattern.isEmpty()) + setPattern(pattern); +} + +void MetaDataFormatter::setPattern(const QString &pattern) +{ + m_pattern = pattern; + m_nodes.clear(); + + qDebug("MetaDataFormatter: pattern: %s", qPrintable(pattern)); + m_nodes = compile(pattern); + qDebug("MetaDataFormatter: dump of nodes"); + foreach (Node n, m_nodes) + { + qDebug("=>%s", qPrintable(dumpNode(n))); + } + qDebug("MetaDataFormatter: end of dump"); +} + +const QString MetaDataFormatter::pattern() const +{ + return m_pattern; } -QString MetaDataFormatter::parse(const PlayListTrack *item) +QString MetaDataFormatter::format(const PlayListTrack *item) { - return parse(*item, item->length()); + return format(*item, item->length()); } -QString MetaDataFormatter::parse(const QMap<Qmmp::MetaData, QString> &metaData, qint64 length) +QString MetaDataFormatter::format(const QMap<Qmmp::MetaData, QString> &metaData, qint64 length) { - QString title = m_format; - title.replace("\\(", "%28"); - title.replace("\\)", "%29"); - title.replace(")", "%)"); - title.replace("&", "%&"); - title.replace(",", "%,"); - title.replace("%p", metaData[Qmmp::ARTIST]); - title.replace("%aa", metaData[Qmmp::ALBUMARTIST]); - title.replace("%a", metaData[Qmmp::ALBUM]); - title.replace("%t", metaData[Qmmp::TITLE]); - title.replace("%n", metaData[Qmmp::TRACK]); - title.replace("%NN", QString("%1").arg(metaData[Qmmp::TRACK],2,'0')); - title.replace("%g", metaData[Qmmp::GENRE]); - title.replace("%c", metaData[Qmmp::COMMENT]); - title.replace("%C", metaData[Qmmp::COMPOSER]); - title.replace("%D", metaData[Qmmp::DISCNUMBER]); - title.replace("%f", metaData[Qmmp::URL].section('/',-1)); - title.replace("%F", metaData[Qmmp::URL]); - title.replace("%y", metaData[Qmmp::YEAR]); - if(title.contains("l")) - title.replace("%l",formatLength(length)); - if(title.contains("%if")) - title = processIfKeyWord(title); - title.replace("%28", "("); - title.replace("%29", ")"); - return title.trimmed(); + return evalute(&m_nodes, &metaData, length).trimmed(); } QString MetaDataFormatter::formatLength(qint64 length) const @@ -96,26 +106,300 @@ QString MetaDataFormatter::formatLength(qint64 length) const return str; } -QString MetaDataFormatter::processIfKeyWord(QString title) +bool MetaDataFormatter::parseField(QList<Node> *nodes, QString::const_iterator *i, QString::const_iterator end) +{ + QString fieldName; + int field = Qmmp::UNKNOWN; + + //try to find field with 2 symbols + if((*i) + 1 != end) + { + fieldName.append((**i)); + fieldName.append(*((*i)+1)); + field = m_fieldNames.value(fieldName, Qmmp::UNKNOWN); + } + //try to find field with 1 symbol + if(field == Qmmp::UNKNOWN) + { + fieldName.clear(); + fieldName.append((**i)); + field = m_fieldNames.value(fieldName, Qmmp::UNKNOWN); + } + + if(field != Qmmp::UNKNOWN) + { + Node node; + node.command = Node::PRINT_TEXT; + Param param; + param.type = Param::FIELD; + param.field = field; + node.params.append(param); + nodes->append(node); + (*i) += fieldName.size() - 1; + return true; + } + return false; +} + +bool MetaDataFormatter::parseIf(QList<MetaDataFormatter::Node> *nodes, QString::const_iterator *i, QString::const_iterator end) { - int pos = title.lastIndexOf("%if("); - int size = title.indexOf("%)",pos) - pos; + if((*i) + 1 == end || (*i) + 2 == end) + return false; + + if((**i) != QChar('i') || *((*i)+1) != QChar('f')) + return false; + + (*i)+=2; + + Node node; + node.command = Node::IF_KEYWORD; - QStringList args = title.mid (pos + 4, size - 4).split("%,"); - if(args.count() < 3) + int brackets_tracker = 0; + QString var1, var2, var3; + + enum { + STARTING = 0, + READING_VAR1, + READING_VAR2, + READING_VAR3, + FINISHED, + + } state = STARTING; + + while((*i) != end) { - qWarning("TitleFormatter: invalid title format"); - return title; + if((**i) == QChar('(')) + { + brackets_tracker++; + if(state == STARTING) + { + state = READING_VAR1; + (*i)++; + continue; + } + } + else if((**i) == QChar(')')) + brackets_tracker--; + + switch (state) + { + case STARTING: + { + break; + } + case READING_VAR1: + { + if((**i) == QChar(',') && brackets_tracker == 1) + { + state = READING_VAR2; + break; + } + var1.append((**i)); + break; + } + case READING_VAR2: + { + if((**i) == QChar(',') && brackets_tracker == 1) + { + state = READING_VAR3; + break; + } + var2.append((**i)); + break; + } + case READING_VAR3: + { + if((**i) == QChar(')') && brackets_tracker == 0) + { + state = FINISHED; + break; + } + var3.append((**i)); + break; + } + default: + break; + } + + if(state == FINISHED) + break; + + (*i)++; } - //process condition - bool cond = true; - foreach(QString arg, args.at(0).split("%&")) + + if(state != FINISHED) + { + qWarning("MetaDataFormatter: syntax error"); + return false; + } + + Param param1, param2, param3; + param1.type = Param::NODES, param2.type = Param::NODES, param3.type = Param::NODES; + param1.children = compile(var1); + param2.children = compile(var2); + param3.children = compile(var3); + node.params << param1 << param2 << param3; + nodes->append(node); + return true; +} + +void MetaDataFormatter::parseText(QList<MetaDataFormatter::Node> *nodes, QString::const_iterator *i, QString::const_iterator end) +{ + Node node; + node.command = Node::PRINT_TEXT; + Param param; + param.type = Param::TEXT; + node.params.append(param); + + forever { - cond &= !arg.isEmpty(); + if((*i) == end || (**i) == QChar('%')) + { + (*i)--; + break; + } + node.params[0].text.append(**i); + (*i)++; + } + if(!node.params[0].text.isEmpty()) + nodes->append(node); +} + +QString MetaDataFormatter::evalute(QList<Node> *nodes, const QMap<Qmmp::MetaData, QString> *metaData, qint64 length) +{ + QString out; + for(int i = 0; i < nodes->count(); ++i) + { + Node node = nodes->at(i); + if(node.command == Node::PRINT_TEXT) + { + Param p = node.params.first(); + out.append(printParam(&p, metaData, length)); + + } + else if(node.command == Node::IF_KEYWORD) + { + QString var1 = printParam(&node.params[0], metaData, length); + if(var1.isEmpty()) + out.append(printParam(&node.params[2], metaData, length)); + else + out.append(printParam(&node.params[1], metaData, length)); + } + } + return out; +} + +QString MetaDataFormatter::printParam(MetaDataFormatter::Param *p, const QMap<Qmmp::MetaData, QString> *metaData, qint64 length) +{ + switch (p->type) + { + case Param::FIELD: + return printField(p->field, metaData, length); + break; + case Param::TEXT: + return p->text; + break; + case Param::NODES: + return evalute(&p->children, metaData, length); + break; + default: + break; + } + return QString(); +} + +QString MetaDataFormatter::printField(int field, const QMap<Qmmp::MetaData, QString> *metaData, qint64 length) +{ + if(field >= Qmmp::TITLE && field <= Qmmp::URL) + { + if(field == Qmmp::TITLE) + { + QString title = metaData->value(Qmmp::TITLE); + if(title.isEmpty()) //using file name if title is empty + { + title = metaData->value(Qmmp::URL).section('/',-1); + title = title.left(title.lastIndexOf('.')); + } + return title; + } + return metaData->value((Qmmp::MetaData) field); + } + else if(field == Param::TWO_DIGIT_TRACK) + { + return QString("%1").arg(metaData->value(Qmmp::TRACK),2,'0'); + } + else if(field == Param::DURATION) + { + return formatLength(length); + } + else if(field == Param::FILE_NAME) + { + return metaData->value(Qmmp::URL).section('/',-1); + } + return QString(); +} + +QString MetaDataFormatter::dumpNode(MetaDataFormatter::Node node) +{ + QString str; + QStringList params; + if(node.command == Node::PRINT_TEXT) + str += "PRINT_TEXT"; + else if(node.command == Node::IF_KEYWORD) + str += "IF_KEYWORD"; + str += "("; + foreach (Param p, node.params) + { + if(p.type == Param::FIELD) + params.append(QString("FIELD:%1").arg(p.field)); + else if(p.type == Param::TEXT) + params.append(QString("TEXT:%1").arg(p.text)); + else if(p.type == Param::NODES) + { + QStringList nodeStrList; + foreach (Node n, p.children) + { + nodeStrList.append(dumpNode(n)); + } + params.append(QString("NODES:%1").arg(nodeStrList.join(","))); + } + } + str.append(params.join(",")); + str.append(")"); + return str; +} + +QList<MetaDataFormatter::Node> MetaDataFormatter::compile(const QString &expr) +{ + QList <Node> nodes; + QString::const_iterator i = expr.constBegin(); + + while (i != expr.constEnd()) + { + if((*i) == QChar('%')) + { + i++; + if(i == expr.constEnd()) + continue; + + if(parseField(&nodes, &i, expr.constEnd())) + { + i++; + continue; + } + + if(parseIf(&nodes, &i, expr.constEnd())) + { + i++; + continue; + } + continue; + } + else + { + parseText(&nodes, &i, expr.constEnd()); + i++; + } } - QString r_str = cond ? args.at(1) : args.at(2); - title.replace (pos, size + 2, r_str); - if(title.contains("%if")) - return processIfKeyWord(title); - return title; + return nodes; } |
