kde-extraapps/amarok/shared/collectionscanner/Track.cpp
2015-01-31 00:30:50 +00:00

530 lines
17 KiB
C++

/***************************************************************************
* Copyright (C) 2003-2005 Max Howell <max.howell@methylblue.com> *
* (C) 2003-2010 Mark Kretschmann <kretschmann@kde.org> *
* (C) 2005-2007 Alexandre Oliveira <aleprj@gmail.com> *
* (C) 2008 Dan Meltzer <parallelgrapefruit@gmail.com> *
* (C) 2008-2009 Jeff Mitchell <mitchell@kde.org> *
* *
* 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 "Track.h"
#include "utils.h"
#include "MetaTagLib.h"
#include "MetaReplayGain.h"
#include <QDebug>
#include <QDir>
#include <QFile>
#include <QFileInfo>
#include <QXmlStreamReader>
#include <QXmlStreamWriter>
bool CollectionScanner::Track::s_useCharsetDetector = false;
CollectionScanner::Track::Track( const QString &path, CollectionScanner::Directory* directory )
: m_valid( true )
, m_directory( directory )
, m_filetype( Amarok::Unknown )
, m_compilation( false )
, m_noCompilation( false )
, m_hasCover( false )
, m_year( -1 )
, m_disc( -1 )
, m_track( -1 )
, m_bpm( -1.0 )
, m_bitrate( -1 )
, m_length( -1.0 )
, m_samplerate( -1 )
, m_filesize( -1 )
, m_trackGain( -1.0 )
, m_trackPeakGain( -1.0 )
, m_albumGain( -1.0 )
, m_albumPeakGain( -1.0 )
, m_rating( -1.0 )
, m_score( -1.0 )
, m_playcount( -1.0 )
{
static const int MAX_SENSIBLE_LENGTH = 1023; // the maximum length for normal strings.
// in corner cases a longer string might cause problems see BUG:276894
// for the unit test.
// in a debug build a file called "crash_amarok_here.ogg" will crash the collection
// scanner
if( path.contains("crash_amarok_here.ogg") )
{
qDebug() << "Crashing at"<<path;
Q_ASSERT( false );
}
Meta::FieldHash values = Meta::Tag::readTags( path, s_useCharsetDetector );
m_valid = !values.empty();
if( values.contains(Meta::valUniqueId) )
m_uniqueid = values.value(Meta::valUniqueId).toString();
m_path = path;
m_rpath = QDir::current().relativeFilePath( path );
if( values.contains(Meta::valFormat) )
m_filetype = Amarok::FileType(values.value(Meta::valFormat).toInt());
if( values.contains(Meta::valTitle) )
m_title = values.value(Meta::valTitle).toString();
if( values.contains(Meta::valArtist) )
m_artist = values.value(Meta::valArtist).toString().left(MAX_SENSIBLE_LENGTH);
if( values.contains(Meta::valAlbum) )
m_album = values.value(Meta::valAlbum).toString().left(MAX_SENSIBLE_LENGTH);
if( values.contains( Meta::valAlbumArtist ) )
m_albumArtist = values.value( Meta::valAlbumArtist ).toString().left(MAX_SENSIBLE_LENGTH);
if( values.contains(Meta::valCompilation) )
{
m_compilation = values.value(Meta::valCompilation).toBool();
m_noCompilation = !values.value(Meta::valCompilation).toBool();
}
if( values.contains(Meta::valHasCover) )
m_hasCover = values.value(Meta::valHasCover).toBool();
if( values.contains(Meta::valComment) )
m_comment = values.value(Meta::valComment).toString();
if( values.contains(Meta::valGenre) )
m_genre = values.value(Meta::valGenre).toString().left(MAX_SENSIBLE_LENGTH);
if( values.contains(Meta::valYear) )
m_year = values.value(Meta::valYear).toInt();
if( values.contains(Meta::valDiscNr) )
m_disc = values.value(Meta::valDiscNr).toInt();
if( values.contains(Meta::valTrackNr) )
m_track = values.value(Meta::valTrackNr).toInt();
if( values.contains(Meta::valBpm) )
m_bpm = values.value(Meta::valBpm).toReal();
if( values.contains(Meta::valBitrate) )
m_bitrate = values.value(Meta::valBitrate).toInt();
if( values.contains(Meta::valLength) )
m_length = values.value(Meta::valLength).toLongLong();
if( values.contains(Meta::valSamplerate) )
m_samplerate = values.value(Meta::valSamplerate).toInt();
if( values.contains(Meta::valFilesize) )
m_filesize = values.value(Meta::valFilesize).toLongLong();
if( values.contains(Meta::valModified) )
m_modified = values.value(Meta::valModified).toDateTime();
if( values.contains(Meta::valTrackGain) )
m_trackGain = values.value(Meta::valTrackGain).toReal();
if( values.contains(Meta::valTrackGainPeak) )
m_trackPeakGain = values.value(Meta::valTrackGainPeak).toReal();
if( values.contains(Meta::valAlbumGain) )
m_albumGain = values.value(Meta::valAlbumGain).toReal();
if( values.contains(Meta::valAlbumGainPeak) )
m_albumPeakGain = values.value(Meta::valAlbumGainPeak).toReal();
while( m_uniqueid.startsWith('/') )
m_uniqueid = m_uniqueid.mid(1);
if( values.contains(Meta::valComposer) )
m_composer = values.value(Meta::valComposer).toString().left(MAX_SENSIBLE_LENGTH);
if( values.contains(Meta::valRating) )
m_rating = values.value(Meta::valRating).toReal();
if( values.contains(Meta::valScore) )
m_score = values.value(Meta::valScore).toReal();
if( values.contains(Meta::valPlaycount) )
m_playcount = values.value(Meta::valPlaycount).toReal();
}
CollectionScanner::Track::Track( QXmlStreamReader *reader, CollectionScanner::Directory* directory )
: m_valid( true )
, m_directory( directory )
, m_filetype( Amarok::Unknown )
, m_compilation( false )
, m_noCompilation( false )
, m_hasCover( false )
, m_year( -1 )
, m_disc( -1 )
, m_track( -1 )
, m_bpm( -1 )
, m_bitrate( -1 )
, m_length( -1 )
, m_samplerate( -1 )
, m_filesize( -1 )
, m_trackGain( -1 )
, m_trackPeakGain( -1 )
, m_albumGain( -1 )
, m_albumPeakGain( -1 )
, m_rating( -1 )
, m_score( -1 )
, m_playcount( -1 )
{
// improve scanner with skipCurrentElement as soon as Amarok requires Qt 4.6
while (!reader->atEnd()) {
reader->readNext();
if( reader->isStartElement() )
{
QStringRef name = reader->name();
if( name == QLatin1String("uniqueid") )
m_uniqueid = reader->readElementText(QXmlStreamReader::SkipChildElements);
else if( name == QLatin1String("path") )
m_path = reader->readElementText(QXmlStreamReader::SkipChildElements);
else if( name == QLatin1String("rpath") )
m_rpath = reader->readElementText(QXmlStreamReader::SkipChildElements);
else if( name == QLatin1String("filetype") )
m_filetype = (Amarok::FileType)reader->readElementText(QXmlStreamReader::SkipChildElements).toInt();
else if( name == QLatin1String("title") )
m_title = reader->readElementText(QXmlStreamReader::SkipChildElements);
else if( name == QLatin1String("artist") )
m_artist = reader->readElementText(QXmlStreamReader::SkipChildElements);
else if( name == QLatin1String("albumArtist") )
m_albumArtist = reader->readElementText(QXmlStreamReader::SkipChildElements);
else if( name == QLatin1String("album") )
m_album = reader->readElementText();
else if( name == QLatin1String("compilation") )
{
m_compilation = true;
reader->skipCurrentElement();
}
else if( name == QLatin1String("noCompilation") )
{
m_noCompilation = true;
reader->skipCurrentElement();
}
else if( name == QLatin1String("hasCover") )
{
m_hasCover = true;
reader->skipCurrentElement();
}
else if( name == QLatin1String("comment") )
m_comment = reader->readElementText(QXmlStreamReader::SkipChildElements);
else if( name == QLatin1String("genre") )
m_genre = reader->readElementText(QXmlStreamReader::SkipChildElements);
else if( name == QLatin1String("year") )
m_year = reader->readElementText(QXmlStreamReader::SkipChildElements).toInt();
else if( name == QLatin1String("disc") )
m_disc = reader->readElementText(QXmlStreamReader::SkipChildElements).toInt();
else if( name == QLatin1String("track") )
m_track = reader->readElementText(QXmlStreamReader::SkipChildElements).toInt();
else if( name == QLatin1String("bpm") )
m_bpm = reader->readElementText(QXmlStreamReader::SkipChildElements).toFloat();
else if( name == QLatin1String("bitrate") )
m_bitrate = reader->readElementText(QXmlStreamReader::SkipChildElements).toInt();
else if( name == QLatin1String("length") )
m_length = reader->readElementText(QXmlStreamReader::SkipChildElements).toLong();
else if( name == QLatin1String("samplerate") )
m_samplerate = reader->readElementText(QXmlStreamReader::SkipChildElements).toInt();
else if( name == QLatin1String("filesize") )
m_filesize = reader->readElementText(QXmlStreamReader::SkipChildElements).toLong();
else if( name == QLatin1String("mtime") )
m_modified = QDateTime::fromTime_t(reader->readElementText(QXmlStreamReader::SkipChildElements).toLong());
else if( name == QLatin1String("trackGain") )
m_trackGain = reader->readElementText(QXmlStreamReader::SkipChildElements).toFloat();
else if( name == QLatin1String("trackPeakGain") )
m_trackPeakGain = reader->readElementText(QXmlStreamReader::SkipChildElements).toFloat();
else if( name == QLatin1String("albumGain") )
m_albumGain = reader->readElementText(QXmlStreamReader::SkipChildElements).toFloat();
else if( name == QLatin1String("albumPeakGain") )
m_albumPeakGain = reader->readElementText(QXmlStreamReader::SkipChildElements).toFloat();
else if( name == QLatin1String("composer") )
m_composer = reader->readElementText(QXmlStreamReader::SkipChildElements);
else if( name == QLatin1String("rating") )
m_rating = reader->readElementText(QXmlStreamReader::SkipChildElements).toFloat();
else if( name == QLatin1String("score") )
m_score = reader->readElementText(QXmlStreamReader::SkipChildElements).toFloat();
else if( name == QLatin1String("playcount") )
m_playcount = reader->readElementText(QXmlStreamReader::SkipChildElements).toInt();
else
{
qDebug() << "Unexpected xml start element"<<name<<"in input";
reader->skipCurrentElement();
}
}
else if( reader->isEndElement() )
{
break;
}
}
}
void
CollectionScanner::Track::write( QXmlStreamWriter *writer,
const QString &tag, const QString &str ) const
{
if( !str.isEmpty() )
writer->writeTextElement( tag, escapeXml10(str) );
}
void
CollectionScanner::Track::toXml( QXmlStreamWriter *writer ) const
{
if( !m_valid )
return;
write( writer, QLatin1String("uniqueid"), m_uniqueid );
write( writer, QLatin1String("path"), m_path );
write( writer, QLatin1String("rpath"), m_rpath );
write(writer, QLatin1String("filetype"), QString::number( (int)m_filetype ) );
write( writer, QLatin1String("title"), m_title);
write( writer, QLatin1String("artist"), m_artist);
write( writer, QLatin1String("albumArtist"), m_albumArtist);
write( writer, QLatin1String("album"), m_album);
if( m_compilation )
writer->writeEmptyElement( QLatin1String("compilation") );
if( m_noCompilation )
writer->writeEmptyElement( QLatin1String("noCompilation") );
if( m_hasCover )
writer->writeEmptyElement( QLatin1String("hasCover") );
write( writer, QLatin1String("comment"), m_comment);
write( writer, QLatin1String("genre"), m_genre);
if( m_year != -1 )
write(writer, QLatin1String("year"), QString::number( m_year ) );
if( m_disc != -1 )
write(writer, QLatin1String("disc"), QString::number( m_disc ) );
if( m_track != -1 )
write(writer, QLatin1String("track"), QString::number( m_track ) );
if( m_bpm != -1 )
write(writer, QLatin1String("bpm"), QString::number( m_bpm ) );
if( m_bitrate != -1 )
write(writer, QLatin1String("bitrate"), QString::number( m_bitrate ) );
if( m_length != -1 )
write(writer, QLatin1String("length"), QString::number( m_length ) );
if( m_samplerate != -1 )
write(writer, QLatin1String("samplerate"), QString::number( m_samplerate ) );
if( m_filesize != -1 )
write(writer, QLatin1String("filesize"), QString::number( m_filesize ) );
if( m_modified.isValid() )
write(writer, QLatin1String("mtime"), QString::number( m_modified.toTime_t() ) );
if( m_trackGain != 0 )
write(writer, QLatin1String("trackGain"), QString::number( m_trackGain ) );
if( m_trackPeakGain != 0 )
write(writer, QLatin1String("trackPeakGain"), QString::number( m_trackPeakGain ) );
if( m_albumGain != 0 )
write(writer, QLatin1String("albumGain"), QString::number( m_albumGain ) );
if( m_albumPeakGain != 0 )
write(writer, QLatin1String("albumPeakGain"), QString::number( m_albumPeakGain ) );
write( writer, QLatin1String("composer"), m_composer);
if( m_rating != -1 )
write(writer, QLatin1String("rating"), QString::number( m_rating ) );
if( m_score != -1 )
write(writer, QLatin1String("score"), QString::number( m_score ) );
if( m_playcount != -1 )
write(writer, QLatin1String("playcount"), QString::number( m_playcount ) );
}
bool
CollectionScanner::Track::isValid() const
{
return m_valid;
}
CollectionScanner::Directory*
CollectionScanner::Track::directory() const
{
return m_directory;
}
QString
CollectionScanner::Track::uniqueid() const
{
return m_uniqueid;
}
QString
CollectionScanner::Track::path() const
{
return m_path;
}
QString
CollectionScanner::Track::rpath() const
{
return m_rpath;
}
Amarok::FileType
CollectionScanner::Track::filetype() const
{
return m_filetype;
}
QString
CollectionScanner::Track::title() const
{
return m_title;
}
QString
CollectionScanner::Track::artist() const
{
return m_artist;
}
QString
CollectionScanner::Track::albumArtist() const
{
return m_albumArtist;
}
QString
CollectionScanner::Track::album() const
{
return m_album;
}
bool
CollectionScanner::Track::isCompilation() const
{
return m_compilation;
}
bool
CollectionScanner::Track::isNoCompilation() const
{
return m_noCompilation;
}
bool
CollectionScanner::Track::hasCover() const
{
return m_hasCover;
}
QString
CollectionScanner::Track::comment() const
{
return m_comment;
}
QString
CollectionScanner::Track::genre() const
{
return m_genre;
}
int
CollectionScanner::Track::year() const
{
return m_year;
}
int
CollectionScanner::Track::disc() const
{
return m_disc;
}
int
CollectionScanner::Track::track() const
{
return m_track;
}
int
CollectionScanner::Track::bpm() const
{
return m_bpm;
}
int
CollectionScanner::Track::bitrate() const
{
return m_bitrate;
}
qint64
CollectionScanner::Track::length() const
{
return m_length;
}
int
CollectionScanner::Track::samplerate() const
{
return m_samplerate;
}
qint64
CollectionScanner::Track::filesize() const
{
return m_filesize;
}
QDateTime
CollectionScanner::Track::modified() const
{
return m_modified;
}
QString
CollectionScanner::Track::composer() const
{
return m_composer;
}
qreal
CollectionScanner::Track::replayGain( Meta::ReplayGainTag mode ) const
{
switch( mode )
{
case Meta::ReplayGain_Track_Gain:
return m_trackGain;
case Meta::ReplayGain_Track_Peak:
return m_trackPeakGain;
case Meta::ReplayGain_Album_Gain:
return m_albumGain;
case Meta::ReplayGain_Album_Peak:
return m_albumPeakGain;
}
return 0.0;
}
qreal
CollectionScanner::Track::rating() const
{
return m_rating;
}
qreal
CollectionScanner::Track::score() const
{
return m_score;
}
int
CollectionScanner::Track::playcount() const
{
return m_playcount;
}
void
CollectionScanner::Track::setUseCharsetDetector( bool value )
{
s_useCharsetDetector = value;
}