multi sample buttons
This commit is contained in:
parent
3585f6a538
commit
2f0c25c421
|
@ -16,15 +16,22 @@ public:
|
|||
std::vector<std::string> devices;
|
||||
};
|
||||
|
||||
struct ButtonConfig {
|
||||
std::string name;
|
||||
struct SampleConfig {
|
||||
std::string file;
|
||||
std::string key;
|
||||
uint64_t offset;
|
||||
uint64_t length;
|
||||
float volume;
|
||||
|
||||
bool isValid() const;
|
||||
};
|
||||
|
||||
struct ButtonConfig {
|
||||
std::string name;
|
||||
std::string key;
|
||||
uint8_t width; // default is 6
|
||||
|
||||
std::vector<SampleConfig> samples;
|
||||
|
||||
bool isValid() const;
|
||||
};
|
||||
|
||||
|
|
|
@ -12,20 +12,20 @@ class SoundButton : public QPushButton
|
|||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit SoundButton(const std::string& filename, const std::string& name_ = "", const std::string& keycombo = "", QWidget* parent = nullptr);
|
||||
struct Sample {
|
||||
std::string file;
|
||||
uint64_t startms = 0;
|
||||
uint64_t lengthms = 0; // ignored when length = 0
|
||||
float volume = 1.f;
|
||||
};
|
||||
|
||||
explicit SoundButton(const std::string& name_ = "", const std::string& keycombo = "", QWidget* parent = nullptr);
|
||||
~SoundButton();
|
||||
|
||||
const std::string& getName() const;
|
||||
const std::string& getFile() const;
|
||||
const std::string& getKeyCombo() const;
|
||||
|
||||
uint64_t getStartMS() const;
|
||||
uint64_t getLengthMS() const;
|
||||
float getVolume() const;
|
||||
|
||||
void setStartMS(uint64_t startms);
|
||||
void setLengthMS(uint64_t lengthms);
|
||||
void setVolume(float v);
|
||||
void addSample(Sample& sample);
|
||||
|
||||
void setHighlighted(bool highlighted);
|
||||
|
||||
|
@ -42,11 +42,10 @@ private:
|
|||
|
||||
uint64_t id;
|
||||
std::string name;
|
||||
std::string file;
|
||||
std::string keycombo;
|
||||
uint64_t startms = 0;
|
||||
uint64_t lengthms = 0; // ignored when length = 0
|
||||
float volume = 1.f;
|
||||
|
||||
uint8_t currentSample = 0;
|
||||
std::vector<Sample> samples;
|
||||
|
||||
bool highlighted = false;
|
||||
bool disabled = false;
|
||||
|
|
|
@ -40,14 +40,30 @@ void from_json(const json& j, Config::AudioConfig& ac) {
|
|||
readVector(ac.devices, j.value("devices", json::array()));
|
||||
}
|
||||
|
||||
void from_json(const json& j, Config::SampleConfig& sc) {
|
||||
sc.file = j.value("file", "");
|
||||
sc.offset = j.value("offset", 0);
|
||||
sc.length = j.value("length", 0);
|
||||
sc.volume = j.value("volume", 1.f);
|
||||
}
|
||||
|
||||
void from_json(const json& j, Config::ButtonConfig& bc) {
|
||||
bc.name = j.value("name", "");
|
||||
bc.file = j.value("file", "");
|
||||
bc.key = j.value("key", "");
|
||||
bc.offset = j.value("offset", 0);
|
||||
bc.length = j.value("length", 0);
|
||||
bc.volume = j.value("volume", 1.f);
|
||||
bc.width = j.value("width", 6);
|
||||
|
||||
// make it possible to volume control all samples from one value
|
||||
float volume = j.value("value", 1.0);
|
||||
|
||||
if(j.contains("samples")) {
|
||||
// sample liste
|
||||
readVector(bc.samples, j["samples"]);
|
||||
for(Config::SampleConfig& sc : bc.samples) {
|
||||
sc.volume *= volume;
|
||||
}
|
||||
} else if(j.contains("file")) {
|
||||
bc.samples.push_back(j); // implizit cast
|
||||
}
|
||||
}
|
||||
|
||||
void from_json(const json& j, Config::RootConfig& rc) {
|
||||
|
@ -64,10 +80,15 @@ void from_json(const json& j, Config::RootConfig& rc) {
|
|||
rc.audioPath = j.value("audioPath", "");
|
||||
}
|
||||
|
||||
bool Config::ButtonConfig::isValid() const {
|
||||
bool Config::SampleConfig::isValid() const {
|
||||
return !file.empty();
|
||||
}
|
||||
|
||||
bool Config::ButtonConfig::isValid() const {
|
||||
bool validfound = std::any_of(samples.begin(), samples.end(), [](const SampleConfig& sc){ return sc.isValid(); });
|
||||
return !samples.empty() && !name.empty() && validfound;
|
||||
}
|
||||
|
||||
void Config::load() {
|
||||
std::ifstream stream(binaryPath + file);
|
||||
json json;
|
||||
|
|
|
@ -169,12 +169,13 @@ void MainWindow::loadButtonsFromConfig() {
|
|||
for (const Config::ButtonConfig& bc : line) {
|
||||
if (!bc.isValid()) continue;
|
||||
|
||||
SoundButton* sb = new SoundButton(bc.file, bc.name, bc.key);
|
||||
sb->setStartMS(bc.offset);
|
||||
sb->setLengthMS(bc.length);
|
||||
sb->setVolume(bc.volume);
|
||||
SoundButton* sb = new SoundButton(bc.name, bc.key);
|
||||
for(const Config::SampleConfig& sc : bc.samples) {
|
||||
if(!sc.isValid()) continue;
|
||||
|
||||
Log::info << "Button: " << bc.name << ": " << bc.file << " " << x << " " << y;
|
||||
SoundButton::Sample sample = {sc.file, sc.offset, sc.length, sc.volume};
|
||||
sb->addSample(sample);
|
||||
}
|
||||
|
||||
soundbuttons.push_back(sb);
|
||||
|
||||
|
|
|
@ -8,9 +8,7 @@
|
|||
|
||||
uint64_t SoundButton::nextid = 0;
|
||||
|
||||
SoundButton::SoundButton(const std::string& filename, const std::string& name_, const std::string& keycombo, QWidget* parent) : QPushButton(parent), id(nextid++), file(filename), keycombo(keycombo) {
|
||||
name = (name_.empty() ? filename : name_);
|
||||
|
||||
SoundButton::SoundButton(const std::string& name_, const std::string& keycombo, QWidget* parent) : QPushButton(parent), id(nextid++), name(name_), keycombo(keycombo) {
|
||||
QString info = getInfo();
|
||||
setText(info);
|
||||
setObjectName(QString::fromStdString("soundButton" + std::to_string(id)));
|
||||
|
@ -34,36 +32,12 @@ const std::string& SoundButton::getName() const {
|
|||
return name;
|
||||
}
|
||||
|
||||
const std::string& SoundButton::getFile() const {
|
||||
return file;
|
||||
}
|
||||
|
||||
const std::string& SoundButton::getKeyCombo() const {
|
||||
return keycombo;
|
||||
}
|
||||
|
||||
uint64_t SoundButton::getStartMS() const {
|
||||
return startms;
|
||||
}
|
||||
|
||||
uint64_t SoundButton::getLengthMS() const {
|
||||
return lengthms;
|
||||
}
|
||||
|
||||
float SoundButton::getVolume() const {
|
||||
return volume;
|
||||
}
|
||||
|
||||
void SoundButton::setStartMS(uint64_t startms_) {
|
||||
startms = startms_;
|
||||
}
|
||||
|
||||
void SoundButton::setLengthMS(uint64_t lengthms_) {
|
||||
lengthms = lengthms_;
|
||||
}
|
||||
|
||||
void SoundButton::setVolume(float v) {
|
||||
volume = v;
|
||||
void SoundButton::addSample(Sample& s) {
|
||||
samples.push_back(s);
|
||||
}
|
||||
|
||||
void SoundButton::setHighlighted(bool highlighted_) {
|
||||
|
@ -78,33 +52,43 @@ void SoundButton::paintEvent(QPaintEvent* event) {
|
|||
QPainter painter(this);
|
||||
if(highlighted) {
|
||||
QSize s = size();
|
||||
QRect rect(HIGHLIGHTBORDEROFFSET, HIGHLIGHTBORDEROFFSET, s.width()-HIGHLIGHTBORDEROFFSET*2, s.height()-HIGHLIGHTBORDEROFFSET*2);
|
||||
QRect rect(HIGHLIGHTBORDEROFFSET, HIGHLIGHTBORDEROFFSET, s.width() - HIGHLIGHTBORDEROFFSET*2, s.height() - HIGHLIGHTBORDEROFFSET*2);
|
||||
painter.setPen(QPen(Qt::red));
|
||||
painter.drawRect(rect);
|
||||
}
|
||||
|
||||
QString text = "";
|
||||
if(samples.size() > 1) {
|
||||
QString text = QString::fromStdString(std::to_string(currentSample+1) + "/" + std::to_string(samples.size()));
|
||||
|
||||
// cancel if nothing to print
|
||||
if(text.isEmpty())
|
||||
return;
|
||||
|
||||
painter.setPen(QPen(Qt::white));
|
||||
QPoint textPos(0, painter.fontMetrics().height());
|
||||
textPos.rx() = width() - painter.fontMetrics().horizontalAdvance(text) - 6;
|
||||
painter.drawText(textPos, text);
|
||||
painter.setPen(QPen(Qt::white));
|
||||
QPoint textPos(0, painter.fontMetrics().height());
|
||||
textPos.rx() = width() - painter.fontMetrics().horizontalAdvance(text) - 6;
|
||||
painter.drawText(textPos, text);
|
||||
}
|
||||
}
|
||||
|
||||
void SoundButton::play() {
|
||||
if(disabled) return;
|
||||
|
||||
uint64_t endms = (lengthms == 0 ? 0 : startms + lengthms);
|
||||
if(samples.size() == 0) {
|
||||
Log::error << "Button " << name << " has no sample set";
|
||||
setDisabled();
|
||||
return;
|
||||
}
|
||||
|
||||
const Sample& sample = samples.at(currentSample++);
|
||||
if(currentSample >= samples.size())
|
||||
currentSample = 0;
|
||||
|
||||
uint64_t endms = (sample.lengthms == 0 ? 0 : sample.startms + sample.lengthms);
|
||||
try {
|
||||
Sound::instance().addPlayback(file, volume, startms, endms);
|
||||
Sound::instance().addPlayback(sample.file, sample.volume, sample.startms, endms);
|
||||
} catch(const std::exception& e) {
|
||||
Log::error << "Catched Exception when plaing Audio File: " << file;
|
||||
Log::error << "Catched Exception when plaing Audio File: " << sample.file;
|
||||
setDisabled();
|
||||
}
|
||||
|
||||
repaint();
|
||||
}
|
||||
|
||||
void SoundButton::setDisabled() {
|
||||
|
|
Loading…
Reference in New Issue