soundboard/src/editsample.cpp

141 lines
4.2 KiB
C++

#include "editsample.h"
#include "ui_editsample.h"
#include "sound.h"
#include <Log.h>
#include <iomanip>
#include <sstream>
EditSample::EditSample(const std::string& audioFile_, QWidget *parent) : QDialog(parent), ui(new Ui::EditSample), audioFile(audioFile_) {
ui->setupUi(this);
std::vector<std::string> sounddevices = Sound::instance().getOutputs();
for(const std::string& dev : sounddevices) {
QString qdeviceName = QString::fromStdString(dev);
ui->soundOutputselect->addItem(qdeviceName, qdeviceName);
}
ui->graphicsView->loadFile(audioFile);
QObject::connect(ui->playButton, SIGNAL( clicked() ), this, SLOT( play() ));
QObject::connect(ui->stopButton, SIGNAL( clicked() ), this, SLOT( stop() ));
QObject::connect(ui->starttoCurrentButton, SIGNAL( clicked() ), this, SLOT( setStartToCurrent() ));
QObject::connect(ui->stoptoCurrentButton, SIGNAL( clicked() ), this, SLOT( setStopToCurrent() ));
QObject::connect(ui->startTime, SIGNAL( editingFinished() ), this, SLOT( timesChanged() ));
QObject::connect(ui->lengthTime, SIGNAL( editingFinished() ), this, SLOT( timesChanged() ));
setCurrentPosition(0);
}
EditSample::~EditSample() {
// 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();
delete ui;
}
uint64_t EditSample::getStartTime() const {
return getTimeInfo(ui->startTime);
}
uint64_t EditSample::getLength() const {
return getTimeInfo(ui->lengthTime);
}
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());
}
void EditSample::play() {
// get audio device
std::string devicename = ui->soundOutputselect->currentText().toStdString();
// get timing info
uint64_t startTime = getStartTime();
uint64_t lengthTime = getLength();
Log::info << "play audio: " << std::quoted(audioFile) << " on " << std::quoted(devicename) << " with " << startTime << " and " << lengthTime;
// stop all other sounds first
Sound::instance().stopAll();
// start new
Sound::instance().addPlayback(devicename, audioFile, 1.0, startTime, lengthTime, std::bind(&EditSample::setCurrentPosition, this, std::placeholders::_1));
}
void EditSample::stop() {
Sound::instance().stopAll();
}
void EditSample::setStartToCurrent() {
setStartTime(currentposition);
}
void EditSample::setStopToCurrent() {
uint64_t offset = getStartTime();
if(offset < currentposition) {
// current position is behind startposition -> shorten length to match
setLength(currentposition-offset);
} else {
// TODO:
// currentposition is before offset -> move entire section to match? do nothing?
}
}
void EditSample::timesChanged() {
uint64_t start = getStartTime();
uint64_t length = getLength();
ui->graphicsView->updateStartPosition(start);
ui->graphicsView->updateEndPosition(length == 0 ? 0 : (start + length));
}
uint64_t EditSample::getTimeInfo(const QTimeEdit* time) const {
QTime timedata = time->time();
return (((((
(timedata.hour() * 60)
+ timedata.minute()) * 60)
+ timedata.second()) * 1000)
+ timedata.msec());
}
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();
}
void EditSample::setCurrentPosition(uint64_t cp) {
currentposition = cp;
QTime time = timeFromMS(cp);
std::string formatedTime = formatTime(time);
// ui->currentPosLabel->setText(QString::fromStdString("Current: " + formatedTime));
// set text async
QString input = QString::fromStdString("Current: " + formatedTime);
QMetaObject::invokeMethod(ui->currentPosLabel, "setText", Qt::QueuedConnection, Q_ARG(QString, input));
// update cursor in view
QMetaObject::invokeMethod(ui->graphicsView, "updatePosition", Qt::QueuedConnection, Q_ARG(unsigned long, currentposition));
}