diff --git a/data/data.qrc b/data/data.qrc
index cf7d66424..b293dd1e1 100644
--- a/data/data.qrc
+++ b/data/data.qrc
@@ -298,5 +298,6 @@
schema/schema-26.sql
pythonstartup.py
schema/schema-27.sql
+ schema/schema-28.sql
diff --git a/data/schema/schema-28.sql b/data/schema/schema-28.sql
new file mode 100644
index 000000000..2f470c118
--- /dev/null
+++ b/data/schema/schema-28.sql
@@ -0,0 +1,3 @@
+UPDATE %allsongstables SET length=length*1e9, beginning=beginning*1e9;
+
+UPDATE schema_version SET version=28;
diff --git a/src/core/database.cpp b/src/core/database.cpp
index 5b12c4fbd..149651602 100644
--- a/src/core/database.cpp
+++ b/src/core/database.cpp
@@ -31,7 +31,7 @@
#include
const char* Database::kDatabaseFilename = "clementine.db";
-const int Database::kSchemaVersion = 27;
+const int Database::kSchemaVersion = 28;
const char* Database::kMagicAllSongsTables = "%allsongstables";
int Database::sNextConnectionId = 1;
diff --git a/src/core/mpris1.cpp b/src/core/mpris1.cpp
index 24efeb338..f6a4be0df 100644
--- a/src/core/mpris1.cpp
+++ b/src/core/mpris1.cpp
@@ -302,8 +302,8 @@ QVariantMap Mpris1::GetMetadata(const Song& song) {
AddMetadata("title", song.PrettyTitle(), &ret);
AddMetadata("artist", song.artist(), &ret);
AddMetadata("album", song.album(), &ret);
- AddMetadata("time", song.length(), &ret);
- AddMetadata("mtime", song.length() * 1000, &ret);
+ AddMetadata("time", song.length_nanosec() / 1e9, &ret);
+ AddMetadata("mtime", song.length_nanosec() / 1e6, &ret);
AddMetadata("tracknumber", song.track(), &ret);
AddMetadata("year", song.year(), &ret);
AddMetadata("genre", song.genre(), &ret);
diff --git a/src/core/mpris1.h b/src/core/mpris1.h
index c4e92e965..ab0af22cf 100644
--- a/src/core/mpris1.h
+++ b/src/core/mpris1.h
@@ -131,7 +131,7 @@ public:
void VolumeSet(int volume);
int VolumeGet() const;
- void PositionSet(int pos);
+ void PositionSet(int pos_msec);
int PositionGet() const;
QVariantMap GetMetadata() const;
diff --git a/src/core/mpris2.cpp b/src/core/mpris2.cpp
index fe9f86c18..8ce25384c 100644
--- a/src/core/mpris2.cpp
+++ b/src/core/mpris2.cpp
@@ -295,7 +295,7 @@ void Mpris2::ArtLoaded(const Song& song, const QString& art_uri) {
AddMetadataAsList("xesam:artist", song.artist(), &last_metadata_);
AddMetadata("xesam:album", song.album(), &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_);
AddMetadataAsList("xesam:genre", song.genre(), &last_metadata_);
AddMetadata("xesam:discNumber", song.disc(), &last_metadata_);
@@ -325,7 +325,7 @@ void Mpris2::SetVolume(double value) {
}
qlonglong Mpris2::Position() const {
- return mpris1_->player()->PositionGet() / 1e3;
+ return player_->engine()->position_nanosec() / 1e3;
}
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) {
offset *= 1e3;
- if(offset < player_->GetCurrentItem()->Metadata().length()) {
+ if(offset < player_->GetCurrentItem()->Metadata().length_nanosec()) {
player_->Seek(offset / 1e9);
}
}
diff --git a/src/core/organiseformat.cpp b/src/core/organiseformat.cpp
index 5d88d2e1e..2b1760792 100644
--- a/src/core/organiseformat.cpp
+++ b/src/core/organiseformat.cpp
@@ -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 == "disc") value = QString::number(song.disc());
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 == "samplerate") value = QString::number(song.samplerate());
else if (tag == "extension") value = song.filename().section('.', -1, -1);
diff --git a/src/core/player.cpp b/src/core/player.cpp
index 9a15967d3..b02f4acf3 100644
--- a/src/core/player.cpp
+++ b/src/core/player.cpp
@@ -96,8 +96,8 @@ void Player::HandleSpecialLoad(const PlaylistItem::SpecialLoadResult &result) {
return;
engine_->Play(result.media_url_, stream_change_type_,
- item->Metadata().beginning() * 1e9,
- item->Metadata().end() * 1e9);
+ item->Metadata().beginning_nanosec(),
+ item->Metadata().end_nanosec());
current_item_ = item;
loading_async_ = QUrl();
@@ -266,8 +266,8 @@ void Player::PlayAt(int index, Engine::TrackChangeType change, bool reshuffle) {
else {
loading_async_ = QUrl();
engine_->Play(current_item_->Url(), change,
- current_item_->Metadata().beginning() * 1e9,
- current_item_->Metadata().end() * 1e9);
+ current_item_->Metadata().beginning_nanosec(),
+ current_item_->Metadata().end_nanosec());
#ifdef HAVE_LIBLASTFM
if (lastfm_->IsScrobblingEnabled())
diff --git a/src/core/song.cpp b/src/core/song.cpp
index f4fba5820..7735281b0 100644
--- a/src/core/song.cpp
+++ b/src/core/song.cpp
@@ -201,17 +201,19 @@ Song::Song(FileRefFactory* 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->title_ = title;
d->artist_ = artist;
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->title_ = title;
@@ -378,7 +380,7 @@ void Song::InitFromFile(const QString& filename, int directory_id) {
if (fileref->audioProperties()) {
d->bitrate_ = fileref->audioProperties()->bitrate();
d->samplerate_ = fileref->audioProperties()->sampleRate();
- set_length(fileref->audioProperties()->length());
+ set_length_nanosec(fileref->audioProperties()->length() * 1e9);
}
// Get the filetype if we can
@@ -475,9 +477,10 @@ void Song::InitFromQuery(const SqlRow& q, int col) {
d->init_from_file_ = true;
- #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 tofloat(n) (q.value(n).isNull() ? -1 : q.value(n).toDouble())
+ #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 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->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
// length is!
- d->beginning_ = q.value(col + 32).isNull() ? 0 : q.value(col + 32).toInt();
- set_length(toint(col + 33));
+ d->beginning_ = q.value(col + 32).isNull() ? 0 : q.value(col + 32).toLongLong();
+ set_length_nanosec(tolonglong(col + 33));
d->cue_path_ = tostr(col + 34);
#undef tostr
#undef toint
+ #undef tolonglong
#undef tofloat
}
@@ -543,7 +547,7 @@ void Song::InitFromLastFM(const lastfm::Track& track) {
d->artist_ = track.artist();
d->track_ = track.trackNumber();
- set_length(track.duration());
+ set_length_nanosec(track.duration() * 1e9);
}
#endif // HAVE_LIBLASTFM
@@ -563,7 +567,7 @@ void Song::InitFromLastFM(const lastfm::Track& track) {
d->genre_ = QString::fromUtf8(track->genre);
d->comment_ = QString::fromUtf8(track->comment);
d->compilation_ = track->compilation;
- set_length(track->tracklen / 1000);
+ set_length_nanosec(track->tracklen * 1e6);
d->bitrate_ = track->bitrate;
d->samplerate_ = track->samplerate;
d->mtime_ = track->time_modified;
@@ -593,7 +597,7 @@ void Song::InitFromLastFM(const lastfm::Track& track) {
track->genre = strdup(d->genre_.toUtf8().constData());
track->comment = strdup(d->comment_.toUtf8().constData());
track->compilation = d->compilation_;
- track->tracklen = length() * 1000;
+ track->tracklen = length_nanosec() / 1e6;
track->bitrate = d->bitrate_;
track->samplerate = d->samplerate_;
track->time_modified = d->mtime_;
@@ -622,7 +626,7 @@ void Song::InitFromLastFM(const lastfm::Track& track) {
d->basefilename_ = d->filename_;
d->track_ = track->tracknumber;
- set_length(track->duration / 1000);
+ set_length_nanosec(track->duration * 1e6);
d->samplerate_ = track->samplerate;
d->bitrate_ = track->bitrate;
d->filesize_ = track->filesize;
@@ -662,7 +666,7 @@ void Song::InitFromLastFM(const lastfm::Track& track) {
track->filename = strdup(d->basefilename_.toUtf8().constData());
track->tracknumber = d->track_;
- track->duration = length() * 1000;
+ track->duration = length_nanosec() / 1e6;
track->samplerate = d->samplerate_;
track->nochannels = 0;
track->wavecodec = 0;
@@ -796,7 +800,7 @@ void Song::InitFromLastFM(const lastfm::Track& track) {
d->filename_ = item_value.toString();
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)
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_wszWMDMBitrate, d->bitrate_);
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_);
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.bitrate.isEmpty()) d->bitrate_ = bundle.bitrate.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.tracknr.isEmpty()) d->track_ = bundle.tracknr.toInt();
}
@@ -984,7 +988,7 @@ void Song::BindToQuery(QSqlQuery *query) const {
query->bindValue(":score", d->score_);
query->bindValue(":beginning", d->beginning_);
- query->bindValue(":length", intval(length()));
+ query->bindValue(":length", intval(length_nanosec()));
query->bindValue(":cue_path", d->cue_path_);
@@ -1009,7 +1013,7 @@ void Song::ToLastFM(lastfm::Track* track) const {
mtrack.setArtist(d->artist_);
mtrack.setAlbum(d->album_);
mtrack.setTitle(d->title_);
- mtrack.setDuration(length());
+ mtrack.setDuration(length_nanosec() / 1e9);
mtrack.setTrackNumber(d->track_);
mtrack.setSource(lastfm::Track::Player);
}
@@ -1037,10 +1041,10 @@ QString Song::PrettyTitleWithArtist() const {
}
QString Song::PrettyLength() const {
- if (length() == -1)
+ if (length_nanosec() == -1)
return QString::null;
- return Utilities::PrettyTime(length());
+ return Utilities::PrettyTimeNanosec(length_nanosec());
}
QString Song::PrettyYear() const {
@@ -1076,7 +1080,7 @@ bool Song::IsMetadataEqual(const Song& other) const {
d->comment_ == other.d->comment_ &&
d->compilation_ == other.d->compilation_ &&
d->beginning_ == other.d->beginning_ &&
- length() == other.length() &&
+ length_nanosec() == other.length_nanosec() &&
d->bitrate_ == other.d->bitrate_ &&
d->samplerate_ == other.d->samplerate_ &&
d->sampler_ == other.d->sampler_ &&
@@ -1177,7 +1181,7 @@ QFuture Song::BackgroundSave() const {
bool Song::operator==(const Song& other) const {
// TODO: this isn't working for radios
return filename() == other.filename() &&
- beginning() == other.beginning();
+ beginning_nanosec() == other.beginning_nanosec();
}
QImage Song::LoadEmbeddedArt(const QString& filename) {
diff --git a/src/core/song.h b/src/core/song.h
index d882f3012..e1189c674 100644
--- a/src/core/song.h
+++ b/src/core/song.h
@@ -122,8 +122,8 @@ class Song {
bool HasProperMediaFile() const;
// 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, int beginning, int end);
+ void Init(const QString& title, const QString& artist, const QString& album, qint64 length);
+ void Init(const QString& title, const QString& artist, const QString& album, qint64 beginning, qint64 end);
void InitFromFile(const QString& filename, int directory_id);
void InitFromQuery(const SqlRow& query, int col = 0);
#ifdef HAVE_LIBLASTFM
@@ -185,10 +185,10 @@ class Song {
const QString& cue_path() const { return d->cue_path_; }
bool has_cue() const { return !d->cue_path_.isEmpty(); }
- int beginning() const { return d->beginning_; }
- int end() const { return d->end_; }
+ qint64 beginning_nanosec() const { return d->beginning_; }
+ 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 samplerate() const { return d->samplerate_; }
@@ -248,9 +248,9 @@ class Song {
void set_comment(const QString& v) { d->comment_ = v; }
void set_compilation(bool v) { d->compilation_ = v; }
void set_sampler(bool v) { d->sampler_ = v; }
- void set_beginning(int v) { d->beginning_ = qMax(0, v); }
- void set_end(int v) { d->end_ = v; }
- void set_length(int v) { d->end_ = d->beginning_ + v; }
+ void set_beginning_nanosec(qint64 v) { d->beginning_ = qMax(0ll, v); }
+ void set_end_nanosec(qint64 v) { d->end_ = v; }
+ void set_length_nanosec(qint64 v) { d->end_ = d->beginning_ + v; }
void set_bitrate(int v) { d->bitrate_ = v; }
void set_samplerate(int v) { d->samplerate_ = 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
// other hand, this will mark the beginning of a section represented by
// 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
// 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
// represented by this Song object.
// This may be negative indicating that the length of this song is
// unknown.
- int end_;
+ qint64 end_;
int bitrate_;
int samplerate_;
diff --git a/src/core/utilities.cpp b/src/core/utilities.cpp
index 643db3b6f..1339976c5 100644
--- a/src/core/utilities.cpp
+++ b/src/core/utilities.cpp
@@ -62,6 +62,10 @@ QString PrettyTime(int seconds) {
return ret;
}
+QString PrettyTimeNanosec(qint64 nanoseconds) {
+ return PrettyTime(nanoseconds / 1e9);
+}
+
QString WordyTime(quint64 seconds) {
quint64 days = seconds / (60*60*24);
@@ -75,6 +79,10 @@ QString WordyTime(quint64 seconds) {
return parts.join(" ");
}
+QString WordyTimeNanosec(qint64 nanoseconds) {
+ return WordyTime(nanoseconds / 1e9);
+}
+
QString Ago(int seconds_since_epoch, const QLocale& locale) {
const QDateTime now = QDateTime::currentDateTime();
const QDateTime then = QDateTime::fromTime_t(seconds_since_epoch);
diff --git a/src/core/utilities.h b/src/core/utilities.h
index feca1e9f7..d0533066c 100644
--- a/src/core/utilities.h
+++ b/src/core/utilities.h
@@ -28,8 +28,10 @@ class QIODevice;
namespace Utilities {
QString PrettyTime(int seconds);
+ QString PrettyTimeNanosec(qint64 nanoseconds);
QString PrettySize(quint64 bytes);
QString WordyTime(quint64 seconds);
+ QString WordyTimeNanosec(qint64 nanoseconds);
QString Ago(int seconds_since_epoch, const QLocale& locale);
QString ColorToRgba(const QColor& color);
diff --git a/src/library/librarybackend.cpp b/src/library/librarybackend.cpp
index 61f59a390..d09715148 100644
--- a/src/library/librarybackend.cpp
+++ b/src/library/librarybackend.cpp
@@ -561,7 +561,7 @@ SongList LibraryBackend::GetSongsById(const QStringList& ids, QSqlDatabase& db)
return ret;
}
-Song LibraryBackend::GetSongByFilename(const QString& filename, int beginning) {
+Song LibraryBackend::GetSongByFilename(const QString& filename, qint64 beginning) {
LibraryQuery query;
query.SetColumnSpec("%songs_table.ROWID, " + Song::kColumnSpec);
query.AddWhere("filename", filename);
diff --git a/src/library/librarybackend.h b/src/library/librarybackend.h
index 790a09218..52c33cec0 100644
--- a/src/library/librarybackend.h
+++ b/src/library/librarybackend.h
@@ -88,7 +88,7 @@ class LibraryBackendInterface : public QObject {
// Returns a section of a song with the given filename and beginning. If the section
// is not present in library, returns invalid song.
// 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 RemoveDirectory(const Directory& dir) = 0;
@@ -144,7 +144,7 @@ class LibraryBackend : public LibraryBackendInterface {
const QString& column);
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 RemoveDirectory(const Directory& dir);
diff --git a/src/library/librarywatcher.cpp b/src/library/librarywatcher.cpp
index a0e590af3..db3c01471 100644
--- a/src/library/librarywatcher.cpp
+++ b/src/library/librarywatcher.cpp
@@ -397,9 +397,9 @@ void LibraryWatcher::UpdateCueAssociatedSongs(const QString& file, const QString
SongList old_sections = backend_->GetSongsByFilename(file);
- QHash sections_map;
+ QHash sections_map;
foreach(const Song& song, old_sections) {
- sections_map[song.beginning()] = song;
+ sections_map[song.beginning_nanosec()] = song;
}
QSet 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)) {
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
if(!matching.is_valid()) {
t->new_songs << cue_song;
diff --git a/src/playlist/playlist.cpp b/src/playlist/playlist.cpp
index 04645de13..a7576befd 100644
--- a/src/playlist/playlist.cpp
+++ b/src/playlist/playlist.cpp
@@ -244,7 +244,7 @@ QVariant Playlist::data(const QModelIndex& index, int role) const {
return song.filename();
case Column_Artist: return song.artist();
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_Disc: return song.disc();
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_Artist: strcmp(artist);
case Column_Album: strcmp(album);
- case Column_Length: cmp(length);
+ case Column_Length: cmp(length_nanosec);
case Column_Track: cmp(track);
case Column_Disc: cmp(disc);
case Column_Year: cmp(year);
@@ -1285,7 +1285,7 @@ Song Playlist::current_item_metadata() const {
}
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);
has_scrobbled_ = false;
@@ -1447,7 +1447,7 @@ SongList Playlist::GetAllSongs() const {
quint64 Playlist::GetTotalLength() const {
quint64 ret = 0;
foreach (PlaylistItemPtr item, items_) {
- int length = item->Metadata().length();
+ quint64 length = item->Metadata().length_nanosec();
if (length > 0)
ret += length;
}
diff --git a/src/playlist/playlistbackend.cpp b/src/playlist/playlistbackend.cpp
index 1e2287f3b..8f8dc7bce 100644
--- a/src/playlist/playlistbackend.cpp
+++ b/src/playlist/playlistbackend.cpp
@@ -191,7 +191,7 @@ PlaylistItemPtr PlaylistBackend::RestoreCueData(PlaylistItemPtr item, boost::sha
foreach(const Song& from_list, song_list) {
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
// item with a new one containing CUE metadata
return PlaylistItemPtr(new SongPlaylistItem(from_list));
diff --git a/src/playlist/playlistdelegates.cpp b/src/playlist/playlistdelegates.cpp
index 23050b20d..7c2c62316 100644
--- a/src/playlist/playlistdelegates.cpp
+++ b/src/playlist/playlistdelegates.cpp
@@ -259,10 +259,10 @@ bool PlaylistDelegateBase::helpEvent(QHelpEvent *event, QAbstractItemView *view,
QString LengthItemDelegate::displayText(const QVariant& value, const QLocale&) const {
bool ok = false;
- int seconds = value.toInt(&ok);
+ qint64 nanoseconds = value.toLongLong(&ok);
- if (ok && seconds > 0)
- return Utilities::PrettyTime(seconds);
+ if (ok && nanoseconds > 0)
+ return Utilities::PrettyTimeNanosec(nanoseconds);
return QString::null;
}
diff --git a/src/playlist/playlistmanager.cpp b/src/playlist/playlistmanager.cpp
index f3d63fce8..a3fd170db 100644
--- a/src/playlist/playlistmanager.cpp
+++ b/src/playlist/playlistmanager.cpp
@@ -264,7 +264,7 @@ void PlaylistManager::ChangePlaylistOrder(const QList& ids) {
void PlaylistManager::UpdateSummaryText() {
int tracks = current()->rowCount();
- quint64 seconds = 0;
+ quint64 nanoseconds = 0;
int selected = 0;
// Get the length of the selected tracks
@@ -274,9 +274,9 @@ void PlaylistManager::UpdateSummaryText() {
selected += range.bottom() - range.top() + 1;
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)
- seconds += length;
+ nanoseconds += length;
}
}
@@ -284,14 +284,14 @@ void PlaylistManager::UpdateSummaryText() {
if (selected > 1) {
summary += tr("%1 selected of").arg(selected) + " ";
} else {
- seconds = current()->GetTotalLength();
+ nanoseconds = current()->GetTotalLength();
}
// TODO: Make the plurals translatable
summary += tracks == 1 ? tr("1 track") : tr("%1 tracks").arg(tracks);
- if (seconds)
- summary += " - [ " + Utilities::WordyTime(seconds) + " ]";
+ if (nanoseconds)
+ summary += " - [ " + Utilities::WordyTimeNanosec(nanoseconds) + " ]";
emit SummaryTextChanged(summary);
}
diff --git a/src/playlist/songplaylistitem.cpp b/src/playlist/songplaylistitem.cpp
index 8eda0c96a..49571dce6 100644
--- a/src/playlist/songplaylistitem.cpp
+++ b/src/playlist/songplaylistitem.cpp
@@ -53,10 +53,10 @@ bool SongPlaylistItem::InitFromQuery(const SqlRow& query) {
} else {
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());
- song_.set_beginning(beginning);
+ song_.set_beginning_nanosec(beginning);
song_.set_cue_path(cue_path);
}
@@ -69,8 +69,8 @@ QVariant SongPlaylistItem::DatabaseValue(DatabaseColumn column) const {
case Column_Title: return song_.title();
case Column_Artist: return song_.artist();
case Column_Album: return song_.album();
- case Column_Length: return song_.length();
- case Column_Beginning: return song_.beginning();
+ case Column_Length: return song_.length_nanosec();
+ case Column_Beginning: return song_.beginning_nanosec();
case Column_CuePath: return song_.cue_path();
default: return PlaylistItem::DatabaseValue(column);
}
diff --git a/src/playlistparsers/cueparser.cpp b/src/playlistparsers/cueparser.cpp
index 3849f66b3..64a4558ec 100644
--- a/src/playlistparsers/cueparser.cpp
+++ b/src/playlistparsers/cueparser.cpp
@@ -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
// last song in the .cue file.
bool CueParser::UpdateSong(const CueEntry& entry, const QString& next_index, Song* song) const {
- int beginning = IndexToMarker(entry.index);
- int end = IndexToMarker(next_index);
+ qint64 beginning = IndexToMarker(entry.index);
+ qint64 end = IndexToMarker(next_index);
// incorrect indices (we won't be able to calculate beginning or end)
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
// last song in the .cue file.
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)
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
// the end of the media file (if it exists)
- song->set_beginning(beginning);
+ song->set_beginning_nanosec(beginning);
return true;
}
-int CueParser::IndexToMarker(const QString& index) const {
+qint64 CueParser::IndexToMarker(const QString& index) const {
QRegExp index_regexp(kIndexRegExp);
if(!index_regexp.exactMatch(index)) {
return -1;
@@ -317,7 +317,7 @@ int CueParser::IndexToMarker(const QString& index) const {
QStringList splitted = index_regexp.capturedTexts().mid(1, -1);
// 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 {
diff --git a/src/playlistparsers/cueparser.h b/src/playlistparsers/cueparser.h
index d09a560c2..a6ffb2920 100644
--- a/src/playlistparsers/cueparser.h
+++ b/src/playlistparsers/cueparser.h
@@ -86,7 +86,7 @@ class CueParser : public ParserBase {
bool UpdateLastSong(const CueEntry& entry, Song* song) const;
QStringList SplitCueLine(const QString& line) const;
- int IndexToMarker(const QString& index) const;
+ qint64 IndexToMarker(const QString& index) const;
};
#endif // CUEPARSER_H
diff --git a/src/playlistparsers/m3uparser.cpp b/src/playlistparsers/m3uparser.cpp
index afd0040dd..37054eb57 100644
--- a/src/playlistparsers/m3uparser.cpp
+++ b/src/playlistparsers/m3uparser.cpp
@@ -119,7 +119,9 @@ void M3UParser::Save(const SongList &songs, QIODevice *device, const QDir &dir)
if (song.filename().isEmpty()) {
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(MakeRelativeTo(song.filename(), dir).toUtf8());
device->write("\n");
diff --git a/src/playlistparsers/parserbase.cpp b/src/playlistparsers/parserbase.cpp
index 7b47095e1..b5671e564 100644
--- a/src/playlistparsers/parserbase.cpp
+++ b/src/playlistparsers/parserbase.cpp
@@ -79,7 +79,7 @@ QString ParserBase::MakeUrl(const QString& filename_or_url) const {
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_)
return Song();
diff --git a/src/playlistparsers/parserbase.h b/src/playlistparsers/parserbase.h
index 24f06ea16..8c6f67443 100644
--- a/src/playlistparsers/parserbase.h
+++ b/src/playlistparsers/parserbase.h
@@ -63,7 +63,7 @@ protected:
// 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, int beginning = 0) const;
+ Song LoadLibrarySong(const QString& filename_or_url, qint64 beginning = 0) const;
private:
LibraryBackendInterface* library_;
diff --git a/src/playlistparsers/plsparser.cpp b/src/playlistparsers/plsparser.cpp
index 6d80d0441..bdadea996 100644
--- a/src/playlistparsers/plsparser.cpp
+++ b/src/playlistparsers/plsparser.cpp
@@ -52,7 +52,7 @@ SongList PLSParser::Load(QIODevice *device, const QString& playlist_path, const
} else if (key.startsWith("title")) {
songs[n].set_title(value);
} 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) {
s << "File" << n << "=" << MakeRelativeTo(song.filename(), dir) << endl;
s << "Title" << n << "=" << song.title() << endl;
- s << "Length" << n << "=" << song.length() << endl;
+ s << "Length" << n << "=" << song.length_nanosec() / 1e9 << endl;
++n;
}
}
diff --git a/src/playlistparsers/xspfparser.cpp b/src/playlistparsers/xspfparser.cpp
index 31e0f9a7c..3b79d4b17 100644
--- a/src/playlistparsers/xspfparser.cpp
+++ b/src/playlistparsers/xspfparser.cpp
@@ -128,8 +128,8 @@ void XSPFParser::Save(const SongList& songs, QIODevice* device, const QDir&) con
if (!song.album().isEmpty()) {
writer.writeTextElement("album", song.album());
}
- if (song.length() != -1) {
- writer.writeTextElement("duration", QString::number(song.length() * 1000));
+ if (song.length_nanosec() != -1) {
+ writer.writeTextElement("duration", QString::number(song.length_nanosec() / 1e6));
}
QString art = song.art_manual().isEmpty() ? song.art_automatic() : song.art_manual();
diff --git a/src/radio/jamendoservice.cpp b/src/radio/jamendoservice.cpp
index 22ee63353..57a2afd33 100644
--- a/src/radio/jamendoservice.cpp
+++ b/src/radio/jamendoservice.cpp
@@ -335,7 +335,7 @@ Song JamendoService::ReadTrack(const QString& artist,
song.set_title(reader->readElementText().trimmed());
} else if (name == "duration") {
const int length = reader->readElementText().toFloat();
- song.set_length(length);
+ song.set_length_nanosec(length * 1e9);
} else if (name == "id3genre") {
int genre_id = reader->readElementText().toInt();
// In theory, genre 0 is "blues"; in practice it's invalid.
diff --git a/src/radio/magnatuneservice.cpp b/src/radio/magnatuneservice.cpp
index 7def5d9fe..694105e6f 100644
--- a/src/radio/magnatuneservice.cpp
+++ b/src/radio/magnatuneservice.cpp
@@ -203,7 +203,7 @@ Song MagnatuneService::ReadTrack(QXmlStreamReader& reader) {
if (name == "tracknum") song.set_track(value.toInt());
if (name == "year") song.set_year(value.toInt());
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 == "cover_small") song.set_art_automatic(value);
if (name == "albumsku") song.set_comment(value);
diff --git a/src/scripting/python/song.sip b/src/scripting/python/song.sip
index db62b30be..e321b7057 100644
--- a/src/scripting/python/song.sip
+++ b/src/scripting/python/song.sip
@@ -58,10 +58,10 @@ public:
const QString& cue_path() const;
bool has_cue() const;
- int beginning() const;
- int end() const;
+ int beginning_nanosec() const;
+ int end_nanosec() const;
- int length() const;
+ int length_nanosec() const;
int bitrate() const;
int samplerate() const;
@@ -115,9 +115,9 @@ public:
void set_comment(const QString& v);
void set_compilation(bool v);
void set_sampler(bool v);
- void set_beginning(int v);
- void set_end(int v);
- void set_length(int v);
+ void set_beginning_nanosec(int v);
+ void set_end_nanosec(int v);
+ void set_length_nanosec(int v);
void set_bitrate(int v);
void set_samplerate(int v);
void set_mtime(int v);
diff --git a/src/ui/edittagdialog.cpp b/src/ui/edittagdialog.cpp
index 8ac78ff47..c99bb0732 100644
--- a/src/ui/edittagdialog.cpp
+++ b/src/ui/edittagdialog.cpp
@@ -430,7 +430,7 @@ void EditTagDialog::UpdateSummaryTab(const Song& song) {
album_cover_choice_controller_->show_cover_action()->setEnabled(art_is_set);
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_->samplerate, song.samplerate(), "Hz");
SetText(ui_->bitrate, song.bitrate(), tr("kbps"));
diff --git a/src/ui/mainwindow.cpp b/src/ui/mainwindow.cpp
index 667bb4ff4..86d3fad1f 100644
--- a/src/ui/mainwindow.cpp
+++ b/src/ui/mainwindow.cpp
@@ -927,7 +927,7 @@ void MainWindow::UpdateTrackPosition() {
PlaylistItemPtr item(player_->GetCurrentItem());
const int position = std::floor(
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) {
// Probably a stream that we don't know the length of