soundboard/src/mainwindow.cpp

291 lines
7.9 KiB
C++

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "buttonmanager.h"
#include "editsample.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);
up = new QxtGlobalShortcut(QKeySequence("Shift+Up"));
down = new QxtGlobalShortcut(QKeySequence("Shift+Down"));
left = new QxtGlobalShortcut(QKeySequence("Shift+Left"));
right = new QxtGlobalShortcut(QKeySequence("Shift+Right"));
play = new QxtGlobalShortcut(QKeySequence("Shift+Num+Enter"));
QKeySequence seq(QString::fromStdString("Shift+Num+0"));
stopGlobal = new QxtGlobalShortcut(seq);
reloadConfig();
QObject::connect(ui->reloadButton, SIGNAL(clicked()), this, SLOT(reloadConfig()));
QObject::connect(ui->stopButton, SIGNAL( clicked() ), this, SLOT( stop() ));
QObject::connect(ui->actionAddButton, SIGNAL( triggered() ), this, SLOT( addSample() ));
QObject::connect(ui->actionSaveConfig, SIGNAL( triggered() ), this, SLOT( saveConfig() ));
QObject::connect(ui->actionButtonManager, SIGNAL( triggered() ), this, SLOT( openButtonManager() ));
QObject::connect(ui->alwaysOnTop, SIGNAL( stateChanged(int) ), this, SLOT( alwaysOnTopSettingChange(int) ));
QObject::connect(stopGlobal, SIGNAL( activated() ), this, SLOT( stop() ));
QObject::connect(this, SIGNAL(newStatusMessage(const QString&)), ui->statusbar, SLOT(showMessage(const QString&)));
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() ));
}
MainWindow::~MainWindow() {
delete ui;
delete stopGlobal;
delete up;
delete down;
delete left;
delete right;
delete play;
Sound::deinitInstance();
}
void MainWindow::reloadConfig() {
Log::info << "realodConfig()";
QString loaded = QString::fromStdString("loading config");
emit newStatusMessage(loaded);
config.load();
loadSoundFromConfig();
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() {
Log::debug << "up";
reselectNext([max = ui->gridLayout->rowCount()](uint8_t&, uint8_t& y){ y = wrap(--y, max); });
Log::debug << "x " << (int) xCoord << " y " << (int) yCoord;
}
void MainWindow::moveDown() {
Log::debug << "down";
reselectNext([max = ui->gridLayout->rowCount()](uint8_t&, uint8_t& y){ y = wrap0(++y, max); });
Log::debug << "x " << (int) xCoord << " y " << (int) yCoord;
}
void MainWindow::moveLeft() {
Log::debug << "left";
reselectNext([max = ui->gridLayout->columnCount()](uint8_t& x, uint8_t&){ x = wrap(--x, max); });
Log::debug << "x " << (int) xCoord << " y " << (int) yCoord;
}
void MainWindow::moveRight() {
Log::debug << "right";
reselectNext([max = ui->gridLayout->columnCount()](uint8_t& x, uint8_t&){ x = wrap0(++x, max); });
Log::debug << "x " << (int) xCoord << " y " << (int) yCoord;
}
void MainWindow::playCurrent() {
Log::debug << "play";
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::addSample() {
Log::debug << "open sampleEditor";
QFileDialog fileselector(this);
fileselector.setFileMode(QFileDialog::ExistingFile);
fileselector.setDirectory(QString::fromStdString(Sound::FOLDER));
fileselector.exec();
QStringList filelist = fileselector.selectedFiles();
if(filelist.size() != 1) {
Log::error << "no file selected";
return;
} else {
QString qfile = filelist.at(0);
std::string file = qfile.toStdString();
file = file.substr(file.rfind('/')+1);
Log::info << "selected file: " << file;
//spawn edit dialog
EditSample esample(file, this);
esample.exec();
}
}
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) {
removeAllButtons();
loadButtonsFromConfig();
}
}
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::FOLDER = config.rootConfig.audioPath;
Log::debug << "Sound::FOLDER: " << Sound::FOLDER;
}
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.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::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;
}