Use URLs everywhere instead of filenames. Move the URL parsing and song loading code out of individual playlist parsers and into the base class. Fix the playlist parser unit tests.
This commit is contained in:
parent
9dd45dbe82
commit
ccb9f8cf94
@ -312,5 +312,6 @@
|
|||||||
<file>icons/48x48/mail-message.png</file>
|
<file>icons/48x48/mail-message.png</file>
|
||||||
<file>schema/schema-29.sql</file>
|
<file>schema/schema-29.sql</file>
|
||||||
<file>schema/schema-30.sql</file>
|
<file>schema/schema-30.sql</file>
|
||||||
|
<file>schema/schema-31.sql</file>
|
||||||
</qresource>
|
</qresource>
|
||||||
</RCC>
|
</RCC>
|
||||||
|
3
data/schema/schema-31.sql
Normal file
3
data/schema/schema-31.sql
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
UPDATE songs SET filename = "file://" || filename;
|
||||||
|
|
||||||
|
UPDATE schema_version SET version=31;
|
@ -125,7 +125,7 @@ class DigitallyImportedServiceBase(clementine.RadioService):
|
|||||||
song = clementine.Song()
|
song = clementine.Song()
|
||||||
song.set_title(stream["name"])
|
song.set_title(stream["name"])
|
||||||
song.set_artist(self.SERVICE_DESCRIPTION)
|
song.set_artist(self.SERVICE_DESCRIPTION)
|
||||||
song.set_filename("digitallyimported://%s" % stream["key"])
|
song.set_url(QUrl("digitallyimported://%s" % stream["key"]))
|
||||||
|
|
||||||
item = QStandardItem(QIcon(":last.fm/icon_radio.png"), stream["name"])
|
item = QStandardItem(QIcon(":last.fm/icon_radio.png"), stream["name"])
|
||||||
item.setData(stream["description"], PyQt4.QtCore.Qt.ToolTipRole)
|
item.setData(stream["description"], PyQt4.QtCore.Qt.ToolTipRole)
|
||||||
@ -192,6 +192,6 @@ class DigitallyImportedServiceBase(clementine.RadioService):
|
|||||||
|
|
||||||
# Take the first track in the playlist
|
# Take the first track in the playlist
|
||||||
result.type_ = clementine.PlaylistItem.SpecialLoadResult.TrackAvailable
|
result.type_ = clementine.PlaylistItem.SpecialLoadResult.TrackAvailable
|
||||||
result.media_url_ = QUrl(songs[0].filename())
|
result.media_url_ = songs[0].url()
|
||||||
|
|
||||||
self.AsyncLoadFinished.emit(result)
|
self.AsyncLoadFinished.emit(result)
|
||||||
|
@ -32,7 +32,7 @@
|
|||||||
#include <QVariant>
|
#include <QVariant>
|
||||||
|
|
||||||
const char* Database::kDatabaseFilename = "clementine.db";
|
const char* Database::kDatabaseFilename = "clementine.db";
|
||||||
const int Database::kSchemaVersion = 30;
|
const int Database::kSchemaVersion = 31;
|
||||||
const char* Database::kMagicAllSongsTables = "%allsongstables";
|
const char* Database::kMagicAllSongsTables = "%allsongstables";
|
||||||
|
|
||||||
int Database::sNextConnectionId = 1;
|
int Database::sNextConnectionId = 1;
|
||||||
|
@ -60,7 +60,7 @@ void DeleteFiles::Start(const QStringList& filenames) {
|
|||||||
SongList songs;
|
SongList songs;
|
||||||
foreach (const QString& filename, filenames) {
|
foreach (const QString& filename, filenames) {
|
||||||
Song song;
|
Song song;
|
||||||
song.set_filename(filename);
|
song.set_url(QUrl::fromLocalFile(filename));
|
||||||
songs << song;
|
songs << song;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -66,14 +66,14 @@ bool FilesystemMusicStorage::CopyToStorage(const CopyJob& job) {
|
|||||||
bool FilesystemMusicStorage::DeleteFromStorage(const DeleteJob& job) {
|
bool FilesystemMusicStorage::DeleteFromStorage(const DeleteJob& job) {
|
||||||
#ifdef HAVE_GIO
|
#ifdef HAVE_GIO
|
||||||
//convert QString to char
|
//convert QString to char
|
||||||
QByteArray ba = job.metadata_.filename().toLocal8Bit();
|
QByteArray ba = job.metadata_.url().toLocalFile().toLocal8Bit();
|
||||||
const char *filepathChar = ba.data();
|
const char *filepathChar = ba.data();
|
||||||
GFile *file = g_file_new_for_path (filepathChar);
|
GFile *file = g_file_new_for_path (filepathChar);
|
||||||
bool success = g_file_trash(file, NULL, NULL);
|
bool success = g_file_trash(file, NULL, NULL);
|
||||||
g_object_unref(file);
|
g_object_unref(file);
|
||||||
return success;
|
return success;
|
||||||
#else
|
#else
|
||||||
return QFile::remove(job.metadata_.filename());
|
return QFile::remove(job.metadata_.url().toLocalFile());
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -321,7 +321,7 @@ void Mpris1TrackList::PlayTrack(int index) {
|
|||||||
QVariantMap Mpris1::GetMetadata(const Song& song) {
|
QVariantMap Mpris1::GetMetadata(const Song& song) {
|
||||||
QVariantMap ret;
|
QVariantMap ret;
|
||||||
|
|
||||||
AddMetadata("location", song.filename(), &ret);
|
AddMetadata("location", song.url().toString(), &ret);
|
||||||
AddMetadata("title", song.PrettyTitle(), &ret);
|
AddMetadata("title", song.PrettyTitle(), &ret);
|
||||||
AddMetadata("artist", song.artist(), &ret);
|
AddMetadata("artist", song.artist(), &ret);
|
||||||
AddMetadata("album", song.album(), &ret);
|
AddMetadata("album", song.album(), &ret);
|
||||||
|
@ -308,7 +308,7 @@ void Mpris2::ArtLoaded(const Song& song, const QString& art_uri) {
|
|||||||
|
|
||||||
using mpris::AddMetadata;
|
using mpris::AddMetadata;
|
||||||
AddMetadata("mpris:trackid", current_track_id(), &last_metadata_);
|
AddMetadata("mpris:trackid", current_track_id(), &last_metadata_);
|
||||||
AddMetadata("xesam:url", song.filename(), &last_metadata_);
|
AddMetadata("xesam:url", song.url().toString(), &last_metadata_);
|
||||||
AddMetadata("xesam:title", song.PrettyTitle(), &last_metadata_);
|
AddMetadata("xesam:title", song.PrettyTitle(), &last_metadata_);
|
||||||
AddMetadataAsList("xesam:artist", song.artist(), &last_metadata_);
|
AddMetadataAsList("xesam:artist", song.artist(), &last_metadata_);
|
||||||
AddMetadata("xesam:album", song.album(), &last_metadata_);
|
AddMetadata("xesam:album", song.album(), &last_metadata_);
|
||||||
|
@ -148,7 +148,7 @@ void Organise::ProcessSomeFiles() {
|
|||||||
song.set_filetype(task.new_filetype_);
|
song.set_filetype(task.new_filetype_);
|
||||||
|
|
||||||
// Fiddle the filename extension as well to match the new type
|
// Fiddle the filename extension as well to match the new type
|
||||||
song.set_filename(FiddleFileExtension(song.filename(), task.new_extension_));
|
song.set_url(QUrl::fromLocalFile(FiddleFileExtension(song.url().toLocalFile(), task.new_extension_)));
|
||||||
song.set_basefilename(FiddleFileExtension(song.basefilename(), task.new_extension_));
|
song.set_basefilename(FiddleFileExtension(song.basefilename(), task.new_extension_));
|
||||||
|
|
||||||
// Have to set this to the size of the new file or else funny stuff happens
|
// Have to set this to the size of the new file or else funny stuff happens
|
||||||
|
@ -139,7 +139,7 @@ QString OrganiseFormat::TagValue(const QString &tag, const Song &song) const {
|
|||||||
else if (tag == "length") value = QString::number(song.length_nanosec() / kNsecPerSec);
|
else if (tag == "length") value = QString::number(song.length_nanosec() / kNsecPerSec);
|
||||||
else if (tag == "bitrate") value = QString::number(song.bitrate());
|
else if (tag == "bitrate") value = QString::number(song.bitrate());
|
||||||
else if (tag == "samplerate") value = QString::number(song.samplerate());
|
else if (tag == "samplerate") value = QString::number(song.samplerate());
|
||||||
else if (tag == "extension") value = song.filename().section('.', -1, -1);
|
else if (tag == "extension") value = song.url().toLocalFile().section('.', -1, -1);
|
||||||
else if (tag == "artistinitial") {
|
else if (tag == "artistinitial") {
|
||||||
value = song.albumartist().trimmed();
|
value = song.albumartist().trimmed();
|
||||||
if (value.isEmpty()) value = song.artist().trimmed();
|
if (value.isEmpty()) value = song.artist().trimmed();
|
||||||
|
@ -253,7 +253,7 @@ bool Song::HasProperMediaFile() const {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
QMutexLocker l(&taglib_mutex_);
|
QMutexLocker l(&taglib_mutex_);
|
||||||
scoped_ptr<TagLib::FileRef> fileref(factory_->GetFileRef(d->filename_));
|
scoped_ptr<TagLib::FileRef> fileref(factory_->GetFileRef(d->url_.toLocalFile()));
|
||||||
|
|
||||||
return !fileref->isNull() && fileref->tag();
|
return !fileref->isNull() && fileref->tag();
|
||||||
}
|
}
|
||||||
@ -266,7 +266,7 @@ void Song::InitFromFile(const QString& filename, int directory_id) {
|
|||||||
|
|
||||||
d->init_from_file_ = true;
|
d->init_from_file_ = true;
|
||||||
|
|
||||||
d->filename_ = filename;
|
d->url_ = QUrl::fromLocalFile(filename);
|
||||||
d->directory_id_ = directory_id;
|
d->directory_id_ = directory_id;
|
||||||
|
|
||||||
QFileInfo info(filename);
|
QFileInfo info(filename);
|
||||||
@ -502,6 +502,7 @@ void Song::InitFromQuery(const SqlRow& q, int col) {
|
|||||||
d->init_from_file_ = true;
|
d->init_from_file_ = true;
|
||||||
|
|
||||||
#define tostr(n) (q.value(n).isNull() ? QString::null : q.value(n).toString())
|
#define tostr(n) (q.value(n).isNull() ? QString::null : q.value(n).toString())
|
||||||
|
#define tobytearray(n)(q.value(n).isNull() ? QByteArray() : q.value(n).toByteArray())
|
||||||
#define toint(n) (q.value(n).isNull() ? -1 : q.value(n).toInt())
|
#define toint(n) (q.value(n).isNull() ? -1 : q.value(n).toInt())
|
||||||
#define tolonglong(n) (q.value(n).isNull() ? -1 : q.value(n).toLongLong())
|
#define tolonglong(n) (q.value(n).isNull() ? -1 : q.value(n).toLongLong())
|
||||||
#define tofloat(n) (q.value(n).isNull() ? -1 : q.value(n).toDouble())
|
#define tofloat(n) (q.value(n).isNull() ? -1 : q.value(n).toDouble())
|
||||||
@ -524,8 +525,8 @@ void Song::InitFromQuery(const SqlRow& q, int col) {
|
|||||||
d->samplerate_ = toint(col + 14);
|
d->samplerate_ = toint(col + 14);
|
||||||
|
|
||||||
d->directory_id_ = toint(col + 15);
|
d->directory_id_ = toint(col + 15);
|
||||||
d->filename_ = tostr(col + 16);
|
d->url_ = QUrl::fromEncoded(tobytearray(col + 16));
|
||||||
d->basefilename_ = QFileInfo(d->filename_).fileName();
|
d->basefilename_ = QFileInfo(d->url_.toLocalFile()).fileName();
|
||||||
d->mtime_ = toint(col + 17);
|
d->mtime_ = toint(col + 17);
|
||||||
d->ctime_ = toint(col + 18);
|
d->ctime_ = toint(col + 18);
|
||||||
d->filesize_ = toint(col + 19);
|
d->filesize_ = toint(col + 19);
|
||||||
@ -562,7 +563,7 @@ void Song::InitFromQuery(const SqlRow& q, int col) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Song::InitFromFilePartial(const QString& filename) {
|
void Song::InitFromFilePartial(const QString& filename) {
|
||||||
d->filename_ = filename;
|
d->url_ = QUrl::fromLocalFile(filename);
|
||||||
// We currently rely on filename suffix to know if it's a music file or not.
|
// We currently rely on filename suffix to know if it's a music file or not.
|
||||||
// TODO: I know this is not satisfying, but currently, we rely on TagLib
|
// TODO: I know this is not satisfying, but currently, we rely on TagLib
|
||||||
// which seems to have the behavior (filename checks). Someday, it would be
|
// which seems to have the behavior (filename checks). Someday, it would be
|
||||||
@ -594,7 +595,7 @@ void Song::InitFromLastFM(const lastfm::Track& track) {
|
|||||||
#endif // HAVE_LIBLASTFM
|
#endif // HAVE_LIBLASTFM
|
||||||
|
|
||||||
#ifdef HAVE_LIBGPOD
|
#ifdef HAVE_LIBGPOD
|
||||||
void Song::InitFromItdb(const Itdb_Track* track) {
|
void Song::InitFromItdb(const Itdb_Track* track, const QString& prefix) {
|
||||||
d->valid_ = true;
|
d->valid_ = true;
|
||||||
|
|
||||||
d->title_ = QString::fromUtf8(track->title);
|
d->title_ = QString::fromUtf8(track->title);
|
||||||
@ -621,9 +622,11 @@ void Song::InitFromLastFM(const lastfm::Track& track) {
|
|||||||
d->skipcount_ = track->skipcount;
|
d->skipcount_ = track->skipcount;
|
||||||
d->lastplayed_ = track->time_played;
|
d->lastplayed_ = track->time_played;
|
||||||
|
|
||||||
d->filename_ = QString::fromLocal8Bit(track->ipod_path);
|
QString filename = QString::fromLocal8Bit(track->ipod_path);
|
||||||
d->filename_.replace(':', '/');
|
filename.replace(':', '/');
|
||||||
d->basefilename_ = QFileInfo(d->filename_).fileName();
|
|
||||||
|
d->url_ = QUrl::fromLocalFile(prefix + filename);
|
||||||
|
d->basefilename_ = QFileInfo(filename).fileName();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Song::ToItdb(Itdb_Track *track) const {
|
void Song::ToItdb(Itdb_Track *track) const {
|
||||||
@ -656,7 +659,7 @@ void Song::InitFromLastFM(const lastfm::Track& track) {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_LIBMTP
|
#ifdef HAVE_LIBMTP
|
||||||
void Song::InitFromMTP(const LIBMTP_track_t* track) {
|
void Song::InitFromMTP(const LIBMTP_track_t* track, const QString& host) {
|
||||||
d->valid_ = true;
|
d->valid_ = true;
|
||||||
|
|
||||||
d->title_ = QString::fromUtf8(track->title);
|
d->title_ = QString::fromUtf8(track->title);
|
||||||
@ -664,8 +667,8 @@ void Song::InitFromLastFM(const lastfm::Track& track) {
|
|||||||
d->album_ = QString::fromUtf8(track->album);
|
d->album_ = QString::fromUtf8(track->album);
|
||||||
d->composer_ = QString::fromUtf8(track->composer);
|
d->composer_ = QString::fromUtf8(track->composer);
|
||||||
d->genre_ = QString::fromUtf8(track->genre);
|
d->genre_ = QString::fromUtf8(track->genre);
|
||||||
d->filename_ = QString::number(track->item_id);
|
d->url_ = QUrl(QString("mtp://%1/%2").arg(host, track->item_id));
|
||||||
d->basefilename_ = d->filename_;
|
d->basefilename_ = QString::number(track->item_id);
|
||||||
|
|
||||||
d->track_ = track->tracknumber;
|
d->track_ = track->tracknumber;
|
||||||
set_length_nanosec(track->duration * kNsecPerMsec);
|
set_length_nanosec(track->duration * kNsecPerMsec);
|
||||||
@ -839,7 +842,7 @@ void Song::InitFromLastFM(const lastfm::Track& track) {
|
|||||||
d->bitrate_ = item_value.toInt();
|
d->bitrate_ = item_value.toInt();
|
||||||
|
|
||||||
else if (wcscmp(name, g_wszWMDMFileName) == 0)
|
else if (wcscmp(name, g_wszWMDMFileName) == 0)
|
||||||
d->filename_ = item_value.toString();
|
d->url_ = QUrl::fromLocalFile(item_value.toString());
|
||||||
|
|
||||||
else if (wcscmp(name, g_wszWMDMDuration) == 0)
|
else if (wcscmp(name, g_wszWMDMDuration) == 0)
|
||||||
set_length_nanosec(item_value.toULongLong() * 1e2);
|
set_length_nanosec(item_value.toULongLong() * 1e2);
|
||||||
@ -913,7 +916,7 @@ void Song::InitFromLastFM(const lastfm::Track& track) {
|
|||||||
|
|
||||||
// Make a final guess based on the file extension
|
// Make a final guess based on the file extension
|
||||||
{
|
{
|
||||||
QString ext = d->filename_.section('.', -1, -1).toLower();
|
QString ext = d->url_.path().section('.', -1, -1).toLower();
|
||||||
if (ext == "mp3" || ext == "wma" || ext == "flac" || ext == "ogg" ||
|
if (ext == "mp3" || ext == "wma" || ext == "flac" || ext == "ogg" ||
|
||||||
ext == "spx" || ext == "mp4" || ext == "aac" || ext == "m4a")
|
ext == "spx" || ext == "mp4" || ext == "aac" || ext == "m4a")
|
||||||
break;
|
break;
|
||||||
@ -1007,7 +1010,7 @@ void Song::BindToQuery(QSqlQuery *query) const {
|
|||||||
query->bindValue(":samplerate", intval(d->samplerate_));
|
query->bindValue(":samplerate", intval(d->samplerate_));
|
||||||
|
|
||||||
query->bindValue(":directory", notnullintval(d->directory_id_));
|
query->bindValue(":directory", notnullintval(d->directory_id_));
|
||||||
query->bindValue(":filename", d->filename_);
|
query->bindValue(":filename", d->url_.toEncoded());
|
||||||
query->bindValue(":mtime", notnullintval(d->mtime_));
|
query->bindValue(":mtime", notnullintval(d->mtime_));
|
||||||
query->bindValue(":ctime", notnullintval(d->ctime_));
|
query->bindValue(":ctime", notnullintval(d->ctime_));
|
||||||
query->bindValue(":filesize", notnullintval(d->filesize_));
|
query->bindValue(":filesize", notnullintval(d->filesize_));
|
||||||
@ -1066,12 +1069,6 @@ void Song::ToLastFM(lastfm::Track* track) const {
|
|||||||
}
|
}
|
||||||
#endif // HAVE_LIBLASTFM
|
#endif // HAVE_LIBLASTFM
|
||||||
|
|
||||||
QUrl Song::url() const {
|
|
||||||
return QFile::exists(filename())
|
|
||||||
? QUrl::fromLocalFile(filename())
|
|
||||||
: filename();
|
|
||||||
}
|
|
||||||
|
|
||||||
QString Song::PrettyTitle() const {
|
QString Song::PrettyTitle() const {
|
||||||
QString title(d->title_);
|
QString title(d->title_);
|
||||||
|
|
||||||
@ -1164,16 +1161,17 @@ TagLib::String QStringToTaglibString(const QString& s) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool Song::IsEditable() const {
|
bool Song::IsEditable() const {
|
||||||
return d->valid_ && !d->filename_.isNull() && !is_stream() &&
|
return d->valid_ && !d->url_.isEmpty() && !is_stream() &&
|
||||||
d->filetype_ != Type_Unknown && !has_cue();
|
d->filetype_ != Type_Unknown && !has_cue();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Song::Save() const {
|
bool Song::Save() const {
|
||||||
if (d->filename_.isNull())
|
const QString filename = d->url_.toLocalFile();
|
||||||
|
if (filename.isNull())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
QMutexLocker l(&taglib_mutex_);
|
QMutexLocker l(&taglib_mutex_);
|
||||||
scoped_ptr<TagLib::FileRef> fileref(factory_->GetFileRef(d->filename_));
|
scoped_ptr<TagLib::FileRef> fileref(factory_->GetFileRef(filename));
|
||||||
|
|
||||||
if (!fileref || fileref->isNull()) // The file probably doesn't exist
|
if (!fileref || fileref->isNull()) // The file probably doesn't exist
|
||||||
return false;
|
return false;
|
||||||
@ -1214,7 +1212,7 @@ bool Song::Save() const {
|
|||||||
if (ret) {
|
if (ret) {
|
||||||
// Linux: inotify doesn't seem to notice the change to the file unless we
|
// Linux: inotify doesn't seem to notice the change to the file unless we
|
||||||
// change the timestamps as well. (this is what touch does)
|
// change the timestamps as well. (this is what touch does)
|
||||||
utimensat(0, QFile::encodeName(d->filename_).constData(), NULL, 0);
|
utimensat(0, QFile::encodeName(filename).constData(), NULL, 0);
|
||||||
}
|
}
|
||||||
#endif // Q_OS_LINUX
|
#endif // Q_OS_LINUX
|
||||||
|
|
||||||
@ -1232,7 +1230,7 @@ QFuture<bool> Song::BackgroundSave() const {
|
|||||||
|
|
||||||
bool Song::operator==(const Song& other) const {
|
bool Song::operator==(const Song& other) const {
|
||||||
// TODO: this isn't working for radios
|
// TODO: this isn't working for radios
|
||||||
return filename() == other.filename() &&
|
return url() == other.url() &&
|
||||||
beginning_nanosec() == other.beginning_nanosec();
|
beginning_nanosec() == other.beginning_nanosec();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,6 +26,7 @@
|
|||||||
#include <QSharedDataPointer>
|
#include <QSharedDataPointer>
|
||||||
#include <QSqlQuery>
|
#include <QSqlQuery>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
|
#include <QUrl>
|
||||||
|
|
||||||
#include <xiphcomment.h>
|
#include <xiphcomment.h>
|
||||||
|
|
||||||
@ -136,12 +137,12 @@ class Song {
|
|||||||
void MergeFromSimpleMetaBundle(const Engine::SimpleMetaBundle& bundle);
|
void MergeFromSimpleMetaBundle(const Engine::SimpleMetaBundle& bundle);
|
||||||
|
|
||||||
#ifdef HAVE_LIBGPOD
|
#ifdef HAVE_LIBGPOD
|
||||||
void InitFromItdb(const Itdb_Track* track);
|
void InitFromItdb(const Itdb_Track* track, const QString& prefix);
|
||||||
void ToItdb(Itdb_Track* track) const;
|
void ToItdb(Itdb_Track* track) const;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_LIBMTP
|
#ifdef HAVE_LIBMTP
|
||||||
void InitFromMTP(const LIBMTP_track_t* track);
|
void InitFromMTP(const LIBMTP_track_t* track, const QString& host);
|
||||||
void ToMTP(LIBMTP_track_t* track) const;
|
void ToMTP(LIBMTP_track_t* track) const;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -197,10 +198,7 @@ class Song {
|
|||||||
int samplerate() const { return d->samplerate_; }
|
int samplerate() const { return d->samplerate_; }
|
||||||
|
|
||||||
int directory_id() const { return d->directory_id_; }
|
int directory_id() const { return d->directory_id_; }
|
||||||
const QString& filename() const { return d->filename_; }
|
const QUrl& url() const { return d->url_; }
|
||||||
// Returns this Song's URL which may point either to a file or to another type
|
|
||||||
// of stream.
|
|
||||||
QUrl url() const;
|
|
||||||
const QString& basefilename() const { return d->basefilename_; }
|
const QString& basefilename() const { return d->basefilename_; }
|
||||||
uint mtime() const { return d->mtime_; }
|
uint mtime() const { return d->mtime_; }
|
||||||
uint ctime() const { return d->ctime_; }
|
uint ctime() const { return d->ctime_; }
|
||||||
@ -277,7 +275,7 @@ class Song {
|
|||||||
void set_cue_path(const QString& v) { d->cue_path_ = v; }
|
void set_cue_path(const QString& v) { d->cue_path_ = v; }
|
||||||
|
|
||||||
// Setters that should only be used by tests
|
// Setters that should only be used by tests
|
||||||
void set_filename(const QString& v) { d->filename_ = v; }
|
void set_url(const QUrl& v) { d->url_ = v; }
|
||||||
void set_basefilename(const QString& v) { d->basefilename_ = v; }
|
void set_basefilename(const QString& v) { d->basefilename_ = v; }
|
||||||
void set_directory_id(int v) { d->directory_id_ = v; }
|
void set_directory_id(int v) { d->directory_id_ = v; }
|
||||||
|
|
||||||
@ -342,7 +340,7 @@ class Song {
|
|||||||
int samplerate_;
|
int samplerate_;
|
||||||
|
|
||||||
int directory_id_;
|
int directory_id_;
|
||||||
QString filename_;
|
QUrl url_;
|
||||||
QString basefilename_;
|
QString basefilename_;
|
||||||
int mtime_;
|
int mtime_;
|
||||||
int ctime_;
|
int ctime_;
|
||||||
|
@ -193,7 +193,7 @@ SongLoader::Result SongLoader::LoadLocal(const QString& filename, bool block,
|
|||||||
void SongLoader::EffectiveSongsLoad() {
|
void SongLoader::EffectiveSongsLoad() {
|
||||||
for (int i = 0; i < songs_.size(); i++) {
|
for (int i = 0; i < songs_.size(); i++) {
|
||||||
Song& song = songs_[i];
|
Song& song = songs_[i];
|
||||||
QString filename = song.filename();
|
QString filename = song.url().toLocalFile();
|
||||||
QFileInfo info(filename);
|
QFileInfo info(filename);
|
||||||
|
|
||||||
LibraryQuery query;
|
LibraryQuery query;
|
||||||
@ -233,7 +233,7 @@ static bool CompareSongs(const Song& left, const Song& right) {
|
|||||||
if (left.disc() > right.disc()) return false;
|
if (left.disc() > right.disc()) return false;
|
||||||
if (left.track() < right.track()) return true;
|
if (left.track() < right.track()) return true;
|
||||||
if (left.track() > right.track()) return false;
|
if (left.track() > right.track()) return false;
|
||||||
return left.filename() < right.filename();
|
return left.url() < right.url();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SongLoader::LoadLocalDirectoryAndEmit(const QString& filename) {
|
void SongLoader::LoadLocalDirectoryAndEmit(const QString& filename) {
|
||||||
@ -256,7 +256,7 @@ void SongLoader::AddAsRawStream() {
|
|||||||
Song song;
|
Song song;
|
||||||
song.set_valid(true);
|
song.set_valid(true);
|
||||||
song.set_filetype(Song::Type_Stream);
|
song.set_filetype(Song::Type_Stream);
|
||||||
song.set_filename(url_.toString());
|
song.set_url(url_);
|
||||||
song.set_title(url_.toString());
|
song.set_title(url_.toString());
|
||||||
songs_ << song;
|
songs_ << song;
|
||||||
}
|
}
|
||||||
|
@ -233,5 +233,5 @@ void AlbumCoverLoader::SetDefaultOutputImage(const QImage &image) {
|
|||||||
|
|
||||||
quint64 AlbumCoverLoader::LoadImageAsync(const Song &song) {
|
quint64 AlbumCoverLoader::LoadImageAsync(const Song &song) {
|
||||||
return LoadImageAsync(song.art_automatic(), song.art_manual(),
|
return LoadImageAsync(song.art_automatic(), song.art_manual(),
|
||||||
song.filename(), song.image());
|
song.url().toLocalFile(), song.image());
|
||||||
}
|
}
|
||||||
|
@ -159,7 +159,7 @@ void AfcDevice::FinaliseDatabase() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool AfcDevice::DeleteFromStorage(const DeleteJob& job) {
|
bool AfcDevice::DeleteFromStorage(const DeleteJob& job) {
|
||||||
const QString path = QUrl(job.metadata_.filename()).path();
|
const QString path = job.metadata_.url().toLocalFile();
|
||||||
|
|
||||||
if (!RemoveTrackFromITunesDb(path))
|
if (!RemoveTrackFromITunesDb(path))
|
||||||
return false;
|
return false;
|
||||||
|
@ -79,7 +79,7 @@ void ConnectedDevice::InitBackendDirectory(
|
|||||||
if (dir.path != mount_point) {
|
if (dir.path != mount_point) {
|
||||||
// The directory is different, commence the munging.
|
// The directory is different, commence the munging.
|
||||||
qLog(Info) << "Changing path from" << dir.path << "to" << mount_point;
|
qLog(Info) << "Changing path from" << dir.path << "to" << mount_point;
|
||||||
backend_->ChangeDirPath(dir.id, mount_point);
|
backend_->ChangeDirPath(dir.id, dir.path, mount_point);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -402,7 +402,7 @@ void DeviceView::Organise() {
|
|||||||
SongList songs = GetSelectedSongs();
|
SongList songs = GetSelectedSongs();
|
||||||
QStringList filenames;
|
QStringList filenames;
|
||||||
foreach (const Song& song, songs) {
|
foreach (const Song& song, songs) {
|
||||||
filenames << song.filename();
|
filenames << song.url().toLocalFile();
|
||||||
}
|
}
|
||||||
|
|
||||||
organise_dialog_->SetCopy(true);
|
organise_dialog_->SetCopy(true);
|
||||||
|
@ -99,9 +99,8 @@ Itdb_Track* GPodDevice::AddTrackToITunesDb(const Song& metadata) {
|
|||||||
void GPodDevice::AddTrackToModel(Itdb_Track* track, const QString& prefix) {
|
void GPodDevice::AddTrackToModel(Itdb_Track* track, const QString& prefix) {
|
||||||
// Add it to our LibraryModel
|
// Add it to our LibraryModel
|
||||||
Song metadata_on_device;
|
Song metadata_on_device;
|
||||||
metadata_on_device.InitFromItdb(track);
|
metadata_on_device.InitFromItdb(track, prefix);
|
||||||
metadata_on_device.set_directory_id(1);
|
metadata_on_device.set_directory_id(1);
|
||||||
metadata_on_device.set_filename(prefix + metadata_on_device.filename());
|
|
||||||
songs_to_add_ << metadata_on_device;
|
songs_to_add_ << metadata_on_device;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -209,11 +208,11 @@ bool GPodDevice::RemoveTrackFromITunesDb(const QString& path, const QString& rel
|
|||||||
bool GPodDevice::DeleteFromStorage(const DeleteJob& job) {
|
bool GPodDevice::DeleteFromStorage(const DeleteJob& job) {
|
||||||
Q_ASSERT(db_);
|
Q_ASSERT(db_);
|
||||||
|
|
||||||
if (!RemoveTrackFromITunesDb(job.metadata_.filename(), url_.path()))
|
if (!RemoveTrackFromITunesDb(job.metadata_.url().toLocalFile(), url_.path()))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Remove the file
|
// Remove the file
|
||||||
if (!QFile::remove(job.metadata_.filename()))
|
if (!QFile::remove(job.metadata_.url().toLocalFile()))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Remove it from our library model
|
// Remove it from our library model
|
||||||
|
@ -66,20 +66,17 @@ void GPodLoader::LoadDatabase() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Convert all the tracks from libgpod structs into Song classes
|
// Convert all the tracks from libgpod structs into Song classes
|
||||||
|
const QString prefix = path_prefix_.isEmpty()
|
||||||
|
? QDir::fromNativeSeparators(mount_point_) : path_prefix_;
|
||||||
|
|
||||||
SongList songs;
|
SongList songs;
|
||||||
for (GList* tracks = db->tracks ; tracks != NULL ; tracks = tracks->next) {
|
for (GList* tracks = db->tracks ; tracks != NULL ; tracks = tracks->next) {
|
||||||
Itdb_Track* track = static_cast<Itdb_Track*>(tracks->data);
|
Itdb_Track* track = static_cast<Itdb_Track*>(tracks->data);
|
||||||
|
|
||||||
Song song;
|
Song song;
|
||||||
song.InitFromItdb(track);
|
song.InitFromItdb(track, prefix);
|
||||||
song.set_directory_id(1);
|
song.set_directory_id(1);
|
||||||
|
|
||||||
QString filename = (path_prefix_.isEmpty() ? mount_point_ : path_prefix_) +
|
|
||||||
song.filename();
|
|
||||||
if (path_prefix_.isEmpty())
|
|
||||||
filename = QDir::cleanPath(QDir::fromNativeSeparators(filename));
|
|
||||||
song.set_filename(filename);
|
|
||||||
|
|
||||||
if (type_ != Song::Type_Unknown)
|
if (type_ != Song::Type_Unknown)
|
||||||
song.set_filetype(type_);
|
song.set_filetype(type_);
|
||||||
songs << song;
|
songs << song;
|
||||||
|
@ -215,7 +215,7 @@ QString iMobileDeviceConnection::GetUnusedFilename(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Use the same file extension as the original file, default to mp3.
|
// Use the same file extension as the original file, default to mp3.
|
||||||
QString extension = metadata.filename().section('.', -1, -1).toLower();
|
QString extension = metadata.url().path().section('.', -1, -1).toLower();
|
||||||
if (extension.isEmpty())
|
if (extension.isEmpty())
|
||||||
extension = "mp3";
|
extension = "mp3";
|
||||||
|
|
||||||
|
@ -112,9 +112,8 @@ bool MtpDevice::CopyToStorage(const CopyJob& job) {
|
|||||||
|
|
||||||
// Add it to our LibraryModel
|
// Add it to our LibraryModel
|
||||||
Song metadata_on_device;
|
Song metadata_on_device;
|
||||||
metadata_on_device.InitFromMTP(&track);
|
metadata_on_device.InitFromMTP(&track, url_.host());
|
||||||
metadata_on_device.set_directory_id(1);
|
metadata_on_device.set_directory_id(1);
|
||||||
metadata_on_device.set_filename("mtp://" + url_.host() + "/" + metadata_on_device.filename());
|
|
||||||
songs_to_add_ << metadata_on_device;
|
songs_to_add_ << metadata_on_device;
|
||||||
|
|
||||||
// Remove the original if requested
|
// Remove the original if requested
|
||||||
@ -150,8 +149,7 @@ void MtpDevice::StartDelete() {
|
|||||||
|
|
||||||
bool MtpDevice::DeleteFromStorage(const DeleteJob& job) {
|
bool MtpDevice::DeleteFromStorage(const DeleteJob& job) {
|
||||||
// Extract the ID from the song's URL
|
// Extract the ID from the song's URL
|
||||||
QUrl url(job.metadata_.filename());
|
QString filename = job.metadata_.url().path();
|
||||||
QString filename = url.path();
|
|
||||||
filename.remove('/');
|
filename.remove('/');
|
||||||
|
|
||||||
bool ok = false;
|
bool ok = false;
|
||||||
|
@ -64,9 +64,8 @@ bool MtpLoader::TryLoad() {
|
|||||||
LIBMTP_track_t* track = tracks;
|
LIBMTP_track_t* track = tracks;
|
||||||
|
|
||||||
Song song;
|
Song song;
|
||||||
song.InitFromMTP(track);
|
song.InitFromMTP(track, url_.host());
|
||||||
song.set_directory_id(1);
|
song.set_directory_id(1);
|
||||||
song.set_filename("mtp://" + url_.host() + "/" + song.filename());
|
|
||||||
songs << song;
|
songs << song;
|
||||||
|
|
||||||
tracks = tracks->next;
|
tracks = tracks->next;
|
||||||
|
@ -89,7 +89,8 @@ void LibraryBackend::LoadDirectories() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void LibraryBackend::ChangeDirPath(int id, const QString &new_path) {
|
void LibraryBackend::ChangeDirPath(int id, const QString& old_path,
|
||||||
|
const QString& new_path) {
|
||||||
QMutexLocker l(db_->Mutex());
|
QMutexLocker l(db_->Mutex());
|
||||||
QSqlDatabase db(db_->Connect());
|
QSqlDatabase db(db_->Connect());
|
||||||
ScopedTransaction t(&db);
|
ScopedTransaction t(&db);
|
||||||
@ -101,12 +102,15 @@ void LibraryBackend::ChangeDirPath(int id, const QString &new_path) {
|
|||||||
q.exec();
|
q.exec();
|
||||||
if (db_->CheckErrors(q)) return;
|
if (db_->CheckErrors(q)) return;
|
||||||
|
|
||||||
const int path_len = new_path.length();
|
const QByteArray old_url = QUrl::fromLocalFile(old_path).toEncoded();
|
||||||
|
const QByteArray new_url = QUrl::fromLocalFile(new_path).toEncoded();
|
||||||
|
|
||||||
|
const int path_len = old_url.length();
|
||||||
|
|
||||||
// Do the subdirs table
|
// Do the subdirs table
|
||||||
q = QSqlQuery(QString("UPDATE %1 SET path=:path || substr(path, %2)"
|
q = QSqlQuery(QString("UPDATE %1 SET path=:path || substr(path, %2)"
|
||||||
" WHERE directory=:id").arg(subdirs_table_).arg(path_len), db);
|
" WHERE directory=:id").arg(subdirs_table_).arg(path_len), db);
|
||||||
q.bindValue(":path", new_path);
|
q.bindValue(":path", new_url);
|
||||||
q.bindValue(":id", id);
|
q.bindValue(":id", id);
|
||||||
q.exec();
|
q.exec();
|
||||||
if (db_->CheckErrors(q)) return;
|
if (db_->CheckErrors(q)) return;
|
||||||
@ -114,7 +118,7 @@ void LibraryBackend::ChangeDirPath(int id, const QString &new_path) {
|
|||||||
// Do the songs table
|
// Do the songs table
|
||||||
q = QSqlQuery(QString("UPDATE %1 SET filename=:path || substr(filename, %2)"
|
q = QSqlQuery(QString("UPDATE %1 SET filename=:path || substr(filename, %2)"
|
||||||
" WHERE directory=:id").arg(songs_table_).arg(path_len), db);
|
" WHERE directory=:id").arg(songs_table_).arg(path_len), db);
|
||||||
q.bindValue(":path", new_path);
|
q.bindValue(":path", new_url);
|
||||||
q.bindValue(":id", id);
|
q.bindValue(":id", id);
|
||||||
q.exec();
|
q.exec();
|
||||||
if (db_->CheckErrors(q)) return;
|
if (db_->CheckErrors(q)) return;
|
||||||
@ -564,10 +568,10 @@ SongList LibraryBackend::GetSongsById(const QStringList& ids, QSqlDatabase& db)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
Song LibraryBackend::GetSongByFilename(const QString& filename, qint64 beginning) {
|
Song LibraryBackend::GetSongByUrl(const QUrl& url, qint64 beginning) {
|
||||||
LibraryQuery query;
|
LibraryQuery query;
|
||||||
query.SetColumnSpec("%songs_table.ROWID, " + Song::kColumnSpec);
|
query.SetColumnSpec("%songs_table.ROWID, " + Song::kColumnSpec);
|
||||||
query.AddWhere("filename", filename);
|
query.AddWhere("filename", url.toEncoded());
|
||||||
query.AddWhere("beginning", beginning);
|
query.AddWhere("beginning", beginning);
|
||||||
|
|
||||||
Song song;
|
Song song;
|
||||||
@ -577,10 +581,10 @@ Song LibraryBackend::GetSongByFilename(const QString& filename, qint64 beginning
|
|||||||
return song;
|
return song;
|
||||||
}
|
}
|
||||||
|
|
||||||
SongList LibraryBackend::GetSongsByFilename(const QString& filename) {
|
SongList LibraryBackend::GetSongsByUrl(const QUrl& url) {
|
||||||
LibraryQuery query;
|
LibraryQuery query;
|
||||||
query.SetColumnSpec("%songs_table.ROWID, " + Song::kColumnSpec);
|
query.SetColumnSpec("%songs_table.ROWID, " + Song::kColumnSpec);
|
||||||
query.AddWhere("filename", filename);
|
query.AddWhere("filename", url.toEncoded());
|
||||||
|
|
||||||
SongList songlist;
|
SongList songlist;
|
||||||
if (ExecQuery(&query)) {
|
if (ExecQuery(&query)) {
|
||||||
@ -754,7 +758,7 @@ LibraryBackend::AlbumList LibraryBackend::GetAlbums(const QString& artist,
|
|||||||
info.album_name = query.Value(0).toString();
|
info.album_name = query.Value(0).toString();
|
||||||
info.art_automatic = query.Value(4).toString();
|
info.art_automatic = query.Value(4).toString();
|
||||||
info.art_manual = query.Value(5).toString();
|
info.art_manual = query.Value(5).toString();
|
||||||
info.first_filename = query.Value(6).toString();
|
info.first_url = QUrl::fromEncoded(query.Value(6).toByteArray());
|
||||||
|
|
||||||
if (info.artist == last_artist && info.album_name == last_album)
|
if (info.artist == last_artist && info.album_name == last_album)
|
||||||
continue;
|
continue;
|
||||||
@ -784,7 +788,7 @@ LibraryBackend::Album LibraryBackend::GetAlbumArt(const QString& artist, const Q
|
|||||||
if (query.Next()) {
|
if (query.Next()) {
|
||||||
ret.art_automatic = query.Value(0).toString();
|
ret.art_automatic = query.Value(0).toString();
|
||||||
ret.art_manual = query.Value(1).toString();
|
ret.art_manual = query.Value(1).toString();
|
||||||
ret.first_filename = query.Value(2).toString();
|
ret.first_url = QUrl::fromEncoded(query.Value(2).toByteArray());
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -40,17 +40,17 @@ class LibraryBackendInterface : public QObject {
|
|||||||
Album() {}
|
Album() {}
|
||||||
Album(const QString& _artist, const QString& _album_name,
|
Album(const QString& _artist, const QString& _album_name,
|
||||||
const QString& _art_automatic, const QString& _art_manual,
|
const QString& _art_automatic, const QString& _art_manual,
|
||||||
const QString& _first_filename)
|
const QUrl& _first_url)
|
||||||
: artist(_artist), album_name(_album_name),
|
: artist(_artist), album_name(_album_name),
|
||||||
art_automatic(_art_automatic), art_manual(_art_manual),
|
art_automatic(_art_automatic), art_manual(_art_manual),
|
||||||
first_filename(_first_filename) {}
|
first_url(_first_url) {}
|
||||||
|
|
||||||
QString artist;
|
QString artist;
|
||||||
QString album_name;
|
QString album_name;
|
||||||
|
|
||||||
QString art_automatic;
|
QString art_automatic;
|
||||||
QString art_manual;
|
QString art_manual;
|
||||||
QString first_filename;
|
QUrl first_url;
|
||||||
};
|
};
|
||||||
typedef QList<Album> AlbumList;
|
typedef QList<Album> AlbumList;
|
||||||
|
|
||||||
@ -63,7 +63,7 @@ class LibraryBackendInterface : public QObject {
|
|||||||
virtual SongList FindSongsInDirectory(int id) = 0;
|
virtual SongList FindSongsInDirectory(int id) = 0;
|
||||||
virtual SubdirectoryList SubdirsInDirectory(int id) = 0;
|
virtual SubdirectoryList SubdirsInDirectory(int id) = 0;
|
||||||
virtual DirectoryList GetAllDirectories() = 0;
|
virtual DirectoryList GetAllDirectories() = 0;
|
||||||
virtual void ChangeDirPath(int id, const QString& new_path) = 0;
|
virtual void ChangeDirPath(int id, const QString& old_path, const QString& new_path) = 0;
|
||||||
|
|
||||||
virtual QStringList GetAllArtists(const QueryOptions& opt = QueryOptions()) = 0;
|
virtual QStringList GetAllArtists(const QueryOptions& opt = QueryOptions()) = 0;
|
||||||
virtual QStringList GetAllArtistsWithAlbums(const QueryOptions& opt = QueryOptions()) = 0;
|
virtual QStringList GetAllArtistsWithAlbums(const QueryOptions& opt = QueryOptions()) = 0;
|
||||||
@ -84,11 +84,11 @@ class LibraryBackendInterface : public QObject {
|
|||||||
|
|
||||||
// Returns all sections of a song with the given filename. If there's just one section
|
// Returns all sections of a song with the given filename. If there's just one section
|
||||||
// the resulting list will have it's size equal to 1.
|
// the resulting list will have it's size equal to 1.
|
||||||
virtual SongList GetSongsByFilename(const QString& filename) = 0;
|
virtual SongList GetSongsByUrl(const QUrl& url) = 0;
|
||||||
// Returns a section of a song with the given filename and beginning. If the section
|
// Returns a section of a song with the given filename and beginning. If the section
|
||||||
// is not present in library, returns invalid song.
|
// is not present in library, returns invalid song.
|
||||||
// Using default beginning value is suitable when searching for single-section songs.
|
// Using default beginning value is suitable when searching for single-section songs.
|
||||||
virtual Song GetSongByFilename(const QString& filename, qint64 beginning = 0) = 0;
|
virtual Song GetSongByUrl(const QUrl& url, qint64 beginning = 0) = 0;
|
||||||
|
|
||||||
virtual void AddDirectory(const QString& path) = 0;
|
virtual void AddDirectory(const QString& path) = 0;
|
||||||
virtual void RemoveDirectory(const Directory& dir) = 0;
|
virtual void RemoveDirectory(const Directory& dir) = 0;
|
||||||
@ -120,7 +120,7 @@ class LibraryBackend : public LibraryBackendInterface {
|
|||||||
SongList FindSongsInDirectory(int id);
|
SongList FindSongsInDirectory(int id);
|
||||||
SubdirectoryList SubdirsInDirectory(int id);
|
SubdirectoryList SubdirsInDirectory(int id);
|
||||||
DirectoryList GetAllDirectories();
|
DirectoryList GetAllDirectories();
|
||||||
void ChangeDirPath(int id, const QString& new_path);
|
void ChangeDirPath(int id, const QString& old_path, const QString& new_path);
|
||||||
|
|
||||||
QStringList GetAll(const QString& column, const QueryOptions& opt = QueryOptions());
|
QStringList GetAll(const QString& column, const QueryOptions& opt = QueryOptions());
|
||||||
QStringList GetAllArtists(const QueryOptions& opt = QueryOptions());
|
QStringList GetAllArtists(const QueryOptions& opt = QueryOptions());
|
||||||
@ -143,8 +143,8 @@ class LibraryBackend : public LibraryBackendInterface {
|
|||||||
SongList GetSongsByForeignId(const QStringList& ids, const QString& table,
|
SongList GetSongsByForeignId(const QStringList& ids, const QString& table,
|
||||||
const QString& column);
|
const QString& column);
|
||||||
|
|
||||||
SongList GetSongsByFilename(const QString& filename);
|
SongList GetSongsByUrl(const QUrl& url);
|
||||||
Song GetSongByFilename(const QString& filename, qint64 beginning = 0);
|
Song GetSongByUrl(const QUrl& url, qint64 beginning = 0);
|
||||||
|
|
||||||
void AddDirectory(const QString& path);
|
void AddDirectory(const QString& path);
|
||||||
void RemoveDirectory(const Directory& dir);
|
void RemoveDirectory(const Directory& dir);
|
||||||
|
@ -392,7 +392,7 @@ QVariant LibraryModel::AlbumIcon(const QModelIndex& index, int role) const {
|
|||||||
if (!songs.isEmpty()) {
|
if (!songs.isEmpty()) {
|
||||||
const Song& s = songs.first();
|
const Song& s = songs.first();
|
||||||
QPixmap pixmap = AlbumCoverLoader::TryLoadPixmap(
|
QPixmap pixmap = AlbumCoverLoader::TryLoadPixmap(
|
||||||
s.art_automatic(), s.art_manual(), s.filename());
|
s.art_automatic(), s.art_manual(), s.url().toLocalFile());
|
||||||
|
|
||||||
if (!pixmap.isNull()) {
|
if (!pixmap.isNull()) {
|
||||||
QImage image = pixmap.toImage().scaled(
|
QImage image = pixmap.toImage().scaled(
|
||||||
@ -931,7 +931,7 @@ QString LibraryModel::SortTextForYear(int year) const {
|
|||||||
QString LibraryModel::SortTextForSong(const Song& song) const {
|
QString LibraryModel::SortTextForSong(const Song& song) const {
|
||||||
QString ret = QString::number(qMax(0, song.disc()) * 1000 + qMax(0, song.track()));
|
QString ret = QString::number(qMax(0, song.disc()) * 1000 + qMax(0, song.track()));
|
||||||
ret.prepend(QString("0").repeated(6 - ret.length()));
|
ret.prepend(QString("0").repeated(6 - ret.length()));
|
||||||
ret.append(song.filename());
|
ret.append(song.url().toString());
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1012,7 +1012,7 @@ void LibraryModel::GetChildSongs(LibraryItem* item, QList<QUrl>* urls,
|
|||||||
}
|
}
|
||||||
|
|
||||||
case LibraryItem::Type_Song:
|
case LibraryItem::Type_Song:
|
||||||
urls->append(QUrl::fromLocalFile(item->metadata.filename()));
|
urls->append(item->metadata.url());
|
||||||
if (!song_ids->contains(item->metadata.id())) {
|
if (!song_ids->contains(item->metadata.id())) {
|
||||||
songs->append(item->metadata);
|
songs->append(item->metadata);
|
||||||
song_ids->insert(item->metadata.id());
|
song_ids->insert(item->metadata.id());
|
||||||
|
@ -32,11 +32,11 @@ LibraryPlaylistItem::LibraryPlaylistItem(const Song& song)
|
|||||||
|
|
||||||
|
|
||||||
QUrl LibraryPlaylistItem::Url() const {
|
QUrl LibraryPlaylistItem::Url() const {
|
||||||
return QUrl::fromLocalFile(song_.filename());
|
return song_.url();
|
||||||
}
|
}
|
||||||
|
|
||||||
void LibraryPlaylistItem::Reload() {
|
void LibraryPlaylistItem::Reload() {
|
||||||
song_.InitFromFile(song_.filename(), song_.directory_id());
|
song_.InitFromFile(song_.url().toLocalFile(), song_.directory_id());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool LibraryPlaylistItem::InitFromQuery(const SqlRow& query) {
|
bool LibraryPlaylistItem::InitFromQuery(const SqlRow& query) {
|
||||||
|
@ -550,7 +550,7 @@ void LibraryView::EditSmartPlaylistFinished() {
|
|||||||
void LibraryView::ShowInBrowser() {
|
void LibraryView::ShowInBrowser() {
|
||||||
QStringList filenames;
|
QStringList filenames;
|
||||||
foreach (const Song& song, GetSelectedSongs()) {
|
foreach (const Song& song, GetSelectedSongs()) {
|
||||||
filenames << song.filename();
|
filenames << song.url().toLocalFile();
|
||||||
}
|
}
|
||||||
|
|
||||||
Utilities::OpenInFileBrowser(filenames);
|
Utilities::OpenInFileBrowser(filenames);
|
||||||
|
@ -132,7 +132,7 @@ SongList LibraryWatcher::ScanTransaction::FindSongsInSubdirectory(const QString
|
|||||||
// TODO: Make this faster
|
// TODO: Make this faster
|
||||||
SongList ret;
|
SongList ret;
|
||||||
foreach (const Song& song, cached_songs_) {
|
foreach (const Song& song, cached_songs_) {
|
||||||
if (song.filename().section('/', 0, -2) == path)
|
if (song.url().toLocalFile().section('/', 0, -2) == path)
|
||||||
ret << song;
|
ret << song;
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
@ -363,8 +363,8 @@ void LibraryWatcher::ScanSubdirectory(
|
|||||||
|
|
||||||
// Look for deleted songs
|
// Look for deleted songs
|
||||||
foreach (const Song& song, songs_in_db) {
|
foreach (const Song& song, songs_in_db) {
|
||||||
if (!files_on_disk.contains(song.filename())) {
|
if (!files_on_disk.contains(song.url().toLocalFile())) {
|
||||||
qLog(Debug) << "Song deleted from disk:" << song.filename();
|
qLog(Debug) << "Song deleted from disk:" << song.url().toLocalFile();
|
||||||
t->deleted_songs << song;
|
t->deleted_songs << song;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -397,7 +397,7 @@ void LibraryWatcher::UpdateCueAssociatedSongs(const QString& file, const QString
|
|||||||
QFile cue(matching_cue);
|
QFile cue(matching_cue);
|
||||||
cue.open(QIODevice::ReadOnly);
|
cue.open(QIODevice::ReadOnly);
|
||||||
|
|
||||||
SongList old_sections = backend_->GetSongsByFilename(file);
|
SongList old_sections = backend_->GetSongsByUrl(QUrl::fromLocalFile(file));
|
||||||
|
|
||||||
QHash<quint64, Song> sections_map;
|
QHash<quint64, Song> sections_map;
|
||||||
foreach(const Song& song, old_sections) {
|
foreach(const Song& song, old_sections) {
|
||||||
@ -437,7 +437,7 @@ void LibraryWatcher::UpdateNonCueAssociatedSong(const QString& file, const Song&
|
|||||||
// 'raw' (cueless) song and we just remove the rest of the sections
|
// 'raw' (cueless) song and we just remove the rest of the sections
|
||||||
// from the library
|
// from the library
|
||||||
if(cue_deleted) {
|
if(cue_deleted) {
|
||||||
foreach(const Song& song, backend_->GetSongsByFilename(file)) {
|
foreach(const Song& song, backend_->GetSongsByUrl(QUrl::fromLocalFile(file))) {
|
||||||
if(!song.IsMetadataEqual(matching_song)) {
|
if(!song.IsMetadataEqual(matching_song)) {
|
||||||
t->deleted_songs << song;
|
t->deleted_songs << song;
|
||||||
}
|
}
|
||||||
@ -470,7 +470,7 @@ SongList LibraryWatcher::ScanNewFile(const QString& file, const QString& path,
|
|||||||
// media files. Playlist parser for CUEs considers every entry in sheet
|
// media files. Playlist parser for CUEs considers every entry in sheet
|
||||||
// valid and we don't want invalid media getting into library!
|
// valid and we don't want invalid media getting into library!
|
||||||
foreach(const Song& cue_song, cue_parser_->Load(&cue, matching_cue, path)) {
|
foreach(const Song& cue_song, cue_parser_->Load(&cue, matching_cue, path)) {
|
||||||
if(cue_song.filename() == file && cue_song.HasProperMediaFile()) {
|
if(cue_song.url().toLocalFile() == file && cue_song.HasProperMediaFile()) {
|
||||||
song_list << cue_song;
|
song_list << cue_song;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -553,7 +553,7 @@ void LibraryWatcher::RemoveDirectory(const Directory& dir) {
|
|||||||
bool LibraryWatcher::FindSongByPath(const SongList& list, const QString& path, Song* out) {
|
bool LibraryWatcher::FindSongByPath(const SongList& list, const QString& path, Song* out) {
|
||||||
// TODO: Make this faster
|
// TODO: Make this faster
|
||||||
foreach (const Song& song, list) {
|
foreach (const Song& song, list) {
|
||||||
if (song.filename() == path) {
|
if (song.url().toLocalFile() == path) {
|
||||||
*out = song;
|
*out = song;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -35,7 +35,7 @@ TagFetcher::TagFetcher(QObject* parent)
|
|||||||
}
|
}
|
||||||
|
|
||||||
QString TagFetcher::GetFingerprint(const Song& song) {
|
QString TagFetcher::GetFingerprint(const Song& song) {
|
||||||
return Fingerprinter(song.filename()).CreateFingerprint();
|
return Fingerprinter(song.url().toLocalFile()).CreateFingerprint();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TagFetcher::StartFetch(const SongList& songs) {
|
void TagFetcher::StartFetch(const SongList& songs) {
|
||||||
|
@ -274,7 +274,7 @@ QVariant Playlist::data(const QModelIndex& index, int role) const {
|
|||||||
case Column_BPM: return song.bpm();
|
case Column_BPM: return song.bpm();
|
||||||
case Column_Bitrate: return song.bitrate();
|
case Column_Bitrate: return song.bitrate();
|
||||||
case Column_Samplerate: return song.samplerate();
|
case Column_Samplerate: return song.samplerate();
|
||||||
case Column_Filename: return song.filename();
|
case Column_Filename: return song.url();
|
||||||
case Column_BaseFilename: return song.basefilename();
|
case Column_BaseFilename: return song.basefilename();
|
||||||
case Column_Filesize: return song.filesize();
|
case Column_Filesize: return song.filesize();
|
||||||
case Column_Filetype: return song.filetype();
|
case Column_Filetype: return song.filetype();
|
||||||
@ -958,7 +958,7 @@ void Playlist::UpdateItems(const SongList& songs) {
|
|||||||
// Update current items list
|
// Update current items list
|
||||||
for (int i=0; i<items_.size(); i++) {
|
for (int i=0; i<items_.size(); i++) {
|
||||||
PlaylistItemPtr item = items_[i];
|
PlaylistItemPtr item = items_[i];
|
||||||
if (item->Metadata().filename() == song.filename()) {
|
if (item->Metadata().url() == song.url()) {
|
||||||
PlaylistItemPtr new_item;
|
PlaylistItemPtr new_item;
|
||||||
if (song.id() == -1) {
|
if (song.id() == -1) {
|
||||||
new_item = PlaylistItemPtr(new SongPlaylistItem(song));
|
new_item = PlaylistItemPtr(new SongPlaylistItem(song));
|
||||||
@ -1041,7 +1041,7 @@ bool Playlist::CompareItems(int column, Qt::SortOrder order,
|
|||||||
case Column_BPM: cmp(bpm);
|
case Column_BPM: cmp(bpm);
|
||||||
case Column_Bitrate: cmp(bitrate);
|
case Column_Bitrate: cmp(bitrate);
|
||||||
case Column_Samplerate: cmp(samplerate);
|
case Column_Samplerate: cmp(samplerate);
|
||||||
case Column_Filename: cmp(filename);
|
case Column_Filename: cmp(url);
|
||||||
case Column_BaseFilename: cmp(basefilename);
|
case Column_BaseFilename: cmp(basefilename);
|
||||||
case Column_Filesize: cmp(filesize);
|
case Column_Filesize: cmp(filesize);
|
||||||
case Column_Filetype: cmp(filetype);
|
case Column_Filetype: cmp(filetype);
|
||||||
@ -1186,7 +1186,7 @@ void Playlist::ItemsLoaded() {
|
|||||||
while (it.hasNext()) {
|
while (it.hasNext()) {
|
||||||
PlaylistItemPtr item = it.next();
|
PlaylistItemPtr item = it.next();
|
||||||
|
|
||||||
if (item->IsLocalLibraryItem() && item->Metadata().filename().isEmpty()) {
|
if (item->IsLocalLibraryItem() && item->Metadata().url().isEmpty()) {
|
||||||
it.remove();
|
it.remove();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1684,7 +1684,7 @@ void Playlist::InvalidateDeletedSongs() {
|
|||||||
Song song = item->Metadata();
|
Song song = item->Metadata();
|
||||||
|
|
||||||
if(!song.is_stream()) {
|
if(!song.is_stream()) {
|
||||||
bool exists = QFile::exists(song.filename());
|
bool exists = QFile::exists(song.url().toLocalFile());
|
||||||
|
|
||||||
if(!exists && !item->HasForegroundColor(kInvalidSongPriority)) {
|
if(!exists && !item->HasForegroundColor(kInvalidSongPriority)) {
|
||||||
// gray out the song if it's not there
|
// gray out the song if it's not there
|
||||||
@ -1707,7 +1707,7 @@ void Playlist::RemoveDeletedSongs() {
|
|||||||
PlaylistItemPtr item = items_[row];
|
PlaylistItemPtr item = items_[row];
|
||||||
Song song = item->Metadata();
|
Song song = item->Metadata();
|
||||||
|
|
||||||
if(!song.is_stream() && !QFile::exists(song.filename())) {
|
if(!song.is_stream() && !QFile::exists(song.url().toLocalFile())) {
|
||||||
rows_to_remove.append(row);
|
rows_to_remove.append(row);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1723,8 +1723,8 @@ bool Playlist::ApplyValidityOnCurrentSong(const QUrl& url, bool valid) {
|
|||||||
|
|
||||||
// if validity has changed, reload the item
|
// if validity has changed, reload the item
|
||||||
if(!current_song.is_stream() &&
|
if(!current_song.is_stream() &&
|
||||||
current_song.filename() == url.toLocalFile() &&
|
current_song.url() == url &&
|
||||||
current_song.is_valid() != QFile::exists(current_song.filename())) {
|
current_song.is_valid() != QFile::exists(current_song.url().toLocalFile())) {
|
||||||
ReloadItems(QList<int>() << current_row());
|
ReloadItems(QList<int>() << current_row());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -192,7 +192,7 @@ PlaylistItemPtr PlaylistBackend::RestoreCueData(PlaylistItemPtr item, boost::sha
|
|||||||
}
|
}
|
||||||
|
|
||||||
foreach(const Song& from_list, song_list) {
|
foreach(const Song& from_list, song_list) {
|
||||||
if(from_list.filename() == song.filename() &&
|
if(from_list.url() == song.url() &&
|
||||||
from_list.beginning_nanosec() == song.beginning_nanosec()) {
|
from_list.beginning_nanosec() == song.beginning_nanosec()) {
|
||||||
// we found a matching section; replace the input
|
// we found a matching section; replace the input
|
||||||
// item with a new one containing CUE metadata
|
// item with a new one containing CUE metadata
|
||||||
|
@ -50,7 +50,7 @@ void InsertItems::undo() {
|
|||||||
bool InsertItems::UpdateItem(const PlaylistItemPtr& updated_item) {
|
bool InsertItems::UpdateItem(const PlaylistItemPtr& updated_item) {
|
||||||
for (int i=0; i<items_.size(); i++) {
|
for (int i=0; i<items_.size(); i++) {
|
||||||
PlaylistItemPtr item = items_[i];
|
PlaylistItemPtr item = items_[i];
|
||||||
if (item->Metadata().filename() == updated_item->Metadata().filename()) {
|
if (item->Metadata().url() == updated_item->Metadata().url()) {
|
||||||
items_[i] = updated_item;
|
items_[i] = updated_item;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -52,7 +52,7 @@ QUrl SongPlaylistItem::Url() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void SongPlaylistItem::Reload() {
|
void SongPlaylistItem::Reload() {
|
||||||
QString old_filename = song_.filename();
|
QString old_filename = song_.url().toLocalFile();
|
||||||
int old_directory_id = song_.directory_id();
|
int old_directory_id = song_.directory_id();
|
||||||
|
|
||||||
song_ = Song();
|
song_ = Song();
|
||||||
|
@ -40,16 +40,8 @@ SongList AsxIniParser::Load(QIODevice *device, const QString& playlist_path, con
|
|||||||
QString value = line.mid(equals + 1);
|
QString value = line.mid(equals + 1);
|
||||||
|
|
||||||
if (key.startsWith("ref")) {
|
if (key.startsWith("ref")) {
|
||||||
Song song;
|
Song song = LoadSong(value, 0, dir);
|
||||||
if (!ParseTrackLocation(value, dir, &song))
|
if (song.is_valid()) {
|
||||||
qLog(Warning) << "Failed to parse location: " << value;
|
|
||||||
|
|
||||||
// Load the song from the library if it's there.
|
|
||||||
Song library_song = LoadLibrarySong(song.filename());
|
|
||||||
if (library_song.is_valid()) {
|
|
||||||
ret << library_song;
|
|
||||||
} else {
|
|
||||||
song.InitFromFile(song.filename(), -1);
|
|
||||||
ret << song;
|
ret << song;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -64,7 +56,7 @@ void AsxIniParser::Save(const SongList &songs, QIODevice *device, const QDir &di
|
|||||||
|
|
||||||
int n = 1;
|
int n = 1;
|
||||||
foreach (const Song& song, songs) {
|
foreach (const Song& song, songs) {
|
||||||
s << "Ref" << n << "=" << MakeRelativeTo(song.filename(), dir) << endl;
|
s << "Ref" << n << "=" << URLOrRelativeFilename(song.url(), dir) << endl;
|
||||||
++n;
|
++n;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -31,7 +31,8 @@ ASXParser::ASXParser(LibraryBackendInterface* library, QObject* parent)
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
SongList ASXParser::Load(QIODevice *device, const QString& playlist_path, const QDir&) const {
|
SongList ASXParser::Load(QIODevice *device, const QString& playlist_path,
|
||||||
|
const QDir& dir) const {
|
||||||
// We have to load everything first so we can munge the "XML".
|
// We have to load everything first so we can munge the "XML".
|
||||||
QByteArray data = device->readAll();
|
QByteArray data = device->readAll();
|
||||||
|
|
||||||
@ -70,7 +71,7 @@ SongList ASXParser::Load(QIODevice *device, const QString& playlist_path, const
|
|||||||
}
|
}
|
||||||
|
|
||||||
while (!reader.atEnd() && ParseUntilElement(&reader, "entry")) {
|
while (!reader.atEnd() && ParseUntilElement(&reader, "entry")) {
|
||||||
Song song = ParseTrack(&reader);
|
Song song = ParseTrack(&reader, dir);
|
||||||
if (song.is_valid()) {
|
if (song.is_valid()) {
|
||||||
ret << song;
|
ret << song;
|
||||||
}
|
}
|
||||||
@ -79,9 +80,9 @@ SongList ASXParser::Load(QIODevice *device, const QString& playlist_path, const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Song ASXParser::ParseTrack(QXmlStreamReader* reader) const {
|
Song ASXParser::ParseTrack(QXmlStreamReader* reader, const QDir& dir) const {
|
||||||
Song song;
|
QString title, artist, album, ref;
|
||||||
QString title, artist, album;
|
|
||||||
while (!reader->atEnd()) {
|
while (!reader->atEnd()) {
|
||||||
QXmlStreamReader::TokenType type = reader->readNext();
|
QXmlStreamReader::TokenType type = reader->readNext();
|
||||||
|
|
||||||
@ -89,24 +90,7 @@ Song ASXParser::ParseTrack(QXmlStreamReader* reader) const {
|
|||||||
case QXmlStreamReader::StartElement: {
|
case QXmlStreamReader::StartElement: {
|
||||||
QStringRef name = reader->name();
|
QStringRef name = reader->name();
|
||||||
if (name == "ref") {
|
if (name == "ref") {
|
||||||
QUrl url(reader->attributes().value("href").toString());
|
ref = reader->attributes().value("href").toString();
|
||||||
if (url.scheme() == "file") {
|
|
||||||
QString filename = url.toLocalFile();
|
|
||||||
if (!QFile::exists(filename)) {
|
|
||||||
return Song();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Load the song from the library if it's there.
|
|
||||||
Song library_song = LoadLibrarySong(filename);
|
|
||||||
if (library_song.is_valid())
|
|
||||||
return library_song;
|
|
||||||
|
|
||||||
song.InitFromFile(filename, -1);
|
|
||||||
return song;
|
|
||||||
} else {
|
|
||||||
song.set_filename(url.toString());
|
|
||||||
song.set_filetype(Song::Type_Stream);
|
|
||||||
}
|
|
||||||
} else if (name == "title") {
|
} else if (name == "title") {
|
||||||
title = reader->readElementText();
|
title = reader->readElementText();
|
||||||
} else if (name == "author") {
|
} else if (name == "author") {
|
||||||
@ -116,8 +100,7 @@ Song ASXParser::ParseTrack(QXmlStreamReader* reader) const {
|
|||||||
}
|
}
|
||||||
case QXmlStreamReader::EndElement: {
|
case QXmlStreamReader::EndElement: {
|
||||||
if (reader->name() == "entry") {
|
if (reader->name() == "entry") {
|
||||||
song.Init(title, artist, album, -1);
|
goto return_song;
|
||||||
return song;
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -125,8 +108,14 @@ Song ASXParser::ParseTrack(QXmlStreamReader* reader) const {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// At least make an effort if we never find a </entry>.
|
|
||||||
song.Init(title, artist, album, -1);
|
return_song:
|
||||||
|
Song song = LoadSong(ref, 0, dir);
|
||||||
|
|
||||||
|
// Override metadata with what was in the playlist
|
||||||
|
song.set_title(title);
|
||||||
|
song.set_artist(artist);
|
||||||
|
song.set_album(album);
|
||||||
return song;
|
return song;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -142,7 +131,7 @@ void ASXParser::Save(const SongList& songs, QIODevice* device, const QDir&) cons
|
|||||||
writer.writeTextElement("title", song.title());
|
writer.writeTextElement("title", song.title());
|
||||||
{
|
{
|
||||||
StreamElement ref("ref", &writer);
|
StreamElement ref("ref", &writer);
|
||||||
writer.writeAttribute("href", MakeUrl(song.filename()));
|
writer.writeAttribute("href", song.url().toString());
|
||||||
}
|
}
|
||||||
if (!song.artist().isEmpty()) {
|
if (!song.artist().isEmpty()) {
|
||||||
writer.writeTextElement("author", song.artist());
|
writer.writeTextElement("author", song.artist());
|
||||||
|
@ -31,11 +31,12 @@ class ASXParser : public XMLParser {
|
|||||||
|
|
||||||
bool TryMagic(const QByteArray &data) const;
|
bool TryMagic(const QByteArray &data) const;
|
||||||
|
|
||||||
SongList Load(QIODevice *device, const QString& playlist_path = "", const QDir &dir = QDir()) const;
|
SongList Load(QIODevice *device, const QString& playlist_path = "",
|
||||||
|
const QDir& dir = QDir()) const;
|
||||||
void Save(const SongList &songs, QIODevice *device, const QDir &dir = QDir()) const;
|
void Save(const SongList &songs, QIODevice *device, const QDir &dir = QDir()) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Song ParseTrack(QXmlStreamReader* reader) const;
|
Song ParseTrack(QXmlStreamReader* reader, const QDir& dir) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -207,15 +207,7 @@ SongList CueParser::Load(QIODevice* device, const QString& playlist_path, const
|
|||||||
for(int i = 0; i < entries.length(); i++) {
|
for(int i = 0; i < entries.length(); i++) {
|
||||||
CueEntry entry = entries.at(i);
|
CueEntry entry = entries.at(i);
|
||||||
|
|
||||||
Song current;
|
Song song = LoadSong(entry.file, IndexToMarker(entry.index), dir);
|
||||||
if (!ParseTrackLocation(entry.file, dir, ¤t)) {
|
|
||||||
qLog(Warning) << "failed to parse location in .cue file from " << dir_path;
|
|
||||||
} else {
|
|
||||||
// look for the section in library
|
|
||||||
Song song = LoadLibrarySong(current.filename(), IndexToMarker(entry.index));
|
|
||||||
if (!song.is_valid()) {
|
|
||||||
song.InitFromFile(current.filename(), -1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// cue song has mtime equal to qMax(media_file_mtime, cue_sheet_mtime)
|
// cue song has mtime equal to qMax(media_file_mtime, cue_sheet_mtime)
|
||||||
if(cue_mtime.isValid()) {
|
if(cue_mtime.isValid()) {
|
||||||
@ -247,7 +239,6 @@ SongList CueParser::Load(QIODevice* device, const QString& playlist_path, const
|
|||||||
|
|
||||||
ret << song;
|
ret << song;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -56,29 +56,13 @@ SongList M3UParser::Load(QIODevice* device, const QString& playlist_path, const
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (!line.isEmpty()) {
|
} else if (!line.isEmpty()) {
|
||||||
Song song;
|
Song song = LoadSong(line, 0, dir);
|
||||||
|
song.set_title(current_metadata.title);
|
||||||
// Track location.
|
song.set_artist(current_metadata.artist);
|
||||||
if (!ParseTrackLocation(line, dir, &song)) {
|
song.set_length_nanosec(current_metadata.length);
|
||||||
qLog(Warning) << "Failed to parse location: " << line;
|
|
||||||
} else {
|
|
||||||
// Load the song from the library if it's there.
|
|
||||||
Song library_song = LoadLibrarySong(song.filename());
|
|
||||||
if (library_song.is_valid()) {
|
|
||||||
ret << library_song;
|
|
||||||
} else {
|
|
||||||
song.Init(current_metadata.title,
|
|
||||||
current_metadata.artist,
|
|
||||||
QString(), // Unknown album.
|
|
||||||
current_metadata.length);
|
|
||||||
song.InitFromFile(song.filename(), -1);
|
|
||||||
ret << song;
|
ret << song;
|
||||||
}
|
|
||||||
|
|
||||||
current_metadata.artist.clear();
|
current_metadata = Metadata();
|
||||||
current_metadata.title.clear();
|
|
||||||
current_metadata.length = -1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (buffer.atEnd()) {
|
if (buffer.atEnd()) {
|
||||||
break;
|
break;
|
||||||
@ -115,14 +99,14 @@ bool M3UParser::ParseMetadata(const QString& line, M3UParser::Metadata* metadata
|
|||||||
void M3UParser::Save(const SongList &songs, QIODevice *device, const QDir &dir) const {
|
void M3UParser::Save(const SongList &songs, QIODevice *device, const QDir &dir) const {
|
||||||
device->write("#EXTM3U\n");
|
device->write("#EXTM3U\n");
|
||||||
foreach (const Song& song, songs) {
|
foreach (const Song& song, songs) {
|
||||||
if (song.filename().isEmpty()) {
|
if (song.url().isEmpty()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
QString meta = QString("#EXTINF:%1,%2 - %3\n")
|
QString meta = QString("#EXTINF:%1,%2 - %3\n")
|
||||||
.arg(song.length_nanosec() / kNsecPerSec)
|
.arg(song.length_nanosec() / kNsecPerSec)
|
||||||
.arg(song.artist()).arg(song.title());
|
.arg(song.artist()).arg(song.title());
|
||||||
device->write(meta.toUtf8());
|
device->write(meta.toUtf8());
|
||||||
device->write(MakeRelativeTo(song.filename(), dir).toUtf8());
|
device->write(URLOrRelativeFilename(song.url(), dir).toUtf8());
|
||||||
device->write("\n");
|
device->write("\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -28,67 +28,72 @@ ParserBase::ParserBase(LibraryBackendInterface* library, QObject *parent)
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ParserBase::ParseTrackLocation(const QString& filename_or_url,
|
void ParserBase::LoadSong(const QString& filename_or_url, qint64 beginning,
|
||||||
const QDir& dir, Song* song) const {
|
const QDir& dir, Song* song) const {
|
||||||
|
if (filename_or_url.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString filename = filename_or_url;
|
||||||
|
|
||||||
if (filename_or_url.contains(QRegExp("^[a-z]+://"))) {
|
if (filename_or_url.contains(QRegExp("^[a-z]+://"))) {
|
||||||
// Looks like a url.
|
QUrl url(filename_or_url);
|
||||||
QUrl temp(filename_or_url);
|
if (url.scheme() == "file") {
|
||||||
if (temp.isValid()) {
|
filename = url.toLocalFile();
|
||||||
song->set_filename(temp.toString());
|
} else {
|
||||||
|
song->set_url(QUrl(filename_or_url));
|
||||||
song->set_filetype(Song::Type_Stream);
|
song->set_filetype(Song::Type_Stream);
|
||||||
song->set_valid(true);
|
song->set_valid(true);
|
||||||
return true;
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert native separators for Windows paths
|
||||||
|
filename = QDir::fromNativeSeparators(filename);
|
||||||
|
|
||||||
|
// Make the path absolute
|
||||||
|
if (!QDir::isAbsolutePath(filename)) {
|
||||||
|
filename = dir.absoluteFilePath(filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use the canonical path
|
||||||
|
if (QFile::exists(filename)) {
|
||||||
|
filename = QFileInfo(filename).canonicalFilePath();
|
||||||
|
}
|
||||||
|
|
||||||
|
const QUrl url = QUrl::fromLocalFile(filename);
|
||||||
|
|
||||||
|
// Search in the library
|
||||||
|
Song library_song;
|
||||||
|
if (library_) {
|
||||||
|
library_song = library_->GetSongByUrl(url, beginning);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If it was found in the library then use it, otherwise load metadata from
|
||||||
|
// disk.
|
||||||
|
if (library_song.is_valid()) {
|
||||||
|
*song = library_song;
|
||||||
} else {
|
} else {
|
||||||
return false;
|
song->InitFromFile(filename, -1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Should be a local path.
|
Song ParserBase::LoadSong(const QString& filename_or_url, qint64 beginning, const QDir& dir) const {
|
||||||
if (QDir::isAbsolutePath(filename_or_url)) {
|
Song song;
|
||||||
// Absolute path.
|
LoadSong(filename_or_url, beginning, dir, &song);
|
||||||
// Fix windows \, eg. C:\foo -> C:/foo.
|
return song;
|
||||||
song->set_filename(QDir::fromNativeSeparators(filename_or_url));
|
|
||||||
} else {
|
|
||||||
// Relative path.
|
|
||||||
QString proper_path = QDir::fromNativeSeparators(filename_or_url);
|
|
||||||
QString absolute_path = dir.absoluteFilePath(proper_path);
|
|
||||||
song->set_filename(absolute_path);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QString ParserBase::MakeRelativeTo(const QString& filename_or_url,
|
QString ParserBase::URLOrRelativeFilename(const QUrl& url, const QDir& dir) const {
|
||||||
const QDir& dir) const {
|
if (url.scheme() != "file")
|
||||||
if (filename_or_url.contains(QRegExp("^[a-z]+://")))
|
return url.toString();
|
||||||
return filename_or_url;
|
|
||||||
|
|
||||||
if (QDir::isAbsolutePath(filename_or_url)) {
|
const QString filename = url.toLocalFile();
|
||||||
QString relative = dir.relativeFilePath(filename_or_url);
|
if (QDir::isAbsolutePath(filename)) {
|
||||||
|
const QString relative = dir.relativeFilePath(filename);
|
||||||
|
|
||||||
if (!relative.contains(".."))
|
if (!relative.contains(".."))
|
||||||
return relative;
|
return relative;
|
||||||
}
|
}
|
||||||
return filename_or_url;
|
return filename;
|
||||||
}
|
|
||||||
|
|
||||||
QString ParserBase::MakeUrl(const QString& filename_or_url) const {
|
|
||||||
if (filename_or_url.contains(QRegExp("^[a-z]+://"))) {
|
|
||||||
return filename_or_url;
|
|
||||||
}
|
|
||||||
|
|
||||||
return QUrl::fromLocalFile(filename_or_url).toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
Song ParserBase::LoadLibrarySong(const QString& filename_or_url, qint64 beginning) const {
|
|
||||||
if (!library_)
|
|
||||||
return Song();
|
|
||||||
|
|
||||||
QFileInfo info;
|
|
||||||
|
|
||||||
if (filename_or_url.contains("://"))
|
|
||||||
info.setFile(QUrl(filename_or_url).path());
|
|
||||||
else
|
|
||||||
info.setFile(filename_or_url);
|
|
||||||
|
|
||||||
return library_->GetSongByFilename(info.canonicalFilePath(), beginning);
|
|
||||||
}
|
}
|
||||||
|
@ -48,22 +48,19 @@ public:
|
|||||||
virtual void Save(const SongList& songs, QIODevice* device, const QDir& dir = QDir()) const = 0;
|
virtual void Save(const SongList& songs, QIODevice* device, const QDir& dir = QDir()) const = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// Takes a URL, relative path or absolute path, and returns an absolute path.
|
// Loads a song. If filename_or_url is a URL (with a scheme other than
|
||||||
// Resolves relative paths to "dir".
|
// "file") then it is set on the song and the song marked as a stream.
|
||||||
bool ParseTrackLocation(const QString& filename_or_url, const QDir& dir,
|
// If it is a filename or a file:// URL then it is made absolute and canonical
|
||||||
Song* song) const;
|
// and set as a file:// url on the song. Also sets the song's metadata by
|
||||||
|
// searching in the Library, or loading from the file as a fallback.
|
||||||
|
// This function should always be used when loading a playlist.
|
||||||
|
Song LoadSong(const QString& filename_or_url, qint64 beginning, const QDir& dir) const;
|
||||||
|
void LoadSong(const QString& filename_or_url, qint64 beginning, const QDir& dir, Song* song) const;
|
||||||
|
|
||||||
// Takes a URL, relative path or absolute path, and in the case of absolute
|
// If the URL is a file:// URL then returns its path relative to the
|
||||||
// paths makes them relative to dir if they are subdirectories.
|
// directory. Otherwise returns the URL as is.
|
||||||
QString MakeRelativeTo(const QString& filename_or_url, const QDir& dir) const;
|
// This function should always be used when saving a playlist.
|
||||||
|
QString URLOrRelativeFilename(const QUrl& url, const QDir& dir) const;
|
||||||
// Takes a URL or absolute path and returns a URL
|
|
||||||
QString MakeUrl(const QString& filename_or_url) const;
|
|
||||||
|
|
||||||
// Converts the URL or path to a canonical path and searches the library for
|
|
||||||
// a section of a song with that path and the given beginning. If one is found,
|
|
||||||
// returns it, otherwise returns an invalid song.
|
|
||||||
Song LoadLibrarySong(const QString& filename_or_url, qint64 beginning = 0) const;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
LibraryBackendInterface* library_;
|
LibraryBackendInterface* library_;
|
||||||
|
@ -40,16 +40,15 @@ SongList PLSParser::Load(QIODevice *device, const QString& playlist_path, const
|
|||||||
int n = n_re.cap(0).toInt();
|
int n = n_re.cap(0).toInt();
|
||||||
|
|
||||||
if (key.startsWith("file")) {
|
if (key.startsWith("file")) {
|
||||||
if (!ParseTrackLocation(value, dir, &songs[n]))
|
Song song = LoadSong(value, 0, dir);
|
||||||
qLog(Warning) << "Failed to parse location: " << value;
|
|
||||||
|
|
||||||
// Load the song from the library if it's there.
|
// Use the title and length we've already loaded if any
|
||||||
Song library_song = LoadLibrarySong(songs[n].filename());
|
if (!songs[n].title().isEmpty())
|
||||||
if (library_song.is_valid()) {
|
song.set_title(songs[n].title());
|
||||||
songs[n] = library_song;
|
if (!songs[n].length_nanosec() != -1)
|
||||||
} else {
|
song.set_length_nanosec(songs[n].length_nanosec());
|
||||||
songs[n].InitFromFile(songs[n].filename(), -1);
|
|
||||||
}
|
songs[n] = song;
|
||||||
} else if (key.startsWith("title")) {
|
} else if (key.startsWith("title")) {
|
||||||
songs[n].set_title(value);
|
songs[n].set_title(value);
|
||||||
} else if (key.startsWith("length")) {
|
} else if (key.startsWith("length")) {
|
||||||
@ -71,7 +70,7 @@ void PLSParser::Save(const SongList &songs, QIODevice *device, const QDir &dir)
|
|||||||
|
|
||||||
int n = 1;
|
int n = 1;
|
||||||
foreach (const Song& song, songs) {
|
foreach (const Song& song, songs) {
|
||||||
s << "File" << n << "=" << MakeRelativeTo(song.filename(), dir) << endl;
|
s << "File" << n << "=" << URLOrRelativeFilename(song.url(), dir) << endl;
|
||||||
s << "Title" << n << "=" << song.title() << endl;
|
s << "Title" << n << "=" << song.title() << endl;
|
||||||
s << "Length" << n << "=" << song.length_nanosec() / kNsecPerSec << endl;
|
s << "Length" << n << "=" << song.length_nanosec() / kNsecPerSec << endl;
|
||||||
++n;
|
++n;
|
||||||
|
@ -29,7 +29,8 @@ XSPFParser::XSPFParser(LibraryBackendInterface* library, QObject* parent)
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
SongList XSPFParser::Load(QIODevice *device, const QString& playlist_path, const QDir&) const {
|
SongList XSPFParser::Load(QIODevice *device, const QString& playlist_path,
|
||||||
|
const QDir& dir) const {
|
||||||
SongList ret;
|
SongList ret;
|
||||||
|
|
||||||
QXmlStreamReader reader(device);
|
QXmlStreamReader reader(device);
|
||||||
@ -39,7 +40,7 @@ SongList XSPFParser::Load(QIODevice *device, const QString& playlist_path, const
|
|||||||
}
|
}
|
||||||
|
|
||||||
while (!reader.atEnd() && ParseUntilElement(&reader, "track")) {
|
while (!reader.atEnd() && ParseUntilElement(&reader, "track")) {
|
||||||
Song song = ParseTrack(&reader);
|
Song song = ParseTrack(&reader, dir);
|
||||||
if (song.is_valid()) {
|
if (song.is_valid()) {
|
||||||
ret << song;
|
ret << song;
|
||||||
}
|
}
|
||||||
@ -47,34 +48,17 @@ SongList XSPFParser::Load(QIODevice *device, const QString& playlist_path, const
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
Song XSPFParser::ParseTrack(QXmlStreamReader* reader) const {
|
Song XSPFParser::ParseTrack(QXmlStreamReader* reader, const QDir& dir) const {
|
||||||
Song song;
|
QString title, artist, album, location;
|
||||||
QString title, artist, album;
|
|
||||||
qint64 nanosec = -1;
|
qint64 nanosec = -1;
|
||||||
|
|
||||||
while (!reader->atEnd()) {
|
while (!reader->atEnd()) {
|
||||||
QXmlStreamReader::TokenType type = reader->readNext();
|
QXmlStreamReader::TokenType type = reader->readNext();
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case QXmlStreamReader::StartElement: {
|
case QXmlStreamReader::StartElement: {
|
||||||
QStringRef name = reader->name();
|
QStringRef name = reader->name();
|
||||||
if (name == "location") {
|
if (name == "location") {
|
||||||
QUrl url(reader->readElementText());
|
location = reader->readElementText();
|
||||||
if (url.scheme() == "file") {
|
|
||||||
QString filename = url.toLocalFile();
|
|
||||||
if (!QFile::exists(filename)) {
|
|
||||||
return Song();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Load the song from the library if it's there.
|
|
||||||
Song library_song = LoadLibrarySong(filename);
|
|
||||||
if (library_song.is_valid())
|
|
||||||
return library_song;
|
|
||||||
|
|
||||||
song.InitFromFile(filename, -1);
|
|
||||||
return song;
|
|
||||||
} else {
|
|
||||||
song.set_filename(url.toString());
|
|
||||||
song.set_filetype(Song::Type_Stream);
|
|
||||||
}
|
|
||||||
} else if (name == "title") {
|
} else if (name == "title") {
|
||||||
title = reader->readElementText();
|
title = reader->readElementText();
|
||||||
} else if (name == "creator") {
|
} else if (name == "creator") {
|
||||||
@ -82,7 +66,7 @@ Song XSPFParser::ParseTrack(QXmlStreamReader* reader) const {
|
|||||||
} else if (name == "album") {
|
} else if (name == "album") {
|
||||||
album = reader->readElementText();
|
album = reader->readElementText();
|
||||||
} else if (name == "duration") { // in milliseconds.
|
} else if (name == "duration") { // in milliseconds.
|
||||||
const QString& duration = reader->readElementText();
|
const QString duration = reader->readElementText();
|
||||||
bool ok = false;
|
bool ok = false;
|
||||||
nanosec = duration.toInt(&ok) * kNsecPerMsec;
|
nanosec = duration.toInt(&ok) * kNsecPerMsec;
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
@ -97,16 +81,22 @@ Song XSPFParser::ParseTrack(QXmlStreamReader* reader) const {
|
|||||||
}
|
}
|
||||||
case QXmlStreamReader::EndElement: {
|
case QXmlStreamReader::EndElement: {
|
||||||
if (reader->name() == "track") {
|
if (reader->name() == "track") {
|
||||||
song.Init(title, artist, album, nanosec);
|
goto return_song;
|
||||||
return song;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// At least make an effort if we never find a </track>.
|
|
||||||
song.Init(title, artist, album, nanosec);
|
return_song:
|
||||||
|
Song song = LoadSong(location, 0, dir);
|
||||||
|
|
||||||
|
// Override metadata with what was in the playlist
|
||||||
|
song.set_title(title);
|
||||||
|
song.set_artist(artist);
|
||||||
|
song.set_album(album);
|
||||||
|
song.set_length_nanosec(nanosec);
|
||||||
return song;
|
return song;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -120,7 +110,7 @@ void XSPFParser::Save(const SongList& songs, QIODevice* device, const QDir&) con
|
|||||||
StreamElement tracklist("trackList", &writer);
|
StreamElement tracklist("trackList", &writer);
|
||||||
foreach (const Song& song, songs) {
|
foreach (const Song& song, songs) {
|
||||||
StreamElement track("track", &writer);
|
StreamElement track("track", &writer);
|
||||||
writer.writeTextElement("location", MakeUrl(song.filename()));
|
writer.writeTextElement("location", song.url().toString());
|
||||||
writer.writeTextElement("title", song.title());
|
writer.writeTextElement("title", song.title());
|
||||||
if (!song.artist().isEmpty()) {
|
if (!song.artist().isEmpty()) {
|
||||||
writer.writeTextElement("creator", song.artist());
|
writer.writeTextElement("creator", song.artist());
|
||||||
@ -136,7 +126,9 @@ void XSPFParser::Save(const SongList& songs, QIODevice* device, const QDir&) con
|
|||||||
// Ignore images that are in our resource bundle.
|
// Ignore images that are in our resource bundle.
|
||||||
if (!art.startsWith(":") && !art.isEmpty()) {
|
if (!art.startsWith(":") && !art.isEmpty()) {
|
||||||
// Convert local files to URLs.
|
// Convert local files to URLs.
|
||||||
art = MakeUrl(art);
|
if (!art.contains("://")) {
|
||||||
|
art = QUrl::fromLocalFile(art).toString();
|
||||||
|
}
|
||||||
writer.writeTextElement("image", art);
|
writer.writeTextElement("image", art);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -36,11 +36,12 @@ class XSPFParser : public XMLParser {
|
|||||||
|
|
||||||
bool TryMagic(const QByteArray &data) const;
|
bool TryMagic(const QByteArray &data) const;
|
||||||
|
|
||||||
SongList Load(QIODevice *device, const QString& playlist_path = "", const QDir &dir = QDir()) const;
|
SongList Load(QIODevice *device, const QString& playlist_path = "",
|
||||||
|
const QDir& dir = QDir()) const;
|
||||||
void Save(const SongList &songs, QIODevice *device, const QDir &dir = QDir()) const;
|
void Save(const SongList &songs, QIODevice *device, const QDir &dir = QDir()) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Song ParseTrack(QXmlStreamReader* reader) const;
|
Song ParseTrack(QXmlStreamReader* reader, const QDir& dir) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -177,7 +177,7 @@ Song IcecastBackend::Station::ToSong() const {
|
|||||||
Song ret;
|
Song ret;
|
||||||
ret.set_valid(true);
|
ret.set_valid(true);
|
||||||
ret.set_title(name);
|
ret.set_title(name);
|
||||||
ret.set_filename(url.toEncoded());
|
ret.set_url(url);
|
||||||
ret.set_bitrate(bitrate);
|
ret.set_bitrate(bitrate);
|
||||||
ret.set_samplerate(samplerate);
|
ret.set_samplerate(samplerate);
|
||||||
ret.set_genre(genre);
|
ret.set_genre(genre);
|
||||||
|
@ -36,5 +36,5 @@ bool JamendoPlaylistItem::InitFromQuery(const SqlRow& query) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
QUrl JamendoPlaylistItem::Url() const {
|
QUrl JamendoPlaylistItem::Url() const {
|
||||||
return QUrl::fromEncoded(song_.filename().toAscii());
|
return song_.url();
|
||||||
}
|
}
|
||||||
|
@ -364,7 +364,7 @@ Song JamendoService::ReadTrack(const QString& artist,
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
QString ogg_url = QString(kOggStreamUrl).arg(id_text);
|
QString ogg_url = QString(kOggStreamUrl).arg(id_text);
|
||||||
song.set_filename(ogg_url);
|
song.set_url(QUrl(ogg_url));
|
||||||
song.set_art_automatic(album_cover);
|
song.set_art_automatic(album_cover);
|
||||||
song.set_valid(true);
|
song.set_valid(true);
|
||||||
|
|
||||||
|
@ -148,22 +148,22 @@ void LastFMService::LazyPopulate(QStandardItem* parent) {
|
|||||||
CreateStationItem(parent,
|
CreateStationItem(parent,
|
||||||
tr("My Recommendations"),
|
tr("My Recommendations"),
|
||||||
":last.fm/recommended_radio.png",
|
":last.fm/recommended_radio.png",
|
||||||
"lastfm://user/USERNAME/recommended",
|
QUrl("lastfm://user/USERNAME/recommended"),
|
||||||
tr("My Last.fm Recommended Radio"));
|
tr("My Last.fm Recommended Radio"));
|
||||||
CreateStationItem(parent,
|
CreateStationItem(parent,
|
||||||
tr("My Radio Station"),
|
tr("My Radio Station"),
|
||||||
":last.fm/personal_radio.png",
|
":last.fm/personal_radio.png",
|
||||||
"lastfm://user/USERNAME/library",
|
QUrl("lastfm://user/USERNAME/library"),
|
||||||
tr("My Last.fm Library"));
|
tr("My Last.fm Library"));
|
||||||
CreateStationItem(parent,
|
CreateStationItem(parent,
|
||||||
tr("My Mix Radio"),
|
tr("My Mix Radio"),
|
||||||
":last.fm/loved_radio.png",
|
":last.fm/loved_radio.png",
|
||||||
"lastfm://user/USERNAME/mix",
|
QUrl("lastfm://user/USERNAME/mix"),
|
||||||
tr("My Last.fm Mix Radio"));
|
tr("My Last.fm Mix Radio"));
|
||||||
CreateStationItem(parent,
|
CreateStationItem(parent,
|
||||||
tr("My Neighborhood"),
|
tr("My Neighborhood"),
|
||||||
":last.fm/neighbour_radio.png",
|
":last.fm/neighbour_radio.png",
|
||||||
"lastfm://user/USERNAME/neighbours",
|
QUrl("lastfm://user/USERNAME/neighbours"),
|
||||||
tr("My Last.fm Neighborhood"));
|
tr("My Last.fm Neighborhood"));
|
||||||
|
|
||||||
// Types that have children
|
// Types that have children
|
||||||
@ -213,17 +213,17 @@ void LastFMService::LazyPopulate(QStandardItem* parent) {
|
|||||||
CreateStationItem(parent,
|
CreateStationItem(parent,
|
||||||
tr("Last.fm Radio Station - %1").arg(parent->text()),
|
tr("Last.fm Radio Station - %1").arg(parent->text()),
|
||||||
":last.fm/personal_radio.png",
|
":last.fm/personal_radio.png",
|
||||||
"lastfm://user/" + parent->text() + "/library",
|
QUrl("lastfm://user/" + parent->text() + "/library"),
|
||||||
tr("Last.fm Library - %1").arg(parent->text()));
|
tr("Last.fm Library - %1").arg(parent->text()));
|
||||||
CreateStationItem(parent,
|
CreateStationItem(parent,
|
||||||
tr("Last.fm Mix Radio - %1").arg(parent->text()),
|
tr("Last.fm Mix Radio - %1").arg(parent->text()),
|
||||||
":last.fm/loved_radio.png",
|
":last.fm/loved_radio.png",
|
||||||
"lastfm://user/" + parent->text() + "/mix",
|
QUrl("lastfm://user/" + parent->text() + "/mix"),
|
||||||
tr("Last.fm Mix Radio - %1").arg(parent->text()));
|
tr("Last.fm Mix Radio - %1").arg(parent->text()));
|
||||||
CreateStationItem(parent,
|
CreateStationItem(parent,
|
||||||
tr("Last.fm Neighbor Radio - %1").arg(parent->text()),
|
tr("Last.fm Neighbor Radio - %1").arg(parent->text()),
|
||||||
":last.fm/neighbour_radio.png",
|
":last.fm/neighbour_radio.png",
|
||||||
"lastfm://user/" + parent->text() + "/neighbours",
|
QUrl("lastfm://user/" + parent->text() + "/neighbours"),
|
||||||
tr("Last.fm Neighbor Radio - %1").arg(parent->text()));
|
tr("Last.fm Neighbor Radio - %1").arg(parent->text()));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -234,9 +234,9 @@ void LastFMService::LazyPopulate(QStandardItem* parent) {
|
|||||||
|
|
||||||
QStandardItem* LastFMService::CreateStationItem(
|
QStandardItem* LastFMService::CreateStationItem(
|
||||||
QStandardItem* parent, const QString& name, const QString& icon,
|
QStandardItem* parent, const QString& name, const QString& icon,
|
||||||
const QString& url, const QString& title) {
|
const QUrl& url, const QString& title) {
|
||||||
Song song;
|
Song song;
|
||||||
song.set_filename(url);
|
song.set_url(url);
|
||||||
song.set_title(title);
|
song.set_title(title);
|
||||||
|
|
||||||
QStandardItem* ret = new QStandardItem(QIcon(icon), name);
|
QStandardItem* ret = new QStandardItem(QIcon(icon), name);
|
||||||
@ -625,7 +625,7 @@ void LastFMService::RefreshFriendsFinished() {
|
|||||||
|
|
||||||
foreach (const lastfm::User& f, friends) {
|
foreach (const lastfm::User& f, friends) {
|
||||||
Song song;
|
Song song;
|
||||||
song.set_filename("lastfm://user/" + f.name() + "/library");
|
song.set_url(QUrl("lastfm://user/" + f.name() + "/library"));
|
||||||
song.set_title(tr("Last.fm Library - %1").arg(f.name()));
|
song.set_title(tr("Last.fm Library - %1").arg(f.name()));
|
||||||
|
|
||||||
QStandardItem* item = new QStandardItem(QIcon(":last.fm/icon_user.png"), f.name());
|
QStandardItem* item = new QStandardItem(QIcon(":last.fm/icon_user.png"), f.name());
|
||||||
@ -657,7 +657,7 @@ void LastFMService::RefreshNeighboursFinished() {
|
|||||||
|
|
||||||
foreach (const lastfm::User& n, neighbours) {
|
foreach (const lastfm::User& n, neighbours) {
|
||||||
Song song;
|
Song song;
|
||||||
song.set_filename("lastfm://user/" + n.name() + "/library");
|
song.set_url(QUrl("lastfm://user/" + n.name() + "/library"));
|
||||||
song.set_title(tr("Last.fm Library - %1").arg(n.name()));
|
song.set_title(tr("Last.fm Library - %1").arg(n.name()));
|
||||||
|
|
||||||
QStandardItem* item = new QStandardItem(QIcon(":last.fm/user_purple.png"), n.name());
|
QStandardItem* item = new QStandardItem(QIcon(":last.fm/user_purple.png"), n.name());
|
||||||
@ -711,7 +711,7 @@ void LastFMService::AddArtistOrTag(const QString& name,
|
|||||||
url_content = content;
|
url_content = content;
|
||||||
|
|
||||||
Song song;
|
Song song;
|
||||||
song.set_filename(url_pattern.arg(url_content));
|
song.set_url(QUrl(url_pattern.arg(url_content)));
|
||||||
song.set_title(title_pattern.arg(content));
|
song.set_title(title_pattern.arg(content));
|
||||||
|
|
||||||
QStandardItem* item = new QStandardItem(QIcon(icon), content);
|
QStandardItem* item = new QStandardItem(QIcon(icon), content);
|
||||||
@ -756,7 +756,7 @@ void LastFMService::RestoreList(const QString& name,
|
|||||||
url_content = content;
|
url_content = content;
|
||||||
|
|
||||||
Song song;
|
Song song;
|
||||||
song.set_filename(url_pattern.arg(url_content));
|
song.set_url(QUrl(url_pattern.arg(url_content)));
|
||||||
song.set_title(title_pattern.arg(content));
|
song.set_title(title_pattern.arg(content));
|
||||||
|
|
||||||
QStandardItem* item = new QStandardItem(icon, content);
|
QStandardItem* item = new QStandardItem(icon, content);
|
||||||
@ -881,7 +881,7 @@ PlaylistItemPtr LastFMService::PlaylistItemForUrl(const QUrl& url) {
|
|||||||
QStringList sections(url.path().split("/", QString::SkipEmptyParts));
|
QStringList sections(url.path().split("/", QString::SkipEmptyParts));
|
||||||
|
|
||||||
Song song;
|
Song song;
|
||||||
song.set_filename(url.toString());
|
song.set_url(url);
|
||||||
|
|
||||||
if (sections.count() == 2 && url.host() == "artist" && sections[1] == "similarartists") {
|
if (sections.count() == 2 && url.host() == "artist" && sections[1] == "similarartists") {
|
||||||
song.set_title(tr(kTitleArtist).arg(sections[0]));
|
song.set_title(tr(kTitleArtist).arg(sections[0]));
|
||||||
|
@ -150,7 +150,7 @@ class LastFMService : public RadioService {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
QStandardItem* CreateStationItem(QStandardItem* parent,
|
QStandardItem* CreateStationItem(QStandardItem* parent,
|
||||||
const QString& name, const QString& icon, const QString& url,
|
const QString& name, const QString& icon, const QUrl& url,
|
||||||
const QString& title);
|
const QString& title);
|
||||||
QString ErrorString(lastfm::ws::Error error) const;
|
QString ErrorString(lastfm::ws::Error error) const;
|
||||||
bool InitScrobbler();
|
bool InitScrobbler();
|
||||||
|
@ -42,7 +42,7 @@ PlaylistItem::Options MagnatunePlaylistItem::options() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
QUrl MagnatunePlaylistItem::Url() const {
|
QUrl MagnatunePlaylistItem::Url() const {
|
||||||
return QUrl::fromEncoded(song_.filename().toAscii());
|
return song_.url();
|
||||||
}
|
}
|
||||||
|
|
||||||
PlaylistItem::SpecialLoadResult MagnatunePlaylistItem::StartLoading() {
|
PlaylistItem::SpecialLoadResult MagnatunePlaylistItem::StartLoading() {
|
||||||
|
@ -205,7 +205,7 @@ Song MagnatuneService::ReadTrack(QXmlStreamReader& reader) {
|
|||||||
if (name == "year") song.set_year(value.toInt());
|
if (name == "year") song.set_year(value.toInt());
|
||||||
if (name == "magnatunegenres") song.set_genre(value.section(',', 0, 0));
|
if (name == "magnatunegenres") song.set_genre(value.section(',', 0, 0));
|
||||||
if (name == "seconds") song.set_length_nanosec(value.toInt() * kNsecPerSec);
|
if (name == "seconds") song.set_length_nanosec(value.toInt() * kNsecPerSec);
|
||||||
if (name == "url") song.set_filename(value);
|
if (name == "url") song.set_url(QUrl(value));
|
||||||
if (name == "cover_small") song.set_art_automatic(value);
|
if (name == "cover_small") song.set_art_automatic(value);
|
||||||
if (name == "albumsku") song.set_comment(value);
|
if (name == "albumsku") song.set_comment(value);
|
||||||
}
|
}
|
||||||
|
@ -77,7 +77,7 @@ QVariant RadioPlaylistItem::DatabaseValue(DatabaseColumn column) const {
|
|||||||
|
|
||||||
void RadioPlaylistItem::InitMetadata() {
|
void RadioPlaylistItem::InitMetadata() {
|
||||||
if (metadata_.title().isEmpty())
|
if (metadata_.title().isEmpty())
|
||||||
metadata_.set_title(metadata_.filename());
|
metadata_.set_title(metadata_.url().toString());
|
||||||
metadata_.set_filetype(Song::Type_Stream);
|
metadata_.set_filetype(Song::Type_Stream);
|
||||||
metadata_.set_valid(true);
|
metadata_.set_valid(true);
|
||||||
}
|
}
|
||||||
@ -108,7 +108,7 @@ PlaylistItem::SpecialLoadResult RadioPlaylistItem::LoadNext() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
QUrl RadioPlaylistItem::Url() const {
|
QUrl RadioPlaylistItem::Url() const {
|
||||||
return QUrl(metadata_.filename());
|
return metadata_.url();
|
||||||
}
|
}
|
||||||
|
|
||||||
PlaylistItem::Options RadioPlaylistItem::options() const {
|
PlaylistItem::Options RadioPlaylistItem::options() const {
|
||||||
|
@ -181,7 +181,7 @@ void SomaFMService::ReadChannel(QXmlStreamReader& reader) {
|
|||||||
} else if (reader.name() == "dj") {
|
} else if (reader.name() == "dj") {
|
||||||
song.set_artist(reader.readElementText());
|
song.set_artist(reader.readElementText());
|
||||||
} else if (reader.name() == "fastpls" && reader.attributes().value("format") == "mp3") {
|
} else if (reader.name() == "fastpls" && reader.attributes().value("format") == "mp3") {
|
||||||
song.set_filename(reader.readElementText());
|
song.set_url(QUrl(reader.readElementText()));
|
||||||
} else {
|
} else {
|
||||||
ConsumeElement(reader);
|
ConsumeElement(reader);
|
||||||
}
|
}
|
||||||
|
@ -278,7 +278,7 @@ void SpotifyService::FillPlaylist(QStandardItem* item, const protobuf::LoadPlayl
|
|||||||
child->setData(Type_Track, RadioModel::Role_Type);
|
child->setData(Type_Track, RadioModel::Role_Type);
|
||||||
child->setData(QVariant::fromValue(song), RadioModel::Role_SongMetadata);
|
child->setData(QVariant::fromValue(song), RadioModel::Role_SongMetadata);
|
||||||
child->setData(RadioModel::PlayBehaviour_SingleItem, RadioModel::Role_PlayBehaviour);
|
child->setData(RadioModel::PlayBehaviour_SingleItem, RadioModel::Role_PlayBehaviour);
|
||||||
child->setData(QUrl(song.filename()), RadioModel::Role_Url);
|
child->setData(song.url(), RadioModel::Role_Url);
|
||||||
|
|
||||||
item->appendRow(child);
|
item->appendRow(child);
|
||||||
}
|
}
|
||||||
@ -293,7 +293,7 @@ void SpotifyService::SongFromProtobuf(const protobuf::Track& track, Song* song)
|
|||||||
song->set_disc(track.disc());
|
song->set_disc(track.disc());
|
||||||
song->set_track(track.track());
|
song->set_track(track.track());
|
||||||
song->set_year(track.year());
|
song->set_year(track.year());
|
||||||
song->set_filename(QStringFromStdString(track.uri()));
|
song->set_url(QUrl(QStringFromStdString(track.uri())));
|
||||||
|
|
||||||
QStringList artists;
|
QStringList artists;
|
||||||
for (int i=0 ; i<track.artist_size() ; ++i) {
|
for (int i=0 ; i<track.artist_size() ; ++i) {
|
||||||
|
@ -9,14 +9,14 @@ public:
|
|||||||
Album();
|
Album();
|
||||||
Album(const QString& _artist, const QString& _album_name,
|
Album(const QString& _artist, const QString& _album_name,
|
||||||
const QString& _art_automatic, const QString& _art_manual,
|
const QString& _art_automatic, const QString& _art_manual,
|
||||||
const QString& _first_filename);
|
const QUrl& _first_url);
|
||||||
|
|
||||||
QString artist;
|
QString artist;
|
||||||
QString album_name;
|
QString album_name;
|
||||||
|
|
||||||
QString art_automatic;
|
QString art_automatic;
|
||||||
QString art_manual;
|
QString art_manual;
|
||||||
QString first_filename;
|
QUrl first_url;
|
||||||
};
|
};
|
||||||
typedef QList<LibraryBackend::Album> AlbumList;
|
typedef QList<LibraryBackend::Album> AlbumList;
|
||||||
|
|
||||||
@ -33,7 +33,7 @@ public:
|
|||||||
SongList FindSongsInDirectory(int id);
|
SongList FindSongsInDirectory(int id);
|
||||||
SubdirectoryList SubdirsInDirectory(int id);
|
SubdirectoryList SubdirsInDirectory(int id);
|
||||||
DirectoryList GetAllDirectories();
|
DirectoryList GetAllDirectories();
|
||||||
void ChangeDirPath(int id, const QString& new_path);
|
void ChangeDirPath(int id, const QString& old_path, const QString& new_path);
|
||||||
|
|
||||||
QStringList GetAll(const QString& column, const QueryOptions& opt = QueryOptions());
|
QStringList GetAll(const QString& column, const QueryOptions& opt = QueryOptions());
|
||||||
QStringList GetAllArtists(const QueryOptions& opt = QueryOptions());
|
QStringList GetAllArtists(const QueryOptions& opt = QueryOptions());
|
||||||
@ -56,8 +56,8 @@ public:
|
|||||||
SongList GetSongsByForeignId(const QStringList& ids, const QString& table,
|
SongList GetSongsByForeignId(const QStringList& ids, const QString& table,
|
||||||
const QString& column);
|
const QString& column);
|
||||||
|
|
||||||
SongList GetSongsByFilename(const QString& filename);
|
SongList GetSongsByUrl(const QUrl& url);
|
||||||
Song GetSongByFilename(const QString& filename, int beginning);
|
Song GetSongByUrl(const QUrl& url, int beginning);
|
||||||
|
|
||||||
void AddDirectory(const QString& path);
|
void AddDirectory(const QString& path);
|
||||||
void RemoveDirectory(const Directory& dir);
|
void RemoveDirectory(const Directory& dir);
|
||||||
|
@ -308,22 +308,16 @@ The ID in the L{LibraryBackend} of the directory containing this song, or -1 if
|
|||||||
the song is not from the library.
|
the song is not from the library.
|
||||||
%End
|
%End
|
||||||
|
|
||||||
const QString& filename() const;
|
const QUrl& url() const;
|
||||||
%Docstring
|
%Docstring
|
||||||
filename() -> str
|
url() -> L{PyQt4.QtCore.QUrl}
|
||||||
The filename I{or URL} of this song.
|
The URL of this song.
|
||||||
%End
|
%End
|
||||||
|
|
||||||
const QString& basefilename() const;
|
const QString& basefilename() const;
|
||||||
%Docstring
|
%Docstring
|
||||||
basefilename() -> str
|
basefilename() -> str
|
||||||
The filename of this song without any directory component.
|
The filename of this song without any directory component.
|
||||||
%End
|
|
||||||
|
|
||||||
QUrl url() const;
|
|
||||||
%Docstring
|
|
||||||
url() -> L{PyQt4.QtCore.QUrl}
|
|
||||||
URL for this song which may point either to a file or to another type of stream.
|
|
||||||
%End
|
%End
|
||||||
|
|
||||||
uint mtime() const;
|
uint mtime() const;
|
||||||
@ -658,9 +652,9 @@ set_lastplayed(lastplayed)
|
|||||||
set_score(score)
|
set_score(score)
|
||||||
%End
|
%End
|
||||||
|
|
||||||
void set_filename(const QString& v);
|
void set_url(const QUrl& v);
|
||||||
%Docstring
|
%Docstring
|
||||||
set_filename(filename)
|
set_url(url)
|
||||||
%End
|
%End
|
||||||
|
|
||||||
void set_basefilename(const QString& v);
|
void set_basefilename(const QString& v);
|
||||||
|
@ -130,8 +130,8 @@ QString AlbumCoverChoiceController::GetInitialPathForFileDialog(const Song& song
|
|||||||
return song.art_automatic();
|
return song.art_automatic();
|
||||||
|
|
||||||
// if no automatic art, start in the song's folder
|
// if no automatic art, start in the song's folder
|
||||||
} else if (!song.filename().isEmpty() && song.filename().contains('/')) {
|
} else if (!song.url().isEmpty() && song.url().toLocalFile().contains('/')) {
|
||||||
return song.filename().section('/', 0, -2) + filename;
|
return song.url().toLocalFile().section('/', 0, -2) + filename;
|
||||||
|
|
||||||
// fallback - start in home
|
// fallback - start in home
|
||||||
} else {
|
} else {
|
||||||
@ -189,7 +189,7 @@ void AlbumCoverChoiceController::ShowCover(const Song& song) {
|
|||||||
|
|
||||||
QLabel* label = new QLabel(dialog);
|
QLabel* label = new QLabel(dialog);
|
||||||
label->setPixmap(AlbumCoverLoader::TryLoadPixmap(
|
label->setPixmap(AlbumCoverLoader::TryLoadPixmap(
|
||||||
song.art_automatic(), song.art_manual(), song.filename()));
|
song.art_automatic(), song.art_manual(), song.url().toLocalFile()));
|
||||||
|
|
||||||
dialog->resize(label->pixmap()->size());
|
dialog->resize(label->pixmap()->size());
|
||||||
dialog->show();
|
dialog->show();
|
||||||
|
@ -293,14 +293,14 @@ void AlbumCoverManager::ArtistChanged(QListWidgetItem* current) {
|
|||||||
QListWidgetItem* item = new QListWidgetItem(no_cover_icon_, info.album_name, ui_->albums);
|
QListWidgetItem* item = new QListWidgetItem(no_cover_icon_, info.album_name, ui_->albums);
|
||||||
item->setData(Role_ArtistName, info.artist);
|
item->setData(Role_ArtistName, info.artist);
|
||||||
item->setData(Role_AlbumName, info.album_name);
|
item->setData(Role_AlbumName, info.album_name);
|
||||||
item->setData(Role_FirstFilename, info.first_filename);
|
item->setData(Role_FirstUrl, info.first_url);
|
||||||
item->setData(Qt::TextAlignmentRole, QVariant(Qt::AlignTop | Qt::AlignHCenter));
|
item->setData(Qt::TextAlignmentRole, QVariant(Qt::AlignTop | Qt::AlignHCenter));
|
||||||
item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsDragEnabled);
|
item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsDragEnabled);
|
||||||
item->setToolTip(info.artist + " - " + info.album_name);
|
item->setToolTip(info.artist + " - " + info.album_name);
|
||||||
|
|
||||||
if (!info.art_automatic.isEmpty() || !info.art_manual.isEmpty()) {
|
if (!info.art_automatic.isEmpty() || !info.art_manual.isEmpty()) {
|
||||||
quint64 id = cover_loader_->Worker()->LoadImageAsync(
|
quint64 id = cover_loader_->Worker()->LoadImageAsync(
|
||||||
info.art_automatic, info.art_manual, info.first_filename);
|
info.art_automatic, info.art_manual, info.first_url.toLocalFile());
|
||||||
item->setData(Role_PathAutomatic, info.art_automatic);
|
item->setData(Role_PathAutomatic, info.art_automatic);
|
||||||
item->setData(Role_PathManual, info.art_manual);
|
item->setData(Role_PathManual, info.art_manual);
|
||||||
cover_loading_tasks_[id] = item;
|
cover_loading_tasks_[id] = item;
|
||||||
@ -487,7 +487,7 @@ Song AlbumCoverManager::ItemAsSong(QListWidgetItem* item) {
|
|||||||
result.set_artist(item->data(Role_ArtistName).toString());
|
result.set_artist(item->data(Role_ArtistName).toString());
|
||||||
result.set_album(item->data(Role_AlbumName).toString());
|
result.set_album(item->data(Role_AlbumName).toString());
|
||||||
|
|
||||||
result.set_filename(item->data(Role_FirstFilename).toString());
|
result.set_url(item->data(Role_FirstUrl).toUrl());
|
||||||
|
|
||||||
result.set_art_automatic(item->data(Role_PathAutomatic).toString());
|
result.set_art_automatic(item->data(Role_PathAutomatic).toString());
|
||||||
result.set_art_manual(item->data(Role_PathManual).toString());
|
result.set_art_manual(item->data(Role_PathManual).toString());
|
||||||
|
@ -110,7 +110,7 @@ class AlbumCoverManager : public QMainWindow {
|
|||||||
Role_AlbumName,
|
Role_AlbumName,
|
||||||
Role_PathAutomatic,
|
Role_PathAutomatic,
|
||||||
Role_PathManual,
|
Role_PathManual,
|
||||||
Role_FirstFilename,
|
Role_FirstUrl,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum HideCovers {
|
enum HideCovers {
|
||||||
|
@ -43,7 +43,7 @@ QMimeData* AlbumCoverManagerList::mimeData(const QList<QListWidgetItem*> items)
|
|||||||
// Get URLs from the songs
|
// Get URLs from the songs
|
||||||
QList<QUrl> urls;
|
QList<QUrl> urls;
|
||||||
foreach (const Song& song, songs) {
|
foreach (const Song& song, songs) {
|
||||||
urls << QUrl::fromLocalFile(song.filename());
|
urls << song.url();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the QAbstractItemModel data so the picture works
|
// Get the QAbstractItemModel data so the picture works
|
||||||
|
@ -191,7 +191,7 @@ QList<EditTagDialog::Data> EditTagDialog::LoadData(const SongList& songs) const
|
|||||||
if (song.IsEditable()) {
|
if (song.IsEditable()) {
|
||||||
// Try reloading the tags from file
|
// Try reloading the tags from file
|
||||||
Song copy(song);
|
Song copy(song);
|
||||||
copy.InitFromFile(copy.filename(), copy.directory_id());
|
copy.InitFromFile(copy.url().toLocalFile(), copy.directory_id());
|
||||||
|
|
||||||
if (copy.is_valid())
|
if (copy.is_valid())
|
||||||
ret << Data(copy);
|
ret << Data(copy);
|
||||||
@ -424,7 +424,11 @@ void EditTagDialog::UpdateSummaryTab(const Song& song) {
|
|||||||
QLocale::system().dateTimeFormat(QLocale::LongFormat)));
|
QLocale::system().dateTimeFormat(QLocale::LongFormat)));
|
||||||
ui_->filesize->setText(Utilities::PrettySize(song.filesize()));
|
ui_->filesize->setText(Utilities::PrettySize(song.filesize()));
|
||||||
ui_->filetype->setText(song.TextForFiletype());
|
ui_->filetype->setText(song.TextForFiletype());
|
||||||
ui_->filename->setText(QDir::toNativeSeparators(song.filename()));
|
|
||||||
|
if (song.url().scheme() == "file")
|
||||||
|
ui_->filename->setText(QDir::toNativeSeparators(song.url().toLocalFile()));
|
||||||
|
else
|
||||||
|
ui_->filename->setText(song.url().toString());
|
||||||
|
|
||||||
album_cover_choice_controller_->search_for_cover_action()->setEnabled(CoverProviders::instance().HasAnyProviders());
|
album_cover_choice_controller_->search_for_cover_action()->setEnabled(CoverProviders::instance().HasAnyProviders());
|
||||||
}
|
}
|
||||||
@ -602,7 +606,7 @@ void EditTagDialog::SaveData(const QList<Data>& data) {
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (!ref.current_.Save()) {
|
if (!ref.current_.Save()) {
|
||||||
emit Error(tr("An error occurred writing metadata to '%1'").arg(ref.current_.filename()));
|
emit Error(tr("An error occurred writing metadata to '%1'").arg(ref.current_.url().toLocalFile()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -736,12 +740,12 @@ void EditTagDialog::FetchTag() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void EditTagDialog::FetchTagSongChosen(const Song& original_song, const Song& new_metadata) {
|
void EditTagDialog::FetchTagSongChosen(const Song& original_song, const Song& new_metadata) {
|
||||||
const QString filename = original_song.filename();
|
const QString filename = original_song.url().toLocalFile();
|
||||||
|
|
||||||
// Find the song with this filename
|
// Find the song with this filename
|
||||||
for (int i=0 ; i<data_.count() ; ++i) {
|
for (int i=0 ; i<data_.count() ; ++i) {
|
||||||
Data* data = &data_[i];
|
Data* data = &data_[i];
|
||||||
if (data->original_.filename() != filename)
|
if (data->original_.url().toLocalFile() != filename)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Is it currently being displayed in the UI?
|
// Is it currently being displayed in the UI?
|
||||||
|
@ -106,19 +106,13 @@ int OrganiseDialog::SetSongs(const SongList& songs) {
|
|||||||
preview_songs_.clear();
|
preview_songs_.clear();
|
||||||
|
|
||||||
foreach (const Song& song, songs) {
|
foreach (const Song& song, songs) {
|
||||||
const QString filename = song.filename();
|
if (song.url().scheme() != "file") {
|
||||||
|
|
||||||
if (filename.isEmpty())
|
|
||||||
continue;
|
continue;
|
||||||
if (filename.contains("://")) {
|
};
|
||||||
QUrl url(song.filename());
|
|
||||||
if (!url.scheme().isEmpty() && url.scheme() != "file")
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (song.filesize() > 0)
|
if (song.filesize() > 0)
|
||||||
total_size_ += song.filesize();
|
total_size_ += song.filesize();
|
||||||
filenames_ << filename;
|
filenames_ << song.url().toLocalFile();
|
||||||
|
|
||||||
if (preview_songs_.count() < kNumberOfPreviews)
|
if (preview_songs_.count() < kNumberOfPreviews)
|
||||||
preview_songs_ << song;
|
preview_songs_ << song;
|
||||||
|
@ -38,7 +38,7 @@ void OrganiseErrorDialog::Show(
|
|||||||
OperationType type, const SongList& songs_with_errors) {
|
OperationType type, const SongList& songs_with_errors) {
|
||||||
QStringList files;
|
QStringList files;
|
||||||
foreach (const Song& song, songs_with_errors) {
|
foreach (const Song& song, songs_with_errors) {
|
||||||
files << song.filename();
|
files << song.url().toLocalFile();
|
||||||
}
|
}
|
||||||
Show(type, files);
|
Show(type, files);
|
||||||
}
|
}
|
||||||
|
@ -77,7 +77,7 @@ void TrackSelectionDialog::Init(const SongList& songs) {
|
|||||||
data_ << data;
|
data_ << data;
|
||||||
|
|
||||||
QListWidgetItem* item = new QListWidgetItem(ui_->song_list);
|
QListWidgetItem* item = new QListWidgetItem(ui_->song_list);
|
||||||
item->setText(QFileInfo(song.filename()).fileName());
|
item->setText(QFileInfo(song.url().toLocalFile()).fileName());
|
||||||
item->setForeground(palette().color(QPalette::Disabled, QPalette::Text));
|
item->setForeground(palette().color(QPalette::Disabled, QPalette::Text));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -94,7 +94,7 @@ void TrackSelectionDialog::FetchTagProgress(const Song& original_song,
|
|||||||
// Find the item with this filename
|
// Find the item with this filename
|
||||||
int row = -1;
|
int row = -1;
|
||||||
for (int i=0 ; i<data_.count() ; ++i) {
|
for (int i=0 ; i<data_.count() ; ++i) {
|
||||||
if (data_[i].original_song_.filename() == original_song.filename()) {
|
if (data_[i].original_song_.url() == original_song.url()) {
|
||||||
row = i;
|
row = i;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -116,7 +116,7 @@ void TrackSelectionDialog::FetchTagFinished(const Song& original_song,
|
|||||||
// Find the item with this filename
|
// Find the item with this filename
|
||||||
int row = -1;
|
int row = -1;
|
||||||
for (int i=0 ; i<data_.count() ; ++i) {
|
for (int i=0 ; i<data_.count() ; ++i) {
|
||||||
if (data_[i].original_song_.filename() == original_song.filename()) {
|
if (data_[i].original_song_.url() == original_song.url()) {
|
||||||
row = i;
|
row = i;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -37,8 +37,8 @@ TEST_F(AsxIniParserTest, ParsesBasicTrackList) {
|
|||||||
|
|
||||||
SongList songs = parser_.Load(&file, "", QDir());
|
SongList songs = parser_.Load(&file, "", QDir());
|
||||||
ASSERT_EQ(2, songs.length());
|
ASSERT_EQ(2, songs.length());
|
||||||
EXPECT_EQ("http://195.245.168.21/antena3?MSWMExt=.asf", songs[0].filename());
|
EXPECT_EQ(QUrl("http://195.245.168.21/antena3?MSWMExt=.asf"), songs[0].url());
|
||||||
EXPECT_EQ("http://195.245.168.21:80/antena3?MSWMExt=.asf", songs[1].filename());
|
EXPECT_EQ(QUrl("http://195.245.168.21:80/antena3?MSWMExt=.asf"), songs[1].url());
|
||||||
EXPECT_TRUE(songs[0].is_valid());
|
EXPECT_TRUE(songs[0].is_valid());
|
||||||
EXPECT_TRUE(songs[1].is_valid());
|
EXPECT_TRUE(songs[1].is_valid());
|
||||||
}
|
}
|
||||||
@ -56,7 +56,7 @@ TEST_F(AsxIniParserTest, WritesBasicTrackList) {
|
|||||||
buffer.open(QIODevice::WriteOnly);
|
buffer.open(QIODevice::WriteOnly);
|
||||||
|
|
||||||
Song song;
|
Song song;
|
||||||
song.set_filename("http://www.example.com/foo.mp3");
|
song.set_url(QUrl("http://www.example.com/foo.mp3"));
|
||||||
|
|
||||||
SongList songs;
|
SongList songs;
|
||||||
songs << song;
|
songs << song;
|
||||||
|
@ -45,7 +45,7 @@ TEST_F(ASXParserTest, ParsesOneTrackFromXML) {
|
|||||||
const Song& song = songs[0];
|
const Song& song = songs[0];
|
||||||
EXPECT_EQ("Foo", song.title());
|
EXPECT_EQ("Foo", song.title());
|
||||||
EXPECT_EQ("Bar", song.artist());
|
EXPECT_EQ("Bar", song.artist());
|
||||||
EXPECT_EQ("http://example.com/foo.mp3", song.filename());
|
EXPECT_EQ(QUrl("http://example.com/foo.mp3"), song.url());
|
||||||
EXPECT_TRUE(song.is_valid());
|
EXPECT_TRUE(song.is_valid());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -64,8 +64,8 @@ TEST_F(ASXParserTest, ParsesMoreThanOneTrackFromXML) {
|
|||||||
ASXParser parser(NULL);
|
ASXParser parser(NULL);
|
||||||
SongList songs = parser.Load(&buffer);
|
SongList songs = parser.Load(&buffer);
|
||||||
ASSERT_EQ(2, songs.length());
|
ASSERT_EQ(2, songs.length());
|
||||||
EXPECT_EQ("http://example.com/foo.mp3", songs[0].filename());
|
EXPECT_EQ(QUrl("http://example.com/foo.mp3"), songs[0].url());
|
||||||
EXPECT_EQ("http://example.com/bar.mp3", songs[1].filename());
|
EXPECT_EQ(QUrl("http://example.com/bar.mp3"), songs[1].url());
|
||||||
EXPECT_TRUE(songs[0].is_stream());
|
EXPECT_TRUE(songs[0].is_stream());
|
||||||
EXPECT_TRUE(songs[1].is_stream());
|
EXPECT_TRUE(songs[1].is_stream());
|
||||||
}
|
}
|
||||||
@ -90,7 +90,7 @@ TEST_F(ASXParserTest, ParsesBrokenXmlEntities) {
|
|||||||
ASXParser parser(NULL);
|
ASXParser parser(NULL);
|
||||||
SongList songs = parser.Load(&buffer);
|
SongList songs = parser.Load(&buffer);
|
||||||
ASSERT_EQ(1, songs.length());
|
ASSERT_EQ(1, songs.length());
|
||||||
EXPECT_EQ("mms://72.26.204.105/classictrance128k?user=h&pass=xxxxxxxxxxxxxxx", songs[0].filename());
|
EXPECT_EQ(QUrl("mms://72.26.204.105/classictrance128k?user=h&pass=xxxxxxxxxxxxxxx"), songs[0].url());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ASXParserTest, SavesSong) {
|
TEST_F(ASXParserTest, SavesSong) {
|
||||||
@ -99,7 +99,7 @@ TEST_F(ASXParserTest, SavesSong) {
|
|||||||
buffer.open(QIODevice::WriteOnly);
|
buffer.open(QIODevice::WriteOnly);
|
||||||
ASXParser parser(NULL);
|
ASXParser parser(NULL);
|
||||||
Song one;
|
Song one;
|
||||||
one.set_filename("http://www.example.com/foo.mp3");
|
one.set_url(QUrl("http://www.example.com/foo.mp3"));
|
||||||
one.set_filetype(Song::Type_Stream);
|
one.set_filetype(Song::Type_Stream);
|
||||||
one.set_title("foo");
|
one.set_title("foo");
|
||||||
one.set_length_nanosec(123 * kNsecPerSec);
|
one.set_length_nanosec(123 * kNsecPerSec);
|
||||||
@ -123,5 +123,5 @@ TEST_F(ASXParserTest, ParsesSomaFM) {
|
|||||||
ASSERT_EQ(4, songs.count());
|
ASSERT_EQ(4, songs.count());
|
||||||
EXPECT_EQ("SomaFM: Secret Agent", songs[0].title());
|
EXPECT_EQ("SomaFM: Secret Agent", songs[0].title());
|
||||||
EXPECT_EQ("Keep us on the air! Click Support SomaFM above!", songs[0].artist());
|
EXPECT_EQ("Keep us on the air! Click Support SomaFM above!", songs[0].artist());
|
||||||
EXPECT_EQ("http://streamer-ntc-aa03.somafm.com:80/stream/1021", songs[0].filename());
|
EXPECT_EQ(QUrl("http://streamer-ntc-aa03.somafm.com:80/stream/1021"), songs[0].url());
|
||||||
}
|
}
|
||||||
|
@ -151,7 +151,7 @@ TEST_F(CueParserTest, UsesAllMetadataInformation) {
|
|||||||
Song first_song = song_list.at(0);
|
Song first_song = song_list.at(0);
|
||||||
Song second_song = song_list.at(1);
|
Song second_song = song_list.at(1);
|
||||||
|
|
||||||
ASSERT_TRUE(first_song.filename().endsWith("a_file.mp3"));
|
ASSERT_TRUE(first_song.url().toString().endsWith("a_file.mp3"));
|
||||||
ASSERT_EQ("Un soffio caldo", first_song.title());
|
ASSERT_EQ("Un soffio caldo", first_song.title());
|
||||||
ASSERT_EQ("Album", first_song.album());
|
ASSERT_EQ("Album", first_song.album());
|
||||||
ASSERT_EQ("Zucchero", first_song.artist());
|
ASSERT_EQ("Zucchero", first_song.artist());
|
||||||
@ -161,7 +161,7 @@ TEST_F(CueParserTest, UsesAllMetadataInformation) {
|
|||||||
ASSERT_EQ(second_song.beginning_nanosec() - first_song.beginning_nanosec(), first_song.length_nanosec());
|
ASSERT_EQ(second_song.beginning_nanosec() - first_song.beginning_nanosec(), first_song.length_nanosec());
|
||||||
ASSERT_EQ(1, first_song.track());
|
ASSERT_EQ(1, first_song.track());
|
||||||
|
|
||||||
ASSERT_TRUE(second_song.filename().endsWith("a_file.mp3"));
|
ASSERT_TRUE(second_song.url().toString().endsWith("a_file.mp3"));
|
||||||
ASSERT_EQ("Hey you!", second_song.title());
|
ASSERT_EQ("Hey you!", second_song.title());
|
||||||
ASSERT_EQ("Album", second_song.album());
|
ASSERT_EQ("Album", second_song.album());
|
||||||
ASSERT_EQ("Zucchero himself", second_song.artist());
|
ASSERT_EQ("Zucchero himself", second_song.artist());
|
||||||
@ -189,7 +189,7 @@ TEST_F(CueParserTest, AcceptsMultipleFileBasedCues) {
|
|||||||
Song fourth_song = song_list.at(3);
|
Song fourth_song = song_list.at(3);
|
||||||
Song fifth_song = song_list.at(4);
|
Song fifth_song = song_list.at(4);
|
||||||
|
|
||||||
ASSERT_TRUE(first_song.filename().endsWith("files/longer_one.mp3"));
|
ASSERT_TRUE(first_song.url().toString().endsWith("files/longer_one.mp3"));
|
||||||
ASSERT_EQ("A1Song1", first_song.title());
|
ASSERT_EQ("A1Song1", first_song.title());
|
||||||
ASSERT_EQ("Artist One Album", first_song.album());
|
ASSERT_EQ("Artist One Album", first_song.album());
|
||||||
ASSERT_EQ("Artist One", first_song.artist());
|
ASSERT_EQ("Artist One", first_song.artist());
|
||||||
@ -199,7 +199,7 @@ TEST_F(CueParserTest, AcceptsMultipleFileBasedCues) {
|
|||||||
ASSERT_EQ(-1, first_song.track());
|
ASSERT_EQ(-1, first_song.track());
|
||||||
ASSERT_EQ("CUEPATH", first_song.cue_path());
|
ASSERT_EQ("CUEPATH", first_song.cue_path());
|
||||||
|
|
||||||
ASSERT_TRUE(second_song.filename().endsWith("files/longer_one.mp3"));
|
ASSERT_TRUE(second_song.url().toString().endsWith("files/longer_one.mp3"));
|
||||||
ASSERT_EQ("A1Song2", second_song.title());
|
ASSERT_EQ("A1Song2", second_song.title());
|
||||||
ASSERT_EQ("Artist One Album", second_song.album());
|
ASSERT_EQ("Artist One Album", second_song.album());
|
||||||
ASSERT_EQ("Artist One", second_song.artist());
|
ASSERT_EQ("Artist One", second_song.artist());
|
||||||
@ -207,7 +207,7 @@ TEST_F(CueParserTest, AcceptsMultipleFileBasedCues) {
|
|||||||
ASSERT_EQ(to_nanosec(5, 3, 68), second_song.beginning_nanosec());
|
ASSERT_EQ(to_nanosec(5, 3, 68), second_song.beginning_nanosec());
|
||||||
ASSERT_EQ(-1, second_song.track());
|
ASSERT_EQ(-1, second_song.track());
|
||||||
|
|
||||||
ASSERT_TRUE(third_song.filename().endsWith("files/longer_two_p1.mp3"));
|
ASSERT_TRUE(third_song.url().toString().endsWith("files/longer_two_p1.mp3"));
|
||||||
ASSERT_EQ("A2P1Song1", third_song.title());
|
ASSERT_EQ("A2P1Song1", third_song.title());
|
||||||
ASSERT_EQ("Artist Two Album", third_song.album());
|
ASSERT_EQ("Artist Two Album", third_song.album());
|
||||||
ASSERT_EQ("Artist X", third_song.artist());
|
ASSERT_EQ("Artist X", third_song.artist());
|
||||||
@ -217,7 +217,7 @@ TEST_F(CueParserTest, AcceptsMultipleFileBasedCues) {
|
|||||||
ASSERT_EQ(-1, third_song.track());
|
ASSERT_EQ(-1, third_song.track());
|
||||||
ASSERT_EQ("CUEPATH", third_song.cue_path());
|
ASSERT_EQ("CUEPATH", third_song.cue_path());
|
||||||
|
|
||||||
ASSERT_TRUE(fourth_song.filename().endsWith("files/longer_two_p1.mp3"));
|
ASSERT_TRUE(fourth_song.url().toString().endsWith("files/longer_two_p1.mp3"));
|
||||||
ASSERT_EQ("A2P1Song2", fourth_song.title());
|
ASSERT_EQ("A2P1Song2", fourth_song.title());
|
||||||
ASSERT_EQ("Artist Two Album", fourth_song.album());
|
ASSERT_EQ("Artist Two Album", fourth_song.album());
|
||||||
ASSERT_EQ("Artist Two", fourth_song.artist());
|
ASSERT_EQ("Artist Two", fourth_song.artist());
|
||||||
@ -225,7 +225,7 @@ TEST_F(CueParserTest, AcceptsMultipleFileBasedCues) {
|
|||||||
ASSERT_EQ(to_nanosec(4, 0, 13), fourth_song.beginning_nanosec());
|
ASSERT_EQ(to_nanosec(4, 0, 13), fourth_song.beginning_nanosec());
|
||||||
ASSERT_EQ(-1, fourth_song.track());
|
ASSERT_EQ(-1, fourth_song.track());
|
||||||
|
|
||||||
ASSERT_TRUE(fifth_song.filename().endsWith("files/longer_two_p2.mp3"));
|
ASSERT_TRUE(fifth_song.url().toString().endsWith("files/longer_two_p2.mp3"));
|
||||||
ASSERT_EQ("A2P2Song1", fifth_song.title());
|
ASSERT_EQ("A2P2Song1", fifth_song.title());
|
||||||
ASSERT_EQ("Artist Two Album", fifth_song.album());
|
ASSERT_EQ("Artist Two Album", fifth_song.album());
|
||||||
ASSERT_EQ("Artist Two", fifth_song.artist());
|
ASSERT_EQ("Artist Two", fifth_song.artist());
|
||||||
@ -253,7 +253,7 @@ TEST_F(CueParserTest, SkipsBrokenSongsInMultipleFileBasedCues) {
|
|||||||
Song fourth_song = song_list.at(3);
|
Song fourth_song = song_list.at(3);
|
||||||
|
|
||||||
// A* - broken song in the middle
|
// A* - broken song in the middle
|
||||||
ASSERT_TRUE(first_song.filename().endsWith("file1.mp3"));
|
ASSERT_TRUE(first_song.url().toString().endsWith("file1.mp3"));
|
||||||
ASSERT_EQ("Artist One", first_song.artist());
|
ASSERT_EQ("Artist One", first_song.artist());
|
||||||
ASSERT_EQ("Artist One Album", first_song.album());
|
ASSERT_EQ("Artist One Album", first_song.album());
|
||||||
ASSERT_EQ("A1", first_song.title());
|
ASSERT_EQ("A1", first_song.title());
|
||||||
@ -261,7 +261,7 @@ TEST_F(CueParserTest, SkipsBrokenSongsInMultipleFileBasedCues) {
|
|||||||
ASSERT_EQ(second_song.beginning_nanosec() - first_song.beginning_nanosec(), first_song.length_nanosec());
|
ASSERT_EQ(second_song.beginning_nanosec() - first_song.beginning_nanosec(), first_song.length_nanosec());
|
||||||
ASSERT_EQ(-1, first_song.track());
|
ASSERT_EQ(-1, first_song.track());
|
||||||
|
|
||||||
ASSERT_TRUE(second_song.filename().endsWith("file1.mp3"));
|
ASSERT_TRUE(second_song.url().toString().endsWith("file1.mp3"));
|
||||||
ASSERT_EQ("Artist One", second_song.artist());
|
ASSERT_EQ("Artist One", second_song.artist());
|
||||||
ASSERT_EQ("Artist One Album", second_song.album());
|
ASSERT_EQ("Artist One Album", second_song.album());
|
||||||
ASSERT_EQ("A3", second_song.title());
|
ASSERT_EQ("A3", second_song.title());
|
||||||
@ -271,7 +271,7 @@ TEST_F(CueParserTest, SkipsBrokenSongsInMultipleFileBasedCues) {
|
|||||||
// all B* songs are broken
|
// all B* songs are broken
|
||||||
|
|
||||||
// C* - broken song at the end
|
// C* - broken song at the end
|
||||||
ASSERT_TRUE(third_song.filename().endsWith("file3.mp3"));
|
ASSERT_TRUE(third_song.url().toString().endsWith("file3.mp3"));
|
||||||
ASSERT_EQ("Artist Three", third_song.artist());
|
ASSERT_EQ("Artist Three", third_song.artist());
|
||||||
ASSERT_EQ("Artist Three Album", third_song.album());
|
ASSERT_EQ("Artist Three Album", third_song.album());
|
||||||
ASSERT_EQ("C1", third_song.title());
|
ASSERT_EQ("C1", third_song.title());
|
||||||
@ -279,7 +279,7 @@ TEST_F(CueParserTest, SkipsBrokenSongsInMultipleFileBasedCues) {
|
|||||||
ASSERT_EQ(-1, third_song.track());
|
ASSERT_EQ(-1, third_song.track());
|
||||||
|
|
||||||
// D* - broken song at the beginning
|
// D* - broken song at the beginning
|
||||||
ASSERT_TRUE(fourth_song.filename().endsWith("file4.mp3"));
|
ASSERT_TRUE(fourth_song.url().toString().endsWith("file4.mp3"));
|
||||||
ASSERT_EQ("Artist Four", fourth_song.artist());
|
ASSERT_EQ("Artist Four", fourth_song.artist());
|
||||||
ASSERT_EQ("Artist Four Album", fourth_song.album());
|
ASSERT_EQ("Artist Four Album", fourth_song.album());
|
||||||
ASSERT_EQ("D2", fourth_song.title());
|
ASSERT_EQ("D2", fourth_song.title());
|
||||||
@ -302,14 +302,14 @@ TEST_F(CueParserTest, SkipsDataFiles) {
|
|||||||
Song first_song = song_list.at(0);
|
Song first_song = song_list.at(0);
|
||||||
Song second_song = song_list.at(1);
|
Song second_song = song_list.at(1);
|
||||||
|
|
||||||
ASSERT_TRUE(first_song.filename().endsWith("file1.mp3"));
|
ASSERT_TRUE(first_song.url().toString().endsWith("file1.mp3"));
|
||||||
ASSERT_EQ("Artist One", first_song.artist());
|
ASSERT_EQ("Artist One", first_song.artist());
|
||||||
ASSERT_EQ("Artist One Album", first_song.album());
|
ASSERT_EQ("Artist One Album", first_song.album());
|
||||||
ASSERT_EQ("A1", first_song.title());
|
ASSERT_EQ("A1", first_song.title());
|
||||||
ASSERT_EQ(to_nanosec(0, 1, 0), first_song.beginning_nanosec());
|
ASSERT_EQ(to_nanosec(0, 1, 0), first_song.beginning_nanosec());
|
||||||
ASSERT_EQ(-1, first_song.track());
|
ASSERT_EQ(-1, first_song.track());
|
||||||
|
|
||||||
ASSERT_TRUE(second_song.filename().endsWith("file4.mp3"));
|
ASSERT_TRUE(second_song.url().toString().endsWith("file4.mp3"));
|
||||||
ASSERT_EQ("Artist Four", second_song.artist());
|
ASSERT_EQ("Artist Four", second_song.artist());
|
||||||
ASSERT_EQ("Artist Four Album", second_song.album());
|
ASSERT_EQ("Artist Four Album", second_song.album());
|
||||||
ASSERT_EQ("D1", second_song.title());
|
ASSERT_EQ("D1", second_song.title());
|
||||||
|
@ -46,7 +46,7 @@ class LibraryBackendTest : public ::testing::Test {
|
|||||||
// Returns a valid song with all the required fields set
|
// Returns a valid song with all the required fields set
|
||||||
Song ret;
|
Song ret;
|
||||||
ret.set_directory_id(directory_id);
|
ret.set_directory_id(directory_id);
|
||||||
ret.set_filename("foo.mp3");
|
ret.set_url(QUrl::fromLocalFile("foo.mp3"));
|
||||||
ret.set_mtime(1);
|
ret.set_mtime(1);
|
||||||
ret.set_ctime(1);
|
ret.set_ctime(1);
|
||||||
ret.set_filesize(1);
|
ret.set_filesize(1);
|
||||||
@ -109,7 +109,7 @@ TEST_F(LibraryBackendTest, AddInvalidSong) {
|
|||||||
backend_->AddOrUpdateSongs(SongList() << s);
|
backend_->AddOrUpdateSongs(SongList() << s);
|
||||||
ASSERT_EQ(1, spy.count()); spy.takeFirst();
|
ASSERT_EQ(1, spy.count()); spy.takeFirst();
|
||||||
|
|
||||||
s.set_filename("foo");
|
s.set_url(QUrl::fromLocalFile("foo"));
|
||||||
backend_->AddOrUpdateSongs(SongList() << s);
|
backend_->AddOrUpdateSongs(SongList() << s);
|
||||||
ASSERT_EQ(1, spy.count()); spy.takeFirst();
|
ASSERT_EQ(1, spy.count()); spy.takeFirst();
|
||||||
|
|
||||||
|
@ -52,7 +52,7 @@ class LibraryModelTest : public ::testing::Test {
|
|||||||
song.set_directory_id(1);
|
song.set_directory_id(1);
|
||||||
if (song.mtime() == -1) song.set_mtime(1);
|
if (song.mtime() == -1) song.set_mtime(1);
|
||||||
if (song.ctime() == -1) song.set_ctime(1);
|
if (song.ctime() == -1) song.set_ctime(1);
|
||||||
if (song.filename().isNull()) song.set_filename("/tmp/foo");
|
if (song.url().isEmpty()) song.set_url(QUrl("file:///tmp/foo"));
|
||||||
if (song.filesize() == -1) song.set_filesize(1);
|
if (song.filesize() == -1) song.set_filesize(1);
|
||||||
|
|
||||||
if (!added_dir_) {
|
if (!added_dir_) {
|
||||||
|
@ -56,10 +56,10 @@ TEST_F(M3UParserTest, ParsesTrackLocation) {
|
|||||||
taglib_.ExpectCall(temp.fileName(), "foo", "bar", "baz");
|
taglib_.ExpectCall(temp.fileName(), "foo", "bar", "baz");
|
||||||
Song song(&taglib_);
|
Song song(&taglib_);
|
||||||
QString line(temp.fileName());
|
QString line(temp.fileName());
|
||||||
ASSERT_TRUE(parser_.ParseTrackLocation(line, QDir(), &song));
|
parser_.LoadSong(line, 0, QDir(), &song);
|
||||||
ASSERT_EQ(temp.fileName(), song.filename());
|
ASSERT_EQ(QUrl::fromLocalFile(temp.fileName()), song.url());
|
||||||
|
|
||||||
song.InitFromFile(song.filename(), -1);
|
song.InitFromFile(song.url().toLocalFile(), -1);
|
||||||
|
|
||||||
EXPECT_EQ("foo", song.title());
|
EXPECT_EQ("foo", song.title());
|
||||||
EXPECT_EQ("bar", song.artist());
|
EXPECT_EQ("bar", song.artist());
|
||||||
@ -74,10 +74,10 @@ TEST_F(M3UParserTest, ParsesTrackLocationRelative) {
|
|||||||
M3UParser parser(NULL);
|
M3UParser parser(NULL);
|
||||||
QString line(info.fileName());
|
QString line(info.fileName());
|
||||||
Song song(&taglib_);
|
Song song(&taglib_);
|
||||||
ASSERT_TRUE(parser.ParseTrackLocation(line, info.dir(), &song));
|
parser.LoadSong(line, 0, info.dir(), &song);
|
||||||
ASSERT_EQ(temp.fileName(), song.filename());
|
ASSERT_EQ(QUrl::fromLocalFile(temp.fileName()), song.url());
|
||||||
|
|
||||||
song.InitFromFile(song.filename(), -1);
|
song.InitFromFile(song.url().toLocalFile(), -1);
|
||||||
|
|
||||||
EXPECT_EQ("foo", song.title());
|
EXPECT_EQ("foo", song.title());
|
||||||
}
|
}
|
||||||
@ -85,8 +85,8 @@ TEST_F(M3UParserTest, ParsesTrackLocationRelative) {
|
|||||||
TEST_F(M3UParserTest, ParsesTrackLocationHttp) {
|
TEST_F(M3UParserTest, ParsesTrackLocationHttp) {
|
||||||
QString line("http://example.com/foo/bar.mp3");
|
QString line("http://example.com/foo/bar.mp3");
|
||||||
Song song;
|
Song song;
|
||||||
ASSERT_TRUE(parser_.ParseTrackLocation(line, QDir(), &song));
|
parser_.LoadSong(line, 0, QDir(), &song);
|
||||||
EXPECT_EQ("http://example.com/foo/bar.mp3", song.filename());
|
EXPECT_EQ(QUrl("http://example.com/foo/bar.mp3"), song.url());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(M3UParserTest, ParsesSongsFromDevice) {
|
TEST_F(M3UParserTest, ParsesSongsFromDevice) {
|
||||||
@ -102,8 +102,7 @@ TEST_F(M3UParserTest, ParsesSongsFromDevice) {
|
|||||||
EXPECT_EQ("Some Artist", s.artist());
|
EXPECT_EQ("Some Artist", s.artist());
|
||||||
EXPECT_EQ("Some Title", s.title());
|
EXPECT_EQ("Some Title", s.title());
|
||||||
EXPECT_EQ(123 * kNsecPerSec, s.length_nanosec());
|
EXPECT_EQ(123 * kNsecPerSec, s.length_nanosec());
|
||||||
EXPECT_PRED_FORMAT2(::testing::IsSubstring,
|
EXPECT_EQ(QUrl("http://foo.com/bar/somefile.mp3"), s.url());
|
||||||
"http://foo.com/bar/somefile.mp3", s.filename().toStdString());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(M3UParserTest, ParsesNonExtendedM3U) {
|
TEST_F(M3UParserTest, ParsesNonExtendedM3U) {
|
||||||
@ -114,10 +113,8 @@ TEST_F(M3UParserTest, ParsesNonExtendedM3U) {
|
|||||||
M3UParser parser(NULL);
|
M3UParser parser(NULL);
|
||||||
SongList songs = parser.Load(&buffer, "", QDir("somedir"));
|
SongList songs = parser.Load(&buffer, "", QDir("somedir"));
|
||||||
ASSERT_EQ(2, songs.size());
|
ASSERT_EQ(2, songs.size());
|
||||||
EXPECT_PRED_FORMAT2(::testing::IsSubstring,
|
EXPECT_EQ(QUrl("http://foo.com/bar/somefile.mp3"), songs[0].url());
|
||||||
"http://foo.com/bar/somefile.mp3", songs[0].filename().toStdString());
|
EXPECT_EQ(QUrl("http://baz.com/thing.mp3"), songs[1].url());
|
||||||
EXPECT_PRED_FORMAT2(::testing::IsSubstring,
|
|
||||||
"http://baz.com/thing.mp3", songs[1].filename().toStdString());
|
|
||||||
EXPECT_EQ(-1, songs[0].length_nanosec());
|
EXPECT_EQ(-1, songs[0].length_nanosec());
|
||||||
EXPECT_EQ(-1, songs[1].length_nanosec());
|
EXPECT_EQ(-1, songs[1].length_nanosec());
|
||||||
EXPECT_TRUE(songs[0].artist().isEmpty());
|
EXPECT_TRUE(songs[0].artist().isEmpty());
|
||||||
@ -144,7 +141,7 @@ TEST_F(M3UParserTest, SavesSong) {
|
|||||||
one.set_title("foo");
|
one.set_title("foo");
|
||||||
one.set_artist("bar");
|
one.set_artist("bar");
|
||||||
one.set_length_nanosec(123 * kNsecPerSec);
|
one.set_length_nanosec(123 * kNsecPerSec);
|
||||||
one.set_filename("http://www.example.com/foo.mp3");
|
one.set_url(QUrl("http://www.example.com/foo.mp3"));
|
||||||
SongList songs;
|
SongList songs;
|
||||||
songs << one;
|
songs << one;
|
||||||
M3UParser parser(NULL);
|
M3UParser parser(NULL);
|
||||||
@ -167,5 +164,6 @@ TEST_F(M3UParserTest, ParsesUTF8) {
|
|||||||
EXPECT_EQ(11, songs[0].title().length());
|
EXPECT_EQ(11, songs[0].title().length());
|
||||||
EXPECT_EQ(QString::fromUtf8("Разные"), songs[0].artist());
|
EXPECT_EQ(QString::fromUtf8("Разные"), songs[0].artist());
|
||||||
EXPECT_EQ(QString::fromUtf8("исполнители"), songs[0].title());
|
EXPECT_EQ(QString::fromUtf8("исполнители"), songs[0].title());
|
||||||
EXPECT_EQ(QString::fromUtf8("/foo/Разные/исполнители.mp3"), songs[0].filename());
|
EXPECT_EQ(QUrl::fromLocalFile(QString::fromUtf8("/foo/Разные/исполнители.mp3")),
|
||||||
|
songs[0].url());
|
||||||
}
|
}
|
||||||
|
@ -33,7 +33,7 @@ class MockLibraryBackend : public LibraryBackendInterface {
|
|||||||
MOCK_METHOD1(FindSongsInDirectory, SongList(int));
|
MOCK_METHOD1(FindSongsInDirectory, SongList(int));
|
||||||
MOCK_METHOD1(SubdirsInDirectory, SubdirectoryList(int));
|
MOCK_METHOD1(SubdirsInDirectory, SubdirectoryList(int));
|
||||||
MOCK_METHOD0(GetAllDirectories, DirectoryList());
|
MOCK_METHOD0(GetAllDirectories, DirectoryList());
|
||||||
MOCK_METHOD2(ChangeDirPath, void(int, const QString&));
|
MOCK_METHOD3(ChangeDirPath, void(int, const QString&, const QString&));
|
||||||
|
|
||||||
MOCK_METHOD1(GetAllArtists, QStringList(const QueryOptions&));
|
MOCK_METHOD1(GetAllArtists, QStringList(const QueryOptions&));
|
||||||
MOCK_METHOD1(GetAllArtistsWithAlbums, QStringList(const QueryOptions&));
|
MOCK_METHOD1(GetAllArtistsWithAlbums, QStringList(const QueryOptions&));
|
||||||
@ -51,8 +51,8 @@ class MockLibraryBackend : public LibraryBackendInterface {
|
|||||||
|
|
||||||
MOCK_METHOD1(GetSongById, Song(int));
|
MOCK_METHOD1(GetSongById, Song(int));
|
||||||
|
|
||||||
MOCK_METHOD1(GetSongsByFilename, SongList(const QString&));
|
MOCK_METHOD1(GetSongsByUrl, SongList(const QUrl&));
|
||||||
MOCK_METHOD2(GetSongByFilename, Song(const QString&, qint64));
|
MOCK_METHOD2(GetSongByUrl, Song(const QUrl&, qint64));
|
||||||
|
|
||||||
MOCK_METHOD1(AddDirectory, void(const QString&));
|
MOCK_METHOD1(AddDirectory, void(const QString&));
|
||||||
MOCK_METHOD1(RemoveDirectory, void(const Directory&));
|
MOCK_METHOD1(RemoveDirectory, void(const Directory&));
|
||||||
|
@ -52,7 +52,7 @@ TEST_F(OrganiseFormatTest, BasicReplace) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(OrganiseFormatTest, Extension) {
|
TEST_F(OrganiseFormatTest, Extension) {
|
||||||
song_.set_filename("/some/path/filename.mp3");
|
song_.set_url(QUrl("file:///some/path/filename.mp3"));
|
||||||
|
|
||||||
format_.set_format("%extension");
|
format_.set_format("%extension");
|
||||||
ASSERT_TRUE(format_.IsValid());
|
ASSERT_TRUE(format_.IsValid());
|
||||||
|
@ -48,7 +48,7 @@ TEST_F(PLSParserTest, ParseOneTrack) {
|
|||||||
|
|
||||||
SongList songs = parser_.Load(file.get(), "", QDir("/relative/to/"));
|
SongList songs = parser_.Load(file.get(), "", QDir("/relative/to/"));
|
||||||
ASSERT_EQ(1, songs.length());
|
ASSERT_EQ(1, songs.length());
|
||||||
EXPECT_EQ("/relative/to/filename with spaces.mp3", songs[0].filename());
|
EXPECT_EQ(QUrl("file:///relative/to/filename with spaces.mp3"), songs[0].url());
|
||||||
EXPECT_EQ("Title", songs[0].title());
|
EXPECT_EQ("Title", songs[0].title());
|
||||||
EXPECT_EQ(123 * kNsecPerSec, songs[0].length_nanosec());
|
EXPECT_EQ(123 * kNsecPerSec, songs[0].length_nanosec());
|
||||||
}
|
}
|
||||||
@ -58,10 +58,10 @@ TEST_F(PLSParserTest, ParseSomaFM) {
|
|||||||
|
|
||||||
SongList songs = parser_.Load(file.get());
|
SongList songs = parser_.Load(file.get());
|
||||||
ASSERT_EQ(4, songs.length());
|
ASSERT_EQ(4, songs.length());
|
||||||
EXPECT_EQ("http://streamer-dtc-aa05.somafm.com:80/stream/1018", songs[0].filename());
|
EXPECT_EQ(QUrl("http://streamer-dtc-aa05.somafm.com:80/stream/1018"), songs[0].url());
|
||||||
EXPECT_EQ("http://streamer-mtc-aa03.somafm.com:80/stream/1018", songs[1].filename());
|
EXPECT_EQ(QUrl("http://streamer-mtc-aa03.somafm.com:80/stream/1018"), songs[1].url());
|
||||||
EXPECT_EQ("http://streamer-ntc-aa04.somafm.com:80/stream/1018", songs[2].filename());
|
EXPECT_EQ(QUrl("http://streamer-ntc-aa04.somafm.com:80/stream/1018"), songs[2].url());
|
||||||
EXPECT_EQ("http://ice.somafm.com/groovesalad", songs[3].filename());
|
EXPECT_EQ(QUrl("http://ice.somafm.com/groovesalad"), songs[3].url());
|
||||||
EXPECT_EQ("SomaFM: Groove Salad (#1 128k mp3): A nicely chilled plate of ambient beats and grooves.", songs[0].title());
|
EXPECT_EQ("SomaFM: Groove Salad (#1 128k mp3): A nicely chilled plate of ambient beats and grooves.", songs[0].title());
|
||||||
EXPECT_EQ("SomaFM: Groove Salad (#2 128k mp3): A nicely chilled plate of ambient beats and grooves.", songs[1].title());
|
EXPECT_EQ("SomaFM: Groove Salad (#2 128k mp3): A nicely chilled plate of ambient beats and grooves.", songs[1].title());
|
||||||
EXPECT_EQ("SomaFM: Groove Salad (#3 128k mp3): A nicely chilled plate of ambient beats and grooves.", songs[2].title());
|
EXPECT_EQ("SomaFM: Groove Salad (#3 128k mp3): A nicely chilled plate of ambient beats and grooves.", songs[2].title());
|
||||||
@ -74,10 +74,10 @@ TEST_F(PLSParserTest, ParseSomaFM2) {
|
|||||||
|
|
||||||
SongList songs = parser_.Load(file.get());
|
SongList songs = parser_.Load(file.get());
|
||||||
ASSERT_EQ(4, songs.length());
|
ASSERT_EQ(4, songs.length());
|
||||||
EXPECT_EQ("http://streamer-ntc-aa03.somafm.com:80/stream/1021", songs[0].filename());
|
EXPECT_EQ(QUrl("http://streamer-ntc-aa03.somafm.com:80/stream/1021"), songs[0].url());
|
||||||
EXPECT_EQ("http://streamer-mtc-aa04.somafm.com:80/stream/1021", songs[1].filename());
|
EXPECT_EQ(QUrl("http://streamer-mtc-aa04.somafm.com:80/stream/1021"), songs[1].url());
|
||||||
EXPECT_EQ("http://streamer-dtc-aa05.somafm.com:80/stream/1021", songs[2].filename());
|
EXPECT_EQ(QUrl("http://streamer-dtc-aa05.somafm.com:80/stream/1021"), songs[2].url());
|
||||||
EXPECT_EQ("http://ice.somafm.com/secretagent", songs[3].filename());
|
EXPECT_EQ(QUrl("http://ice.somafm.com/secretagent"), songs[3].url());
|
||||||
EXPECT_EQ("SomaFM: Secret Agent (#1 128k mp3): The soundtrack for your stylish, mysterious, dangerous life. For Spies and PIs too!", songs[0].title());
|
EXPECT_EQ("SomaFM: Secret Agent (#1 128k mp3): The soundtrack for your stylish, mysterious, dangerous life. For Spies and PIs too!", songs[0].title());
|
||||||
EXPECT_EQ("SomaFM: Secret Agent (#2 128k mp3): The soundtrack for your stylish, mysterious, dangerous life. For Spies and PIs too!", songs[1].title());
|
EXPECT_EQ("SomaFM: Secret Agent (#2 128k mp3): The soundtrack for your stylish, mysterious, dangerous life. For Spies and PIs too!", songs[1].title());
|
||||||
EXPECT_EQ("SomaFM: Secret Agent (#3 128k mp3): The soundtrack for your stylish, mysterious, dangerous life. For Spies and PIs too!", songs[2].title());
|
EXPECT_EQ("SomaFM: Secret Agent (#3 128k mp3): The soundtrack for your stylish, mysterious, dangerous life. For Spies and PIs too!", songs[2].title());
|
||||||
@ -87,11 +87,11 @@ TEST_F(PLSParserTest, ParseSomaFM2) {
|
|||||||
|
|
||||||
TEST_F(PLSParserTest, SaveAndLoad) {
|
TEST_F(PLSParserTest, SaveAndLoad) {
|
||||||
Song one;
|
Song one;
|
||||||
one.set_filename("http://www.example.com/foo.mp3");
|
one.set_url(QUrl("http://www.example.com/foo.mp3"));
|
||||||
one.set_title("Foo, with, some, commas");
|
one.set_title("Foo, with, some, commas");
|
||||||
|
|
||||||
Song two;
|
Song two;
|
||||||
two.set_filename("relative/bar.mp3");
|
two.set_url(QUrl("relative/bar.mp3"));
|
||||||
two.set_title("Bar");
|
two.set_title("Bar");
|
||||||
two.set_length_nanosec(123 * kNsecPerSec);
|
two.set_length_nanosec(123 * kNsecPerSec);
|
||||||
|
|
||||||
@ -106,8 +106,8 @@ TEST_F(PLSParserTest, SaveAndLoad) {
|
|||||||
songs = parser_.Load(&temp, "", QDir("/meep"));
|
songs = parser_.Load(&temp, "", QDir("/meep"));
|
||||||
|
|
||||||
ASSERT_EQ(2, songs.count());
|
ASSERT_EQ(2, songs.count());
|
||||||
EXPECT_EQ(one.filename(), songs[0].filename());
|
EXPECT_EQ(one.url(), songs[0].url());
|
||||||
EXPECT_EQ("/meep/relative/bar.mp3", songs[1].filename());
|
EXPECT_EQ(QUrl("file:///meep/relative/bar.mp3"), songs[1].url());
|
||||||
EXPECT_EQ(one.title(), songs[0].title());
|
EXPECT_EQ(one.title(), songs[0].title());
|
||||||
EXPECT_EQ(two.title(), songs[1].title());
|
EXPECT_EQ(two.title(), songs[1].title());
|
||||||
EXPECT_EQ(one.length_nanosec(), songs[0].length_nanosec());
|
EXPECT_EQ(one.length_nanosec(), songs[0].length_nanosec());
|
||||||
|
@ -55,7 +55,7 @@ protected:
|
|||||||
loader_->set_timeout(20000);
|
loader_->set_timeout(20000);
|
||||||
|
|
||||||
// the thing we return is not really important
|
// the thing we return is not really important
|
||||||
EXPECT_CALL(*library_.get(), GetSongByFilename(_, _)).WillRepeatedly(Return(Song()));
|
EXPECT_CALL(*library_.get(), GetSongByUrl(_, _)).WillRepeatedly(Return(Song()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void LoadLocalDirectory(const QString& dir);
|
void LoadLocalDirectory(const QString& dir);
|
||||||
@ -191,7 +191,7 @@ TEST_F(SongLoaderTest, LoadRemoteMp3) {
|
|||||||
|
|
||||||
// Check the song got loaded
|
// Check the song got loaded
|
||||||
ASSERT_EQ(1, loader_->songs().count());
|
ASSERT_EQ(1, loader_->songs().count());
|
||||||
EXPECT_EQ(QString(kRemoteUrl) + "/beep.mp3", loader_->songs()[0].filename());
|
EXPECT_EQ(QUrl(QString(kRemoteUrl) + "/beep.mp3"), loader_->songs()[0].url());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(SongLoaderTest, LoadRemote404) {
|
TEST_F(SongLoaderTest, LoadRemote404) {
|
||||||
@ -231,7 +231,7 @@ TEST_F(SongLoaderTest, LoadRemotePls) {
|
|||||||
ASSERT_EQ(4, loader_->songs().count());
|
ASSERT_EQ(4, loader_->songs().count());
|
||||||
EXPECT_EQ("SomaFM: Groove Salad (#3 128k mp3): A nicely chilled plate of ambient beats and grooves.",
|
EXPECT_EQ("SomaFM: Groove Salad (#3 128k mp3): A nicely chilled plate of ambient beats and grooves.",
|
||||||
loader_->songs()[2].title());
|
loader_->songs()[2].title());
|
||||||
EXPECT_EQ("http://ice.somafm.com/groovesalad", loader_->songs()[3].filename());
|
EXPECT_EQ(QUrl("http://ice.somafm.com/groovesalad"), loader_->songs()[3].url());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(SongLoaderTest, LoadRemotePlainText) {
|
TEST_F(SongLoaderTest, LoadRemotePlainText) {
|
||||||
@ -268,8 +268,8 @@ TEST_F(SongLoaderTest, LoadRemotePlainM3U) {
|
|||||||
EXPECT_EQ(true, spy[0][0].toBool());
|
EXPECT_EQ(true, spy[0][0].toBool());
|
||||||
|
|
||||||
ASSERT_EQ(2, loader_->songs().count());
|
ASSERT_EQ(2, loader_->songs().count());
|
||||||
EXPECT_EQ("http://www.example.com/one.mp3", loader_->songs()[0].filename());
|
EXPECT_EQ(QUrl("http://www.example.com/one.mp3"), loader_->songs()[0].url());
|
||||||
EXPECT_EQ("http://www.example.com/two.mp3", loader_->songs()[1].filename());
|
EXPECT_EQ(QUrl("http://www.example.com/two.mp3"), loader_->songs()[1].url());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(SongLoaderTest, LoadLocalDirectory) {
|
TEST_F(SongLoaderTest, LoadLocalDirectory) {
|
||||||
|
@ -38,7 +38,7 @@ class SongPlaylistItemTest : public ::testing::TestWithParam<const char*> {
|
|||||||
absolute_file_name_ = QFileInfo(temp_file_.fileName()).absoluteFilePath();
|
absolute_file_name_ = QFileInfo(temp_file_.fileName()).absoluteFilePath();
|
||||||
|
|
||||||
song_.Init("Title", "Artist", "Album", 123);
|
song_.Init("Title", "Artist", "Album", 123);
|
||||||
song_.set_filename(absolute_file_name_);
|
song_.set_url(QUrl::fromLocalFile(absolute_file_name_));
|
||||||
|
|
||||||
item_.reset(new SongPlaylistItem(song_));
|
item_.reset(new SongPlaylistItem(song_));
|
||||||
|
|
||||||
|
@ -50,6 +50,10 @@ void PrintTo(const ::QVariant& var, std::ostream& os) {
|
|||||||
os << var.toString().toStdString();
|
os << var.toString().toStdString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PrintTo(const ::QUrl& url, std::ostream& os) {
|
||||||
|
os << url.toString().toStdString();
|
||||||
|
}
|
||||||
|
|
||||||
TemporaryResource::TemporaryResource(const QString& filename) {
|
TemporaryResource::TemporaryResource(const QString& filename) {
|
||||||
setFileTemplate(QDir::tempPath() + "/clementine_test-XXXXXX." +
|
setFileTemplate(QDir::tempPath() + "/clementine_test-XXXXXX." +
|
||||||
filename.section('.', -1, -1));
|
filename.section('.', -1, -1));
|
||||||
|
@ -46,6 +46,7 @@ std::ostream& operator <<(std::ostream& stream, const QList<T>& list) {
|
|||||||
|
|
||||||
void PrintTo(const ::QString& str, std::ostream& os);
|
void PrintTo(const ::QString& str, std::ostream& os);
|
||||||
void PrintTo(const ::QVariant& var, std::ostream& os);
|
void PrintTo(const ::QVariant& var, std::ostream& os);
|
||||||
|
void PrintTo(const ::QUrl& url, std::ostream& os);
|
||||||
|
|
||||||
#define EXPOSE_SIGNAL0(n) \
|
#define EXPOSE_SIGNAL0(n) \
|
||||||
void Emit##n() { emit n(); }
|
void Emit##n() { emit n(); }
|
||||||
|
@ -49,7 +49,7 @@ TEST_F(XSPFParserTest, ParsesOneTrackFromXML) {
|
|||||||
EXPECT_EQ("Foo", song.title());
|
EXPECT_EQ("Foo", song.title());
|
||||||
EXPECT_EQ("Bar", song.artist());
|
EXPECT_EQ("Bar", song.artist());
|
||||||
EXPECT_EQ("Baz", song.album());
|
EXPECT_EQ("Baz", song.album());
|
||||||
EXPECT_EQ("http://example.com/foo.mp3", song.filename());
|
EXPECT_EQ(QUrl("http://example.com/foo.mp3"), song.url());
|
||||||
EXPECT_EQ(60 * kNsecPerSec, song.length_nanosec());
|
EXPECT_EQ(60 * kNsecPerSec, song.length_nanosec());
|
||||||
EXPECT_TRUE(song.is_valid());
|
EXPECT_TRUE(song.is_valid());
|
||||||
}
|
}
|
||||||
@ -69,8 +69,8 @@ TEST_F(XSPFParserTest, ParsesMoreThanOneTrackFromXML) {
|
|||||||
XSPFParser parser(NULL);
|
XSPFParser parser(NULL);
|
||||||
SongList songs = parser.Load(&buffer);
|
SongList songs = parser.Load(&buffer);
|
||||||
ASSERT_EQ(2, songs.length());
|
ASSERT_EQ(2, songs.length());
|
||||||
EXPECT_EQ("http://example.com/foo.mp3", songs[0].filename());
|
EXPECT_EQ(QUrl("http://example.com/foo.mp3"), songs[0].url());
|
||||||
EXPECT_EQ("http://example.com/bar.mp3", songs[1].filename());
|
EXPECT_EQ(QUrl("http://example.com/bar.mp3"), songs[1].url());
|
||||||
EXPECT_TRUE(songs[0].is_stream());
|
EXPECT_TRUE(songs[0].is_stream());
|
||||||
EXPECT_TRUE(songs[1].is_stream());
|
EXPECT_TRUE(songs[1].is_stream());
|
||||||
}
|
}
|
||||||
@ -100,7 +100,7 @@ TEST_F(XSPFParserTest, SavesSong) {
|
|||||||
buffer.open(QIODevice::WriteOnly);
|
buffer.open(QIODevice::WriteOnly);
|
||||||
XSPFParser parser(NULL);
|
XSPFParser parser(NULL);
|
||||||
Song one;
|
Song one;
|
||||||
one.set_filename("http://www.example.com/foo.mp3");
|
one.set_url(QUrl("http://www.example.com/foo.mp3"));
|
||||||
one.set_filetype(Song::Type_Stream);
|
one.set_filetype(Song::Type_Stream);
|
||||||
one.set_title("foo");
|
one.set_title("foo");
|
||||||
one.set_length_nanosec(123 * kNsecPerSec);
|
one.set_length_nanosec(123 * kNsecPerSec);
|
||||||
@ -121,7 +121,7 @@ TEST_F(XSPFParserTest, SavesLocalFile) {
|
|||||||
buffer.open(QIODevice::WriteOnly);
|
buffer.open(QIODevice::WriteOnly);
|
||||||
XSPFParser parser(NULL);
|
XSPFParser parser(NULL);
|
||||||
Song one;
|
Song one;
|
||||||
one.set_filename("/bar/foo.mp3");
|
one.set_url(QUrl("file:///bar/foo.mp3"));
|
||||||
one.set_filetype(Song::Type_Mpeg);
|
one.set_filetype(Song::Type_Mpeg);
|
||||||
one.set_title("foo");
|
one.set_title("foo");
|
||||||
one.set_length_nanosec(123 * kNsecPerSec);
|
one.set_length_nanosec(123 * kNsecPerSec);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user