#include "editsample.h" #include "ui_editsample.h" #include "sound.h" #include #include #include EditSample::EditSample(const std::string& audioFile_, QWidget *parent) : QDialog(parent), ui(new Ui::EditSample), audioFile(audioFile_) { ui->setupUi(this); std::vector 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)); }