File indexing completed on 2024-04-21 04:45:42

0001 /****************************************************************************************
0002  * Copyright (c) 2010 Sergey Ivanov <123kash@gmail.com>                                 *
0003  *                                                                                      *
0004  * This program is free software; you can redistribute it and/or modify it under        *
0005  * the terms of the GNU General Public License as published by the Free Software        *
0006  * Foundation; either version 2 of the License, or (at your option) any later           *
0007  * version.                                                                             *
0008  *                                                                                      *
0009  * This program is distributed in the hope that it will be useful, but WITHOUT ANY      *
0010  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A      *
0011  * PARTICULAR PURPOSE. See the GNU General Public License for more details.             *
0012  *                                                                                      *
0013  * You should have received a copy of the GNU General Public License along with         *
0014  * this program.  If not, see <http://www.gnu.org/licenses/>.                           *
0015  ****************************************************************************************/
0016 
0017 #include "TagsFromFileNameGuesser.h"
0018 
0019 #include <QStringList>
0020 
0021 const QStringList m_schemes( QStringList()
0022     //01 Artist - Title.ext
0023     << QStringLiteral("^%track%\\W*-?\\W*%artist%\\W*-\\W*%title%\\.+(?:\\w{2,5})$")
0024     //01 Title.ext
0025     << QStringLiteral("^%track%\\W*-?\\W*%title%\\.+?:\\w{2,5}$")
0026     //Album - 01 - Artist - Title.ext
0027     << QStringLiteral("^%album%\\W*-\\W*%track%\\W*-\\W*%artist%\\W*-\\W*%title%\\.+(?:\\w{2,5})$")
0028     //Artist - Album - 01 - Title.ext
0029     << QStringLiteral("^%artist%\\W*-\\W*%album%\\W*-\\W*%track%\\W*-\\W*%title%\\.+(?:\\w{2,5})$")
0030     // Artist - Album - Title.ext
0031     << QStringLiteral("^%artist%\\W*-\\W*%album%\\W*-\\W*%title%\\.+(?:\\w{2,5})$")
0032     //Artist - Title.ext
0033     << QStringLiteral("^%artist%\\W*-\\W*%title%\\.+(?:\\w{2,5})$")
0034     //Title.ext
0035     << QStringLiteral("^%title%\\.+(?:\\w{2,5})$")
0036 );
0037 
0038 const QRegExp m_digitalFields( QStringLiteral("(%(?:discnumber|track|year)%)") );
0039 const QRegExp m_literalFields( QStringLiteral("(%(?:album|albumartist|artist|comment|composer|genre|title)%)") );
0040 
0041 quint64
0042 fieldName( const QString &field )
0043 {
0044     if( field == QLatin1String("album") )
0045         return Meta::valAlbum;
0046     else if( field == QLatin1String("albumartist") )
0047         return Meta::valAlbumArtist;
0048     else if( field == QLatin1String("artist") )
0049         return Meta::valArtist;
0050     else if( field == QLatin1String("comment") )
0051         return Meta::valComment;
0052     else if( field == QLatin1String("composer") )
0053         return Meta::valComposer;
0054     else if( field == QLatin1String("discnumber") )
0055         return Meta::valDiscNr;
0056     else if( field == QLatin1String("genre") )
0057         return Meta::valGenre;
0058     else if( field == QLatin1String("title") )
0059         return Meta::valTitle;
0060     else if( field == QLatin1String("track") )
0061         return Meta::valTrackNr;
0062     else if( field == QLatin1String("year") )
0063         return Meta::valYear;
0064 
0065     return 0;
0066 }
0067 
0068 QList< qint64 >
0069 parseTokens( const QString &scheme )
0070 {
0071     QRegExp rxm( QStringLiteral("%(\\w+)%") );
0072     QList< qint64 > tokens;
0073 
0074     int pos = 0;
0075     qint64 field;
0076     while( ( pos = rxm.indexIn( scheme, pos ) ) != -1 )
0077     {
0078         field = fieldName( rxm.cap( 1 ) );
0079         if( field )
0080             tokens << field;
0081         pos += rxm.matchedLength();
0082     }
0083 
0084     return tokens;
0085 }
0086 
0087 Meta::FieldHash
0088 Meta::Tag::TagGuesser::guessTagsByScheme( const QString &fileName, const QString &scheme,
0089                                           bool cutTrailingSpaces, bool convertUnderscores,
0090                                           bool isRegExp )
0091 {
0092     Meta::FieldHash metadata;
0093 
0094     QRegExp rx;
0095 
0096     QString m_fileName = fileName;
0097     QString m_scheme = scheme;
0098 
0099     QList< qint64 > tokens = parseTokens( m_scheme );
0100     
0101     // Screen all special symbols
0102     if( !isRegExp )
0103         m_scheme = m_scheme.replace( QRegExp( QStringLiteral("([~!\\^&*()\\-+\\[\\]{}\\\\:\"?\\.])" )), QStringLiteral("\\\\1") );
0104     
0105     QRegExp spaces( QStringLiteral("(\\s+)") );
0106     rx.setPattern( m_scheme.replace( spaces, QStringLiteral("\\s+") )
0107                            .replace( m_digitalFields, QStringLiteral("(\\d+)") )
0108                            .replace( m_literalFields, QStringLiteral("(.+)") )
0109                            .replace( QLatin1String("%ignore%"), QLatin1String("(?:.+)") ) );
0110 
0111     if( !rx.exactMatch( m_fileName ) )
0112         return metadata;
0113 
0114     QString value;
0115     for( int i = 0; i < tokens.count(); i++ )
0116     {
0117         value = rx.cap( i + 1 );
0118         if( convertUnderscores )
0119             value.replace( QLatin1Char('_'), QLatin1Char(' ') );
0120         if( cutTrailingSpaces )
0121             value = value.trimmed();
0122         metadata.insert( tokens[i], value );
0123     }
0124     return metadata;
0125 }
0126 
0127 Meta::FieldHash
0128 Meta::Tag::TagGuesser::guessTags( const QString &fileName )
0129 {
0130     QString tmpStr = fileName;
0131     int pos = 0;
0132     if( ( pos = fileName.lastIndexOf( QLatin1Char('/') ) ) != -1 )
0133             tmpStr = fileName.mid( pos + 1 );
0134 
0135     foreach( const QString &scheme, m_schemes )
0136     {
0137         Meta::FieldHash metadata = guessTagsByScheme( tmpStr, scheme, true, true, true );
0138         if( !metadata.isEmpty() )
0139             return metadata;
0140     }
0141 
0142     return Meta::FieldHash();
0143 }