diff --git a/docs/LibreMediaServer_Audio.hed b/docs/LibreMediaServer_Audio.hed
index fda3e2d..5da3a28 100644
--- a/docs/LibreMediaServer_Audio.hed
+++ b/docs/LibreMediaServer_Audio.hed
@@ -1,79 +1,76 @@
ް׆ˌĠ鿰맫͓Ԕ
ҊÅЁ䍡
ӽ
-Ꭸʆ
-ɑ
-ɬ
-
-Ԑɉ
-
-ٿդϨ҃
-ڔ
-ڑŌ
-
-
-
-
-
-
-
-
-
-쏎ބ
-힇ݳ
-
-Ԓlj
-
-Ŷ§
-ÐÊ
-𡭟Ē
-
-܊
-
-зм
-
-ҭ
-ܻۏ
-ڑן
-ޏ
-
-Ƴ
-
-
-
-Ǖ
-
-𓎍Ԏ
-
-
-Ξ
-ֆ
-
-ց
-
-ᱯ
-݈
-
-؈
-
-馹
-۴
-𓎍
-
-
-
-
-
-𓎑
-
-
-
-Ɨ
-
-
-
-Ӌ
-쏎
-
-
-
+䉭ėĈ
+ϛ
+Ӧ
+ڑ
+ė
+
+ݍ
+Ȫ
+웣傪Ⓨ֚
+ކՂ
+߸
+Ŷ
+ѝ
+ωƀ
+
+
+
+
+ŕ
+ʷí
+̙
+
+ԥѼ܅
+𗹣َ
+̚
+Რ
+
+Ņ
+⽬
+̫
+喤쏎ʁǏ
+
+߬ػс
+썎ޛ
+
+쏎
+
+
+
+Ճ
+
+尨
+ގ
+
+ލ
+ƕ
+
+ŗ
+
+
+
+
+
+ˤ
+
+
+
+
+
+쏐
+
+
+
+쏎
+
+
+
+
+ÛƘ
+
+
+
+
diff --git a/docs/changelog.txt b/docs/changelog.txt
index 5c7e0b6..48b0ddf 100644
--- a/docs/changelog.txt
+++ b/docs/changelog.txt
@@ -4,45 +4,39 @@ Libre Media Server Audio - An Open source Media Server for arts and performing.
https://git.criptomart.net/libremediaserver
*******************************************************************************
-Libre Media Server ChangeLog
+Lbre Media Server ChangeLog
-v 0.2.0 Antígona (26/05/2024)
-+ Change audio engine to miniaudio because is imposible pan in SFML and it has not access to low API and audio processing.
-+ Refactor all audio methods to MiniAudioEngine class.
+v 0.2.0 Antigona (24/04/2024)
++ change engine to miniaudio because is imposible pan in SFML and it has not access to low API and audio processing.
++ Refactor all audio methods to MiniAudioEngine.
+ Select sound device output.
-+ Pan.
-+ Show faders values. New SliderGroup class.
-+ Entry Point 16 bits.
++ pan.
++ Show faders values.
++ play offset.
+ Refactor AudioMasterWidget to AudioDMXReceptionWidget.
-+ Read mp3, flac, wav (mp3 has given some errors seeking cursor...).
-+ Removed settings dialog, only read xml conf file at startup.
-+ Real dynamic variable number of layers based on conf file setting.
-+ OlaThread send double channels (volume, entry point, load media) only once for each dmx frame buffer.
-+ Terminal mode without graphical interface. All audio methods has been refactorized out of QWidget world.
-+ Compilation without GUI (-DNOGUI).
-+ 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);
-+ 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).
-+ Load media files from ui clicking in the media labels.
++ 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 Leúcade (19/04/2024)
+v 0.1.3 Unreleased (19/04/2024)
+ Ubuntu 22.04 jammy.
++ Use SFML as audio engine.
+ Qt 5.15.3.
-+ Pitch.
-+ Loop.
++ pitch.
++ loop.
v 0.1.2 Mayordomo (12/08/2015)
-- GUI config.
-- Several bugs tested in real world.
-- Variable layers.
-- SFML as audio engine.
+- GUI config
+- Several bugs tested in real world
+- variable layers
+- SFML as audio engine
v 0.1.1 Pascual (24/09/2014)
-+ First Version: 4 layers playing .ogg.
-+ Needs Open Lighting Arquitecture => 0.9.0.
-+ Pure Data as audio engine.
++ First Version: 4 layers playing .ogg
++ Needs Open Lighting Arquitecture => 0.9.0
++ Pure Data as audio engine
diff --git a/docs/lms-audio.xlm b/docs/lms-audio.xlm
index 4274267..cc498ca 100644
--- a/docs/lms-audio.xlm
+++ b/docs/lms-audio.xlm
@@ -1,8 +1,8 @@
-
-
-
-
-
-
-
+
+
+
+
+
+
+
diff --git a/docs/roadmap.txt b/docs/roadmap.txt
index 0771257..8ff57d7 100644
--- a/docs/roadmap.txt
+++ b/docs/roadmap.txt
@@ -5,6 +5,7 @@ https://git.criptomart.net/libremediaserver
*******************************************************************************
Libre Media Server Roadmap
+(en continuo crecimiento...)
v 0.2.x
- skin, UI/UX
@@ -19,8 +20,8 @@ v 0.2.2
+ hay que empaquetar OLA, incluirlo en el binario, o implementar sACN y linkarlo estáticamente.
+ https://github.com/ETCLabs/sACN
- Qt6.
-- Audio processing (eq, rev, compresor, ...) by master and layer.
-- CIPT/MSex, send icons play/pause/stop.
+- audio processing (eq, rev, compresor, ...) por master y capa.
+- CIPT/MSex, send icons play-pause-stop.
- Rasp build.
- Octopus Sound Card support (6 outputs - 8 inputs).
@@ -40,15 +41,15 @@ v 0.2.1
- audio device linked, outputs will be redirected there.
- dmx address + universe settings.
- Rose noise and sine generator in menu to test system.
-- Ui/Ux; Keyboards strokes.
-- Ui/Ux: Dar la opción clickeando en el widget de tiempo de poner una cuenta atrás en vez de hacia delante.
+- 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, verbosity, timestamp.
-- New play mode without pitch control, it saves resources. MA_SOUND_FLAG_NO_PITCH
+- 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.
-- ¿Exit Point? is it needed?
-- Hardening: check return errors, try/catch exceptions, i'm too happy....
-- Tests: errors on wrong conf file.
-
-v0.2.0:
-- Vumeter or indicator about audio output in layer and master, add to sliderGroup.
+- ¿stop offset? is it needed?
+- 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/libremediaserver-audio.pro b/libremediaserver-audio.pro
index 41d6ecd..a33e231 100644
--- a/libremediaserver-audio.pro
+++ b/libremediaserver-audio.pro
@@ -2,10 +2,7 @@ TEMPLATE = app
TARGET = libremediaserver-audio
QT += webkitwidgets widgets
HEADERS += src/libremediaserver-audio.h \
- src/clickablelabel.h \
src/dmxwidget.h \
- src/libremediaserver-audio-gui.h \
- src/main.h \
src/miniaudio.h \
src/medialibrary.h \
src/miniaudioengine.h \
@@ -17,9 +14,7 @@ HEADERS += src/libremediaserver-audio.h \
src/settings.h \
src/slidergroup.h
SOURCES += src/main.cpp \
- src/clickablelabel.cpp \
src/dmxwidget.cpp \
- src/libremediaserver-audio-gui.cpp \
src/miniaudio.c \
src/libremediaserver-audio.cpp \
src/medialibrary.cpp \
@@ -29,10 +24,10 @@ SOURCES += src/main.cpp \
src/audiowidget.cpp \
src/settings.cpp \
src/slidergroup.cpp
-FORMS += src/libremediaserver-audio-gui.ui
-CCFLAG += -msse2 -mavx2 #-fsanitize=address -g3 -O0
+FORMS += src/libremediaserver-audio.ui
+CCFLAG += -msse2 -mavx2 #-fsanitize=address -g -O0
QMAKE_CXXFLAGS += $$(CXXFLAG)
-#QMAKE_CXXFLAGS += -fsanitize=address -g3 -O0
+#QMAKE_CXXFLAGS += -fsanitize=address -g -O0
QMAKE_CFLAGS += $$(CCFLAG)
QMAKE_LFLAGS += $$(LDFLAG)
LIBS += -lola -lolacommon -ldl -lpthread -lm
diff --git a/src/audiolayerwidget.cpp b/src/audiolayerwidget.cpp
index e8d22bd..99e1996 100644
--- a/src/audiolayerwidget.cpp
+++ b/src/audiolayerwidget.cpp
@@ -1,89 +1,64 @@
#include "audiolayerwidget.h"
-#include
-AudioLayerWidget::AudioLayerWidget(QWidget *parent, int layer):
- QWidget(parent)
+
+AudioLayerWidget::AudioLayerWidget(QWidget *parent, QString name, int layer):
+ QGroupBox(parent)
, m_layer(layer)
, m_suspendResumeButton(0)
{
+ this->setTitle(name);
QVBoxLayout *layout = new QVBoxLayout;
- QVBoxLayout *playback = new QVBoxLayout;
- m_folderValue = new ClickableLabel;
- m_folderValue->setMaximumWidth(160);
- m_folderValue->setAlignment(Qt::AlignLeft);
- m_folderValue->setStyleSheet(
- "color: white;"
- "background-color: black;"
- );
- playback->addWidget(m_folderValue);
- m_fileValue = new ClickableLabel;
- connect(m_fileValue, SIGNAL(clicked()), this, SLOT(openMediaDialog()));
- connect(m_folderValue, SIGNAL(clicked()), this, SLOT(openMediaDialog()));
- m_fileValue->setMaximumWidth(160);
- m_fileValue->setAlignment(Qt::AlignLeft);
- m_fileValue->setStyleSheet(
- "color: white;"
- "background-color: black;"
- );
- playback->addWidget(m_fileValue);
- playback->setSpacing(0);
- playback->setContentsMargins(0, 0, 0, 0);
- layout->addLayout(playback);
-
- m_suspendResumeButton = new QPushButton(this);
- m_suspendResumeButton->setText(StatusStr[Status::Iddle]);
- connect(m_suspendResumeButton, SIGNAL(clicked()), SLOT(toggleSuspendResume()));
- layout->addWidget(m_suspendResumeButton);
-
- m_progress = new QProgressBar(this);
- m_progress->setOrientation(Qt::Horizontal);
- m_progress->setRange(0, 0);
- m_progress->setValue(0);
- m_progress->setFormat("%v / %m");
- layout->addWidget(m_progress);
-
+ QHBoxLayout *progressTime = new QHBoxLayout;
m_progressTime = new QTimeEdit;
- m_progressTime->setToolTip("Current Time");
- m_progressTime->setObjectName("Current Time");
- m_progressTime->setDisplayFormat("mm:ss:zz");
+ m_progressTime->text();
+ m_progressTime->setDisplayFormat("h:mm:ss:zzz");
m_progressTime->setReadOnly(true);
m_progressTime->setButtonSymbols(QAbstractSpinBox::NoButtons);
- m_progressTime->setMinimumWidth(80);
- m_progressTime->setMaximumWidth(80);
+ m_progressTime->setMaximumWidth(90);
m_progressTime->setFocusPolicy(Qt::NoFocus);
- m_progressTime->setAlignment(Qt::AlignHCenter);
- m_progressTime->setContentsMargins(0,0,0,0);
+ progressTime->addWidget(m_progressTime);
m_totalTimeValue = new QTimeEdit;
- m_totalTimeValue->setObjectName("Track Length");
- m_totalTimeValue->setToolTip("Track Length");
- m_totalTimeValue->setDisplayFormat("mm:ss:zzz");
+ m_totalTimeValue->setDisplayFormat("h:mm:ss:zzz");
m_totalTimeValue->setReadOnly(true);
m_totalTimeValue->setButtonSymbols(QAbstractSpinBox::NoButtons);
- m_totalTimeValue->setMinimumWidth(80);
+ m_totalTimeValue->setMaximumWidth(90);
m_totalTimeValue->setFocusPolicy(Qt::NoFocus);
- m_totalTimeValue->setAlignment(Qt::AlignHCenter);
- m_totalTimeValue->setContentsMargins(0,0,0,0);
- QHBoxLayout *status = new QHBoxLayout;
- status->addWidget(m_progressTime);
- status->addWidget(m_totalTimeValue);
+ progressTime->addWidget(m_totalTimeValue);
+ layout->addLayout(progressTime);
+
+ m_progressSlider = new QSlider(Qt::Horizontal);
+ m_progressSlider->setFocusPolicy(Qt::NoFocus);
+ layout->addWidget(m_progressSlider);
+
+ QGridLayout *status = new QGridLayout;
+ m_statusValue = new QLabel;
+ status->addWidget(m_statusValue, 0, 0);
+ m_folderValue = new QLabel;
+ m_folderValue->setMaximumWidth(200);
+ status->addWidget(m_folderValue, 1, 0);
+ m_fileValue = new QLabel;
+ m_fileValue->setMaximumWidth(200);
+ status->addWidget(m_fileValue, 2, 0);
layout->addLayout(status);
+
QHBoxLayout *volumeBox = new QHBoxLayout;
m_volume = new SliderGroup("Vol", 0 , 100, 2, NULL);
volumeBox->addWidget(m_volume);
- connect(m_volume, SIGNAL(valueChanged(int)), this, SLOT(volumeChanged(int)));
+ 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)));
+ connect(m_pan, SIGNAL(valueChanged(float)), this, SLOT(panChanged(float)));
m_pitch = new SliderGroup("Pitch", 0 , 255, 0, NULL);
volumeBox->addWidget(m_pitch);
- volumeBox->setSpacing(0);
- volumeBox->setContentsMargins(0, 0, 0, 0);
- connect(m_pitch, SIGNAL(valueChanged(int)), this, SLOT(pitchChanged(int)));
+ connect(m_pitch, SIGNAL(valueChanged(float)), this, SLOT(pitchChanged(float)));
layout->addLayout(volumeBox);
- layout->setAlignment(Qt::AlignHCenter);
- layout->setSpacing(0);
- layout->setContentsMargins(2, 2, 2, 2);
+
+ m_suspendResumeButton = new QPushButton(this);
+ m_suspendResumeButton->setText(StatusStr[Status::Stopped]);
+ connect(m_suspendResumeButton, SIGNAL(clicked()), SLOT(toggleSuspendResume()));
+ layout->addWidget(m_suspendResumeButton);
+
this->setLayout(layout);
}
@@ -93,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));
}
@@ -118,28 +93,12 @@ void AudioLayerWidget::toggleSuspendResume()
break;
case Status::Paused:
case Status::Stopped:
- this->setPlaybackStatus(Status::PlayingLoop);
- emit uiPlaybackChanged(m_layer, Status::PlayingLoop);
- case Status::Iddle:
+ this->setPlaybackStatus(Status::PlayingOnce);
+ emit uiPlaybackChanged(m_layer, Status::PlayingOnce);
break;
}
}
-void AudioLayerWidget::openMediaDialog()
-{
- QFileDialog dialog(this);
- dialog.setFileMode(QFileDialog::ExistingFile);
- dialog.setNameFilter(tr("Sound Tracks (*.mp3 *.mp3 *.flac *.wav"));
- dialog.setViewMode(QFileDialog::Detail);
- dialog.setDirectory(Settings::getInstance()->getPathMedia());
- if (!dialog.exec())
- return;
- QStringList fileNames;
- fileNames = dialog.selectedFiles();
- emit uiLoadMedia(m_layer, fileNames.at(0));
- this->setMediaFile(fileNames.at(0));
-}
-
// from DMX signals
void AudioLayerWidget::setVol(float vol)
{
@@ -162,7 +121,7 @@ void AudioLayerWidget::setPitch(int pitch)
m_pitch->blockSignals(false);
}
-void AudioLayerWidget::setMediaFile(QString file)
+void AudioLayerWidget::fileLoaded(QString file)
{
QStringList list = file.split("/");
int size = list.size();
@@ -172,36 +131,41 @@ void AudioLayerWidget::setMediaFile(QString file)
}
}
-void AudioLayerWidget::setPlaybackStatus(Status s)
+void AudioLayerWidget::setPlaybackStatus(Status status)
{
- Status status = static_cast(s);
- m_suspendResumeButton->blockSignals(true);
m_status = status;
+ if (status == Status::Stopped)
+ 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->setStyleSheet("QLabel { color : red; }");
+ break;
+ case Status::PlayingLoop:
+ case Status::PlayingOnce:
+ m_statusValue->setStyleSheet("QLabel { color : green; }");
+ break;
+ case Status::Stopped:
+ m_statusValue->setStyleSheet("QLabel { color : red; }");
+ break;
+ }
+ m_statusValue->blockSignals(false);
m_suspendResumeButton->blockSignals(false);
}
-void AudioLayerWidget::setDuration(float dur)
+void AudioLayerWidget::durationChanged(float dur)
{
- m_progress->blockSignals(true);
- m_progressTime->blockSignals(true);
- m_totalTimeValue->blockSignals(true);
- m_progress->setRange(0, dur);
- m_progress->setValue(0);
- m_progressTime->setTime(QTime::fromMSecsSinceStartOfDay(0));
+ dur *= 1000;
+ m_progressSlider->setMaximum(dur);
m_totalTimeValue->setTime(QTime::fromMSecsSinceStartOfDay(dur));
- m_progress->blockSignals(false);
- m_progressTime->blockSignals(false);
- m_totalTimeValue->blockSignals(false);
}
-void AudioLayerWidget::setCurrentTime(float progress)
+void AudioLayerWidget::refreshUi(float progress)
{
progress *= 1000;
- m_progress->blockSignals(true);
- m_progressTime->blockSignals(true);
- m_progress->setValue(progress);
+ m_progressSlider->setValue(progress);
m_progressTime->setTime(QTime::fromMSecsSinceStartOfDay(progress));
- m_progress->blockSignals(false);
- m_progressTime->blockSignals(false);
}
diff --git a/src/audiolayerwidget.h b/src/audiolayerwidget.h
index 9380b81..53401fb 100644
--- a/src/audiolayerwidget.h
+++ b/src/audiolayerwidget.h
@@ -3,57 +3,53 @@
#include
#include
-#include
-#include
+#include
#include "defines.h"
#include "slidergroup.h"
-#include "clickablelabel.h"
-#include "settings.h"
-class AudioLayerWidget : public QWidget
+class AudioLayerWidget : public QGroupBox
{
Q_OBJECT
public:
- explicit AudioLayerWidget(QWidget *parent = 0, int layer = 0);
+ explicit AudioLayerWidget(QWidget *parent = 0, QString name = "Layer", int layer = 0);
~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:
Status m_status;
int m_layer;
QPushButton *m_suspendResumeButton;
- ClickableLabel *m_fileValue;
- ClickableLabel * m_folderValue;
+ QLabel * m_statusValue;
+ QLabel *m_fileValue;
+ QLabel * m_folderValue;
SliderGroup *m_volume;
SliderGroup *m_pan;
SliderGroup *m_pitch;
+ QSlider *m_progressSlider;
QTimeEdit *m_progressTime;
QTimeEdit *m_totalTimeValue;
- QProgressBar *m_progress;
-// From DMX
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 volumeChanged(int vol);
- void panChanged(int pan);
- void pitchChanged(int pitch);
+ void volumeChanged(float vol);
+ void panChanged(float pan);
+ void pitchChanged(float pitch);
+ void fileLoaded(QString file);
+ void durationChanged(float dur);
+ void refreshUi(float progress);
signals:
void uiPlaybackChanged(int layer, Status s);
void uiSliderChanged(int layer, Slider s, int value);
- void uiLoadMedia(int layer, QString s);
+
};
#endif // AUDIOLAYERWIDGET_H
diff --git a/src/audiowidget.cpp b/src/audiowidget.cpp
index 8bd077c..4b35a5c 100644
--- a/src/audiowidget.cpp
+++ b/src/audiowidget.cpp
@@ -1,100 +1,121 @@
#include "audiowidget.h"
-#include
-AudioWidget::AudioWidget(QWidget *parent) :
- QWidget(parent)
- , m_layout(new QHBoxLayout())
+
+AudioWidget::AudioWidget() :
+ m_layout(new QHBoxLayout())
+ , m_refreshUi(new QTimer(this))
{
for (int i= 0; i < Settings::getInstance()->getLayersNumber(); i++ ) {
- AudioLayerWidget *alw = new AudioLayerWidget(this, i);
+ AudioLayerWidget *alw = new AudioLayerWidget(this, tr("Layer %1").arg(i + 1), i);
m_layout->insertWidget(i, alw);
- connect(alw, SIGNAL(uiSliderChanged(int, Slider, int)), this, SIGNAL(uiSliderChanged(int, Slider, int)));
- connect(alw, SIGNAL(uiPlaybackChanged(int, Status)), this, SIGNAL(uiPlaybackChanged(int, Status)));
- connect(alw, SIGNAL(uiLoadMedia(int, QString)), this, SIGNAL(uiLoadMedia(int, QString)));
- m_layerUpdate[i].status = Status::Iddle;
- m_layerUpdate[i].duration = 0;
- m_layerUpdate[i].media = "";
- m_layerUpdate[i].vol = 0;
- m_layerUpdate[i].pan = 128;
- m_layerUpdate[i].pitch = 128;
- m_layerUpdate[i].cursor = 0;
+ connect(alw, SIGNAL(uiSliderChanged(int, Slider, int)), this, SLOT(uiSliderAction(int, Slider, int)));
+ connect(alw, SIGNAL(uiPlaybackChanged(int, Status)), this, SLOT(uiChangePlaybackStatus(int, Status)));
}
- m_layout->setSpacing(0);
- m_layout->setContentsMargins(1, 1, 1, 1);
setLayout(m_layout);
- m_refreshUi = new QTimer(this);
connect(m_refreshUi, SIGNAL(timeout()), this, SLOT(refreshUi()));
- m_refreshUi->start(UI_REFRESH_TIME * 1.5);
+ m_refreshUi->start(UI_REFRESH_TIME);
}
-void AudioWidget::mediaLoaded(int layer, QString file, float duration)
+bool AudioWidget::startEngine(int id)
{
- m_layerUpdate[layer].media = file;
- m_layerUpdate[layer].duration = duration;
- m_layerUpdate[layer].updated = true;
+ return (m_mae.startEngine(id));
+}
+
+bool AudioWidget::startEngine()
+{
+ return (m_mae.startEngine(Settings::getInstance()->getAudioDeviceId()));
+}
+
+void AudioWidget::stopEngine()
+{
+ m_mae.stopEngine();
+}
+
+void AudioWidget::mediaLoaded(int layer, QString file)
+{
+ ma_result result;
+
+ if (m_currentMedia[layer].compare(file) == 0 ) {
+ return;
+ }
+ if (!QFile::exists(file)) {
+ qWarning("Can not access to file %s", file.toLatin1().constData());
+ return;
+ }
+ result = m_mae.loadMedia(layer, file.toLatin1().data());
+ if (result != MA_SUCCESS) {
+ qWarning("can not open file %s", file.toLatin1().constData());
+ return;
+ }
+ m_currentMedia[layer] = file;
+ float pLength = m_mae.getDuration(layer);
+ qInfo("File loaded: %s - Duration: %f secs", file.toLatin1().constData(), pLength);
+ m_mae.printFormatInfo(layer);
+ QLayoutItem * const item = m_layout->itemAt(layer);
+ dynamic_cast(item->widget())->fileLoaded(file);
+ dynamic_cast(item->widget())->durationChanged(pLength);
}
void AudioWidget::volChanged(int layer, float vol) {
- m_layerUpdate[layer].vol = vol;
- m_layerUpdate[layer].updated = true;
+ m_mae.volChanged(layer, vol);
+ QLayoutItem * const item = m_layout->itemAt(layer);
+ dynamic_cast(item->widget())->setVol(vol);
}
void AudioWidget::panChanged(int layer, int pan) {
- m_layerUpdate[layer].pan = pan;
- m_layerUpdate[layer].updated = true;
+ m_mae.panChanged(layer, pan);
+ QLayoutItem * const item = m_layout->itemAt(layer);
+ dynamic_cast(item->widget())->setPan(pan);
}
void AudioWidget::pitchChanged(int layer, int pitch) {
-
- m_layerUpdate[layer].pitch = pitch;
- m_layerUpdate[layer].updated = true;
+ m_mae.pitchChanged(layer, pitch);
+ QLayoutItem * const item = m_layout->itemAt(layer);
+ dynamic_cast(item->widget())->setPitch(pitch);
}
void AudioWidget::playbackChanged(int layer, Status status)
{
- m_layerUpdate[layer].status = status;
- m_layerUpdate[layer].updated = true;
+ m_mae.playbackChanged(layer, status);
+ QLayoutItem * const item = m_layout->itemAt(layer);
+ dynamic_cast(item->widget())->setPlaybackStatus(status);
}
-void AudioWidget::cursorChanged(int layer, float cursor)
+void AudioWidget::entryPointChanged(int layer, int cursor)
{
- m_layerUpdate[layer].cursor = cursor;
- m_layerUpdate[layer].updated = true;
+ m_mae.setCursor(layer, cursor);
+ QLayoutItem * const item = m_layout->itemAt(layer);
+ AudioLayerWidget *aw = dynamic_cast(item->widget());
+ aw->refreshUi(m_mae.getCursor(layer));
}
-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(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;
+void AudioWidget::refreshUi() {
+ for (int i= 0; i < Settings::getInstance()->getLayersNumber(); i++ ) {
+ QLayoutItem * const item = m_layout->itemAt(i);
+ AudioLayerWidget *aw = dynamic_cast(item->widget());
+ Status s = aw->getPlaybackStatus();
+ if (s == Status::PlayingOnce || s == Status::PlayingLoop) {
+ aw->refreshUi(m_mae.getCursor(i));
}
}
}
+
+void AudioWidget::uiSliderAction(int layer, Slider s, int value)
+{
+ switch (s){
+ case Slider::Volume:
+ m_mae.volChanged(layer, value);
+ break;
+ case Slider::Pan:
+ m_mae.panChanged(layer, value);
+ break;
+ case Slider::Pitch:
+ m_mae.pitchChanged(layer, value);
+ break;
+ }
+}
+
+void AudioWidget::uiChangePlaybackStatus(int layer, Status s) {
+ m_mae.playbackChanged(layer, s);
+}
+
diff --git a/src/audiowidget.h b/src/audiowidget.h
index dd9b1f1..254e59e 100644
--- a/src/audiowidget.h
+++ b/src/audiowidget.h
@@ -5,6 +5,7 @@
#include "audiolayerwidget.h"
#include "settings.h"
+#include "miniaudioengine.h"
#include "defines.h" // MAX_LAYERS
class AudioWidget : public QWidget
@@ -12,27 +13,29 @@ class AudioWidget : public QWidget
Q_OBJECT
public:
- AudioWidget(QWidget *parent = nullptr);
-
-private:
- QHBoxLayout *m_layout;
- layerData m_layerUpdate[MAX_LAYERS];
- QTimer *m_refreshUi;
-
-public slots:
+ AudioWidget();
+ bool startEngine();
+ bool startEngine(int id);
+ void stopEngine();
+ void mediaLoaded(int layer, QString media );
void volChanged(int layer, float vol);
void panChanged(int layer, int pan);
void pitchChanged(int layer, int pitch);
- void cursorChanged(int layer, float cursor);
- void mediaLoaded(int layer, QString media, float duration);
void playbackChanged(int layer, Status status);
+ void entryPointChanged(int layer, int cursor);
+
+private:
+ MiniAudioEngine m_mae;
+ QString m_currentMedia[MAX_LAYERS];
+ QHBoxLayout *m_layout;
+ QTimer *m_refreshUi;
+
+public slots:
+ void uiSliderAction(int layer, Slider s, int value);
+ void uiChangePlaybackStatus(int layer, Status s);
private slots:
void refreshUi();
-signals:
- void uiPlaybackChanged(int layer, Status s);
- void uiSliderChanged(int layer, Slider s, int vol);
- void uiLoadMedia(int layer, QString s);
};
#endif // AUDIOWIDGET_H
diff --git a/src/clickablelabel.cpp b/src/clickablelabel.cpp
deleted file mode 100644
index 623493d..0000000
--- a/src/clickablelabel.cpp
+++ /dev/null
@@ -1,14 +0,0 @@
-#include "clickablelabel.h"
-
-ClickableLabel::ClickableLabel(QWidget *parent, Qt::WindowFlags f)
- : QLabel{parent}
-{
- Q_UNUSED(f);
-}
-
-ClickableLabel::~ClickableLabel() {}
-
-void ClickableLabel::mousePressEvent(QMouseEvent* event) {
- Q_UNUSED(event);
- emit clicked();
-}
diff --git a/src/clickablelabel.h b/src/clickablelabel.h
deleted file mode 100644
index e75aae7..0000000
--- a/src/clickablelabel.h
+++ /dev/null
@@ -1,22 +0,0 @@
-#ifndef CLICKABLELABEL_H
-#define CLICKABLELABEL_H
-
-#include
-#include
-#include
-
-class ClickableLabel : public QLabel
-{
- Q_OBJECT
-public:
- explicit ClickableLabel(QWidget *parent = Q_NULLPTR, Qt::WindowFlags f = Qt::WindowFlags());
- ~ClickableLabel();
-
-signals:
- void clicked();
-
-protected:
- void mousePressEvent(QMouseEvent* event);
-};
-
-#endif // CLICKABLELABEL_H
diff --git a/src/defines.h b/src/defines.h
index ff299c1..68675c2 100644
--- a/src/defines.h
+++ b/src/defines.h
@@ -1,15 +1,15 @@
#ifndef DEFINES_H
#define DEFINES_H
-#define VERSION "LibreMediaServerAudio 0.2.0 Antigona Release"
+//#define VERSION "LibreMediaServerAudio 0.2.0 Antigona Release"
+#define VERSION "Kike Substitutor - No AI required - v0.2.0"
#define COPYRIGHT "(C) 2014-2024 Santi Noreña "
-#define LICENSE "GPL 3 Licensed. See LICENSE.txt."
+#define LICENSE "GPL 3 Licensed. See LICENSE.txt.\nSound guys are not allowed to use this software."
#define DEFAULT_FILE "lms-audio.xlm"
-#define MAX_LAYERS 4
-#define MAX_AUDIODEVICES 8
-#define UI_REFRESH_TIME 66
-#define FADE_TIME 25 // DMX Frame time, 40 fps, avoid clicks
+#define MAX_LAYERS 16
+#define UI_REFRESH_TIME 200
+// struct where save the DMX settings for each layer
struct dmxSetting {
int address;
unsigned int universe;
@@ -22,10 +22,6 @@ enum Status
Paused,
PlayingOnce,
PlayingLoop,
- Iddle,
- PlayingFolder,
- PlayingFolderLoop,
- PlayingFolderRandom
};
static const char* StatusStr[] =
@@ -33,11 +29,7 @@ static const char* StatusStr[] =
"Stop",
"Pause",
"Playing One",
- "Playing One Loop",
- "Iddle",
- "Playing Folder",
- "Playing Folder Loop",
- "Playing Folder Random",
+ "Playing Loop",
0x0
};
@@ -48,18 +40,5 @@ enum Slider
Pitch,
};
-#include
-struct layerData {
- QString media;
- Status status;
- bool updated;
- float vol;
- float cursor;
- int pan;
- int pitch;
- float duration;
- int address;
- unsigned int universe;
- int device;
-};
#endif // DEFINES_H
+
diff --git a/src/dmxPersonality.h b/src/dmxPersonality.h
index 82f9468..1e42df7 100644
--- a/src/dmxPersonality.h
+++ b/src/dmxPersonality.h
@@ -1,15 +1,39 @@
#ifndef DMXPERSONALITY_H
#define DMXPERSONALITY_H
-#define VOLUME_COARSE 3
-#define PAN 6
-#define DMX_FOLDER 0
-#define DMX_FILE 1
-#define PLAYBACK 8
-#define VOLUME_FINE 2
-#define ENTRY_POINT_COARSE 5
-#define ENTRY_POINT_FINE 4
-#define PITCH 7
-#define LAYER_CHANNELS 9
+/** Define the DMX personality to avoid dealing with
+ * numbers and change it easyly in case
+ *
+1 - Volumen Coarse
+2 - Pan
+3 - Folder
+4 - File
+5 - Playback
+ 0-24 : Play once.
+ 25-49: Stop. Returns to start of file.
+ 50-74: Pause. It keeps the time of reproductions.
+ 75-99: Play loop.
+6 - Control - Reservado, sin uso en este momento.
+7 - Volume Fine
+8 - Entry Point Coarse - Punto de entrada de reproducción.
+9 - Entry Point Fine - El valor de estos dos canales en centésimas de segundo.
+10 - Pan
+11 - Pitch
+*/
+
+// ToDo: Mejor inicializacion, primero folder, file, después params, ultimo playback.7
+// quitar CONTROL no usado
+#define VOLUME_COARSE 0
+#define PAN 1
+#define DMX_FOLDER 2
+#define DMX_FILE 3
+#define PLAYBACK 4
+#define CONTROL 5
+#define VOLUME_FINE 6
+#define ENTRY_POINT_COARSE 7
+#define ENTRY_POINT_FINE 8
+#define PITCH 9
+
+#define LAYER_CHANNELS 10
#endif // DMXPERSONALITY_H
diff --git a/src/dmxwidget.cpp b/src/dmxwidget.cpp
index c5b4150..60d4206 100644
--- a/src/dmxwidget.cpp
+++ b/src/dmxwidget.cpp
@@ -9,8 +9,6 @@ dmxWidget::dmxWidget(QWidget *parent) :
QVBoxLayout *vbox = new QVBoxLayout;
m_receiveDMX->setText("DMX Signal");
vbox->addWidget(m_receiveDMX);
- vbox->setSpacing(1);
- vbox->setContentsMargins(1, 1, 1, 1);
this->setLayout(vbox);
connect(m_watchDMX, SIGNAL(timeout()),
this, SLOT(watchDMXExpired()));
diff --git a/src/libremediaserver-audio-gui.cpp b/src/libremediaserver-audio-gui.cpp
deleted file mode 100644
index b769679..0000000
--- a/src/libremediaserver-audio-gui.cpp
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
-
- Libre Media Server Audio - An Open source Media Server for arts and performing.
- (c) Criptomart - Santiago Noreña 2012-2024
- https://git.criptomart.net/libremediaserver
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see .
-*/
-
-#include "libremediaserver-audio-gui.h"
-
-
-libreMediaServerAudioUi::libreMediaServerAudioUi(QWidget *parent)
- : QMainWindow(parent)
-{
- ui.setupUi(this);
- this->setWindowTitle(VERSION);
- m_aw = new AudioWidget(this);
- setCentralWidget(m_aw);
- m_dmxWidget = new dmxWidget(this);
- QDockWidget *topWidget = new QDockWidget(tr("Master"), this);
- topWidget->setAllowedAreas(Qt::TopDockWidgetArea);
- topWidget->setWidget(m_dmxWidget);
- topWidget->setContentsMargins(0, 0, 0, 0);
- addDockWidget(Qt::TopDockWidgetArea, topWidget);
- connect(ui.actionLaunch_OLA_Setup, SIGNAL(triggered()), this, SLOT(olasetup()));
- this->setContentsMargins(5, 5, 5, 5);
- this->setStyleSheet(
- "color: white;"
- "background-color: #4f4048;"
- "selection-color: blue;"
- "selection-background-color: green"
- );
-}
-
-libreMediaServerAudioUi::~libreMediaServerAudioUi()
-{
-}
-
-void libreMediaServerAudioUi::olasetup()
-{
- QWebView *view = new QWebView();
- view->load(QUrl("http://localhost:9090/ola.html"));
- view->show();
-}
diff --git a/src/libremediaserver-audio-gui.h b/src/libremediaserver-audio-gui.h
deleted file mode 100644
index 50b4d8b..0000000
--- a/src/libremediaserver-audio-gui.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- Libre Media Server Audio - An Open source Media Server for arts and performing.
- (c) Criptomart - Santiago Noreña 2012-2024
- https://git.criptomart.net/libremediaserver
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see .
-*/
-
-#ifndef LIBREMEDIASERVERAUDIOUI_H
-#define LIBREMEDIASERVERAUDIOUI_H
-
-#include
-#include
-
-#include "audiowidget.h"
-#include "dmxwidget.h"
-#include "defines.h"
-#include "ui_libremediaserver-audio-gui.h"
-
-class libreMediaServerAudioUi : public QMainWindow
-{
- Q_OBJECT
-
-public:
- libreMediaServerAudioUi(QWidget *parent = 0);
- virtual ~libreMediaServerAudioUi();
- AudioWidget *m_aw;
- dmxWidget *m_dmxWidget;
-
-private:
- Ui::LibreMediaServerAudio ui;
-
-private slots:
- void olasetup();
-};
-
-#endif // LIBREMEDIASERVERAUDIOUI_H
diff --git a/src/libremediaserver-audio-gui.ui b/src/libremediaserver-audio-gui.ui
deleted file mode 100644
index c0f11ad..0000000
--- a/src/libremediaserver-audio-gui.ui
+++ /dev/null
@@ -1,55 +0,0 @@
-
-
- Santi Noreña lms@criptomart.net
- LibreMediaServerAudio
-
-
-
- 0
- 0
- 500
- 400
-
-
-
-
- Unifont
- 12
- 75
- true
-
-
-
- LibreMediaServer
-
-
-
- ../../../../criptomart/artwork/logo_v2_criptomart.net.png../../../../criptomart/artwork/logo_v2_criptomart.net.png
-
-
-
-
-
- OLA Setup
-
-
-
-
-
-
diff --git a/src/libremediaserver-audio.cpp b/src/libremediaserver-audio.cpp
index a9868fd..0d595ec 100644
--- a/src/libremediaserver-audio.cpp
+++ b/src/libremediaserver-audio.cpp
@@ -21,239 +21,106 @@
#include "libremediaserver-audio.h"
-libreMediaServerAudio::libreMediaServerAudio()
+libreMediaServerAudio::libreMediaServerAudio(QStringList args, QWidget *parent)
+ : QMainWindow(parent)
{
- m_settings = Settings::getInstance();
- m_settings->readFile();
- m_ui = m_settings->getShowUi();
+ Q_UNUSED(args);
+ qDebug() << VERSION;
+ qDebug() << COPYRIGHT;
+ qDebug() << LICENSE;
+ ui.setupUi(this);
+ this->setWindowTitle(VERSION);
+ Settings *set = Settings::getInstance();
+ set->readFile();
m_mediaLibrary = new MediaLibrary;
m_mediaLibrary->initMediaLibrary();
- for (int i = 0; i < MAX_LAYERS; i++) {
- m_currentMedia[i] = "";
- m_currentStatus[i] = Status::Iddle;
-#ifdef NOGUI
- m_updateUi[i][0] = -1;
- m_updateUi[i][1] = -1;
- m_updateUi[i][2] = -1;
- m_updateUi[i][3] = -1;
-#endif
- }
- m_ola = new olaThread(this, m_settings->getLayersNumber());
+ m_aw = new AudioWidget;
+ setCentralWidget(m_aw);
+ m_dmxWidget = new dmxWidget(this);
+ QDockWidget *topWidget = new QDockWidget(tr("Master"), this);
+ topWidget->setAllowedAreas(Qt::TopDockWidgetArea);
+ topWidget->setWidget(m_dmxWidget);
+ addDockWidget(Qt::TopDockWidgetArea, topWidget);
+ m_ola = new olaThread(this, set->getLayersNumber());
Q_CHECK_PTR(m_ola);
m_ola->blockSignals(true);
+ connect(m_ola, SIGNAL (universeReceived(int)), m_dmxWidget, SLOT(updateWatchDMX(int)));
+ connect(m_ola, SIGNAL(dmxOutput(int, int, int)), this, SLOT(dmxInput(int, int, int)));
m_ola->registerUniverse();
- m_mae.startEngine(m_settings->getAudioDeviceId());
- qDebug("Core init Complete. Start reading DMX.");
+ connect(ui.actionLaunch_OLA_Setup, SIGNAL(triggered()), this, SLOT(olasetup()));
+ m_aw->startEngine();
+ qDebug("Init Complete.");
m_ola->blockSignals(false);
-#ifdef NOGUI
m_ola->start(QThread::TimeCriticalPriority );
-#endif
}
libreMediaServerAudio::~libreMediaServerAudio()
{
m_ola->stop();
- m_mae.stopEngine();
+ m_aw->stopEngine();
}
-void libreMediaServerAudio::loadMedia(int layer, int folder, int file)
+void libreMediaServerAudio::olasetup()
{
- 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);
- }
- if (m_currentStatus[layer] == Status::PlayingFolder \
- || (m_currentStatus[layer] == Status::PlayingFolderLoop)\
- || (m_currentStatus[layer] == Status::PlayingFolderRandom)) {
- m_played.append(file);
- } else if (m_currentStatus[layer] == Status::PlayingOnce \
- || m_currentStatus[layer] == Status::PlayingLoop) {
- m_played.clear();
- }
+ QWebView *view = new QWebView();
+ view->load(QUrl("http://localhost:9090/ola.html"));
+ view->show();
}
void libreMediaServerAudio::dmxInput(int layer, int channel, int value)
{
- if (layer >= MAX_LAYERS || channel >= LAYER_CHANNELS)
+ if (layer > LAYER_CHANNELS)
return;
QString mediaFile = NULL;
int aux;
- if (channel == VOLUME_COARSE || channel == VOLUME_FINE) {
- float tmp = value / 65025.0f;
- m_mae.volChanged(layer, tmp);
- m_updateUi[layer][0] = tmp * 100.0f;
- } else if (channel == PAN) {
- m_mae.panChanged(layer, value);
- m_updateUi[layer][1] = value;
- } else if (channel == PITCH) {
- m_mae.pitchChanged(layer, value);
- m_updateUi[layer][2] = value;
- } else if (channel == ENTRY_POINT_COARSE || channel == ENTRY_POINT_FINE) {
- m_mae.setCursor(layer, value);
- m_updateUi[layer][3] = value;
- } else if (channel == PLAYBACK && value > 0) {
+ switch(channel){
+ case DMX_FOLDER:
+ aux = m_ola->getValue(layer, DMX_FILE);
+ mediaFile = m_mediaLibrary->requestNewFile(value, aux);
+ if (QFile::exists(mediaFile))
+ m_aw->mediaLoaded(layer, mediaFile);
+ break;
+ case DMX_FILE:
+ aux = m_ola->getValue(layer, DMX_FOLDER);
+ mediaFile = m_mediaLibrary->requestNewFile(aux, value);
+ if (QFile::exists(mediaFile))
+ m_aw->mediaLoaded(layer, mediaFile);
+ break;
+ case VOLUME_COARSE:
+ case VOLUME_FINE:
+ m_aw->volChanged(layer, (value / 65025.0f));
+ break;
+ case PAN:
+ m_aw->panChanged(layer, value);
+ break;
+ case PITCH:
+ m_aw->pitchChanged(layer, value);
+ break;
+ case ENTRY_POINT_COARSE:
+ case ENTRY_POINT_FINE:
+ m_aw->entryPointChanged(layer, value);
+ break;
+ case PLAYBACK:
+ if (value == 0)
+ break;
aux = value / 25;
- Status s = m_currentStatus[layer];
- if (aux == 0)
- s = Status::PlayingOnce;
- else if (aux == 1)
- s = Status::Stopped;
- else if (aux == 2)
- s = Status::Paused;
- else if (aux == 3)
- s = Status::PlayingLoop;
- else if (aux == 4)
- s = Status::PlayingFolder;
- else if (aux == 5)
- s = Status::PlayingFolderLoop;
- else if (aux == 6)
- s = Status::PlayingFolderRandom;
- m_mae.playbackChanged(layer, s);
- m_currentStatus[layer] = s;
- qInfo() << "Layer" << layer << StatusStr[s];
-#ifndef NOGUI
- if (m_ui) {
- m_lmsUi->m_aw->playbackChanged(layer, s);
- //m_lmsUi->m_aw->cursorChanged(layer, m_mae.getCursor(layer));
+ switch (aux) {
+ case 0 :
+ m_aw->playbackChanged(layer, PlayingOnce);
+ break;
+ case 1 :
+ m_aw->playbackChanged(layer, Stopped);
+ break;
+ case 2 :
+ m_aw->playbackChanged(layer, Paused);
+ break;
+ case 3 :
+ m_aw->playbackChanged(layer, PlayingLoop);
+ break;
+ default :
+ break;
}
-#endif
- }
-}
-#ifndef NOGUI
-void libreMediaServerAudio::refreshUi() {
- if (!m_ui) return;
- for (int i= 0; i < m_settings->getLayersNumber(); i++ ) {
- if (m_updateUi[i][0] >= 0) {
- m_lmsUi->m_aw->volChanged(i, m_updateUi[i][0]);
- m_updateUi[i][0] = -1;
- }
- if (m_updateUi[i][1] >= 0) {
- m_lmsUi->m_aw->panChanged(i, m_updateUi[i][1]);
- m_updateUi[i][1] = -1;
- }
- if (m_updateUi[i][2] >= 0) {
- m_lmsUi->m_aw->pitchChanged(i, m_updateUi[i][2]);
- m_updateUi[i][2] = -1;
- }
- if (m_updateUi[i][3] >= 0 \
- || m_currentStatus[i] == Status::PlayingOnce\
- || m_currentStatus[i] == Status::PlayingLoop\
- || m_currentStatus[i] == Status::PlayingFolder\
- || m_currentStatus[i] == Status::PlayingFolderLoop
- || m_currentStatus[i] == Status::PlayingFolderRandom) {
- m_lmsUi->m_aw->cursorChanged(i, m_mae.getCursor(i));
- m_updateUi[i][3] = -1;
- }
- if (m_mae.getAtEnd(i)) {
- if (m_played.isEmpty())
- m_played.append(m_ola->getValue(i, DMX_FILE));
- if (m_currentStatus[i] == Status::PlayingOnce) {
- m_currentStatus[i] = Status::Stopped;
- }
- if (m_currentStatus[i] == Status::PlayingFolder) {
- uint last = m_played.last();
- int folder = m_ola->getValue(i, DMX_FOLDER);
- last++;
- if (last < m_mediaLibrary->getMediaFolderCount(folder)) {
- this->loadMedia(i, folder, last);
- m_mae.playbackChanged(i, Status::PlayingFolder);
- }
- else {
- m_currentStatus[i] = Status::Stopped;
- m_lmsUi->m_aw->playbackChanged(i, Status::Stopped);
- }
- }
- if (m_currentStatus[i] == Status::PlayingFolderLoop) {
- uint last = m_played.last();
- int folder = m_ola->getValue(i, DMX_FOLDER);
- last++;
- if (last >= m_mediaLibrary->getMediaFolderCount(folder)) {
- this->loadMedia(i, folder, 0);
- m_mae.playbackChanged(i, Status::PlayingFolderLoop);
- } else {
- this->loadMedia(i, folder, last);
- m_mae.playbackChanged(i, Status::PlayingFolder);
- }
- }
- if (m_currentStatus[i] == Status::PlayingFolderRandom) {
- int last = -1;
- int folder = m_ola->getValue(i, DMX_FOLDER);
- if (uint(abs(m_played.size())) >= m_mediaLibrary->getMediaFolderCount(folder))
- m_played.clear();
- while (last == -1) {
- last = rand() % m_mediaLibrary->getMediaFolderCount(folder);
- if (m_played.contains(last))
- last = -1;
- }
- this->loadMedia(i, folder, last);
- m_mae.playbackChanged(i, Status::PlayingFolderRandom);
- }
- }
- }
-}
-
-void libreMediaServerAudio::setUi(libreMediaServerAudioUi *lmsUi)
-{
- m_lmsUi = lmsUi;
- m_ui = true;
- 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(uiPlaybackChanged(int, Status)), this, SLOT(uiPlaybackChanged(int, Status)));
- connect(m_lmsUi->m_aw, SIGNAL(uiLoadMedia(int, QString)), this, SLOT(uiLoadMedia(int, QString)));
- m_refreshUi = new QTimer(this);
- connect(m_refreshUi, SIGNAL(timeout()), this, SLOT(refreshUi()));
- m_refreshUi->start(UI_REFRESH_TIME);
- m_ola->start(QThread::TimeCriticalPriority );
-};
-
-// From Ui widgets
-void libreMediaServerAudio::uiSliderChanged(int layer, Slider s, int value)
-{
- switch (s){
- case Slider::Volume:
- m_mae.volChanged(layer, float((value / 100.0f)));
- break;
- case Slider::Pan:
- m_mae.panChanged(layer, value);
- break;
- case Slider::Pitch:
- m_mae.pitchChanged(layer, value);
+ default:
break;
}
}
-
-void libreMediaServerAudio::uiPlaybackChanged(int layer, Status s)
-{
- ma_result result;
-
- result = m_mae.playbackChanged(layer, s);
- if (result == MA_SUCCESS) {
- m_currentStatus[layer] = s;
- } else {
- qWarning() << "ui playback change error" << result << "status" << s << "layer" << layer;
- }
-}
-
-void libreMediaServerAudio::uiLoadMedia(int layer, QString mediaFile)
-{
- ma_result result;
-
- if (strcmp(mediaFile.toLatin1().constData(), m_currentMedia[layer].toLatin1().constData()) == 0)
- return;
- result = m_mae.loadMedia(layer, mediaFile.toLatin1().data());
- if (result == MA_SUCCESS) {
- m_currentMedia[layer] = mediaFile;
- m_lmsUi->m_aw->mediaLoaded(layer, mediaFile, m_mae.getDuration(layer));
- } else {
- qWarning() << "ui load media error" << result << "file" << mediaFile << "layer" << layer;
- }
-}
-#endif
diff --git a/src/libremediaserver-audio.h b/src/libremediaserver-audio.h
index d83446a..9cd154b 100644
--- a/src/libremediaserver-audio.h
+++ b/src/libremediaserver-audio.h
@@ -20,51 +20,35 @@
#ifndef LIBREMEDIASERVERAUDIO_H
#define LIBREMEDIASERVERAUDIO_H
+#include
+#include
+
+#include "audiowidget.h"
#include "medialibrary.h"
-#include "miniaudioengine.h"
#include "olathread.h"
#include "settings.h"
+#include "dmxwidget.h"
#include "defines.h"
-#ifndef NOGUI
-#include "libremediaserver-audio-gui.h"
-#endif
+#include "ui_libremediaserver-audio.h"
-class libreMediaServerAudio : public QObject
+class libreMediaServerAudio : public QMainWindow
{
Q_OBJECT
public:
- libreMediaServerAudio();
+ libreMediaServerAudio (QStringList args, QWidget *parent = 0);
virtual ~libreMediaServerAudio();
- void dmxInput(int layer, int channel, int value);
- void loadMedia(int layer, int folder, int file);
-#ifndef NOGUI
- void setUi(libreMediaServerAudioUi *lmsUi);
- bool inline getShowUi() { return m_settings->getShowUi(); }
-#endif
+ Ui::LibreMediaServerAudio ui;
private:
+ AudioWidget *m_aw;
+ dmxWidget *m_dmxWidget;
olaThread *m_ola;
MediaLibrary *m_mediaLibrary;
- MiniAudioEngine m_mae;
- Settings *m_settings;
- QString m_currentMedia[MAX_LAYERS];
- Status m_currentStatus[MAX_LAYERS];
- QList m_dmxSettings;
- bool m_ui;
- QList m_played;
-#ifndef NOGUI
- QTimer *m_refreshUi;
- libreMediaServerAudioUi *m_lmsUi;
- float m_updateUi[MAX_LAYERS][4];
private slots:
- void refreshUi();
- void uiSliderChanged(int layer, Slider s, int value);
- void uiPlaybackChanged(int layer, Status s);
- void uiLoadMedia(int layer, QString s);
-
-#endif
+ void olasetup();
+ void dmxInput(int layer, int channel, int value);
};
#endif // LIBREMEDIASERVERAUDIO_H
diff --git a/src/libremediaserver-audio.ui b/src/libremediaserver-audio.ui
new file mode 100644
index 0000000..6ade744
--- /dev/null
+++ b/src/libremediaserver-audio.ui
@@ -0,0 +1,81 @@
+
+
+ Santi Noreña belfegor@gmail.com
+ LibreMediaServerAudio
+
+
+
+ 0
+ 0
+ 114
+ 218
+
+
+
+ LibreMediaServer
+
+
+
+
+
+ Exit
+
+
+
+
+ Open Configuration...
+
+
+
+
+ Save Configuration...
+
+
+
+
+ Settings...
+
+
+
+
+ false
+
+
+ Init
+
+
+
+
+ IP Address
+
+
+
+
+ Make Thumbs
+
+
+
+
+ OLA Setup...
+
+
+
+
+
+
diff --git a/src/main.cpp b/src/main.cpp
index 79b7a91..bfadafe 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -18,28 +18,34 @@
along with this program. If not, see .
*/
-#include "main.h"
+#include "libremediaserver-audio.h"
-bool hasUi(int &argc, char *argv[])
-{
- for (int i = 1; i < argc; ++i) {
- if (!strcmp(argv[i], "--gui"))
- return true;
- }
- return false;
-}
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
- libreMediaServerAudio lms;
-#ifndef NOGUI
- if (hasUi(argc, argv) || lms.getShowUi())
+ QStringList args = app.arguments();
+ if (args.size() > 1)
{
- libreMediaServerAudioUi *lmsUi = new libreMediaServerAudioUi();
- lms.setUi(lmsUi);
- lmsUi->show();
+ if (args.contains("-v"))
+ {
+ qDebug() << VERSION;
+ qDebug() << COPYRIGHT;
+ qDebug() << LICENSE;
+ return 0;
+ }
+ if (args.contains("-h"))
+ {
+ qDebug() << VERSION;
+ qDebug() << COPYRIGHT;
+ qDebug() << LICENSE;
+ qDebug() << "Help for command line options:";
+ qDebug() << "-v show the version and exits";
+ qDebug() << "-h this help";
+ return 0;
+ }
}
-#endif
+ libreMediaServerAudio libreMediaServerAudio(args);
+ libreMediaServerAudio.show();
return app.exec();
}
diff --git a/src/main.h b/src/main.h
deleted file mode 100644
index 1a96ff6..0000000
--- a/src/main.h
+++ /dev/null
@@ -1,20 +0,0 @@
-#ifndef MAIN_H
-#define MAIN_H
-
-#include
-#include
-
-#include "medialibrary.h"
-#include "olathread.h"
-#include "settings.h"
-#include "libremediaserver-audio.h"
-#include "libremediaserver-audio-gui.h"
-#include "defines.h"
-
- olaThread *m_ola;
- MediaLibrary *m_mediaLibrary;
-
- // slots
- void dmxInput(int layer, int channel, int value);
-
-#endif // MAIN_H
diff --git a/src/medialibrary.h b/src/medialibrary.h
index ea92bca..5a0b55b 100644
--- a/src/medialibrary.h
+++ b/src/medialibrary.h
@@ -27,11 +27,14 @@ class MediaLibrary : public QObject
public:
MediaLibrary(QObject *parent = 0);
+ /**
+ * @brief request a new file from the media library
+ * @param int folder - the folder required
+ * @param int layer - file required
+ * @return QString the file required with full path
+ */
QString requestNewFile(int folder, int layer);
void initMediaLibrary();
- inline uint getMediaFolderCount(int folder) {
- return m_media->at(folder).m_ElementCount;
- }
private:
QList *m_media;
diff --git a/src/miniaudioengine.cpp b/src/miniaudioengine.cpp
index 9204636..6d5490c 100644
--- a/src/miniaudioengine.cpp
+++ b/src/miniaudioengine.cpp
@@ -1,15 +1,8 @@
#include "miniaudioengine.h"
-#include //enum macro
+
MiniAudioEngine::MiniAudioEngine()
{
- for (int i =0; i < MAX_LAYERS; i++) {
- 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;
- }
+
}
void MiniAudioEngine::audioDataCallback(ma_device* pDevice, void* pOutput, const void* pInput, ma_uint32 frameCount)
@@ -27,26 +20,25 @@ void MiniAudioEngine::stopEngine()
ma_resource_manager_uninit(&resourceManager);
}
-bool MiniAudioEngine::startEngine(uint n)
+bool MiniAudioEngine::startEngine(int n)
{
ma_result result;
result = this->startContext();
- if (result != MA_SUCCESS) return result;
- result = this->getAllAudioDevices();
- if (result != MA_SUCCESS) return result;
+ if (result != MA_SUCCESS) {
+ return result;
+ }
+ this->getAllAudioDevices();
result = this->startDevice(n);
return result;
}
-ma_result MiniAudioEngine::startDevice(uint id)
+ma_result MiniAudioEngine::startDevice(int id)
{
ma_result result;
ma_device_config deviceConfig;
ma_engine_config engineConfig;
- if (id >= playbackDeviceCount)
- id = playbackDeviceCount - 1;
deviceConfig = ma_device_config_init(ma_device_type_playback);
deviceConfig.playback.pDeviceID = &pPlaybackDeviceInfos[id].id;
deviceConfig.playback.format = resourceManager.config.decodedFormat;
@@ -74,7 +66,7 @@ ma_result MiniAudioEngine::startDevice(uint id)
return result;
}
iChosenDevice = id;
- qInfo("Initialized audio device %d : %s", id, pPlaybackDeviceInfos[id].name);
+ qInfo("Initialized audio device %d: %s", id, pPlaybackDeviceInfos[id].name);
return result;
}
@@ -85,8 +77,8 @@ ma_result MiniAudioEngine::startContext()
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.decodedChannels = 0;
- resourceManagerConfig.decodedSampleRate = ma_standard_sample_rate_48000;
- resourceManagerConfig.jobThreadCount = 4;
+ resourceManagerConfig.decodedSampleRate = 0;
+ resourceManagerConfig.jobThreadCount = 0;
result = ma_resource_manager_init(&resourceManagerConfig, &resourceManager);
if (result != MA_SUCCESS) {
qCritical("Failed to initialize audio resource manager.");
@@ -110,7 +102,7 @@ ma_result MiniAudioEngine::getAllAudioDevices()
ma_context_uninit(&context);
return result;
}
- printf("Audio devices available:\n");
+ printf("Audio devices detected in system:\n");
for (ma_uint32 iAvailableDevice = 0; iAvailableDevice < playbackDeviceCount; iAvailableDevice += 1) {
qInfo("%d: : %s", iAvailableDevice, pPlaybackDeviceInfos[iAvailableDevice].name);
}
@@ -123,20 +115,21 @@ ma_result MiniAudioEngine::loadMedia(int layer, char *file)
if (m_mediaLoaded[layer] == true)
{
+ qInfo("removing sound %i", layer);
ma_sound_uninit(&m_currentSound[layer]);
m_mediaLoaded[layer] = false;
}
result = ma_sound_init_from_file(&engine, file, \
MA_SOUND_FLAG_NO_SPATIALIZATION \
- | MA_SOUND_FLAG_DECODE \
- /*| MA_SOUND_FLAG_NO_PITCH \*/
+ /*| MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_DECODE \
+ | MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_ASYNC \
+ | MA_RESOURCE_MANAGER_DATA_SOURCE_FLAG_STREAM \*/
, NULL, NULL, &m_currentSound[layer]);
if (result != MA_SUCCESS)
qWarning("Failed to load file %s", file);
else {
m_mediaLoaded[layer] = true;
- this->refreshValues(layer);
- m_currentLayerValues[layer].media = file;
+ this->volChanged(layer, 0);
}
return result;
}
@@ -144,21 +137,16 @@ ma_result MiniAudioEngine::loadMedia(int layer, char *file)
float MiniAudioEngine::getDuration(int layer)
{
ma_result result;
- ma_uint64 lengthInPCMFrames;
- ma_uint32 sampleRate;
- float ret;
+ float ret = 0;
if (m_mediaLoaded[layer] == false)
return MA_DOES_NOT_EXIST;
- result = ma_sound_get_length_in_pcm_frames(&m_currentSound[layer], &lengthInPCMFrames);
- if (result != MA_SUCCESS) {
- return result;
+ result = ma_sound_get_length_in_seconds(&m_currentSound[layer], &ret);
+ if (result != MA_SUCCESS)
+ {
+ qWarning("Can not get duration %i", layer);
+ ret = 0;
}
- result = ma_sound_get_data_format(&m_currentSound[layer], NULL, NULL, &sampleRate, NULL, 0);
- if (result != MA_SUCCESS) {
- return MA_ERROR;
- }
- ret = 1000.0f * (lengthInPCMFrames / float(sampleRate));
return ret;
}
@@ -172,8 +160,8 @@ float MiniAudioEngine::getCursor(int layer)
result = ma_sound_get_cursor_in_seconds(&m_currentSound[layer], &ret);
if (result != MA_SUCCESS)
{
- qWarning("%i can not get cursor error %i", layer, result);
- ret = MA_ERROR;
+ qWarning("Can not get cursor %i", layer);
+ ret = 0;
}
return ret;
}
@@ -187,10 +175,11 @@ ma_result MiniAudioEngine::printFormatInfo(int layer)
if (m_mediaLoaded[layer] == false)
return MA_DOES_NOT_EXIST;
ma_result result = ma_sound_get_data_format(&m_currentSound[layer], &format, &channels, &sampleRate, NULL, 0);
- if (result != MA_SUCCESS)
- qWarning("%i failed to get data format %i\n", layer, result);
- else
- qInfo() << "Layer:" << layer << m_currentLayerValues[layer].media << "samples/sec:" << sampleRate << "format:" << format << "channels:" << channels;
+ if (result != MA_SUCCESS) {
+ qWarning("Failed to get data format %i\n", layer);
+ return MA_INVALID_DATA;
+ }
+ qInfo("samples/sec: %u format: %u channels: %u", sampleRate, format, channels);
return result;
}
@@ -199,10 +188,7 @@ void MiniAudioEngine::volChanged(int layer, float vol)
{
if (m_mediaLoaded[layer] == false)
return;
- if (vol >= 1)
- vol = 0.99f;
- ma_sound_group_set_fade_in_milliseconds(&m_currentSound[layer], -1, vol, FADE_TIME);
- m_currentLayerValues[layer].vol = vol;
+ ma_sound_group_set_volume(&m_currentSound[layer], vol);
}
void MiniAudioEngine::panChanged(int layer, float value)
@@ -213,90 +199,48 @@ void MiniAudioEngine::panChanged(int layer, float value)
return;
result = (value / 128.0) - 1.0;
ma_sound_group_set_pan(&m_currentSound[layer], result);
- m_currentLayerValues[layer].pan = value;
}
void MiniAudioEngine::pitchChanged(int layer, float value)
{
- float pitch;
+ float result;
if (m_mediaLoaded[layer] == false)
return;
- pitch = value / 128.0;
- ma_sound_group_set_pitch(&m_currentSound[layer], pitch);
- m_currentLayerValues[layer].pitch = value;
+ result = value / 128.0;
+ ma_sound_group_set_pitch(&m_currentSound[layer], result);
}
-ma_result MiniAudioEngine::playbackChanged(int layer, Status status)
+void MiniAudioEngine::playbackChanged(int layer, Status status)
{
- ma_result result = MA_SUCCESS;
-
if (m_mediaLoaded[layer] == false)
- return MA_DOES_NOT_EXIST;
+ return;
switch (status) {
case Status::Paused:
- result = ma_sound_stop_with_fade_in_milliseconds(&m_currentSound[layer], FADE_TIME);
+ ma_sound_stop(&m_currentSound[layer]);
break;
case Status::Stopped:
- result = ma_sound_stop_with_fade_in_milliseconds(&m_currentSound[layer], FADE_TIME);
- result = this->seekToCursor(layer, m_currentLayerValues[layer].cursor);
+ ma_sound_stop(&m_currentSound[layer]);
+ ma_sound_seek_to_pcm_frame(&m_currentSound[layer], 0);
break;
case Status::PlayingLoop:
- ma_sound_set_stop_time_in_milliseconds(&m_currentSound[layer], ~(ma_uint64)0);
ma_sound_set_looping(&m_currentSound[layer], true);
- result = ma_sound_start(&m_currentSound[layer]);
- break;
+ ma_sound_start(&m_currentSound[layer]);
+ break;
case Status::PlayingOnce:
- case Status::PlayingFolder:
- case Status::PlayingFolderLoop:
- case Status::PlayingFolderRandom:
- ma_sound_set_stop_time_in_milliseconds(&m_currentSound[layer], ~(ma_uint64)0);
ma_sound_set_looping(&m_currentSound[layer], false);
- result = ma_sound_start(&m_currentSound[layer]);
- break;
- default:
+ ma_sound_start(&m_currentSound[layer]);
break;
}
- if (result == MA_SUCCESS)
- m_currentLayerValues[layer].status = status;
- return result;
}
-ma_result MiniAudioEngine::seekToCursor(int layer, int cursor)
+void MiniAudioEngine::setCursor(int layer, int cursor)
{
- ma_result result = MA_SUCCESS;
- ma_uint64 end, start;
+ ma_uint64 f;
if (m_mediaLoaded[layer] == false)
- return MA_DOES_NOT_EXIST;
- result = ma_sound_get_length_in_pcm_frames(&m_currentSound[layer], &end);
- if (result != MA_SUCCESS) { return result; }
- start = (cursor * end) / 65025;
- result = ma_sound_seek_to_pcm_frame(&m_currentSound[layer], start);
- //if (result != MA_SUCCESS) { return result; }
- //result = ma_data_source_set_loop_point_in_pcm_frames(&m_currentSound[layer], start, end);
- return (result);
-}
-
-ma_result MiniAudioEngine::setCursor(int layer, int cursor)
-{
- ma_result result = MA_SUCCESS;
-
- m_currentLayerValues[layer].cursor = cursor;
- result = this->seekToCursor(layer, cursor);
- return (result);
-}
-
-Status MiniAudioEngine::getStatus(int layer)
-{
- return m_currentLayerValues[layer].status;
-}
-
-void MiniAudioEngine::refreshValues(int layer)
-{
- this->seekToCursor(layer, m_currentLayerValues[layer].cursor);
- this->panChanged(layer, m_currentLayerValues[layer].pan);
- this->volChanged(layer, m_currentLayerValues[layer].vol);
- this->pitchChanged(layer, m_currentLayerValues[layer].pitch);
- this->playbackChanged(layer, m_currentLayerValues[layer].status);
+ return;
+ ma_sound_get_length_in_pcm_frames(&m_currentSound[layer], &f);
+ f = (cursor * f) / 65025;
+ ma_sound_seek_to_pcm_frame(&m_currentSound[layer], f);
}
diff --git a/src/miniaudioengine.h b/src/miniaudioengine.h
index 6e1393c..9549602 100644
--- a/src/miniaudioengine.h
+++ b/src/miniaudioengine.h
@@ -5,16 +5,15 @@
#include "miniaudio.h"
#include "defines.h" // MAX_LAYERS
#include // prints messages
-#define MA_DEBUG_OUTPUT
class MiniAudioEngine
{
- friend class libreMediaServerAudio;
+ friend class AudioWidget;
public:
MiniAudioEngine();
void stopEngine();
- bool startEngine(uint id);
+ bool startEngine(int id);
static void audioDataCallback(ma_device* pDevice, void* pOutput, const void* pInput, ma_uint32 frameCount);
protected:
@@ -22,15 +21,11 @@ protected:
void volChanged(int layer, float vol);
void panChanged(int layer, float pan);
void pitchChanged(int layer, float pitch);
- ma_result playbackChanged(int layer, Status status);
- ma_result setCursor(int layer, int cursor);
- ma_result printFormatInfo(int layer);
+ void playbackChanged(int layer, Status status);
float getDuration(int layer);
float getCursor(int layer);
- Status getStatus(int layer);
- inline float getVol(int layer) {
- return ma_sound_get_volume(&m_currentSound[layer]); }
- inline bool getAtEnd(int layer) { return m_currentSound[layer].atEnd; }
+ void setCursor(int layer, int cursor);
+ ma_result printFormatInfo(int layer);
private:
ma_resource_manager_config resourceManagerConfig;
@@ -43,13 +38,10 @@ private:
ma_context context;
ma_sound m_currentSound[MAX_LAYERS];
ma_bool8 m_mediaLoaded[MAX_LAYERS];
- layerData m_currentLayerValues[MAX_LAYERS];
ma_result getAllAudioDevices();
- ma_result startDevice(uint id);
+ ma_result startDevice(int id);
ma_result startContext();
- void refreshValues(int layer);
- ma_result seekToCursor(int layer, int cursor);
};
#endif // MINIAUDIOENGINE_H
diff --git a/src/olathread.cpp b/src/olathread.cpp
index 6ca9325..ed0998b 100644
--- a/src/olathread.cpp
+++ b/src/olathread.cpp
@@ -1,10 +1,11 @@
-#include "libremediaserver-audio.h"
+#include "olathread.h"
+
olaThread::olaThread(QObject *parent, int layers) :
m_counter(0)
, m_layers(layers)
{
- this->setParent(parent);
+ Q_UNUSED(parent);
gettimeofday(&m_last_data, NULL);
for (int i=0; i < MAX_LAYERS; i++)
{
@@ -62,65 +63,42 @@ void olaThread::stop()
void olaThread::NewDmx(const ola::client::DMXMetadata &data,
const ola::DmxBuffer &buffer)
{
+ bool volSent = false;
+ bool entrySent = false;
+
foreach (const dmxSetting &i, m_dmxSettings) {
if(i.universe == data.universe && i.address > -1) {
- bool volSent = false;
- bool entrySent = false;
- bool fileSent = false;
- int aux;
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;
switch (j) {
- case DMX_FOLDER:
- aux = buffer.Get(i.address + DMX_FILE);
- qobject_cast(parent())->loadMedia(i.layer, value, aux);
- m_dmx[i.layer][DMX_FILE] = aux;
- fileSent = true;
- break;
- case DMX_FILE:
- if (fileSent)
- break;
- aux = buffer.Get(i.address + DMX_FOLDER);
- qobject_cast(parent())->loadMedia(i.layer, aux, value);
- m_dmx[i.layer][DMX_FOLDER] = aux;
- fileSent = true;
- break;
- case VOLUME_FINE:
- aux = buffer.Get(i.address + VOLUME_COARSE);
- value += (aux * 0x100);
- qobject_cast(parent())->dmxInput(i.layer, j, value);
- m_dmx[i.layer][VOLUME_COARSE] = aux;
- volSent = true;
- break;
case VOLUME_COARSE:
- if (volSent)
- break;
value = (value * 0x100) + buffer.Get(i.address + VOLUME_FINE);
- qobject_cast(parent())->dmxInput(i.layer, j, value);
- m_dmx[i.layer][VOLUME_FINE] = buffer.Get(i.address + VOLUME_FINE);
+ emit dmxOutput(i.layer,j,value);
volSent = true;
break;
- case PLAYBACK:
- qobject_cast(parent())->dmxInput(i.layer, j, value);
- break;
- case ENTRY_POINT_FINE:
- value = (buffer.Get(i.address + ENTRY_POINT_COARSE) * 0x100) + value;
- qobject_cast(parent())->dmxInput(i.layer, j, value);
- m_dmx[i.layer][ENTRY_POINT_COARSE] = buffer.Get(i.address + ENTRY_POINT_COARSE);
- entrySent = true;
- break;
case ENTRY_POINT_COARSE:
- if (entrySent)
- break;
value = (value * 0x100) + buffer.Get(i.address + ENTRY_POINT_FINE);
- qobject_cast(parent())->dmxInput(i.layer, j, value);
- m_dmx[i.layer][ENTRY_POINT_FINE] = buffer.Get(i.address + ENTRY_POINT_FINE);
+ emit dmxOutput(i.layer,j,value);
entrySent = true;
break;
+ case VOLUME_FINE:
+ if (volSent == false)
+ {
+ value = (buffer.Get(i.address + VOLUME_COARSE) * 0x100) + value;
+ emit dmxOutput(i.layer,j,value);
+ }
+ break;
+ case ENTRY_POINT_FINE:
+ if (entrySent == false)
+ {
+ value = (buffer.Get(i.address + ENTRY_POINT_COARSE) * 0x100) + value;
+ emit dmxOutput(i.layer,j,value);
+ }
+ break;
default:
- qobject_cast(parent())->dmxInput(i.layer, j, value);
+ emit dmxOutput(i.layer,j,value);
break;
}
}
@@ -149,7 +127,7 @@ bool olaThread::CheckDataLoss() {
void olaThread::socketClosed()
{
- qWarning("ola daemon closed connection, reopening it... ");
+ qWarning("ola closed connection. Try reopening it... ");
m_clientWrapper->GetSelectServer()->Terminate();
m_client = NULL;
m_clientWrapper = NULL;
diff --git a/src/olathread.h b/src/olathread.h
index ed2735a..91d78b6 100644
--- a/src/olathread.h
+++ b/src/olathread.h
@@ -20,17 +20,10 @@ class olaThread : public QThread
Q_OBJECT
public:
- QList m_dmxSettings;
- int m_dmx[MAX_LAYERS][LAYER_CHANNELS];
- ola::client::OlaClientWrapper *m_clientWrapper;
- ola::client::OlaClient *m_client;
- unsigned int m_counter;
- struct timeval m_last_data; // Last DMX frame received
- int m_layers;
olaThread(QObject *parent = 0, int layers = 0);
virtual ~olaThread();
- void run ();
+
/** Retorna el valor de un canal
*@param int layer the layer for we want the channel
*@param int channel the channel for the value wanted
@@ -42,6 +35,14 @@ public:
void resendDmx();
private:
+ void run ();
+ ola::client::OlaClientWrapper *m_clientWrapper;
+ ola::client::OlaClient *m_client;
+ unsigned int m_counter;
+ 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
* typedef SingleUseCallback1 ola::client::SetCallback
@@ -52,7 +53,7 @@ private:
if (error.Success()) {
qDebug("Register Universe success");
} else {
- qCritical("Register command failed: %s", error.Error().c_str());
+ qWarning("Register command failed: %s", error.Error().c_str());
}
}
/**
@@ -66,7 +67,7 @@ private:
* This is called one for second if there is not updated in the DMX frame.
* emit only the channels that has been changed.
*/
- void NewDmx(const ola::client::DMXMetadata &dmx_meta, const ola::DmxBuffer &buffer);
+ void NewDmx(const ola::client::DMXMetadata &dmx_meta, const ola::DmxBuffer &buffer); //
/**
* @brief Sometimes the ola server closes the connection. This is a callback to handle this event an reconect to ola
*/
diff --git a/src/settings.cpp b/src/settings.cpp
index 9d06394..f664bb0 100644
--- a/src/settings.cpp
+++ b/src/settings.cpp
@@ -15,7 +15,6 @@ Settings::Settings(QObject *parent) :
QObject(parent)
{
m_layersNumber = 0;
- m_ui = false;
}
// Read the dmx settings for dmx.xml At the moment we need:
@@ -24,7 +23,6 @@ Settings::Settings(QObject *parent) :
// - The first DMX channel of each source/layer
// - The universe to bind in OLA
// - Audio device id
-// - Show the Ui or not
void Settings::readFromFile(QString file) {
QFile* xmlFile = new QFile(file);
if (!xmlFile->open(QIODevice::ReadOnly | QIODevice::Text)) {
@@ -36,56 +34,53 @@ void Settings::readFromFile(QString file) {
exit(1);
}
QXmlStreamReader* xmlReader = new QXmlStreamReader(xmlFile);
- while(!xmlReader->atEnd() && !xmlReader->hasError()) {
+ int counter = 0;
+ //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();
+ //If token is just StartDocument - go to next
if(token == QXmlStreamReader::StartDocument) {
continue;
}
+ //If token is StartElement - read it
if(token == QXmlStreamReader::StartElement) {
- if(xmlReader->name() == "lmsAudio") {
- m_ui = xmlReader->attributes().value("ui").toLocal8Bit().toInt();
- m_layersNumber = xmlReader->attributes().value("layersNumber").toLocal8Bit().toInt();
- m_pathmedia = xmlReader->attributes().value("path").toLocal8Bit();
- continue;
+ if(xmlReader->name() == "dmxSettings") {
+ int version = xmlReader->attributes().value("fileVersion").toLocal8Bit().toInt();
+ if(version == 1) {
+ m_layersNumber = xmlReader->attributes().value("layersNumber").toLocal8Bit().toInt();
+ m_pathmedia = xmlReader->attributes().value("path").toLocal8Bit();
+ continue;
+ }
}
if(xmlReader->name() == "audioDevice") {
- m_audioDeviceQty = xmlReader->attributes().value("devicesNumber").toLocal8Bit().toInt();
- for (uint i = 0; i < m_audioDeviceQty; i++)
- {
- m_audioDeviceId[i] = xmlReader->attributes().value(QString("id%1").arg(i)).toLocal8Bit().toInt();
- }
-
+ m_audioDeviceId = xmlReader->attributes().value("id").toLocal8Bit().toInt();
+ continue;
}
- if(xmlReader->name() == "layer") {
+ QString add = "layer";
+ add.append(QString("%1").arg(counter));
+ if((xmlReader->name() == add)) {
dmxSetting temp;
temp.address = xmlReader->attributes().value("dmx").toLocal8Bit().toInt() - 1;
temp.universe = xmlReader->attributes().value("universe").toLocal8Bit().toInt();
- temp.layer = xmlReader->attributes().value("id").toLocal8Bit().toInt();
+ temp.layer = counter;
m_settings.append(temp);
if (!m_universe.contains(temp.universe)) {
m_universe.insert(temp.universe);
}
+ counter++;
}
}
}
if(xmlReader->hasError()) {
QMessageBox::critical(NULL,"File xml Parse Error ", xmlReader->errorString(), QMessageBox::Ok);
qWarning("File xml Parse Error %s", xmlReader->errorString().toLatin1().constData());
- // ToDo: manage this, open a dialog to load a new file.
+ return;
}
xmlReader->clear();
xmlFile->close();
delete xmlReader;
delete xmlFile;
- this->printSettings();
-}
-
-void Settings::printSettings() {
- qInfo() << "Settings readed:\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 internal id:" << i << "system 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() {
diff --git a/src/settings.h b/src/settings.h
index f27da6a..8cd55bb 100644
--- a/src/settings.h
+++ b/src/settings.h
@@ -5,7 +5,6 @@
#include
#include
#include
-#include
#include "medialibrary.h"
#include "audiowidget.h"
@@ -16,27 +15,25 @@ class Settings : public QObject
Q_OBJECT
public:
- Settings(QObject *parent = 0);
static Settings *getInstance();
inline QSet getUniverses() { return m_universe; }
inline QString getPathMedia() { return m_pathmedia; }
inline QList getDmxSettings() { return m_settings; }
inline int getLayersNumber() { return m_layersNumber; }
- inline int getAudioDeviceId() { return m_audioDeviceId[0]; }
- inline bool getShowUi() { return m_ui; }
void readFile();
- void readFromFile(QString file);
- void printSettings();
+ inline int getAudioDeviceId() { return m_audioDeviceId; }
private:
static Settings *_instance;
QList m_settings;
QString m_pathmedia;
- uint m_audioDeviceId[MAX_AUDIODEVICES];
- uint m_audioDeviceQty;
+ uint m_audioDeviceId;
QSet m_universe;
int m_layersNumber;
- bool m_ui;
+
+ explicit Settings(QObject *parent = 0);
+ void readFromFile(QString file);
+
};
#endif // SETTINGS_H
diff --git a/src/slidergroup.cpp b/src/slidergroup.cpp
index 9ef9680..e80a03f 100644
--- a/src/slidergroup.cpp
+++ b/src/slidergroup.cpp
@@ -1,81 +1,45 @@
#include "slidergroup.h"
-#include
-SliderGroup::SliderGroup(QString name,
+
+SliderGroup::SliderGroup(const QString &title, \
int min,
int max,
int decimals,
QWidget *parent)
- : QWidget(parent)
+ : QGroupBox(title, parent)
{
- QVBoxLayout *layout = new QVBoxLayout;
- layout->setAlignment(Qt::AlignHCenter);
- layout->setContentsMargins(0, 0, 0, 0);
- //this->setMaximumWidth(40);
+ this->setFlat(true);
+ this->setTitle(title);
slider = new QSlider(Qt::Orientation::Vertical);
slider->setFocusPolicy(Qt::StrongFocus);
slider->setTickPosition(QSlider::TicksBothSides);
slider->setTickInterval((max - min) / 11);
- slider->setMinimumHeight(0);
slider->setSingleStep(1);
slider->setRange(min, max);
- slider->setValue(0);
- slider->setMinimumWidth(50);
- slider->setToolTip(name);
- slider->setStyleSheet("QSlider {"
- "border: 1px solid #5a4855;"
- "margin: 0px;"
- "height: 200px;"
- "width: 50px;}"
- );
- slider->setContentsMargins(0, 0, 0, 0);
valueBox = new QDoubleSpinBox();
valueBox->setFocusPolicy(Qt::NoFocus);
valueBox->setButtonSymbols(QAbstractSpinBox::NoButtons);
- valueBox->setMinimumWidth(50);
+ valueBox->setMaximumWidth(45);
valueBox->setRange(min, max);
- valueBox->setValue(0);
valueBox->setDecimals(decimals);
- valueBox->setObjectName(name);
- valueBox->setToolTip(name);
- valueBox->setAlignment(Qt::AlignHCenter);
- valueBox->setContentsMargins(0, 0, 0, 0);
connect(slider, SIGNAL(valueChanged(int)), this, SLOT(sliderValueChanged(int)));
- //connect(slider, SIGNAL(mousePressEvent(QMouseEvent)), this, SLOT(mousePressEvent(QMouseEvent *)));
- layout->addWidget(slider);
- layout->addWidget(valueBox);
- this->setStyleSheet("border: 1px solid #5a4855;"
- "width: 50px;"
- "margin: 0px;"
- "background-color: #383034;"
- );
- layout->setSpacing(0);
- layout->setContentsMargins(0, 0, 0, 0);
- this->setLayout(layout);
+ QVBoxLayout *slidersLayout = new QVBoxLayout();
+ slidersLayout->addWidget(valueBox);
+ slidersLayout->addWidget(slider);
+ setLayout(slidersLayout);
}
void SliderGroup::sliderValueChanged(int value)
{
- valueBox->blockSignals(true);
- valueBox->setValue(value);
- valueBox->blockSignals(false);
+ if (valueBox->decimals() > 1)
+ value /= 100.0f;
emit valueChanged(value);
+ valueBox->setValue(value);
};
void SliderGroup::setValue(float value)
{
- slider->blockSignals(true);
- valueBox->blockSignals(true);
- if (int(value) != slider->value())
- slider->setValue(value);
+ if (valueBox->decimals() > 1)
+ value *= 100.0f;
+ slider->setValue(value);
valueBox->setValue(value);
- slider->blockSignals(false);
- valueBox->blockSignals(false);
-}
-
-void SliderGroup::mousePressEvent(QMouseEvent* event) {
- Q_UNUSED(event);
- if (slider->isEnabled())
- slider->setDisabled(true);
- else
- slider->setDisabled(false);
}
diff --git a/src/slidergroup.h b/src/slidergroup.h
index 5bfeeb8..f5bae60 100644
--- a/src/slidergroup.h
+++ b/src/slidergroup.h
@@ -6,19 +6,19 @@
#include
#include
-class SliderGroup : public QWidget
+class SliderGroup : public QGroupBox
{
Q_OBJECT
public:
- SliderGroup(QString name,
- int min,
- int max,
- int decimals,
- QWidget *parent = nullptr);
+ SliderGroup(const QString &title,
+ int min,
+ int max,
+ int decimals,
+ QWidget *parent = nullptr);
signals:
- void valueChanged(int value);
+ void valueChanged(float value);
public slots:
void setValue(float value);
@@ -27,8 +27,6 @@ public slots:
private:
QSlider *slider;
QDoubleSpinBox *valueBox;
-
- void mousePressEvent(QMouseEvent* event);
};
#endif