Added a new "syncing" banner to the MainLayout. This also exposed some

bugs related to relative positioning in Window.
This commit is contained in:
casey langen 2017-03-09 17:30:24 -08:00
parent 8b1cac7f9b
commit 5d2a3bcc2e
17 changed files with 151 additions and 41 deletions

View File

@ -41,10 +41,15 @@
namespace musik { namespace core {
class IIndexer {
public:
sigslot::signal0<> SynchronizeStart;
sigslot::signal0<> SynchronizeEnd;
sigslot::signal0<> Started;
sigslot::signal1<int> Finished;
sigslot::signal0<> PathsUpdated;
sigslot::signal0<> TrackRefreshed;
sigslot::signal1<int> Progress;
enum State {
StateIdle,
StateIndexing
};
virtual ~IIndexer() { }
@ -52,5 +57,6 @@ namespace musik { namespace core {
virtual void RemovePath(const std::string& path) = 0;
virtual void GetPaths(std::vector<std::string>& paths) = 0;
virtual void Synchronize(bool restart = false) = 0;
virtual State GetState() = 0;
};
} }

View File

@ -57,7 +57,7 @@
static const std::string TAG = "Indexer";
static const int MAX_THREADS = 2;
static const size_t NOTIFY_INTERVAL = 300;
static const size_t TRANSACTION_INTERVAL = 300;
using namespace musik::core;
using namespace musik::core::sdk;
@ -85,6 +85,7 @@ Indexer::Indexer(const std::string& libraryPath, const std::string& dbFilename)
, restart(false)
, filesSaved(0)
, exit(false)
, state(StateIdle)
, prefs(Preferences::ForComponent(prefs::components::Settings))
, readSemaphore(prefs->GetInt(prefs::keys::MaxTagReadThreads, MAX_THREADS)) {
this->dbFilename = dbFilename;
@ -214,13 +215,15 @@ void Indexer::FinalizeSync() {
}
/* notify observers */
this->TrackRefreshed();
this->Progress(this->filesSaved);
/* unload reader DLLs*/
this->metadataReaders.clear();
this->RunAnalyzers();
this->state = StateIdle;
IndexerTrack::ResetIdCache();
}
@ -297,6 +300,8 @@ void Indexer::ReadMetadataFromFile(
}
}
++this->filesSaved;
#ifdef MULTI_THREADED_INDEXER
this->readSemaphore.post();
#endif
@ -330,12 +335,12 @@ void Indexer::SyncDirectory(
std::vector<Thread> threads;
for( ; file != end && !this->Exited() && !this->Restarted(); file++) {
if (this->filesSaved > NOTIFY_INTERVAL) {
if (this->filesSaved > TRANSACTION_INTERVAL) {
if (this->trackTransaction) {
this->trackTransaction->CommitAndRestart();
}
this->TrackRefreshed();
this->Progress(this->filesSaved);
this->filesSaved = 0;
}
if (is_directory(file->status())) {
@ -378,7 +383,8 @@ void Indexer::ThreadLoop() {
this->restart = false;
if(!firstTime || (firstTime && prefs->GetBool(prefs::keys::SyncOnStartup, true))) { /* first time through the loop skips this */
this->SynchronizeStart();
this->state = StateIndexing;
this->Started();
this->dbConnection.Open(this->dbFilename.c_str(), 0); /* ensure the db is open */
@ -405,7 +411,11 @@ void Indexer::ThreadLoop() {
this->FinalizeSync();
this->dbConnection.Close(); /* TODO: raii */
this->SynchronizeEnd();
if (!restart) {
this->Finished(this->filesSaved);
}
musik::debug::info(TAG, "done!");
} /* end skip */

View File

@ -66,6 +66,7 @@ namespace musik { namespace core {
virtual void RemovePath(const std::string& paths);
virtual void GetPaths(std::vector<std::string>& paths);
virtual void Synchronize(bool restart = false);
virtual State GetState() { return this->state; }
private:
void ThreadLoop();
@ -101,6 +102,7 @@ namespace musik { namespace core {
bool restart;
bool exit;
State state;
boost::mutex stateMutex;
boost::condition waitCondition;

View File

@ -149,7 +149,7 @@ int main(int argc, char* argv[])
Layout consoleLayout(new ConsoleLayout(transport, library));
Layout settingsLayout(new SettingsLayout(library, transport));
Main mainLayout(new MainLayout());
Main mainLayout(new MainLayout(library));
std::vector<std::string> paths;
library->Indexer()->GetPaths(paths);

View File

@ -83,8 +83,8 @@ BrowseLayout::BrowseLayout(
: LayoutBase()
, playback(playback) {
this->library = library;
this->library->Indexer()->TrackRefreshed.connect(this, &BrowseLayout::OnIndexerProgress);
this->library->Indexer()->SynchronizeEnd.connect(this, &BrowseLayout::OnIndexerProgress);
this->library->Indexer()->Progress.connect(this, &BrowseLayout::OnIndexerProgress);
this->library->Indexer()->Finished.connect(this, &BrowseLayout::OnIndexerProgress);
this->InitializeWindows();
}
@ -93,7 +93,7 @@ BrowseLayout::~BrowseLayout() {
void BrowseLayout::OnLayout() {
size_t cx = this->GetWidth(), cy = this->GetHeight();
size_t x = this->GetX(), y = this->GetY();
size_t x = 0, y = 0;
size_t categoryWidth = std::min(MAX_CATEGORY_WIDTH, cx / 4);
@ -161,7 +161,7 @@ void BrowseLayout::OnVisibilityChanged(bool visible) {
}
}
void BrowseLayout::OnIndexerProgress() {
void BrowseLayout::OnIndexerProgress(int count) {
this->categoryList->Requery();
}

View File

@ -74,7 +74,7 @@ namespace musik {
private:
void InitializeWindows();
void OnIndexerProgress();
void OnIndexerProgress(int count);
void RequeryTrackList(cursespp::ListWindow *view);
void OnCategoryViewSelectionChanged(

View File

@ -96,17 +96,15 @@ ConsoleLayout::~ConsoleLayout() {
void ConsoleLayout::OnLayout() {
const int cx = this->GetWidth();
const int cy = this->GetHeight();
const int x = this->GetX();
const int y = this->GetY();
const int leftCx = cx / 2;
const int rightCx = cx - leftCx;
/* top left */
this->output->MoveAndResize(x, y, leftCx, cy - 3);
this->output->MoveAndResize(0, 0, leftCx, cy - 3);
/* bottom left */
this->commands->MoveAndResize(x, cy - 3, leftCx, 3);
this->commands->MoveAndResize(0, cy - 3, leftCx, 3);
/* right */
this->logs->MoveAndResize(cx / 2, 0, rightCx, cy);

View File

@ -72,7 +72,7 @@ LibraryLayout::~LibraryLayout() {
}
void LibraryLayout::OnLayout() {
int x = this->GetX(), y = this->GetY();
int x = 0, y = 0;
int cx = this->GetWidth(), cy = this->GetHeight();
int mainHeight = cy - TRANSPORT_HEIGHT;

View File

@ -35,24 +35,45 @@
#include "stdafx.h"
#include <cursespp/Screen.h>
#include <cursespp/Colors.h>
#include <core/runtime/Message.h>
#include <app/util/PreferenceKeys.h>
#include "SettingsLayout.h"
#include "MainLayout.h"
#define MESSAGE_INDEXER_STARTED 1000
#define MESSAGE_INDEXER_PROGRESS 1001
#define MESSAGE_INDEXER_FINISHED 1002
#define SYNCING_TEXT_FORMAT "syncing metadata (%d tracks processed)"
using namespace musik;
using namespace musik::box;
using namespace musik::core;
using namespace musik::core::runtime;
using namespace cursespp;
MainLayout::MainLayout()
static void updateSyncingText(TextLabel* label, int updates) {
label->SetText(boost::str(boost::format(
SYNCING_TEXT_FORMAT) % updates), cursespp::text::AlignCenter);
}
MainLayout::MainLayout(ILibraryPtr library)
: shortcutsFocused(false)
, topLevelLayout(nullptr)
, syncUpdateCount(0)
, library(library)
, LayoutBase() {
this->Initialize();
this->prefs = Preferences::ForComponent("settings");
this->ResizeToViewport();
library->Indexer()->Started.connect(this, &MainLayout::OnIndexerStarted);
library->Indexer()->Finished.connect(this, &MainLayout::OnIndexerFinished);
library->Indexer()->Progress.connect(this, &MainLayout::OnIndexerProgress);
}
MainLayout::~MainLayout() {
@ -65,8 +86,20 @@ void MainLayout::ResizeToViewport() {
void MainLayout::OnLayout() {
size_t cx = Screen::GetWidth(), cy = Screen::GetHeight();
int yOffset = 0;
auto state = this->library->Indexer()->GetState();
if (state == IIndexer::StateIndexing) {
yOffset = 1;
this->syncing->MoveAndResize(0, 0, cx, 1);
this->syncing->Show();
}
else {
this->syncing->Hide();
}
if (this->layout) {
this->layout->MoveAndResize(0, 0, cx, cy - 1);
this->layout->MoveAndResize(0, yOffset, cx, cy - 1 - yOffset);
this->layout->Show();
this->layout->BringToTop();
@ -81,6 +114,10 @@ void MainLayout::OnLayout() {
void MainLayout::Initialize() {
this->shortcuts.reset(new ShortcutsWindow());
this->AddWindow(this->shortcuts);
this->syncing.reset(new TextLabel());
this->syncing->SetContentColor(CURSESPP_BANNER);
this->AddWindow(this->syncing);
}
cursespp::IWindowPtr MainLayout::GetFocus() {
@ -201,3 +238,34 @@ bool MainLayout::KeyPress(const std::string& key) {
return this->layout ? this->layout->KeyPress(key) : false;
}
void MainLayout::ProcessMessage(musik::core::runtime::IMessage &message) {
int type = message.Type();
if (type == MESSAGE_INDEXER_STARTED) {
updateSyncingText(this->syncing.get(), 0);
this->syncUpdateCount = 0;
if (!syncing->IsVisible()) {
this->Layout();
}
}
else if (type == MESSAGE_INDEXER_FINISHED) {
this->Layout();
}
else if (type == MESSAGE_INDEXER_PROGRESS) {
this->syncUpdateCount += (int)message.UserData1();
updateSyncingText(this->syncing.get(), this->syncUpdateCount);
}
}
void MainLayout::OnIndexerStarted() {
this->PostMessage(MESSAGE_INDEXER_STARTED);
}
void MainLayout::OnIndexerProgress(int count) {
this->PostMessage(MESSAGE_INDEXER_PROGRESS, count);
}
void MainLayout::OnIndexerFinished(int count) {
this->PostMessage(MESSAGE_INDEXER_FINISHED);
}

View File

@ -39,6 +39,8 @@
#include <cursespp/ShortcutsWindow.h>
#include <cursespp/IViewRoot.h>
#include <core/support/Preferences.h>
#include <core/library/ILibrary.h>
#include <core/runtime/IMessageTarget.h>
#include "ITopLevelLayout.h"
@ -55,7 +57,7 @@ namespace musik {
public sigslot::has_slots<>
{
public:
MainLayout();
MainLayout(musik::core::ILibraryPtr library);
virtual ~MainLayout();
virtual bool KeyPress(const std::string& key);
@ -69,7 +71,14 @@ namespace musik {
void SetMainLayout(std::shared_ptr<cursespp::LayoutBase> layout);
virtual void ProcessMessage(musik::core::runtime::IMessage &message);
private:
void OnIndexerStarted();
void OnIndexerProgress(int count);
void OnIndexerFinished(int count);
void Initialize();
cursespp::IWindowPtr BlurShortcuts();
void FocusShortcuts();
@ -77,9 +86,12 @@ namespace musik {
std::shared_ptr<musik::core::Preferences> prefs;
std::shared_ptr<cursespp::ShortcutsWindow> shortcuts;
std::shared_ptr<cursespp::LayoutBase> layout;
std::shared_ptr<cursespp::TextLabel> syncing;
musik::core::ILibraryPtr library;
cursespp::IWindowPtr lastFocus;
ITopLevelLayout* topLevelLayout;
bool shortcutsFocused;
int syncUpdateCount;
};
}
}

View File

@ -68,7 +68,7 @@ SearchLayout::~SearchLayout() {
void SearchLayout::OnLayout() {
size_t cx = this->GetWidth(), cy = this->GetHeight();
size_t x = this->GetX(), y = this->GetY();
size_t x = 0, y = 0;
size_t inputWidth = cx / 2;
size_t inputX = x + ((cx - inputWidth) / 2);

View File

@ -76,7 +76,7 @@ TrackSearchLayout::~TrackSearchLayout() {
void TrackSearchLayout::OnLayout() {
size_t cx = this->GetWidth(), cy = this->GetHeight();
int x = this->GetX(), y = this->GetY();
int x = 0, y = 0;
size_t inputWidth = cx / 2;
size_t inputX = x + ((cx - inputWidth) / 2);

View File

@ -165,9 +165,6 @@ void App::Run(ILayoutPtr layout) {
bool quit = false;
bool wasVisible = true;
bool visible = true;
this->state.input = nullptr;
this->state.keyHandler = nullptr;
@ -180,6 +177,7 @@ void App::Run(ILayoutPtr layout) {
/* if the focused window is an input, allow it to draw a cursor */
WINDOW *c = this->state.focused->GetContent();
keypad(c, TRUE);
wtimeout(c, IDLE_TIMEOUT_MS);
ch = wgetch(c);
}
else {
@ -231,15 +229,11 @@ void App::Run(ILayoutPtr layout) {
resizeAt = 0;
}
if (visible || (!visible && wasVisible)) {
this->CheckShowOverlay();
this->EnsureFocusIsValid();
Window::WriteToScreen(this->state.input);
}
this->CheckShowOverlay();
this->EnsureFocusIsValid();
Window::WriteToScreen(this->state.input);
Window::MessageQueue().Dispatch();
wasVisible = visible;
}
overlays.Clear();

View File

@ -166,4 +166,6 @@ void Colors::Init(bool disableCustomColors) {
init_pair(CURSESPP_OVERLAY_FRAME, blue, selected);
init_pair(CURSESPP_OVERLAY_BACKGROUND, white, selected);
init_pair(CURSESPP_OVERLAY_INPUT_FRAME, red, selected);
init_pair(CURSESPP_BANNER, black, orange);
}

View File

@ -67,6 +67,8 @@
#define CURSESPP_OVERLAY_BACKGROUND 22
#define CURSESPP_OVERLAY_INPUT_FRAME 23
#define CURSESPP_BANNER 24
namespace cursespp {
class Colors {
private:

View File

@ -108,6 +108,8 @@ Window::Window(IWindow *parent) {
this->width = 0;
this->x = 0;
this->y = 0;
this->lastAbsoluteX = 0;
this->lastAbsoluteY = 0;
this->contentColor = CURSESPP_DEFAULT_CONTENT_COLOR;
this->frameColor = CURSESPP_DEFAULT_FRAME_COLOR;
this->focusedContentColor = CURSESPP_DEFAULT_CONTENT_COLOR;
@ -214,13 +216,21 @@ void Window::RecreateForUpdatedDimensions() {
void Window::MoveAndResize(int x, int y, int width, int height) {
bool sizeChanged = this->width != width || this->height != height;
bool positionChanged = this->x != x || this->y != y;
this->x = x;
this->y = y;
int absX = this->GetAbsoluteX();
int absY = this->GetAbsoluteY();
bool positionChanged =
absX != this->lastAbsoluteX ||
absY != this->lastAbsoluteY;
if (sizeChanged || positionChanged) {
this->lastAbsoluteX = absX;
this->lastAbsoluteY = absY;
this->width = width;
this->height = height;
this->x = x;
this->y = y;
this->RecreateForUpdatedDimensions();
}
}
@ -234,9 +244,14 @@ void Window::SetSize(int width, int height) {
}
void Window::SetPosition(int x, int y) {
if (this->x != x || this->y != y) {
this->x = x;
this->y = y;
this->x = x;
this->y = y;
int absX = this->GetAbsoluteX();
int absY = this->GetAbsoluteY();
if (absX != this->lastAbsoluteX || absY != this->lastAbsoluteY) {
this->lastAbsoluteX = absX;
this->lastAbsoluteY = absY;
this->RecreateForUpdatedDimensions();
}
}

View File

@ -152,5 +152,6 @@ namespace cursespp {
int64 contentColor, frameColor;
int64 focusedContentColor, focusedFrameColor;
int width, height, x, y;
int lastAbsoluteX, lastAbsoluteY;
};
}