soundboard/src/mainwindow.cpp

320 lines
8.1 KiB
C++

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "buttonmanager.h"
#include "editsample.h"
#include "settings.h"
#include "buttonsearch.h"
#include <QFileDialog>
#include <QMessageBox>
#include <iostream>
#include <string>
#include <Log.h>
MainWindow::MainWindow(const std::string& binary, QWidget* parent) : QMainWindow(parent), ui(new Ui::Soundboard), config(binary) {
ui->setupUi(this);
reloadConfig();
QObject::connect(ui->stopButton, SIGNAL( clicked() ), this, SLOT( stop() ));
QObject::connect(ui->actionSaveConfig, SIGNAL( triggered() ), this, SLOT( saveConfig() ));
QObject::connect(ui->actionButtonManager, SIGNAL( triggered() ), this, SLOT( openButtonManager() ));
QObject::connect(ui->actionSettings, SIGNAL( triggered() ), this, SLOT( openSettings() ));
QObject::connect(ui->actionReloadConfig, SIGNAL( triggered() ), this, SLOT(reloadConfig()));
QObject::connect(ui->alwaysOnTop, SIGNAL( stateChanged(int) ), this, SLOT( alwaysOnTopSettingChange(int) ));
QObject::connect(this, SIGNAL(newStatusMessage(const QString&)), ui->statusbar, SLOT(showMessage(const QString&)));
}
MainWindow::~MainWindow() {
delete ui;
delete stopGlobal;
delete up;
delete down;
delete left;
delete right;
delete play;
delete search;
Sound::deinitInstance();
}
void MainWindow::reloadConfig() {
Log::info << "realodConfig()";
QString loaded = QString::fromStdString("loading config");
emit newStatusMessage(loaded);
config.load();
loadSoundFromConfig();
loadShortcuts();
removeAllButtons();
loadButtonsFromConfig();
QString done = QString::fromStdString("config loaded");
emit newStatusMessage(done);
Log::info << "realodConfig() done";
}
void MainWindow::stop() {
Sound::instance().stopAll();
}
static uint8_t wrap(uint8_t a, uint8_t max) {
if(a >= max)
return max-1;
return a;
}
static uint8_t wrap0(uint8_t a, uint8_t max) {
if(a >= max)
return 0;
return a;
}
void MainWindow::moveUp() {
reselectNext([max = ui->gridLayout->rowCount()](uint8_t&, uint8_t& y){ y = wrap(--y, max); });
}
void MainWindow::moveDown() {
reselectNext([max = ui->gridLayout->rowCount()](uint8_t&, uint8_t& y){ y = wrap0(++y, max); });
}
void MainWindow::moveLeft() {
reselectNext([max = ui->gridLayout->columnCount()](uint8_t& x, uint8_t&){ x = wrap(--x, max); });
}
void MainWindow::moveRight() {
reselectNext([max = ui->gridLayout->columnCount()](uint8_t& x, uint8_t&){ x = wrap0(++x, max); });
}
void MainWindow::playCurrent() {
QLayoutItem* item = ui->gridLayout->itemAtPosition(yCoord, xCoord);
if(item && item->widget()) {
SoundButton* button = (SoundButton*) item->widget();
button->click();
}
}
void MainWindow::reloadButtonConfig() {
removeAllButtons();
loadButtonsFromConfig();
}
void MainWindow::alwaysOnTopSettingChange(int status) {
Qt::WindowFlags eFlags = windowFlags();
Log::debug << "status: " << status;
if(status) {
setWindowFlags(eFlags | Qt::WindowStaysOnTopHint | Qt::X11BypassWindowManagerHint);
} else {
setWindowFlags(eFlags & ~(Qt::WindowStaysOnTopHint | Qt::X11BypassWindowManagerHint));
}
show();
}
void MainWindow::saveConfig() {
Log::info << "save Config";
config.save();
}
void MainWindow::openButtonManager() {
Log::info << "openButtonManager";
ButtonManager buttonManager(config, this);
buttonManager.exec();
// reload button config
if(buttonManager.result() == QMessageBox::ButtonRole::AcceptRole) {
reloadButtonConfig();
}
}
void MainWindow::openSettings() {
Log::info << "openSettings";
Settings settings(config, this);
settings.exec();
// reload complete config
if(settings.result() == QMessageBox::ButtonRole::AcceptRole) {
reloadConfig();
}
}
void MainWindow::openSearch() {
Log::info << "openSearch";
ButtonSearch* bs = new ButtonSearch(config);
int res = bs->exec();
if(res >= 0) {
playButtonID(res);
}
delete bs;
}
void MainWindow::loadSoundFromConfig() {
Sound& sound = Sound::instance(); // init sound
sound.reset();
const std::vector<std::string>& devices = config.rootConfig.audio.devices;
for (const std::string& device : devices) {
Log::note << "loadAudio device: \"" << device << '"';
if (!sound.addDeviceWithName(device)) {
Log::warn << "AudioDevice could not be loaded: \"" << device << '"';
QString done = QString::fromStdString("Sound Device: " + device + " not found!");
emit newStatusMessage(done);
return;
}
}
Log::debug << "Sound devices loaded";
sound.setMasterVolume(config.rootConfig.audio.volume);
Sound::FOLDER = config.rootConfig.audioPath;
Log::debug << "Sound::FOLDER: " << Sound::FOLDER;
}
void MainWindow::loadShortcuts() {
delete up;
delete down;
delete left;
delete right;
delete play;
delete search;
delete stopGlobal;
const Config::ShortcutConfig& sc = config.rootConfig.shortcuts;
up = loadShortcut(sc.up);
down = loadShortcut(sc.down);
left = loadShortcut(sc.left);
right = loadShortcut(sc.right);
play = loadShortcut(sc.play);
search = loadShortcut(sc.search);
stopGlobal = loadShortcut(sc.stop);
QObject::connect(up, SIGNAL( activated() ), this, SLOT( moveUp() ));
QObject::connect(down, SIGNAL( activated() ), this, SLOT( moveDown() ));
QObject::connect(left, SIGNAL( activated() ), this, SLOT( moveLeft() ));
QObject::connect(right, SIGNAL( activated() ), this, SLOT( moveRight() ));
QObject::connect(play, SIGNAL( activated() ), this, SLOT( playCurrent() ));
QObject::connect(search, SIGNAL( activated() ), this, SLOT( openSearch() ));
QObject::connect(stopGlobal, SIGNAL( activated() ), this, SLOT( stop() ));
}
void MainWindow::removeAllButtons() {
//remove old buttons
for (SoundButton* sb : soundbuttons) {
ui->gridLayout->removeWidget(sb);
delete sb;
}
soundbuttons.clear();
}
void MainWindow::loadButtonsFromConfig() {
int x = 0;
int y = 0;
const std::vector<std::vector<Config::ButtonConfig>>& buttonConfigs = config.rootConfig.buttons;
for (const std::vector<Config::ButtonConfig>& line : buttonConfigs) {
if(line.empty()) continue;
for (const Config::ButtonConfig& bc : line) {
if (!bc.isValid()) continue;
SoundButton* sb = new SoundButton(bc.id, bc.name, bc.key);
for(const Config::SampleConfig& sc : bc.samples) {
if(!sc.isValid()) continue;
SoundButton::Sample sample = {sc.file, sc.offset, sc.length, sc.volume};
sb->addSample(sample);
}
soundbuttons.push_back(sb);
ui->gridLayout->addWidget(sb, y, x, 1, bc.width);
sb->show();
x += bc.width;
}
//ui->gridLayout->setRowMinimumHeight(y, 60);
x = 0;
y++;
}
xCoord = 0;
yCoord = 0;
// select the first button
QLayoutItem* item = ui->gridLayout->itemAtPosition(0, 0);
if(item && item->widget()) {
((SoundButton*) item->widget())->setHighlighted(true);
}
// ui->gridLayout->setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred));
}
void MainWindow::playButtonID(uint32_t buttonid) {
const Config::ButtonConfig* btnconf = config.getButtonByID(buttonid);
if(!btnconf) {
Log::error << "invalid button id triggered: " << buttonid;
return;
}
SoundButton* sb = findChild<SoundButton*>(QString::fromStdString("soundButton" + std::to_string(buttonid)));
if(sb == nullptr) {
Log::error << "button not found: " << buttonid;
return;
}
sb->click();
}
void MainWindow::reselectNext(std::function<void(uint8_t&,uint8_t&)> stepf) {
QLayoutItem* item = ui->gridLayout->itemAtPosition(yCoord, xCoord);
QLayoutItem* newitem = findNextButton(stepf);
if(item != newitem) {
if(item && item->widget()) {
((SoundButton*) item->widget())->setHighlighted(false);
}
if(newitem && newitem->widget()) {
((SoundButton*) newitem->widget())->setHighlighted(true);
}
}
}
QLayoutItem* MainWindow::findNextButton(std::function<void(uint8_t&,uint8_t&)> stepf) {
// need copy for while condition
uint8_t x = xCoord;
uint8_t y = yCoord;
QLayoutItem* currentItem = ui->gridLayout->itemAtPosition(y, x);
QLayoutItem* item = currentItem;
do {
stepf(x, y);
item = ui->gridLayout->itemAtPosition(y, x);
} while(item == currentItem && (x != xCoord || y != yCoord));
xCoord = x;
yCoord = y;
// might the same item
return item;
}
QxtGlobalShortcut* MainWindow::loadShortcut(const std::string& key) {
QKeySequence seq(QString::fromStdString(key));
if(seq.isEmpty())
return nullptr;
return new QxtGlobalShortcut(seq);
}