/* This file is part of Clementine.
Clementine 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 3 of the License, or
(at your option) any later version.
Clementine 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 Clementine. If not, see .
*/
#include "song.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "radio/fixlastfm.h"
#include
#include
#include
#include
#include
#include
#include
#include
#ifdef Q_OS_WIN32
# include
# include
#endif // Q_OS_WIN32
#include
#include
using boost::scoped_ptr;
#include "albumcoverloader.h"
#include "encoding.h"
#include "utilities.h"
#include "engines/enginebase.h"
#include "library/sqlrow.h"
#include "widgets/trackslider.h"
static QStringList Prepend(const QString& text, const QStringList& list) {
QStringList ret(list);
for (int i=0 ; ivalid_ = true;
d->title_ = title;
d->artist_ = artist;
d->album_ = album;
d->length_ = length;
}
QString Song::Decode(const TagLib::String& tag, const QTextCodec* codec) {
if (codec && tag.isLatin1()) { // Never override UTF-8.
const std::string fixed = QString::fromUtf8(tag.toCString(true)).toStdString();
return codec->toUnicode(fixed.c_str()).trimmed();
} else {
return TStringToQString(tag).trimmed();
}
}
QString Song::Decode(const QString& tag, const QTextCodec* codec) {
if (!codec) {
return tag;
}
return codec->toUnicode(tag.toUtf8());
}
void Song::InitFromFile(const QString& filename, int directory_id) {
#ifndef QT_NO_DEBUG_OUTPUT
if (qApp->thread() == QThread::currentThread())
qWarning() << Q_FUNC_INFO << "on GUI thread!";
#endif
d->filename_ = filename;
d->directory_id_ = directory_id;
QMutexLocker l(&taglib_mutex_);
scoped_ptr fileref(factory_->GetFileRef(filename));
if(fileref->isNull())
return;
QFileInfo info(filename);
d->basefilename_ = info.fileName();
d->filesize_ = info.size();
d->mtime_ = info.lastModified().toTime_t();
d->ctime_ = info.created().toTime_t();
// This is single byte encoding, therefore can't be CJK.
UniversalEncodingHandler detector(NS_FILTER_NON_CJK);
TagLib::Tag* tag = fileref->tag();
QTextCodec* codec = NULL;
if (tag) {
codec = detector.Guess(*fileref);
d->title_ = Decode(tag->title(), codec);
d->artist_ = Decode(tag->artist(), codec);
d->album_ = Decode(tag->album(), codec);
d->genre_ = Decode(tag->genre(), codec);
d->year_ = tag->year();
d->track_ = tag->track();
d->valid_ = true;
}
QString disc;
QString compilation;
if (TagLib::MPEG::File* file = dynamic_cast(fileref->file())) {
if (file->ID3v2Tag()) {
const TagLib::ID3v2::FrameListMap& map = file->ID3v2Tag()->frameListMap();
if (!map["TPOS"].isEmpty())
disc = TStringToQString(map["TPOS"].front()->toString()).trimmed();
if (!map["TBPM"].isEmpty())
d->bpm_ = TStringToQString(map["TBPM"].front()->toString()).trimmed().toFloat();
if (!map["TCOM"].isEmpty())
d->composer_ = Decode(map["TCOM"].front()->toString(), codec);
if (!map["TPE2"].isEmpty()) // non-standard: Apple, Microsoft
d->albumartist_ = Decode(map["TPE2"].front()->toString(), codec);
if (!map["TCMP"].isEmpty())
compilation = TStringToQString(map["TCMP"].front()->toString()).trimmed();
if (!map["APIC"].isEmpty())
d->art_automatic_ = AlbumCoverLoader::kEmbeddedCover;
// Find a suitable comment tag. For now we ignore iTunNORM comments.
for (int i=0 ; i