diff --git a/docs/changelog.txt b/docs/changelog.txt index 89eaf47..48b0ddf 100644 --- a/docs/changelog.txt +++ b/docs/changelog.txt @@ -16,6 +16,8 @@ v 0.2.0 Antigona (24/04/2024) + Refactor AudioMasterWidget to AudioDMXReceptionWidget. + mp3, flac, wav (mp3 has given some errors seeking cursor...). + settings dialog not working, only read the conf file at startup. ++ variable number of layers. ++ olathread, send double channels only once for each dmx frame buffer. v 0.1.3 Unreleased (19/04/2024) diff --git a/docs/roadmap.txt b/docs/roadmap.txt index 4b96379..8ff57d7 100644 --- a/docs/roadmap.txt +++ b/docs/roadmap.txt @@ -27,12 +27,10 @@ v 0.2.2 v 0.2.1 - Multi devices output. -- Rose noise and sine generator in menu to test system. - Play Mode: - Play all medias found in folder consecutevily or random, with loop. - Play all medias, consecutevily and random, with loop. - mute/panic on layer. -- number of layers configured in conf file, up to 256. - Master Bus Layer: - each layer will have one "Gain" prefader that acts in source, "Vol" in v 1.3. - each layer will have one volume dmx channel for each bus layer. One aux "Send" prefader. @@ -42,13 +40,16 @@ v 0.2.1 - magicq .hed - audio device linked, outputs will be redirected there. - dmx address + universe settings. +- Rose noise and sine generator in menu to test system. - Keyboards strokes, load media files from ui. - Dar la opción clickeando en el widget de tiempo de poner una cuenta atrás en vez de hacia delante. -- LOGs y entrada de comandos. +- Logs, verbosity, timestamp. - Bufgix: depurar errores cuando no carga la librería de medias, cambia el númmero de capas, cambia el universo, etc. - New control mode without pitch control, it saves resources. MA_SOUND_FLAG_NO_PITCH - Vumeter or indicator about audio output in layer and master. - SettingsDialog. - Load/save conf file. - ¿stop offset? is it needed? -- decouple MiniAudioEngine from AudioWidget, starts whith no gui or with gui in a dedicated thread. +- decouple MiniAudioEngine from AudioWidget, starts whith no gui or with audio in a dedicated thread. +- New Status "Iddle" in playbacks if is not loaded. +- check return errors, we are too happy.... diff --git a/src/audiolayerwidget.cpp b/src/audiolayerwidget.cpp index 1a5996c..99e1996 100644 --- a/src/audiolayerwidget.cpp +++ b/src/audiolayerwidget.cpp @@ -10,9 +10,6 @@ AudioLayerWidget::AudioLayerWidget(QWidget *parent, QString name, int layer): QVBoxLayout *layout = new QVBoxLayout; QHBoxLayout *progressTime = new QHBoxLayout; - //m_progressTimeLabel = new QLabel; - //m_progressTimeLabel->setText(PROGRESS_TIME_LABEL); - //progressTime->addWidget(m_progressTimeLabel); m_progressTime = new QTimeEdit; m_progressTime->text(); m_progressTime->setDisplayFormat("h:mm:ss:zzz"); @@ -21,9 +18,6 @@ AudioLayerWidget::AudioLayerWidget(QWidget *parent, QString name, int layer): m_progressTime->setMaximumWidth(90); m_progressTime->setFocusPolicy(Qt::NoFocus); progressTime->addWidget(m_progressTime); - //m_totalTimeLabel = new QLabel; - //m_totalTimeLabel->setText(TOTAL_TIME_LABEL); - //progressTime->addWidget(m_totalTimeLabel); m_totalTimeValue = new QTimeEdit; m_totalTimeValue->setDisplayFormat("h:mm:ss:zzz"); m_totalTimeValue->setReadOnly(true); @@ -49,19 +43,19 @@ AudioLayerWidget::AudioLayerWidget(QWidget *parent, QString name, int layer): layout->addLayout(status); QHBoxLayout *volumeBox = new QHBoxLayout; - m_volume = new SliderGroup("Vol", 0 , 100, NULL); + m_volume = new SliderGroup("Vol", 0 , 100, 2, NULL); volumeBox->addWidget(m_volume); - connect(m_volume, SIGNAL(valueChanged(int)), this, SLOT(volumeChanged(int))); - m_pan = new SliderGroup("Pan", 0 , 255, NULL); + connect(m_volume, SIGNAL(valueChanged(float)), this, SLOT(volumeChanged(float))); + m_pan = new SliderGroup("Pan", 0 , 255, 0, NULL); volumeBox->addWidget(m_pan); - connect(m_pan, SIGNAL(valueChanged(int)), this, SLOT(panChanged(int))); - m_pitch = new SliderGroup("Pitch", 0 , 255, NULL); + connect(m_pan, SIGNAL(valueChanged(float)), this, SLOT(panChanged(float))); + m_pitch = new SliderGroup("Pitch", 0 , 255, 0, NULL); volumeBox->addWidget(m_pitch); - connect(m_pitch, SIGNAL(valueChanged(int)), this, SLOT(pitchChanged(int))); + connect(m_pitch, SIGNAL(valueChanged(float)), this, SLOT(pitchChanged(float))); layout->addLayout(volumeBox); m_suspendResumeButton = new QPushButton(this); - m_suspendResumeButton->setText(tr(SUSPEND_LABEL)); + m_suspendResumeButton->setText(StatusStr[Status::Stopped]); connect(m_suspendResumeButton, SIGNAL(clicked()), SLOT(toggleSuspendResume())); layout->addWidget(m_suspendResumeButton); @@ -74,17 +68,17 @@ AudioLayerWidget::~AudioLayerWidget() } // From UI. -void AudioLayerWidget::volumeChanged(int value) +void AudioLayerWidget::volumeChanged(float value) { emit(uiSliderChanged(m_layer, Slider::Volume, value)); } -void AudioLayerWidget::panChanged(int value) +void AudioLayerWidget::panChanged(float value) { emit(uiSliderChanged(m_layer, Slider::Pan, value)); } -void AudioLayerWidget::pitchChanged(int value) +void AudioLayerWidget::pitchChanged(float value) { emit(uiSliderChanged(m_layer, Slider::Pitch, value)); } @@ -106,21 +100,21 @@ void AudioLayerWidget::toggleSuspendResume() } // from DMX signals -void AudioLayerWidget::setVol(qreal vol) +void AudioLayerWidget::setVol(float vol) { m_volume->blockSignals(true); m_volume->setValue(vol); m_volume->blockSignals(false); } -void AudioLayerWidget::setPan(qreal pan) +void AudioLayerWidget::setPan(int pan) { m_pan->blockSignals(true); m_pan->setValue(pan); m_pan->blockSignals(false); } -void AudioLayerWidget::setPitch(qreal pitch) +void AudioLayerWidget::setPitch(int pitch) { m_pitch->blockSignals(true); m_pitch->setValue(pitch); @@ -144,33 +138,25 @@ void AudioLayerWidget::setPlaybackStatus(Status status) m_progressTime->setTime(QTime::fromMSecsSinceStartOfDay(0)); m_statusValue->blockSignals(true); m_suspendResumeButton->blockSignals(true); + m_statusValue->setText(StatusStr[status]); + m_suspendResumeButton->setText(StatusStr[status]); switch (m_status) { case Status::Paused: - m_statusValue->setText("Pause"); m_statusValue->setStyleSheet("QLabel { color : red; }"); - m_suspendResumeButton->setText("Pause"); break; case Status::PlayingLoop: - m_statusValue->setText("Play Loop"); - m_statusValue->setStyleSheet("QLabel { color : green; }"); - m_suspendResumeButton->setText("Play Loop"); - break; case Status::PlayingOnce: - m_statusValue->setText("Play One"); m_statusValue->setStyleSheet("QLabel { color : green; }"); - m_suspendResumeButton->setText("Play One"); break; case Status::Stopped: - m_statusValue->setText("Stop"); m_statusValue->setStyleSheet("QLabel { color : red; }"); - m_suspendResumeButton->setText("Stop"); break; } m_statusValue->blockSignals(false); m_suspendResumeButton->blockSignals(false); } -void AudioLayerWidget::durationChanged(qint64 dur) +void AudioLayerWidget::durationChanged(float dur) { dur *= 1000; m_progressSlider->setMaximum(dur); diff --git a/src/audiolayerwidget.h b/src/audiolayerwidget.h index a484227..13f829f 100644 --- a/src/audiolayerwidget.h +++ b/src/audiolayerwidget.h @@ -26,10 +26,10 @@ class AudioLayerWidget : public QGroupBox public: explicit AudioLayerWidget(QWidget *parent = 0, QString name = "Layer", int layer = 0); ~AudioLayerWidget(); - void setVol(qreal vol); + void setVol(float vol); void resume(); - void setPan(qreal pan); - void setPitch(qreal pitch); + void setPan(int pan); + void setPitch(int pitch); void setLoop(bool on); void setPlaybackStatus(Status status); inline Status getPlaybackStatus() { return m_status; } @@ -38,29 +38,23 @@ private: Status m_status; int m_layer; QPushButton *m_suspendResumeButton; - QLabel *m_statusLabel; QLabel * m_statusValue; - QLabel *m_fileLabel; QLabel *m_fileValue; - QLabel * m_folderLabel; QLabel * m_folderValue; SliderGroup *m_volume; SliderGroup *m_pan; SliderGroup *m_pitch; - QLabel * m_progressLabel; QSlider *m_progressSlider; - QLabel *m_progressTimeLabel; QTimeEdit *m_progressTime; - QLabel *m_totalTimeLabel; QTimeEdit *m_totalTimeValue; public slots: void toggleSuspendResume(); - void volumeChanged(int vol); - void panChanged(int vol); - void pitchChanged(int vol); + void volumeChanged(float vol); + void panChanged(float pan); + void pitchChanged(float pitch); void fileLoaded(QString file); - void durationChanged(qint64 dur); + void durationChanged(float dur); void refreshUi(float progress); signals: diff --git a/src/audiowidget.cpp b/src/audiowidget.cpp index 63ca562..4b35a5c 100644 --- a/src/audiowidget.cpp +++ b/src/audiowidget.cpp @@ -56,19 +56,19 @@ void AudioWidget::mediaLoaded(int layer, QString file) dynamic_cast(item->widget())->durationChanged(pLength); } -void AudioWidget::volChanged(int layer, qreal vol) { +void AudioWidget::volChanged(int layer, float vol) { m_mae.volChanged(layer, vol); QLayoutItem * const item = m_layout->itemAt(layer); dynamic_cast(item->widget())->setVol(vol); } -void AudioWidget::panChanged(int layer, qreal pan) { +void AudioWidget::panChanged(int layer, int pan) { m_mae.panChanged(layer, pan); QLayoutItem * const item = m_layout->itemAt(layer); dynamic_cast(item->widget())->setPan(pan); } -void AudioWidget::pitchChanged(int layer, qreal pitch) { +void AudioWidget::pitchChanged(int layer, int pitch) { m_mae.pitchChanged(layer, pitch); QLayoutItem * const item = m_layout->itemAt(layer); dynamic_cast(item->widget())->setPitch(pitch); diff --git a/src/audiowidget.h b/src/audiowidget.h index cee8dd1..61c640c 100644 --- a/src/audiowidget.h +++ b/src/audiowidget.h @@ -27,9 +27,9 @@ public: protected: void mediaLoaded(int layer, QString media ); - void volChanged(int layer, qreal vol); - void panChanged(int layer, qreal pan); - void pitchChanged(int layer, qreal pitch); + void volChanged(int layer, float vol); + void panChanged(int layer, int pan); + void pitchChanged(int layer, int pitch); void playbackChanged(int layer, Status status); void entryPointChanged(int layer, int cursor); diff --git a/src/defines.h b/src/defines.h index 341bd0e..780c461 100644 --- a/src/defines.h +++ b/src/defines.h @@ -9,23 +9,8 @@ #define COPYRIGHT "(C) 2014-2024 Santi Norena lms@criptomart.net" #define LICENSE "GPL 3 License. See LICENSE.txt and credits.txt for details" #define DEFAULT_FILE "lms-audio.xlm" -#define SUSPEND_LABEL "Pause" -#define RESUME_LABEL "Resume" -#define PLAY_LABEL "Play" -#define STOP_LABEL "Stop" -#define PAUSE_LABEL "Pause" -#define IDDLE_LABEL "Iddle playback" -#define VOLUME_LABEL "Vol" -#define PROGRESS_LABEL "Progress" -#define PROGRESS_TIME_LABEL "Current" -#define REMAINING_TIME "Remaining" -#define TOTAL_TIME_LABEL "Total" -#define NOTIFY_INTERVAL 150 -#define PULL_TIMER_INTERVAL 10 -#define MAX_DEVICES 16 -#define MAX_SOUNDS 4096 #define MAX_LAYERS 16 -#define UI_REFRESH_TIME 100 +#define UI_REFRESH_TIME 200 // struct where save the DMX settings for each layer struct dmxSetting { @@ -58,6 +43,15 @@ enum Status PlayingLoop, }; +static const char* StatusStr[] = +{ + "Stop", + "Pause", + "Playing One", + "Playing Loop", + NULL +}; + enum Slider { Volume, diff --git a/src/libremediaserver-audio.cpp b/src/libremediaserver-audio.cpp index 6f6e263..f20d038 100644 --- a/src/libremediaserver-audio.cpp +++ b/src/libremediaserver-audio.cpp @@ -48,12 +48,12 @@ libreMediaServerAudio::libreMediaServerAudio(QStringList args, QWidget *parent) connect(set, SIGNAL(registerUniverse(int)), ola, SLOT(registerUniverse(int))); connect(ola, SIGNAL (universeReceived(int)), m_dmxWidget, SLOT(updateWatchDMX(int))); connect(ola, SIGNAL(dmxOutput(int, int, int)), this, SLOT(dmxInput(int, int, int))); - connect(ui.actionLaunch_OLA_Setup, SIGNAL(triggered()), this, SLOT(olasetup())); ola->registerUniverse(); ola->start(QThread::TimeCriticalPriority ); connect(ui.actionOpen_conf, SIGNAL(triggered()), this, SLOT(openFile())); connect(ui.actionSave_conf, SIGNAL(triggered()), this, SLOT(saveFile())); connect(ui.action_Settings, SIGNAL(triggered()), this, SLOT(settings())); + connect(ui.actionLaunch_OLA_Setup, SIGNAL(triggered()), this, SLOT(olasetup())); aw->startEngine(); qDebug("Init Complete."); ola->blockSignals(false); @@ -107,8 +107,6 @@ void libreMediaServerAudio::dmxInput(int layer, int channel, int value) return; QString mediaFile = NULL; int aux; - qreal f; - int r; switch(channel){ case DMX_FOLDER: aux = ola->getValue(layer, DMX_FILE); @@ -123,12 +121,8 @@ void libreMediaServerAudio::dmxInput(int layer, int channel, int value) aw->mediaLoaded(layer, mediaFile); break; case VOLUME_COARSE: - f = ( value * 0x100 ) + ola->getValue(layer, VOLUME_FINE); - aw->volChanged(layer, (f / 655.35)); - break; case VOLUME_FINE: - f = ( ola->getValue(layer, VOLUME_COARSE) * 0x100 ) + value; - aw->volChanged(layer, (f / 655.35)); + aw->volChanged(layer, (value / 65025.0f)); break; case PAN: aw->panChanged(layer, value); @@ -137,12 +131,8 @@ void libreMediaServerAudio::dmxInput(int layer, int channel, int value) aw->pitchChanged(layer, value); break; case ENTRY_POINT_COARSE: - r = ( value * 0x100 ) + ola->getValue(layer, ENTRY_POINT_FINE); - aw->entryPointChanged(layer, r); - break; case ENTRY_POINT_FINE: - r = ( ola->getValue(layer, ENTRY_POINT_COARSE) * 0x100 ) + value; - aw->entryPointChanged(layer, r); + aw->entryPointChanged(layer, value); break; case PLAYBACK: if (value == 0) diff --git a/src/main.cpp b/src/main.cpp index 25d84e0..bfadafe 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -20,133 +20,11 @@ #include "libremediaserver-audio.h" -// Handler for pipe the stderr to a log file and texEdit -//bool initMessageHandler = false; -//QFile outFile; -//QMutex mutex; -//QMutexLocker mutexLocker(mutex); -/* -void MessageHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg) -{ - Q_UNUSED(context); -// mutex.lock(); - // Create the log dir and log file - if (!initMessageHandler) { - QDir dir; - if (!dir.exists("log")) { - if (!dir.mkdir("log")) { - qDebug()<<"MessageHandler: Can not create log folder"; - return; - } - } - QString filename; - QDate date = QDate::currentDate(); - QTime time = QTime::currentTime(); - filename.append("./log/log_"); - filename.append(date.toString("ddMMyy-")); - filename.append(time.toString("hhmmss.txt")); - outFile.setFileName(filename); - if (!outFile.open(QIODevice::WriteOnly | QIODevice::Append)) { - qWarning("main/MessageHandler/Qfile::open: can not open log file"); - return; - } - initMessageHandler = true; - } - QTextStream ts(&outFile);*/ -/* if (libreMediaServerAudio::textEdit == 0) - { - QByteArray localMsg = msg.toLocal8Bit(); - switch (type) { - case QtDebugMsg: - fprintf(stderr, "Debug: %s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line, context.function); - break; - case QtWarningMsg: - fprintf(stderr, "Warning: %s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line, context.function); - break; - case QtCriticalMsg: - fprintf(stderr, "Critical: %s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line, context.function); - break; - case QtFatalMsg: - fprintf(stderr, "Fatal: %s (%s:%u, %s)\n", localMsg.constData(), context.file, context.line, context.function); - abort(); - } - } - else - { - QString txt; - switch (type) { - case QtDebugMsg: - txt.append("Debug from File: "); - txt.append(context.file); - txt.append(" Line: "); - txt.append(QString::number(context.line)); -// txt.append(" Function: "); -// txt.append(context.function); - txt.append(" Message: "); - txt.append(msg); -// libreMediaServerAudio::textEdit->append(msg);, context.file, context.line, context.function); - libreMediaServerAudio::textEdit->append(txt); - break; - case QtWarningMsg: - txt.append("Warning from File: "); - txt.append(context.file); - txt.append(" Line: "); - txt.append(QString::number(context.line)); - txt.append(" Function: "); - txt.append(context.function); - txt.append(" Message: "); - txt.append(msg); -// libreMediaServerAudio::textEdit->append(msg);, context.file, context.line, context.function); - libreMediaServerAudio::textEdit->append(txt); - abort(); - break; - case QtCriticalMsg: -// txt.append("Critical from File: "); - txt.append(context.file); - txt.append(" Line: "); - txt.append(QString::number(context.line)); - txt.append(" Function: "); - txt.append(context.function); - txt.append(" Message "); - txt.append(msg); -// libreMediaServerAudio::textEdit->append(msg);, context.file, context.line, context.function); - libreMediaServerAudio::textEdit->append(txt); - abort(); - break; - case QtFatalMsg: -// txt.append("Fatal from File: "); - txt.append(context.file); - txt.append(" Line: "); - txt.append(QString::number(context.line)); - txt.append(" Function: "); - txt.append(context.function); - txt.append(" Message: "); - txt.append(msg); -// libreMediaServerAudio::textEdit->append(msg);, context.file, context.line, context.function); - libreMediaServerAudio::textEdit->append(txt);// ts << txt << endl; - abort(); - } -// outFile.write(txt.toLatin1().constData(), txt.size()); -// ts << txt << endl; -// libreMediaServerAudio::textEdit->append(txt); - } -// mutex.unlock(); -}*/ int main(int argc, char *argv[]) { - - // ToDo: discriminar niveles de log y log a fichero segúna argumentos - /* - if (args.contains("-log")) - { - qInstallMessageHandler(MessageHandler); - }*/ - QApplication app(argc, argv); - QStringList args = app.arguments(); - if (args.size() > 1) { if (args.contains("-v")) @@ -163,7 +41,6 @@ int main(int argc, char *argv[]) qDebug() << LICENSE; qDebug() << "Help for command line options:"; qDebug() << "-v show the version and exits"; - qDebug() << "-log write the debug information to a log file instead stderr"; qDebug() << "-h this help"; return 0; } @@ -172,5 +49,3 @@ int main(int argc, char *argv[]) libreMediaServerAudio.show(); return app.exec(); } - - diff --git a/src/miniaudioengine.cpp b/src/miniaudioengine.cpp index 6fb6709..5e11919 100644 --- a/src/miniaudioengine.cpp +++ b/src/miniaudioengine.cpp @@ -183,15 +183,16 @@ ma_result MiniAudioEngine::printFormatInfo(int layer) return result; } -// Expects between 0 and 100 vol value in db +// Expects between 0 and 1 vol value in db void MiniAudioEngine::volChanged(int layer, float vol) { - float result; + //float result; if (m_mediaLoaded[layer] == false) return; - result = ma_volume_linear_to_db(1.00000000 + (vol / 800.0)); - ma_sound_group_set_volume(&m_currentSound[layer], result); + //result = ma_volume_linear_to_db(1.00000000 + (vol / 8.0)); + //qInfo("vol %f %f", vol, result); + ma_sound_group_set_volume(&m_currentSound[layer], vol); } void MiniAudioEngine::panChanged(int layer, float value) diff --git a/src/miniaudioengine.h b/src/miniaudioengine.h index c38c793..d9dc13a 100644 --- a/src/miniaudioengine.h +++ b/src/miniaudioengine.h @@ -3,7 +3,6 @@ #define MINIAUDIO_IMPLEMENTATION #include "miniaudio.h" - #include "defines.h" //MAX_LAYERS #include // for printf @@ -18,7 +17,6 @@ public: static void audioDataCallback(ma_device* pDevice, void* pOutput, const void* pInput, ma_uint32 frameCount); protected: - // slots for DMX input ma_result loadMedia(int layer, char *media ); void volChanged(int layer, float vol); void panChanged(int layer, float pan); diff --git a/src/olathread.cpp b/src/olathread.cpp index fdfe041..70002f1 100644 --- a/src/olathread.cpp +++ b/src/olathread.cpp @@ -38,6 +38,7 @@ void olaThread::init() m_client->SetDMXCallback(ola::NewCallback(this, &olaThread::NewDmx)); m_clientWrapper->GetSelectServer()->RegisterRepeatingTimeout(4000, ola::NewCallback(this, &olaThread::CheckDataLoss)); m_client->SetCloseHandler(ola::NewSingleCallback(this, &olaThread::socketClosed)); + m_dmxSettings = Settings::getInstance()->getDmxSettings(); } void olaThread::run() @@ -62,19 +63,50 @@ void olaThread::stop() void olaThread::NewDmx(const ola::client::DMXMetadata &data, const ola::DmxBuffer &buffer) { - m_counter++; - gettimeofday(&m_last_data, NULL); - foreach (const dmxSetting &i, Settings::getInstance()->getDmxSettings()) { + bool volSent = false; + bool entrySent = false; + + foreach (const dmxSetting &i, m_dmxSettings) { if(i.universe == data.universe && i.address > -1) { for (int j = 0; j < LAYER_CHANNELS; j++){ int value = buffer.Get((i.address) + j); if (m_dmx[i.layer][j] != value) { m_dmx[i.layer][j] = value; - emit dmxOutput(i.layer,j,value); + switch (j) { + case 0: + value = (value * 0x100) + buffer.Get(i.address + 6); + emit dmxOutput(i.layer,j,value); + volSent = true; + break; + case 7: + value = (value * 0x100) + buffer.Get(i.address + 8); + emit dmxOutput(i.layer,j,value); + entrySent = true; + break; + case 6: + if (volSent == false) + { + value = (buffer.Get(i.address) * 0x100) + value; + emit dmxOutput(i.layer,j,value); + } + break; + case 8: + if (entrySent == false) + { + value = (buffer.Get(i.address + 7) * 0x100) + value; + emit dmxOutput(i.layer,j,value); + } + break; + default: + emit dmxOutput(i.layer,j,value); + break; + } } } } } + m_counter++; + gettimeofday(&m_last_data, NULL); emit universeReceived(data.universe); } diff --git a/src/olathread.h b/src/olathread.h index ee18824..5ad75c8 100644 --- a/src/olathread.h +++ b/src/olathread.h @@ -47,6 +47,7 @@ private: struct timeval m_last_data; // Last DMX frame received int m_layers; int m_dmx[MAX_LAYERS][LAYER_CHANNELS]; + QList m_dmxSettings; /** * @brief Callback from ola. Control de errores en el registro de Universos en OLA diff --git a/src/slidergroup.cpp b/src/slidergroup.cpp index 9b7e234..e80a03f 100644 --- a/src/slidergroup.cpp +++ b/src/slidergroup.cpp @@ -3,6 +3,7 @@ SliderGroup::SliderGroup(const QString &title, \ int min, int max, + int decimals, QWidget *parent) : QGroupBox(title, parent) { @@ -14,17 +15,31 @@ SliderGroup::SliderGroup(const QString &title, \ slider->setTickInterval((max - min) / 11); slider->setSingleStep(1); slider->setRange(min, max); - //slider->setInvertedAppearance(false); - //slider->setInvertedControls(false); - valueBox = new QSpinBox(); + valueBox = new QDoubleSpinBox(); valueBox->setFocusPolicy(Qt::NoFocus); valueBox->setButtonSymbols(QAbstractSpinBox::NoButtons); - valueBox->setMaximumWidth(40); + valueBox->setMaximumWidth(45); valueBox->setRange(min, max); - connect(slider, &QSlider::valueChanged, valueBox, &QSpinBox::setValue); + valueBox->setDecimals(decimals); connect(slider, SIGNAL(valueChanged(int)), this, SLOT(sliderValueChanged(int))); QVBoxLayout *slidersLayout = new QVBoxLayout(); slidersLayout->addWidget(valueBox); slidersLayout->addWidget(slider); setLayout(slidersLayout); } + +void SliderGroup::sliderValueChanged(int value) +{ + if (valueBox->decimals() > 1) + value /= 100.0f; + emit valueChanged(value); + valueBox->setValue(value); +}; + +void SliderGroup::setValue(float value) +{ + if (valueBox->decimals() > 1) + value *= 100.0f; + slider->setValue(value); + valueBox->setValue(value); +} diff --git a/src/slidergroup.h b/src/slidergroup.h index 9b7b704..d1d34bf 100644 --- a/src/slidergroup.h +++ b/src/slidergroup.h @@ -21,18 +21,19 @@ public: SliderGroup(const QString &title, int min, int max, + int decimals, QWidget *parent = nullptr); signals: - void valueChanged(int value); + void valueChanged(float value); public slots: - inline void setValue(int value) { slider->setValue(value); }; - inline void sliderValueChanged(int value) { emit valueChanged(value); }; + void setValue(float value); + void sliderValueChanged(int value); private: QSlider *slider; - QSpinBox *valueBox; + QDoubleSpinBox *valueBox; }; #endif