mirror of
https://bitbucket.org/smil3y/kde-extraapps.git
synced 2025-02-24 19:02:53 +00:00
530 lines
17 KiB
C++
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;
|
|
}
|