mirror of
https://github.com/clangen/musikcube.git
synced 2025-02-11 18:40:28 +00:00
Fit & finish and license.
This commit is contained in:
parent
8b164fc035
commit
6236247969
@ -64,32 +64,43 @@ static const std::vector<std::string> BANDS = {
|
||||
|
||||
static const int UPDATE_DEBOUNCE_MS = 350;
|
||||
static const int VERTICAL_PADDING = 2;
|
||||
static const int MAX_HEIGHT = 7 + (int) BANDS.size();
|
||||
static const int MAX_HEIGHT = 8 + (int) BANDS.size();
|
||||
static const int DEFAULT_WIDTH = 46;
|
||||
static const int TRACK_WIDTH = 21;
|
||||
static const int DB_LABEL_WIDTH = 6; /* "-XY dB" */
|
||||
|
||||
static std::string formatBandRow(size_t width, const std::string& band, double value) {
|
||||
static std::string formatDbLabel(double db) {
|
||||
return u8fmt("%d dB", (int)round(db));
|
||||
}
|
||||
|
||||
static std::string formatBandRow(size_t width, const std::string& band, double db) {
|
||||
width -= 2; /* left/right padding */
|
||||
int leftWidth = 10; /* "16744 hz " */
|
||||
|
||||
std::string left = u8fmt(" %s khz ", band.c_str());
|
||||
/* frequency */
|
||||
std::string leftText = u8fmt(" %s hz", band.c_str());
|
||||
leftText = text::Align(leftText, text::AlignRight, leftWidth);
|
||||
|
||||
int remain = width - u8cols(left);
|
||||
int trackWidth = std::min(remain, 25);
|
||||
trackWidth = (trackWidth % 2 == 0) ? trackWidth - 1 : trackWidth;
|
||||
|
||||
double percent = value / 2.0f;
|
||||
|
||||
std::string right;
|
||||
size_t thumbOffset = std::min(trackWidth - 1, (int) (percent * trackWidth));
|
||||
for (int i = 0; i < trackWidth; i++) {
|
||||
right += (i == thumbOffset) ? "■" : "─";
|
||||
/* track */
|
||||
double percent = (db + 20.0) / 40.0;
|
||||
std::string trackText;
|
||||
size_t thumbOffset = std::min(TRACK_WIDTH - 1, (int) (percent * TRACK_WIDTH));
|
||||
for (int i = 0; i < TRACK_WIDTH; i++) {
|
||||
trackText += (i == thumbOffset) ? "■" : "─";
|
||||
}
|
||||
|
||||
right = u8fmt(" %s %0.2f", right.c_str(), value);
|
||||
/* db */
|
||||
std::string dbText = text::Align(formatDbLabel(db), text::AlignRight, DB_LABEL_WIDTH);
|
||||
|
||||
/* track + db */
|
||||
std::string rightText = u8fmt(" %s %s", trackText.c_str(), dbText.c_str());
|
||||
|
||||
/* TODO: i'm dumb and it's late; we shouldn't need the `+ 1` here, there's
|
||||
another calculation error that i'm currently blind to. */
|
||||
remain = width - (u8cols(left) + u8cols(right)) + 1;
|
||||
int remain = width - (u8cols(leftText) + u8cols(rightText)) + 1;
|
||||
|
||||
return text::Align(left, text::AlignLeft, u8cols(left) + remain) + right;
|
||||
/* pad the area between the left and right text, if necessary */
|
||||
return text::Align(leftText, text::AlignLeft, u8cols(leftText) + remain) + rightText;
|
||||
}
|
||||
|
||||
EqualizerOverlay::EqualizerOverlay()
|
||||
@ -111,10 +122,18 @@ EqualizerOverlay::EqualizerOverlay()
|
||||
this->listView = std::make_shared<ListWindow>(this->adapter);
|
||||
this->listView->SetFrameTitle(_TSTR("equalizer_overlay_frequencies"));
|
||||
|
||||
this->shortcuts = std::make_shared<ShortcutsWindow>();
|
||||
// this->shortcuts->AddShortcut("l", _TSTR("equalizer_button_load"));
|
||||
// this->shortcuts->AddShortcut("s", _TSTR("equalizer_button_save"));
|
||||
this->shortcuts->AddShortcut("z", _TSTR("equalizer_button_zero"));
|
||||
this->shortcuts->AddShortcut("ESC", _TSTR("button_close"));
|
||||
this->shortcuts->SetAlignment(text::AlignRight);
|
||||
|
||||
/* add */
|
||||
this->AddWindow(this->titleLabel);
|
||||
this->AddWindow(this->enabledCb);
|
||||
this->AddWindow(this->listView);
|
||||
this->AddWindow(this->shortcuts);
|
||||
|
||||
/* focus */
|
||||
int order = 0;
|
||||
@ -153,7 +172,7 @@ std::shared_ptr<IPlugin> EqualizerOverlay::FindPlugin() {
|
||||
}
|
||||
|
||||
void EqualizerOverlay::Layout() {
|
||||
int width = (int)(0.8f * (float) Screen::GetWidth());
|
||||
int width = _DIMEN("equalizer_overlay_width", DEFAULT_WIDTH);
|
||||
int height = std::min(Screen::GetHeight() - 4, MAX_HEIGHT);
|
||||
int y = VERTICAL_PADDING;
|
||||
int x = (Screen::GetWidth() / 2) - (width / 2);
|
||||
@ -169,7 +188,10 @@ void EqualizerOverlay::Layout() {
|
||||
this->enabledCb->MoveAndResize(x, y, cx, 1);
|
||||
y += 1;
|
||||
cy -= 3;
|
||||
this->listView->MoveAndResize(x, y, cx, cy);
|
||||
this->listView->MoveAndResize(x, y, cx, cy - 1);
|
||||
|
||||
cy = this->GetContentHeight();
|
||||
this->shortcuts->MoveAndResize(0, cy - 1, cx, 1);
|
||||
}
|
||||
|
||||
void EqualizerOverlay::OnEnabledChanged(cursespp::Checkbox* cb, bool checked) {
|
||||
@ -186,17 +208,19 @@ bool EqualizerOverlay::KeyPress(const std::string& key) {
|
||||
}
|
||||
else if (key == "z") {
|
||||
for (auto band : BANDS) {
|
||||
this->prefs->SetDouble(band.c_str(), 1.0);
|
||||
this->prefs->SetDouble(band.c_str(), 0.0);
|
||||
}
|
||||
this->NotifyAndRedraw();
|
||||
}
|
||||
else if (keys.Left(key)) {
|
||||
this->UpdateSelectedBand(-0.1f);
|
||||
return true;
|
||||
}
|
||||
else if (keys.Right(key)) {
|
||||
this->UpdateSelectedBand(0.1f);
|
||||
return true;
|
||||
else if (this->GetFocus() == this->listView) {
|
||||
if (keys.Left(key)) {
|
||||
this->UpdateSelectedBand(-1.0);
|
||||
return true;
|
||||
}
|
||||
else if (keys.Right(key)) {
|
||||
this->UpdateSelectedBand(1.0);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return OverlayBase::KeyPress(key);
|
||||
}
|
||||
@ -214,8 +238,8 @@ void EqualizerOverlay::ProcessMessage(musik::core::runtime::IMessage &message) {
|
||||
|
||||
void EqualizerOverlay::UpdateSelectedBand(double delta) {
|
||||
const std::string band = BANDS[this->listView->GetSelectedIndex()];
|
||||
double existing = this->prefs->GetDouble(band.c_str(), 1.0);
|
||||
double updated = std::min(2.0, std::max(0.0, existing + delta));
|
||||
double existing = this->prefs->GetDouble(band.c_str(), 0.0);
|
||||
double updated = std::min(20.0, std::max(-20.0, existing + delta));
|
||||
this->prefs->SetDouble(band.c_str(), updated);
|
||||
this->NotifyAndRedraw();
|
||||
}
|
||||
@ -238,7 +262,9 @@ ScrollAdapterBase::EntryPtr EqualizerOverlay::BandsAdapter::GetEntry(cursespp::S
|
||||
const std::string band = BANDS[index];
|
||||
|
||||
auto entry = std::make_shared<SingleLineEntry>(formatBandRow(
|
||||
window->GetContentWidth(), band, prefs->GetDouble(band.c_str(), 1.0)));
|
||||
window->GetContentWidth(),
|
||||
band,
|
||||
prefs->GetDouble(band.c_str(), 0.0)));
|
||||
|
||||
entry->SetAttrs(CURSESPP_DEFAULT_COLOR);
|
||||
if (index == window->GetScrollPosition().logicalIndex) {
|
||||
|
@ -40,6 +40,7 @@
|
||||
#include <cursespp/Checkbox.h>
|
||||
#include <cursespp/ListWindow.h>
|
||||
#include <cursespp/ScrollAdapterBase.h>
|
||||
#include <cursespp/ShortcutsWindow.h>
|
||||
#include <sigslot/sigslot.h>
|
||||
#include <memory>
|
||||
|
||||
@ -88,6 +89,7 @@ namespace musik {
|
||||
std::shared_ptr<cursespp::TextLabel> titleLabel;
|
||||
std::shared_ptr<cursespp::Checkbox> enabledCb;
|
||||
std::shared_ptr<cursespp::ListWindow> listView;
|
||||
std::shared_ptr<cursespp::ShortcutsWindow> shortcuts;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -165,6 +165,9 @@
|
||||
"equalizer_overlay_title": "equalizer",
|
||||
"equalizer_overlay_enabled": "enabled",
|
||||
"equalizer_overlay_frequencies": "frequency bands",
|
||||
"equalizer_button_load": "load",
|
||||
"equalizer_button_save": "save",
|
||||
"equalizer_button_zero": "zero",
|
||||
|
||||
"plugin_overlay_title": "configure plugins",
|
||||
|
||||
@ -215,6 +218,7 @@
|
||||
"indexer_overlay_width": 28,
|
||||
"reassign_hotkey_overlay_width": 35,
|
||||
"server_overlay_width": 45,
|
||||
"preamp_overlay_width": 40
|
||||
"preamp_overlay_width": 40,
|
||||
"equalizer_overlay_width": 46
|
||||
}
|
||||
}
|
@ -4,31 +4,25 @@
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
// Note: this musikcube plugin (supereq) is not distributed under a BSD
|
||||
// license like most other project components because it consumes GPL2
|
||||
// code.
|
||||
//
|
||||
// * 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.
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// * 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.
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@ -38,12 +32,15 @@
|
||||
#include <core/sdk/IPreferences.h>
|
||||
#include <core/sdk/ISchema.h>
|
||||
#include <atomic>
|
||||
#include <math.h>
|
||||
|
||||
using namespace musik::core::sdk;
|
||||
|
||||
static IPreferences* prefs = nullptr;
|
||||
static std::atomic<int> currentState;
|
||||
|
||||
static const double LN_10 = 2.3025850929940002f;
|
||||
|
||||
static const std::vector<std::string> BANDS = {
|
||||
"65", "92", "131", "185", "262",
|
||||
"370", "523", "740", "1047", "1480",
|
||||
@ -89,7 +86,9 @@ bool SuperEqDsp::Process(IBuffer* buffer) {
|
||||
float bands[17];
|
||||
|
||||
for (size_t i = 0; i < BANDS.size(); i++) {
|
||||
bands[i] = (float) prefs->GetDouble(BANDS[i].c_str(), 1.0);
|
||||
double dB = prefs->GetDouble(BANDS[i].c_str(), 0.0);
|
||||
double amp = exp(LN_10 * dB / 20.f);
|
||||
bands[i] = (float) amp;
|
||||
}
|
||||
|
||||
equ_makeTable(
|
||||
|
@ -4,33 +4,28 @@
|
||||
//
|
||||
// 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.
|
||||
// Note: this musikcube plugin (supereq) is not distributed under a BSD
|
||||
// license like most other project components because it consumes GPL2
|
||||
// code.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <core/sdk/IDSP.h>
|
||||
|
@ -4,38 +4,30 @@
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
// Note: this musikcube plugin (supereq) is not distributed under a BSD
|
||||
// license like most other project components because it consumes GPL2
|
||||
// code.
|
||||
//
|
||||
// * 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.
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// * 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.
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <atomic>
|
||||
|
||||
#ifdef WIN32
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#define WINVER 0x0502
|
||||
|
@ -4,31 +4,25 @@
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
// Note: this musikcube plugin (supereq) is not distributed under a BSD
|
||||
// license like most other project components because it consumes GPL2
|
||||
// code.
|
||||
//
|
||||
// * 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.
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 2
|
||||
// of the License, or (at your option) any later version.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// * 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.
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user