soundboard/src/editsample.cpp

141 lines
4.2 KiB
C++
Raw Normal View History

2021-12-20 00:19:35 +01:00
#include "editsample.h"
#include "ui_editsample.h"
2021-12-20 01:30:04 +01:00
#include "sound.h"
#include <Log.h>
#include <iomanip>
2021-12-20 02:13:26 +01:00
#include <sstream>
2021-12-20 01:30:04 +01:00
EditSample::EditSample(const std::string& audioFile_, QWidget *parent) : QDialog(parent), ui(new Ui::EditSample), audioFile(audioFile_) {
2021-12-20 00:19:35 +01:00
ui->setupUi(this);
2021-12-20 01:30:04 +01:00
std::vector<std::string> sounddevices = Sound::instance().getOutputs();
for(const std::string& dev : sounddevices) {
QString qdeviceName = QString::fromStdString(dev);
ui->soundOutputselect->addItem(qdeviceName, qdeviceName);
}
2021-12-20 15:59:03 +01:00
ui->graphicsView->loadFile(audioFile);
2021-12-20 01:30:04 +01:00
QObject::connect(ui->playButton, SIGNAL( clicked() ), this, SLOT( play() ));
QObject::connect(ui->stopButton, SIGNAL( clicked() ), this, SLOT( stop() ));
2021-12-20 02:13:26 +01:00
2021-12-20 15:00:13 +01:00
QObject::connect(ui->starttoCurrentButton, SIGNAL( clicked() ), this, SLOT( setStartToCurrent() ));
QObject::connect(ui->stoptoCurrentButton, SIGNAL( clicked() ), this, SLOT( setStopToCurrent() ));
2021-12-20 15:59:03 +01:00
QObject::connect(ui->startTime, SIGNAL( editingFinished() ), this, SLOT( timesChanged() ));
QObject::connect(ui->lengthTime, SIGNAL( editingFinished() ), this, SLOT( timesChanged() ));
2021-12-20 02:13:26 +01:00
setCurrentPosition(0);
2021-12-20 00:19:35 +01:00
}
EditSample::~EditSample() {
2022-05-01 14:49:14 +02:00
// here was a race condition: when the sample is played and the current possition is updated
// after this object is destroyed there will be a segfault.
stop();
2021-12-20 00:19:35 +01:00
delete ui;
}
2021-12-20 01:30:04 +01:00
2021-12-22 02:53:03 +01:00
uint64_t EditSample::getStartTime() const {
return getTimeInfo(ui->startTime);
}
uint64_t EditSample::getLength() const {
return getTimeInfo(ui->lengthTime);
}
2021-12-22 13:39:19 +01:00
void EditSample::setStartTime(uint64_t start) {
QTime time = timeFromMS(start);
ui->startTime->setTime(time);
ui->graphicsView->updateStartPosition(start);
}
void EditSample::setLength(uint64_t len) {
QTime time = timeFromMS(len);
ui->lengthTime->setTime(time);
ui->graphicsView->updateEndPosition(len + getStartTime());
}
2021-12-20 01:30:04 +01:00
void EditSample::play() {
// get audio device
std::string devicename = ui->soundOutputselect->currentText().toStdString();
// get timing info
2021-12-22 02:53:03 +01:00
uint64_t startTime = getStartTime();
uint64_t lengthTime = getLength();
2021-12-20 01:30:04 +01:00
Log::info << "play audio: " << std::quoted(audioFile) << " on " << std::quoted(devicename) << " with " << startTime << " and " << lengthTime;
2021-12-20 15:59:03 +01:00
// stop all other sounds first
Sound::instance().stopAll();
// start new
2021-12-20 02:13:26 +01:00
Sound::instance().addPlayback(devicename, audioFile, 1.0, startTime, lengthTime, std::bind(&EditSample::setCurrentPosition, this, std::placeholders::_1));
2021-12-20 01:30:04 +01:00
}
void EditSample::stop() {
Sound::instance().stopAll();
}
2021-12-20 15:00:13 +01:00
void EditSample::setStartToCurrent() {
2021-12-22 13:39:19 +01:00
setStartTime(currentposition);
2021-12-20 15:00:13 +01:00
}
void EditSample::setStopToCurrent() {
2021-12-22 02:53:03 +01:00
uint64_t offset = getStartTime();
2021-12-20 15:00:13 +01:00
if(offset < currentposition) {
// current position is behind startposition -> shorten length to match
2021-12-22 13:39:19 +01:00
setLength(currentposition-offset);
2021-12-20 15:00:13 +01:00
} else {
// TODO:
// currentposition is before offset -> move entire section to match? do nothing?
}
}
2021-12-20 15:59:03 +01:00
void EditSample::timesChanged() {
2021-12-22 02:53:03 +01:00
uint64_t start = getStartTime();
uint64_t length = getLength();
2021-12-20 15:59:03 +01:00
ui->graphicsView->updateStartPosition(start);
ui->graphicsView->updateEndPosition(length == 0 ? 0 : (start + length));
}
2021-12-20 01:30:04 +01:00
uint64_t EditSample::getTimeInfo(const QTimeEdit* time) const {
QTime timedata = time->time();
return (((((
(timedata.hour() * 60)
+ timedata.minute()) * 60)
+ timedata.second()) * 1000)
+ timedata.msec());
}
2021-12-20 02:13:26 +01:00
QTime EditSample::timeFromMS(uint64_t ms) const {
// return QTime().addMSecs(ms);
// return QTime(0, 0, 0, ms);
return QTime::fromMSecsSinceStartOfDay(ms);
}
std::string EditSample::formatTime(const QTime& time) const {
std::ostringstream str;
str << std::setw(2) << std::setfill('0')
<< time.minute() << ':' << std::setw(2)
<< time.second() << '.' << std::setw(3)
<< time.msec();
return str.str();
}
2021-12-20 01:30:04 +01:00
void EditSample::setCurrentPosition(uint64_t cp) {
currentposition = cp;
2021-12-20 02:13:26 +01:00
QTime time = timeFromMS(cp);
std::string formatedTime = formatTime(time);
2021-12-20 14:47:40 +01:00
2021-12-20 02:13:26 +01:00
// ui->currentPosLabel->setText(QString::fromStdString("Current: " + formatedTime));
2021-12-20 14:47:40 +01:00
// set text async
QString input = QString::fromStdString("Current: " + formatedTime);
QMetaObject::invokeMethod(ui->currentPosLabel, "setText", Qt::QueuedConnection, Q_ARG(QString, input));
2021-12-20 15:59:03 +01:00
// update cursor in view
QMetaObject::invokeMethod(ui->graphicsView, "updatePosition", Qt::QueuedConnection, Q_ARG(unsigned long, currentposition));
2021-12-20 01:30:04 +01:00
}