2 * (c) 2005 Alexandre Oliveira <aleprj@gmail.com>
3 * (c) 2003 Frerich Raabe <raabe@kde.org>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
11 #define DEBUG_PREFIX "TagGuesser"
13 #include "TagGuesser.h"
18 #include <KApplication>
20 #include <KConfigGroup>
22 #include <KMacroExpanderBase>
24 FileNameScheme::FileNameScheme( const QString
&s
)
30 , m_commentField( -1 )
32 , m_composerField( -1 )
35 int artist
= s
.indexOf( "%artist" );
36 int title
= s
.indexOf( "%title" );
37 int track
= s
.indexOf( "%track" );
38 int album
= s
.indexOf( "%album" );
39 int comment
= s
.indexOf( "%comment" );
40 int year
= s
.indexOf( "%year" );
41 int composer
= s
.indexOf( "%composer" );
42 int genre
= s
.indexOf( "%genre" );
45 int i
= s
.indexOf( '%' );
48 m_titleField
= fieldNumber
++;
50 m_artistField
= fieldNumber
++;
52 m_albumField
= fieldNumber
++;
54 m_trackField
= fieldNumber
++;
56 m_commentField
= fieldNumber
++;
58 m_yearField
= fieldNumber
++;
60 m_composerField
= fieldNumber
++;
62 m_genreField
= fieldNumber
++;
64 i
= s
.indexOf('%', i
+ 1);
66 m_regExp
.setPattern( composeRegExp( s
) );
69 bool FileNameScheme::matches( const QString
&fileName
) const
71 /* Strip extension ('.mp3') because '.' may be part of a title, and thus
72 * does not work as a separator.
74 QString stripped
= fileName
;
75 stripped
.truncate( stripped
.lastIndexOf( '.' ) );
76 return m_regExp
.exactMatch( stripped
);
79 QString
FileNameScheme::title() const
81 if( m_titleField
== -1 )
83 return m_regExp
.capturedTexts()[ m_titleField
];
86 QString
FileNameScheme::artist() const
88 if( m_artistField
== -1 )
90 return m_regExp
.capturedTexts()[ m_artistField
];
93 QString
FileNameScheme::album() const
95 if( m_albumField
== -1 )
97 return m_regExp
.capturedTexts()[ m_albumField
];
100 QString
FileNameScheme::track() const
102 if( m_trackField
== -1 )
104 return m_regExp
.capturedTexts()[ m_trackField
];
107 QString
FileNameScheme::comment() const
109 if( m_commentField
== -1 )
111 return m_regExp
.capturedTexts()[ m_commentField
];
114 QString
FileNameScheme::year() const
116 if( m_yearField
== -1 )
118 return m_regExp
.capturedTexts()[ m_yearField
];
121 QString
FileNameScheme::composer() const
123 if( m_composerField
== -1 )
125 return m_regExp
.capturedTexts()[ m_composerField
];
128 QString
FileNameScheme::genre() const
130 if( m_genreField
== -1 )
132 return m_regExp
.capturedTexts()[ m_genreField
];
135 QString
FileNameScheme::composeRegExp( const QString
&s
) const
137 QHash
<QString
, QString
> substitutions
;
139 KConfigGroup
config(KGlobal::config(), "TagGuesser");
141 substitutions
[ "title" ] = config
.readEntry( "Title regexp", "([\\w\\s'&_,\\.]+)" );
142 substitutions
[ "artist" ] = config
.readEntry( "Artist regexp", "([\\w\\s'&_,\\.]+)" );
143 substitutions
[ "album" ] = config
.readEntry( "Album regexp", "([\\w\\s'&_,\\.]+)" );
144 substitutions
[ "track" ] = config
.readEntry( "Track regexp", "(\\d+)" );
145 substitutions
[ "comment" ] = config
.readEntry( "Comment regexp", "([\\w\\s_]+)" );
146 substitutions
[ "year" ] = config
.readEntry( "Year regexp", "(\\d+)" );
147 substitutions
[ "composer" ] = config
.readEntry( "Composer regexp", "([\\w\\s'&_,\\.]+)" );
148 substitutions
[ "genre" ] = config
.readEntry( "Genre regexp", "([\\w\\s'&_,\\.]+)" );
151 QString regExp
= QRegExp::escape( s
.simplified() );
152 regExp
= ".*" + regExp
;
153 regExp
.replace( ' ', "\\s+" );
154 regExp
= KMacroExpander::expandMacros( regExp
, substitutions
);
159 QStringList
TagGuesser::schemeStrings()
163 schemes
= Amarok::config( "TagGuesser" ).readEntry( "Filename schemes", QStringList() );
165 if ( schemes
.isEmpty() ) {
166 schemes
+= "%track - %title";
167 schemes
+= "%artist - (%track) - %title [%comment]";
168 schemes
+= "%artist - (%track) - %title (%comment)";
169 schemes
+= "%artist - (%track) - %title";
170 schemes
+= "%artist - [%track] - %title [%comment]";
171 schemes
+= "%artist - [%track] - %title (%comment)";
172 schemes
+= "%artist - [%track] - %title";
173 schemes
+= "%artist - %track - %title [%comment]";
174 schemes
+= "%artist - %track - %title (%comment)";
175 schemes
+= "%artist - %track - %title";
176 schemes
+= "(%track) %artist - %title [%comment]";
177 schemes
+= "(%track) %artist - %title (%comment)";
178 schemes
+= "(%track) %artist - %title";
179 schemes
+= "[%track] %artist - %title [%comment]";
180 schemes
+= "[%track] %artist - %title (%comment)";
181 schemes
+= "[%track] %artist - %title";
182 schemes
+= "%track %artist - %title [%comment]";
183 schemes
+= "%track %artist - %title (%comment)";
184 schemes
+= "%track %artist - %title";
185 schemes
+= "(%artist) %title [%comment]";
186 schemes
+= "(%artist) %title (%comment)";
187 schemes
+= "(%artist) %title";
188 schemes
+= "%artist - %title [%comment]";
189 schemes
+= "%artist - %title (%comment)";
190 schemes
+= "%artist - %title";
191 schemes
+= "%artist/%album/[%track] %title [%comment]";
192 schemes
+= "%artist/%album/[%track] %title (%comment)";
193 schemes
+= "%artist/%album/[%track] %title";
198 void TagGuesser::setSchemeStrings( const QStringList
&schemes
)
200 KConfigGroup cfg
= Amarok::config("TagGuesser");
201 cfg
.writeEntry( "Filename schemes", schemes
);
205 TagGuesser::TagGuesser()
210 TagGuesser::TagGuesser( const QString
&absFileName
)
213 guess( absFileName
);
216 void TagGuesser::loadSchemes()
218 const QStringList schemes
= schemeStrings();
219 QStringList::ConstIterator it
= schemes
.begin();
220 QStringList::ConstIterator end
= schemes
.end();
221 for ( ; it
!= end
; ++it
)
222 m_schemes
+= FileNameScheme( *it
);
225 void TagGuesser::guess( const QString
&absFileName
)
227 m_title
= m_artist
= m_album
= m_track
= m_comment
= m_year
= m_composer
= m_genre
= QString();
229 FileNameScheme::List::ConstIterator it
= m_schemes
.begin();
230 FileNameScheme::List::ConstIterator end
= m_schemes
.end();
231 for ( ; it
!= end
; ++it
) {
232 const FileNameScheme
schema( *it
);
233 if( schema
.matches( absFileName
) ) {
234 debug() <<"Schema used: " << " " << schema
.pattern();
235 m_title
= capitalizeWords( schema
.title().replace( '_', " " ) ).trimmed();
236 m_artist
= capitalizeWords( schema
.artist().replace( '_', " " ) ).trimmed();
237 m_album
= capitalizeWords( schema
.album().replace( '_', " " ) ).trimmed();
238 m_track
= schema
.track().trimmed();
239 m_comment
= schema
.comment().replace( '_', " " ).trimmed();
240 m_year
= schema
.year().trimmed();
241 m_composer
= capitalizeWords( schema
.composer().replace( '_', " " ) ).trimmed();
242 m_genre
= capitalizeWords( schema
.genre().replace( '_', " " ) ).trimmed();
248 QString
TagGuesser::capitalizeWords( const QString
&s
)
254 result
[ 0 ] = result
[ 0 ].toUpper();
256 const QRegExp
wordRegExp( "\\s\\w" );
257 int i
= result
.indexOf( wordRegExp
);
259 result
[ i
+ 1 ] = result
[ i
+ 1 ].toUpper();
260 i
= result
.indexOf( wordRegExp
, ++i
);