config laden / neuladen

This commit is contained in:
mrbesen 2021-12-13 17:28:32 +01:00
parent 610d0eee5f
commit ec733d21cc
Signed by untrusted user: MrBesen
GPG Key ID: 596B2350DCD67504
10 changed files with 146 additions and 24 deletions

View File

@ -23,6 +23,7 @@ public:
std::string key;
uint64_t offset;
uint64_t length;
float volume;
bool isValid() const;
};

View File

@ -14,13 +14,13 @@ public:
static Sound& instance();
static void deinit();
void addPlayback(const std::string& name, float volume = 1.f);
void addPlayback(const std::string& name, float volume = 1.f, uint64_t beginms = 0, uint64_t endms = 0);
bool addDefaultDevice();
bool addDeviceWithName(const std::string& name);
void stopAll();
void reset();
const static std::string FOLDER;
static std::string FOLDER;
private:
Sound();
~Sound();

View File

@ -18,6 +18,14 @@ public:
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);
QPushButton* getButton();
public slots:
@ -25,10 +33,14 @@ public slots:
private:
static uint64_t nextid;
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;
QxtGlobalShortcut* globalShortcut = nullptr;
QPushButton* button = nullptr;

View File

@ -4,6 +4,7 @@
#include "miniaudio.h"
#include <list>
#include <limits>
#include <string>
class SoundDevice {
@ -15,7 +16,7 @@ public:
static SoundDevice* createDevice(ma_context* ctx, const ma_device_id* did = NULL);
void stop();
void addPlayback(const std::string& name, float volume = 1.f);
void addPlayback(const std::string& name, float volume = 1.f, uint64_t beginms = 0, uint64_t endms = 0);
void startDevice();
void cleanupDecoders(); //fertige decoder löschen
@ -27,6 +28,9 @@ private:
struct Playback {
ma_decoder decoder;
float volume;
uint64_t currentFrame = 0;
uint64_t startFrame = 0;
uint64_t endFrame = std::numeric_limits<uint64_t>::max();
bool isDone = false;
Playback() {}
};

18
soundboard.json.example Normal file
View File

@ -0,0 +1,18 @@
{
"audio": {
"devices": [
"VirtualMic",
""
]
},
"buttons": [
{
"name": "",
"file": "<required>",
"key": "",
"offset": 0,
"length": 0,
"volume": 1.0
}
]
}

View File

@ -30,6 +30,7 @@ void from_json(const json& j, Config::RootConfig::ButtonConfig& bc) {
bc.key = j.value("key", "");
bc.offset = j.value("offset", 0);
bc.length = j.value("length", 0);
bc.volume = j.value("volume", 1.f);
}
void from_json(const json& j, Config::RootConfig& rc) {

View File

@ -6,22 +6,14 @@
#include <Log.h>
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::Soundboard) {
MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent), ui(new Ui::Soundboard) {
ui->setupUi(this);
reloadConfig();
// init Buttons
SoundButton* sb;
sb = new SoundButton("Uwu_voice-xjrU3N8M4eo-251.mp3", "UwU", "Shift+F1");
ui->gridLayout->addWidget(sb->getButton(), 0, 0);
soundbuttons.push_back(sb);
sb = new SoundButton("bonk.wav", "Bonk");
ui->gridLayout->addWidget(sb->getButton(), 0, 1);
soundbuttons.push_back(sb);
QObject::connect(ui->reloadButton, SIGNAL( clicked() ), this, SLOT( reloadConfig() ));
QObject::connect(this, SIGNAL( newStatusMessage(const QString&) ), ui->statusbar, SLOT( showMessage(const QString&) ));
QObject::connect(ui->reloadButton, SIGNAL(clicked()), this, SLOT(reloadConfig()));
QObject::connect(this, SIGNAL(newStatusMessage(const QString&)), ui->statusbar, SLOT(showMessage(const QString&)));
}
MainWindow::~MainWindow() {
@ -41,10 +33,10 @@ void MainWindow::reloadConfig() {
Sound& sound = Sound::instance(); // init sound
sound.reset();
const std::vector<std::string>& devices = config.rootConfig.audio.devices;
for(const std::string& device : devices) {
for (const std::string& device : devices) {
Log::note << "loadAudio device: \"" << device << '"';
if(!sound.addDeviceWithName(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);
@ -52,6 +44,50 @@ void MainWindow::reloadConfig() {
}
}
Log::debug << "Sound devices loaded";
//remove old buttons
for (SoundButton* sb : soundbuttons) {
ui->gridLayout->removeWidget(sb->getButton());
delete sb;
}
soundbuttons.clear();
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()) {
SoundButton* sb = new SoundButton(bc.file, bc.name, bc.key);
sb->setStartMS(bc.offset);
sb->setLengthMS(bc.length);
sb->setVolume(bc.volume);
Log::info << "Button: " << bc.name << ": " << bc.file << " " << x << " " << y;
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);
sb->getButton()->show();
x++;
if (x >= 10) {
y++;
x = 0;
}
}
}
QString done = QString::fromStdString("config loaded");
emit newStatusMessage(done);

View File

@ -45,7 +45,7 @@
#include <Log.h>
Sound* Sound::inst = nullptr;
const std::string Sound::FOLDER = "/home/yannis/prog/ts3/soundboardsounds/";
std::string Sound::FOLDER = "./";
Sound& Sound::instance() {
if (!inst) {
@ -64,9 +64,12 @@ void Sound::deinit() {
Log::info << "Sound deinited";
}
void Sound::addPlayback(const std::string& name, float volume) {
void Sound::addPlayback(const std::string& name, float volume, uint64_t beginms, uint64_t endms) {
if(volume < 0.00001f)
volume = 0.00001f;
for(SoundDevice* sd : devices) {
sd->addPlayback(name, volume);
sd->addPlayback(name, volume, beginms, endms);
}
}

View File

@ -34,10 +34,35 @@ 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;
}
QPushButton* SoundButton::getButton() {
return button;
}
void SoundButton::play() {
Sound::instance().addPlayback(file);
uint64_t endms = (lengthms == 0 ? 0 : startms + lengthms);
Sound::instance().addPlayback(file, volume, startms, endms);
}

View File

@ -58,11 +58,19 @@ void SoundDevice::sound_callback(void* outbuffer, ma_uint32 frameCount) {
ma_decoder* pDecoder = &(pb->decoder);
float volume = pb->volume;
// if a end frame is set, make sure to not read over it
ma_uint32 shouldReadCount = frameCount;
if(pb->currentFrame + frameCount > pb->endFrame) {
shouldReadCount = pb->endFrame - pb->currentFrame;
}
//decoder "reinaddieren"
ma_uint64 read = readDecoderandAdd(pDecoder, volume, streamDivider, frameCount, outbuffer);
ma_uint64 read = 0;
if(shouldReadCount > 0)
read = readDecoderandAdd(pDecoder, volume, streamDivider, shouldReadCount, outbuffer);
//decoder fertig -> nicht mehr verwenden
if (read < frameCount) {
if (read < shouldReadCount) {
pb->isDone = true;
--data.decoderCount;
}
@ -148,19 +156,33 @@ void SoundDevice::stop() {
deviceRunning = false;
}
void SoundDevice::addPlayback(const std::string& name, float volume) {
void SoundDevice::addPlayback(const std::string& name, float volume, uint64_t beginms, uint64_t endms) {
cleanupDecoders();
Playback* pb = new Playback();
if (ma_decoder_init_file((Sound::FOLDER + name).c_str(), NULL, &(pb->decoder)) != MA_SUCCESS) {
Log::info << "Sound datei: " << name << " konnte nicht geladen werden!";
Log::error << "Sound datei: " << name << " konnte nicht geladen werden!";
throw std::exception();
}
Log::debug << "created decoder with samplerate: " << pb->decoder.internalSampleRate;
pb->volume = volume;
pb->isDone = false;
if(beginms != 0) {
pb->startFrame = (pb->decoder.internalSampleRate * 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;
Log::trace << "skip endframe: " << pb->endFrame;
}
ma_mutex_lock(data.mutex);
data.playbacks.push_back(pb);