refactorizada la GUI, ola y audioengine se ejecutan fuera de widgets.
Opción para ejecutar sin mostrar la GUI. Los controles de la interfaz no son reactivos, no están conectados a las órdenes de audio. cambio en la personalidad dmx para procesar los canales en mejor orden. evita mandar dos veces los canales dobles por cada dmx frame, incluyendo file/folder.
This commit is contained in:
parent
4ee82c5e5f
commit
1fccbf64fd
20 changed files with 416 additions and 323 deletions
|
@ -3,6 +3,8 @@ TARGET = libremediaserver-audio
|
||||||
QT += webkitwidgets widgets
|
QT += webkitwidgets widgets
|
||||||
HEADERS += src/libremediaserver-audio.h \
|
HEADERS += src/libremediaserver-audio.h \
|
||||||
src/dmxwidget.h \
|
src/dmxwidget.h \
|
||||||
|
src/libremediaserver-audio-gui.h \
|
||||||
|
src/main.h \
|
||||||
src/miniaudio.h \
|
src/miniaudio.h \
|
||||||
src/medialibrary.h \
|
src/medialibrary.h \
|
||||||
src/miniaudioengine.h \
|
src/miniaudioengine.h \
|
||||||
|
@ -15,6 +17,7 @@ HEADERS += src/libremediaserver-audio.h \
|
||||||
src/slidergroup.h
|
src/slidergroup.h
|
||||||
SOURCES += src/main.cpp \
|
SOURCES += src/main.cpp \
|
||||||
src/dmxwidget.cpp \
|
src/dmxwidget.cpp \
|
||||||
|
src/libremediaserver-audio-gui.cpp \
|
||||||
src/miniaudio.c \
|
src/miniaudio.c \
|
||||||
src/libremediaserver-audio.cpp \
|
src/libremediaserver-audio.cpp \
|
||||||
src/medialibrary.cpp \
|
src/medialibrary.cpp \
|
||||||
|
@ -24,7 +27,7 @@ SOURCES += src/main.cpp \
|
||||||
src/audiowidget.cpp \
|
src/audiowidget.cpp \
|
||||||
src/settings.cpp \
|
src/settings.cpp \
|
||||||
src/slidergroup.cpp
|
src/slidergroup.cpp
|
||||||
FORMS += src/libremediaserver-audio.ui
|
FORMS += src/libremediaserver-audio-gui.ui
|
||||||
CCFLAG += -msse2 -mavx2 #-fsanitize=address -g -O0
|
CCFLAG += -msse2 -mavx2 #-fsanitize=address -g -O0
|
||||||
QMAKE_CXXFLAGS += $$(CXXFLAG)
|
QMAKE_CXXFLAGS += $$(CXXFLAG)
|
||||||
#QMAKE_CXXFLAGS += -fsanitize=address -g -O0
|
#QMAKE_CXXFLAGS += -fsanitize=address -g -O0
|
||||||
|
|
|
@ -1,64 +1,67 @@
|
||||||
#include "audiolayerwidget.h"
|
#include "audiolayerwidget.h"
|
||||||
|
#include <QComboBox>
|
||||||
|
|
||||||
|
AudioLayerWidget::AudioLayerWidget(QWidget *parent, int layer):
|
||||||
AudioLayerWidget::AudioLayerWidget(QWidget *parent, QString name, int layer):
|
QWidget(parent)
|
||||||
QGroupBox(parent)
|
|
||||||
, m_layer(layer)
|
, m_layer(layer)
|
||||||
, m_suspendResumeButton(0)
|
, m_suspendResumeButton(0)
|
||||||
{
|
{
|
||||||
this->setTitle(name);
|
|
||||||
QVBoxLayout *layout = new QVBoxLayout;
|
QVBoxLayout *layout = new QVBoxLayout;
|
||||||
|
|
||||||
QHBoxLayout *progressTime = new QHBoxLayout;
|
m_suspendResumeButton = new QPushButton(this);
|
||||||
|
m_suspendResumeButton->setText(StatusStr[Status::Iddle]);
|
||||||
|
m_suspendResumeButton->setMaximumWidth(200);
|
||||||
|
//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");
|
||||||
|
m_progress->setMaximumWidth(200);
|
||||||
|
layout->addWidget(m_progress);
|
||||||
|
|
||||||
m_progressTime = new QTimeEdit;
|
m_progressTime = new QTimeEdit;
|
||||||
m_progressTime->text();
|
m_progressTime->setToolTip("Current Time");
|
||||||
|
m_progressTime->setObjectName("Current Time");
|
||||||
m_progressTime->setDisplayFormat("h:mm:ss:zzz");
|
m_progressTime->setDisplayFormat("h:mm:ss:zzz");
|
||||||
m_progressTime->setReadOnly(true);
|
m_progressTime->setReadOnly(true);
|
||||||
m_progressTime->setButtonSymbols(QAbstractSpinBox::NoButtons);
|
m_progressTime->setButtonSymbols(QAbstractSpinBox::NoButtons);
|
||||||
m_progressTime->setMaximumWidth(90);
|
m_progressTime->setMaximumWidth(88);
|
||||||
m_progressTime->setFocusPolicy(Qt::NoFocus);
|
m_progressTime->setFocusPolicy(Qt::NoFocus);
|
||||||
progressTime->addWidget(m_progressTime);
|
|
||||||
m_totalTimeValue = new QTimeEdit;
|
m_totalTimeValue = new QTimeEdit;
|
||||||
|
m_totalTimeValue->setObjectName("Track Length");
|
||||||
|
m_totalTimeValue->setToolTip("Track Length");
|
||||||
m_totalTimeValue->setDisplayFormat("h:mm:ss:zzz");
|
m_totalTimeValue->setDisplayFormat("h:mm:ss:zzz");
|
||||||
m_totalTimeValue->setReadOnly(true);
|
m_totalTimeValue->setReadOnly(true);
|
||||||
m_totalTimeValue->setButtonSymbols(QAbstractSpinBox::NoButtons);
|
m_totalTimeValue->setButtonSymbols(QAbstractSpinBox::NoButtons);
|
||||||
m_totalTimeValue->setMaximumWidth(90);
|
m_totalTimeValue->setMaximumWidth(88);
|
||||||
m_totalTimeValue->setFocusPolicy(Qt::NoFocus);
|
m_totalTimeValue->setFocusPolicy(Qt::NoFocus);
|
||||||
progressTime->addWidget(m_totalTimeValue);
|
QHBoxLayout *status = new QHBoxLayout;
|
||||||
layout->addLayout(progressTime);
|
status->addWidget(m_progressTime);
|
||||||
|
status->addWidget(m_totalTimeValue);
|
||||||
m_progressSlider = new QSlider(Qt::Horizontal);
|
layout->addLayout(status);
|
||||||
m_progressSlider->setFocusPolicy(Qt::NoFocus);
|
QVBoxLayout *playback = new QVBoxLayout;
|
||||||
layout->addWidget(m_progressSlider);
|
|
||||||
|
|
||||||
QGridLayout *status = new QGridLayout;
|
|
||||||
m_statusValue = new QLabel;
|
|
||||||
status->addWidget(m_statusValue, 0, 0);
|
|
||||||
m_folderValue = new QLabel;
|
m_folderValue = new QLabel;
|
||||||
m_folderValue->setMaximumWidth(200);
|
m_folderValue->setMaximumWidth(200);
|
||||||
status->addWidget(m_folderValue, 1, 0);
|
playback->addWidget(m_folderValue);
|
||||||
m_fileValue = new QLabel;
|
m_fileValue = new QLabel;
|
||||||
m_fileValue->setMaximumWidth(200);
|
m_fileValue->setMaximumWidth(200);
|
||||||
status->addWidget(m_fileValue, 2, 0);
|
playback->addWidget(m_fileValue);
|
||||||
layout->addLayout(status);
|
layout->addLayout(playback);
|
||||||
|
|
||||||
QHBoxLayout *volumeBox = new QHBoxLayout;
|
QHBoxLayout *volumeBox = new QHBoxLayout;
|
||||||
m_volume = new SliderGroup("Vol", 0 , 100, 2, NULL);
|
m_volume = new SliderGroup(0 , 100, 2, NULL);
|
||||||
volumeBox->addWidget(m_volume);
|
volumeBox->addWidget(m_volume);
|
||||||
connect(m_volume, SIGNAL(valueChanged(float)), this, SLOT(volumeChanged(float)));
|
connect(m_volume, SIGNAL(valueChanged(float)), this, SLOT(volumeChanged(float)));
|
||||||
m_pan = new SliderGroup("Pan", 0 , 255, 0, NULL);
|
m_pan = new SliderGroup(0 , 255, 0, NULL);
|
||||||
volumeBox->addWidget(m_pan);
|
volumeBox->addWidget(m_pan);
|
||||||
connect(m_pan, SIGNAL(valueChanged(float)), this, SLOT(panChanged(float)));
|
connect(m_pan, SIGNAL(valueChanged(float)), this, SLOT(panChanged(float)));
|
||||||
m_pitch = new SliderGroup("Pitch", 0 , 255, 0, NULL);
|
m_pitch = new SliderGroup(0 , 255, 0, NULL);
|
||||||
volumeBox->addWidget(m_pitch);
|
volumeBox->addWidget(m_pitch);
|
||||||
connect(m_pitch, SIGNAL(valueChanged(float)), this, SLOT(pitchChanged(float)));
|
connect(m_pitch, SIGNAL(valueChanged(float)), this, SLOT(pitchChanged(float)));
|
||||||
layout->addLayout(volumeBox);
|
layout->addLayout(volumeBox);
|
||||||
|
|
||||||
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);
|
this->setLayout(layout);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -95,6 +98,7 @@ void AudioLayerWidget::toggleSuspendResume()
|
||||||
case Status::Stopped:
|
case Status::Stopped:
|
||||||
this->setPlaybackStatus(Status::PlayingOnce);
|
this->setPlaybackStatus(Status::PlayingOnce);
|
||||||
emit uiPlaybackChanged(m_layer, Status::PlayingOnce);
|
emit uiPlaybackChanged(m_layer, Status::PlayingOnce);
|
||||||
|
case Status::Iddle:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -129,43 +133,40 @@ void AudioLayerWidget::fileLoaded(QString file)
|
||||||
m_folderValue->setText(list.at(size - 2));
|
m_folderValue->setText(list.at(size - 2));
|
||||||
m_fileValue->setText(list.at(size - 1));
|
m_fileValue->setText(list.at(size - 1));
|
||||||
}
|
}
|
||||||
|
this->setPlaybackStatus(Status::Stopped);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioLayerWidget::setPlaybackStatus(Status status)
|
void AudioLayerWidget::setPlaybackStatus(Status status)
|
||||||
{
|
{
|
||||||
m_status = status;
|
m_status = status;
|
||||||
if (status == Status::Stopped)
|
if (status == Status::Stopped)
|
||||||
m_progressTime->setTime(QTime::fromMSecsSinceStartOfDay(0));
|
m_progress->setValue(0);
|
||||||
m_statusValue->blockSignals(true);
|
|
||||||
m_suspendResumeButton->blockSignals(true);
|
m_suspendResumeButton->blockSignals(true);
|
||||||
m_statusValue->setText(StatusStr[status]);
|
|
||||||
m_suspendResumeButton->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);
|
m_suspendResumeButton->blockSignals(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioLayerWidget::durationChanged(float dur)
|
void AudioLayerWidget::durationChanged(float dur)
|
||||||
{
|
{
|
||||||
dur *= 1000;
|
m_progress->blockSignals(true);
|
||||||
m_progressSlider->setMaximum(dur);
|
m_progressTime->blockSignals(true);
|
||||||
|
m_totalTimeValue->blockSignals(true);
|
||||||
|
m_progress->setRange(0, dur);
|
||||||
|
m_progress->setValue(0);
|
||||||
|
m_progressTime->setTime(QTime::fromMSecsSinceStartOfDay(0));
|
||||||
m_totalTimeValue->setTime(QTime::fromMSecsSinceStartOfDay(dur));
|
m_totalTimeValue->setTime(QTime::fromMSecsSinceStartOfDay(dur));
|
||||||
|
m_progress->blockSignals(false);
|
||||||
|
m_progressTime->blockSignals(false);
|
||||||
|
m_totalTimeValue->blockSignals(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioLayerWidget::refreshUi(float progress)
|
void AudioLayerWidget::refreshUi(float progress)
|
||||||
{
|
{
|
||||||
progress *= 1000;
|
progress *= 1000;
|
||||||
m_progressSlider->setValue(progress);
|
m_progress->blockSignals(true);
|
||||||
|
m_progressTime->blockSignals(true);
|
||||||
|
m_progress->setValue(progress);
|
||||||
m_progressTime->setTime(QTime::fromMSecsSinceStartOfDay(progress));
|
m_progressTime->setTime(QTime::fromMSecsSinceStartOfDay(progress));
|
||||||
|
m_progress->blockSignals(false);
|
||||||
|
m_progressTime->blockSignals(false);
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,16 +4,17 @@
|
||||||
#include <QPushButton>
|
#include <QPushButton>
|
||||||
#include <QTimeEdit>
|
#include <QTimeEdit>
|
||||||
#include <QLabel>
|
#include <QLabel>
|
||||||
|
#include <QProgressBar>
|
||||||
|
|
||||||
#include "defines.h"
|
#include "defines.h"
|
||||||
#include "slidergroup.h"
|
#include "slidergroup.h"
|
||||||
|
|
||||||
class AudioLayerWidget : public QGroupBox
|
class AudioLayerWidget : public QWidget
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit AudioLayerWidget(QWidget *parent = 0, QString name = "Layer", int layer = 0);
|
explicit AudioLayerWidget(QWidget *parent = 0, int layer = 0);
|
||||||
~AudioLayerWidget();
|
~AudioLayerWidget();
|
||||||
void setVol(float vol);
|
void setVol(float vol);
|
||||||
void resume();
|
void resume();
|
||||||
|
@ -27,15 +28,14 @@ private:
|
||||||
Status m_status;
|
Status m_status;
|
||||||
int m_layer;
|
int m_layer;
|
||||||
QPushButton *m_suspendResumeButton;
|
QPushButton *m_suspendResumeButton;
|
||||||
QLabel * m_statusValue;
|
|
||||||
QLabel *m_fileValue;
|
QLabel *m_fileValue;
|
||||||
QLabel * m_folderValue;
|
QLabel * m_folderValue;
|
||||||
SliderGroup *m_volume;
|
SliderGroup *m_volume;
|
||||||
SliderGroup *m_pan;
|
SliderGroup *m_pan;
|
||||||
SliderGroup *m_pitch;
|
SliderGroup *m_pitch;
|
||||||
QSlider *m_progressSlider;
|
|
||||||
QTimeEdit *m_progressTime;
|
QTimeEdit *m_progressTime;
|
||||||
QTimeEdit *m_totalTimeValue;
|
QTimeEdit *m_totalTimeValue;
|
||||||
|
QProgressBar *m_progress;
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void toggleSuspendResume();
|
void toggleSuspendResume();
|
||||||
|
|
|
@ -3,119 +3,66 @@
|
||||||
|
|
||||||
AudioWidget::AudioWidget() :
|
AudioWidget::AudioWidget() :
|
||||||
m_layout(new QHBoxLayout())
|
m_layout(new QHBoxLayout())
|
||||||
, m_refreshUi(new QTimer(this))
|
|
||||||
{
|
{
|
||||||
for (int i= 0; i < Settings::getInstance()->getLayersNumber(); i++ ) {
|
for (int i= 0; i < Settings::getInstance()->getLayersNumber(); i++ ) {
|
||||||
AudioLayerWidget *alw = new AudioLayerWidget(this, tr("Layer %1").arg(i + 1), i);
|
AudioLayerWidget *alw = new AudioLayerWidget(this, i);
|
||||||
m_layout->insertWidget(i, alw);
|
m_layout->insertWidget(i, alw);
|
||||||
connect(alw, SIGNAL(uiSliderChanged(int, Slider, int)), this, SLOT(uiSliderAction(int, Slider, int)));
|
connect(alw, SIGNAL(uiSliderChanged(int, Slider, int)), this, SLOT(uiSliderAction(int, Slider, int)));
|
||||||
connect(alw, SIGNAL(uiPlaybackChanged(int, Status)), this, SLOT(uiChangePlaybackStatus(int, Status)));
|
connect(alw, SIGNAL(uiPlaybackChanged(int, Status)), this, SLOT(uiChangePlaybackStatus(int, Status)));
|
||||||
}
|
}
|
||||||
setLayout(m_layout);
|
setLayout(m_layout);
|
||||||
connect(m_refreshUi, SIGNAL(timeout()), this, SLOT(refreshUi()));
|
|
||||||
m_refreshUi->start(UI_REFRESH_TIME);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AudioWidget::startEngine(int id)
|
void AudioWidget::mediaLoaded(int layer, QString file, float duration)
|
||||||
{
|
{
|
||||||
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);
|
QLayoutItem * const item = m_layout->itemAt(layer);
|
||||||
dynamic_cast<AudioLayerWidget *>(item->widget())->fileLoaded(file);
|
dynamic_cast<AudioLayerWidget *>(item->widget())->fileLoaded(file);
|
||||||
dynamic_cast<AudioLayerWidget *>(item->widget())->durationChanged(pLength);
|
dynamic_cast<AudioLayerWidget *>(item->widget())->durationChanged(duration);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioWidget::volChanged(int layer, float vol) {
|
void AudioWidget::volChanged(int layer, float vol) {
|
||||||
m_mae.volChanged(layer, vol);
|
|
||||||
QLayoutItem * const item = m_layout->itemAt(layer);
|
QLayoutItem * const item = m_layout->itemAt(layer);
|
||||||
dynamic_cast<AudioLayerWidget *>(item->widget())->setVol(vol);
|
dynamic_cast<AudioLayerWidget *>(item->widget())->setVol(vol);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioWidget::panChanged(int layer, int pan) {
|
void AudioWidget::panChanged(int layer, int pan) {
|
||||||
m_mae.panChanged(layer, pan);
|
|
||||||
QLayoutItem * const item = m_layout->itemAt(layer);
|
QLayoutItem * const item = m_layout->itemAt(layer);
|
||||||
dynamic_cast<AudioLayerWidget *>(item->widget())->setPan(pan);
|
dynamic_cast<AudioLayerWidget *>(item->widget())->setPan(pan);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioWidget::pitchChanged(int layer, int pitch) {
|
void AudioWidget::pitchChanged(int layer, int pitch) {
|
||||||
m_mae.pitchChanged(layer, pitch);
|
|
||||||
QLayoutItem * const item = m_layout->itemAt(layer);
|
QLayoutItem * const item = m_layout->itemAt(layer);
|
||||||
dynamic_cast<AudioLayerWidget *>(item->widget())->setPitch(pitch);
|
dynamic_cast<AudioLayerWidget *>(item->widget())->setPitch(pitch);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioWidget::playbackChanged(int layer, Status status)
|
void AudioWidget::playbackChanged(int layer, Status status)
|
||||||
{
|
{
|
||||||
m_mae.playbackChanged(layer, status);
|
|
||||||
QLayoutItem * const item = m_layout->itemAt(layer);
|
QLayoutItem * const item = m_layout->itemAt(layer);
|
||||||
dynamic_cast<AudioLayerWidget *>(item->widget())->setPlaybackStatus(status);
|
dynamic_cast<AudioLayerWidget *>(item->widget())->setPlaybackStatus(status);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioWidget::entryPointChanged(int layer, int cursor)
|
void AudioWidget::cursorChanged(int layer, float cursor)
|
||||||
{
|
{
|
||||||
m_mae.setCursor(layer, cursor);
|
|
||||||
QLayoutItem * const item = m_layout->itemAt(layer);
|
QLayoutItem * const item = m_layout->itemAt(layer);
|
||||||
AudioLayerWidget *aw = dynamic_cast<AudioLayerWidget *>(item->widget());
|
AudioLayerWidget *alw = dynamic_cast<AudioLayerWidget *>(item->widget());
|
||||||
aw->refreshUi(m_mae.getCursor(layer));
|
alw->refreshUi(cursor);
|
||||||
}
|
|
||||||
|
|
||||||
void AudioWidget::refreshUi() {
|
|
||||||
for (int i= 0; i < Settings::getInstance()->getLayersNumber(); i++ ) {
|
|
||||||
QLayoutItem * const item = m_layout->itemAt(i);
|
|
||||||
AudioLayerWidget *aw = dynamic_cast<AudioLayerWidget *>(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)
|
void AudioWidget::uiSliderAction(int layer, Slider s, int value)
|
||||||
{
|
{
|
||||||
switch (s){
|
switch (s){
|
||||||
case Slider::Volume:
|
case Slider::Volume:
|
||||||
m_mae.volChanged(layer, value);
|
emit uiVolChanged(layer, value);
|
||||||
break;
|
break;
|
||||||
case Slider::Pan:
|
case Slider::Pan:
|
||||||
m_mae.panChanged(layer, value);
|
emit uiPanChanged(layer, value);
|
||||||
break;
|
break;
|
||||||
case Slider::Pitch:
|
case Slider::Pitch:
|
||||||
m_mae.pitchChanged(layer, value);
|
emit uiPitchChanged(layer, value);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioWidget::uiChangePlaybackStatus(int layer, Status s) {
|
void AudioWidget::uiChangePlaybackStatus(int layer, Status s) {
|
||||||
m_mae.playbackChanged(layer, s);
|
emit uiPlaybackChanged(layer, s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,28 +14,25 @@ class AudioWidget : public QWidget
|
||||||
|
|
||||||
public:
|
public:
|
||||||
AudioWidget();
|
AudioWidget();
|
||||||
bool startEngine();
|
void mediaLoaded(int layer, QString media, float duration);
|
||||||
bool startEngine(int id);
|
|
||||||
void stopEngine();
|
|
||||||
void mediaLoaded(int layer, QString media );
|
|
||||||
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 playbackChanged(int layer, Status status);
|
||||||
void entryPointChanged(int layer, int cursor);
|
void cursorChanged(int layer, float cursor);
|
||||||
|
|
||||||
private:
|
|
||||||
MiniAudioEngine m_mae;
|
|
||||||
QString m_currentMedia[MAX_LAYERS];
|
|
||||||
QHBoxLayout *m_layout;
|
QHBoxLayout *m_layout;
|
||||||
QTimer *m_refreshUi;
|
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void uiSliderAction(int layer, Slider s, int value);
|
void uiSliderAction(int layer, Slider s, int value);
|
||||||
void uiChangePlaybackStatus(int layer, Status s);
|
void uiChangePlaybackStatus(int layer, Status s);
|
||||||
|
|
||||||
private slots:
|
signals:
|
||||||
void refreshUi();
|
void uiMediaLoaded(int layer, QString media );
|
||||||
|
void uiVolChanged(int layer, float vol);
|
||||||
|
void uiPanChanged(int layer, int pan);
|
||||||
|
void uiPitchChanged(int layer, int pitch);
|
||||||
|
void uiPlaybackChanged(int layer, Status status);
|
||||||
|
void uiEntryPointChanged(int layer, int cursor);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // AUDIOWIDGET_H
|
#endif // AUDIOWIDGET_H
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
#ifndef DEFINES_H
|
#ifndef DEFINES_H
|
||||||
#define 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 <lms@criptomart.net>"
|
#define COPYRIGHT "(C) 2014-2024 Santi Noreña <lms@criptomart.net>"
|
||||||
#define LICENSE "GPL 3 Licensed. See LICENSE.txt.\nSound guys are not allowed to use this software."
|
#define LICENSE "GPL 3 Licensed. See LICENSE.txt.\nSound guys are not allowed to use this software."
|
||||||
#define DEFAULT_FILE "lms-audio.xlm"
|
#define DEFAULT_FILE "lms-audio.xlm"
|
||||||
|
@ -22,6 +21,7 @@ enum Status
|
||||||
Paused,
|
Paused,
|
||||||
PlayingOnce,
|
PlayingOnce,
|
||||||
PlayingLoop,
|
PlayingLoop,
|
||||||
|
Iddle
|
||||||
};
|
};
|
||||||
|
|
||||||
static const char* StatusStr[] =
|
static const char* StatusStr[] =
|
||||||
|
@ -30,6 +30,7 @@ static const char* StatusStr[] =
|
||||||
"Pause",
|
"Pause",
|
||||||
"Playing One",
|
"Playing One",
|
||||||
"Playing Loop",
|
"Playing Loop",
|
||||||
|
"Iddle",
|
||||||
0x0
|
0x0
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,39 +1,16 @@
|
||||||
#ifndef DMXPERSONALITY_H
|
#ifndef DMXPERSONALITY_H
|
||||||
#define DMXPERSONALITY_H
|
#define DMXPERSONALITY_H
|
||||||
|
|
||||||
/** Define the DMX personality to avoid dealing with
|
#define VOLUME_COARSE 3
|
||||||
* numbers and change it easyly in case
|
#define PAN 6
|
||||||
*
|
#define DMX_FOLDER 0
|
||||||
1 - Volumen Coarse
|
#define DMX_FILE 1
|
||||||
2 - Pan
|
#define PLAYBACK 8
|
||||||
3 - Folder
|
#define VOLUME_FINE 2
|
||||||
4 - File
|
#define ENTRY_POINT_COARSE 5
|
||||||
5 - Playback
|
#define ENTRY_POINT_FINE 4
|
||||||
0-24 : Play once.
|
#define PITCH 7
|
||||||
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
|
#define LAYER_CHANNELS 9
|
||||||
// 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
|
#endif // DMXPERSONALITY_H
|
||||||
|
|
48
src/libremediaserver-audio-gui.cpp
Normal file
48
src/libremediaserver-audio-gui.cpp
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
/*
|
||||||
|
|
||||||
|
Libre Media Server Audio - An Open source Media Server for arts and performing.
|
||||||
|
(c) Criptomart - Santiago Noreña 2012-2024 <lms@criptomart.net>
|
||||||
|
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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "libremediaserver-audio-gui.h"
|
||||||
|
|
||||||
|
|
||||||
|
libreMediaServerAudioUi::libreMediaServerAudioUi(QWidget *parent)
|
||||||
|
: QMainWindow(parent)
|
||||||
|
{
|
||||||
|
ui.setupUi(this);
|
||||||
|
this->setWindowTitle(VERSION);
|
||||||
|
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);
|
||||||
|
connect(ui.actionLaunch_OLA_Setup, SIGNAL(triggered()), this, SLOT(olasetup()));
|
||||||
|
}
|
||||||
|
|
||||||
|
libreMediaServerAudioUi::~libreMediaServerAudioUi()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void libreMediaServerAudioUi::olasetup()
|
||||||
|
{
|
||||||
|
QWebView *view = new QWebView();
|
||||||
|
view->load(QUrl("http://localhost:9090/ola.html"));
|
||||||
|
view->show();
|
||||||
|
}
|
48
src/libremediaserver-audio-gui.h
Normal file
48
src/libremediaserver-audio-gui.h
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
/*
|
||||||
|
Libre Media Server Audio - An Open source Media Server for arts and performing.
|
||||||
|
(c) Criptomart - Santiago Noreña 2012-2024 <lms@criptomart.net>
|
||||||
|
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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef LIBREMEDIASERVERAUDIOUI_H
|
||||||
|
#define LIBREMEDIASERVERAUDIOUI_H
|
||||||
|
|
||||||
|
#include <QDockWidget>
|
||||||
|
#include <QWebView>
|
||||||
|
|
||||||
|
#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
|
|
@ -21,50 +21,35 @@
|
||||||
#include "libremediaserver-audio.h"
|
#include "libremediaserver-audio.h"
|
||||||
|
|
||||||
|
|
||||||
libreMediaServerAudio::libreMediaServerAudio(QStringList args, QWidget *parent)
|
libreMediaServerAudio::libreMediaServerAudio(bool gui)
|
||||||
: QMainWindow(parent)
|
|
||||||
{
|
{
|
||||||
Q_UNUSED(args);
|
m_ui = gui;
|
||||||
qDebug() << VERSION;
|
|
||||||
qDebug() << COPYRIGHT;
|
|
||||||
qDebug() << LICENSE;
|
|
||||||
ui.setupUi(this);
|
|
||||||
this->setWindowTitle(VERSION);
|
|
||||||
Settings *set = Settings::getInstance();
|
Settings *set = Settings::getInstance();
|
||||||
set->readFile();
|
set->readFile();
|
||||||
m_mediaLibrary = new MediaLibrary;
|
m_mediaLibrary = new MediaLibrary;
|
||||||
m_mediaLibrary->initMediaLibrary();
|
m_mediaLibrary->initMediaLibrary();
|
||||||
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());
|
m_ola = new olaThread(this, set->getLayersNumber());
|
||||||
Q_CHECK_PTR(m_ola);
|
Q_CHECK_PTR(m_ola);
|
||||||
m_ola->blockSignals(true);
|
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)));
|
connect(m_ola, SIGNAL(dmxOutput(int, int, int)), this, SLOT(dmxInput(int, int, int)));
|
||||||
m_ola->registerUniverse();
|
m_ola->registerUniverse();
|
||||||
connect(ui.actionLaunch_OLA_Setup, SIGNAL(triggered()), this, SLOT(olasetup()));
|
m_mae.startEngine(set->getAudioDeviceId());
|
||||||
m_aw->startEngine();
|
|
||||||
qDebug("Init Complete.");
|
qDebug("Init Complete.");
|
||||||
m_ola->blockSignals(false);
|
m_ola->blockSignals(false);
|
||||||
m_ola->start(QThread::TimeCriticalPriority );
|
m_ola->start(QThread::TimeCriticalPriority );
|
||||||
|
#ifndef NOGUI
|
||||||
|
if (m_ui) {
|
||||||
|
m_refreshUi = new QTimer(this);
|
||||||
|
connect(m_refreshUi, SIGNAL(timeout()), this, SLOT(refreshUi()));
|
||||||
|
m_refreshUi->start(UI_REFRESH_TIME);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
libreMediaServerAudio::~libreMediaServerAudio()
|
libreMediaServerAudio::~libreMediaServerAudio()
|
||||||
{
|
{
|
||||||
m_ola->stop();
|
m_ola->stop();
|
||||||
m_aw->stopEngine();
|
m_mae.stopEngine();
|
||||||
}
|
|
||||||
|
|
||||||
void libreMediaServerAudio::olasetup()
|
|
||||||
{
|
|
||||||
QWebView *view = new QWebView();
|
|
||||||
view->load(QUrl("http://localhost:9090/ola.html"));
|
|
||||||
view->show();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void libreMediaServerAudio::dmxInput(int layer, int channel, int value)
|
void libreMediaServerAudio::dmxInput(int layer, int channel, int value)
|
||||||
|
@ -73,54 +58,82 @@ void libreMediaServerAudio::dmxInput(int layer, int channel, int value)
|
||||||
return;
|
return;
|
||||||
QString mediaFile = NULL;
|
QString mediaFile = NULL;
|
||||||
int aux;
|
int aux;
|
||||||
switch(channel){
|
if (channel == DMX_FOLDER || channel == DMX_FILE){
|
||||||
case DMX_FOLDER:
|
int folder = (value >> 8) & 0x000000FF;
|
||||||
aux = m_ola->getValue(layer, DMX_FILE);
|
int file = value & 0x000000FF;
|
||||||
mediaFile = m_mediaLibrary->requestNewFile(value, aux);
|
mediaFile = m_mediaLibrary->requestNewFile(folder, file);
|
||||||
if (QFile::exists(mediaFile))
|
if (strcmp(mediaFile.toLatin1().constData(), m_currentMedia[layer].toLatin1().constData()) == 0)
|
||||||
m_aw->mediaLoaded(layer, mediaFile);
|
return;
|
||||||
break;
|
if (QFile::exists(mediaFile)){
|
||||||
case DMX_FILE:
|
m_mae.loadMedia(layer, mediaFile.toLatin1().data());
|
||||||
aux = m_ola->getValue(layer, DMX_FOLDER);
|
#ifndef NOGUI
|
||||||
mediaFile = m_mediaLibrary->requestNewFile(aux, value);
|
if (m_ui)
|
||||||
if (QFile::exists(mediaFile))
|
m_lmsUi->m_aw->mediaLoaded(layer, mediaFile, m_mae.getDuration(layer));
|
||||||
m_aw->mediaLoaded(layer, mediaFile);
|
#endif
|
||||||
break;
|
m_currentMedia[layer] = mediaFile;
|
||||||
case VOLUME_COARSE:
|
}
|
||||||
case VOLUME_FINE:
|
} else if (channel == VOLUME_COARSE || channel == VOLUME_FINE) {
|
||||||
m_aw->volChanged(layer, (value / 65025.0f));
|
m_mae.volChanged(layer, (value / 65025.0f));
|
||||||
break;
|
#ifndef NOGUI
|
||||||
case PAN:
|
if (m_ui)
|
||||||
m_aw->panChanged(layer, value);
|
m_lmsUi->m_aw->volChanged(layer, (value / 650.25f));
|
||||||
break;
|
#endif
|
||||||
case PITCH:
|
} else if (channel == PAN) {
|
||||||
m_aw->pitchChanged(layer, value);
|
m_mae.panChanged(layer, value);
|
||||||
break;
|
#ifndef NOGUI
|
||||||
case ENTRY_POINT_COARSE:
|
if (m_ui)
|
||||||
case ENTRY_POINT_FINE:
|
m_lmsUi->m_aw->panChanged(layer, value);
|
||||||
m_aw->entryPointChanged(layer, value);
|
#endif
|
||||||
break;
|
} else if (channel == PITCH) {
|
||||||
case PLAYBACK:
|
m_mae.pitchChanged(layer, value);
|
||||||
if (value == 0)
|
#ifndef NOGUI
|
||||||
break;
|
if (m_ui)
|
||||||
aux = value / 25;
|
m_lmsUi->m_aw->pitchChanged(layer, value);
|
||||||
switch (aux) {
|
#endif
|
||||||
case 0 :
|
} else if (channel == ENTRY_POINT_COARSE || channel == ENTRY_POINT_FINE) {
|
||||||
m_aw->playbackChanged(layer, PlayingOnce);
|
m_mae.setCursor(layer, value);
|
||||||
break;
|
#ifndef NOGUI
|
||||||
case 1 :
|
if (m_ui)
|
||||||
m_aw->playbackChanged(layer, Stopped);
|
m_lmsUi->m_aw->cursorChanged(layer, m_mae.getCursor(layer));
|
||||||
break;
|
#endif
|
||||||
case 2 :
|
|
||||||
m_aw->playbackChanged(layer, Paused);
|
} else if (channel == PLAYBACK && value > 0) {
|
||||||
break;
|
Status s = m_mae.getStatus(layer);
|
||||||
case 3 :
|
aux = value / 25;
|
||||||
m_aw->playbackChanged(layer, PlayingLoop);
|
if (s != aux) {
|
||||||
break;
|
if (aux == 0)
|
||||||
default :
|
s = Status::PlayingOnce;
|
||||||
break;
|
else if (aux == 1)
|
||||||
|
s = Status::Stopped;
|
||||||
|
else if (aux == 2)
|
||||||
|
s = Status::Paused;
|
||||||
|
else if (aux == 3)
|
||||||
|
s = Status::PlayingLoop;
|
||||||
|
m_mae.playbackChanged(layer, s);
|
||||||
|
#ifndef NOGUI
|
||||||
|
if (m_ui)
|
||||||
|
m_lmsUi->m_aw->playbackChanged(layer, s);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef NOGUI
|
||||||
|
void libreMediaServerAudio::refreshUi() {
|
||||||
|
if (!m_ui)
|
||||||
|
return;
|
||||||
|
for (int i= 0; i < Settings::getInstance()->getLayersNumber(); i++ ) {
|
||||||
|
Status s = m_mae.getStatus(i);
|
||||||
|
if (s == Status::PlayingOnce || s == Status::PlayingLoop) {
|
||||||
|
m_lmsUi->m_aw->cursorChanged(i, m_mae.getCursor(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void libreMediaServerAudio::setUi(libreMediaServerAudioUi *lmsUi)
|
||||||
|
{
|
||||||
|
m_lmsUi = lmsUi;
|
||||||
|
connect(m_ola, SIGNAL(universeReceived(int)), m_lmsUi->m_dmxWidget, SLOT(updateWatchDMX(int)));
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
|
@ -20,35 +20,41 @@
|
||||||
#ifndef LIBREMEDIASERVERAUDIO_H
|
#ifndef LIBREMEDIASERVERAUDIO_H
|
||||||
#define LIBREMEDIASERVERAUDIO_H
|
#define LIBREMEDIASERVERAUDIO_H
|
||||||
|
|
||||||
#include <QDockWidget>
|
|
||||||
#include <QWebView>
|
|
||||||
|
|
||||||
#include "audiowidget.h"
|
|
||||||
#include "medialibrary.h"
|
#include "medialibrary.h"
|
||||||
#include "olathread.h"
|
#include "olathread.h"
|
||||||
#include "settings.h"
|
#include "settings.h"
|
||||||
#include "dmxwidget.h"
|
|
||||||
#include "defines.h"
|
#include "defines.h"
|
||||||
#include "ui_libremediaserver-audio.h"
|
#ifndef NOGUI
|
||||||
|
#include "libremediaserver-audio-gui.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
class libreMediaServerAudio : public QMainWindow
|
class libreMediaServerAudio : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
libreMediaServerAudio (QStringList args, QWidget *parent = 0);
|
libreMediaServerAudio(bool gui = false);
|
||||||
virtual ~libreMediaServerAudio();
|
virtual ~libreMediaServerAudio();
|
||||||
Ui::LibreMediaServerAudio ui;
|
olaThread *m_ola;
|
||||||
|
#ifndef NOGUI
|
||||||
|
void setUi(libreMediaServerAudioUi *lmsUi);
|
||||||
|
#endif
|
||||||
|
|
||||||
private:
|
private:
|
||||||
AudioWidget *m_aw;
|
|
||||||
dmxWidget *m_dmxWidget;
|
|
||||||
olaThread *m_ola;
|
|
||||||
MediaLibrary *m_mediaLibrary;
|
MediaLibrary *m_mediaLibrary;
|
||||||
|
MiniAudioEngine m_mae;
|
||||||
|
QString m_currentMedia[MAX_LAYERS];
|
||||||
|
#ifndef NOGUI
|
||||||
|
bool m_ui;
|
||||||
|
QTimer *m_refreshUi;
|
||||||
|
libreMediaServerAudioUi *m_lmsUi;
|
||||||
|
#endif
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void olasetup();
|
|
||||||
void dmxInput(int layer, int channel, int value);
|
void dmxInput(int layer, int channel, int value);
|
||||||
|
#ifndef NOGUI
|
||||||
|
void refreshUi();
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // LIBREMEDIASERVERAUDIO_H
|
#endif // LIBREMEDIASERVERAUDIO_H
|
||||||
|
|
39
src/main.cpp
39
src/main.cpp
|
@ -18,34 +18,29 @@
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "libremediaserver-audio.h"
|
#include "main.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[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
QApplication app(argc, argv);
|
QApplication app(argc, argv);
|
||||||
QStringList args = app.arguments();
|
|
||||||
if (args.size() > 1)
|
libreMediaServerAudio lms(hasUi(argc, argv));
|
||||||
|
#ifndef NOGUI
|
||||||
|
if (hasUi(argc, argv))
|
||||||
{
|
{
|
||||||
if (args.contains("-v"))
|
libreMediaServerAudioUi *lmsUi = new libreMediaServerAudioUi();
|
||||||
{
|
lms.setUi(lmsUi);
|
||||||
qDebug() << VERSION;
|
lmsUi->show();
|
||||||
qDebug() << COPYRIGHT;
|
|
||||||
qDebug() << LICENSE;
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
if (args.contains("-h"))
|
#endif
|
||||||
{
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
libreMediaServerAudio libreMediaServerAudio(args);
|
|
||||||
libreMediaServerAudio.show();
|
|
||||||
return app.exec();
|
return app.exec();
|
||||||
}
|
}
|
||||||
|
|
20
src/main.h
Normal file
20
src/main.h
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
#ifndef MAIN_H
|
||||||
|
#define MAIN_H
|
||||||
|
|
||||||
|
#include <QCoreApplication>
|
||||||
|
#include <QApplication>
|
||||||
|
|
||||||
|
#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
|
|
@ -115,7 +115,6 @@ ma_result MiniAudioEngine::loadMedia(int layer, char *file)
|
||||||
|
|
||||||
if (m_mediaLoaded[layer] == true)
|
if (m_mediaLoaded[layer] == true)
|
||||||
{
|
{
|
||||||
qInfo("removing sound %i", layer);
|
|
||||||
ma_sound_uninit(&m_currentSound[layer]);
|
ma_sound_uninit(&m_currentSound[layer]);
|
||||||
m_mediaLoaded[layer] = false;
|
m_mediaLoaded[layer] = false;
|
||||||
}
|
}
|
||||||
|
@ -137,16 +136,21 @@ ma_result MiniAudioEngine::loadMedia(int layer, char *file)
|
||||||
float MiniAudioEngine::getDuration(int layer)
|
float MiniAudioEngine::getDuration(int layer)
|
||||||
{
|
{
|
||||||
ma_result result;
|
ma_result result;
|
||||||
float ret = 0;
|
ma_uint64 lengthInPCMFrames;
|
||||||
|
ma_uint32 sampleRate;
|
||||||
|
float ret;
|
||||||
|
|
||||||
if (m_mediaLoaded[layer] == false)
|
if (m_mediaLoaded[layer] == false)
|
||||||
return MA_DOES_NOT_EXIST;
|
return MA_DOES_NOT_EXIST;
|
||||||
result = ma_sound_get_length_in_seconds(&m_currentSound[layer], &ret);
|
result = ma_sound_get_length_in_pcm_frames(&m_currentSound[layer], &lengthInPCMFrames);
|
||||||
if (result != MA_SUCCESS)
|
if (result != MA_SUCCESS) {
|
||||||
{
|
return result;
|
||||||
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 result;
|
||||||
|
}
|
||||||
|
ret = 1000.0f * (lengthInPCMFrames / float(sampleRate));
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -161,7 +165,7 @@ float MiniAudioEngine::getCursor(int layer)
|
||||||
if (result != MA_SUCCESS)
|
if (result != MA_SUCCESS)
|
||||||
{
|
{
|
||||||
qWarning("Can not get cursor %i", layer);
|
qWarning("Can not get cursor %i", layer);
|
||||||
ret = 0;
|
ret = -1;
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -231,6 +235,8 @@ void MiniAudioEngine::playbackChanged(int layer, Status status)
|
||||||
ma_sound_set_looping(&m_currentSound[layer], false);
|
ma_sound_set_looping(&m_currentSound[layer], false);
|
||||||
ma_sound_start(&m_currentSound[layer]);
|
ma_sound_start(&m_currentSound[layer]);
|
||||||
break;
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -244,3 +250,17 @@ void MiniAudioEngine::setCursor(int layer, int cursor)
|
||||||
f = (cursor * f) / 65025;
|
f = (cursor * f) / 65025;
|
||||||
ma_sound_seek_to_pcm_frame(&m_currentSound[layer], f);
|
ma_sound_seek_to_pcm_frame(&m_currentSound[layer], f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Status MiniAudioEngine::getStatus(int layer)
|
||||||
|
{
|
||||||
|
if (m_mediaLoaded[layer] == ma_bool8(false))
|
||||||
|
return Status::Iddle;
|
||||||
|
if (ma_sound_is_playing(&m_currentSound[layer])) {
|
||||||
|
if (ma_sound_is_looping(&m_currentSound[layer]))
|
||||||
|
return Status::PlayingLoop;
|
||||||
|
return Status::PlayingOnce;
|
||||||
|
}
|
||||||
|
if (this->getDuration(layer) > 0)
|
||||||
|
return Status::Paused;
|
||||||
|
return Status::Stopped;
|
||||||
|
}
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
|
|
||||||
class MiniAudioEngine
|
class MiniAudioEngine
|
||||||
{
|
{
|
||||||
friend class AudioWidget;
|
friend class libreMediaServerAudio;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
MiniAudioEngine();
|
MiniAudioEngine();
|
||||||
|
@ -26,6 +26,7 @@ protected:
|
||||||
float getCursor(int layer);
|
float getCursor(int layer);
|
||||||
void setCursor(int layer, int cursor);
|
void setCursor(int layer, int cursor);
|
||||||
ma_result printFormatInfo(int layer);
|
ma_result printFormatInfo(int layer);
|
||||||
|
Status getStatus(int layer);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ma_resource_manager_config resourceManagerConfig;
|
ma_resource_manager_config resourceManagerConfig;
|
||||||
|
|
|
@ -63,39 +63,58 @@ void olaThread::stop()
|
||||||
void olaThread::NewDmx(const ola::client::DMXMetadata &data,
|
void olaThread::NewDmx(const ola::client::DMXMetadata &data,
|
||||||
const ola::DmxBuffer &buffer)
|
const ola::DmxBuffer &buffer)
|
||||||
{
|
{
|
||||||
bool volSent = false;
|
|
||||||
bool entrySent = false;
|
|
||||||
|
|
||||||
foreach (const dmxSetting &i, m_dmxSettings) {
|
foreach (const dmxSetting &i, m_dmxSettings) {
|
||||||
if(i.universe == data.universe && i.address > -1) {
|
if(i.universe == data.universe && i.address > -1) {
|
||||||
|
bool volSent = false;
|
||||||
|
bool entrySent = false;
|
||||||
|
bool fileSent = false;
|
||||||
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 VOLUME_COARSE:
|
case DMX_FOLDER:
|
||||||
value = (value * 0x100) + buffer.Get(i.address + VOLUME_FINE);
|
value *= 0x100;
|
||||||
|
value += buffer.Get(i.address + DMX_FILE);
|
||||||
emit dmxOutput(i.layer,j,value);
|
emit dmxOutput(i.layer,j,value);
|
||||||
volSent = true;
|
m_dmx[i.layer][DMX_FILE] = buffer.Get(i.address + DMX_FILE);
|
||||||
|
fileSent = true;
|
||||||
break;
|
break;
|
||||||
case ENTRY_POINT_COARSE:
|
case DMX_FILE:
|
||||||
value = (value * 0x100) + buffer.Get(i.address + ENTRY_POINT_FINE);
|
if (fileSent)
|
||||||
|
break;
|
||||||
|
value += buffer.Get(i.address + DMX_FOLDER) * 0x100;
|
||||||
emit dmxOutput(i.layer,j,value);
|
emit dmxOutput(i.layer,j,value);
|
||||||
entrySent = true;
|
m_dmx[i.layer][DMX_FOLDER] = buffer.Get(i.address + DMX_FOLDER);
|
||||||
|
fileSent = true;
|
||||||
break;
|
break;
|
||||||
case VOLUME_FINE:
|
case VOLUME_FINE:
|
||||||
if (volSent == false)
|
|
||||||
{
|
|
||||||
value = (buffer.Get(i.address + VOLUME_COARSE) * 0x100) + value;
|
value = (buffer.Get(i.address + VOLUME_COARSE) * 0x100) + value;
|
||||||
emit dmxOutput(i.layer,j,value);
|
emit dmxOutput(i.layer,j,value);
|
||||||
}
|
m_dmx[i.layer][VOLUME_COARSE] = buffer.Get(i.address + VOLUME_COARSE);
|
||||||
|
volSent = true;
|
||||||
|
break;
|
||||||
|
case VOLUME_COARSE:
|
||||||
|
if (volSent)
|
||||||
|
break;
|
||||||
|
value = (value * 0x100) + buffer.Get(i.address + VOLUME_FINE);
|
||||||
|
emit dmxOutput(i.layer,j,value);
|
||||||
|
m_dmx[i.layer][VOLUME_FINE] = buffer.Get(i.address + VOLUME_FINE);
|
||||||
|
volSent = true;
|
||||||
break;
|
break;
|
||||||
case ENTRY_POINT_FINE:
|
case ENTRY_POINT_FINE:
|
||||||
if (entrySent == false)
|
|
||||||
{
|
|
||||||
value = (buffer.Get(i.address + ENTRY_POINT_COARSE) * 0x100) + value;
|
value = (buffer.Get(i.address + ENTRY_POINT_COARSE) * 0x100) + value;
|
||||||
emit dmxOutput(i.layer,j,value);
|
emit dmxOutput(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);
|
||||||
|
emit dmxOutput(i.layer,j,value);
|
||||||
|
m_dmx[i.layer][ENTRY_POINT_FINE] = buffer.Get(i.address + ENTRY_POINT_FINE);
|
||||||
|
entrySent = true;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
emit dmxOutput(i.layer,j,value);
|
emit dmxOutput(i.layer,j,value);
|
||||||
|
@ -127,7 +146,7 @@ bool olaThread::CheckDataLoss() {
|
||||||
|
|
||||||
void olaThread::socketClosed()
|
void olaThread::socketClosed()
|
||||||
{
|
{
|
||||||
qWarning("ola closed connection. Try reopening it... ");
|
qWarning("ola daemon closed connection, reopening it... ");
|
||||||
m_clientWrapper->GetSelectServer()->Terminate();
|
m_clientWrapper->GetSelectServer()->Terminate();
|
||||||
m_client = NULL;
|
m_client = NULL;
|
||||||
m_clientWrapper = NULL;
|
m_clientWrapper = NULL;
|
||||||
|
|
|
@ -53,7 +53,7 @@ private:
|
||||||
if (error.Success()) {
|
if (error.Success()) {
|
||||||
qDebug("Register Universe success");
|
qDebug("Register Universe success");
|
||||||
} else {
|
} else {
|
||||||
qWarning("Register command failed: %s", error.Error().c_str());
|
qCritical("Register command failed: %s", error.Error().c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -1,45 +1,43 @@
|
||||||
#include "slidergroup.h"
|
#include "slidergroup.h"
|
||||||
|
|
||||||
SliderGroup::SliderGroup(const QString &title, \
|
SliderGroup::SliderGroup(int min,
|
||||||
int min,
|
|
||||||
int max,
|
int max,
|
||||||
int decimals,
|
int decimals,
|
||||||
QWidget *parent)
|
QWidget *parent)
|
||||||
: QGroupBox(title, parent)
|
: QWidget(parent)
|
||||||
{
|
{
|
||||||
this->setFlat(true);
|
QVBoxLayout *layout = new QVBoxLayout;
|
||||||
this->setTitle(title);
|
layout->setAlignment(Qt::AlignHCenter);
|
||||||
|
this->setMaximumWidth(65);
|
||||||
slider = new QSlider(Qt::Orientation::Vertical);
|
slider = new QSlider(Qt::Orientation::Vertical);
|
||||||
slider->setFocusPolicy(Qt::StrongFocus);
|
slider->setFocusPolicy(Qt::StrongFocus);
|
||||||
slider->setTickPosition(QSlider::TicksBothSides);
|
slider->setTickPosition(QSlider::TicksBothSides);
|
||||||
slider->setTickInterval((max - min) / 11);
|
slider->setTickInterval((max - min) / 11);
|
||||||
slider->setSingleStep(1);
|
slider->setSingleStep(1);
|
||||||
slider->setRange(min, max);
|
slider->setRange(min, max);
|
||||||
|
slider->setMaximumWidth(65);
|
||||||
valueBox = new QDoubleSpinBox();
|
valueBox = new QDoubleSpinBox();
|
||||||
valueBox->setFocusPolicy(Qt::NoFocus);
|
valueBox->setFocusPolicy(Qt::NoFocus);
|
||||||
valueBox->setButtonSymbols(QAbstractSpinBox::NoButtons);
|
valueBox->setButtonSymbols(QAbstractSpinBox::NoButtons);
|
||||||
valueBox->setMaximumWidth(45);
|
valueBox->setMaximumWidth(65);
|
||||||
valueBox->setRange(min, max);
|
valueBox->setRange(min, max);
|
||||||
valueBox->setDecimals(decimals);
|
valueBox->setDecimals(decimals);
|
||||||
connect(slider, SIGNAL(valueChanged(int)), this, SLOT(sliderValueChanged(int)));
|
connect(slider, SIGNAL(valueChanged(int)), this, SLOT(sliderValueChanged(int)));
|
||||||
QVBoxLayout *slidersLayout = new QVBoxLayout();
|
layout->addWidget(slider);
|
||||||
slidersLayout->addWidget(valueBox);
|
layout->addWidget(valueBox);
|
||||||
slidersLayout->addWidget(slider);
|
this->setLayout(layout);
|
||||||
setLayout(slidersLayout);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SliderGroup::sliderValueChanged(int value)
|
void SliderGroup::sliderValueChanged(int value)
|
||||||
{
|
{
|
||||||
|
valueBox->setValue(value);
|
||||||
if (valueBox->decimals() > 1)
|
if (valueBox->decimals() > 1)
|
||||||
value /= 100.0f;
|
value /= 100.0f;
|
||||||
emit valueChanged(value);
|
emit valueChanged(value);
|
||||||
valueBox->setValue(value);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
void SliderGroup::setValue(float value)
|
void SliderGroup::setValue(float value)
|
||||||
{
|
{
|
||||||
if (valueBox->decimals() > 1)
|
|
||||||
value *= 100.0f;
|
|
||||||
slider->setValue(value);
|
slider->setValue(value);
|
||||||
valueBox->setValue(value);
|
valueBox->setValue(value);
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,13 +6,12 @@
|
||||||
#include <QVBoxLayout>
|
#include <QVBoxLayout>
|
||||||
#include <QSlider>
|
#include <QSlider>
|
||||||
|
|
||||||
class SliderGroup : public QGroupBox
|
class SliderGroup : public QWidget
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
SliderGroup(const QString &title,
|
SliderGroup(int min,
|
||||||
int min,
|
|
||||||
int max,
|
int max,
|
||||||
int decimals,
|
int decimals,
|
||||||
QWidget *parent = nullptr);
|
QWidget *parent = nullptr);
|
||||||
|
|
Loading…
Add table
Reference in a new issue