diff --git a/src/core/utfutil.h b/src/core/utfutil.h index b3354ac54..147e4d8d2 100644 --- a/src/core/utfutil.h +++ b/src/core/utfutil.h @@ -69,3 +69,12 @@ inline static std::string u8substr(const std::string& in, int offset, int len) { return std::string(begin, it); } + +template +static std::string u8fmt(const std::string& format, Args ... args) { + /* https://stackoverflow.com/a/26221725 */ + size_t size = std::snprintf(nullptr, 0, format.c_str(), args ...) + 1; /* extra space for '\0' */ + std::unique_ptr buf(new char[size]); + std::snprintf(buf.get(), size, format.c_str(), args ...); + return std::string(buf.get(), buf.get() + size - 1); /* omit the '\0' */ +} \ No newline at end of file diff --git a/src/musikcube/app/overlay/EqualizerOverlay.cpp b/src/musikcube/app/overlay/EqualizerOverlay.cpp index aebd3f765..62a53b610 100644 --- a/src/musikcube/app/overlay/EqualizerOverlay.cpp +++ b/src/musikcube/app/overlay/EqualizerOverlay.cpp @@ -33,8 +33,11 @@ ////////////////////////////////////////////////////////////////////////////// #include "EqualizerOverlay.h" +#include #include +#include #include +#include using namespace cursespp; using namespace musik::core; @@ -43,21 +46,66 @@ using namespace musik::cube; static const std::string SUPEREQ_PLUGIN_GUID = "6f0ed53b-0f13-4220-9b0a-ca496b6421cc"; -static std::string formatBandRow(const std::string& band, float value) { - return band + "khz"; -} +static const size_t NO_INDEX = (size_t)-1; -static int calculateWidth() { - return (int)(0.8f * Screen::GetWidth()); +static const std::vector BANDS = { + "65", "92", "131", "185", "262", + "370", "523", "740", "1047", "1480", + "2093", "2960", "4186", "5920", "8372", + "11840", "16744" +}; + +static const int VERTICAL_PADDING = 2; +static const int MAX_HEIGHT = 8 + (int) BANDS.size(); + +static std::string formatBandRow(const std::string& band, float value) { + return u8fmt("%s khz (%0.2f)", band.c_str(), value); } EqualizerOverlay::EqualizerOverlay() : OverlayBase() { this->plugin = this->FindPlugin(); this->prefs = Preferences::ForPlugin(this->plugin->Name()); + + this->titleLabel = std::make_shared(); + this->titleLabel->SetText(_TSTR("equalizer_overlay_title"), text::AlignCenter); + this->titleLabel->SetBold(true); + + this->enabledCb = std::make_shared(); + this->enabledCb->SetText(_TSTR("equalizer_overlay_enabled")); + this->enabledCb->SetChecked(this->prefs->GetBool("enabled", false)); + + this->adapter = std::make_shared(prefs); + + this->listView = std::make_shared(this->adapter); + this->listView->SetFrameTitle(_TSTR("equalizer_overlay_frequencies")); + + /* add */ + this->AddWindow(this->titleLabel); + this->AddWindow(this->enabledCb); + this->AddWindow(this->listView); + + /* focus */ + int order = 0; + this->enabledCb->SetFocusOrder(order++); + this->listView->SetFocusOrder(order++); + + /* style */ + style(*this->titleLabel); + style(*this->enabledCb); + style(*this->listView); + this->listView->SetFrameVisible(true); +} + +EqualizerOverlay::~EqualizerOverlay() { } void EqualizerOverlay::ShowOverlay() { + App::Overlays().Push(std::make_shared()); +} + +bool EqualizerOverlay::CanScroll(int listViewHeight) { + return listViewHeight < this->adapter->GetEntryCount(); } std::shared_ptr EqualizerOverlay::FindPlugin() { @@ -72,3 +120,59 @@ std::shared_ptr EqualizerOverlay::FindPlugin() { }); return result; } + +void EqualizerOverlay::Layout() { + int width = (int)(0.8f * (float) Screen::GetWidth()); + int height = std::min(Screen::GetHeight() - 4, MAX_HEIGHT); + int y = VERTICAL_PADDING; + int x = (Screen::GetWidth() / 2) - (width / 2); + this->MoveAndResize(x, y, width, height); + + int cx = this->GetContentWidth(); + int cy = this->GetContentHeight(); + x = 0; + y = 0; + + this->titleLabel->MoveAndResize(x, y, cx, 1); + y += 2; + this->enabledCb->MoveAndResize(x, y, cx, 1); + y += 2; + cy -= 4; + this->listView->MoveAndResize(x, y, cx, cy); +} + +bool EqualizerOverlay::KeyPress(const std::string& key) { + if (key == "^[" || key == "ESC") { /* esc closes */ + this->Dismiss(); + return true; + } + return OverlayBase::KeyPress(key); +} + +/* ~~~~~~ BandsAdapter ~~~~~ */ + +EqualizerOverlay::BandsAdapter::BandsAdapter(EqualizerOverlay::Prefs prefs) +: prefs(prefs) { + +} + +EqualizerOverlay::BandsAdapter::~BandsAdapter() { +} + +size_t EqualizerOverlay::BandsAdapter::GetEntryCount() { + return BANDS.size(); +} + +ScrollAdapterBase::EntryPtr EqualizerOverlay::BandsAdapter::GetEntry(cursespp::ScrollableWindow* window, size_t index) { + const std::string band = BANDS[index]; + + auto entry = std::make_shared( + formatBandRow(band, prefs->GetDouble(band.c_str(), 1.0))); + + entry->SetAttrs(CURSESPP_DEFAULT_COLOR); + if (index == window->GetScrollPosition().logicalIndex) { + entry->SetAttrs(COLOR_PAIR(CURSESPP_HIGHLIGHTED_LIST_ITEM)); + } + + return entry; +} diff --git a/src/musikcube/app/overlay/EqualizerOverlay.h b/src/musikcube/app/overlay/EqualizerOverlay.h index e34ce12e0..ab1c8b37b 100644 --- a/src/musikcube/app/overlay/EqualizerOverlay.h +++ b/src/musikcube/app/overlay/EqualizerOverlay.h @@ -39,6 +39,7 @@ #include #include #include +#include #include #include @@ -50,6 +51,12 @@ namespace musik { #endif { public: + using Plugin = std::shared_ptr; + using Prefs = std::shared_ptr; + + EqualizerOverlay(); + virtual ~EqualizerOverlay(); + static void ShowOverlay(); static std::shared_ptr FindPlugin(); @@ -57,10 +64,23 @@ namespace musik { virtual bool KeyPress(const std::string& key) override; private: - EqualizerOverlay(); + class BandsAdapter : public cursespp::ScrollAdapterBase { + public: + BandsAdapter(Prefs prefs); + virtual ~BandsAdapter(); + virtual size_t GetEntryCount() override; + virtual EntryPtr GetEntry(cursespp::ScrollableWindow* window, size_t index) override; - std::shared_ptr plugin; - std::shared_ptr prefs; + private: + Prefs prefs; + }; + + bool CanScroll(int listViewHeight); + + Plugin plugin; + Prefs prefs; + std::shared_ptr adapter; + std::shared_ptr titleLabel; std::shared_ptr enabledCb; std::shared_ptr listView; }; diff --git a/src/musikcube/app/overlay/ServerOverlay.cpp b/src/musikcube/app/overlay/ServerOverlay.cpp index a8e2129f2..48320bdf3 100644 --- a/src/musikcube/app/overlay/ServerOverlay.cpp +++ b/src/musikcube/app/overlay/ServerOverlay.cpp @@ -168,19 +168,19 @@ void ServerOverlay::InitViews() { this->pwInput.reset(new TextInput(TextInput::StyleLine, IInput::InputPassword)); /* style 'em */ - applyLabelOverlayStyle(*this->titleLabel); - applyCheckboxOverlayStyle(*this->enableWssCb); - applyLabelOverlayStyle(*this->wssPortLabel); - applyInputOverlayStyle(*this->wssPortInput); - applyCheckboxOverlayStyle(*this->enableHttpCb); - applyLabelOverlayStyle(*this->httpPortLabel); - applyInputOverlayStyle(*this->httpPortInput); - applyCheckboxOverlayStyle(*this->ipv6Cb); - applyCheckboxOverlayStyle(*this->enableSyncTransCb); - applyLabelOverlayStyle(*this->transCacheLabel); - applyInputOverlayStyle(*this->transCacheInput); - applyLabelOverlayStyle(*this->pwLabel); - applyInputOverlayStyle(*this->pwInput); + style(*this->titleLabel); + style(*this->enableWssCb); + style(*this->wssPortLabel); + style(*this->wssPortInput); + style(*this->enableHttpCb); + style(*this->httpPortLabel); + style(*this->httpPortInput); + style(*this->ipv6Cb); + style(*this->enableSyncTransCb); + style(*this->transCacheLabel); + style(*this->transCacheInput); + style(*this->pwLabel); + style(*this->pwInput); /* add 'em */ this->AddWindow(this->titleLabel); diff --git a/src/musikcube/cursespp/ListWindow.cpp b/src/musikcube/cursespp/ListWindow.cpp index fc1d1585a..8d3347a7f 100755 --- a/src/musikcube/cursespp/ListWindow.cpp +++ b/src/musikcube/cursespp/ListWindow.cpp @@ -66,12 +66,20 @@ void ListWindow::SetScrollbarVisible(bool visible) { } } +void ListWindow::SetDecorator(Decorator decorator) { + this->decorator = decorator; +} + void ListWindow::Invalidate() { this->DecorateFrame(); Window::Invalidate(); } void ListWindow::DecorateFrame() { + if (this->decorator) { + this->decorator(this); + } + if (this->IsFrameVisible()) { Scrollbar::Draw(this); } diff --git a/src/musikcube/cursespp/ListWindow.h b/src/musikcube/cursespp/ListWindow.h index 4dc62050e..24334f470 100755 --- a/src/musikcube/cursespp/ListWindow.h +++ b/src/musikcube/cursespp/ListWindow.h @@ -38,6 +38,7 @@ #include "IScrollAdapter.h" #include "ScrollableWindow.h" #include +#include namespace cursespp { class ListWindow : @@ -49,6 +50,8 @@ namespace cursespp { public: static size_t NO_SELECTION; + using Decorator = std::function; + sigslot::signal3 SelectionChanged; sigslot::signal2 Invalidated; sigslot::signal2 EntryActivated; @@ -79,6 +82,7 @@ namespace cursespp { virtual bool MouseEvent(const IMouseHandler::Event& event); void SetScrollbarVisible(bool visible); + void SetDecorator(Decorator decorator); protected: virtual void OnSelectionChanged(size_t newIndex, size_t oldIndex); @@ -95,5 +99,6 @@ namespace cursespp { bool showScrollbar; IScrollAdapter::ScrollPosition scrollPosition; size_t selectedIndex; + Decorator decorator; }; } diff --git a/src/musikcube/cursespp/OverlayBase.h b/src/musikcube/cursespp/OverlayBase.h index c4d3b31e5..8474bdb1b 100644 --- a/src/musikcube/cursespp/OverlayBase.h +++ b/src/musikcube/cursespp/OverlayBase.h @@ -41,12 +41,15 @@ #include "TextLabel.h" #include "Checkbox.h" #include "TextInput.h" +#include "ListWindow.h" namespace cursespp { class OverlayBase : public LayoutBase, public IOverlay { public: OverlayBase() : LayoutBase() { - + this->SetFrameVisible(true); + this->SetFrameColor(CURSESPP_OVERLAY_FRAME); + this->SetContentColor(CURSESPP_OVERLAY_CONTENT); } virtual ~OverlayBase() { @@ -72,16 +75,16 @@ namespace cursespp { } protected: - static void applyLabelOverlayStyle(TextLabel& label) { + static void style(TextLabel& label) { label.SetContentColor(CURSESPP_OVERLAY_CONTENT); } - static void applyCheckboxOverlayStyle(Checkbox& cb) { + static void style(Checkbox& cb) { cb.SetContentColor(CURSESPP_OVERLAY_CONTENT); cb.SetFocusedContentColor(CURSESPP_OVERLAY_TEXT_FOCUSED); } - static void applyInputOverlayStyle(TextInput& input) { + static void style(TextInput& input) { if (input.GetStyle() == TextInput::StyleBox) { input.SetFrameColor(CURSESPP_OVERLAY_FRAME); input.SetContentColor(CURSESPP_OVERLAY_CONTENT); @@ -94,6 +97,12 @@ namespace cursespp { } } + static void style(ListWindow& listWindow, bool frameVisible = false) { + listWindow.SetContentColor(CURSESPP_OVERLAY_CONTENT); + listWindow.SetFocusedContentColor(CURSESPP_OVERLAY_CONTENT); + listWindow.SetFrameVisible(frameVisible); + } + OverlayStack* GetOverlayStack() { return this->stack; } diff --git a/src/musikcube/data/locales/en_US.json b/src/musikcube/data/locales/en_US.json index 690f8a348..19403b346 100644 --- a/src/musikcube/data/locales/en_US.json +++ b/src/musikcube/data/locales/en_US.json @@ -162,6 +162,10 @@ "visualizer_overlay_title": "visualizers", "visualizer_overlay_no_visualizers_message": "no visualizers found!", + "equalizer_overlay_title": "equalizer", + "equalizer_overlay_enabled": "equalizer enabled", + "equalizer_overlay_frequencies": "frequencies", + "plugin_overlay_title": "configure plugins", "shortcuts_settings": "settings", diff --git a/src/plugins/supereqdsp/SuperEqDsp.cpp b/src/plugins/supereqdsp/SuperEqDsp.cpp index 198e9cb6d..deb9ab548 100644 --- a/src/plugins/supereqdsp/SuperEqDsp.cpp +++ b/src/plugins/supereqdsp/SuperEqDsp.cpp @@ -32,16 +32,35 @@ // ////////////////////////////////////////////////////////////////////////////// +#include "constants.h" #include "SuperEqDsp.h" - #include #include #include +#include using namespace musik::core::sdk; -SuperEqDsp::SuperEqDsp() { +static IPreferences* prefs = nullptr; +static std::atomic currentState; +static const std::vector BANDS = { + "65", "92", "131", "185", "262", + "370", "523", "740", "1047", "1480", + "2093", "2960", "4186", "5920", "8372", + "11840", "16744" +}; + +extern "C" DLLEXPORT void SetPreferences(IPreferences* prefs) { + ::prefs = prefs; +} + +void SuperEqDsp::NotifyChanged() { + currentState.fetch_add(1); +} + +SuperEqDsp::SuperEqDsp() { + this->enabled = ::prefs && ::prefs->GetBool("enabled", false); } SuperEqDsp::~SuperEqDsp() { @@ -56,17 +75,25 @@ void SuperEqDsp::Release() { } bool SuperEqDsp::Process(IBuffer* buffer) { - int channels = buffer->Channels(); + if (!this->enabled) { + return false; + } + + int channels = buffer->Channels(); + int current = ::currentState.load(); + + if (!this->supereq || this->lastUpdated != current) { + this->enabled = ::prefs && ::prefs->GetBool("enabled", false); + this->lastUpdated = current; - if (!this->supereq) { this->supereq = new SuperEqState(); equ_init(this->supereq, 10, channels); void *params = paramlist_alloc(); - float bands[18]; + float bands[17]; - for (int i = 0; i < 18; i++) { - bands[i] = 1.0f; //i > 9 ? -0.0f : 1.0f; + for (int i = 0; i < BANDS.size(); i++) { + prefs->GetDouble(BANDS[i].c_str(), 1.0); } equ_makeTable( diff --git a/src/plugins/supereqdsp/SuperEqDsp.h b/src/plugins/supereqdsp/SuperEqDsp.h index 338ba50dc..e4a36a4b3 100644 --- a/src/plugins/supereqdsp/SuperEqDsp.h +++ b/src/plugins/supereqdsp/SuperEqDsp.h @@ -46,6 +46,10 @@ class SuperEqDsp : public IDSP { virtual void Release() override; virtual bool Process(IBuffer *buffer) override; + static void NotifyChanged(); + private: SuperEqState* supereq {nullptr}; + int lastUpdated {0}; + bool enabled; }; diff --git a/src/plugins/supereqdsp/constants.h b/src/plugins/supereqdsp/constants.h new file mode 100644 index 000000000..31904b558 --- /dev/null +++ b/src/plugins/supereqdsp/constants.h @@ -0,0 +1,43 @@ +////////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2007-2017 musikcube team +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// * Neither the name of the author nor the names of other contributors may +// be used to endorse or promote products derived from this software +// without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include + +#ifdef WIN32 +#define DLLEXPORT __declspec(dllexport) +#else +#define DLLEXPORT +#endif diff --git a/src/plugins/supereqdsp/supereqdsp_plugin.cpp b/src/plugins/supereqdsp/supereqdsp_plugin.cpp index 9f0938890..206cffdec 100644 --- a/src/plugins/supereqdsp/supereqdsp_plugin.cpp +++ b/src/plugins/supereqdsp/supereqdsp_plugin.cpp @@ -32,18 +32,13 @@ // ////////////////////////////////////////////////////////////////////////////// +#include "constants.h" #include #include #include #include #include "SuperEqDsp.h" -#ifdef WIN32 -#define DLLEXPORT __declspec(dllexport) -#else -#define DLLEXPORT -#endif - class SuperEqPlugin : public musik::core::sdk::IPlugin { public: virtual void Release() { delete this; } @@ -53,7 +48,7 @@ class SuperEqPlugin : public musik::core::sdk::IPlugin { virtual const char* Guid() { return "6f0ed53b-0f13-4220-9b0a-ca496b6421cc"; } virtual bool Configurable() { return false; } virtual void Configure() { } - virtual void Reload() { } + virtual void Reload() { SuperEqDsp::NotifyChanged(); } virtual int SdkVersion() { return musik::core::sdk::SdkVersion; } };