forked from MrBesen/soundboard
multi column button, define rows
This commit is contained in:
parent
ec733d21cc
commit
0db1d49949
|
@ -12,23 +12,26 @@ public:
|
|||
bool hasChanged();
|
||||
void load();
|
||||
|
||||
struct AudioConfig {
|
||||
std::vector<std::string> devices;
|
||||
};
|
||||
|
||||
struct ButtonConfig {
|
||||
std::string name;
|
||||
std::string file;
|
||||
std::string key;
|
||||
uint64_t offset;
|
||||
uint64_t length;
|
||||
float volume;
|
||||
uint8_t width; // default is 6
|
||||
|
||||
bool isValid() const;
|
||||
};
|
||||
|
||||
struct RootConfig {
|
||||
struct AudioConfig {
|
||||
std::vector<std::string> devices;
|
||||
} audio;
|
||||
AudioConfig audio;
|
||||
|
||||
struct ButtonConfig {
|
||||
std::string name;
|
||||
std::string file;
|
||||
std::string key;
|
||||
uint64_t offset;
|
||||
uint64_t length;
|
||||
float volume;
|
||||
|
||||
bool isValid() const;
|
||||
};
|
||||
|
||||
std::vector<ButtonConfig> buttons;
|
||||
std::vector<std::vector<ButtonConfig>> buttons;
|
||||
std::string audioPath;
|
||||
} rootConfig;
|
||||
|
||||
|
|
|
@ -6,13 +6,15 @@
|
|||
]
|
||||
},
|
||||
"buttons": [
|
||||
{
|
||||
"name": "",
|
||||
"file": "<required>",
|
||||
"key": "",
|
||||
"offset": 0,
|
||||
"length": 0,
|
||||
"volume": 1.0
|
||||
}
|
||||
[
|
||||
{
|
||||
"name": "",
|
||||
"file": "<required>",
|
||||
"key": "",
|
||||
"offset": 0,
|
||||
"length": 0,
|
||||
"volume": 1.0
|
||||
}
|
||||
]
|
||||
]
|
||||
}
|
|
@ -20,29 +20,35 @@ Config::Config() {
|
|||
Config::~Config() {
|
||||
}
|
||||
|
||||
void from_json(const json& j, Config::RootConfig::AudioConfig& ac) {
|
||||
void from_json(const json& j, Config::AudioConfig& ac) {
|
||||
readVector(ac.devices, j.value("devices", json::array()));
|
||||
}
|
||||
|
||||
void from_json(const json& j, Config::RootConfig::ButtonConfig& bc) {
|
||||
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);
|
||||
}
|
||||
|
||||
void from_json(const json& j, Config::RootConfig& rc) {
|
||||
rc.audio = j.value<Config::RootConfig::AudioConfig>("audio", {});
|
||||
rc.audio = j.value<Config::AudioConfig>("audio", {});
|
||||
json barr = j.value("buttons", json::array());
|
||||
if(barr.is_array() && !barr.empty()) {
|
||||
readVector(rc.buttons, barr);
|
||||
rc.buttons.reserve(barr.size());
|
||||
for(const json& line : barr) {
|
||||
std::vector<Config::ButtonConfig> btns;
|
||||
readVector(btns, line);
|
||||
rc.buttons.push_back(btns);
|
||||
}
|
||||
}
|
||||
rc.audioPath = j.value("audioPath", "");
|
||||
}
|
||||
|
||||
bool Config::RootConfig::ButtonConfig::isValid() const {
|
||||
bool Config::ButtonConfig::isValid() const {
|
||||
return !file.empty();
|
||||
}
|
||||
|
||||
|
|
|
@ -22,6 +22,23 @@ MainWindow::~MainWindow() {
|
|||
Sound::deinit();
|
||||
}
|
||||
|
||||
// https://stackoverflow.com/a/4857631/4399859
|
||||
static void clearLayout(QLayout* layout) {
|
||||
if (layout == NULL)
|
||||
return;
|
||||
QLayoutItem* item;
|
||||
while ((item = layout->takeAt(0))) {
|
||||
if (item->layout()) {
|
||||
clearLayout(item->layout());
|
||||
delete item->layout();
|
||||
}
|
||||
if (item->widget()) {
|
||||
delete item->widget();
|
||||
}
|
||||
delete item;
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::reloadConfig() {
|
||||
Log::info << "realodConfig()";
|
||||
|
||||
|
@ -53,14 +70,18 @@ void MainWindow::reloadConfig() {
|
|||
}
|
||||
soundbuttons.clear();
|
||||
|
||||
// clearLayout(ui->gridLayout);
|
||||
|
||||
Sound::FOLDER = config.rootConfig.audioPath;
|
||||
Log::debug << "Sound::FOLDER: " << Sound::FOLDER;
|
||||
|
||||
int x = 0;
|
||||
int y = 0;
|
||||
const std::vector<Config::RootConfig::ButtonConfig>& buttonConfigs = config.rootConfig.buttons;
|
||||
for (const Config::RootConfig::ButtonConfig& bc : buttonConfigs) {
|
||||
if (bc.isValid()) {
|
||||
const std::vector<std::vector<Config::ButtonConfig>>& buttonConfigs = config.rootConfig.buttons;
|
||||
for (const std::vector<Config::ButtonConfig>& line : buttonConfigs) {
|
||||
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);
|
||||
|
@ -70,22 +91,14 @@ void MainWindow::reloadConfig() {
|
|||
|
||||
soundbuttons.push_back(sb);
|
||||
|
||||
QLayoutItem* item = ui->gridLayout->itemAtPosition(y, x);
|
||||
if(item != nullptr) {
|
||||
// ui->gridLayout->removeWidget(item->widget());
|
||||
int index = ui->gridLayout->indexOf(item->widget());
|
||||
ui->gridLayout->takeAt(index);
|
||||
}
|
||||
|
||||
ui->gridLayout->addWidget(sb->getButton(), y, x);
|
||||
ui->gridLayout->addWidget(sb->getButton(), y, x, 1, bc.width);
|
||||
sb->getButton()->show();
|
||||
|
||||
x++;
|
||||
if (x >= 10) {
|
||||
y++;
|
||||
x = 0;
|
||||
}
|
||||
x += bc.width;
|
||||
}
|
||||
ui->gridLayout->setRowMinimumHeight(y, 40);
|
||||
x = 0;
|
||||
y++;
|
||||
}
|
||||
|
||||
QString done = QString::fromStdString("config loaded");
|
||||
|
|
|
@ -9,9 +9,9 @@ SoundButton::SoundButton(const std::string& filename, const std::string& name_,
|
|||
|
||||
button = new QPushButton(QString::fromStdString(name));
|
||||
button->setObjectName(QString::fromStdString("soundButton" + std::to_string(id)));
|
||||
button->setGeometry(QRect(10, 10, 100, 27));
|
||||
|
||||
globalShortcut = new QxtGlobalShortcut(QString::fromStdString(keycombo));
|
||||
QKeySequence seq(QString::fromStdString(keycombo));
|
||||
globalShortcut = new QxtGlobalShortcut(seq);
|
||||
|
||||
QObject::connect(globalShortcut, SIGNAL( activated() ), this, SLOT( play() ));
|
||||
QObject::connect(button, SIGNAL( clicked() ), this, SLOT( play() ));
|
||||
|
|
|
@ -166,20 +166,20 @@ void SoundDevice::addPlayback(const std::string& name, float volume, uint64_t be
|
|||
throw std::exception();
|
||||
}
|
||||
|
||||
Log::debug << "created decoder with samplerate: " << pb->decoder.internalSampleRate;
|
||||
Log::debug << "created decoder with samplerate: " << pb->decoder.outputSampleRate;
|
||||
|
||||
pb->volume = volume;
|
||||
pb->isDone = false;
|
||||
|
||||
if(beginms != 0) {
|
||||
pb->startFrame = (pb->decoder.internalSampleRate * beginms) / 1000;
|
||||
pb->startFrame = (pb->decoder.outputSampleRate * beginms) / 1000;
|
||||
ma_decoder_seek_to_pcm_frame(&pb->decoder, pb->startFrame);
|
||||
pb->currentFrame = pb->startFrame;
|
||||
Log::trace << "skip to frame: " << pb->currentFrame;
|
||||
}
|
||||
|
||||
if(endms != 0) {
|
||||
pb->endFrame = (pb->decoder.internalSampleRate * endms) / 1000;
|
||||
pb->endFrame = (pb->decoder.outputSampleRate * endms) / 1000;
|
||||
Log::trace << "skip endframe: " << pb->endFrame;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue