Change the fields in Song from seconds to nanoseconds

This commit is contained in:
David Sansome 2011-02-13 18:34:30 +00:00
parent 37618dae96
commit 507c5e2632
32 changed files with 113 additions and 93 deletions

View File

@ -298,5 +298,6 @@
<file>schema/schema-26.sql</file>
<file>pythonstartup.py</file>
<file>schema/schema-27.sql</file>
<file>schema/schema-28.sql</file>
</qresource>
</RCC>

View File

@ -0,0 +1,3 @@
UPDATE %allsongstables SET length=length*1e9, beginning=beginning*1e9;
UPDATE schema_version SET version=28;

View File

@ -31,7 +31,7 @@
#include <QVariant>
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;

View File

@ -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);

View File

@ -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;

View File

@ -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);
}
}

View File

@ -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);

View File

@ -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())

View File

@ -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<bool> 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) {

View File

@ -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_;

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -397,9 +397,9 @@ void LibraryWatcher::UpdateCueAssociatedSongs(const QString& file, const QString
SongList old_sections = backend_->GetSongsByFilename(file);
QHash<int, Song> sections_map;
QHash<quint64, Song> sections_map;
foreach(const Song& song, old_sections) {
sections_map[song.beginning()] = song;
sections_map[song.beginning_nanosec()] = song;
}
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)) {
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;

View File

@ -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;
}

View File

@ -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));

View File

@ -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;
}

View File

@ -264,7 +264,7 @@ void PlaylistManager::ChangePlaylistOrder(const QList<int>& 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);
}

View File

@ -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);
}

View File

@ -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 {

View File

@ -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

View File

@ -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");

View File

@ -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();

View File

@ -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_;

View File

@ -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;
}
}

View File

@ -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();

View File

@ -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.

View File

@ -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);

View File

@ -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);

View File

@ -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"));

View File

@ -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