mirror of
https://github.com/clangen/musikcube.git
synced 2025-02-11 09:40:26 +00:00
More boring incremental equalizer UI work.
This commit is contained in:
parent
db37f5e5f0
commit
64691f8c83
@ -69,3 +69,12 @@ inline static std::string u8substr(const std::string& in, int offset, int len) {
|
||||
|
||||
return std::string(begin, it);
|
||||
}
|
||||
|
||||
template<typename... Args>
|
||||
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<char[]> 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' */
|
||||
}
|
@ -33,8 +33,11 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "EqualizerOverlay.h"
|
||||
#include <cursespp/App.h>
|
||||
#include <cursespp/Screen.h>
|
||||
#include <cursespp/Scrollbar.h>
|
||||
#include <core/plugin/PluginFactory.h>
|
||||
#include <cursespp/SingleLineEntry.h>
|
||||
|
||||
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<std::string> 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<TextLabel>();
|
||||
this->titleLabel->SetText(_TSTR("equalizer_overlay_title"), text::AlignCenter);
|
||||
this->titleLabel->SetBold(true);
|
||||
|
||||
this->enabledCb = std::make_shared<Checkbox>();
|
||||
this->enabledCb->SetText(_TSTR("equalizer_overlay_enabled"));
|
||||
this->enabledCb->SetChecked(this->prefs->GetBool("enabled", false));
|
||||
|
||||
this->adapter = std::make_shared<BandsAdapter>(prefs);
|
||||
|
||||
this->listView = std::make_shared<ListWindow>(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<EqualizerOverlay>());
|
||||
}
|
||||
|
||||
bool EqualizerOverlay::CanScroll(int listViewHeight) {
|
||||
return listViewHeight < this->adapter->GetEntryCount();
|
||||
}
|
||||
|
||||
std::shared_ptr<IPlugin> EqualizerOverlay::FindPlugin() {
|
||||
@ -72,3 +120,59 @@ std::shared_ptr<IPlugin> 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<SingleLineEntry>(
|
||||
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;
|
||||
}
|
||||
|
@ -39,6 +39,7 @@
|
||||
#include <cursespp/OverlayBase.h>
|
||||
#include <cursespp/Checkbox.h>
|
||||
#include <cursespp/ListWindow.h>
|
||||
#include <cursespp/ScrollAdapterBase.h>
|
||||
#include <sigslot/sigslot.h>
|
||||
#include <memory>
|
||||
|
||||
@ -50,6 +51,12 @@ namespace musik {
|
||||
#endif
|
||||
{
|
||||
public:
|
||||
using Plugin = std::shared_ptr<musik::core::sdk::IPlugin>;
|
||||
using Prefs = std::shared_ptr<musik::core::Preferences>;
|
||||
|
||||
EqualizerOverlay();
|
||||
virtual ~EqualizerOverlay();
|
||||
|
||||
static void ShowOverlay();
|
||||
static std::shared_ptr<musik::core::sdk::IPlugin> 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<musik::core::sdk::IPlugin> plugin;
|
||||
std::shared_ptr<musik::core::Preferences> prefs;
|
||||
private:
|
||||
Prefs prefs;
|
||||
};
|
||||
|
||||
bool CanScroll(int listViewHeight);
|
||||
|
||||
Plugin plugin;
|
||||
Prefs prefs;
|
||||
std::shared_ptr<BandsAdapter> adapter;
|
||||
std::shared_ptr<cursespp::TextLabel> titleLabel;
|
||||
std::shared_ptr<cursespp::Checkbox> enabledCb;
|
||||
std::shared_ptr<cursespp::ListWindow> listView;
|
||||
};
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -38,6 +38,7 @@
|
||||
#include "IScrollAdapter.h"
|
||||
#include "ScrollableWindow.h"
|
||||
#include <sigslot/sigslot.h>
|
||||
#include <functional>
|
||||
|
||||
namespace cursespp {
|
||||
class ListWindow :
|
||||
@ -49,6 +50,8 @@ namespace cursespp {
|
||||
public:
|
||||
static size_t NO_SELECTION;
|
||||
|
||||
using Decorator = std::function<void(ListWindow*)>;
|
||||
|
||||
sigslot::signal3<ListWindow*, size_t, size_t> SelectionChanged;
|
||||
sigslot::signal2<ListWindow*, size_t> Invalidated;
|
||||
sigslot::signal2<ListWindow*, size_t> 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;
|
||||
};
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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",
|
||||
|
@ -32,16 +32,35 @@
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "constants.h"
|
||||
#include "SuperEqDsp.h"
|
||||
|
||||
#include <core/sdk/constants.h>
|
||||
#include <core/sdk/IPreferences.h>
|
||||
#include <core/sdk/ISchema.h>
|
||||
#include <atomic>
|
||||
|
||||
using namespace musik::core::sdk;
|
||||
|
||||
SuperEqDsp::SuperEqDsp() {
|
||||
static IPreferences* prefs = nullptr;
|
||||
static std::atomic<int> currentState;
|
||||
|
||||
static const std::vector<std::string> 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(
|
||||
|
@ -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;
|
||||
};
|
||||
|
43
src/plugins/supereqdsp/constants.h
Normal file
43
src/plugins/supereqdsp/constants.h
Normal file
@ -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 <atomic>
|
||||
|
||||
#ifdef WIN32
|
||||
#define DLLEXPORT __declspec(dllexport)
|
||||
#else
|
||||
#define DLLEXPORT
|
||||
#endif
|
@ -32,18 +32,13 @@
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "constants.h"
|
||||
#include <core/sdk/constants.h>
|
||||
#include <core/sdk/IPlugin.h>
|
||||
#include <core/sdk/ISchema.h>
|
||||
#include <core/sdk/IDSP.h>
|
||||
#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; }
|
||||
};
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user