Change the fields in Song from seconds to nanoseconds
This commit is contained in:
parent
37618dae96
commit
507c5e2632
|
@ -298,5 +298,6 @@
|
||||||
<file>schema/schema-26.sql</file>
|
<file>schema/schema-26.sql</file>
|
||||||
<file>pythonstartup.py</file>
|
<file>pythonstartup.py</file>
|
||||||
<file>schema/schema-27.sql</file>
|
<file>schema/schema-27.sql</file>
|
||||||
|
<file>schema/schema-28.sql</file>
|
||||||
</qresource>
|
</qresource>
|
||||||
</RCC>
|
</RCC>
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
UPDATE %allsongstables SET length=length*1e9, beginning=beginning*1e9;
|
||||||
|
|
||||||
|
UPDATE schema_version SET version=28;
|
|
@ -31,7 +31,7 @@
|
||||||
#include <QVariant>
|
#include <QVariant>
|
||||||
|
|
||||||
const char* Database::kDatabaseFilename = "clementine.db";
|
const char* Database::kDatabaseFilename = "clementine.db";
|
||||||
const int Database::kSchemaVersion = 27;
|
const int Database::kSchemaVersion = 28;
|
||||||
const char* Database::kMagicAllSongsTables = "%allsongstables";
|
const char* Database::kMagicAllSongsTables = "%allsongstables";
|
||||||
|
|
||||||
int Database::sNextConnectionId = 1;
|
int Database::sNextConnectionId = 1;
|
||||||
|
|
|
@ -302,8 +302,8 @@ QVariantMap Mpris1::GetMetadata(const Song& song) {
|
||||||
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);
|
||||||
AddMetadata("time", song.length(), &ret);
|
AddMetadata("time", song.length_nanosec() / 1e9, &ret);
|
||||||
AddMetadata("mtime", song.length() * 1000, &ret);
|
AddMetadata("mtime", song.length_nanosec() / 1e6, &ret);
|
||||||
AddMetadata("tracknumber", song.track(), &ret);
|
AddMetadata("tracknumber", song.track(), &ret);
|
||||||
AddMetadata("year", song.year(), &ret);
|
AddMetadata("year", song.year(), &ret);
|
||||||
AddMetadata("genre", song.genre(), &ret);
|
AddMetadata("genre", song.genre(), &ret);
|
||||||
|
|
|
@ -131,7 +131,7 @@ public:
|
||||||
|
|
||||||
void VolumeSet(int volume);
|
void VolumeSet(int volume);
|
||||||
int VolumeGet() const;
|
int VolumeGet() const;
|
||||||
void PositionSet(int pos);
|
void PositionSet(int pos_msec);
|
||||||
int PositionGet() const;
|
int PositionGet() const;
|
||||||
QVariantMap GetMetadata() const;
|
QVariantMap GetMetadata() const;
|
||||||
|
|
||||||
|
|
|
@ -295,7 +295,7 @@ void Mpris2::ArtLoaded(const Song& song, const QString& art_uri) {
|
||||||
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_);
|
||||||
AddMetadataAsList("xesam:albumArtist", song.albumartist(), &last_metadata_);
|
AddMetadataAsList("xesam:albumArtist", song.albumartist(), &last_metadata_);
|
||||||
AddMetadata("mpris:length", song.length()*1e6, &last_metadata_);
|
AddMetadata("mpris:length", song.length_nanosec() / 1e3, &last_metadata_);
|
||||||
AddMetadata("xesam:trackNumber", song.track(), &last_metadata_);
|
AddMetadata("xesam:trackNumber", song.track(), &last_metadata_);
|
||||||
AddMetadataAsList("xesam:genre", song.genre(), &last_metadata_);
|
AddMetadataAsList("xesam:genre", song.genre(), &last_metadata_);
|
||||||
AddMetadata("xesam:discNumber", song.disc(), &last_metadata_);
|
AddMetadata("xesam:discNumber", song.disc(), &last_metadata_);
|
||||||
|
@ -325,7 +325,7 @@ void Mpris2::SetVolume(double value) {
|
||||||
}
|
}
|
||||||
|
|
||||||
qlonglong Mpris2::Position() const {
|
qlonglong Mpris2::Position() const {
|
||||||
return mpris1_->player()->PositionGet() / 1e3;
|
return player_->engine()->position_nanosec() / 1e3;
|
||||||
}
|
}
|
||||||
|
|
||||||
double Mpris2::MaximumRate() const {
|
double Mpris2::MaximumRate() const {
|
||||||
|
@ -408,7 +408,7 @@ void Mpris2::SetPosition(const QDBusObjectPath& trackId, qlonglong offset) {
|
||||||
if (CanSeek() && trackId.path() == current_track_id() && offset >= 0) {
|
if (CanSeek() && trackId.path() == current_track_id() && offset >= 0) {
|
||||||
offset *= 1e3;
|
offset *= 1e3;
|
||||||
|
|
||||||
if(offset < player_->GetCurrentItem()->Metadata().length()) {
|
if(offset < player_->GetCurrentItem()->Metadata().length_nanosec()) {
|
||||||
player_->Seek(offset / 1e9);
|
player_->Seek(offset / 1e9);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -136,7 +136,7 @@ QString OrganiseFormat::TagValue(const QString &tag, const Song &song) const {
|
||||||
else if (tag == "track") value = QString::number(song.track());
|
else if (tag == "track") value = QString::number(song.track());
|
||||||
else if (tag == "disc") value = QString::number(song.disc());
|
else if (tag == "disc") value = QString::number(song.disc());
|
||||||
else if (tag == "bpm") value = QString::number(song.bpm());
|
else if (tag == "bpm") value = QString::number(song.bpm());
|
||||||
else if (tag == "length") value = QString::number(song.length());
|
else if (tag == "length") value = QString::number(song.length_nanosec() / 1e9);
|
||||||
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.filename().section('.', -1, -1);
|
||||||
|
|
|
@ -96,8 +96,8 @@ void Player::HandleSpecialLoad(const PlaylistItem::SpecialLoadResult &result) {
|
||||||
return;
|
return;
|
||||||
|
|
||||||
engine_->Play(result.media_url_, stream_change_type_,
|
engine_->Play(result.media_url_, stream_change_type_,
|
||||||
item->Metadata().beginning() * 1e9,
|
item->Metadata().beginning_nanosec(),
|
||||||
item->Metadata().end() * 1e9);
|
item->Metadata().end_nanosec());
|
||||||
|
|
||||||
current_item_ = item;
|
current_item_ = item;
|
||||||
loading_async_ = QUrl();
|
loading_async_ = QUrl();
|
||||||
|
@ -266,8 +266,8 @@ void Player::PlayAt(int index, Engine::TrackChangeType change, bool reshuffle) {
|
||||||
else {
|
else {
|
||||||
loading_async_ = QUrl();
|
loading_async_ = QUrl();
|
||||||
engine_->Play(current_item_->Url(), change,
|
engine_->Play(current_item_->Url(), change,
|
||||||
current_item_->Metadata().beginning() * 1e9,
|
current_item_->Metadata().beginning_nanosec(),
|
||||||
current_item_->Metadata().end() * 1e9);
|
current_item_->Metadata().end_nanosec());
|
||||||
|
|
||||||
#ifdef HAVE_LIBLASTFM
|
#ifdef HAVE_LIBLASTFM
|
||||||
if (lastfm_->IsScrobblingEnabled())
|
if (lastfm_->IsScrobblingEnabled())
|
||||||
|
|
|
@ -201,17 +201,19 @@ Song::Song(FileRefFactory* factory)
|
||||||
factory_(factory) {
|
factory_(factory) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Song::Init(const QString& title, const QString& artist, const QString& album, int length) {
|
void Song::Init(const QString& title, const QString& artist,
|
||||||
|
const QString& album, qint64 length) {
|
||||||
d->valid_ = true;
|
d->valid_ = true;
|
||||||
|
|
||||||
d->title_ = title;
|
d->title_ = title;
|
||||||
d->artist_ = artist;
|
d->artist_ = artist;
|
||||||
d->album_ = album;
|
d->album_ = album;
|
||||||
|
|
||||||
set_length(length);
|
set_length_nanosec(length);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Song::Init(const QString& title, const QString& artist, const QString& album, int beginning, int end) {
|
void Song::Init(const QString& title, const QString& artist,
|
||||||
|
const QString& album, qint64 beginning, qint64 end) {
|
||||||
d->valid_ = true;
|
d->valid_ = true;
|
||||||
|
|
||||||
d->title_ = title;
|
d->title_ = title;
|
||||||
|
@ -378,7 +380,7 @@ void Song::InitFromFile(const QString& filename, int directory_id) {
|
||||||
if (fileref->audioProperties()) {
|
if (fileref->audioProperties()) {
|
||||||
d->bitrate_ = fileref->audioProperties()->bitrate();
|
d->bitrate_ = fileref->audioProperties()->bitrate();
|
||||||
d->samplerate_ = fileref->audioProperties()->sampleRate();
|
d->samplerate_ = fileref->audioProperties()->sampleRate();
|
||||||
set_length(fileref->audioProperties()->length());
|
set_length_nanosec(fileref->audioProperties()->length() * 1e9);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the filetype if we can
|
// Get the filetype if we can
|
||||||
|
@ -475,9 +477,10 @@ 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 toint(n) (q.value(n).isNull() ? -1 : q.value(n).toInt())
|
#define toint(n) (q.value(n).isNull() ? -1 : q.value(n).toInt())
|
||||||
#define tofloat(n) (q.value(n).isNull() ? -1 : q.value(n).toDouble())
|
#define tolonglong(n) (q.value(n).isNull() ? -1 : q.value(n).toLongLong())
|
||||||
|
#define tofloat(n) (q.value(n).isNull() ? -1 : q.value(n).toDouble())
|
||||||
|
|
||||||
d->id_ = toint(col + 0);
|
d->id_ = toint(col + 0);
|
||||||
d->title_ = tostr(col + 1);
|
d->title_ = tostr(col + 1);
|
||||||
|
@ -523,13 +526,14 @@ void Song::InitFromQuery(const SqlRow& q, int col) {
|
||||||
|
|
||||||
// do not move those statements - beginning must be initialized before
|
// do not move those statements - beginning must be initialized before
|
||||||
// length is!
|
// length is!
|
||||||
d->beginning_ = q.value(col + 32).isNull() ? 0 : q.value(col + 32).toInt();
|
d->beginning_ = q.value(col + 32).isNull() ? 0 : q.value(col + 32).toLongLong();
|
||||||
set_length(toint(col + 33));
|
set_length_nanosec(tolonglong(col + 33));
|
||||||
|
|
||||||
d->cue_path_ = tostr(col + 34);
|
d->cue_path_ = tostr(col + 34);
|
||||||
|
|
||||||
#undef tostr
|
#undef tostr
|
||||||
#undef toint
|
#undef toint
|
||||||
|
#undef tolonglong
|
||||||
#undef tofloat
|
#undef tofloat
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -543,7 +547,7 @@ void Song::InitFromLastFM(const lastfm::Track& track) {
|
||||||
d->artist_ = track.artist();
|
d->artist_ = track.artist();
|
||||||
d->track_ = track.trackNumber();
|
d->track_ = track.trackNumber();
|
||||||
|
|
||||||
set_length(track.duration());
|
set_length_nanosec(track.duration() * 1e9);
|
||||||
}
|
}
|
||||||
#endif // HAVE_LIBLASTFM
|
#endif // HAVE_LIBLASTFM
|
||||||
|
|
||||||
|
@ -563,7 +567,7 @@ void Song::InitFromLastFM(const lastfm::Track& track) {
|
||||||
d->genre_ = QString::fromUtf8(track->genre);
|
d->genre_ = QString::fromUtf8(track->genre);
|
||||||
d->comment_ = QString::fromUtf8(track->comment);
|
d->comment_ = QString::fromUtf8(track->comment);
|
||||||
d->compilation_ = track->compilation;
|
d->compilation_ = track->compilation;
|
||||||
set_length(track->tracklen / 1000);
|
set_length_nanosec(track->tracklen * 1e6);
|
||||||
d->bitrate_ = track->bitrate;
|
d->bitrate_ = track->bitrate;
|
||||||
d->samplerate_ = track->samplerate;
|
d->samplerate_ = track->samplerate;
|
||||||
d->mtime_ = track->time_modified;
|
d->mtime_ = track->time_modified;
|
||||||
|
@ -593,7 +597,7 @@ void Song::InitFromLastFM(const lastfm::Track& track) {
|
||||||
track->genre = strdup(d->genre_.toUtf8().constData());
|
track->genre = strdup(d->genre_.toUtf8().constData());
|
||||||
track->comment = strdup(d->comment_.toUtf8().constData());
|
track->comment = strdup(d->comment_.toUtf8().constData());
|
||||||
track->compilation = d->compilation_;
|
track->compilation = d->compilation_;
|
||||||
track->tracklen = length() * 1000;
|
track->tracklen = length_nanosec() / 1e6;
|
||||||
track->bitrate = d->bitrate_;
|
track->bitrate = d->bitrate_;
|
||||||
track->samplerate = d->samplerate_;
|
track->samplerate = d->samplerate_;
|
||||||
track->time_modified = d->mtime_;
|
track->time_modified = d->mtime_;
|
||||||
|
@ -622,7 +626,7 @@ void Song::InitFromLastFM(const lastfm::Track& track) {
|
||||||
d->basefilename_ = d->filename_;
|
d->basefilename_ = d->filename_;
|
||||||
|
|
||||||
d->track_ = track->tracknumber;
|
d->track_ = track->tracknumber;
|
||||||
set_length(track->duration / 1000);
|
set_length_nanosec(track->duration * 1e6);
|
||||||
d->samplerate_ = track->samplerate;
|
d->samplerate_ = track->samplerate;
|
||||||
d->bitrate_ = track->bitrate;
|
d->bitrate_ = track->bitrate;
|
||||||
d->filesize_ = track->filesize;
|
d->filesize_ = track->filesize;
|
||||||
|
@ -662,7 +666,7 @@ void Song::InitFromLastFM(const lastfm::Track& track) {
|
||||||
track->filename = strdup(d->basefilename_.toUtf8().constData());
|
track->filename = strdup(d->basefilename_.toUtf8().constData());
|
||||||
|
|
||||||
track->tracknumber = d->track_;
|
track->tracknumber = d->track_;
|
||||||
track->duration = length() * 1000;
|
track->duration = length_nanosec() / 1e6;
|
||||||
track->samplerate = d->samplerate_;
|
track->samplerate = d->samplerate_;
|
||||||
track->nochannels = 0;
|
track->nochannels = 0;
|
||||||
track->wavecodec = 0;
|
track->wavecodec = 0;
|
||||||
|
@ -796,7 +800,7 @@ void Song::InitFromLastFM(const lastfm::Track& track) {
|
||||||
d->filename_ = item_value.toString();
|
d->filename_ = item_value.toString();
|
||||||
|
|
||||||
else if (wcscmp(name, g_wszWMDMDuration) == 0)
|
else if (wcscmp(name, g_wszWMDMDuration) == 0)
|
||||||
set_length(item_value.toULongLong() / 10000000ll);
|
set_length(item_value.toULongLong() * 1e2);
|
||||||
|
|
||||||
else if (wcscmp(name, L"WMDM/FileSize") == 0)
|
else if (wcscmp(name, L"WMDM/FileSize") == 0)
|
||||||
d->filesize_ = item_value.toULongLong();
|
d->filesize_ = item_value.toULongLong();
|
||||||
|
@ -894,7 +898,7 @@ void Song::InitFromLastFM(const lastfm::Track& track) {
|
||||||
AddWmdmItem(metadata, g_wszWMDMComposer, d->composer_);
|
AddWmdmItem(metadata, g_wszWMDMComposer, d->composer_);
|
||||||
AddWmdmItem(metadata, g_wszWMDMBitrate, d->bitrate_);
|
AddWmdmItem(metadata, g_wszWMDMBitrate, d->bitrate_);
|
||||||
AddWmdmItem(metadata, g_wszWMDMFileName, d->basefilename_);
|
AddWmdmItem(metadata, g_wszWMDMFileName, d->basefilename_);
|
||||||
AddWmdmItem(metadata, g_wszWMDMDuration, qint64(length()) * 10000000ll);
|
AddWmdmItem(metadata, g_wszWMDMDuration, qint64(length_nanosec()) / 1e2);
|
||||||
AddWmdmItem(metadata, L"WMDM/FileSize", d->filesize_);
|
AddWmdmItem(metadata, L"WMDM/FileSize", d->filesize_);
|
||||||
|
|
||||||
WMDM_FORMATCODE format;
|
WMDM_FORMATCODE format;
|
||||||
|
@ -932,7 +936,7 @@ void Song::MergeFromSimpleMetaBundle(const Engine::SimpleMetaBundle &bundle) {
|
||||||
if (!bundle.genre.isEmpty()) d->genre_ = Decode(bundle.genre, codec);
|
if (!bundle.genre.isEmpty()) d->genre_ = Decode(bundle.genre, codec);
|
||||||
if (!bundle.bitrate.isEmpty()) d->bitrate_ = bundle.bitrate.toInt();
|
if (!bundle.bitrate.isEmpty()) d->bitrate_ = bundle.bitrate.toInt();
|
||||||
if (!bundle.samplerate.isEmpty()) d->samplerate_ = bundle.samplerate.toInt();
|
if (!bundle.samplerate.isEmpty()) d->samplerate_ = bundle.samplerate.toInt();
|
||||||
if (!bundle.length.isEmpty()) set_length(bundle.length.toInt());
|
if (!bundle.length.isEmpty()) set_length_nanosec(bundle.length.toLongLong());
|
||||||
if (!bundle.year.isEmpty()) d->year_ = bundle.year.toInt();
|
if (!bundle.year.isEmpty()) d->year_ = bundle.year.toInt();
|
||||||
if (!bundle.tracknr.isEmpty()) d->track_ = bundle.tracknr.toInt();
|
if (!bundle.tracknr.isEmpty()) d->track_ = bundle.tracknr.toInt();
|
||||||
}
|
}
|
||||||
|
@ -984,7 +988,7 @@ void Song::BindToQuery(QSqlQuery *query) const {
|
||||||
query->bindValue(":score", d->score_);
|
query->bindValue(":score", d->score_);
|
||||||
|
|
||||||
query->bindValue(":beginning", d->beginning_);
|
query->bindValue(":beginning", d->beginning_);
|
||||||
query->bindValue(":length", intval(length()));
|
query->bindValue(":length", intval(length_nanosec()));
|
||||||
|
|
||||||
query->bindValue(":cue_path", d->cue_path_);
|
query->bindValue(":cue_path", d->cue_path_);
|
||||||
|
|
||||||
|
@ -1009,7 +1013,7 @@ void Song::ToLastFM(lastfm::Track* track) const {
|
||||||
mtrack.setArtist(d->artist_);
|
mtrack.setArtist(d->artist_);
|
||||||
mtrack.setAlbum(d->album_);
|
mtrack.setAlbum(d->album_);
|
||||||
mtrack.setTitle(d->title_);
|
mtrack.setTitle(d->title_);
|
||||||
mtrack.setDuration(length());
|
mtrack.setDuration(length_nanosec() / 1e9);
|
||||||
mtrack.setTrackNumber(d->track_);
|
mtrack.setTrackNumber(d->track_);
|
||||||
mtrack.setSource(lastfm::Track::Player);
|
mtrack.setSource(lastfm::Track::Player);
|
||||||
}
|
}
|
||||||
|
@ -1037,10 +1041,10 @@ QString Song::PrettyTitleWithArtist() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
QString Song::PrettyLength() const {
|
QString Song::PrettyLength() const {
|
||||||
if (length() == -1)
|
if (length_nanosec() == -1)
|
||||||
return QString::null;
|
return QString::null;
|
||||||
|
|
||||||
return Utilities::PrettyTime(length());
|
return Utilities::PrettyTimeNanosec(length_nanosec());
|
||||||
}
|
}
|
||||||
|
|
||||||
QString Song::PrettyYear() const {
|
QString Song::PrettyYear() const {
|
||||||
|
@ -1076,7 +1080,7 @@ bool Song::IsMetadataEqual(const Song& other) const {
|
||||||
d->comment_ == other.d->comment_ &&
|
d->comment_ == other.d->comment_ &&
|
||||||
d->compilation_ == other.d->compilation_ &&
|
d->compilation_ == other.d->compilation_ &&
|
||||||
d->beginning_ == other.d->beginning_ &&
|
d->beginning_ == other.d->beginning_ &&
|
||||||
length() == other.length() &&
|
length_nanosec() == other.length_nanosec() &&
|
||||||
d->bitrate_ == other.d->bitrate_ &&
|
d->bitrate_ == other.d->bitrate_ &&
|
||||||
d->samplerate_ == other.d->samplerate_ &&
|
d->samplerate_ == other.d->samplerate_ &&
|
||||||
d->sampler_ == other.d->sampler_ &&
|
d->sampler_ == other.d->sampler_ &&
|
||||||
|
@ -1177,7 +1181,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 filename() == other.filename() &&
|
||||||
beginning() == other.beginning();
|
beginning_nanosec() == other.beginning_nanosec();
|
||||||
}
|
}
|
||||||
|
|
||||||
QImage Song::LoadEmbeddedArt(const QString& filename) {
|
QImage Song::LoadEmbeddedArt(const QString& filename) {
|
||||||
|
|
|
@ -122,8 +122,8 @@ class Song {
|
||||||
bool HasProperMediaFile() const;
|
bool HasProperMediaFile() const;
|
||||||
|
|
||||||
// Constructors
|
// Constructors
|
||||||
void Init(const QString& title, const QString& artist, const QString& album, int length);
|
void Init(const QString& title, const QString& artist, const QString& album, qint64 length);
|
||||||
void Init(const QString& title, const QString& artist, const QString& album, int beginning, int end);
|
void Init(const QString& title, const QString& artist, const QString& album, qint64 beginning, qint64 end);
|
||||||
void InitFromFile(const QString& filename, int directory_id);
|
void InitFromFile(const QString& filename, int directory_id);
|
||||||
void InitFromQuery(const SqlRow& query, int col = 0);
|
void InitFromQuery(const SqlRow& query, int col = 0);
|
||||||
#ifdef HAVE_LIBLASTFM
|
#ifdef HAVE_LIBLASTFM
|
||||||
|
@ -185,10 +185,10 @@ class Song {
|
||||||
const QString& cue_path() const { return d->cue_path_; }
|
const QString& cue_path() const { return d->cue_path_; }
|
||||||
bool has_cue() const { return !d->cue_path_.isEmpty(); }
|
bool has_cue() const { return !d->cue_path_.isEmpty(); }
|
||||||
|
|
||||||
int beginning() const { return d->beginning_; }
|
qint64 beginning_nanosec() const { return d->beginning_; }
|
||||||
int end() const { return d->end_; }
|
qint64 end_nanosec() const { return d->end_; }
|
||||||
|
|
||||||
int length() const { return d->end_ - d->beginning_; }
|
qint64 length_nanosec() const { return d->end_ - d->beginning_; }
|
||||||
|
|
||||||
int bitrate() const { return d->bitrate_; }
|
int bitrate() const { return d->bitrate_; }
|
||||||
int samplerate() const { return d->samplerate_; }
|
int samplerate() const { return d->samplerate_; }
|
||||||
|
@ -248,9 +248,9 @@ class Song {
|
||||||
void set_comment(const QString& v) { d->comment_ = v; }
|
void set_comment(const QString& v) { d->comment_ = v; }
|
||||||
void set_compilation(bool v) { d->compilation_ = v; }
|
void set_compilation(bool v) { d->compilation_ = v; }
|
||||||
void set_sampler(bool v) { d->sampler_ = v; }
|
void set_sampler(bool v) { d->sampler_ = v; }
|
||||||
void set_beginning(int v) { d->beginning_ = qMax(0, v); }
|
void set_beginning_nanosec(qint64 v) { d->beginning_ = qMax(0ll, v); }
|
||||||
void set_end(int v) { d->end_ = v; }
|
void set_end_nanosec(qint64 v) { d->end_ = v; }
|
||||||
void set_length(int v) { d->end_ = d->beginning_ + v; }
|
void set_length_nanosec(qint64 v) { d->end_ = d->beginning_ + v; }
|
||||||
void set_bitrate(int v) { d->bitrate_ = v; }
|
void set_bitrate(int v) { d->bitrate_ = v; }
|
||||||
void set_samplerate(int v) { d->samplerate_ = v; }
|
void set_samplerate(int v) { d->samplerate_ = v; }
|
||||||
void set_mtime(int v) { d->mtime_ = v; }
|
void set_mtime(int v) { d->mtime_ = v; }
|
||||||
|
@ -321,14 +321,14 @@ class Song {
|
||||||
// streams, this will equal to 0. In case of multi-part streams on the
|
// streams, this will equal to 0. In case of multi-part streams on the
|
||||||
// other hand, this will mark the beginning of a section represented by
|
// other hand, this will mark the beginning of a section represented by
|
||||||
// this Song object. This is always greater than 0.
|
// this Song object. This is always greater than 0.
|
||||||
int beginning_;
|
qint64 beginning_;
|
||||||
// The end of the song in seconds. In case of single-part media
|
// The end of the song in seconds. In case of single-part media
|
||||||
// streams, this will equal to the song's length. In case of multi-part
|
// streams, this will equal to the song's length. In case of multi-part
|
||||||
// streams on the other hand, this will mark the end of a section
|
// streams on the other hand, this will mark the end of a section
|
||||||
// represented by this Song object.
|
// represented by this Song object.
|
||||||
// This may be negative indicating that the length of this song is
|
// This may be negative indicating that the length of this song is
|
||||||
// unknown.
|
// unknown.
|
||||||
int end_;
|
qint64 end_;
|
||||||
|
|
||||||
int bitrate_;
|
int bitrate_;
|
||||||
int samplerate_;
|
int samplerate_;
|
||||||
|
|
|
@ -62,6 +62,10 @@ QString PrettyTime(int seconds) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString PrettyTimeNanosec(qint64 nanoseconds) {
|
||||||
|
return PrettyTime(nanoseconds / 1e9);
|
||||||
|
}
|
||||||
|
|
||||||
QString WordyTime(quint64 seconds) {
|
QString WordyTime(quint64 seconds) {
|
||||||
quint64 days = seconds / (60*60*24);
|
quint64 days = seconds / (60*60*24);
|
||||||
|
|
||||||
|
@ -75,6 +79,10 @@ QString WordyTime(quint64 seconds) {
|
||||||
return parts.join(" ");
|
return parts.join(" ");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString WordyTimeNanosec(qint64 nanoseconds) {
|
||||||
|
return WordyTime(nanoseconds / 1e9);
|
||||||
|
}
|
||||||
|
|
||||||
QString Ago(int seconds_since_epoch, const QLocale& locale) {
|
QString Ago(int seconds_since_epoch, const QLocale& locale) {
|
||||||
const QDateTime now = QDateTime::currentDateTime();
|
const QDateTime now = QDateTime::currentDateTime();
|
||||||
const QDateTime then = QDateTime::fromTime_t(seconds_since_epoch);
|
const QDateTime then = QDateTime::fromTime_t(seconds_since_epoch);
|
||||||
|
|
|
@ -28,8 +28,10 @@ class QIODevice;
|
||||||
|
|
||||||
namespace Utilities {
|
namespace Utilities {
|
||||||
QString PrettyTime(int seconds);
|
QString PrettyTime(int seconds);
|
||||||
|
QString PrettyTimeNanosec(qint64 nanoseconds);
|
||||||
QString PrettySize(quint64 bytes);
|
QString PrettySize(quint64 bytes);
|
||||||
QString WordyTime(quint64 seconds);
|
QString WordyTime(quint64 seconds);
|
||||||
|
QString WordyTimeNanosec(qint64 nanoseconds);
|
||||||
QString Ago(int seconds_since_epoch, const QLocale& locale);
|
QString Ago(int seconds_since_epoch, const QLocale& locale);
|
||||||
|
|
||||||
QString ColorToRgba(const QColor& color);
|
QString ColorToRgba(const QColor& color);
|
||||||
|
|
|
@ -561,7 +561,7 @@ SongList LibraryBackend::GetSongsById(const QStringList& ids, QSqlDatabase& db)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
Song LibraryBackend::GetSongByFilename(const QString& filename, int beginning) {
|
Song LibraryBackend::GetSongByFilename(const QString& filename, 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", filename);
|
||||||
|
|
|
@ -88,7 +88,7 @@ class LibraryBackendInterface : public QObject {
|
||||||
// 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, int beginning = 0) = 0;
|
virtual Song GetSongByFilename(const QString& filename, 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;
|
||||||
|
@ -144,7 +144,7 @@ class LibraryBackend : public LibraryBackendInterface {
|
||||||
const QString& column);
|
const QString& column);
|
||||||
|
|
||||||
SongList GetSongsByFilename(const QString& filename);
|
SongList GetSongsByFilename(const QString& filename);
|
||||||
Song GetSongByFilename(const QString& filename, int beginning = 0);
|
Song GetSongByFilename(const QString& filename, qint64 beginning = 0);
|
||||||
|
|
||||||
void AddDirectory(const QString& path);
|
void AddDirectory(const QString& path);
|
||||||
void RemoveDirectory(const Directory& dir);
|
void RemoveDirectory(const Directory& dir);
|
||||||
|
|
|
@ -397,9 +397,9 @@ void LibraryWatcher::UpdateCueAssociatedSongs(const QString& file, const QString
|
||||||
|
|
||||||
SongList old_sections = backend_->GetSongsByFilename(file);
|
SongList old_sections = backend_->GetSongsByFilename(file);
|
||||||
|
|
||||||
QHash<int, Song> sections_map;
|
QHash<quint64, Song> sections_map;
|
||||||
foreach(const Song& song, old_sections) {
|
foreach(const Song& song, old_sections) {
|
||||||
sections_map[song.beginning()] = song;
|
sections_map[song.beginning_nanosec()] = song;
|
||||||
}
|
}
|
||||||
|
|
||||||
QSet<int> used_ids;
|
QSet<int> used_ids;
|
||||||
|
@ -408,7 +408,7 @@ void LibraryWatcher::UpdateCueAssociatedSongs(const QString& file, const QString
|
||||||
foreach(Song cue_song, cue_parser_->Load(&cue, matching_cue, path)) {
|
foreach(Song cue_song, cue_parser_->Load(&cue, matching_cue, path)) {
|
||||||
cue_song.set_directory_id(t->dir());
|
cue_song.set_directory_id(t->dir());
|
||||||
|
|
||||||
Song matching = sections_map[cue_song.beginning()];
|
Song matching = sections_map[cue_song.beginning_nanosec()];
|
||||||
// a new section
|
// a new section
|
||||||
if(!matching.is_valid()) {
|
if(!matching.is_valid()) {
|
||||||
t->new_songs << cue_song;
|
t->new_songs << cue_song;
|
||||||
|
|
|
@ -244,7 +244,7 @@ QVariant Playlist::data(const QModelIndex& index, int role) const {
|
||||||
return song.filename();
|
return song.filename();
|
||||||
case Column_Artist: return song.artist();
|
case Column_Artist: return song.artist();
|
||||||
case Column_Album: return song.album();
|
case Column_Album: return song.album();
|
||||||
case Column_Length: return song.length();
|
case Column_Length: return song.length_nanosec();
|
||||||
case Column_Track: return song.track();
|
case Column_Track: return song.track();
|
||||||
case Column_Disc: return song.disc();
|
case Column_Disc: return song.disc();
|
||||||
case Column_Year: return song.year();
|
case Column_Year: return song.year();
|
||||||
|
@ -960,7 +960,7 @@ bool Playlist::CompareItems(int column, Qt::SortOrder order,
|
||||||
case Column_Title: strcmp(title);
|
case Column_Title: strcmp(title);
|
||||||
case Column_Artist: strcmp(artist);
|
case Column_Artist: strcmp(artist);
|
||||||
case Column_Album: strcmp(album);
|
case Column_Album: strcmp(album);
|
||||||
case Column_Length: cmp(length);
|
case Column_Length: cmp(length_nanosec);
|
||||||
case Column_Track: cmp(track);
|
case Column_Track: cmp(track);
|
||||||
case Column_Disc: cmp(disc);
|
case Column_Disc: cmp(disc);
|
||||||
case Column_Year: cmp(year);
|
case Column_Year: cmp(year);
|
||||||
|
@ -1285,7 +1285,7 @@ Song Playlist::current_item_metadata() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Playlist::UpdateScrobblePoint() {
|
void Playlist::UpdateScrobblePoint() {
|
||||||
const int length = current_item_metadata().length();
|
const int length = current_item_metadata().length_nanosec();
|
||||||
|
|
||||||
scrobble_point_ = length == 0 ? 240 : qBound(31, length/2, 240);
|
scrobble_point_ = length == 0 ? 240 : qBound(31, length/2, 240);
|
||||||
has_scrobbled_ = false;
|
has_scrobbled_ = false;
|
||||||
|
@ -1447,7 +1447,7 @@ SongList Playlist::GetAllSongs() const {
|
||||||
quint64 Playlist::GetTotalLength() const {
|
quint64 Playlist::GetTotalLength() const {
|
||||||
quint64 ret = 0;
|
quint64 ret = 0;
|
||||||
foreach (PlaylistItemPtr item, items_) {
|
foreach (PlaylistItemPtr item, items_) {
|
||||||
int length = item->Metadata().length();
|
quint64 length = item->Metadata().length_nanosec();
|
||||||
if (length > 0)
|
if (length > 0)
|
||||||
ret += length;
|
ret += length;
|
||||||
}
|
}
|
||||||
|
|
|
@ -191,7 +191,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.filename() == song.filename() &&
|
||||||
from_list.beginning() == song.beginning()) {
|
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
|
||||||
return PlaylistItemPtr(new SongPlaylistItem(from_list));
|
return PlaylistItemPtr(new SongPlaylistItem(from_list));
|
||||||
|
|
|
@ -259,10 +259,10 @@ bool PlaylistDelegateBase::helpEvent(QHelpEvent *event, QAbstractItemView *view,
|
||||||
|
|
||||||
QString LengthItemDelegate::displayText(const QVariant& value, const QLocale&) const {
|
QString LengthItemDelegate::displayText(const QVariant& value, const QLocale&) const {
|
||||||
bool ok = false;
|
bool ok = false;
|
||||||
int seconds = value.toInt(&ok);
|
qint64 nanoseconds = value.toLongLong(&ok);
|
||||||
|
|
||||||
if (ok && seconds > 0)
|
if (ok && nanoseconds > 0)
|
||||||
return Utilities::PrettyTime(seconds);
|
return Utilities::PrettyTimeNanosec(nanoseconds);
|
||||||
return QString::null;
|
return QString::null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -264,7 +264,7 @@ void PlaylistManager::ChangePlaylistOrder(const QList<int>& ids) {
|
||||||
|
|
||||||
void PlaylistManager::UpdateSummaryText() {
|
void PlaylistManager::UpdateSummaryText() {
|
||||||
int tracks = current()->rowCount();
|
int tracks = current()->rowCount();
|
||||||
quint64 seconds = 0;
|
quint64 nanoseconds = 0;
|
||||||
int selected = 0;
|
int selected = 0;
|
||||||
|
|
||||||
// Get the length of the selected tracks
|
// Get the length of the selected tracks
|
||||||
|
@ -274,9 +274,9 @@ void PlaylistManager::UpdateSummaryText() {
|
||||||
|
|
||||||
selected += range.bottom() - range.top() + 1;
|
selected += range.bottom() - range.top() + 1;
|
||||||
for (int i=range.top() ; i<=range.bottom() ; ++i) {
|
for (int i=range.top() ; i<=range.bottom() ; ++i) {
|
||||||
int length = range.model()->index(i, Playlist::Column_Length).data().toInt();
|
int length = range.model()->index(i, Playlist::Column_Length).data().toLongLong();
|
||||||
if (length > 0)
|
if (length > 0)
|
||||||
seconds += length;
|
nanoseconds += length;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -284,14 +284,14 @@ void PlaylistManager::UpdateSummaryText() {
|
||||||
if (selected > 1) {
|
if (selected > 1) {
|
||||||
summary += tr("%1 selected of").arg(selected) + " ";
|
summary += tr("%1 selected of").arg(selected) + " ";
|
||||||
} else {
|
} else {
|
||||||
seconds = current()->GetTotalLength();
|
nanoseconds = current()->GetTotalLength();
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Make the plurals translatable
|
// TODO: Make the plurals translatable
|
||||||
summary += tracks == 1 ? tr("1 track") : tr("%1 tracks").arg(tracks);
|
summary += tracks == 1 ? tr("1 track") : tr("%1 tracks").arg(tracks);
|
||||||
|
|
||||||
if (seconds)
|
if (nanoseconds)
|
||||||
summary += " - [ " + Utilities::WordyTime(seconds) + " ]";
|
summary += " - [ " + Utilities::WordyTimeNanosec(nanoseconds) + " ]";
|
||||||
|
|
||||||
emit SummaryTextChanged(summary);
|
emit SummaryTextChanged(summary);
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,10 +53,10 @@ bool SongPlaylistItem::InitFromQuery(const SqlRow& query) {
|
||||||
} else {
|
} else {
|
||||||
song_.InitFromFile(filename, -1);
|
song_.InitFromFile(filename, -1);
|
||||||
|
|
||||||
int beginning(query.value(row + 7).toInt());
|
qint64 beginning(query.value(row + 7).toInt());
|
||||||
QString cue_path(query.value(row + 8).toString());
|
QString cue_path(query.value(row + 8).toString());
|
||||||
|
|
||||||
song_.set_beginning(beginning);
|
song_.set_beginning_nanosec(beginning);
|
||||||
song_.set_cue_path(cue_path);
|
song_.set_cue_path(cue_path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -69,8 +69,8 @@ QVariant SongPlaylistItem::DatabaseValue(DatabaseColumn column) const {
|
||||||
case Column_Title: return song_.title();
|
case Column_Title: return song_.title();
|
||||||
case Column_Artist: return song_.artist();
|
case Column_Artist: return song_.artist();
|
||||||
case Column_Album: return song_.album();
|
case Column_Album: return song_.album();
|
||||||
case Column_Length: return song_.length();
|
case Column_Length: return song_.length_nanosec();
|
||||||
case Column_Beginning: return song_.beginning();
|
case Column_Beginning: return song_.beginning_nanosec();
|
||||||
case Column_CuePath: return song_.cue_path();
|
case Column_CuePath: return song_.cue_path();
|
||||||
default: return PlaylistItem::DatabaseValue(column);
|
default: return PlaylistItem::DatabaseValue(column);
|
||||||
}
|
}
|
||||||
|
|
|
@ -266,8 +266,8 @@ QStringList CueParser::SplitCueLine(const QString& line) const {
|
||||||
// Updates the song with data from the .cue entry. This one mustn't be used for the
|
// Updates the song with data from the .cue entry. This one mustn't be used for the
|
||||||
// last song in the .cue file.
|
// last song in the .cue file.
|
||||||
bool CueParser::UpdateSong(const CueEntry& entry, const QString& next_index, Song* song) const {
|
bool CueParser::UpdateSong(const CueEntry& entry, const QString& next_index, Song* song) const {
|
||||||
int beginning = IndexToMarker(entry.index);
|
qint64 beginning = IndexToMarker(entry.index);
|
||||||
int end = IndexToMarker(next_index);
|
qint64 end = IndexToMarker(next_index);
|
||||||
|
|
||||||
// incorrect indices (we won't be able to calculate beginning or end)
|
// incorrect indices (we won't be able to calculate beginning or end)
|
||||||
if(beginning == -1 || end == -1) {
|
if(beginning == -1 || end == -1) {
|
||||||
|
@ -286,7 +286,7 @@ bool CueParser::UpdateSong(const CueEntry& entry, const QString& next_index, Son
|
||||||
// Updates the song with data from the .cue entry. This one must be used only for the
|
// Updates the song with data from the .cue entry. This one must be used only for the
|
||||||
// last song in the .cue file.
|
// last song in the .cue file.
|
||||||
bool CueParser::UpdateLastSong(const CueEntry& entry, Song* song) const {
|
bool CueParser::UpdateLastSong(const CueEntry& entry, Song* song) const {
|
||||||
int beginning = IndexToMarker(entry.index);
|
qint64 beginning = IndexToMarker(entry.index);
|
||||||
|
|
||||||
// incorrect index (we won't be able to calculate beginning)
|
// incorrect index (we won't be able to calculate beginning)
|
||||||
if(beginning == -1) {
|
if(beginning == -1) {
|
||||||
|
@ -304,12 +304,12 @@ bool CueParser::UpdateLastSong(const CueEntry& entry, Song* song) const {
|
||||||
|
|
||||||
// we don't do anything with the end here because it's already set to
|
// we don't do anything with the end here because it's already set to
|
||||||
// the end of the media file (if it exists)
|
// the end of the media file (if it exists)
|
||||||
song->set_beginning(beginning);
|
song->set_beginning_nanosec(beginning);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int CueParser::IndexToMarker(const QString& index) const {
|
qint64 CueParser::IndexToMarker(const QString& index) const {
|
||||||
QRegExp index_regexp(kIndexRegExp);
|
QRegExp index_regexp(kIndexRegExp);
|
||||||
if(!index_regexp.exactMatch(index)) {
|
if(!index_regexp.exactMatch(index)) {
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -317,7 +317,7 @@ int CueParser::IndexToMarker(const QString& index) const {
|
||||||
|
|
||||||
QStringList splitted = index_regexp.capturedTexts().mid(1, -1);
|
QStringList splitted = index_regexp.capturedTexts().mid(1, -1);
|
||||||
// TODO: use frames when #1166 is fixed
|
// TODO: use frames when #1166 is fixed
|
||||||
return splitted.at(0).toInt() * 60 + splitted.at(1).toInt();
|
return splitted.at(0).toLongLong() * 60 + splitted.at(1).toLongLong();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CueParser::Save(const SongList &songs, QIODevice *device, const QDir &dir) const {
|
void CueParser::Save(const SongList &songs, QIODevice *device, const QDir &dir) const {
|
||||||
|
|
|
@ -86,7 +86,7 @@ class CueParser : public ParserBase {
|
||||||
bool UpdateLastSong(const CueEntry& entry, Song* song) const;
|
bool UpdateLastSong(const CueEntry& entry, Song* song) const;
|
||||||
|
|
||||||
QStringList SplitCueLine(const QString& line) const;
|
QStringList SplitCueLine(const QString& line) const;
|
||||||
int IndexToMarker(const QString& index) const;
|
qint64 IndexToMarker(const QString& index) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // CUEPARSER_H
|
#endif // CUEPARSER_H
|
||||||
|
|
|
@ -119,7 +119,9 @@ void M3UParser::Save(const SongList &songs, QIODevice *device, const QDir &dir)
|
||||||
if (song.filename().isEmpty()) {
|
if (song.filename().isEmpty()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
QString meta = QString("#EXTINF:%1,%2 - %3\n").arg(song.length()).arg(song.artist()).arg(song.title());
|
QString meta = QString("#EXTINF:%1,%2 - %3\n")
|
||||||
|
.arg(song.length_nanosec())
|
||||||
|
.arg(song.artist()).arg(song.title());
|
||||||
device->write(meta.toUtf8());
|
device->write(meta.toUtf8());
|
||||||
device->write(MakeRelativeTo(song.filename(), dir).toUtf8());
|
device->write(MakeRelativeTo(song.filename(), dir).toUtf8());
|
||||||
device->write("\n");
|
device->write("\n");
|
||||||
|
|
|
@ -79,7 +79,7 @@ QString ParserBase::MakeUrl(const QString& filename_or_url) const {
|
||||||
return QUrl::fromLocalFile(filename_or_url).toString();
|
return QUrl::fromLocalFile(filename_or_url).toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
Song ParserBase::LoadLibrarySong(const QString& filename_or_url, int beginning) const {
|
Song ParserBase::LoadLibrarySong(const QString& filename_or_url, qint64 beginning) const {
|
||||||
if (!library_)
|
if (!library_)
|
||||||
return Song();
|
return Song();
|
||||||
|
|
||||||
|
|
|
@ -63,7 +63,7 @@ protected:
|
||||||
// Converts the URL or path to a canonical path and searches the library for
|
// 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,
|
// a section of a song with that path and the given beginning. If one is found,
|
||||||
// returns it, otherwise returns an invalid song.
|
// returns it, otherwise returns an invalid song.
|
||||||
Song LoadLibrarySong(const QString& filename_or_url, int beginning = 0) const;
|
Song LoadLibrarySong(const QString& filename_or_url, qint64 beginning = 0) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
LibraryBackendInterface* library_;
|
LibraryBackendInterface* library_;
|
||||||
|
|
|
@ -52,7 +52,7 @@ SongList PLSParser::Load(QIODevice *device, const QString& playlist_path, const
|
||||||
} 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")) {
|
||||||
songs[n].set_length(value.toInt());
|
songs[n].set_length_nanosec(value.toLongLong() * 1e9);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -69,7 +69,7 @@ void PLSParser::Save(const SongList &songs, QIODevice *device, const QDir &dir)
|
||||||
foreach (const Song& song, songs) {
|
foreach (const Song& song, songs) {
|
||||||
s << "File" << n << "=" << MakeRelativeTo(song.filename(), dir) << endl;
|
s << "File" << n << "=" << MakeRelativeTo(song.filename(), dir) << endl;
|
||||||
s << "Title" << n << "=" << song.title() << endl;
|
s << "Title" << n << "=" << song.title() << endl;
|
||||||
s << "Length" << n << "=" << song.length() << endl;
|
s << "Length" << n << "=" << song.length_nanosec() / 1e9 << endl;
|
||||||
++n;
|
++n;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -128,8 +128,8 @@ void XSPFParser::Save(const SongList& songs, QIODevice* device, const QDir&) con
|
||||||
if (!song.album().isEmpty()) {
|
if (!song.album().isEmpty()) {
|
||||||
writer.writeTextElement("album", song.album());
|
writer.writeTextElement("album", song.album());
|
||||||
}
|
}
|
||||||
if (song.length() != -1) {
|
if (song.length_nanosec() != -1) {
|
||||||
writer.writeTextElement("duration", QString::number(song.length() * 1000));
|
writer.writeTextElement("duration", QString::number(song.length_nanosec() / 1e6));
|
||||||
}
|
}
|
||||||
|
|
||||||
QString art = song.art_manual().isEmpty() ? song.art_automatic() : song.art_manual();
|
QString art = song.art_manual().isEmpty() ? song.art_automatic() : song.art_manual();
|
||||||
|
|
|
@ -335,7 +335,7 @@ Song JamendoService::ReadTrack(const QString& artist,
|
||||||
song.set_title(reader->readElementText().trimmed());
|
song.set_title(reader->readElementText().trimmed());
|
||||||
} else if (name == "duration") {
|
} else if (name == "duration") {
|
||||||
const int length = reader->readElementText().toFloat();
|
const int length = reader->readElementText().toFloat();
|
||||||
song.set_length(length);
|
song.set_length_nanosec(length * 1e9);
|
||||||
} else if (name == "id3genre") {
|
} else if (name == "id3genre") {
|
||||||
int genre_id = reader->readElementText().toInt();
|
int genre_id = reader->readElementText().toInt();
|
||||||
// In theory, genre 0 is "blues"; in practice it's invalid.
|
// In theory, genre 0 is "blues"; in practice it's invalid.
|
||||||
|
|
|
@ -203,7 +203,7 @@ Song MagnatuneService::ReadTrack(QXmlStreamReader& reader) {
|
||||||
if (name == "tracknum") song.set_track(value.toInt());
|
if (name == "tracknum") song.set_track(value.toInt());
|
||||||
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(value.toInt());
|
if (name == "seconds") song.set_length_nanosec(value.toInt() * 1e9);
|
||||||
if (name == "url") song.set_filename(value);
|
if (name == "url") song.set_filename(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);
|
||||||
|
|
|
@ -58,10 +58,10 @@ public:
|
||||||
const QString& cue_path() const;
|
const QString& cue_path() const;
|
||||||
bool has_cue() const;
|
bool has_cue() const;
|
||||||
|
|
||||||
int beginning() const;
|
int beginning_nanosec() const;
|
||||||
int end() const;
|
int end_nanosec() const;
|
||||||
|
|
||||||
int length() const;
|
int length_nanosec() const;
|
||||||
|
|
||||||
int bitrate() const;
|
int bitrate() const;
|
||||||
int samplerate() const;
|
int samplerate() const;
|
||||||
|
@ -115,9 +115,9 @@ public:
|
||||||
void set_comment(const QString& v);
|
void set_comment(const QString& v);
|
||||||
void set_compilation(bool v);
|
void set_compilation(bool v);
|
||||||
void set_sampler(bool v);
|
void set_sampler(bool v);
|
||||||
void set_beginning(int v);
|
void set_beginning_nanosec(int v);
|
||||||
void set_end(int v);
|
void set_end_nanosec(int v);
|
||||||
void set_length(int v);
|
void set_length_nanosec(int v);
|
||||||
void set_bitrate(int v);
|
void set_bitrate(int v);
|
||||||
void set_samplerate(int v);
|
void set_samplerate(int v);
|
||||||
void set_mtime(int v);
|
void set_mtime(int v);
|
||||||
|
|
|
@ -430,7 +430,7 @@ void EditTagDialog::UpdateSummaryTab(const Song& song) {
|
||||||
album_cover_choice_controller_->show_cover_action()->setEnabled(art_is_set);
|
album_cover_choice_controller_->show_cover_action()->setEnabled(art_is_set);
|
||||||
ui_->summary_art_button->setEnabled(song.id() != -1);
|
ui_->summary_art_button->setEnabled(song.id() != -1);
|
||||||
|
|
||||||
ui_->length->setText(Utilities::PrettyTime(song.length()));
|
ui_->length->setText(Utilities::PrettyTimeNanosec(song.length_nanosec()));
|
||||||
SetText(ui_->bpm, song.bpm(), tr("bpm"));
|
SetText(ui_->bpm, song.bpm(), tr("bpm"));
|
||||||
SetText(ui_->samplerate, song.samplerate(), "Hz");
|
SetText(ui_->samplerate, song.samplerate(), "Hz");
|
||||||
SetText(ui_->bitrate, song.bitrate(), tr("kbps"));
|
SetText(ui_->bitrate, song.bitrate(), tr("kbps"));
|
||||||
|
|
|
@ -927,7 +927,7 @@ void MainWindow::UpdateTrackPosition() {
|
||||||
PlaylistItemPtr item(player_->GetCurrentItem());
|
PlaylistItemPtr item(player_->GetCurrentItem());
|
||||||
const int position = std::floor(
|
const int position = std::floor(
|
||||||
float(player_->engine()->position_nanosec()) / 1e9 + 0.5);
|
float(player_->engine()->position_nanosec()) / 1e9 + 0.5);
|
||||||
const int length = item->Metadata().length();
|
const int length = item->Metadata().length_nanosec() / 1e9;
|
||||||
|
|
||||||
if (length <= 0) {
|
if (length <= 0) {
|
||||||
// Probably a stream that we don't know the length of
|
// Probably a stream that we don't know the length of
|
||||||
|
|
Loading…
Reference in New Issue