forked from MrBesen/soundboard
config laden / neuladen
This commit is contained in:
parent
610d0eee5f
commit
ec733d21cc
|
@ -23,6 +23,7 @@ public:
|
|||
std::string key;
|
||||
uint64_t offset;
|
||||
uint64_t length;
|
||||
float volume;
|
||||
|
||||
bool isValid() const;
|
||||
};
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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() {}
|
||||
};
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
{
|
||||
"audio": {
|
||||
"devices": [
|
||||
"VirtualMic",
|
||||
""
|
||||
]
|
||||
},
|
||||
"buttons": [
|
||||
{
|
||||
"name": "",
|
||||
"file": "<required>",
|
||||
"key": "",
|
||||
"offset": 0,
|
||||
"length": 0,
|
||||
"volume": 1.0
|
||||
}
|
||||
]
|
||||
}
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue