From 37618dae968faf3584d67b3a3ed31f1122ec617f Mon Sep 17 00:00:00 2001 From: David Sansome Date: Sun, 13 Feb 2011 18:29:27 +0000 Subject: [PATCH] Use nanoseconds instead of seconds or milliseconds throughout the Player and Engine. --- src/core/mpris1.cpp | 6 +-- src/core/mpris2.cpp | 8 ++-- src/core/player.cpp | 21 +++++----- src/engines/enginebase.cpp | 21 +++++----- src/engines/enginebase.h | 24 +++++------ src/engines/gstengine.cpp | 68 +++++++++++++++---------------- src/engines/gstengine.h | 20 ++++----- src/engines/gstenginepipeline.cpp | 12 +++--- src/engines/gstenginepipeline.h | 6 +-- src/ui/mainwindow.cpp | 11 ++--- 10 files changed, 101 insertions(+), 96 deletions(-) diff --git a/src/core/mpris1.cpp b/src/core/mpris1.cpp index 20e7077a3..24efeb338 100644 --- a/src/core/mpris1.cpp +++ b/src/core/mpris1.cpp @@ -191,12 +191,12 @@ int Mpris1Player::VolumeGet() const { return player_->GetVolume(); } -void Mpris1Player::PositionSet(int pos) { - player_->Seek(pos/1000); +void Mpris1Player::PositionSet(int pos_msec) { + player_->Seek(pos_msec / 1e3); } int Mpris1Player::PositionGet() const { - return player_->engine()->position(); + return player_->engine()->position_nanosec() / 1e6; } QVariantMap Mpris1Player::GetMetadata() const { diff --git a/src/core/mpris2.cpp b/src/core/mpris2.cpp index 03829ef0a..fe9f86c18 100644 --- a/src/core/mpris2.cpp +++ b/src/core/mpris2.cpp @@ -325,7 +325,7 @@ void Mpris2::SetVolume(double value) { } qlonglong Mpris2::Position() const { - return mpris1_->player()->PositionGet() * 1e3; + return mpris1_->player()->PositionGet() / 1e3; } double Mpris2::MaximumRate() const { @@ -400,16 +400,16 @@ void Mpris2::Play() { void Mpris2::Seek(qlonglong offset) { if(CanSeek()) { - player_->Seek((Position() + offset) / 1e6); + player_->Seek(player_->engine()->position_nanosec() / 1e9 + offset / 1e6); } } void Mpris2::SetPosition(const QDBusObjectPath& trackId, qlonglong offset) { if (CanSeek() && trackId.path() == current_track_id() && offset >= 0) { - offset /= 1e6; + offset *= 1e3; if(offset < player_->GetCurrentItem()->Metadata().length()) { - player_->Seek(offset); + player_->Seek(offset / 1e9); } } } diff --git a/src/core/player.cpp b/src/core/player.cpp index 3506b3eaf..9a15967d3 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() * 1000, - item->Metadata().end() * 1000); + item->Metadata().beginning() * 1e9, + item->Metadata().end() * 1e9); current_item_ = item; loading_async_ = QUrl(); @@ -245,7 +245,7 @@ int Player::GetVolume() const { } void Player::PlayAt(int index, Engine::TrackChangeType change, bool reshuffle) { - if (change == Engine::Manual && engine_->position() != engine_->length()) { + if (change == Engine::Manual && engine_->position_nanosec() != engine_->length_nanosec()) { emit TrackSkipped(current_item_); } @@ -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() * 1000, - current_item_->Metadata().end() * 1000); + current_item_->Metadata().beginning() * 1e9, + current_item_->Metadata().end() * 1e9); #ifdef HAVE_LIBLASTFM if (lastfm_->IsScrobblingEnabled()) @@ -283,21 +283,22 @@ void Player::CurrentMetadataChanged(const Song& metadata) { } void Player::Seek(int seconds) { - int msec = qBound(0, seconds * 1000, int(engine_->length())); - engine_->Seek(msec); + qint64 nanosec = qBound(0ll, qint64(seconds) * qint64(1e9), + engine_->length_nanosec()); + engine_->Seek(nanosec); // If we seek the track we don't want to submit it to last.fm playlists_->active()->set_scrobbled(true); - emit Seeked(msec * 1000); + emit Seeked(nanosec / 1000); } void Player::SeekForward() { - Seek(engine()->position() / 1000 + 5); + Seek(engine()->position_nanosec() / 1e9 + 5); } void Player::SeekBackward() { - Seek(engine()->position() / 1000 - 5); + Seek(engine()->position_nanosec() / 1e9 - 5); } void Player::EngineMetadataReceived(const Engine::SimpleMetaBundle& bundle) { diff --git a/src/engines/enginebase.cpp b/src/engines/enginebase.cpp index 71c2f2f0c..29e21d6ab 100644 --- a/src/engines/enginebase.cpp +++ b/src/engines/enginebase.cpp @@ -29,11 +29,11 @@ const char* Engine::Base::kSettingsGroup = "Player"; Engine::Base::Base() : volume_(50), - beginning_(0), - end_(0), + beginning_nanosec_(0), + end_nanosec_(0), scope_(kScopeSize), fadeout_enabled_(true), - fadeout_duration_(2000), + fadeout_duration_nanosec_(2000 * 1e6), // 2s crossfade_enabled_(true), next_background_stream_id_(0), about_to_end_emitted_(false) @@ -43,11 +43,11 @@ Engine::Base::Base() Engine::Base::~Base() { } -bool Engine::Base::Load(const QUrl &url, TrackChangeType, - uint beginning, int end) { +bool Engine::Base::Load(const QUrl& url, TrackChangeType, + quint64 beginning_nanosec, qint64 end_nanosec) { url_ = url; - beginning_ = beginning; - end_ = end; + beginning_nanosec_ = beginning_nanosec; + end_nanosec_ = end_nanosec; about_to_end_emitted_ = false; return true; @@ -69,7 +69,7 @@ void Engine::Base::ReloadSettings() { s.beginGroup(kSettingsGroup); fadeout_enabled_ = s.value("FadeoutEnabled", true).toBool(); - fadeout_duration_ = s.value("FadeoutDuration", 2000).toInt(); + fadeout_duration_nanosec_ = s.value("FadeoutDuration", 2000).toLongLong() * 1e6; crossfade_enabled_ = s.value("CrossfadeEnabled", true).toBool(); autocrossfade_enabled_ = s.value("AutoCrossfadeEnabled", false).toBool(); } @@ -86,8 +86,9 @@ int Engine::Base::AddBackgroundStream(const QUrl& url) { return -1; } -bool Engine::Base::Play(const QUrl& u, TrackChangeType c, uint beginning, int end) { - if (!Load(u, c, beginning, end)) +bool Engine::Base::Play(const QUrl& u, TrackChangeType c, + quint64 beginning_nanosec, qint64 end_nanosec) { + if (!Load(u, c, beginning_nanosec, end_nanosec)) return false; return Play(0); diff --git a/src/engines/enginebase.h b/src/engines/enginebase.h index 3032d463a..5f916f81b 100644 --- a/src/engines/enginebase.h +++ b/src/engines/enginebase.h @@ -46,31 +46,31 @@ class Base : public QObject, boost::noncopyable { virtual bool CanDecode(const QUrl &url) = 0; virtual void StartPreloading(const QUrl&) {} - virtual bool Play(uint offset) = 0; + virtual bool Play(quint64 offset_nanosec) = 0; virtual void Stop() = 0; virtual void Pause() = 0; virtual void Unpause() = 0; - virtual void Seek( uint ms ) = 0; + virtual void Seek(quint64 offset_nanosec) = 0; virtual int AddBackgroundStream(const QUrl& url); virtual void StopBackgroundStream(int id) {} virtual void SetBackgroundStreamVolume(int id, int volume) {} virtual State state() const = 0; - virtual uint position() const = 0; - virtual uint length() const { return 0; } + virtual qint64 position_nanosec() const = 0; + virtual qint64 length_nanosec() const = 0; // Subclasses should respect given markers (beginning and end) which are // in miliseconds. virtual bool Load(const QUrl& url, TrackChangeType change, - uint beginning, int end); + quint64 beginning_nanosec, qint64 end_nanosec); // Plays a media stream represented with the URL 'u' from the given 'beginning' // to the given 'end' (usually from 0 to a song's length). Both markers - // should be passed in miliseconds. 'end' can be negative, indicating that the + // should be passed in nanoseconds. 'end' can be negative, indicating that the // real length of 'u' stream is unknown. bool Play(const QUrl& u, TrackChangeType c, - uint beginning, int end); + quint64 beginning_nanosec, qint64 end_nanosec); void SetVolume(uint value); @@ -115,14 +115,14 @@ class Base : public QObject, boost::noncopyable { void EmitAboutToEnd(); protected: - uint volume_; - uint beginning_; - int end_; - QUrl url_; + uint volume_; + quint64 beginning_nanosec_; + qint64 end_nanosec_; + QUrl url_; Scope scope_; bool fadeout_enabled_; - int fadeout_duration_; + qint64 fadeout_duration_nanosec_; bool crossfade_enabled_; bool autocrossfade_enabled_; int next_background_stream_id_; diff --git a/src/engines/gstengine.cpp b/src/engines/gstengine.cpp index 383dfd22f..45ed60c69 100644 --- a/src/engines/gstengine.cpp +++ b/src/engines/gstengine.cpp @@ -75,13 +75,13 @@ GstEngine::GstEngine() rg_mode_(0), rg_preamp_(0.0), rg_compression_(true), - buffer_duration_ms_(1000), + buffer_duration_nanosec_(1000 * 1e6), // 1s seek_timer_(new QTimer(this)), timer_id_(-1), next_element_id_(0) { seek_timer_->setSingleShot(true); - seek_timer_->setInterval(kSeekDelay); + seek_timer_->setInterval(kSeekDelayNanosec / 1e6); connect(seek_timer_, SIGNAL(timeout()), SLOT(SeekNow())); ReloadSettings(); @@ -168,7 +168,7 @@ void GstEngine::ReloadSettings() { rg_preamp_ = s.value("rgpreamp", 0.0).toDouble(); rg_compression_ = s.value("rgcompression", true).toBool(); - buffer_duration_ms_ = s.value("bufferduration", 1000).toInt(); + buffer_duration_nanosec_ = s.value("bufferduration", 1000).toLongLong() * 1e6; } @@ -263,20 +263,20 @@ gboolean GstEngine::CanDecodeBusCallback(GstBus*, GstMessage* msg, gpointer) { } -uint GstEngine::position() const { +qint64 GstEngine::position_nanosec() const { if (!current_pipeline_) return 0; - int result = (current_pipeline_->position() / GST_MSECOND) - beginning_; - return uint(qMax(0, result)); + qint64 result = current_pipeline_->position() - beginning_nanosec_; + return qint64(qMax(0ll, result)); } -uint GstEngine::length() const { +qint64 GstEngine::length_nanosec() const { if (!current_pipeline_) return 0; - int result = end_ - beginning_; - return uint(qMax(0, result)); + qint64 result = end_nanosec_ - beginning_nanosec_; + return qint64(qMax(0ll, result)); } Engine::State GstEngine::state() const { @@ -442,10 +442,10 @@ QUrl GstEngine::FixupUrl(const QUrl& url) { } bool GstEngine::Load(const QUrl& url, Engine::TrackChangeType change, - uint beginning, int end) { + quint64 beginning_nanosec, qint64 end_nanosec) { EnsureInitialised(); - Engine::Base::Load(url, change, beginning, end); + Engine::Base::Load(url, change, beginning_nanosec, end_nanosec); // Clementine just crashes when asked to load a file that doesn't exist on // Windows, so check for that here. This is definitely the wrong place for @@ -490,7 +490,7 @@ bool GstEngine::Load(const QUrl& url, Engine::TrackChangeType change, // Maybe fade in this track if (crossfade) - current_pipeline_->StartFader(fadeout_duration_, QTimeLine::Forward); + current_pipeline_->StartFader(fadeout_duration_nanosec_, QTimeLine::Forward); return true; } @@ -501,20 +501,20 @@ void GstEngine::StartFadeout() { fadeout_pipeline_->RemoveAllBufferConsumers(); ClearScopeBuffers(); - fadeout_pipeline_->StartFader(fadeout_duration_, QTimeLine::Backward); + fadeout_pipeline_->StartFader(fadeout_duration_nanosec_, QTimeLine::Backward); connect(fadeout_pipeline_.get(), SIGNAL(FaderFinished()), SLOT(FadeoutFinished())); } -bool GstEngine::Play(uint offset) { +bool GstEngine::Play(quint64 offset_nanosec) { EnsureInitialised(); if (!current_pipeline_) return false; QFuture future = current_pipeline_->SetState(GST_STATE_PLAYING); - BoundFutureWatcher* watcher = - new BoundFutureWatcher(offset, this); + BoundFutureWatcher* watcher = + new BoundFutureWatcher(offset_nanosec, this); watcher->setFuture(future); connect(watcher, SIGNAL(finished()), SLOT(PlayDone())); @@ -522,12 +522,12 @@ bool GstEngine::Play(uint offset) { } void GstEngine::PlayDone() { - BoundFutureWatcher* watcher = - static_cast*>(sender()); + BoundFutureWatcher* watcher = + static_cast*>(sender()); watcher->deleteLater(); GstStateChangeReturn ret = watcher->result(); - uint offset = watcher->data(); + quint64 offset_nanosec = watcher->data(); if (!current_pipeline_) return; @@ -538,7 +538,7 @@ void GstEngine::PlayDone() { if (!redirect_url.isEmpty() && redirect_url != current_pipeline_->url()) { qDebug() << "Redirecting to" << redirect_url; current_pipeline_ = CreatePipeline(redirect_url); - Play(offset); + Play(offset_nanosec); return; } @@ -553,8 +553,8 @@ void GstEngine::PlayDone() { current_sample_ = 0; // initial offset - if(offset != 0 || beginning_ != 0) { - Seek(offset); + if(offset_nanosec != 0 || beginning_nanosec_ != 0) { + Seek(offset_nanosec); } emit StateChanged(Engine::Playing); @@ -565,7 +565,7 @@ void GstEngine::Stop() { StopTimers(); url_ = QUrl(); // To ensure we return Empty from state() - beginning_ = end_ = 0; + beginning_nanosec_ = end_nanosec_ = 0; if (fadeout_enabled_ && current_pipeline_) StartFadeout(); @@ -602,11 +602,11 @@ void GstEngine::Unpause() { } } -void GstEngine::Seek(uint ms) { +void GstEngine::Seek(quint64 offset_nanosec) { if (!current_pipeline_) return; - seek_pos_ = beginning_ + ms; + seek_pos_ = beginning_nanosec_ + offset_nanosec; waiting_to_seek_ = true; if (!seek_timer_->isActive()) { @@ -622,7 +622,7 @@ void GstEngine::SeekNow() { if (!current_pipeline_) return; - if (current_pipeline_->Seek(seek_pos_ * GST_MSECOND)) + if (current_pipeline_->Seek(seek_pos_)) ClearScopeBuffers(); else qDebug() << "Seek failed"; @@ -652,7 +652,7 @@ void GstEngine::SetVolumeSW( uint percent ) { void GstEngine::StartTimers() { StopTimers(); - timer_id_ = startTimer(kTimerInterval); + timer_id_ = startTimer(kTimerIntervalNanosec / 1e6); } void GstEngine::StopTimers() { @@ -672,13 +672,13 @@ void GstEngine::timerEvent(QTimerEvent* e) { PruneScope(); if (current_pipeline_) { - const qint64 current_position = position(); - const qint64 current_length = length(); + const qint64 current_position = position_nanosec(); + const qint64 current_length = length_nanosec(); const qint64 remaining = current_length - current_position; - const qint64 fudge = kTimerInterval + 100; // Mmm fudge - const qint64 gap = autocrossfade_enabled_ ? fadeout_duration_ : kPreloadGap; + const qint64 fudge = kTimerIntervalNanosec + 100 * 1e6; // Mmm fudge + const qint64 gap = autocrossfade_enabled_ ? fadeout_duration_nanosec_ : kPreloadGapNanosec; // only if we know the length of the current stream... if(current_length > 0) { @@ -692,7 +692,7 @@ void GstEngine::timerEvent(QTimerEvent* e) { // check to allow for the fact that the length has been rounded down to // the nearest second, and to stop us from occasionally stopping the // stream just before it ends normally. - if(current_position >= current_length + 1000) { + if(current_position >= current_length + 1000 * 1e6) { EndOfStreamReached(current_pipeline_->has_next_valid_url()); } } @@ -774,7 +774,7 @@ shared_ptr GstEngine::CreatePipeline() { shared_ptr ret(new GstEnginePipeline(this)); ret->set_output_device(sink_, device_); ret->set_replaygain(rg_enabled_, rg_mode_, rg_preamp_, rg_compression_); - ret->set_buffer_duration_ms(buffer_duration_ms_); + ret->set_buffer_duration_nanosec(buffer_duration_nanosec_); ret->AddBufferConsumer(this); foreach (BufferConsumer* consumer, buffer_consumers_) @@ -808,7 +808,7 @@ qint64 GstEngine::PruneScope() { return 0; // get the position playing in the audio device - const qint64 pos = position() * 1e6; + const qint64 pos = position_nanosec(); const qint64 segment_start = current_pipeline_->segment_start(); GstBuffer *buf = 0; diff --git a/src/engines/gstengine.h b/src/engines/gstengine.h index 20eb3e4f5..27273daa0 100644 --- a/src/engines/gstengine.h +++ b/src/engines/gstengine.h @@ -72,8 +72,8 @@ class GstEngine : public Engine::Base, public BufferConsumer { void StopBackgroundStream(int id); void SetBackgroundStreamVolume(int id, int volume); - uint position() const; - uint length() const; + qint64 position_nanosec() const; + qint64 length_nanosec() const; Engine::State state() const; const Engine::Scope& scope(); @@ -88,12 +88,12 @@ class GstEngine : public Engine::Base, public BufferConsumer { public slots: void StartPreloading(const QUrl &); bool Load(const QUrl&, Engine::TrackChangeType change, - uint beginning, int end); - bool Play(uint offset); + quint64 beginning_nanosec, qint64 end_nanosec); + bool Play(quint64 offset_nanosec); void Stop(); void Pause(); void Unpause(); - void Seek(uint ms); + void Seek(quint64 offset_nanosec); /** Set whether equalizer is enabled */ void SetEqualizerEnabled(bool); @@ -150,9 +150,9 @@ class GstEngine : public Engine::Base, public BufferConsumer { static QUrl FixupUrl(const QUrl& url); private: - static const int kTimerInterval = 1000; // msec - static const int kPreloadGap = 1000; // msec - static const int kSeekDelay = 100; // msec + static const int kTimerIntervalNanosec = 1000 * 1e6; // 1s + static const int kPreloadGapNanosec = 1000 * 1e6; // 1s + static const int kSeekDelayNanosec = 100 * 1e6; // 100msec static const char* kHypnotoadPipeline; @@ -181,7 +181,7 @@ class GstEngine : public Engine::Base, public BufferConsumer { float rg_preamp_; bool rg_compression_; - int buffer_duration_ms_; + qint64 buffer_duration_nanosec_; mutable bool can_decode_success_; mutable bool can_decode_last_; @@ -189,7 +189,7 @@ class GstEngine : public Engine::Base, public BufferConsumer { // Hack to stop seeks happening too often QTimer* seek_timer_; bool waiting_to_seek_; - uint seek_pos_; + quint64 seek_pos_; int timer_id_; int next_element_id_; diff --git a/src/engines/gstenginepipeline.cpp b/src/engines/gstenginepipeline.cpp index e5bc1d155..b0c8a4e4f 100644 --- a/src/engines/gstenginepipeline.cpp +++ b/src/engines/gstenginepipeline.cpp @@ -48,7 +48,7 @@ GstEnginePipeline::GstEnginePipeline(GstEngine* engine) rg_mode_(0), rg_preamp_(0.0), rg_compression_(true), - buffer_duration_ms_(1000), + buffer_duration_nanosec_(1000 * 1e6), ignore_tags_(false), volume_percent_(100), volume_modifier_(1.0), @@ -86,8 +86,8 @@ void GstEnginePipeline::set_replaygain(bool enabled, int mode, float preamp, rg_compression_ = compression; } -void GstEnginePipeline::set_buffer_duration_ms(int buffer_duration_ms) { - buffer_duration_ms_ = buffer_duration_ms; +void GstEnginePipeline::set_buffer_duration_nanosec(qint64 buffer_duration_nanosec) { + buffer_duration_nanosec_ = buffer_duration_nanosec; } bool GstEnginePipeline::ReplaceDecodeBin(GstElement* new_bin) { @@ -112,7 +112,7 @@ bool GstEnginePipeline::ReplaceDecodeBin(GstElement* new_bin) { bool GstEnginePipeline::ReplaceDecodeBin(const QUrl& url) { GstElement* new_bin = engine_->CreateElement("uridecodebin"); g_object_set(G_OBJECT(new_bin), "uri", url.toEncoded().constData(), NULL); - g_object_set(G_OBJECT(new_bin), "buffer-duration", buffer_duration_ms_ * 1000 * 1000, NULL); + g_object_set(G_OBJECT(new_bin), "buffer-duration", buffer_duration_nanosec_, NULL); g_object_set(G_OBJECT(new_bin), "download", true, NULL); g_object_set(G_OBJECT(new_bin), "use-buffering", true, NULL); g_signal_connect(G_OBJECT(new_bin), "drained", G_CALLBACK(SourceDrainedCallback), this); @@ -529,9 +529,11 @@ void GstEnginePipeline::UpdateVolume() { g_object_set(G_OBJECT(volume_), "volume", vol, NULL); } -void GstEnginePipeline::StartFader(int duration_msec, +void GstEnginePipeline::StartFader(qint64 duration_nanosec, QTimeLine::Direction direction, QTimeLine::CurveShape shape) { + const int duration_msec = duration_nanosec / 1e6; + // If there's already another fader running then start from the same time // that one was already at. int start_time = direction == QTimeLine::Forward ? 0 : duration_msec; diff --git a/src/engines/gstenginepipeline.h b/src/engines/gstenginepipeline.h index 579eb0527..0d00981ce 100644 --- a/src/engines/gstenginepipeline.h +++ b/src/engines/gstenginepipeline.h @@ -46,7 +46,7 @@ class GstEnginePipeline : public QObject { // Call these setters before Init void set_output_device(const QString& sink, const QString& device); void set_replaygain(bool enabled, int mode, float preamp, bool compression); - void set_buffer_duration_ms(int duration_ms); + void set_buffer_duration_nanosec(qint64 duration_nanosec); // Creates the pipeline, returns false on error bool InitFromUrl(const QUrl& url); @@ -63,7 +63,7 @@ class GstEnginePipeline : public QObject { void SetEqualizerEnabled(bool enabled); void SetEqualizerParams(int preamp, const QList& band_gains); void SetVolume(int percent); - void StartFader(int duration_msec, + void StartFader(qint64 duration_nanosec, QTimeLine::Direction direction = QTimeLine::Forward, QTimeLine::CurveShape shape = QTimeLine::LinearCurve); @@ -154,7 +154,7 @@ class GstEnginePipeline : public QObject { int rg_mode_; float rg_preamp_; bool rg_compression_; - quint64 buffer_duration_ms_; + quint64 buffer_duration_nanosec_; // The URL that is currently playing, and the URL that is to be preloaded // when the current track is close to finishing. diff --git a/src/ui/mainwindow.cpp b/src/ui/mainwindow.cpp index c484a515f..667bb4ff4 100644 --- a/src/ui/mainwindow.cpp +++ b/src/ui/mainwindow.cpp @@ -806,8 +806,8 @@ void MainWindow::TrackSkipped(PlaylistItemPtr item) { // the database. if (item && item->IsLocalLibraryItem() && !playlists_->active()->has_scrobbled()) { Song song = item->Metadata(); - const int position = player_->engine()->position(); - const int length = player_->engine()->length(); + const qint64 position = player_->engine()->position_nanosec(); + const qint64 length = player_->engine()->length_nanosec(); const float percentage = (length == 0 ? 1 : float(position) / length); library_->backend()->IncrementSkipCountAsync(song.id(), percentage); @@ -925,7 +925,8 @@ void MainWindow::FilePathChanged(const QString& path) { void MainWindow::UpdateTrackPosition() { // Track position in seconds PlaylistItemPtr item(player_->GetCurrentItem()); - const int position = std::floor(float(player_->engine()->position()) / 1000.0 + 0.5); + const int position = std::floor( + float(player_->engine()->position_nanosec()) / 1e9 + 0.5); const int length = item->Metadata().length(); if (length <= 0) { @@ -1399,9 +1400,9 @@ void MainWindow::CommandlineOptionsReceived(const CommandlineOptions &options) { player_->SetVolume(player_->GetVolume() + options.volume_modifier()); if (options.seek_to() != -1) - player_->Seek(options.seek_to()); + player_->Seek(options.seek_to() * 1e9); else if (options.seek_by() != 0) - player_->Seek(player_->engine()->position() / 1000 + options.seek_by()); + player_->Seek(player_->engine()->position_nanosec() + options.seek_by() * 1e9); if (options.play_track_at() != -1) player_->PlayAt(options.play_track_at(), Engine::Manual, true);