diff --git a/src/core/sdk/IOutput.h b/src/core/sdk/IOutput.h index 55b674556..6cbc2edf3 100644 --- a/src/core/sdk/IOutput.h +++ b/src/core/sdk/IOutput.h @@ -42,7 +42,7 @@ namespace musik { namespace core { namespace audio { class IOutput { - public: + public: virtual void Destroy() = 0; virtual void Pause() = 0; virtual void Resume() = 0; diff --git a/src/musikbox/app/window/TrackListView.cpp b/src/musikbox/app/window/TrackListView.cpp index 87a643c3c..9077ae75e 100755 --- a/src/musikbox/app/window/TrackListView.cpp +++ b/src/musikbox/app/window/TrackListView.cpp @@ -56,6 +56,17 @@ using namespace musik::core::library; using namespace musik::box; using namespace cursespp; +using namespace boost::chrono; + +/* if the user hasn't changed the selected index in 30 seconds +we assume he's not paying attention, and will automatically scroll +the view to the next track if it's invisible. */ +static const milliseconds AUTO_SCROLL_COOLDOWN = milliseconds(30000LL); + +static inline milliseconds now() { + return duration_cast(system_clock::now().time_since_epoch()); +} + static IScrollAdapter::EntryPtr MISSING_ENTRY = IScrollAdapter::EntryPtr(); TrackListView::TrackListView( @@ -69,6 +80,7 @@ TrackListView::TrackListView( this->playback.TrackChanged.connect(this, &TrackListView::OnTrackChanged); this->adapter = new Adapter(*this); this->lastQueryHash = 0; + this->lastChanged = now(); this->formatter = formatter; if (!MISSING_ENTRY) { @@ -94,6 +106,11 @@ void TrackListView::OnQueryCompleted(IQueryPtr query) { } } +void TrackListView::OnSelectionChanged(size_t newIndex, size_t oldIndex) { + ListWindow::OnSelectionChanged(newIndex, oldIndex); + this->lastChanged = now(); +} + std::shared_ptr TrackListView::GetTrackList() { return this->metadata; } @@ -110,8 +127,14 @@ void TrackListView::ScrollToPlaying() { DBID id = this->playing->Id(); for (size_t i = 0; i < this->metadata->Count(); i++) { if (this->metadata->GetId(i) == id) { - this->SetSelectedIndex(i); - this->ScrollTo(i); + auto pos = this->GetScrollPosition(); + size_t first = pos.firstVisibleEntryIndex; + size_t last = first + pos.visibleEntryCount; + if (i < first || i > last) { + /* only scroll if the playing track is not visible. */ + this->SetSelectedIndex(i); + this->ScrollTo(i); + } break; } } @@ -152,6 +175,10 @@ bool TrackListView::KeyPress(const std::string& key) { void TrackListView::OnTrackChanged(size_t index, musik::core::TrackPtr track) { this->playing = track; this->OnAdapterChanged(); + + if (now() - lastChanged >= AUTO_SCROLL_COOLDOWN) { + this->ScrollToPlaying(); + } } IScrollAdapter& TrackListView::GetScrollAdapter() { @@ -177,7 +204,7 @@ static std::string formatWithoutAlbum(TrackPtr track, size_t width) { TRACK_COL_WIDTH); std::string duration = text::Align( - duration::Duration(track->GetValue(constants::Track::DURATION)), + musik::box::duration::Duration(track->GetValue(constants::Track::DURATION)), text::AlignRight, DURATION_COL_WIDTH); diff --git a/src/musikbox/app/window/TrackListView.h b/src/musikbox/app/window/TrackListView.h index eca78339d..0b180c8f2 100755 --- a/src/musikbox/app/window/TrackListView.h +++ b/src/musikbox/app/window/TrackListView.h @@ -79,6 +79,7 @@ namespace musik { protected: virtual cursespp::IScrollAdapter& GetScrollAdapter(); void OnQueryCompleted(musik::core::IQueryPtr query); + void OnSelectionChanged(size_t newIndex, size_t oldIndex); class Adapter : public cursespp::ScrollAdapterBase { public: @@ -106,6 +107,7 @@ namespace musik { musik::core::LibraryPtr library; size_t lastQueryHash; RowFormatter formatter; + boost::chrono::milliseconds lastChanged; }; } }