Antigona Release #1

Merged
snt merged 49 commits from filters into main 2024-05-26 12:42:53 +00:00
20 changed files with 271 additions and 160 deletions
Showing only changes of commit 7a9c0cd0ac - Show all commits

View file

@ -27,6 +27,8 @@ v 0.2.0 Antígona (24/04/2024)
+ Compilation without GUI (-DNOGUI). + Compilation without GUI (-DNOGUI).
+ New Status "Iddle" in playbacks if is not loaded. + New Status "Iddle" in playbacks if is not loaded.
+ New DMX personality version, better sort for audio needs (first load media, set vol, pan, etc, last playback order); + New DMX personality version, better sort for audio needs (first load media, set vol, pan, etc, last playback order);
+ Refresh layer values when it loads a new sound file.
+ No QtSignals for sending data, better performance about 20% in my machine. Now, libremediaserver only updates values in AudioWidget, ui refresh is doing with a timer in audiowidget, so there is not problems between graphical and ola thread (the callback).
v 0.1.3 Leúcade (19/04/2024) v 0.1.3 Leúcade (19/04/2024)

View file

@ -1,8 +1,8 @@
<?xml version='1.0' encoding='UTF-8'?> <?xml version='1.0' encoding='UTF-8'?>
<dmxSettings fileVersion="1" layersNumber="4" path="/home/snt/Documentos/lab/lms/media/sound"> <lmsAudio ui="1" layersNumber="4" path="../media/sound" >
<audioDevice id="3" /> <audioDevice devicesNumber="2" id0="3" id1="4" />
<layer0 dmx="1" universe="1" /> <layer id="0" dmx="1" universe="1" />
<layer1 dmx="17" universe="1" /> <layer id="1" dmx="17" universe="1" />
<layer2 dmx="33" universe="1" /> <layer id="2" dmx="33" universe="1" />
<layer3 dmx="49" universe="1" /> <layer id="3" dmx="49" universe="1" />
</dmxSettings> </lmsAudio>

View file

@ -45,9 +45,13 @@ v 0.2.1
- Ui/Ux: Dar la opción clickeando en el widget de tiempo de poner una cuenta atrás en vez de hacia delante. - Ui/Ux: Dar la opción clickeando en el widget de tiempo de poner una cuenta atrás en vez de hacia delante.
- Logs, verbosity, timestamp. - Logs, verbosity, timestamp.
- New play mode without pitch control, it saves resources. MA_SOUND_FLAG_NO_PITCH - New play mode without pitch control, it saves resources. MA_SOUND_FLAG_NO_PITCH
- Vumeter or indicator about audio output in layer and master. - Vumeter or indicator about audio output in layer and master, add to sliderGroup.
- QSlider can not accept floats and it can no manage high frequency updates.
- SettingsDialog. - SettingsDialog.
- Load/save conf file. - Load/save conf file.
- ¿Exit Point? is it needed? - ¿Exit Point? is it needed?
- Hardening: check return errors, catch execptions, i'm too happy.... - Hardening: check return errors, try/catch exceptions, i'm too happy....
- Tests: errors on wrong conf file. - Tests: errors on wrong conf file.
- BUGFIX: there are some small clicks when changing volume and play/stop/pause. vol 24 bits? microfades in engine? setVol 0 before changing playback state?
- refactorize dmxInput: loadMedia, changePlayBack,
- BUGFIX: in nogui mode we need more info print at terminal (load media, change playback status).

View file

@ -52,6 +52,7 @@ AudioLayerWidget::AudioLayerWidget(QWidget *parent, int layer):
m_progressTime->setReadOnly(true); m_progressTime->setReadOnly(true);
m_progressTime->setButtonSymbols(QAbstractSpinBox::NoButtons); m_progressTime->setButtonSymbols(QAbstractSpinBox::NoButtons);
m_progressTime->setMinimumWidth(80); m_progressTime->setMinimumWidth(80);
m_progressTime->setMaximumWidth(80);
m_progressTime->setFocusPolicy(Qt::NoFocus); m_progressTime->setFocusPolicy(Qt::NoFocus);
m_progressTime->setAlignment(Qt::AlignHCenter); m_progressTime->setAlignment(Qt::AlignHCenter);
m_progressTime->setContentsMargins(0,0,0,0); m_progressTime->setContentsMargins(0,0,0,0);
@ -138,7 +139,7 @@ void AudioLayerWidget::openMediaDialog()
QStringList fileNames; QStringList fileNames;
fileNames = dialog.selectedFiles(); fileNames = dialog.selectedFiles();
emit uiLoadMedia(m_layer, fileNames.at(0)); emit uiLoadMedia(m_layer, fileNames.at(0));
this->fileLoaded(fileNames.at(0)); this->setMediaFile(fileNames.at(0));
} }
// from DMX signals // from DMX signals
@ -163,7 +164,7 @@ void AudioLayerWidget::setPitch(int pitch)
m_pitch->blockSignals(false); m_pitch->blockSignals(false);
} }
void AudioLayerWidget::fileLoaded(QString file) void AudioLayerWidget::setMediaFile(QString file)
{ {
QStringList list = file.split("/"); QStringList list = file.split("/");
int size = list.size(); int size = list.size();
@ -174,19 +175,18 @@ void AudioLayerWidget::fileLoaded(QString file)
this->setPlaybackStatus(Status::Stopped); this->setPlaybackStatus(Status::Stopped);
} }
void AudioLayerWidget::setPlaybackStatus(Status status) void AudioLayerWidget::setPlaybackStatus(Status s)
{ {
if (!strcmp(StatusStr[status], m_suspendResumeButton->text().toLatin1().constData())) Status status = static_cast<Status>(s);
return;
m_suspendResumeButton->blockSignals(true); m_suspendResumeButton->blockSignals(true);
m_status = status; m_status = status;
if (status == Status::Stopped) //if (status == Status::Stopped)
refreshCurrentTime(0); // refreshCurrentTime(0);
m_suspendResumeButton->setText(StatusStr[status]); m_suspendResumeButton->setText(StatusStr[status]);
m_suspendResumeButton->blockSignals(false); m_suspendResumeButton->blockSignals(false);
} }
void AudioLayerWidget::durationChanged(float dur) void AudioLayerWidget::setDuration(float dur)
{ {
m_progress->blockSignals(true); m_progress->blockSignals(true);
m_progressTime->blockSignals(true); m_progressTime->blockSignals(true);
@ -200,7 +200,7 @@ void AudioLayerWidget::durationChanged(float dur)
m_totalTimeValue->blockSignals(false); m_totalTimeValue->blockSignals(false);
} }
void AudioLayerWidget::refreshCurrentTime(float progress) void AudioLayerWidget::setCurrentTime(float progress)
{ {
progress *= 1000; progress *= 1000;
m_progress->blockSignals(true); m_progress->blockSignals(true);

View file

@ -18,13 +18,6 @@ class AudioLayerWidget : public QWidget
public: public:
explicit AudioLayerWidget(QWidget *parent = 0, int layer = 0); explicit AudioLayerWidget(QWidget *parent = 0, int layer = 0);
~AudioLayerWidget(); ~AudioLayerWidget();
void setVol(float vol);
void resume();
void setPan(int pan);
void setPitch(int pitch);
void setLoop(bool on);
void setPlaybackStatus(Status status);
inline Status getPlaybackStatus() { return m_status; }
private: private:
Status m_status; Status m_status;
@ -39,17 +32,23 @@ private:
QTimeEdit *m_totalTimeValue; QTimeEdit *m_totalTimeValue;
QProgressBar *m_progress; QProgressBar *m_progress;
// From DMX
public slots: public slots:
void setMediaFile(QString file);
void setDuration(float dur);
void setCurrentTime(float progress);
void setPlaybackStatus(Status status);
void setVol(float vol);
void setPan(int pan);
void setPitch(int pitch);
// From Ui
private slots:
void openMediaDialog();
void toggleSuspendResume(); void toggleSuspendResume();
void volumeChanged(int vol); void volumeChanged(int vol);
void panChanged(int pan); void panChanged(int pan);
void pitchChanged(int pitch); void pitchChanged(int pitch);
void fileLoaded(QString file);
void durationChanged(float dur);
void refreshCurrentTime(float progress);
private slots:
void openMediaDialog();
signals: signals:
void uiPlaybackChanged(int layer, Status s); void uiPlaybackChanged(int layer, Status s);

View file

@ -1,5 +1,5 @@
#include "audiowidget.h" #include "audiowidget.h"
#include <cmath>
AudioWidget::AudioWidget(QWidget *parent) : AudioWidget::AudioWidget(QWidget *parent) :
QWidget(parent) QWidget(parent)
@ -15,39 +15,79 @@ AudioWidget::AudioWidget(QWidget *parent) :
m_layout->setSpacing(0); m_layout->setSpacing(0);
m_layout->setContentsMargins(1, 1, 1, 1); m_layout->setContentsMargins(1, 1, 1, 1);
setLayout(m_layout); setLayout(m_layout);
m_refreshUi = new QTimer(this);
connect(m_refreshUi, SIGNAL(timeout()), this, SLOT(refreshUi()));
m_refreshUi->start(UI_REFRESH_TIME * 2);
} }
void AudioWidget::mediaLoaded(int layer, QString file, float duration) void AudioWidget::mediaLoaded(int layer, QString file, float duration)
{ {
QLayoutItem * const item = m_layout->itemAt(layer); m_layerUpdate[layer].media = file;
dynamic_cast<AudioLayerWidget *>(item->widget())->fileLoaded(file); m_layerUpdate[layer].duration = duration;
dynamic_cast<AudioLayerWidget *>(item->widget())->durationChanged(duration); m_layerUpdate[layer].updated = true;
} }
void AudioWidget::volChanged(int layer, float vol) { void AudioWidget::volChanged(int layer, float vol) {
QLayoutItem * const item = m_layout->itemAt(layer); m_layerUpdate[layer].vol = vol;
dynamic_cast<AudioLayerWidget *>(item->widget())->setVol(vol); m_layerUpdate[layer].updated = true;
} }
void AudioWidget::panChanged(int layer, int pan) { void AudioWidget::panChanged(int layer, int pan) {
QLayoutItem * const item = m_layout->itemAt(layer); m_layerUpdate[layer].pan = pan;
dynamic_cast<AudioLayerWidget *>(item->widget())->setPan(pan); m_layerUpdate[layer].updated = true;
} }
void AudioWidget::pitchChanged(int layer, int pitch) { void AudioWidget::pitchChanged(int layer, int pitch) {
QLayoutItem * const item = m_layout->itemAt(layer);
dynamic_cast<AudioLayerWidget *>(item->widget())->setPitch(pitch); m_layerUpdate[layer].pitch = pitch;
m_layerUpdate[layer].updated = true;
} }
void AudioWidget::playbackChanged(int layer, Status status) void AudioWidget::playbackChanged(int layer, Status status)
{ {
QLayoutItem * const item = m_layout->itemAt(layer); m_layerUpdate[layer].status = status;
dynamic_cast<AudioLayerWidget *>(item->widget())->setPlaybackStatus(status); m_layerUpdate[layer].updated = true;
} }
void AudioWidget::cursorChanged(int layer, float cursor) void AudioWidget::cursorChanged(int layer, float cursor)
{ {
QLayoutItem * const item = m_layout->itemAt(layer); m_layerUpdate[layer].cursor = floor(cursor * 1000) / 1000;
AudioLayerWidget *alw = dynamic_cast<AudioLayerWidget *>(item->widget()); m_layerUpdate[layer].updated = true;
alw->refreshCurrentTime(cursor); }
void AudioWidget::refreshUi()
{
for (int i = 0; i < MAX_LAYERS; i++)
{
if (m_layerUpdate[i].updated) {
QLayoutItem * const item = m_layout->itemAt(i);
AudioLayerWidget *alw = dynamic_cast<AudioLayerWidget *>(item->widget());
if (m_layerUpdate[i].vol > -1) {
alw->setVol(m_layerUpdate[i].vol);
m_layerUpdate[i].vol = -1;
}
if (m_layerUpdate[i].cursor > -1) {
alw->setCurrentTime(m_layerUpdate[i].cursor);
m_layerUpdate[i].cursor = -1;
}
if (m_layerUpdate[i].pan > -1) {
alw->setPan(m_layerUpdate[i].pan);
m_layerUpdate[i].pan = -1;
}
if (m_layerUpdate[i].pitch > -1) {
alw->setPitch(m_layerUpdate[i].pitch);
m_layerUpdate[i].pitch = -1;
}
if (m_layerUpdate[i].status != Status::Iddle) {
alw->setPlaybackStatus(m_layerUpdate[i].status);
m_layerUpdate[i].status = Status::Iddle;
}
if (m_layerUpdate[i].duration > -1) {
alw->setMediaFile(m_layerUpdate[i].media);
alw->setDuration(m_layerUpdate[i].duration);
m_layerUpdate[i].duration = -1;
}
m_layerUpdate[i].updated = false;
}
}
} }

View file

@ -5,7 +5,6 @@
#include "audiolayerwidget.h" #include "audiolayerwidget.h"
#include "settings.h" #include "settings.h"
#include "miniaudioengine.h"
#include "defines.h" // MAX_LAYERS #include "defines.h" // MAX_LAYERS
class AudioWidget : public QWidget class AudioWidget : public QWidget
@ -14,14 +13,22 @@ class AudioWidget : public QWidget
public: public:
AudioWidget(QWidget *parent = nullptr); AudioWidget(QWidget *parent = nullptr);
void mediaLoaded(int layer, QString media, float duration);
private:
QHBoxLayout *m_layout;
layerData m_layerUpdate[MAX_LAYERS];
QTimer *m_refreshUi;
public slots:
void volChanged(int layer, float vol); void volChanged(int layer, float vol);
void panChanged(int layer, int pan); void panChanged(int layer, int pan);
void pitchChanged(int layer, int pitch); void pitchChanged(int layer, int pitch);
void playbackChanged(int layer, Status status);
void cursorChanged(int layer, float cursor); void cursorChanged(int layer, float cursor);
QHBoxLayout *m_layout; void mediaLoaded(int layer, QString media, float duration);
void playbackChanged(int layer, Status status);
private slots:
void refreshUi();
signals: signals:
void uiPlaybackChanged(int layer, Status s); void uiPlaybackChanged(int layer, Status s);
void uiSliderChanged(int layer, Slider s, int vol); void uiSliderChanged(int layer, Slider s, int vol);

View file

@ -6,9 +6,10 @@
#define LICENSE "GPL 3 Licensed. See LICENSE.txt." #define LICENSE "GPL 3 Licensed. See LICENSE.txt."
#define DEFAULT_FILE "lms-audio.xlm" #define DEFAULT_FILE "lms-audio.xlm"
#define MAX_LAYERS 4 #define MAX_LAYERS 4
#define UI_REFRESH_TIME 93 #define MAX_AUDIODEVICES 8
#define UI_REFRESH_TIME 77
#define FADE_TIME 25 // DMX Frame time, 40 fps, avoid clicks
// struct where save the DMX settings for each layer
struct dmxSetting { struct dmxSetting {
int address; int address;
unsigned int universe; unsigned int universe;
@ -41,5 +42,15 @@ enum Slider
Pitch, Pitch,
}; };
#include <QString>
struct layerData {
QString media;
Status status;
bool updated;
float vol;
float cursor;
int pan;
int pitch;
float duration;
};
#endif // DEFINES_H #endif // DEFINES_H

View file

@ -10,7 +10,6 @@
#define ENTRY_POINT_COARSE 5 #define ENTRY_POINT_COARSE 5
#define ENTRY_POINT_FINE 4 #define ENTRY_POINT_FINE 4
#define PITCH 7 #define PITCH 7
#define LAYER_CHANNELS 9 #define LAYER_CHANNELS 9
#endif // DMXPERSONALITY_H #endif // DMXPERSONALITY_H

View file

@ -38,7 +38,7 @@ libreMediaServerAudioUi::libreMediaServerAudioUi(QWidget *parent)
this->setContentsMargins(5, 5, 5, 5); this->setContentsMargins(5, 5, 5, 5);
this->setStyleSheet( this->setStyleSheet(
"color: white;" "color: white;"
"background-color: gray;" "background-color: #4f4048;"
"selection-color: blue;" "selection-color: blue;"
"selection-background-color: green" "selection-background-color: green"
); );

View file

@ -21,11 +21,11 @@
#include "libremediaserver-audio.h" #include "libremediaserver-audio.h"
libreMediaServerAudio::libreMediaServerAudio(bool gui) libreMediaServerAudio::libreMediaServerAudio()
{ {
m_ui = gui; m_settings = Settings::getInstance();
Settings *set = Settings::getInstance(); m_settings->readFile();
set->readFile(); m_ui = m_settings->getShowUi();
m_mediaLibrary = new MediaLibrary; m_mediaLibrary = new MediaLibrary;
m_mediaLibrary->initMediaLibrary(); m_mediaLibrary->initMediaLibrary();
for (int i = 0; i < MAX_LAYERS; i++) { for (int i = 0; i < MAX_LAYERS; i++) {
@ -38,12 +38,11 @@ libreMediaServerAudio::libreMediaServerAudio(bool gui)
m_updateUi[i][3] = -1; m_updateUi[i][3] = -1;
#endif #endif
} }
m_ola = new olaThread(this, set->getLayersNumber()); m_ola = new olaThread(this, m_settings->getLayersNumber());
Q_CHECK_PTR(m_ola); Q_CHECK_PTR(m_ola);
m_ola->blockSignals(true); m_ola->blockSignals(true);
connect(m_ola, SIGNAL(dmxOutput(int, int, int)), this, SLOT(dmxInput(int, int, int)));
m_ola->registerUniverse(); m_ola->registerUniverse();
m_mae.startEngine(set->getAudioDeviceId()); m_mae.startEngine(m_settings->getAudioDeviceId());
qDebug("Core init Complete. Start reading DMX."); qDebug("Core init Complete. Start reading DMX.");
m_ola->blockSignals(false); m_ola->blockSignals(false);
#ifdef NOGUI #ifdef NOGUI
@ -57,27 +56,29 @@ libreMediaServerAudio::~libreMediaServerAudio()
m_mae.stopEngine(); m_mae.stopEngine();
} }
void libreMediaServerAudio::loadMedia(int layer, int folder, int file)
{
QString mediaFile = m_mediaLibrary->requestNewFile(folder, file);
if (strcmp(mediaFile.toLatin1().constData(), m_currentMedia[layer].toLatin1().constData()) == 0)
return;
if (QFile::exists(mediaFile)){
m_mae.loadMedia(layer, mediaFile.toLatin1().data());
m_currentMedia[layer] = mediaFile;
#ifndef NOGUI
if (m_ui)
m_lmsUi->m_aw->mediaLoaded(layer, mediaFile, m_mae.getDuration(layer));
#endif
m_mae.printFormatInfo(layer);
}
}
void libreMediaServerAudio::dmxInput(int layer, int channel, int value) void libreMediaServerAudio::dmxInput(int layer, int channel, int value)
{ {
if (layer >= MAX_LAYERS || channel >= LAYER_CHANNELS) if (layer >= MAX_LAYERS || channel >= LAYER_CHANNELS)
return; return;
QString mediaFile = NULL; QString mediaFile = NULL;
int aux; int aux;
if (channel == DMX_FOLDER || channel == DMX_FILE){ if (channel == VOLUME_COARSE || channel == VOLUME_FINE) {
int folder = (value >> 8) & 0x000000FF;
int file = value & 0x000000FF;
mediaFile = m_mediaLibrary->requestNewFile(folder, file);
if (strcmp(mediaFile.toLatin1().constData(), m_currentMedia[layer].toLatin1().constData()) == 0)
return;
if (QFile::exists(mediaFile)){
m_mae.loadMedia(layer, mediaFile.toLatin1().data());
m_currentMedia[layer] = mediaFile;
#ifndef NOGUI
if (m_ui)
m_lmsUi->m_aw->mediaLoaded(layer, mediaFile, m_mae.getDuration(layer));
#endif
}
} else if (channel == VOLUME_COARSE || channel == VOLUME_FINE) {
float tmp = value / 65025.0f; float tmp = value / 65025.0f;
m_mae.volChanged(layer, tmp); m_mae.volChanged(layer, tmp);
m_updateUi[layer][0] = tmp * 100.0f; m_updateUi[layer][0] = tmp * 100.0f;
@ -104,15 +105,17 @@ void libreMediaServerAudio::dmxInput(int layer, int channel, int value)
m_mae.playbackChanged(layer, s); m_mae.playbackChanged(layer, s);
m_currentStatus[layer] = s; m_currentStatus[layer] = s;
#ifndef NOGUI #ifndef NOGUI
if (m_ui) m_lmsUi->m_aw->playbackChanged(layer, s); if (m_ui) {
m_lmsUi->m_aw->playbackChanged(layer, s);
m_lmsUi->m_aw->cursorChanged(layer, m_mae.getCursor(layer));
}
#endif #endif
} }
} }
#ifndef NOGUI #ifndef NOGUI
void libreMediaServerAudio::refreshUi() { void libreMediaServerAudio::refreshUi() {
if (!m_ui) return; if (!m_ui) return;
for (int i= 0; i < Settings::getInstance()->getLayersNumber(); i++ ) { for (int i= 0; i < m_settings->getLayersNumber(); i++ ) {
if (m_updateUi[i][0] >= 0) { if (m_updateUi[i][0] >= 0) {
m_lmsUi->m_aw->volChanged(i, m_updateUi[i][0]); m_lmsUi->m_aw->volChanged(i, m_updateUi[i][0]);
m_updateUi[i][0] = -1; m_updateUi[i][0] = -1;
@ -125,7 +128,9 @@ void libreMediaServerAudio::refreshUi() {
m_lmsUi->m_aw->pitchChanged(i, m_updateUi[i][2]); m_lmsUi->m_aw->pitchChanged(i, m_updateUi[i][2]);
m_updateUi[i][2] = -1; m_updateUi[i][2] = -1;
} }
if (m_updateUi[i][3] >= 0) { if (m_updateUi[i][3] >= 0 \
|| m_currentStatus[i] == Status::PlayingOnce\
|| m_currentStatus[i] == Status::PlayingLoop) {
m_lmsUi->m_aw->cursorChanged(i, m_mae.getCursor(i)); m_lmsUi->m_aw->cursorChanged(i, m_mae.getCursor(i));
m_updateUi[i][3] = -1; m_updateUi[i][3] = -1;
} }
@ -135,6 +140,7 @@ void libreMediaServerAudio::refreshUi() {
void libreMediaServerAudio::setUi(libreMediaServerAudioUi *lmsUi) void libreMediaServerAudio::setUi(libreMediaServerAudioUi *lmsUi)
{ {
m_lmsUi = lmsUi; m_lmsUi = lmsUi;
m_ui = true;
connect(m_ola, SIGNAL(universeReceived(int)), m_lmsUi->m_dmxWidget, SLOT(updateWatchDMX(int))); connect(m_ola, SIGNAL(universeReceived(int)), m_lmsUi->m_dmxWidget, SLOT(updateWatchDMX(int)));
connect(m_lmsUi->m_aw, SIGNAL(uiSliderChanged(int, Slider, int)), this, SLOT(uiSliderChanged(int, Slider, int))); connect(m_lmsUi->m_aw, SIGNAL(uiSliderChanged(int, Slider, int)), this, SLOT(uiSliderChanged(int, Slider, int)));
connect(m_lmsUi->m_aw, SIGNAL(uiPlaybackChanged(int, Status)), this, SLOT(uiPlaybackChanged(int, Status))); connect(m_lmsUi->m_aw, SIGNAL(uiPlaybackChanged(int, Status)), this, SLOT(uiPlaybackChanged(int, Status)));
@ -145,6 +151,7 @@ void libreMediaServerAudio::setUi(libreMediaServerAudioUi *lmsUi)
m_ola->start(QThread::TimeCriticalPriority ); m_ola->start(QThread::TimeCriticalPriority );
}; };
// From Ui widgets
void libreMediaServerAudio::uiSliderChanged(int layer, Slider s, int value) void libreMediaServerAudio::uiSliderChanged(int layer, Slider s, int value)
{ {
switch (s){ switch (s){
@ -166,8 +173,12 @@ void libreMediaServerAudio::uiPlaybackChanged(int layer, Status s)
m_currentStatus[layer] = s; m_currentStatus[layer] = s;
} }
void libreMediaServerAudio::uiLoadMedia(int layer, QString s) void libreMediaServerAudio::uiLoadMedia(int layer, QString mediaFile)
{ {
m_mae.loadMedia(layer, s.toLatin1().data()); if (strcmp(mediaFile.toLatin1().constData(), m_currentMedia[layer].toLatin1().constData()) == 0)
return;
m_mae.loadMedia(layer, mediaFile.toLatin1().data());
m_currentMedia[layer] = mediaFile;
m_lmsUi->m_aw->mediaLoaded(layer, mediaFile, m_mae.getDuration(layer));
} }
#endif #endif

View file

@ -21,6 +21,7 @@
#define LIBREMEDIASERVERAUDIO_H #define LIBREMEDIASERVERAUDIO_H
#include "medialibrary.h" #include "medialibrary.h"
#include "miniaudioengine.h"
#include "olathread.h" #include "olathread.h"
#include "settings.h" #include "settings.h"
#include "defines.h" #include "defines.h"
@ -33,33 +34,35 @@ class libreMediaServerAudio : public QObject
Q_OBJECT Q_OBJECT
public: public:
libreMediaServerAudio(bool gui = false); libreMediaServerAudio();
virtual ~libreMediaServerAudio(); virtual ~libreMediaServerAudio();
void dmxInput(int layer, int channel, int value); void dmxInput(int layer, int channel, int value);
void loadMedia(int layer, int folder, int file);
#ifndef NOGUI #ifndef NOGUI
void setUi(libreMediaServerAudioUi *lmsUi); void setUi(libreMediaServerAudioUi *lmsUi);
bool inline getShowUi() { return m_settings->getShowUi(); }
#endif #endif
//static void NewDmx(const ola::client::DMXMetadata &data, const ola::DmxBuffer &buffer);
private: private:
olaThread *m_ola; olaThread *m_ola;
MediaLibrary *m_mediaLibrary; MediaLibrary *m_mediaLibrary;
MiniAudioEngine m_mae; MiniAudioEngine m_mae;
Settings *m_settings;
QString m_currentMedia[MAX_LAYERS]; QString m_currentMedia[MAX_LAYERS];
Status m_currentStatus[MAX_LAYERS]; Status m_currentStatus[MAX_LAYERS];
static QList<dmxSetting> m_dmxSettings; QList<dmxSetting> m_dmxSettings;
#ifndef NOGUI
bool m_ui; bool m_ui;
#ifndef NOGUI
QTimer *m_refreshUi; QTimer *m_refreshUi;
libreMediaServerAudioUi *m_lmsUi; libreMediaServerAudioUi *m_lmsUi;
float m_updateUi[MAX_LAYERS][4]; float m_updateUi[MAX_LAYERS][4];
#endif
private slots: private slots:
#ifndef NOGUI
void refreshUi(); void refreshUi();
void uiSliderChanged(int layer, Slider s, int value); void uiSliderChanged(int layer, Slider s, int value);
void uiPlaybackChanged(int layer, Status s); void uiPlaybackChanged(int layer, Status s);
void uiLoadMedia(int layer, QString s); void uiLoadMedia(int layer, QString s);
#endif #endif
}; };

View file

@ -32,9 +32,9 @@ bool hasUi(int &argc, char *argv[])
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
QApplication app(argc, argv); QApplication app(argc, argv);
libreMediaServerAudio lms(hasUi(argc, argv)); libreMediaServerAudio lms;
#ifndef NOGUI #ifndef NOGUI
if (hasUi(argc, argv)) if (hasUi(argc, argv) || lms.getShowUi())
{ {
libreMediaServerAudioUi *lmsUi = new libreMediaServerAudioUi(); libreMediaServerAudioUi *lmsUi = new libreMediaServerAudioUi();
lms.setUi(lmsUi); lms.setUi(lmsUi);

View file

@ -4,6 +4,11 @@ MiniAudioEngine::MiniAudioEngine()
{ {
for (int i =0; i < MAX_LAYERS; i++) { for (int i =0; i < MAX_LAYERS; i++) {
m_mediaLoaded[i] = false; m_mediaLoaded[i] = false;
m_currentLayerValues[i].status = Status::Iddle;
m_currentLayerValues[i].pan = 128;
m_currentLayerValues[i].pitch = 128;
m_currentLayerValues[i].vol = 0;
m_currentLayerValues[i].cursor = 0;
} }
} }
@ -79,8 +84,8 @@ ma_result MiniAudioEngine::startContext()
resourceManagerConfig = ma_resource_manager_config_init(); resourceManagerConfig = ma_resource_manager_config_init();
resourceManagerConfig.decodedFormat = ma_format_f32; /* ma_format_f32 should almost always be used as that's what the engine (and most everything else) uses for mixing. */ resourceManagerConfig.decodedFormat = ma_format_f32; /* ma_format_f32 should almost always be used as that's what the engine (and most everything else) uses for mixing. */
resourceManagerConfig.decodedChannels = 0; resourceManagerConfig.decodedChannels = 0;
resourceManagerConfig.decodedSampleRate = 0; resourceManagerConfig.decodedSampleRate = ma_standard_sample_rate_48000;
resourceManagerConfig.jobThreadCount = 0; resourceManagerConfig.jobThreadCount = 1;
result = ma_resource_manager_init(&resourceManagerConfig, &resourceManager); result = ma_resource_manager_init(&resourceManagerConfig, &resourceManager);
if (result != MA_SUCCESS) { if (result != MA_SUCCESS) {
qCritical("Failed to initialize audio resource manager."); qCritical("Failed to initialize audio resource manager.");
@ -114,11 +119,9 @@ ma_result MiniAudioEngine::getAllAudioDevices()
ma_result MiniAudioEngine::loadMedia(int layer, char *file) ma_result MiniAudioEngine::loadMedia(int layer, char *file)
{ {
ma_result result; ma_result result;
float vol = -1;
if (m_mediaLoaded[layer] == true) if (m_mediaLoaded[layer] == true)
{ {
vol = ma_sound_get_volume(&m_currentSound[layer]);
ma_sound_uninit(&m_currentSound[layer]); ma_sound_uninit(&m_currentSound[layer]);
m_mediaLoaded[layer] = false; m_mediaLoaded[layer] = false;
} }
@ -133,10 +136,8 @@ ma_result MiniAudioEngine::loadMedia(int layer, char *file)
qWarning("Failed to load file %s", file); qWarning("Failed to load file %s", file);
else { else {
m_mediaLoaded[layer] = true; m_mediaLoaded[layer] = true;
if (vol == -1) this->refreshValues(layer);
this->volChanged(layer, 0); m_currentLayerValues[layer].media = file;
else
this->volChanged(layer, vol);
} }
return result; return result;
} }
@ -191,7 +192,7 @@ ma_result MiniAudioEngine::printFormatInfo(int layer)
qWarning("Failed to get data format %i\n", layer); qWarning("Failed to get data format %i\n", layer);
return MA_INVALID_DATA; return MA_INVALID_DATA;
} }
qInfo("samples/sec: %u format: %u channels: %u", sampleRate, format, channels); qInfo() << "name:" << m_currentLayerValues[layer].media << "samples/sec:" << sampleRate << "format:" << format << "channels:" << channels;
return result; return result;
} }
@ -200,9 +201,10 @@ void MiniAudioEngine::volChanged(int layer, float vol)
{ {
if (m_mediaLoaded[layer] == false) if (m_mediaLoaded[layer] == false)
return; return;
if (vol > 1) if (vol >= 1)
vol = 1; vol = 0.99f;
ma_sound_group_set_volume(&m_currentSound[layer], vol); ma_sound_group_set_fade_in_milliseconds(&m_currentSound[layer], -1, vol, FADE_TIME);
m_currentLayerValues[layer].vol = vol;
} }
void MiniAudioEngine::panChanged(int layer, float value) void MiniAudioEngine::panChanged(int layer, float value)
@ -213,6 +215,7 @@ void MiniAudioEngine::panChanged(int layer, float value)
return; return;
result = (value / 128.0) - 1.0; result = (value / 128.0) - 1.0;
ma_sound_group_set_pan(&m_currentSound[layer], result); ma_sound_group_set_pan(&m_currentSound[layer], result);
m_currentLayerValues[layer].pan = value;
} }
void MiniAudioEngine::pitchChanged(int layer, float value) void MiniAudioEngine::pitchChanged(int layer, float value)
@ -223,6 +226,7 @@ void MiniAudioEngine::pitchChanged(int layer, float value)
return; return;
result = value / 128.0; result = value / 128.0;
ma_sound_group_set_pitch(&m_currentSound[layer], result); ma_sound_group_set_pitch(&m_currentSound[layer], result);
m_currentLayerValues[layer].pitch = value;
} }
void MiniAudioEngine::playbackChanged(int layer, Status status) void MiniAudioEngine::playbackChanged(int layer, Status status)
@ -235,7 +239,7 @@ void MiniAudioEngine::playbackChanged(int layer, Status status)
break; break;
case Status::Stopped: case Status::Stopped:
ma_sound_stop(&m_currentSound[layer]); ma_sound_stop(&m_currentSound[layer]);
ma_sound_seek_to_pcm_frame(&m_currentSound[layer], 0); this->setCursor(layer, m_currentLayerValues[layer].cursor);
break; break;
case Status::PlayingLoop: case Status::PlayingLoop:
ma_sound_set_looping(&m_currentSound[layer], true); ma_sound_set_looping(&m_currentSound[layer], true);
@ -248,30 +252,35 @@ void MiniAudioEngine::playbackChanged(int layer, Status status)
default: default:
break; break;
} }
m_currentLayerValues[layer].status = status;
} }
void MiniAudioEngine::setCursor(int layer, int cursor) void MiniAudioEngine::setCursor(int layer, int cursor)
{ {
ma_uint64 f; ma_uint64 end;
m_currentLayerValues[layer].cursor = cursor;
if (m_mediaLoaded[layer] == false) if (m_mediaLoaded[layer] == false)
return; return;
ma_sound_get_length_in_pcm_frames(&m_currentSound[layer], &f); ma_sound_get_length_in_pcm_frames(&m_currentSound[layer], &end);
f = (cursor * f) / 65025; ma_uint64 start = (cursor * end) / 65025;
ma_sound_seek_to_pcm_frame(&m_currentSound[layer], f); ma_sound_seek_to_pcm_frame(&m_currentSound[layer], start);
// ToDo: change the loop entry point too ma_result result = ma_data_source_set_loop_point_in_pcm_frames(&m_currentSound[layer], start, end);
if (result != MA_SUCCESS) {
return; // Failed to set the loop point.
}
} }
Status MiniAudioEngine::getStatus(int layer) Status MiniAudioEngine::getStatus(int layer)
{ {
if (m_mediaLoaded[layer] == false) return m_currentLayerValues[layer].status;
return Status::Iddle; }
if (ma_sound_is_playing(&m_currentSound[layer])) {
if (ma_sound_is_looping(&m_currentSound[layer])) void MiniAudioEngine::refreshValues(int layer)
return Status::PlayingLoop; {
return Status::PlayingOnce; this->panChanged(layer, m_currentLayerValues[layer].pan);
} this->volChanged(layer, m_currentLayerValues[layer].vol);
if (this->getDuration(layer) > 0) this->pitchChanged(layer, m_currentLayerValues[layer].pitch);
return Status::Paused; this->playbackChanged(layer, m_currentLayerValues[layer].status);
return Status::Stopped; this->setCursor(layer, m_currentLayerValues[layer].cursor);
} }

View file

@ -40,10 +40,12 @@ private:
ma_context context; ma_context context;
ma_sound m_currentSound[MAX_LAYERS]; ma_sound m_currentSound[MAX_LAYERS];
ma_bool8 m_mediaLoaded[MAX_LAYERS]; ma_bool8 m_mediaLoaded[MAX_LAYERS];
layerData m_currentLayerValues[MAX_LAYERS];
ma_result getAllAudioDevices(); ma_result getAllAudioDevices();
ma_result startDevice(int id); ma_result startDevice(int id);
ma_result startContext(); ma_result startContext();
void refreshValues(int layer);
}; };
#endif // MINIAUDIOENGINE_H #endif // MINIAUDIOENGINE_H

View file

@ -1,5 +1,4 @@
#include "libremediaserver-audio.h" #include "libremediaserver-audio.h"
//#include "olathread.h"
olaThread::olaThread(QObject *parent, int layers) : olaThread::olaThread(QObject *parent, int layers) :
m_counter(0) m_counter(0)
@ -36,7 +35,6 @@ void olaThread::init()
} }
m_client = m_clientWrapper->GetClient(); m_client = m_clientWrapper->GetClient();
m_client->SetDMXCallback(ola::NewCallback(this, &olaThread::NewDmx)); m_client->SetDMXCallback(ola::NewCallback(this, &olaThread::NewDmx));
//m_client->SetDMXCallback(ola::NewCallback((libreMediaServerAudio *)this->parent(), libreMediaServerAudio::NewDmx));
m_clientWrapper->GetSelectServer()->RegisterRepeatingTimeout(4000, ola::NewCallback(this, &olaThread::CheckDataLoss)); m_clientWrapper->GetSelectServer()->RegisterRepeatingTimeout(4000, ola::NewCallback(this, &olaThread::CheckDataLoss));
m_client->SetCloseHandler(ola::NewSingleCallback(this, &olaThread::socketClosed)); m_client->SetCloseHandler(ola::NewSingleCallback(this, &olaThread::socketClosed));
m_dmxSettings = Settings::getInstance()->getDmxSettings(); m_dmxSettings = Settings::getInstance()->getDmxSettings();
@ -69,30 +67,31 @@ void olaThread::NewDmx(const ola::client::DMXMetadata &data,
bool volSent = false; bool volSent = false;
bool entrySent = false; bool entrySent = false;
bool fileSent = false; bool fileSent = false;
int aux;
for (int j = 0; j < LAYER_CHANNELS; j++){ for (int j = 0; j < LAYER_CHANNELS; j++){
int value = buffer.Get((i.address) + j); int value = buffer.Get((i.address) + j);
if (m_dmx[i.layer][j] != value) { if (m_dmx[i.layer][j] != value) {
m_dmx[i.layer][j] = value; m_dmx[i.layer][j] = value;
switch (j) { switch (j) {
case DMX_FOLDER: case DMX_FOLDER:
value *= 0x100; aux = buffer.Get(i.address + DMX_FILE);
value += buffer.Get(i.address + DMX_FILE); qobject_cast<libreMediaServerAudio *>(parent())->loadMedia(i.layer, value, aux);
qobject_cast<libreMediaServerAudio *>(parent())->dmxInput(i.layer, j, value); m_dmx[i.layer][DMX_FILE] = aux;
m_dmx[i.layer][DMX_FILE] = buffer.Get(i.address + DMX_FILE);
fileSent = true; fileSent = true;
break; break;
case DMX_FILE: case DMX_FILE:
if (fileSent) if (fileSent)
break; break;
value += buffer.Get(i.address + DMX_FOLDER) * 0x100; aux = buffer.Get(i.address + DMX_FOLDER);
qobject_cast<libreMediaServerAudio *>(parent())->dmxInput(i.layer, j, value); qobject_cast<libreMediaServerAudio *>(parent())->loadMedia(i.layer, aux, value);
m_dmx[i.layer][DMX_FOLDER] = buffer.Get(i.address + DMX_FOLDER); m_dmx[i.layer][DMX_FOLDER] = aux;
fileSent = true; fileSent = true;
break; break;
case VOLUME_FINE: case VOLUME_FINE:
value = (buffer.Get(i.address + VOLUME_COARSE) * 0x100) + value; aux = buffer.Get(i.address + VOLUME_COARSE);
value += (aux * 0x100);
qobject_cast<libreMediaServerAudio *>(parent())->dmxInput(i.layer, j, value); qobject_cast<libreMediaServerAudio *>(parent())->dmxInput(i.layer, j, value);
m_dmx[i.layer][VOLUME_COARSE] = buffer.Get(i.address + VOLUME_COARSE); m_dmx[i.layer][VOLUME_COARSE] = aux;
volSent = true; volSent = true;
break; break;
case VOLUME_COARSE: case VOLUME_COARSE:
@ -103,6 +102,9 @@ void olaThread::NewDmx(const ola::client::DMXMetadata &data,
m_dmx[i.layer][VOLUME_FINE] = buffer.Get(i.address + VOLUME_FINE); m_dmx[i.layer][VOLUME_FINE] = buffer.Get(i.address + VOLUME_FINE);
volSent = true; volSent = true;
break; break;
case PLAYBACK:
qobject_cast<libreMediaServerAudio *>(parent())->dmxInput(i.layer, j, value);
break;
case ENTRY_POINT_FINE: case ENTRY_POINT_FINE:
value = (buffer.Get(i.address + ENTRY_POINT_COARSE) * 0x100) + value; value = (buffer.Get(i.address + ENTRY_POINT_COARSE) * 0x100) + value;
qobject_cast<libreMediaServerAudio *>(parent())->dmxInput(i.layer, j, value); qobject_cast<libreMediaServerAudio *>(parent())->dmxInput(i.layer, j, value);

View file

@ -15,6 +15,7 @@ Settings::Settings(QObject *parent) :
QObject(parent) QObject(parent)
{ {
m_layersNumber = 0; m_layersNumber = 0;
m_ui = false;
} }
// Read the dmx settings for dmx.xml At the moment we need: // Read the dmx settings for dmx.xml At the moment we need:
@ -23,6 +24,7 @@ Settings::Settings(QObject *parent) :
// - The first DMX channel of each source/layer // - The first DMX channel of each source/layer
// - The universe to bind in OLA // - The universe to bind in OLA
// - Audio device id // - Audio device id
// - Show the Ui or not
void Settings::readFromFile(QString file) { void Settings::readFromFile(QString file) {
QFile* xmlFile = new QFile(file); QFile* xmlFile = new QFile(file);
if (!xmlFile->open(QIODevice::ReadOnly | QIODevice::Text)) { if (!xmlFile->open(QIODevice::ReadOnly | QIODevice::Text)) {
@ -34,53 +36,56 @@ void Settings::readFromFile(QString file) {
exit(1); exit(1);
} }
QXmlStreamReader* xmlReader = new QXmlStreamReader(xmlFile); QXmlStreamReader* xmlReader = new QXmlStreamReader(xmlFile);
int counter = 0; while(!xmlReader->atEnd() && !xmlReader->hasError()) {
//Parse the XML until we reach end of it
while(!xmlReader->atEnd() && !xmlReader->hasError() && counter < MAX_LAYERS) {
// Read next element
QXmlStreamReader::TokenType token = xmlReader->readNext(); QXmlStreamReader::TokenType token = xmlReader->readNext();
//If token is just StartDocument - go to next
if(token == QXmlStreamReader::StartDocument) { if(token == QXmlStreamReader::StartDocument) {
continue; continue;
} }
//If token is StartElement - read it
if(token == QXmlStreamReader::StartElement) { if(token == QXmlStreamReader::StartElement) {
if(xmlReader->name() == "dmxSettings") { if(xmlReader->name() == "lmsAudio") {
int version = xmlReader->attributes().value("fileVersion").toLocal8Bit().toInt(); m_ui = xmlReader->attributes().value("ui").toLocal8Bit().toInt();
if(version == 1) { m_layersNumber = xmlReader->attributes().value("layersNumber").toLocal8Bit().toInt();
m_layersNumber = xmlReader->attributes().value("layersNumber").toLocal8Bit().toInt(); m_pathmedia = xmlReader->attributes().value("path").toLocal8Bit();
m_pathmedia = xmlReader->attributes().value("path").toLocal8Bit();
continue;
}
}
if(xmlReader->name() == "audioDevice") {
m_audioDeviceId = xmlReader->attributes().value("id").toLocal8Bit().toInt();
continue; continue;
} }
QString add = "layer"; if(xmlReader->name() == "audioDevice") {
add.append(QString("%1").arg(counter)); m_audioDeviceQty = xmlReader->attributes().value("devicesNumber").toLocal8Bit().toInt();
if((xmlReader->name() == add)) { for (uint i = 0; i < m_audioDeviceQty; i++)
{
m_audioDeviceId[i] = xmlReader->attributes().value(QString("id%1").arg(i)).toLocal8Bit().toInt();
}
}
if(xmlReader->name() == "layer") {
dmxSetting temp; dmxSetting temp;
temp.address = xmlReader->attributes().value("dmx").toLocal8Bit().toInt() - 1; temp.address = xmlReader->attributes().value("dmx").toLocal8Bit().toInt() - 1;
temp.universe = xmlReader->attributes().value("universe").toLocal8Bit().toInt(); temp.universe = xmlReader->attributes().value("universe").toLocal8Bit().toInt();
temp.layer = counter; temp.layer = xmlReader->attributes().value("id").toLocal8Bit().toInt();
m_settings.append(temp); m_settings.append(temp);
if (!m_universe.contains(temp.universe)) { if (!m_universe.contains(temp.universe)) {
m_universe.insert(temp.universe); m_universe.insert(temp.universe);
} }
counter++;
} }
} }
} }
if(xmlReader->hasError()) { if(xmlReader->hasError()) {
QMessageBox::critical(NULL,"File xml Parse Error ", xmlReader->errorString(), QMessageBox::Ok); QMessageBox::critical(NULL,"File xml Parse Error ", xmlReader->errorString(), QMessageBox::Ok);
qWarning("File xml Parse Error %s", xmlReader->errorString().toLatin1().constData()); qWarning("File xml Parse Error %s", xmlReader->errorString().toLatin1().constData());
return; // ToDo: manage this, open a dialog to load a new file.
} }
xmlReader->clear(); xmlReader->clear();
xmlFile->close(); xmlFile->close();
delete xmlReader; delete xmlReader;
delete xmlFile; delete xmlFile;
this->printSettings();
}
void Settings::printSettings() {
qInfo() << "Settings read;\nShow Ui:" << m_ui << "Layers:" << m_layersNumber << "Path:" << m_pathmedia <<"Audio Device qty:" << m_audioDeviceQty;
for (uint i = 0; i < m_audioDeviceQty; i++)
qInfo() << "Audio device id:" << m_audioDeviceId[i];
for (int i = 0; i < m_layersNumber; i++)
qInfo() << "Layer:" << m_settings[i].layer << "Address:" << m_settings[i].address << "Universe:" << m_settings[i].universe;
} }
void Settings::readFile() { void Settings::readFile() {

View file

@ -5,6 +5,7 @@
#include <QFile> #include <QFile>
#include <QMessageBox> #include <QMessageBox>
#include <QSet> #include <QSet>
#include <QDebug>
#include "medialibrary.h" #include "medialibrary.h"
#include "audiowidget.h" #include "audiowidget.h"
@ -15,25 +16,27 @@ class Settings : public QObject
Q_OBJECT Q_OBJECT
public: public:
Settings(QObject *parent = 0);
static Settings *getInstance(); static Settings *getInstance();
inline QSet<int> getUniverses() { return m_universe; } inline QSet<int> getUniverses() { return m_universe; }
inline QString getPathMedia() { return m_pathmedia; } inline QString getPathMedia() { return m_pathmedia; }
inline QList<dmxSetting> getDmxSettings() { return m_settings; } inline QList<dmxSetting> getDmxSettings() { return m_settings; }
inline int getLayersNumber() { return m_layersNumber; } inline int getLayersNumber() { return m_layersNumber; }
inline int getAudioDeviceId() { return m_audioDeviceId[0]; }
inline bool getShowUi() { return m_ui; }
void readFile(); void readFile();
inline int getAudioDeviceId() { return m_audioDeviceId; } void readFromFile(QString file);
void printSettings();
private: private:
static Settings *_instance; static Settings *_instance;
QList<dmxSetting> m_settings; QList<dmxSetting> m_settings;
QString m_pathmedia; QString m_pathmedia;
uint m_audioDeviceId; uint m_audioDeviceId[MAX_AUDIODEVICES];
uint m_audioDeviceQty;
QSet<int> m_universe; QSet<int> m_universe;
int m_layersNumber; int m_layersNumber;
bool m_ui;
explicit Settings(QObject *parent = 0);
void readFromFile(QString file);
}; };
#endif // SETTINGS_H #endif // SETTINGS_H

View file

@ -18,10 +18,11 @@ SliderGroup::SliderGroup(QString name,
slider->setMinimumHeight(0); slider->setMinimumHeight(0);
slider->setSingleStep(1); slider->setSingleStep(1);
slider->setRange(min, max); slider->setRange(min, max);
slider->setValue(0);
slider->setMinimumWidth(50); slider->setMinimumWidth(50);
slider->setToolTip(name); slider->setToolTip(name);
slider->setStyleSheet("QSlider {" slider->setStyleSheet("QSlider {"
"border: 2px solid #685060;" "border: 1px solid #5a4855;"
"margin: 0px;" "margin: 0px;"
"height: 200px;" "height: 200px;"
"width: 50px;}" "width: 50px;}"
@ -32,17 +33,20 @@ SliderGroup::SliderGroup(QString name,
valueBox->setButtonSymbols(QAbstractSpinBox::NoButtons); valueBox->setButtonSymbols(QAbstractSpinBox::NoButtons);
valueBox->setMinimumWidth(50); valueBox->setMinimumWidth(50);
valueBox->setRange(min, max); valueBox->setRange(min, max);
valueBox->setValue(0);
valueBox->setDecimals(decimals); valueBox->setDecimals(decimals);
valueBox->setObjectName(name); valueBox->setObjectName(name);
valueBox->setToolTip(name); valueBox->setToolTip(name);
valueBox->setAlignment(Qt::AlignHCenter); valueBox->setAlignment(Qt::AlignHCenter);
valueBox->setContentsMargins(0, 0, 0, 0); valueBox->setContentsMargins(0, 0, 0, 0);
connect(slider, SIGNAL(valueChanged(int)), this, SLOT(sliderValueChanged(int))); connect(slider, SIGNAL(valueChanged(int)), this, SLOT(sliderValueChanged(int)));
//connect(slider, SIGNAL(mousePressEvent(QMouseEvent)), this, SLOT(mousePressEvent(QMouseEvent *)));
layout->addWidget(slider); layout->addWidget(slider);
layout->addWidget(valueBox); layout->addWidget(valueBox);
this->setStyleSheet("border: 2px solid #685060;" this->setStyleSheet("border: 1px solid #5a4855;"
"width: 50px;" "width: 50px;"
"margin: 0px;" "margin: 0px;"
"background-color: #383034;"
); );
layout->setSpacing(0); layout->setSpacing(0);
layout->setContentsMargins(0, 0, 0, 0); layout->setContentsMargins(0, 0, 0, 0);
@ -67,3 +71,11 @@ void SliderGroup::setValue(float value)
slider->blockSignals(false); slider->blockSignals(false);
valueBox->blockSignals(false); valueBox->blockSignals(false);
} }
void SliderGroup::mousePressEvent(QMouseEvent* event) {
Q_UNUSED(event);
if (slider->isEnabled())
slider->setDisabled(true);
else
slider->setDisabled(false);
}

View file

@ -27,6 +27,8 @@ public slots:
private: private:
QSlider *slider; QSlider *slider;
QDoubleSpinBox *valueBox; QDoubleSpinBox *valueBox;
void mousePressEvent(QMouseEvent* event);
}; };
#endif #endif