From 507c5e26327cfd4296b952fe8ed5ca243729db14 Mon Sep 17 00:00:00 2001 From: David Sansome Date: Sun, 13 Feb 2011 18:34:30 +0000 Subject: [PATCH] Change the fields in Song from seconds to nanoseconds --- data/data.qrc | 1 + data/schema/schema-28.sql | 3 ++ src/core/database.cpp | 2 +- src/core/mpris1.cpp | 4 +-- src/core/mpris1.h | 2 +- src/core/mpris2.cpp | 6 ++-- src/core/organiseformat.cpp | 2 +- src/core/player.cpp | 8 ++--- src/core/song.cpp | 50 ++++++++++++++++-------------- src/core/song.h | 20 ++++++------ src/core/utilities.cpp | 8 +++++ src/core/utilities.h | 2 ++ src/library/librarybackend.cpp | 2 +- src/library/librarybackend.h | 4 +-- src/library/librarywatcher.cpp | 6 ++-- src/playlist/playlist.cpp | 8 ++--- src/playlist/playlistbackend.cpp | 2 +- src/playlist/playlistdelegates.cpp | 6 ++-- src/playlist/playlistmanager.cpp | 12 +++---- src/playlist/songplaylistitem.cpp | 8 ++--- src/playlistparsers/cueparser.cpp | 12 +++---- src/playlistparsers/cueparser.h | 2 +- src/playlistparsers/m3uparser.cpp | 4 ++- src/playlistparsers/parserbase.cpp | 2 +- src/playlistparsers/parserbase.h | 2 +- src/playlistparsers/plsparser.cpp | 4 +-- src/playlistparsers/xspfparser.cpp | 4 +-- src/radio/jamendoservice.cpp | 2 +- src/radio/magnatuneservice.cpp | 2 +- src/scripting/python/song.sip | 12 +++---- src/ui/edittagdialog.cpp | 2 +- src/ui/mainwindow.cpp | 2 +- 32 files changed, 113 insertions(+), 93 deletions(-) create mode 100644 data/schema/schema-28.sql 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